% \iffalse meta-comment % boolexpr : purely expandable boolean expressions and switch (eTeX) [v3.14 2010/04/15] % % 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 % % Copyright (C) 2009 by Florent Chervet % % This work consists of the main source file boolexpr.dtx % and the derived files % boolexpr.sty, boolexpr.pdf, boolexpr.ins, % % Unpacking: % (a) If boolexpr.ins is present: % etex boolexpr.ins % (b) Without boolexpr.ins: % etex boolexpr.dtx % (c) If you insist on using LaTeX % latex \let\install=y\input{boolexpr.dtx} % (quote the arguments according to the demands of your shell) % % Documentation: % (pdf)latex boolexpr.dtx % %<*ignore> \begingroup \def\x{LaTeX2e}% \expandafter\endgroup \ifcase 0\ifx\install y1\fi\expandafter \ifx\csname processbatchFile\endcsname\relax\else1\fi \ifx\fmtname\x\else 1\fi\relax \else\csname fi\endcsname % %<*install> \input docstrip.tex \Msg{************************************************************************} \Msg{* Installation} \Msg{* Package: boolexpr 2010/04/15 v3.14 provides purely expandable boolean expressions and switch (eTeX)} \Msg{************************************************************************} \keepsilent \askforoverwritefalse \let\MetaPrefix\relax \preamble This is a generated file. boolexpr : a purely expandable boolean expressions and switch (eTeX) 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 Copyright (C) 2009 by Florent Chervet This work consists of the main source file boolexpr.dtx and the derived files boolexpr.sty, boolexpr.pdf, boolexpr.ins, boolexpr : a purely expandable boolean expressions and switch (eTeX) \endpreamble \let\MetaPrefix\DoubleperCent \generate{% \file{boolexpr.ins}{\from{boolexpr.dtx}{install}}% \file{boolexpr.sty}{\from{boolexpr.dtx}{package}}% } \obeyspaces \Msg{************************************************************************} \Msg{*} \Msg{* To finish the installation you have to move the following} \Msg{* file into a directory searched by TeX:} \Msg{*} \Msg{* boolexpr.sty} \Msg{*} \Msg{* To produce the documentation run the file `boolexpr.dtx'} \Msg{* through LaTeX.} \Msg{*} \Msg{* Happy TeXing!} \Msg{*} \Msg{************************************************************************} \endbatchfile % %<*ignore> \fi % %<*driver> \listfiles \edef\thisfile{\jobname} \def\thisinfo{Purely expandable boolean expressions and switch (\eTeX).} \def\thisversion{v3.14} \def\thisdate{2010/04/15} \let\loadclass\LoadClass \def\LoadClass#1{\loadclass[abstracton]{scrartcl}\let\scrmaketitle\maketitle\AtEndOfClass{\let\maketitle\scrmaketitle}} \documentclass[a4paper,oneside]{ltxdoc} \usepackage[latin9]{inputenc} \usepackage[american]{babel} \usepackage{etex,holtxdoc,etextools,xspace,geometry,tocloft,fancyhdr,color,bbding,makecell,enumitem,framed,txfonts,relsize}\CodelineNumbered \usepackage{fancyvrb,ifpdf} \IfFileExists{\thisfile.sty} {\RequirePackage{\thisfile}} \relax \ifpdf\usepackage{embedfile}\embedfile{\thisfile.dtx}\fi \geometry{top=2cm,headheight=1cm,headsep=.3cm,bottom=1.4cm,footskip=.5cm,left=4cm,right=2cm} \hypersetup{% pdftitle={The boolexpr package}, pdfsubject={An e-TeX package for more useful tools for LaTeX package writers}, pdfauthor={Florent CHERVET}, colorlinks,linkcolor=reflink,urlcolor=refurl, pdfstartview={FitH}, pdfkeywords={tex, e-tex, latex, package, boolexpr, boolean, ifthen, ifthenelse, conditionals}, bookmarksopen=true,bookmarksopenlevel=2} \begin{document} \DocInput{\thisfile.dtx} \end{document} % % \fi % % \CheckSum{396} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % \DoNotIndex{\begin,\CodelineIndex,\CodelineNumbered,\def,\DisableCrossrefs} % \DoNotIndex{\DocInput,\documentclass,\EnableCrossrefs,\end,\GetFileInfo} % \DoNotIndex{\NeedsTeXFormat,\OnlyDescription,\RecordChanges,\usepackage} % \DoNotIndex{\ProvidesClass,\ProvidesPackage,\ProvidesFile,\RequirePackage} % \DoNotIndex{\filename,\fileversion,\filedate,\let} % \DoNotIndex{\@listctr,\@nameuse,\csname,\else,\endcsname,\expandafter,\@ehd,\@nil,\bex,\case,\endcase} % \DoNotIndex{\gdef,\global,\if,\item,\newcommand,\nobibliography} % \DoNotIndex{\par,\providecommand,\relax,\renewcommand,\renewenvironment} % \DoNotIndex{\stepcounter,\usecounter,\nocite,\fi} % \DoNotIndex{\@fileswfalse,\@gobble,\@ifstar,\@unexpandable@protect} % \DoNotIndex{\AtBeginDocument,\AtEndDocument} % \DoNotIndex{\frenchspacing,\MessageBreak,\newif,\PackageWarningNoLine} % \DoNotIndex{\protect,\string,\xdef,\ifx,\texttt,\@biblabel,\bibitem} % \DoNotIndex{\z@,\wd,\vrule,\voidb@x,\verb,\bibitem} % \DoNotIndex{\hskip,\hfil,\hfill,\hsize,\hspace,\hss,\hbox,\hb@xt@,\escapechar} % \DoNotIndex{\date,\ifdefined,\ifhmode,\ifmmode,\cr} % \DoNotIndex{\box,\author,\advance,\multiply,\Command,\outer,\kern,\title,\tt} % \DoNotIndex{\the,\space,\section,\subsection,\textwidth} % \DoNotIndex{\",\@empty,\@latex@error,\makeatletter,\makeatother} % \DoNotIndex{\maketitle,\parindent,\setbox} % % % \makeatletter % \lastlinefit999 % \newif\ifboolexprLoaded % \ifdefined\boolexpr\boolexprLoadedtrue\else\boolexprLoadedfalse\fi % \newcommand\macrocodecolor{\color{macrocode}}\definecolor{macrocode}{rgb}{0.18,0.00,0.45} % \newcommand\reflinkcolor{\color{reflink}}\definecolor{reflink}{rgb}{0.49,0.00,0.00} % \newcommand\refurlcolor{\color{refurl}}\definecolor{refurl}{rgb}{0.00,0.00,1.00} % \newcommand\cmdref[1]{\hyperref[#1]{\underline{\reflinkcolor\CS{#1}}}} % \newcommand\cmdlabel[1]{\label{#1}\hyperdef{cmdlabel}{#1}{}} % \definecolor{dg}{rgb}{0.02,0.37,0.00} % \def\ThisPackage{\Xpackage{\thisfile}\xspace}\def\thispackage{\xpackage{\thisfile}\xspace} % \fancyhf{}\fancyhead[L]{\thispackage\ -- \thisinfo} % \fancyfoot[L]{\color[gray]{.35}\scriptsize\thispackage\quad\copyright\oldstylenums{2009}\,\lower.3ex\hbox{\NibRight}\,Florent Chervet} % \fancyfoot[R]{\oldstylenums{\thepage} / \oldstylenums{\pageref{LastPage}}} % \pagestyle{fancy} % \fancypagestyle{plain}{\fancyhf{}\let\headrulewidth\z@\fancyfoot[R]{\oldstylenums{\thepage} / \oldstylenums{\pageref{LastPage}}}} % % \catcode`\§\active\def§{\par\nobreak\vskip-\parskip} % \newlength\saveparskip\saveparskip.4\baselineskip % \newcommand\restoreparskip{\parskip\saveparskip} % \parindent\z@\parskip\saveparskip\topsep\z@\partopsep\z@ % \g@addto@macro\macro@font{\macrocodecolor\let\AltMacroFont\macro@font} % \def\smex{\leavevmode\hb@xt@2em{\hfil$\longrightarrow$\hfil}} % \def\csred#1{\textcolor{red}{\cs{#1}}} % \def\CSif\bgroup\ignorespaces#1{\bgroup\ignorespaces\ifx#1\unskip\else \CS{#1}\fi} % \def\CSbf#1{\textbf{\CS{#1}}} % \def\Repeat#1#2{\ifnum\numexpr#1\relax>0\relax #2\relax\Repeat{#1-1}{#2}\fi} % \def\Xpackage{\@dblarg\X@package} % \def\X@package[#1]#2{% % \xpackage{#2\footnote{\noindent\xpackage{#2}: \href{http://www.ctan.org/tex-archive/macros/latex/contrib/#1}{\nolinkurl{CTAN:macros/latex/contrib/#1}}}}} % \deffootnote{1em}{0pt}{\rlap{\textsuperscript{\thefootnotemark}}\kern1em} % \def\nq{\,!\!=} % \def\nq{<>} % \def\ie{\textsl{ie.\,}} % \newbox\Sharpbox\setbox\Sharpbox=\hbox{|#|} % \newcommand\Sharp[1]{\usebox\Sharpbox|#1|} % \newcommand\myfbox[2][3em]{\fbox{\hbox to#1{\hss#2\hss}}} % \newbox\boxedb@x % \newcommand\boxedbox[1]{\setbox\boxedb@x\vbox{#1}\fbox{\box\boxedb@x}} % \DefineVerbatimEnvironment{VerbEx}{Verbatim}{gobble=1,commandchars=![],fontfamily=tt,fontseries=tt,fontshape=tt} % \newcommand\evaluated{\textcolor{blue}} % \newcommand\notevaluated{\textcolor{black}} % \newcommand\stripmeaning{\expandafter\strip@prefix\meaning} % % \makeatother % % \title{\vskip-2.3cm\mdseries The {\bfseries \ThisPackage}\kern.6em package} % \author{\small\xemail{florent.chervet@free.fr}} % \date{\thisdate -- \thisversion} % \subtitle{\thisinfo} % % % \maketitle \vskip-2\baselineskip\strut % % \makeatletter\begingroup\let\@thefnmark\@empty\let\@makefntext\@firstofone % \footnotetext{\noindent % This documentation is produced with the |DocStrip| utility. % \begin{tabbing} % \qquad\=\smex\=To get the documentation, \= run (thrice):\quad\= \texttt{pdflatex \thisfile.dtx} \\ % \>\>for the index:\>\>\texttt{makeindex -s gind.ist \thisfile.idx} \\ % \>\smex\>To get the package, \> run:\> \texttt{etex \thisfile.dtx} % \end{tabbing}§ % The \xext{dtx} file is embedded into this pdf file thank to \xpackage{embedfile} by H. Oberdiek.} % \endgroup\makeatother % % \deffootnote{1em}{0pt}{\rlap{\thefootnotemark.}\kern1em} % % \begin{abstract}\parindent0pt\noindent\parskip\medskipamount\small\abovedisplayskip=0pt\belowdisplayskip=0pt % \vskip-\baselineskip % \thispackage provides a purely expandable way to evaluate boolean expressions of the form: % % \hfil\framebox[.618\linewidth][c]{$\alpha\quad\cs{AND}\quad\beta\quad\cs{OR}\quad\gamma\quad\dots$}\hfil % % where $\alpha$\,,\, $\beta$\, and $\gamma$ are \textit{atomic expressions} of one of those 8 valid forms: % \begin{center} % \begin{tabular}{*{6}{>{\hskip4pt}c<{\hskip4pt}}} % \myfbox{$x=y$} & \myfbox{$x\nq y$}\footnotemark & \myfbox{$xy$} & \myfbox{$x>=y$} \\[12pt] % \multicolumn{3}{c}{\myfbox[4.5cm]{\cs{if}\meta{test}\ $0$\cs{else} $1$\cs{fi}}} & % \multicolumn{3}{c}{\myfbox[4.5cm]{another \cs{boolexpr} evaluation}} % \end{tabular}\end{center} % \footnotetext{The choice of $\nq$ rather than $\char33\!=$ is due to \nameref{catcodes}.} % % where $x$ and $y$ are either numeric expressions (or dimensions, glue, muglue to test using |\dimexpr|, |\glueexpr| % or |\muexpr| -- please refer to the \nameref{examples}) and \meta{test} may be a switch (\cs{iftrue} / \cs{iffalse} % or a conditional\footnote{\cs{if}, \cs{ifcase}, \cs{ifcat}, \cs{ifcsname}, \cs{ifdefined}, \cs{ifdim}, \cs{ifeof}, % \cs{iffontchar}, \cs{ifhmode}, \cs{ifinner}, \cs{ifmmode}, \cs{ifnum}, \cs{ifodd}, \cs{ifvmode}, \cs{ifvoid}, \cs{ifx}}). % \thispackage abide by the precedence of |\AND| on |\OR|, % and the whole expression is evaluated until the result is known (in other words, |\AND| and |\OR| are \textit{shortcut} % boolean operators). % % \cmdref{boolexpr} will expand to \textbf{0} if the expression is \textbf{true}, making it proper to work with |\ifcase| % Furthermore, \thispackage defines a \cmdref{switch} syntax which remains purely expandable. % % \textbf{Be aware that \cs{boolexpr} (a little like \cs{numexpr}) works only if its argument is purely expandable}; % the same for \cs{switch}. If you wish a more general \cs{CASE} syntax refer to this excellent paper: % \url{http://www.tug.org/TUGboat/Articles/tb14-1/tb38fine.pdf}. % % The \thispackage package is designed to work with an \eTeX{} distribution of \LaTeX{}: % it is based on the \eTeX{} |\numexpr| primitive and requires no other package. % % \end{abstract}\vskip-.5\baselineskip % % \cftbeforesecskip=5pt plus2pt minus4pt % \smallskip\setcounter{tocdepth}{2}\enlargethispage{\baselineskip} % \renewcommand\contentsname{Contents\vskip-5pt} % {\smaller\tableofcontents} % % \def\B#1{\texttt{[}\meta{#1}\texttt{]}} % % \catcode95 11^^A% _ % \section{Introduction -- Using \thispackage : \cs{boolexpr} and \cs{switch}} % % \begin{declcs}{boolexpr}\,\M{boolean expression} % \end{declcs}\cmdlabel{boolexpr} % \cs{boolexpr} is a macro that takes for unique argument a series of \textit{atomic expressions} of the form:\par % \hskip2em\begin{tabular}{r>{$}c<{$}l} % numeric expr. & = & numeric expr. \\ % numeric expr. & \nq & numeric expr. \\ % numeric expr. & < & numeric expr \\ % numeric expr. & <= & numeric expr \\ % numeric expr. & > & numeric expr. \\ % numeric expr. & >= & numeric expr. \\ % \cs{if}& \meta{test}& 0\ \cs{else}\ 1\cs{fi}\\ % \multicolumn{3}{c}{\cs{boolexpr}\{\meta{boolean expression}\}} % \end{tabular}\par\noindent % related by \CSbf{AND} or \CSbf{OR} (with the usual logical precedence). % % \textbf{\cs{boolexpr} expands to \textbf{0} if the whole expression is \textbf{true}} % and to a non nul number if the whole expression is false. % % \cs{boolexpr} is \textbf{purely expandable}. % % \begin{framed} % Therefore, testing may be used as follow:§ % \begin{Verbatim}[gobble=1] % \ifcase\boolexpr{ boolean expression } % what to do if true % \else % what to do if false % \fi % \end{Verbatim} % \end{framed} % % It is possible to use \texttt{switches} as boolean quantities into a \cs{boolexpr} expression % with the syntax:§ % \qquad|\ifswitch 0\else 1\fi| % % It is also possible to use |\ifdim|, |\ifnum| etc. (although it is not necessary because other forms % of atomic expression can perform those tests more easily) and |\ifdefined|, |\ifcsname| etc. with % the same syntax, f.ex.:§ % \qquad|\ifcsname| \meta{cs-name} |\endcsname 0\else 1\fi| % % It means that if the conditional is \texttt{true} then the \textit{atomic expression} is \texttt{true} % (expands to |0|), otherwise the \textit{atomic expression} is |false| (expands to non |0|). % % It is possible to test |dimensions| (or |glue| or |muglue|) by writing |\dimexpr| % (or |\glueexpr| or |\muexpr|) in front of the \textit{atomic expression}; therefore, the following are valid atomic expressions:§ % \hskip2em\begin{tabular}{rr>{$}c<{$}l} % \cs{dimexpr} & dimen expr. & < & dimen expr \\ % \cs{glueexpr} & glue expr. & \nq & glue expr. \\ % \cs{muexpr} & mu expr. & = & mu expr. % \end{tabular} % % It is allowed to group expressions inside the argument of |\boolexpr| by inserting another |\boolexpr| evaluation, f.ex.:§ % \qquad|\boolexpr{ \boolexpr{ |$\alpha$ | \OR | $\beta$ |} \AND | $\gamma$ | }| % % The logical \textbf{NOT} operator can be achieved by writing for example:§ % \qquad|\ifcase\boolexpr{|\meta{boolean expression}|} 1\else 0\fi| % % Finally, if the \meta{boolean expression} is missing:§ %\qquad|\boolexpr{ }| expands to |1| (\ie |false|). % % \begin{declcs}{ifboolexpr}\,\M{boolean expression}\,\M{true part}\,\M{false part} % \end{declcs} % \cs{ifboolexpr} is the \LaTeX{} form of a |\boolexpr| test.\enlargethispage{\baselineskip} % % \cs{ifboolexpr} is purely expandable (provided \meta{true part} and \meta{false part} are so). % % % \clearpage % \subsection*{\CSbf{boolexpr} examples}\label{examples}\addcontentsline{toc}{subsection}{\cs{boolexpr} Examples} % \vskip-\baselineskip The part of the expression that is evaluated \textcolor{blue}{is in blue} (the remainder is not evaluated). % % \begin{tabular}{m{9.5cm}>{\color{dg}\smex\tt}m{5.6cm}}\hline % \begin{VerbEx} % \ifcase\boolexpr{ !evaluated[45 > 80 \OR 5<>5 \AND] 5<4 } % boolexpr is true % \else boolexpr is false % \fi % \end{VerbEx} % & % \ifboolexprLoaded % \ifcase\boolexpr{ 45 > 80 \OR 5<>5 \AND 5<4 } % boolexpr is true % \else boolexpr is false % \fi % \else % boolexpr is false % \fi % \\ \hline % \begin{VerbEx} % \ifcase\boolexpr{ !evaluated[45 < 80 \OR] 5 = 5 \AND 0<>0 } % boolexpr is true % \else boolexpr is false % \fi % \end{VerbEx} % & % \ifboolexprLoaded % \ifcase\boolexpr{ 45 < 80 \OR 5 = 5 \AND 0<>0 } % boolexpr is true % \else boolexpr is false % \fi % \else % boolexpr is true % \fi % \\ \hline % \begin{VerbEx} % \ifcase\boolexpr{ !evaluated[\boolexpr{ 45 < 80 \OR !notevaluated[5 = 5] } \AND 0<>0] } % boolexpr is true % \else boolexpr is false % \fi % \end{VerbEx} % & % \ifboolexprLoaded % \ifnum\boolexpr{ \boolexpr{ 45 < 80 \OR 5 = 5 } \AND 0<>0 }=0 % boolexpr is true % \else boolexpr is false % \fi % \else % boolexpr is false % \fi % \\ \hline % \begin{VerbEx} % \ifcase\boolexpr{ !evaluated[12>0 \AND (4+3)*5 > 20] } % boolexpr is true % \else boolexpr is false % \fi % \end{VerbEx} % & % \ifboolexprLoaded % \ifcase\boolexpr{ 12>0 \AND (4+3)*5 > 20} % boolexpr is true % \else boolexpr is false % \fi % \else % boolexpr is true % \fi % \\ \hline % \begin{VerbEx} % \makeatletter % \number\boolexpr{ !evaluated[\the\catcode`\@=11] } % \end{VerbEx} % & % \ifboolexprLoaded % \makeatletter % $\number\boolexpr{\the\catcode`\@=11}$ §{\small(catcode of character @ is 11)} % \else % $0$ §{\small(catcode of character @ is 11)} % \fi % \\ \hline % \begin{VerbEx} % \makeatother % \number\boolexpr{ !evaluated[\the\catcode`\@=11] \AND \ifdefined\@undefined 0\else 1\fi } % \end{VerbEx} % &\omit \\[-2ex] & \omit % \ifboolexprLoaded {\color{dg}\smex % $\number\boolexpr{\catcode`\@=11 \AND \ifdefined\@undefined 0\else 1\fi}$} \\ &\omit {\color{dg}\tt\small(catcode of character @ is 12)} % \else {\color{dg}\smex % $1$ {\small(catcode of character @ is 12)} } % \fi % \\ \hline % \begin{VerbEx} % \makeatletter % \number\boolexpr{ !evaluated[3<4 \AND \@ifundefined{iftest}{1}]{\iftest 0\else 1\fi} } % \end{VerbEx} % & \omit\\[-2ex] & \omit % \ifboolexprLoaded {\color{dg}\smex % \makeatletter % \number\boolexpr{ 3<4 \AND \@ifundefined{iftest}{1}{\iftest 0\else 1\fi} }: |\iftest| not defined \hfil} % \else {\color{bg} \smex 1: |\iftest| not defined\hfil} % \fi % \\ \hline % \begin{VerbEx} % \makeatletter \newif\iftest \testtrue % \number\boolexpr{ !evaluated[3<4 \AND \@ifundefined{iftest}]{1}!evaluated[{\iftest 0\else 1\fi}] } % \end{VerbEx} % & \omit\\[-2ex] & \omit % \ifboolexprLoaded {\color{dg}\smex % \makeatletter\newif\iftest\testtrue % \number\boolexpr{ 3<4 \AND \@ifundefined{iftest}{1}{\iftest 0\else 1\fi} }: |\iftest| is true \hfil} % \else {\color{bg} \smex 0: |\iftest| is true \hfil} % \fi % \\ \hline % \begin{VerbEx} % \ifcase\boolexpr{ !evaluated[\dimexpr 12pt + 1in > 8mm * 2 \AND \iftest 0\else 1\fi] } % boolexpr is true % \else boolexpr is false % \fi % \end{VerbEx} % & % \ifboolexprLoaded % \newif\iftest \testtrue % \ifcase\boolexpr{ \dimexpr 12pt + 1in > 8mm * 2 \AND \iftest 0\else 1\fi } % boolexpr is true % \else boolexpr is false % \fi % \else boolexpr is true % \fi % \\ \hline % \begin{VerbEx} % \ifcase\boolexpr{ !evaluated[0=0 \AND \ifcase\boolexpr{1=1 \AND 5<=5} 1\else 0\fi] } % boolexpr is true % \else boolexpr is false % \fi % \end{VerbEx} % & % \ifboolexprLoaded % \ifcase\boolexpr{ 0=0 \AND \ifcase\boolexpr{ 1=1 \AND 5<=5 } 1\else 0\fi } % boolexpr is true % \else boolexpr is false % \fi % \else boolexpr is false % \fi \footnotesize % § $\alpha$ |\AND NOT( |$\beta$| \AND |$\gamma$| )| % § $\!\!\!\!\!\!=\alpha$| \AND NOT |$\beta$| \OR |$\alpha$| \AND NOT |$\gamma$ % \\ \hline % \end{tabular} % % \ifboolexprLoaded Results in \textcolor{green}{green} were evaluated by \thispackage at compilation time. % \else Results in \textcolor{green}{green} were not evaluated at compilation time: \thispackage was not found. % \fi % % \clearpage % \subsection*{The \CSbf{switch} syntax}\label{switchsyntax}\addcontentsline{toc}{subsection}{The \cs{switch} syntax} % % \begin{declcs}{switch}\\ % \CSbf{case}\,\M{boolean expression}\quad... \\ % \CSbf{case}\,\M{boolean expression}\quad... \\ % \CSbf{otherwise}\quad... \\ % \CS{endswitch} % \end{declcs}\cmdlabel{switch} % % \thispackage defines a syntax for \cs{switch} conditionals which remains purely expandable: % \iffalse % \begin{VerbEx} % \switch % !textbf[\case]{ !meta[bool expr] } ... % !textbf[\case]{ !meta[bool expr] } ... % !textbf[\case]{ !meta[bool expr] } ... % !textbf[\otherwise] ... % \endswitch % \end{VerbEx} % \fi % % \textbf{Each part of the switch is optional.} That means: % \begin{center} % \begin{tabular}{m{.4\textwidth}m{.4\textwidth}} % \begin{VerbEx}[frame=single] % \switch % !textbf[\case]{ !meta[bool expr] } ... % !textbf[\case]{ !meta[beel expr] } ... % !textbf[\case]{ !meta[bool expr] } ... % !textbf[\otherwise] ... % \endswitch % \end{VerbEx} % & % \begin{VerbEx}[frame=single] % \switch % !textbf[\case]{ !meta[bool expr] } ... % !textbf[\case]{ !meta[beel expr] } ... % !textbf[\case]{ !meta[bool expr] } ... % \endswitch % \end{VerbEx} % \\ % \begin{VerbEx}[frame=single] % \switch % !textbf[\otherwise] ... % \endswitch % \end{VerbEx} % & % \begin{VerbEx}[frame=single] % \switch % \endswitch % \end{VerbEx} % \end{tabular}\\ % are allowed by \thispackage. % \end{center} % % % % \subsection*{\CSbf{switch} examples}\label{switchexamples}\addcontentsline{toc}{subsection}{switch examples} % % The part of the expression that is evaluated \textcolor{blue}{is in blue} (the remainder is not evaluated). % % \begin{tabular}{m{9.5cm}>{\color{dg}\smex\tt}m{5.6cm}}\hline % \begin{VerbEx} % !evaluated[\switch] % !evaluated[\case{6>1 \AND 6<=5}$\geq 1$ and $\leq 5$%] % !evaluated[\case{3<10}$> 5$ and $< 10$%] % \case{3>10}$\geq 10$% % !evaluated[\endswitch] % \end{VerbEx} % & % \ifboolexprLoaded % \switch % \case{6>1 \AND 6<=5}$\geq 1$ and $\leq 5$% % \case{3<10}$>5$ and $< 10$% % \case{3>10}$\geq 10$% % \endswitch % \else % $>5$ and $< 10$% % \fi % \\ \hline % \begin{VerbEx} % \edef\result{% % !evaluated[\switch] % !evaluated[\case{6>1 \AND 6<=5}$\geq 1$ and $\leq 5$%] % !evaluated[\case{3<10}$> 5$ and $< 10$%] % \case{3>10}$\geq 10$% % !evaluated[\endswitch]} % \end{VerbEx} % & % \ifboolexprLoaded % \edef\result{% % \switch % \case{6>1 \AND 6<=5}$\geq 1$ and $\leq 5$% % \case{3<10}$>5$ and $< 10$% % \case{3>10}$\geq 10$% % \endswitch} % \else % \def\result{$>5$ and $< 10$} % \fi % result:\par\stripmeaning\result % \\ \hline % \begin{VerbEx}[commandchars=!()] % \newcounter{myCounter} \setcounter{myCounter}{2} % \edef\result{% % !evaluated(\switch)[\value{myCounter}=] % !evaluated(\case{1}one)% % | ----------------------------> | % !evaluated(\case{2}two)% <=> \case{value{myCounter}=2} % \case{3}three% % \case{2}vartwo%(never found)% % \otherwise something else% % !evaluated(\endswitch)} % % \end{VerbEx} % & % \ifboolexprLoaded % \newcounter{myCounter} \setcounter{myCounter}{2} % \edef\result{% % \switch[\value{myCounter}=] % \case{2}two% % \case{3}three% % \case{2}vartwo% % \otherwise something else% % \endswitch} % \else % \edef\result{two} % \fi % result:\stripmeaning\result % \\ \hline % \begin{VerbEx}[commandchars=!()] % !evaluated(switch)[\value{myCounter}] % !evaluated(\case{=1})It's $1$% % !evaluated(\case{=-1})It's $-1$% % |-| -------------------------> |-| % !evaluated(\case{>=0})It's $>=0$% <=> \case{\value{myCounter}>=0} % \otherwise something else% % !evaluated(\endswitch) % \end{VerbEx} % & % \ifboolexprLoaded \loggingall % \vspace*{2cm}% % \switch[\value{myCounter}] % \case{=1}It's $1$% % \case{=-1}It's $-1$% % \case{>=0}It's $>=0$% % \otherwise something else% % \endswitch % \else It's $>=0$% % \fi % \\\hline % \begin{VerbEx}[commandchars=!()] % !evaluated(switch)[\pdfstrcmp{DuMmY}] % !evaluated(\case{{First}})It's "First"% % |-| -------------------------> |-| % !evaluated(\case{{DuMmY})It's DuMmY% % \otherwise something else% % !evaluated(\endswitch) % \end{VerbEx} % & % \ifboolexprLoaded % \ifdefined\pdfstrcmp % \vspace*{2cm}% % \switch[\pdfstrcmp{DuMmY}] % \case{{First}}It's "First"% % \case{{DuMmY}}It's "DuMmY"% % \otherwise something else% % \endswitch % \else It's It's "DuMmY"% % \fi % \else It's "DuMmY"% % \fi % \\\hline % \end{tabular} % % \ifboolexprLoaded Results in \textcolor{green}{green} were evaluated by \xpackage{boolexpr.sty} at compilation time. % \else Results in \textcolor{green}{green} were not evaluated at compilation time: \thispackage was not found. % \fi % % \subsection{Purely expandable macros for tests with \xpackage{boolexpr}} % % Please refer to the \xpackage{etextools} package documentation at :§ % \url{http://www.ctan.org/tex-archive/macros/latex/contrib/etextools/etextools.pdf} % % % % % % \StopEventually{ % } % % \clearpage % \section{Implementation} % % \subsection{The algorithm} \enlargethispage{2\baselineskip} % % The \emph{string} is the suite of \textit{atomic expressions} connected by |\AND| or |\OR|.§ % The \emph{result} must be $0$ if the \emph{string} is true, and non zero if the \emph{string} is false.§ % ``\emph{go to} |some macro|'' means: ``\emph{now expand} |some macro|''. % % \def\orbuffer{\textsc{or}-buffer} % \begin{enumerate}[label=\fbox{\Alph*},itemsep=12pt] % \item |\bex@OR| % \begin{enumerate}[label=\arabic*)] % \item Split the \emph{string} into two parts:\\ % |#1| = before the first |\OR| (|#1| does not contain any |\OR|) \\ % |#2| = after the first |\OR| % \item If |#2| is blank: the \emph{string} contains no |\OR|\\ % \hspace*{2em} then go to |\bex@AND| to test |\AND| relations in |#1| \\ % Otherwise: test the |\AND| relations in |#1| and keep |#2| in a so called ``\orbuffer'' for further testing. % \end{enumerate} % \item |\bex@AND| \\ % |#1| = \orbuffer\ for further testing if needed % \begin{enumerate}[label=\arabic*)] % \item Split the string ``before the first |\OR|'' (\ie the |#1| of A.1) into two parts:\\ % |#2| = before the first |\AND| (|#2| is an \textit{atomic expression}) \\ % |#3| = after the first |\AND| (|#3| does not contain any |\OR|) % \item Then test |#2| (the \textit{atomic expression}): % \begin{enumerate}[label=\textbullet\:] % \item[TRUE:] \underline{If \Sharp3 is blank} then |#2| is either: % \begin{enumerate}[label=\textbullet,topsep=0pt,partopsep=0pt,itemsep=0pt,parsep=0pt] % \item an atomic expression alone % \item the last atomic expression in \emph{string}, preceded by |\OR| % \item an atomic expression preceded by |\OR| and followed by |\OR| % \end{enumerate} % In each of these 3 cases, the whole expression (\ie the \textit{string}) is true % because |#2| is true (otherwise, we had known the result of the whole \textit{string} earlier, and % were not into testing |#2|) \\ % \underline{Now if \Sharp3 is not blank} then |#2| is followed by |\AND|:\\ % \hspace*{2em} go to |\bex@ANDAND| to test the series of |\AND| % \item[FALSE:] \underline{if the \orbuffer\ \Sharp1 is blank} then |#2| is either: % \begin{enumerate}[label=\textbullet,topsep=0pt,partopsep=0pt,itemsep=0pt,parsep=0pt] % \item an atomic expression alone % \item an atomic expression followed a series of |\AND| (and no |\OR|) % \item the last atomic expression of the \emph{string} % \end{enumerate} % In each or these 3 cases, the whole expression (\ie the \emph{string}) is false % because |#2| is false (otherwise, the result would have been known earlier) \\ % \underline{Now if the \orbuffer\ \Sharp1 is not blank,} then we have to do more tests to get the result:\\ % \hspace*{2em} go to |\bex@OR| to split the \orbuffer\ (|#1| here) and continue testing... % \end{enumerate} % \end{enumerate} % \item |\bex@ANDAND| \\ % |#1| is the \orbuffer\ for further testing if needed % \begin{enumerate}[label=\arabic*)] % \item Split the string (\ie |#3| in B.2.\textsc{true}) into two parts:\\ % |#2| : before the first |\AND| (|#2| is an \textit{atomic expression}) \\ % |#3| : after the first |\AND| \\ \clearpage % \item Test the \textit{atomic expression} |#2|: % \begin{enumerate}[label=\textbullet\:] % \item [TRUE:] \underline{If \Sharp3 is blank} then |#2| is the last atomic expression of a series of |\AND| % (possibly followed by |\OR|). \\ % Conclusion: the whole \emph{string} is true (otherwise, we would have concluded earlier % that it was false and were not into testing |#2|... think about it) \\ % \underline{Now if \Sharp3 is not blank} then |#2| is followed by |\AND| and we have to test further:\\ % \hspace*{2em} go to |\bex@ANDAND| to test |#3|. % % \item [FALSE:] we do not have to test the following |\AND|: the |\AND|-connected series is false.\\ % \underline{If the \orbuffer\ \Sharp1 is blank} then the whole \emph{string} is false. \\ % \underline{Now if the \orbuffer\ \Sharp1 is not blank}: continue testing into this \orbuffer\ :\\ % \hspace*{2em} go to |\bex@OR|. % \end{enumerate} % \end{enumerate} % % \end{enumerate} % % \subsection{Category codes considerations}\label{catcodes} % % At first glance, the author of this package wanted to test inequality with the operator $\char33\!=$. A problem arose % because some languages make the character \char33\ active (f.ex. french). As far as babel changes the catcodes % |\AtBeginDocument|, the category code of \char33\ is different in the preamble (12) than in the document (13). % % After all, it was possible to change the definitions after begin document but... if you try to make the = character % active, you will (surprisingly) observe that a test like:§ % \qquad|\ifnum 4=4 ok\fi|§ % leads you to one of the following error messages:\parskip=0pt§ % \begin{tabbing} %\qquad\=|undefined control sequence =|\qquad\= if |=| is undefined \\ %\>|missing = inserted for \ifnum|\> if |=| is defined. % \end{tabbing}\restoreparskip % % The same apply for |<| or |>|. Therefore: such conditionals are possible for \TeX{} only if |=|\,,\,|<| and |>| % have a category code of 12 (11 is forbidden too). % % Thus the choice of |<>| is far easier and more reliable than the c-like $\char33\!=$. % % \subsection{Identification} % % This package is intended to use with a \LaTeX{} distribution of \eTeX{}. % % \begin{macrocode} %<*package> \ProvidesPackage{boolexpr} [2010/04/15 v3.14 Purely expandable boolean expressions and switch (eTeX)] % \end{macrocode} % \iffalse % % \fi % % \subsection{Special catcode} % The colon (/) will be used as a delimiter. We give it a category code of 8 (as in \xpackage{etextools}): % \iffalse %% Make a colon (:) of catcode 4 (used as delimiter) % \fi % \begin{macrocode} \let\bex@AtEnd\@empty \def\TMP@EnsureCode#1#2{% \edef\bex@AtEnd{% \bex@AtEnd \catcode#1 \the\catcode#1\relax }% \catcode#1 #2\relax } \TMP@EnsureCode{95}{11}% _ \TMP@EnsureCode{47}{8}% / etextool delimiter \TMP@EnsureCode{60}{12}% < \TMP@EnsureCode{61}{12}% = \TMP@EnsureCode{62}{12}% > \TMP@EnsureCode{43}{12}% - \TMP@EnsureCode{45}{12}% + \TMP@EnsureCode{58}{8}% : delimitor % \end{macrocode} % \iffalse % % \fi % % \subsection{Tree helper macros} % % While reading the \texttt{log} file it is preferable to read |\@firstoftwo|/|\@secondoftwo| % when the algorithm is making a choice (|\ifblank|) and |\bex@truepart|/|bex@falsepart| % when the algorithm has just determined the result of an atomic expression. % \iffalse %% Three helper macros % \fi % \begin{macrocode} \let\bex@truepart\@firstoftwo \let\bex@falsepart\@secondoftwo % \end{macrocode} % \iffalse % % \fi % % % \begin{macro}{\bex@nbk} % The following macro is purely expandable and its code is most probably due to D. Arseneau (\xpackage{url.sty}). % \cs{bex@nbk} means if \textbf{n}ot \textbf{b}lan\textbf{k}. % \begin{macrocode} \long\def\bex@nbk#1#2/#3#4#5//{#4} % \end{macrocode} % \end{macro} % % \begin{macro}{\bex@ifoptchar} % \cs{bex@ifoptchar} checks if a character is a single opening bracket `\,\textbf{[}\,`. % \begin{macrocode} \long\def\bex@ifoptchar#1[#2/#3#{\csname @\if @\detokenize{#1#2}@% first\else second\fi oftwo\endcsname} % \end{macrocode} % \end{macro} % % \iffalse % % \fi % % \subsection{Atomic expression evaluation} % % The six possible numeric atomic expressions\, $x < y$\,, $x<=y$\,, $x > y$\,, $x>=y$\,, $x<>y$\, and $x=y$ are first % transformed to their zero-form:§ % |\numexpr| $x-y<0$\,,|\numexpr| $x-y>0$\,,|\numexpr| $x-y<>0$\,, |\numexpr| $x-y=0$\, etc. % % Before all, we need to know which relation is used in the atomic expression: % % \begin{macro}{\bex@rel} % |\bex@rel| tests an \textit{atomic expression}: first determine its type % (inferior to, superior to, equality, inequality, other |\boolexpr|) and then % use the appropriate evaluation macro: % \iffalse %% \bex@rel tests each atomic expression: choose which evaluation macro to use first % \fi % \begin{macrocode} \long\def\bex@rel#1{% \bex@test_eval#1/{\bex@eval{#1}} {\bex@test_neq#1<>//{\bex@neq #1/} {\bex@test_infeq#1<=//{\bex@infeq #1/} {\bex@test_inf#1=//{\bex@supeq #1/} {\bex@test_sup#1>//{\bex@sup #1/} {\bex@test_eq#1=//{\bex@eq #1/} {\@latex@error{Unknown relation found while scanning \noexpand\boolexpr!}\@ehd}//}//}//}//}//}//}} % \end{macrocode} % \end{macro} % \iffalse % % \fi % % \begin{macro}{The test macros} % They test each \textit{atomic expression} in order to determine its type: % \iffalse %% Tests macros to determine the type of each atomic expression % \fi % \begin{macrocode} \def\bex@test_neq#1<>#2/{\bex@nbk#2/} \def\bex@test_eq#1=#2/{\bex@nbk #2/} \def\bex@test_infeq#1<=#2/{\bex@nbk #2/} \def\bex@test_inf#1<#2/{\bex@nbk #2/} \def\bex@test_supeq#1>=#2/{\bex@nbk #2/} \def\bex@test_sup#1>#2/{\bex@nbk #2/} \long\def\bex@test_eval#1#2/{% \ifcat\noexpand#1\relax% #1 is a control sequence \bex@test_Eval{#1} \else \expandafter\@secondoftwo \fi} \long\def\bex@test_Eval#1#2\fi{\fi\csname @% \ifx#1\the second% \else\ifx#1\numexpr second% \else\ifx #1\number second% \else\ifx #1\dimexpr second% \else\ifx #1\glueexpr second% \else\ifx #1\muexpr second% \else\ifx #1\value second% \else first% \fi\fi\fi\fi\fi\fi\fi oftwo\endcsname} % \end{macrocode} % \end{macro} % \iffalse % % \fi % % \begin{macro}{Evaluation macros} % They evaluate each \textit{atomic expression} according to its type: % \iffalse %% Evaluation macro that evaluates an atomic expression depending on its type: % \fi % \begin{macrocode} \long\def\bex@true_or_false#1{\csname bex@% \ifnum\numexpr#1 true\else false\fi part\endcsname} \long\def\bex@false_or_true#1{\csname bex@% \ifnum\numexpr#1 false\else true\fi part\endcsname} % \end{macrocode} % % \iffalse % % \fi % \begin{macrocode} \def\bex@eq#1=#2/{\bex@true_or_false{#1-(#2)=0}} \def\bex@neq#1<>#2/{\bex@false_or_true{#1-(#2)=0}} \def\bex@infeq#1<=#2/{\bex@false_or_true{#1-(#2)>0}} \def\bex@inf#1<#2/{\bex@true_or_false{#1-(#2)<0}} \def\bex@supeq#1>=#2/{\bex@false_or_true{#1-(#2)<0}} \def\bex@sup#1>#2/{\bex@true_or_false{#1-(#2)>0}} \long\def\bex@eval#1{\bex@true_or_false{#1=0}} % \end{macrocode} % \end{macro} % \iffalse % % \fi % % \subsection{\texttt{\textbf{\textbackslash AND}} and \texttt{\textbf{\textbackslash OR}} management} % % \begin{macro}{\bex@OR} % |\bex@OR| splits the string to evaluate into two parts: before the first |\OR| and after: % \iffalse %% \bex@OR splits the string to evaluate into two parts: before the first \OR and after % \fi % \begin{macrocode} \long\def\bex@OR#1\OR#2:{\bex@AND{#2}#1\AND:} % \end{macrocode} % \end{macro} % \iffalse % % \fi % % \begin{macro}{\bex@AND} % |\bex@AND| splits the string to evaluate into two parts: before the first |\AND| and after: % \iffalse %% \bex@AND splits the string to evaluate into two parts: before the first \AND and after: % \fi % \begin{macrocode} \long\def\bex@AND#1#2\AND#3:{% \bex@rel{#2} {\bex@nbk #3//{\bex@ANDAND{#1}#3:}{+0}//} {\bex@nbk #1//{\bex@OR#1:}{+1}//}} % \end{macrocode} % \end{macro} % \iffalse % % \fi % % \begin{macro}{\bex@ANDAND} % |\bex@ANDAND| evaluate successive \textit{atomic expressions} related by |\AND| until % false is found or until the end if every expression is true: % \iffalse %% \bex@ANDAND evaluate successive atomic expressions related by \AND: % \fi % \begin{macrocode} \long\def\bex@ANDAND#1#2\AND#3:{% \bex@rel{#2} {\bex@nbk #3//{\bex@ANDAND{#1}#3:}{+0}//} {\bex@nbk #1//{\bex@OR#1:}{+1}//}} % \end{macrocode} % \end{macro} % \iffalse % % \fi % % \begin{macro}{\boolexpr} % |\boolexpr| is the entry point for evaluating boolean expressions: % \iffalse %% \boolexpr: the entry point for evaluating boolean expressions % \fi % \begin{macrocode} \newcommand\boolexpr[1]{\bex@nbk #1//{\numexpr\bex@OR#1\OR:}{+1}//} % \end{macrocode} % \end{macro} % \iffalse % % \fi % % \begin{macro}{\ifboolexpr} % |\ifboolexpr| is the \LaTeX{} form of |\boolexpr| tests: % \iffalse %% \ifboolexpr: the LaTeX form of \boolexpr tests % \fi % \begin{macrocode} \ifdefined\ifboolexpr% etoolbox defines ifboolexpr... \PackageWarning{boolexpr}{\string\ifboolexpr\space has been defined before\MessageBreak by etoolbox (I suppose) - Overwritting} \renewcommand\ifboolexpr[1]{\bex@true_or_false{\boolexpr{#1}=0}} \else \newcommand\ifboolexpr[1]{\bex@true_or_false{\boolexpr{#1}=0}} \fi % \end{macrocode} % \end{macro} % \iffalse % % \fi % % \begin{macro}{\switch} % \cs{switch} is not long to implement... see: % \begin{macrocode} \long\def \switch#1\endswitch {\bex@nbk#1//{\bex@switch_opt#1\endswitch}{}//} \long\def \bex@switch_opt#1#2\endswitch{\bex@ifoptchar#1/[/ {\bex@switch_opti#1#2\endswitch}{\bex@switch_opti[]#1#2\endswitch}}%] \def \bex@switch_opti[#1]#2\endswitch {\bex@switch_otherwise[{#1}]#2\otherwise\endswitch} \def\bex@switch_otherwise[#1]#2\otherwise#3\endswitch{% \bex@switch_case[{#1}]#2\case\endswitch {\bex@nbk#3//{\bex@otherwise#3\endswitch}{}//} \endswitch} \def\bex@switch_case[#1]#2\case#3\endswitch{\bex@nbk#2//% {\bex@case[{#1}]#2\endcase% {\bex@nbk#3//{\bex@switch_case[{#1}]#3\endswitch}\@firstoftwo//}}% {\bex@nbk#3//{\bex@switch_case[{#1}]#3\endswitch}\@firstoftwo//}//} \long\def\bex@case[#1]#2#3\endcase{\ifboolexpr{#1#2}{\bex@after_endswitch{#3}}} \long\def\bex@after_endswitch#1#2\endswitch{#1} \long\def\bex@otherwise#1\otherwise#2\endswitch{#1} % \end{macrocode} % \end{macro} % % \subsubsection{Purely expandable macros for tests with \xpackage{boolexpr}} % %\begin{macro}{\bex@pdfmatch} % \begin{macrocode} \long\def\bex@pdfmatch#1#2{\ifnum\pdfmatch{#2}{#1}=0 1\else0\fi} % \end{macrocode} %\end{macro} % % \begin{macro}{\bex@ifempty} % \begin{macrocode} \long\def\bex@ifempty#1{\if\relax\detokenize{#1}\relax0\else1\fi} \long\def\bex_ifempty#1{\csname @\if\relax\detokenize{#1}\relax first\else second\fi oftwo\endcsname} % \end{macrocode} % \end{macro} % %\begin{macro}{\bex@ifblank} % \begin{macrocode} \long\def\bex@ifblank#1{\bex@nbk#1//10//} % \end{macrocode} %\end{macro} % %\begin{macro}{\bex@ifx} % \begin{macrocode} \long\def\bex@ifx#1#2{\bex__ifx#1#2//} \long\def\bex_ifx#1#2#3/#4#5#6//{\bex@nbk#6//{\ifx#1#2\bex_else#5\else\bex_fi#6\fi}{#5}//} \long\def\bex_else#1\else#2\fi{\fi#1} \long\def\bex_fi#1\fi{\fi#1} % \end{macrocode} %\end{macro} % %\begin{macro}{\bex@comp} % \begin{macrocode} \long\def\bex@comp#1{\bex@ifoptchar#1/[/\bex@c@mp{\bex@c@mp@[\numexpr]}} \long\def\bex@c@mp[#1#2]#3#4#5{% \bex_ifempty{#2}{% \ifx #1\dimexpr \bex@c@mp@\ifdim\dimexpr{#3}{#4}{#5}% \else\ifx #1\numexpr \bex@c@mp@\ifnum\numexpr{#3}{#4}{#5}% \else\ifx #1\glueexpr \bex@c@mp@\ifdim\glueexpr{#3}{#4}{#5}% \else\ifx #1\muexpr \bex@c@mp@\ifdim\muexpr{#3}{#4}{#5}% \else\ifx #1\number \bex@c@mp@\ifnum\numexpr{#3}{#4}{#5}% \else\PackageError{boolexpr}{% Invalid comparison test while scanning \string\bex@comp\MessageBreak found: \detokenize{#1}}% \fi\fi\fi\fi\fi}% {\PackageError{boolexpr}{Invalid comparison test while scanning \string\bex@comp\MessageBreak found: \detokenize{#1}}}} \long\def\bex@c@mp@#1#2#3#4#5{#1#2#3#4#5 0\else 1\fi} % \end{macrocode} %\end{macro} % % \begin{macrocode} \bex@AtEnd\let\bex@AtEnd\@undefined % % \end{macrocode} % % \subsection{Future developments : to do} % % \thispackage should work either with \eTeX{} or \eTeX-\LaTeX{}... % % May be build a ``real'' |\NOT| operator. % % \begin{History} % \begin{Version}{2010/04/15 v3.14} % \item \xpackage{etoolbox} now defines a \cs{ifboolexpr} macro (not purely expandable). \\ % Fix has been done (with a warning) to be able to use \cs{ifboolexpr} from \thispackage. % \end{Version} % % \begin{Version}{2009/09/30 v3.1} % \item Support of |\pdfmatch| added (|\bex@pdfmatch|) \\ % \end{Version} % % \begin{Version}{2009/09/03 v3.0 -- \eTeX{}- and Xe\TeX{}- stable} % \item % Many bug fixed in \cmdref{switch}. Tested on \LaTeX, pdf\LaTeX{} and Xe\LaTeX. % \item % Revision of this pdf documentation. % \end{Version} % % \begin{Version}{2009/08/31 v2.9} % \item % Added |\value| in the ``list of exceptions'' (\cs{bex@test_Eval}) % Enhancement of |\switch| with the optional first argument (refer to the examples). % \end{Version} % % \begin{Version}{2009/08/13 v2.2} % \item % Small optimisation in \cs{bex@OR} % \end{Version} % % \begin{Version}{2009/08/12 v2.1} % \item % Added the \cs{switch} syntax % \item % Small bug (|\numexpr| forgotten in the ``list of exceptions'' (\cs{bex@test_Eval}) % \item % Redesigned tests for better compilation % \end{Version} % % \begin{Version}{2009/07/22 v1.0} % \item % First version. % \end{Version} % % \end{History} % % \clearpage % \PrintIndex % % \label{LastPage} % \Finale