summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/latex/xstring/xstring.tex
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/doc/latex/xstring/xstring.tex')
-rw-r--r--Master/texmf-dist/doc/latex/xstring/xstring.tex645
1 files changed, 645 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/xstring/xstring.tex b/Master/texmf-dist/doc/latex/xstring/xstring.tex
new file mode 100644
index 00000000000..71623a89b58
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/xstring/xstring.tex
@@ -0,0 +1,645 @@
+% __________________________________________________
+% | |
+% | |
+% | xstring v1.1 |
+% | |
+% | August 15 2008 |
+% | |
+% |__________________________________________________|
+%
+% This is xtring.sty
+%
+% Christian Tellechea 2008
+% email : unbonpetit@gmail.com
+% -------------------------------------------------------------------
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) 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.
+% -------------------------------------------------------------------
+% 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
+% README
+% xstring_doc_fr.tex, xstring_doc_fr.pdf (manual in french)
+% xstring_doc_en.tex, xstring_doc_en.pdf (manual in english)
+% test_latex.tex, test_latex.pdf (test file with LaTeX)
+% test_etex.tex, test_etex.pdf (test file with Plain eTeX)
+%
+\def\xstringversion {1.1}
+\def\xstringdate {2008/08/15}
+\def\xstringfrenchdate {15 ao\^ut 2008}
+\def\xstringenglishdate{August $15^{\mathrm{th}}$ 2008}
+\edef\CurrentAtCatcode{\the\catcode`\@}
+\catcode`\@=11
+\newwrite\@xs@unused% pour lesmessages
+\newcount\integerpart% pour les tests sur les nombres
+\newcount\decimalpart
+
+\immediate\write\@xs@unused{Package: xstring v\xstringversion\space<\xstringdate>\space Extended macros for strings (C Tellechea).}%
+
+\expandafter\ifx\csname @latexerr\endcsname\relax% on n'utilise pas LaTeX ?
+ \long\def\@firstoftwo#1#2{#1}
+ \long\def\@secondoftwo#1#2{#2}
+ \long\def\@ifnextchar#1#2#3{%
+ \let\reserved@d=#1%
+ \def\reserved@a{#2}%
+ \def\reserved@b{#3}%
+ \futurelet\@let@token\@ifnch}
+ \def\@ifnch{%
+ \ifx\@let@token\@sptoken
+ \let\reserved@c\@xifnch
+ \else
+ \ifx\@let@token\reserved@d
+ \let\reserved@c\reserved@a
+ \else
+ \let\reserved@c\reserved@b
+ \fi
+ \fi
+ \reserved@c}
+ \def\:{\let\@sptoken= } \:
+ \def\:{\@xifnch} \expandafter\def\: {\futurelet\@let@token\@ifnch}
+ \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}}
+ \long\def\@testopt#1#2{\@ifnextchar[{#1}{#1[{#2}]}}
+ \def\@empty{}
+\fi% fin des définitions LaTeX
+
+\def\@xs@gobblefirstchar#1#2\@nil{#2}
+\def\@xs@returnfirstchar#1#2\@nil{#1}
+
+% Gestion des messages d'erreur
+\def\@xs@linenumber{on input line \the\inputlineno}
+\def\@xs@errorwrite#1#2{%
+ \begingroup
+ \newlinechar`\^^J%
+ \errhelp{#2}%
+ \errmessage{Package xstring Error: \@xs@linenumber\space#1^^J%
+ See user manual for further information.^^J%
+ Type \space H <return> \space for immediate help.}%
+ \endgroup}
+
+\def\@xs@warningwrite#1{%
+ \begingroup
+ \newlinechar`\^^J%
+ \immediate\write\@xs@unused{Package xstring Warning: #1 \@xs@linenumber^^J}%
+ \endgroup}
+
+\def\@xs@infowrite#1{%
+ \begingroup
+ \newlinechar`\^^J%
+ \immediate\write\m@ne{Package xstring Info: #1}%
+ \endgroup}
+
+% Messages d'information pour situations particulières
+\def\@xs@BadNumArg {\@xs@infowrite{numerical argument out of range}}
+\def\@xs@ArgNotFound {\@xs@infowrite{substring not found in string}}
+\def\@xs@ArgEmpty {\@xs@infowrite{empty argument}}
+
+% Ouvre un groupe où les catcodes sont à 12 et à 10 pour les espaces
+% ensuite, appelle \@xs@ReadVerb qui lit un argument entre délimiteurs verb
+\def\@xs@MakeVerb{% lit 1 argument et le transforme en verb
+ \begingroup% groupe où les catcodes sont à 12 pour la lecture suivante
+ \def\do##1{\catcode`##112\relax}%
+ \dospecials% on entre dans le mode verb
+ \obeyspaces% et on tient compte des espaces
+ \@xs@ReadVerb}% et on va lire l'argument
+
+% 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
+ \else
+ \@xs@warningwrite{verb delimiter is not a single char}%
+ \fi
+ \def\@xs@ReadVerb##1#1##2#1{% lit ##2 qui est entre les délimiteurs de verb
+ \endgroup% on ferme le groupe
+ \@xs@afterreadverb{##2}}}% on appelle l'exécution de fin
+
+% Assigne l'argument entre délimiteur verb dans la sc #1
+\def\verbtocs#1{%
+ \def\@xs@afterreadverb##1{\edef#1{##1}}%
+ \@xs@MakeVerb}
+
+% A l'aide d'un pont d'\expandafter, développe d'un niveau toutes
+% les sc 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
+ \ifx\@empty#2\@empty\else\@xs@expandallonelevel#2\@nil\fi}% s'il reste des sc, on boucle
+
+\def\@xs@notestcs#1\@nil{\relax}%
+\def\@xs@testcs#1#2\@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...}%
+ \fi}
+
+% \scancs développe #3 autant de fois que spécifié en #1
+% puis le développement obtenu est verbatimisé.
+% On utilise \@xs@expandalltodepth autant de fois que #1 le spécifie
+% 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}%
+ \def\@xs@testornot{\@xs@notestcs}%
+ \@xs@scancs}%
+ {\def\@xs@testornot{\@xs@testcs}%
+ \@xs@scancs}}
+\def\@xs@scancs{\@ifnextchar[{\@xs@scancs@}{\@xs@scancs@[1]}}
+\def\@xs@scancs@[#1]#2#3{%
+% #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##2\@nil{% développe de #1 niveaux toutes les sc de #3 et l'assigne à \@xs@result@scancs
+ \def\@xs@result@expandallonelevel{}%
+ \ifnum\numexpr##2<#1% tant que la profondeur de développement n'est pas atteinte
+ \@xs@testornot##1\@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}%
+ \expandafter\@xs@expandalltodepth\@xs@result@scancs\@nil##2+1\@nil% et on recommence
+ \fi}%
+ \def\@xs@result@scancs{#3}%
+ \@xs@expandalltodepth#3\@nil0\@nil
+ \expandafter\def\expandafter#2\expandafter{\detokenize\expandafter{\@xs@result@scancs}}}
+
+% Cette macro développe #2 au maximum (ce qui doit donner du texte),
+% 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
+ %\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
+ \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
+
+% 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
+\def\@xs@ReturnResult#1#2{%
+ \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
+ \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}}}
+
+% Expansion 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 enlève le 1er caractère de la chaine passée en argument
+\def\@xs@RemoveFirst#1[#2]{%
+ \ifx\@empty#1\@empty
+ \edef#2{}%
+ \else
+ \@xs@IfBeginWith{#1}{ }%
+ {\@xs@StrBehind[1]{#1}{ }[#2]}%
+ {\def\@xs@RemoveFirst@ii##1##2\@nil{\edef#2{##2}}%
+ \@xs@RemoveFirst@ii#1\@nil}%
+ \fi}
+
+% Cette macro interne renvoie le 1er caractère de la chaine passée en argument
+\def\@xs@ReturnFirst#1[#2]{%
+ \ifx\@empty#1\@empty%
+ \edef#2{}%
+ \else
+ \@xs@IfBeginWith{#1}{ }%
+ {\edef#2{ }}%
+ {\def\@xs@ReturnFirst@ii##1##2\@nil{\edef#2{##1}}%
+ \@xs@ReturnFirst@ii#1\@nil}%
+ \fi}
+
+% Cette macro interne est utilisée dans les macros étoilées pour :
+% 1) développer l'argument selon qu'on a choisit \fullexpandarg
+% ou \normalexpandarg, et ceci à l'aide de la macro \@xs@def
+% 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
+ \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@addtomacro#1#2{\edef#1{\unexpanded\expandafter{#1}#2}}
+\def\@xs@argstring{0########1########2########3########4########5########6########7########8########9}
+\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{\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@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@BuildLines#1#2{% #1 : numéro du 1er argument et % #2 : nombre de lignes
+ \def\@xs@newlines{}%
+ \def\@xs@newargs{}%
+ \def\@xs@buildlines##1\@nil{%
+ \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}}%
+ \ifnum\numexpr##1<#2\@xs@buildlines##1+1\@nil\fi}
+ \@xs@buildlines1\@nil}
+
+\def\@xs@newmacro#1#2#3#4#5{%
+% #1 : nom de la macro publique
+% #2 : argument optionnel (vide si pas d'arg optionnel)
+% #3 : nombre d'arguments obligatoires
+% #4 : utilisation de testopt (1 si oui, 0 si non)
+% #5 : code de la macro
+% Cette macro construit les macros privées suivantes :
+% 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]}}
+ \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@{%
+ \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}}%
+ \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]}}%
+ \fi}%
+ \@xs@temp@
+ \ifx\@empty#2\@empty
+ \@xs@BuildLines{1}{#3}%
+ \@xs@DefArg{#3}%
+ \else
+ \@xs@BuildLines{2}{#3}%
+ \@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@@}}}%
+ \@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}}}%
+ \@xs@temp@}
+
+% Cette macro teste si une chaine (#2) en contient au moins (#1) fois une autre (#3)
+% Au final, \@xs@behind@IfSubStr et \@xs@before@IfSubStr contiennent
+% ce qui se trouve après et avant la (#1)èmé occurrence de la chaine (#2)
+% si elle existe,et contiennent des chaines vides sinon.
+\def\@xs@strip@delimit#1\@delimit#2\@nil{#1}
+\def\@xs@IfSubStr@case@false{%
+ \def\@xsresult@IfSubStr{\expandafter\@secondoftwo}% on exécute #5
+ \def\@xs@behind@IfSubStr{}%
+ \def\@xs@before@IfSubStr{}}
+\@xs@newmacro\IfSubStr{1}{2}{0}{%
+ \ifnum#1<\@ne% on gère les cas spéciaux
+ \@xs@BadNumArg
+ \@xs@IfSubStr@case@false
+ \else
+ \ifx\@empty#2\@empty\@xs@ArgEmpty\fi
+ \ifx\@empty#3\@empty
+ \@xs@ArgEmpty
+ \@xs@IfSubStr@case@false
+ \else
+ \def\@xs@before@IfSubStr{}%
+ \def\@xs@IfSubStr@i##1#3##2\@nil##3\@nil{%
+ \ifx\@empty##2\@empty% rien après la sous chaine ?
+ \@xs@IfSubStr@case@false
+ \else% si ce qu'il est reste n'est pas vide
+ \ifnum\numexpr##3<#1% tant que le nombre d'occurrence n'est pas atteint
+ \edef\@xs@before@IfSubStr{\@xs@before@IfSubStr##1#3}%
+ \@xs@IfSubStr@i##2\@nil##3+1\@nil% on recommence
+ \else
+ \def\@xsresult@IfSubStr{\expandafter\@firstoftwo}% nombre d'occurrences atteint : on renvoie #4
+ \edef\@xs@before@IfSubStr{\@xs@before@IfSubStr##1}%
+ \edef\@xs@behind@IfSubStr{\@xs@strip@delimit##2\@nil}%
+ \fi
+ \fi}%
+ \@xs@IfSubStr@i#2\@delimit#3\@nil1\@nil% \@delimit pour éviter le cas de \IfSubStr{a}{aa}{V}{F} qui renverrait V
+ \fi
+ \fi
+ \@xsresult@IfSubStr}
+
+\@xs@newmacro\IfBeginWith{}{2}{0}{%
+ \@xs@IfSubStr[\@ne]{#1}{#2}%
+ {\ifx\@empty\@xs@before@IfSubStr\@empty
+ \def\@xs@result@IfBeginWith{\expandafter\@firstoftwo}%
+ \else
+ \def\@xs@result@IfBeginWith{\expandafter\@secondoftwo}%
+ \fi}%
+ {\def\@xs@result@IfBeginWith{\expandafter\@secondoftwo}}%
+ \@xs@result@IfBeginWith}
+
+\@xs@newmacro\IfEndWith{}{2}{0}{%
+ \@xs@StrCount{#1}{#2}[\@xs@result@IfEndWith]%
+ \ifnum\@xs@result@IfEndWith=\z@
+ \def\@xs@result@IfEndWith{\expandafter\@secondoftwo}%
+ \else
+ \ifx\@empty\@xs@after@StrCount\@empty
+ \def\@xs@result@IfEndWith{\expandafter\@firstoftwo}%
+ \else
+ \def\@xs@result@IfEndWith{\expandafter\@secondoftwo}%
+ \fi
+ \fi
+ \@xs@result@IfEndWith}
+
+% 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@IfSubStr[#1]{#2}{#3}%
+ {\@xs@ReturnResult{\@xs@before@IfSubStr}{#4}}%
+ {\@xs@ReturnResult{}{#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@IfSubStr[#1]{#2}{#3}%
+ {\@xs@ReturnResult{\@xs@behind@IfSubStr}{#4}}%
+ {\@xs@ReturnResult{}{#4}}}
+
+\@xs@newmacro\IfSubStrBefore{1,1}{3}{0}{\@xs@IfSubStrBefore@i[#1]{#2}{#3}{#4}}
+\def\@xs@IfSubStrBefore@i[#1,#2]#3#4#5{%
+ \@xs@IfSubStr[#2]{#3}{#5}%
+ {\expandafter\@xs@IfSubStr\expandafter[\expandafter#1\expandafter]\expandafter{\@xs@before@IfSubStr}{#4}%
+ {\def\@xs@result@IfSubStrBefore{\expandafter\@firstoftwo}}%
+ {\def\@xs@result@IfSubStrBefore{\expandafter\@secondoftwo}}%
+ }%
+ {\def\@xs@result@IfSubStrBefore{\expandafter\@secondoftwo}}%
+ \@xs@result@IfSubStrBefore}
+
+\@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{\ifx\@empty#1\@empty X\else#1\fi}
+\def\@xs@formatnumber#1{%
+ \expandafter\ifx\@xs@returnfirstchar#1\@nil+%
+ +0\expandafter\@xs@putXifempty\expandafter{\@xs@gobblefirstchar#1\@nil}%
+ \else
+ \expandafter\ifx\@xs@returnfirstchar#1\@nil-%
+ -0\expandafter\@xs@putXifempty\expandafter{\@xs@gobblefirstchar#1\@nil}%
+ \else
+ 0#1%
+ \fi
+ \fi}
+\def\@xs@formatdecimalpart#1{}
+
+\@xs@newmacro\IfInteger{}{1}{0}{%
+ \@xs@def\@xs@formattednumber{\@xs@formatnumber{#1}}%
+ \decimalpart=0
+ \afterassignment\@xs@defafterinteger\integerpart=\@xs@formattednumber\relax\@nil
+ \if\relax\@xs@afterinteger
+ \def\@xs@result@IfInteger{\expandafter\@firstoftwo}%
+ \else
+ \def\@xs@result@IfInteger{\expandafter\@secondoftwo}%
+ \fi
+ \@xs@result@IfInteger}
+
+\@xs@newmacro\IfDecimal{}{1}{0}{%
+ \@xs@def\@xs@formattednumber{\@xs@formatnumber{#1}}%
+ \decimalpart=0\relax
+ \afterassignment\@xs@defafterinteger\integerpart=\@xs@formattednumber\relax\@nil
+ \expandafter\@xs@testdot\@xs@afterinteger\@nil
+ \if\relax\@xs@afterdecimal
+ \def\@xs@result@IfDecimal{\expandafter\@firstoftwo}%
+ \else
+ \def\@xs@result@IfDecimal{\expandafter\@secondoftwo}%
+ \fi
+ \@xs@result@IfDecimal}
+\def\@xs@defafterinteger#1\@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}}
+
+% 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@IfSubStr[#2]{#3}{#5}%
+ {\expandafter\@xs@IfSubStr\expandafter[\expandafter#1\expandafter]\expandafter{\@xs@before@IfSubStr}{#4}%
+ {\@xs@ReturnResult{\@xs@behind@IfSubStr}{#6}}%
+ {\@xs@ReturnResult{}{#6}}%
+ }%
+ {\@xs@ReturnResult{}{#6}}}
+
+% Remplace les #1 premières occurences de la chaine #3
+% par la chaine #4 dans la chaine #2
+\@xs@newmacro\StrSubstitute{0}{3}{1}{%
+ \ifx\@empty#3\@empty% si #3 est vide, on ne fait rien
+ \@xs@ArgEmpty% warning
+ \edef\@xs@result@StrSubstitute{#2}%
+ \else
+ \edef\@xs@result@StrSubstitute{}% on initialise à vide, histoire d'enlever le statut undefined
+ \ifnum#1>\z@
+ \def\@xs@StrSubstitute@i##1#3##2\@nil##3\@nil{% ici, on compte 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
+ {\ifnum\numexpr##3<#1% tant qu'on n'a pas atteint la bonne occurrence,
+ \@xs@StrSubstitute@i##2\@nil##3+1\@nil% on recommence
+ \else
+ \edef\@xs@result@StrSubstitute{\@xs@result@StrSubstitute##2}% l'occurrence est atteinte : on rajoute ce qui reste
+ \fi}%
+ {\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\@nil1\@nil}% si #2 contient #3, on exécute la macro
+ {\edef\@xs@result@StrSubstitute{#2}}% sinon, on renvoie la chaine #2
+ \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
+ \fi
+ \fi
+ \@xs@ReturnResult{\@xs@result@StrSubstitute}{#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 ?
+\@xs@newmacro\StrLen{}{1}{1}{\@xs@StrLen@i#1\@nil0\@nil#2\@nil}
+\def\@xs@StrLen@i#1\@nil#2\@nil#3\@nil{%
+ \ifx\@empty#1\@empty%
+ \@xs@ReturnResult{\number\numexpr#2}{#3}%
+ \else
+ \@xs@RemoveFirst{#1}[\@xs@remain@StrLen]%
+ \expandafter\@xs@StrLen@i\@xs@remain@StrLen\@nil#2+1\@nil#3\@nil
+ \fi}
+
+\def\StrMid{\@ifstar{\let\@xs@assign\@xs@expand@and@detokenize\@xs@StrMid@@}{\let\@xs@assign\@xs@expand@and@assign\@xs@StrMid@@}}
+\def\@xs@StrMid@@#1#2#3{%
+ \@xs@def\@xs@First@StrMid{\@xs@expand#2}%
+ \@xs@def\@xs@Last@StrMid{\@xs@expand#3}% position début et fin
+ \ifnum#2>#3\@xs@BadNumArg\fi
+ \@xs@assign{\@xs@arg@i}{#1}%
+ \edef\@xs@call{\noexpand\@testopt{\noexpand\@xs@StrMid{\@xs@expand\@xs@arg@i}}{}}%
+ \@xs@call}
+% cette sous macro supprime le nombre de caractère nécessaires
+% à la gauche de son argument, et renvoie le résultat dans \@xs@result@MidGobble
+\def\@xs@MidGobble#1\@nil#2\@nil{%
+ \ifnum\numexpr#2=\@xs@First@StrMid% si on a atteint la position
+ \edef\@xs@result@MidGobble{#1}% on renvoie ce qui reste
+ \else% sinon
+ \@xs@RemoveFirst{#1}[\@xs@remain@StrMid]% on enlève un caractère
+ \expandafter\@xs@MidGobble\@xs@remain@StrMid\@nil#2+1\@nil% et on recommence
+ \fi}
+% cette sous macro prend le nombre de caractères nécessaires
+% à la gauche de son argument, et renvoie le résultat dans \@xs@result@StrMid
+\def\@xs@MidConcat#1\@nil#2\@nil{%
+ \@xs@ReturnFirst{#1}[\@xs@CharToAdd@StrMid]% prend le 1er caractère
+ \edef\@xs@result@StrMid{\@xs@result@StrMid\@xs@CharToAdd@StrMid}% l'ajoute au résultat final
+ \@xs@RemoveFirst{#1}[\@xs@remain@StrMid]% puis l'enlève de la chaine
+ \ifnum\numexpr#2<\numexpr\@xs@Last@StrMid-\@xs@First@StrMid% si pas encore fini
+ \expandafter\@xs@MidConcat\@xs@remain@StrMid\@nil#2+1\@nil% on recommence
+ \fi}
+\def\@xs@StrMid#1[#2]{%
+% renvoie la sous chaine de #1 comprise entre les positions \@xs@First@StrMid et \@xs@Last@StrMid
+ \@xs@StrLen{#1}[\@len@StrMid]%
+ \ifnum\@xs@First@StrMid>\@xs@Last@StrMid% mauvais ordre ?
+ \@xs@ReturnResult{}{#2}% on renvoie rien
+ \else
+ \ifnum\@xs@Last@StrMid<\@ne% si position fin trop petite
+ \@xs@ReturnResult{}{#2}% on renvoie rien
+ \else
+ \ifnum\@xs@First@StrMid<\@ne% 1ère position trop petite ?
+ \edef\@xs@First@StrMid{1}% on limite à 1
+ \@xs@BadNumArg% avertissement
+ \fi
+ \ifnum\@xs@Last@StrMid>\@len@StrMid% dernière position trop grande ?
+ \edef\@xs@Last@StrMid{\@len@StrMid}% on limite à la longueur de la chaine
+ \@xs@BadNumArg% avertissement
+ \fi
+ \@xs@MidGobble#1\@nil1\@nil% on supprime ce qu'il faut à gauche
+ \edef\@xs@result@StrMid{}% rien dans le résultat final pour l'instant
+ \expandafter\@xs@MidConcat\@xs@result@MidGobble\@nil0\@nil% on prend les caractères qu'il faut à gauche
+ \@xs@ReturnResult{\@xs@result@StrMid}{#2}%
+ \fi
+ \fi}
+
+% supprime #2 caractères à gauche dans la chaine #1
+\@xs@newmacro\StrGobbleLeft{}{2}{1}{%
+ \edef\@xs@First@StrMid{\numexpr#2+1}%
+ \@xs@StrLen{#1}[\@xs@Last@StrMid]%
+ \@xs@StrMid{#1}[\@xs@result@StrGobbleLeft]%
+ \@xs@ReturnResult{\@xs@result@StrGobbleLeft}{#3}}
+
+% extrait de #1 la chaine à gauche de longueur #2
+\@xs@newmacro\StrLeft{}{2}{1}{%
+ \edef\@xs@First@StrMid{1}%
+ \ifnum#2<0\@xs@BadNumArg\fi% avertissement
+ \edef\@xs@Last@StrMid{#2}%
+ \@xs@StrMid{#1}[\@xs@result@StrLeft]%
+ \@xs@ReturnResult{\@xs@result@StrLeft}{#3}}
+
+% supprime #2 caractères à droite dans la chaine #1
+\@xs@newmacro\StrGobbleRight{}{2}{1}{%
+ \@xs@StrLen{#1}[\@Result@Length]%
+ \ifnum#2>\@Result@Length\@xs@BadNumArg\fi% avertissement
+ \edef\@xs@First@StrMid{1}%
+ \edef\@xs@Last@StrMid{\numexpr\@Result@Length-#2}%
+ \@xs@StrMid{#1}[\@xs@result@StrGobbleRight]%
+ \@xs@ReturnResult{\@xs@result@StrGobbleRight}{#3}}
+
+% renvoie #2 caractères à la droite de la chaine #1
+\@xs@newmacro\StrRight{}{2}{1}{%
+ \ifnum#2<\z@\@xs@BadNumArg\fi% avertissement
+ \@xs@StrLen{#1}[\@xs@Last@StrMid]%
+ \edef\@xs@First@StrMid{\numexpr\@xs@Last@StrMid+1-#2}%
+ \@xs@StrMid{#1}[\@xs@result@StrRight]%
+ \@xs@ReturnResult{\@xs@result@StrRight}{#3}}
+
+\@xs@newmacro\StrChar{}{2}{1}{%
+ \@xs@def\@xs@First@StrMid{\@xs@expand#2}%
+ \@xs@def\@xs@Last@StrMid{\@xs@expand#2}%
+ \@xs@StrMid{#1}[#3]}
+
+% Combien de fois compte t-on #2 dans #1 ?
+\@xs@newmacro\StrCount{}{2}{1}{%
+ \ifx\@empty#2\@empty
+ \@xs@ArgEmpty
+ \edef\@xs@after@StrCount{}%
+ \@xs@ReturnResult{0}{#3}%
+ \else
+ \def\@xs@StrCount@i##1#2##2\@nil##3\@nil{%
+ \ifx\@empty##2\@empty
+ \ifnum\numexpr##3=\z@
+ \edef\@xs@after@StrCount{}%
+ \else
+ \edef\@xs@after@StrCount{\@xs@strip@delimit##1\@nil}%
+ \fi
+ \@xs@ReturnResult{\number\numexpr##3}{#3}%
+ \else
+ \@xs@StrCount@i##2\@nil##3+1\@nil
+ \fi}%
+ \@xs@StrCount@i#1\@delimit#2\@nil0\@nil
+ \fi}
+
+% renvoie la position de l'occurrence #1 de la sous chaine #3 dans la chaine #2
+\@xs@newmacro\StrPosition{1}{2}{1}{%
+ \ifx\@empty#3\@empty%
+ \@xs@ArgEmpty
+ \@xs@ReturnResult{0}{#4}%
+ \else
+ \@xs@IfSubStr[#1]{#2}{#3}%
+ {\expandafter\@xs@StrLen\expandafter{\@xs@before@IfSubStr}[\@xs@lenbefore@StrPosition]%
+ \@xs@ReturnResult{\number\numexpr\@xs@lenbefore@StrPosition+1}{#4}%
+ }%
+ {\@xs@ReturnResult{0}{#4}}%
+ \fi}
+% Restaure le code de @
+\catcode`\@=\CurrentAtCatcode\relax
+% Définit le délimiteur verb et le développement des arguments par défaut
+\setverbdelim{|}
+\fullexpandarg
+\endinput
+%
+% Historique
+%
+% v1.0 4/7/2008 : - Package achevé.
+% 7/7/2008 : - Package publié sur CTAN.
+%
+% v1.1 /8/2008 : - 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
+% - 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{éù}
+% - Amélioration du code de la plupart des 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
+% \StrCount
+% a) ajout de ce qui se trouve après la dernière
+% occurrence dans la sc \@xs@after@StrCount
+% b) la macro ne dépend plus d'aucune autre \ No newline at end of file