summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/datatool/datatool.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2007-08-24 18:43:05 +0000
committerKarl Berry <karl@freefriends.org>2007-08-24 18:43:05 +0000
commitfe752bd7396fcc8c6fb65128bcd481a5e326e7cd (patch)
tree216701b87bcd27c641a8a57b4cbd7e2c9dd815ae /Master/texmf-dist/source/latex/datatool/datatool.dtx
parentfabf181c6946e1e5ea931f003df726c9c1c553b8 (diff)
datatool 1.01 (20aug07)
git-svn-id: svn://tug.org/texlive/trunk@4804 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/datatool/datatool.dtx')
-rw-r--r--Master/texmf-dist/source/latex/datatool/datatool.dtx19616
1 files changed, 19616 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/datatool/datatool.dtx b/Master/texmf-dist/source/latex/datatool/datatool.dtx
new file mode 100644
index 00000000000..f2afe8ec4b3
--- /dev/null
+++ b/Master/texmf-dist/source/latex/datatool/datatool.dtx
@@ -0,0 +1,19616 @@
+%\iffalse
+% datatool.dtx generated using makedtx version 0.94b (c) Nicola Talbot
+% Command line args:
+% -macrocode "databib.bst"
+% -src "datatool.sty=>datatool.sty"
+% -src "datapie.sty=>datapie.sty"
+% -src "dataplot.sty=>dataplot.sty"
+% -src "databar.sty=>databar.sty"
+% -src "databib.sty=>databib.sty"
+% -src "databib.bst=>databib.bst"
+% -author "Nicola Talbot"
+% -dir "source"
+% -setambles ".*\.bst=>\nopreamble\usepreamble\defaultpreamble\nopostamble"
+% -comment "databib.bst"
+% -doc "manual.tex"
+% -codetitle "datatool.sty"
+% datatool
+% Created on 2007/8/19 14:27
+%\fi
+%\iffalse
+%<*package>
+%% \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 \~}
+%</package>
+%\fi
+% \iffalse
+% Doc-Source file to use with LaTeX2e
+% Copyright (C) 2007 Nicola Talbot, all rights reserved.
+% \fi
+% \iffalse
+%<*driver>
+\documentclass[a4paper]{ltxdoc}
+\usepackage{ifthen}
+\usepackage[verbose=false]{datatool}
+\usepackage{datapie,databar,databib}
+\usepackage{textcomp}
+\usepackage{graphicx}
+\usepackage{colortbl}
+\usepackage[colorlinks,
+ bookmarks,
+ hyperindex=false,
+ pdfauthor={Nicola L.C. Talbot},
+ pdftitle={datatool: Databases and data manipulation},
+ pdfkeywords={LaTeX,package,database,data,chart,plot}]{hyperref}
+\usetikzlibrary{snakes}
+
+ %hyperindex conflicts with doc
+ %(end up with |usage|hyperpage in indexentry)
+ %This unfortunately means that the changes section doesn't
+ %have active links, but at least it will keep makeindex happy.
+
+\renewcommand{\usage}[1]{\textit{\hyperpage{#1}}}
+\renewcommand{\main}[1]{\hyperpage{#1}}
+\newcommand{\see}[2]{\emph{see} #1}
+\makeatletter
+\def\index@prologue{\section*{Index}}
+
+ % commands are too wide for a 3 column index
+ \def\theindex{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi
+ \columnseprule \z@ \columnsep 35\p@
+ \twocolumn[\index@prologue]%
+ \IndexParms \let\item\@idxitem \ignorespaces}
+ \def\endtheindex{\if@restonecol\onecolumn\else\clearpage\fi}
+\makeatother
+\RecordChanges
+\PageIndex
+\CheckSum{13202}
+
+\newcommand*{\sty}[1]{\textsf{#1}}
+\newcommand*{\env}[1]{\textsf{#1}}
+\newcommand*{\ext}[1]{\texttt{#1}}
+\definecolor{defbackground}{rgb}{0.8,1,1}
+
+\makeatletter
+\newcommand*{\setting}[2]{\textsf{#2}\relax
+\@for\thiscmd:=#1\do{%
+\edef\doindex{\noexpand\index
+{\thiscmd\space settings=\noexpand\cs{\thiscmd} settings>#2=\noexpand
+\textsf{#2}|hyperpage}}\doindex
+}}
+\makeatother
+
+\newcommand*{\counterfmt}[1]{\texttt{#1}\index
+{#1 counter=\texttt{#1} counter|hyperpage}}
+
+\newcommand*{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}}
+
+\newsavebox\defsbox
+\newlength\defwidth
+\newenvironment{definition}{%
+\setlength{\fboxsep}{4pt}\setlength{\fboxrule}{1.25pt}%
+\begin{lrbox}{\defsbox}%
+\setlength\defwidth\linewidth
+\addtolength\defwidth{-2\fboxrule}%
+\addtolength\defwidth{-2\fboxsep}%
+\begin{minipage}{\defwidth}\flushleft
+}{%
+\end{minipage}
+\end{lrbox}%
+\vskip10pt
+\noindent
+\fcolorbox{black}{defbackground}{\usebox\defsbox}%
+\vskip10pt
+}
+
+\newlength\tmplength
+\newcommand{\importantpar}{\relax
+\settowidth{\hangindent}{\bfseries\Huge$\bigtriangleup$\space}\relax
+\settoheight{\tmplength}{\bfseries\Huge$\bigtriangleup$}\relax
+\addtolength{\tmplength}{-0.5\baselineskip}\relax
+\hskip-\hangindent
+\smash{\raisebox{-\tmplength}{\bfseries
+\raisebox{3pt}{\large!}$\!$\makebox[0pt]{\Huge$\bigtriangleup$}\relax
+}}\relax
+\hskip0.5\hangindent
+\hangafter=-2\relax
+}
+
+\newcommand*{\pkgopt}[2][datatool]{\textsf{#2}\index
+{#1 package options=\textsf{#1} package options>#2=\textsf{#2}|hyperpage}}
+
+\newcounter{example}
+\newcommand*{\examplename}{example}
+\makeatletter
+\newenvironment{example}[2]{\refstepcounter{example}\label{#2}%
+\par\vskip10pt\noindent
+\textbf{\large Example \theexample\ (#1)}%
+\addcontentsline{loe}{section}{\protect\numberline{\theexample}#1}%
+\nopagebreak\par\vskip10pt\nopagebreak
+}%
+{\begin{center}\rule{2in}{1pt}\end{center}}
+
+\newcommand*{\listofexamples}{\section*{List of Examples}%
+\@starttoc{loe}}
+\makeatother
+
+ %bibliography database
+\DTLnewdb{docbib}
+\DTLnewrow{docbib}
+\DTLnewdbentry{docbib}{CiteKey}{Goossens}
+\DTLnewdbentry{docbib}{EntryType}{book}
+\DTLnewdbentry{docbib}{Author}{{}{Goossens}{}{Michel},{}{Mittelbach}{}{Frank},{}{Samarin}{}{Alexander}}
+\DTLnewdbentry{docbib}{Title}{The \LaTeX\ Companion}
+\DTLnewdbentry{docbib}{Publisher}{Addison-Wesley}
+\DTLnewdbentry{docbib}{Year}{1994}
+
+
+\begin{document}
+\DocInput{datatool.dtx}
+\end{document}
+%</driver>
+%\fi
+%\MakeShortVerb{"}
+%\DeleteShortVerb{\|}
+%
+% \title{datatool v 1.01: Databases and data manipulation}
+% \author{Nicola L.C. Talbot\\[10pt]
+%School of Computing Sciences\\
+%University of East Anglia\\
+%Norwich. Norfolk\\
+%NR4 7TJ. United Kingdom.\\
+%\url{http://theoval.cmp.uea.ac.uk/~nlct/}}
+%
+% \date{17th August 2007}
+% \maketitle
+%\tableofcontents
+%\listofexamples
+%\listoffigures
+%\listoftables
+%
+% \section{Introduction}
+%
+% \changes{1.0}{2007 July 22}{Initial version}
+%The \sty{datatool} bundle consists of the following
+%packages: \sty{datatool}, \sty{datapie}, \sty{dataplot},
+%\sty{databar} and \sty{databib}.
+%
+%The \sty{datatool} package can be used to:
+%\begin{itemize}
+%\item Create or load databases.
+%\item Sort rows of a database (either numerically or alphabetically,
+%ascending or descending.)
+%\item Perform repetitive operations on each row of a database
+%(e.g.\ mail merging.) Conditions may be imposed to exclude rows.
+%\item Determine whether an argument is an integer, a real number,
+%currency or a string. (Scientific notation is currently not
+%supported.) Locale dependent number settings are supported (such
+%as a comma as a decimal character and a full stop as a number
+%group character.)
+%\item Convert locale dependent numbers/currency to the decimal
+%format required by the \sty{fp} package, enabling fixed point
+%arithmetic to be performed on elements of the database.
+%\item Names can be converted to initials.
+%\item Strings can be tested to determine if they are all
+%upper or lower case.
+%\item String comparisons (both case sensitive and case insensitive)
+%can be performed.
+%\end{itemize}
+%
+%The \sty{datapie} package can be used to convert a database into
+%a pie chart:
+%\begin{itemize}
+%\item Segments can be separated from the rest of the chart to make
+%them stand out.
+%\item Colour/grey scale options.
+%\item Predefined segment colours can be changed.
+%\item Hooks provided to add extra information to the chart
+%\end{itemize}
+%
+%The \sty{databar} package can be used to convert a database into
+%a bar chart:
+%\begin{itemize}
+%\item Colour/grey scale options.
+%\item Predefined bar colours can be changed.
+%\item Hooks provided to add extra information to the chart
+%\end{itemize}
+%
+%(The \sty{datapie} and \sty{databar} packages do not support the
+%creation of 3D charts, and I have no plans to implement them at any
+%later date. The use of 3D charts should be discouraged. They may look
+%pretty, but the purpose of a chart is to be informative. Three
+%dimensional graphics cause distortion, which can result in misleading
+%impressions.)
+%
+%The \sty{dataplot} package can be used to convert a database into
+%a two dimensional plot using markers and/or lines. Three dimensional
+%plots are currently not supported.
+%
+%The \sty{databib} package can be used to convert a \BibTeX\ database
+%into a \sty{datatool} database.
+%
+%\section{Data Types}
+%\label{sec:datatypes}
+%
+%The \sty{datatool} package recognises four data types: integers,
+%real numbers, currency and strings.
+%
+%\begin{description}
+%\item[Integers] An integer is a sequence of digits, optionally
+%groups of three digits may be separated by the number group character.
+%The default number group character is a comma (,) but may be
+%changed using \cs{DTLsetnumberchars} (see below.)
+%
+%\item[Real Numbers] A real number is an integer followed by the
+%decimal character followed by one or more digits. The decimal
+%character is a full stop (.) by default. The number group
+%and decimal characters may be changed using
+%\DescribeMacro{\DTLsetnumberchars}
+%\begin{definition}
+%\cs{DTLsetnumberchars}\marg{number group character}\marg{decimal character}
+%\end{definition}
+%Note that scientific notation is not supported, and the number group
+%character may not be used after the decimal character.
+%
+%\item[Currency] A currency symbol followed by an integer or
+%real number is considered to be the currency data type.
+%There are two predefined currency symbols, "\$" and \cs{pounds}.
+%In addition, if any of the following commands are defined at the
+%start of the document, they are also considered to be a currency
+%symbol: \cs{texteuro}, \cs{textdollar}, \cs{textstirling},
+%\cs{textyen}, \cs{textwon}, \cs{textcurrency}, \cs{euro}
+%and \cs{yen}. Additional currency symbols can be defined using
+%\DescribeMacro{\DTLnewcurrencysymbol}
+%\begin{definition}
+%\cs{DTLnewcurrencysymbol}\marg{symbol}
+%\end{definition}
+%
+%\item[Strings] Anything that doesn't belong to the above three
+%types is considered to be a string.
+%
+%\end{description}
+%
+%\subsection{Conditionals}
+%\label{sec:ifconditions}
+%
+%The following conditionals are provided by the \sty{datatool}
+%package:
+%
+%\DescribeMacro{\DTLifint}
+%\begin{definition}
+%\cs{DTLifint}\marg{text}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{text} is an integer then do \meta{true part}, otherwise
+%do \meta{false part}. For example
+%\begin{verbatim}
+%\DTLifint{2536}{integer}{not an integer}
+%\end{verbatim}
+%produces:
+%\DTLifint{2536}{integer}{not an integer}.
+%
+%The number group character may appear in the number, for example:
+%\begin{verbatim}
+%\DTLifint{2,536}{integer}{not an integer}
+%\end{verbatim}
+%produces:
+%\DTLifint{2,536}{integer}{not an integer}.
+%However, the number group character may only be followed by a group
+%of three digits. For example:
+%\begin{verbatim}
+%\DTLifint{2,5,3,6}{integer}{not an integer}
+%\end{verbatim}
+%produces:
+%\DTLifint{2,5,3,6}{integer}{not an integer}.
+%The number group character may be changed. For example:
+%\begin{verbatim}
+%\DTLsetnumberchars{.}{,}%
+%\DTLifint{2,536}{integer}{not an integer}
+%\end{verbatim}
+%this now produces:
+%\DTLsetnumberchars{.}{,}\relax
+%\DTLifint{2,536}{integer}{not an integer}, since 2,536 is now
+%a real number.
+%
+%Note that nothing else can be appended or prepended to the
+%number. For example:
+%\begin{verbatim}
+%\DTLsetnumberchars{,}{.}%
+%\DTLifint{2,536m}{integer}{not an integer}
+%\end{verbatim}
+%produces:
+%\DTLsetnumberchars{,}{.}\relax
+%\DTLifint{2,536m}{integer}{not an integer}.
+%
+%\DescribeMacro{\DTLifreal}
+%\begin{definition}
+%\cs{DTLifreal}\marg{text}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{text} is a real number then do \meta{true part}, otherwise
+%do \meta{false part}. For example
+%\begin{verbatim}
+%\DTLifreal{1000.0}{real}{not real}
+%\end{verbatim}
+%produces:
+%\DTLifreal{1000.0}{real}{not real}.
+%
+%Note that an integer is not a real number:
+%\begin{verbatim}
+%\DTLifreal{1,000}{real}{not real}
+%\end{verbatim}
+%produces:
+%\DTLifreal{1,000}{real}{not real}.
+%
+%Whereas
+%\begin{verbatim}
+%\DTLifreal{1,000.0}{real}{not real}
+%\end{verbatim}
+%produces:
+%\DTLifreal{1,000.0}{real}{not real}.
+%
+%However
+%\begin{verbatim}
+%\DTLsetnumberchars{.}{,}%
+%\DTLifreal{1,000}{real}{not real}
+%\end{verbatim}
+%produces:
+%\DTLsetnumberchars{.}{,}\relax
+%\DTLifreal{1,000}{real}{not real} since the comma is now
+%the decimal character.
+%
+%Currency is not considered to be real:
+%\begin{verbatim}
+%\DTLsetnumberchars{,}{.}%
+%\DTLifreal{\$1.00}{real}{not real}
+%\end{verbatim}
+%produces:
+%\DTLsetnumberchars{,}{.}\relax
+%\DTLifreal{\$1.00}{real}{not real}.
+%
+%\DescribeMacro{\DTLifcurrency}
+%\begin{definition}
+%\cs{DTLifcurrency}\marg{text}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{text} is currency, then do \meta{true part}, otherwise
+%do false part. For example:
+%\begin{verbatim}
+%\DTLifcurrency{\$5.99}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\DTLifcurrency{\$5.99}{currency}{not currency}. Similarly:
+%\begin{verbatim}
+%\DTLifcurrency{\pounds5.99}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\DTLifcurrency{\pounds5.99}{currency}{not currency}.
+%Note, however, that
+%\begin{verbatim}
+%\DTLifcurrency{US\$5.99}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\DTLifcurrency{US\$5.99}{currency}{not currency}. If you want
+%this to be considered currency, you will have to add the
+%sequence "US\$" to the set of currency symbols:
+%\begin{verbatim}
+%\DTLnewcurrencysymbol{US\$}%
+%\DTLifcurrency{US\$5.99}{currency}{not currency}
+%\end{verbatim}
+%this now produces:
+%\DTLnewcurrencysymbol{US\$}\relax
+%\DTLifcurrency{US\$5.99}{currency}{not currency}.
+%
+%This document has used the \sty{textcomp} package which defines
+%\cs{texteuro}, so this is also considered to be currency. For
+%example:
+%\begin{verbatim}
+%\DTLifcurrency{\texteuro5.99}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\DTLifcurrency{\texteuro5.99}{currency}{not currency}.
+%
+%The preferred method is to display the euro symbol in a sans-serif
+%font, but
+%\begin{verbatim}
+%\DTLifcurrency{\textsf{\texteuro}5.99}{currency}{not currency}
+%\end{verbatim}
+%will produce:
+%\DTLifcurrency{\textsf{\texteuro}5.99}{currency}{not currency}.
+%
+%It is better to define a new command, for example:
+%\begin{verbatim}
+%\DeclareRobustCommand*{\euro}{\textsf{\texteuro}}
+%\end{verbatim}
+%and add that command to the list of currency symbols. In fact,
+%in this case, if you define the command \cs{euro} in the
+%preamble, it will automatically be added to the list of known
+%currency symbols. If however you define \cs{euro} in the document,
+%you will have to add it using \ics{DTLnewcurrencysymbol}. For
+%example:
+%\begin{verbatim}
+%\newcommand*{\euro}{\textsf{\texteuro}}%
+%\DTLnewcurrencysymbol{\euro}%
+%\DTLifcurrency{\euro5.99}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\DeclareRobustCommand*{\euro}{\textsf{\texteuro}}\relax
+%\DTLnewcurrencysymbol{\euro}\relax
+%\DTLifcurrency{\euro5.99}{currency}{not currency}.
+%
+%\DescribeMacro{\DTLifcurrencyunit}
+%\begin{definition}
+%\cs{DTLifcurrencyunit}\marg{text}\marg{symbol}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{text} is currency, and uses \meta{symbol} as the unit of
+%currency, then do \meta{true part} otherwise do \meta{false part}.
+%For example:
+%\begin{verbatim}
+%\DTLifcurrencyunit{\$6.99}{\$}{dollars}{not dollars}
+%\end{verbatim}
+%produces:
+%\DTLifcurrencyunit{\$6.99}{\$}{dollars}{not dollars}.
+%Another example:
+%\begin{verbatim}
+%\def\cost{\euro10.50}%
+%\DTLifcurrencyunit{\cost}{\euro}{euros}{not euros}
+%\end{verbatim}
+%produces:
+%\def\cost{\euro10.50}\relax
+%\DTLifcurrencyunit{\cost}{\euro}{euros}{not euros}.
+%
+%\DescribeMacro{\DTLifnumerical}
+%\begin{definition}
+%\cs{DTLifnumerical}\marg{text}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{text} is numerical (either an integer, real number or
+%currency) then do \meta{true part} otherwise do
+%\meta{false part}.
+%For example:
+%\begin{verbatim}
+%\DTLifnumerical{1,000.0}{number}{string}.
+%\end{verbatim}
+%produces: \DTLifnumerical{1,000.0}{number}{string}.
+%Whereas
+%\begin{verbatim}
+%\DTLsetnumberchars{.}{,}%
+%\DTLifnumerical{1,000.0}{number}{string}.
+%\end{verbatim}
+%produces:
+%\DTLsetnumberchars{.}{,}\relax
+%\DTLifnumerical{1,000.0}{number}{string}.
+%Since the number group character is now a full stop, and the
+%decimal character is now a comma. (The number group character
+%may only appear before the decimal character, not after it.)
+%
+%Currency is also considered to be numerical:
+%\begin{verbatim}
+%\DTLsetnumberchars{,}{.}%
+%\DTLifnumerical{\$1,000.0}{number}{string}.
+%\end{verbatim}
+%produces:
+%\DTLsetnumberchars{,}{.}\relax
+%\DTLifnumerical{\$1,000.0}{number}{string}.
+%
+%\DescribeMacro{\DTLifstring}
+%\begin{definition}
+%\cs{DTLifstring}\marg{text}\marg{true part}\marg{false part}
+%\end{definition}
+%This is the opposite of \cs{DTLifnumerical}. If \meta{text} is
+%not numerical, do \meta{true part}, otherwise do \meta{false part}.
+%
+%\DescribeMacro{\DTLifcasedatatype}
+%\begin{definition}
+%\cs{DTLifcasedatatype}\marg{text}\marg{string case}\marg{int case}\marg{real case}\marg{currency case}
+%\end{definition}
+%If \meta{text} is a string do \meta{string case}, if \meta{text}
+%is an integer do \meta{int case}, if \meta{text} is a real number
+%do \meta{real case}, if \meta{text} is currency do
+%\meta{currency case}. For example:
+%\begin{verbatim}
+%\DTLifcasedatatype{1,000}{string}{integer}{real}{currency}
+%\end{verbatim}
+%produces:
+%\DTLifcasedatatype{1,000}{string}{integer}{real}{currency}.
+%
+%\DescribeMacro{\DTLifnumeq}
+%\begin{definition}
+%\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{num1} is equal to \meta{num2}, then do \meta{true part},
+%otherwise do \meta{false part}. Note that both \meta{num1} and
+%\meta{num2} must be numerical (either integers, real numbers or
+%currency.) The currency symbol is ignored when determining
+%equality. For example
+%\begin{verbatim}
+%\DTLifnumeq{\pounds10.50}{10.5}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifnumeq{\pounds10.50}{10.5}{true}{false}, since they are
+%considered to be numerically equivalent. Likewise:
+%\begin{verbatim}
+%\DTLifnumeq{\pounds10.50}{\$10.50}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifnumeq{\pounds10.50}{\$10.50}{true}{false}.
+%
+%\DescribeMacro{\DTLifstringeq}
+%\begin{definition}
+%\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+%\DescribeMacro{\DTLifstringeq*}
+%\begin{definition}
+%\cs{DTLifstringeq*}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{string1} and \meta{string2} are the same, then do
+%\meta{true part}, otherwise do \meta{false part}. The starred
+%version ignores the case, the unstarred version is case
+%sensitive. Both
+%\meta{string1} and \meta{string2} are considered to be strings,
+%so for example:
+%\begin{verbatim}
+%\DTLifstringeq{10.50}{10.5}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifstringeq{10.50}{10.5}{true}{false}.
+%
+%Note that
+%\begin{verbatim}
+%\DTLifstringeq{Text}{text}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifstringeq{Text}{text}{true}{false}, whereas
+%\begin{verbatim}
+%\DTLifstringeq*{Text}{text}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifstringeq*{Text}{text}{true}{false}, however it should also be
+%noted that many commands will be ignored, so:
+%\begin{verbatim}
+%\DTLifstringeq{\uppercase{t}ext}{text}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifstringeq{\uppercase{t}ext}{text}{true}{false}.
+%
+%Spaces are considered to be equivalent to \cs{space} and "~". For
+%example:
+%\begin{verbatim}
+%\DTLifstringeq{an apple}{an~apple}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifstringeq{an apple}{an~apple}{true}{false}. Consecutive spaces
+%are treated as the same, for example:
+%\begin{verbatim}
+%\DTLifstringeq{an apple}{an apple}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifstringeq{an apple}{an apple}{true}{false}.
+%
+%\DescribeMacro{\DTLifeq}
+%\begin{definition}
+%\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+%\DescribeMacro{\DTLifeq*}
+%\begin{definition}
+%\cs{DTLifeq*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+%If both \meta{arg1} and \meta{arg2} are numerical, then this is
+%equivalent to \cs{DTLifnumeq}, otherwise it is equivalent to
+%\cs{DTLifstringeq} (when using \cs{DTLifeq}) or \cs{DTLifstringeq*}
+%(when using \cs{DTLifeq*}).
+%
+%\DescribeMacro{\DTLifnumlt}
+%\begin{definition}
+%\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{num1} is less than \meta{num2}, then do \meta{true part},
+%otherwise do \meta{false part}. Note that both \meta{num1} and
+%\meta{num2} must be numerical (either integers, real numbers or
+%currency.)
+%
+%\DescribeMacro{\DTLifstringlt}
+%\begin{definition}
+%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true
+%part}\marg{false part}
+%\end{definition}
+%\DescribeMacro{\DTLifstringlt*}
+%\begin{definition}
+%\cs{DTLifstringlt*}\marg{string1}\marg{string2}\marg{true
+%part}\marg{false part}
+%\end{definition}
+%If \meta{string1} is alphabetically less than \meta{string2}, then do
+%\meta{true part}, otherwise do \meta{false part}. The starred
+%version ignores the case, the unstarred version is case
+%sensitive.
+%For example:
+%\begin{verbatim}
+%\DTLifstringlt{aardvark}{zebra}{less}{not less}
+%\end{verbatim}
+%produces:
+%\DTLifstringlt{aardvark}{zebra}{less}{not less}.
+%
+%Note that both \meta{string1} and \meta{string2} are considered to be
+%strings, so for example:
+%\begin{verbatim}
+%\DTLifstringlt{2}{10}{less}{not less}
+%\end{verbatim}
+%produces:
+%\DTLifstringlt{2}{10}{less}{not less}, since the string "2"
+%comes after the string "10" when arranged alphabetically.
+%
+%The case sensitive (unstarred) version considers uppercase characters
+%to be less than lowercase characters, so
+%\begin{verbatim}
+%\DTLifstringlt{B}{a}{less}{not less}
+%\end{verbatim}
+%produces:
+%\DTLifstringlt{B}{a}{less}{not less}, whereas
+%\begin{verbatim}
+%\DTLifstringlt*{B}{a}{less}{not less}
+%\end{verbatim}
+%produces:
+%\DTLifstringlt*{B}{a}{less}{not less}.
+%
+%\DescribeMacro{\DTLiflt}
+%\begin{definition}
+%\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+%\DescribeMacro{\DTLiflt*}
+%\begin{definition}
+%\cs{DTLiflt*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{arg1} and \meta{arg2} are both numerical, then this
+%is equivalent to \cs{DTLifnumlt}, otherwise it is equivalent
+%to \cs{DTLstringlt} (when using \cs{DTLiflt}) or
+%\cs{DTLstringlt*} (when using \cs{DTLiflt*}).
+%
+%\DescribeMacro{\DTLifnumgt}
+%\begin{definition}
+%\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{num1} is greater than \meta{num2}, then do \meta{true part},
+%otherwise do \meta{false part}. Note that both \meta{num1} and
+%\meta{num2} must be numerical (either integers, real numbers or
+%currency.)
+%
+%\DescribeMacro{\DTLifstringgt}
+%\begin{definition}
+%\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true
+%part}\marg{false part}
+%\end{definition}
+%\DescribeMacro{\DTLifstringgt*}
+%\begin{definition}
+%\cs{DTLifstringgt*}\marg{string1}\marg{string2}\marg{true
+%part}\marg{false part}
+%\end{definition}
+%If \meta{string1} is alphabetically greater than \meta{string2}, then
+%do \meta{true part}, otherwise do \meta{false part}. The
+%starred version ignores the case, the unstarred version is
+%case sensitive. For example:
+%\begin{verbatim}
+%\DTLifstringgt{aardvark}{zebra}{greater}{not greater}
+%\end{verbatim}
+%produces:
+%\DTLifstringgt{aardvark}{zebra}{greater}{not greater}.
+%
+%Note that both \meta{string1} and \meta{string2} are considered to be
+%strings, so for example:
+%\begin{verbatim}
+%\DTLifstringgt{2}{10}{greater}{not greater}
+%\end{verbatim}
+%produces:
+%\DTLifstringgt{2}{10}{greater}{not greater}, since the string "2"
+%comes after the string "10" when arranged alphabetically.
+%
+%As with \cs{DTLifstringlt}, uppercase characters are considered
+%to be less than lower case characters when performing a
+%case sensitive comparison so:
+%\begin{verbatim}
+%\DTLifstringgt{B}{a}{greater}{not greater}
+%\end{verbatim}
+%produces:
+%\DTLifstringgt{B}{a}{greater}{not greater}, whereas
+%\begin{verbatim}
+%\DTLifstringgt*{B}{a}{greater}{not greater}
+%\end{verbatim}
+%produces:
+%\DTLifstringgt*{B}{a}{greater}{not greater}.
+%
+%\DescribeMacro{\DTLifgt}
+%\begin{definition}
+%\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+%\DescribeMacro{\DTLifgt*}
+%\begin{definition}
+%\cs{DTLifgt*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{arg1} and \meta{arg2} are both numerical, then this
+%is equivalent to \cs{DTLifnumgt}, otherwise it is equivalent
+%to \cs{DTLstringgt} (when using \cs{DTLifgt}) or
+%\cs{DTLstringgt*} (when using \cs{DTLifgt*}).
+%
+%\DescribeMacro{\DTLifnumclosedbetween}
+%\begin{definition}
+%\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} then do \meta{true part},
+%otherwise do \meta{false part}. Note that \meta{num}, \meta{min} and
+%\meta{max} must be numerical (either integers, real numbers or
+%currency.) The currency symbol is ignored when determining
+%equality. For example:
+%\begin{verbatim}
+%\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside}
+%\end{verbatim}
+%produces:
+%\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside}.
+%Note that the closed range includes end points:
+%\begin{verbatim}
+%\DTLifnumclosedbetween{5}{5}{7}{inside}{outside}
+%\end{verbatim}
+%produces:
+%\DTLifnumclosedbetween{5}{5}{7}{inside}{outside}.
+%
+%\DescribeMacro{\DTLifstringclosedbetween}
+%\begin{definition}
+%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%\DescribeMacro{\DTLifstringclosedbetween*}
+%\begin{definition}
+%\cs{DTLifstringclosedbetween*}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%This determines if \meta{string} is between \meta{min} and
+%\meta{max} in the alphabetical sense, or is equal to either
+%\meta{min} or \meta{max}. The starred version ignores the case,
+%the unstarred version is case sensitive.
+%
+%\DescribeMacro{\DTLifclosedbetween}
+%\begin{definition}
+%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%\DescribeMacro{\DTLifclosedbetween*}
+%\begin{definition}
+%\cs{DTLifclosedbetween*}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{arg}, \meta{min} and \meta{max} are numerical, then this is
+%equivalent to \cs{DTLifnumclosedbetween}, otherwise it is equivalent to
+%\cs{DTLifstringclosedbetween} (when using \cs{DTLifclosedbetween})
+%or
+%\cs{DTLifstringclosedbetween*} (when using \cs{DTLifclosedbetween*}).
+%
+%\DescribeMacro{\DTLifnumopenbetween}
+%\begin{definition}
+%\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{min} $<$ \meta{num} $<$ \meta{max} then do \meta{true part},
+%otherwise do \meta{false part}. Note that \meta{num}, \meta{min} and
+%\meta{max} must be numerical (either integers, real numbers or
+%currency.) Again, the currency symbol is ignored when determining
+%equality. For example:
+%\begin{verbatim}
+%\DTLifnumopenbetween{5.4}{5}{7}{inside}{outside}
+%\end{verbatim}
+%produces:
+%\DTLifnumopenbetween{5.4}{5}{7}{inside}{outside}.
+%Note that end points are not included. For example:
+%\begin{verbatim}
+%\DTLifnumopenbetween{5}{5}{7}{inside}{outside}
+%\end{verbatim}
+%produces:
+%\DTLifnumopenbetween{5}{5}{7}{inside}{outside}.
+%
+%\DescribeMacro{\DTLifstringopenbetween}
+%\begin{definition}
+%\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%\DescribeMacro{\DTLifstringopenbetween*}
+%\begin{definition}
+%\cs{DTLifstringopenbetween*}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%This determines if \meta{string} is between \meta{min} and
+%\meta{max} in the alphabetical sense.
+%The starred version ignores the case,
+%the unstarred version is case sensitive.
+%
+%\DescribeMacro{\DTLifopenbetween}
+%\begin{definition}
+%\cs{DTLifopenbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%\DescribeMacro{\DTLifopenbetween*}
+%\begin{definition}
+%\cs{DTLifopenbetween*}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{arg}, \meta{min} and \meta{max} are numerical, then this is
+%equivalent to \cs{DTLifnumopenbetween}, otherwise it is equivalent to
+%\cs{DTLifstringopenbetween} (when using \cs{DTLifopenbetween})
+%\cs{DTLifstringopenbetween*} (when using \cs{DTLifopenbetween*}).
+%
+%\DescribeMacro{\DTLifFPclosedbetween}
+%\begin{definition}
+%\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} then do \meta{true part},
+%otherwise do \meta{false part} where \meta{num}, \meta{min}
+%and \meta{max} are all in standard fixed point notation (i.e.\
+%no number group separator, no currency symbols and a full stop as
+%a decimal point.)
+%
+%\DescribeMacro{\DTLifFPopenbetween}
+%\begin{definition}
+%\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{min} $<$ \meta{num} $<$ \meta{max} then do \meta{true part},
+%otherwise do \meta{false part} where \meta{num}, \meta{min}
+%and \meta{max} are all in standard fixed point notation (i.e.\
+%no number group separator, no currency symbols and a full stop as
+%a decimal point.)
+%
+%\DescribeMacro{\DTLifAllUpperCase}
+%\begin{definition}
+%\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part}
+%\end{definition}
+%Tests if \meta{string} is all upper case. For example:
+%\begin{verbatim}
+%\DTLifAllUpperCase{WORD}{all upper}{not all upper}
+%\end{verbatim}
+%produces:
+%\DTLifAllUpperCase{WORD}{all upper}{not all upper},
+%whereas
+%\begin{verbatim}
+%\DTLifAllUpperCase{Word}{all upper}{not all upper}
+%\end{verbatim}
+%produces:
+%\DTLifAllUpperCase{Word}{all upper}{not all upper}.
+%Note also that:
+%\begin{verbatim}
+%\DTLifAllUpperCase{\MakeUppercase{word}}{all upper}{not all upper}
+%\end{verbatim}
+%also produces:
+%\DTLifAllUpperCase{\MakeUppercase{word}}{all upper}{not all upper}.
+%\cs{MakeTextUppercase} (defined in David Carlisle's \sty{textcase}
+%package) and \cs{uppercase} are also detected, otherwise, if
+%a command is encountered, the case of the command is considered.
+%For example:
+%\begin{verbatim}
+%\DTLifAllUpperCase{MAN{\OE}UVRE}{all upper}{not all upper}
+%\end{verbatim}
+%produces:
+%\DTLifAllUpperCase{MAN{\OE}UVRE}{all upper}{not all upper}.
+%
+%\DescribeMacro{\DTLifAllLowerCase}
+%\begin{definition}
+%\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part}
+%\end{definition}
+%Tests if \meta{string} is all lower case. For example:
+%\begin{verbatim}
+%\DTLifAllLowerCase{word}{all lower}{not all lower}
+%\end{verbatim}
+%produces:
+%\DTLifAllLowerCase{word}{all lower}{not all lower},
+%whereas
+%\begin{verbatim}
+%\DTLifAllLowerCase{Word}{all lower}{not all lower}
+%\end{verbatim}
+%produces:
+%\DTLifAllLowerCase{Word}{all lower}{not all lower}.
+%Note also that:
+%\begin{verbatim}
+%\DTLifAllLowerCase{\MakeLowercase{WORD}}{all lower}{not all lower}
+%\end{verbatim}
+%also produces:
+%\DTLifAllLowerCase{\MakeLowercase{WORD}}{all lower}{not all lower}.
+%\cs{MakeTextLowercase} (defined in David Carlisle's \sty{textcase}
+%package) and \cs{lowercase} are also detected, otherwise, if
+%a command is encountered, the case of the command is considered.
+%For example:
+%\begin{verbatim}
+%\DTLifAllLowerCase{man{\oe}uvre}{all lower}{not all lower}
+%\end{verbatim}
+%produces:
+%\DTLifAllLowerCase{man{\oe}uvre}{all lower}{not all lower}.
+%
+%\DescribeMacro{\DTLifSubString}
+%\begin{definition}
+%\cs{DTLifSubString}\marg{string}\marg{substring}\marg{true
+%part}\marg{false part}
+%\end{definition}
+%This tests if \meta{substring} is a sub-string of \meta{string}.
+%This command performs a case sensitive match. For example:
+%\begin{verbatim}
+%\DTLifSubString{An apple}{app}{is substring}{isn't substring}
+%\end{verbatim}
+%produces:
+%\DTLifSubString{An apple}{app}{is substring}{isn't substring}.
+%Note that spaces are considered to be equivalent to \cs{space}
+%or "~", so
+%\begin{verbatim}
+%\DTLifSubString{An apple}{n~a}{is substring}{isn't substring}
+%\end{verbatim}
+%produces:
+%\DTLifSubString{An apple}{n~a}{is substring}{isn't substring},
+%but other commands are skipped, so
+%\begin{verbatim}
+%\DTLifSubString{An \uppercase{a}pple}{app}{is substring}{isn't
+%substring}
+%\end{verbatim}
+%produces:
+%\DTLifSubString{An \uppercase{a}pple}{app}{is substring}{isn't
+%substring}, since the \cs{uppercase} command is ignored. Note also
+%that grouping is ignored, so:
+%\begin{verbatim}
+%\DTLifSubString{An {ap}ple}{app}{is substring}{isn't substring}
+%\end{verbatim}
+%produces:
+%\DTLifSubString{An {ap}ple}{app}{is substring}{isn't substring}.
+%
+%\cs{DTLifSubString} is case sensitive, so:
+%\begin{verbatim}
+%\DTLifSubString{An Apple}{app}{is substring}{isn't substring}
+%\end{verbatim}
+%produces:
+%\DTLifSubString{An Apple}{app}{is substring}{isn't substring}.
+%
+%\DescribeMacro{\DTLifStartsWith}
+%\begin{definition}
+%\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true
+%part}\marg{false part}
+%\end{definition}
+%This is like \cs{DTLifSubString}, except that \meta{substring} must
+%occur at the start of \meta{string}. This command performs a case
+%sensitive match. For example,
+%\begin{verbatim}
+%\DTLifStartsWith{An apple}{app}{prefix}{not a prefix}
+%\end{verbatim}
+%produces:
+%\DTLifStartsWith{An apple}{app}{prefix}{not a prefix}. All the
+%above remarks for \cs{DTLifSubString} also applies to
+%\cs{DTLifStartsWith}. For example:
+%\begin{verbatim}
+%\DTLifStartsWith{\uppercase{a}n apple}{an~}{prefix}{not a prefix}
+%\end{verbatim}
+%produces:
+%\DTLifStartsWith{\uppercase{a}n apple}{an~}{prefix}{not a prefix},
+%since \cs{uppercase} is ignored, and "~" is considered to be the
+%same as a space, whereas
+%\begin{verbatim}
+%\DTLifStartsWith{An apple}{an~}{prefix}{not a prefix}
+%\end{verbatim}
+%produces:
+%\DTLifStartsWith{An apple}{an~}{prefix}{not a prefix}.
+%
+%\subsection{\texorpdfstring{\sty{ifthen}}{ifthen} conditionals}
+%\label{sec:ifthen}
+%
+%The commands described in the previous section can not be
+%used as the conditional part of the \cs{ifthenelse} or
+%\cs{whiledo} commands provided by the \sty{ifthen} package.
+%This section describes analogous commands which may only be
+%used in the conditional argument of \cs{ifthenelse} and
+%\cs{whiledo}.
+%
+%\DescribeMacro{\DTLisstring}
+%\begin{definition}
+%\cs{DTLisstring}\marg{text}
+%\end{definition}
+%Tests if \meta{text} is a string. For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLisstring{some text}}{string}{not a string}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLisstring{some text}}{string}{not a string}.
+%
+%\DescribeMacro{\DTLisnumerical}
+%\begin{definition}
+%\cs{DTLisnumerical}\marg{text}
+%\end{definition}
+%Tests if \meta{text} is numerical (i.e.\ not a string.) For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLisnumerical{\$10.95}}{numerical}{not numerical}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLisnumerical{\$10.95}}{numerical}{not numerical}.
+%
+%Note however that \cs{DTLisnumerical} requires more care than
+%\cs{DTLifnumerical} when used with some of the other currency
+%symbols. Consider:
+%\begin{verbatim}
+%\DTLifnumerical{\pounds10.95}{numerical}{not numerical}
+%\end{verbatim}
+%This produces:
+%\DTLifnumerical{\pounds10.95}{numerical}{not numerical}.
+%However
+%\begin{verbatim}
+%\ifthenelse{\DTLisnumerical{\pounds10.95}}{numerical}{not numerical}
+%\end{verbatim}
+%produces
+%\ifthenelse{\DTLisnumerical{\pounds10.95}}{numerical}{not numerical}.
+%This is due to the expansion that occurs within \cs{ifthenelse}.
+%This can be prevented using \cs{noexpand}, for example:
+%\begin{verbatim}
+%\ifthenelse{\DTLisnumerical{\noexpand\pounds10.95}}{numerical}{not numerical}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLisnumerical{\noexpand\pounds10.95}}{numerical}{not numerical}.
+%
+%Likewise:
+%\begin{verbatim}
+%\def\cost{\pounds10.95}%
+%\ifthenelse{\DTLisnumerical{\noexpand\cost}}{numerical}{not numerical}
+%\end{verbatim}
+%produces
+%\def\cost{\pounds10.95}\relax
+%\ifthenelse{\DTLisnumerical{\noexpand\cost}}{numerical}{not numerical}.
+%
+%\DescribeMacro{\DTLiscurrency}
+%\begin{definition}
+%\cs{DTLiscurrency}\marg{text}
+%\end{definition}
+%Tests if \meta{text} is currency. For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLiscurrency{\$10.95}}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLiscurrency{\$10.95}}{currency}{not currency}.
+%
+%The same warning given above for \cs{DTLisnumerical} also applies
+%here.
+%
+%\DescribeMacro{\DTLiscurrencyunit}
+%\begin{definition}
+%\cs{DTLiscurrencyunit}\marg{text}\marg{symbol}
+%\end{definition}
+%Tests if \meta{text} is currency, and uses \meta{symbol} as the unit
+%of currency.
+%For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars}
+%Another example:
+%\begin{verbatim}
+%\def\cost{\euro10.50}%
+%\ifthenelse{\DTLiscurrencyunit{\noexpand\cost}{\noexpand\euro}}%
+%{euros}{not euros}
+%\end{verbatim}
+%produces:
+%\def\cost{\euro10.50}\relax
+%\ifthenelse{\DTLiscurrencyunit{\noexpand\cost}{\noexpand\euro}}%
+%{euros}{not euros}. Again note the use of \cs{noexpand}.
+%
+%\DescribeMacro{\DTLisreal}
+%\begin{definition}
+%\cs{DTLisreal}\marg{text}
+%\end{definition}
+%Tests if \meta{text} is a fixed point number (again, an integer is
+%not considered to be a fixed point number.) For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLisreal{1.5}}{real}{not real}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLisreal{1.5}}{real}{not real}.
+%
+%\DescribeMacro{\DTLisint}
+%\begin{definition}
+%\cs{DTLisint}\marg{text}
+%\end{definition}
+%Tests if \meta{text} is an integer. For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLisint{153}}{integer}{not an integer}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLisint{153}}{integer}{not an integer}.
+%
+%\DescribeMacro{\DTLislt}
+%\begin{definition}
+%\cs{DTLislt}\marg{arg1}\marg{arg2}
+%\end{definition}
+%This checks if \meta{arg1} is less than \meta{arg2}. As with
+%\cs{DTLiflt}, if \meta{arg1} and \meta{arg2} are numerical,
+%a numerical comparison is used, otherwise a case sensitive
+%alphabetical comparison is used. (Note that there is no starred
+%version of this command, but you can instead use \cs{DTLisilt}
+%to ignore the case.)
+%
+%\DescribeMacro{\DTLisilt}
+%\begin{definition}
+%\cs{DTLisilt}\marg{arg1}\marg{arg2}
+%\end{definition}
+%This checks if \meta{arg1} is less than \meta{arg2}. As with
+%\cs{DTLiflt*}, if \meta{arg1} and \meta{arg2} are numerical,
+%a numerical comparison is used, otherwise a case insensitive
+%alphabetical comparison is used.
+%
+%\DescribeMacro{\DTLisgt}
+%\begin{definition}
+%\cs{DTLisgt}\marg{arg1}\marg{arg2}
+%\end{definition}
+%This checks if \meta{arg1} is greater than \meta{arg2}. As with
+%\cs{DTLifgt}, if \meta{arg1} and \meta{arg2} are numerical,
+%a numerical comparison is used, otherwise a case sensitive
+%alphabetical comparison is used. (Note that there is no starred
+%version of this command, instead use \cs{DTLisigt} to
+%ignore the case.)
+%
+%\DescribeMacro{\DTLisigt}
+%\begin{definition}
+%\cs{DTLisigt}\marg{arg1}\marg{arg2}
+%\end{definition}
+%This checks if \meta{arg1} is greater than \meta{arg2}. As with
+%\cs{DTLifgt*}, if \meta{arg1} and \meta{arg2} are numerical,
+%a numerical comparison is used, otherwise a case insensitive
+%alphabetical comparison is used.
+%
+%\DescribeMacro{\DTLiseq}
+%\begin{definition}
+%\cs{DTLiseq}\marg{arg1}\marg{arg2}
+%\end{definition}
+%This checks if \meta{arg1} is equal to \meta{arg2}. As with
+%\cs{DTLifeq}, if \meta{arg1} and \meta{arg2} are numerical,
+%a numerical comparison is used, otherwise a case sensitive
+%alphabetical comparison is used. (Note that there is no starred
+%version of this command, instead use \cs{DTLisieq}.)
+%
+%\DescribeMacro{\DTLisieq}
+%\begin{definition}
+%\cs{DTLisieq}\marg{arg1}\marg{arg2}
+%\end{definition}
+%This checks if \meta{arg1} is equal to \meta{arg2}. As with
+%\cs{DTLifeq*}, if \meta{arg1} and \meta{arg2} are numerical,
+%a numerical comparison is used, otherwise a case insensitive
+%alphabetical comparison is used.
+%
+%\DescribeMacro{\DTLisclosedbetween}
+%\begin{definition}
+%\cs{DTLisclosedbetween}\marg{arg}\marg{min}\marg{max}
+%\end{definition}
+%This checks if \meta{arg} lies between \meta{min} and
+%\meta{max} (end points included.) As with
+%\cs{DTLifclosedbetween}, if the arguments are numerical,
+%a numerical comparison is used, otherwise a case sensitive
+%alphabetical comparison is used. (Note that there is no starred
+%version of this command, instead use \cs{DTLisiclosedbetween}.)
+%
+%\DescribeMacro{\DTLisiclosedbetween}
+%\begin{definition}
+%\cs{DTLisiclosedbetween}\marg{arg}\marg{min}\marg{max}
+%\end{definition}
+%This checks if \meta{arg} lies between \meta{min} and
+%\meta{max} (end points included.) As with
+%\cs{DTLifclosedbetween*}, if the arguments are numerical,
+%a numerical comparison is used, otherwise a case insensitive
+%alphabetical comparison is used.
+%
+%\DescribeMacro{\DTLisopenbetween}
+%\begin{definition}
+%\cs{DTLisopenbetween}\marg{arg}\marg{min}\marg{max}
+%\end{definition}
+%This checks if \meta{arg} lies between \meta{min} and
+%\meta{max} (end points excluded.) As with
+%\cs{DTLifopenbetween}, if the arguments are numerical,
+%a numerical comparison is used, otherwise a case sensitive
+%alphabetical comparison is used. (Note that there is no starred
+%version of this command, instead use \cs{DTLisiopenbetween}.)
+%
+%\DescribeMacro{\DTLisiopenbetween}
+%\begin{definition}
+%\cs{DTLisiopenbetween}\marg{arg}\marg{min}\marg{max}
+%\end{definition}
+%This checks if \meta{arg} lies between \meta{min} and
+%\meta{max} (end points excluded.) As with
+%\cs{DTLifopenbetween*}, if the arguments are numerical,
+%a numerical comparison is used, otherwise a case insensitive
+%alphabetical comparison is used.
+%
+%\DescribeMacro{\DTLisFPlt}
+%\begin{definition}
+%\cs{DTLisFPlt}\marg{num1}\marg{num2}
+%\end{definition}
+%This checks if \meta{num1} is less than \meta{num2}, where both
+%numbers are in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPlteq}
+%\begin{definition}
+%\cs{DTLisFPlteq}\marg{num1}\marg{num2}
+%\end{definition}
+%This checks if \meta{num1} is less than or equal to \meta{num2}, where both
+%numbers are in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPgt}
+%\begin{definition}
+%\cs{DTLisFPgt}\marg{num1}\marg{num2}
+%\end{definition}
+%This checks if \meta{num1} is greater than \meta{num2}, where both
+%numbers are in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPgteq}
+%\begin{definition}
+%\cs{DTLisFPgteq}\marg{num1}\marg{num2}
+%\end{definition}
+%This checks if \meta{num1} is greater than or equal to \meta{num2}, where both
+%numbers are in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPeq}
+%\begin{definition}
+%\cs{DTLisFPeq}\marg{num1}\marg{num2}
+%\end{definition}
+%This checks if \meta{num1} is equal to \meta{num2}, where both
+%numbers are in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPclosedbetween}
+%\begin{definition}
+%\cs{DTLisFPclosedbetween}\marg{num}\marg{min}\marg{max}
+%\end{definition}
+%This checks if \meta{num} lies between \meta{min} and
+%\meta{max} (end points included.) All arguments must be
+%numbers in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPopenbetween}
+%\begin{definition}
+%\cs{DTLisFPopenbetween}\marg{num}\marg{min}\marg{max}
+%\end{definition}
+%This checks if \meta{num} lies between \meta{min} and
+%\meta{max} (end points excluded.) All arguments must be
+%numbers in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisSubString}
+%\begin{definition}
+%\cs{DTLisSubString}\marg{string}\marg{substring}
+%\end{definition}
+%This checks if \meta{substring} is contained in \meta{string}.
+%The remarks about \cs{DTLifSubString} also apply to
+%\cs{DTLisSubString}. This command performs a case sensitive
+%match.
+%
+%\DescribeMacro{\DTLisPrefix}
+%\begin{definition}
+%\cs{DTLisPrefix}\marg{string}\marg{prefix}
+%\end{definition}
+%This checks if \meta{string} starts with \meta{prefix}.
+%The remarks about \cs{DTLifStartsWith} also apply to
+%\cs{DTLisPrefix}. This command performs a case sensitive
+%match.
+%
+%\section{Fixed Point Arithmetic}
+%\label{sec:fp}
+%
+%The \sty{datatool} package uses the \sty{fp} package to perform
+%fixed point arithmetic, however all numbers must be converted
+%from the locale dependent format into the format required by the
+%\sty{fp} package. A numerical value (i.e.\ an integer, a real
+%or currency) can be converted into a plain decimal number using
+%\DescribeMacro{\DTLconverttodecimal}
+%\begin{definition}
+%\cs{DTLconverttodecimal}\marg{num}\marg{cmd}
+%\end{definition}
+%The decimal number will be stored in \meta{cmd} which must be
+%a control sequence. For example:
+%\begin{verbatim}
+%\DTLconverttodecimal{1,563.54}{\mynum}
+%\end{verbatim}
+%\DTLconverttodecimal{1,563.54}{\mynum}\relax
+%will define \cs{mynum} to be \texttt{\mynum}. The command
+%can then be used in any of the arithmetic macros provided by the
+%\sty{fp} package. There are two commands provided to perform
+%the reverse:
+%\DescribeMacro{\DTLdecimaltolocale}
+%\begin{definition}
+%\cs{DTLdecimaltolocale}\marg{number}\marg{cmd}
+%\end{definition}
+%This converts a plain decimal number \meta{number} (that uses a full
+%stop as the decimal character and has no number group characters)
+%into a locale dependent format. The resulting number is stored
+%in \meta{cmd}, which must be a control sequence. For example:
+%\begin{verbatim}
+%\DTLdecimaltolocale{6795.3}{\mynum}
+%\end{verbatim}
+%\DTLdecimaltolocale{6795.3}{\mynum}
+%will define \cs{mynum} to be \texttt{\mynum}.
+%
+%\DescribeMacro{\DTLdecimaltocurrency}
+%\begin{definition}
+%\cs{DTLdecimaltocurrency}\marg{number}\marg{cmd}
+%\end{definition}
+%This will convert a plain decimal number \meta{number} into a
+%locale dependent currency format. For example:
+%\begin{verbatim}
+%\DTLdecimaltocurrency{267.5}{\price}\price
+%\end{verbatim}
+%will produce:
+%\DTLdecimaltocurrency{267.5}{\price}\price.
+%
+%The currency symbol used by \cs{DTLdecimaltocurrency} is
+%initially "\$", but will use the currency last encountered.
+%So, for example
+%\begin{verbatim}
+%\DTLifcurrency{\texteuro45.00}{}{}%
+%\DTLdecimaltocurrency{267.5}{\price}\price
+%\end{verbatim}
+%will produce:
+%\DTLifcurrency{\texteuro45.00}{}{}\relax
+%\DTLdecimaltocurrency{267.5}{\price}\price. This is because
+%the last currency symbol to be encountered was \cs{texteuro}.
+%You can reset the currency symbol using the command:
+%\DescribeMacro{\DTLsetdefaultcurrency}
+%\begin{definition}
+%\cs{DTLsetdefaultcurrency}\marg{symbol}
+%\end{definition}
+%For example:
+%\begin{verbatim}
+%\DTLsetdefaultcurrency{\textyen}%
+%\DTLdecimaltocurrency{267.5}{\price}\price
+%\end{verbatim}
+%will produce:
+%\DTLsetdefaultcurrency{\textyen}\relax
+%\DTLdecimaltocurrency{267.5}{\price}\price
+%
+%The \sty{datatool} package provides convenience commands which
+%use \cs{DTLconverttodecimal}, and then use the basic macros provided
+%by the \sty{fp} package. The resulting value is then converted
+%back into the locale format using
+%\cs{DTLdecimaltolocale} or \cs{DTLdecimaltocurrency}.
+%
+%\DescribeMacro{\DTLadd}
+%\begin{definition}
+%\cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgadd}
+%\begin{definition}
+%\cs{DTLgadd}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to \meta{num1}+\meta{num2}.
+%\cs{DLTadd} sets \meta{cmd} locally, while \cs{DTLgadd} sets
+%\meta{cmd} globally.
+%
+%For example:
+%\begin{verbatim}
+%\DTLadd{\result}{3,562.65}{412.2}\result
+%\end{verbatim}
+%will produce:
+%\DTLadd{\result}{3,562.65}{412.2}\result. Since
+%\cs{DTLconverttodecimal} can also convert currency, you can
+%also add prices. For example:
+%\begin{verbatim}
+%\DTLadd{\result}{\pounds3,562.65}{\pounds452.2}\result
+%\end{verbatim}
+%produces:
+%\DTLadd{\result}{\pounds3,562.65}{\pounds452.2}\result.
+%
+%Note that \sty{datatool} isn't aware of exchange rates! If you
+%use different currency symbols, the last symbol will be used.
+%For example
+%\begin{verbatim}
+%\DTLadd{\result}{\pounds3,562.65}{\euro452.2}\result
+%\end{verbatim}
+%produces:
+%\DTLadd{\result}{\pounds3,562.65}{\euro452.2}\result.
+%
+%Likewise, if one value is a number and the other is a currency,
+%the type of the last value, \meta{num2}, will be used for the
+%result. For example:
+%\begin{verbatim}
+%\DTLadd{\result}{3,562.65}{\$452.2}\result
+%\end{verbatim}
+%produces:
+%\DTLadd{\result}{3,562.65}{\$452.2}\result.
+%
+%\DescribeMacro{\DTLaddall}
+%\begin{definition}
+%\cs{DTLaddall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgaddall}
+%\begin{definition}
+%\cs{DTLgaddall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the sum of all
+%the numbers in \meta{number list}.
+%\cs{DLTaddall} sets \meta{cmd} locally, while \cs{DTLgaddall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLaddall{\total}{25.1,45.2,35.6}\total
+%\end{verbatim}
+%produces:
+%\DTLaddall{\total}{25.1,45.2,35.6}\total.
+%Note that if any of the numbers in \meta{number list} contain
+%a comma, you must group the number. Example:
+%\begin{verbatim}
+%\DTLaddall{\total}{{1,525},{2,340},500}\total
+%\end{verbatim}
+%produces:
+%\DTLaddall{\total}{{1,525},{2,340},500}\total.
+%
+%\DescribeMacro{\DTLsub}
+%\begin{definition}
+%\cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgsub}
+%\begin{definition}
+%\cs{DTLgsub}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to
+%\meta{num1}$-$\meta{num2}.
+%\cs{DLTsub} sets \meta{cmd} locally, while \cs{DTLgsub} sets
+%\meta{cmd} globally.
+%
+%For example:
+%\begin{verbatim}
+%\DTLsub{\result}{3,562.65}{412.2}\result
+%\end{verbatim}
+%will produce:
+%\DTLsub{\result}{3,562.65}{412.2}\result. As with \cs{DTLadd},
+%\meta{num1} and \meta{num2} may be currency.
+%
+%\DescribeMacro{\DTLmul}
+%\begin{definition}
+%\cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgmul}
+%\begin{definition}
+%\cs{DTLgmul}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to
+%\meta{num1}$\times$\meta{num2}.
+%\cs{DLTmul} sets \meta{cmd} locally, while \cs{DTLgmul} sets
+%\meta{cmd} globally.
+%
+%For example:
+%\begin{verbatim}
+%\DTLmul{\result}{568.95}{2}\result
+%\end{verbatim}
+%will produce:
+%\DTLmul{\result}{568.95}{2}\result. Again, \meta{num1} or
+%\meta{num2} may be currency, but unlike \cs{DTLadd} and \cs{DTLsub},
+%currency overrides integer/real. For example:
+%\begin{verbatim}
+%\DTLmul{\result}{\pounds568.95}{2}\result
+%\end{verbatim}
+%will produce:
+%\DTLmul{\result}{\pounds568.95}{2}\result. Likewise,
+%\begin{verbatim}
+%\DTLmul{\result}{2}{\pounds568.95}\result
+%\end{verbatim}
+%will produce:
+%\DTLmul{\result}{2}{\pounds568.95}\result. Although it doesn't make
+%sense to multiply two currencies, \sty{datatool} will allow
+%\begin{verbatim}
+%\DTLmul{\result}{\$2}{\pounds568.95}\result
+%\end{verbatim}
+%which will produce:
+%\DTLmul{\result}{\$2}{\pounds568.95}\result.
+%
+%\DescribeMacro{\DTLdiv}
+%\begin{definition}
+%\cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgdiv}
+%\begin{definition}
+%\cs{DTLgdiv}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to
+%\meta{num1}$\div$\meta{num2}.
+%\cs{DLTdiv} sets \meta{cmd} locally, while \cs{DTLgdiv} sets
+%\meta{cmd} globally.
+%
+%For example:
+%\begin{verbatim}
+%\DTLdiv{\result}{501}{2}\result
+%\end{verbatim}
+%will produce:
+%\DTLdiv{\result}{501}{2}\result. Again, \meta{num1} or \meta{num2}
+%may be currency, but the resulting type will be not be a currency
+%if both \meta{num1} and \meta{num2} use the same currency symbol.
+%For example:
+%\begin{verbatim}
+%\DTLdiv{\result}{\$501}{\$2}\result
+%\end{verbatim}
+%will produce:
+%\DTLdiv{\result}{\$501}{\$2}\result. Whereas
+%\begin{verbatim}
+%\DTLdiv{\result}{\$501}{2}\result
+%\end{verbatim}
+%will produce:
+%\DTLdiv{\result}{\$501}{2}\result.
+%
+%\DescribeMacro{\DTLabs}
+%\begin{definition}
+%\cs{DTLabs}\marg{cmd}\marg{num}
+%\end{definition}
+%\DescribeMacro{\DTLgabs}
+%\begin{definition}
+%\cs{DTLgabs}\marg{cmd}\marg{num}
+%\end{definition}
+%This sets \meta{cmd} to the absolute value of \meta{num}.
+%\cs{DLTabs} sets \meta{cmd} locally, while \cs{DTLgabs} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLabs{\result}{-\pounds2.50}\result
+%\end{verbatim}
+%produces:
+%\DTLabs{\result}{-\pounds2.50}\result.
+%
+%\DescribeMacro{\DTLneg}
+%\begin{definition}
+%\cs{DTLneg}\marg{cmd}\marg{num}
+%\end{definition}
+%\DescribeMacro{\DTLgneg}
+%\begin{definition}
+%\cs{DTLgneg}\marg{cmd}\marg{num}
+%\end{definition}
+%This sets \meta{cmd} to the negative of \meta{num}.
+%\cs{DLTneg} sets \meta{cmd} locally, while \cs{DTLgneg} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLneg{\result}{\pounds2.50}\result
+%\end{verbatim}
+%produces:
+%\DTLneg{\result}{\pounds2.50}\result.
+%
+%\DescribeMacro{\DTLsqrt}
+%\begin{definition}
+%\cs{DTLsqrt}\marg{cmd}\marg{num}
+%\end{definition}
+%\DescribeMacro{\DTLgsqrt}
+%\begin{definition}
+%\cs{DTLgsqrt}\marg{cmd}\marg{num}
+%\end{definition}
+%This sets \meta{cmd} to the sqrt root of \meta{num}.
+%\cs{DLTsqrt} sets \meta{cmd} locally, while \cs{DTLgsqrt} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLsqrt{\result}{2}\result
+%\end{verbatim}
+%produces:
+%\DTLsqrt{\result}{2}\result.
+%
+%\DescribeMacro{\DTLmin}
+%\begin{definition}
+%\cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgmin}
+%\begin{definition}
+%\cs{DTLgmin}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the minimum of
+%\meta{num1} and \meta{num2}.
+%\cs{DLTmin} sets \meta{cmd} locally, while \cs{DTLgmin} sets
+%\meta{cmd} globally. For example:
+%\begin{verbatim}
+%\DTLmin{\result}{256}{32}\result
+%\end{verbatim}
+%produces:
+%\DTLmin{\result}{256}{32}\result.
+%Again, \meta{num1} and \meta{num2} may
+%be currency. For example:
+%\begin{verbatim}
+%\DTLmin{\result}{256}{\pounds32}\result
+%\end{verbatim}
+%produces:
+%\DTLmin{\result}{256}{\pounds32}\result, whereas
+%\begin{verbatim}
+%\DTLmin{\result}{\pounds256}{32}\result
+%\end{verbatim}
+%produces:
+%\DTLmin{\result}{\pounds256}{32}\result. As mentioned above,
+%\sty{datatool} doesn't know about exchange rates, so be careful
+%about mixing currencies. For example:
+%\begin{verbatim}
+%\DTLmin{\result}{\pounds5}{\$6}\result
+%\end{verbatim}
+%produces:
+%\DTLmin{\result}{\pounds5}{\$6}\result, which may not necessarily
+%be true!
+%
+%\DescribeMacro{\DTLminall}
+%\begin{definition}
+%\cs{DTLminall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgminall}
+%\begin{definition}
+%\cs{DTLgminall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the minimum of all
+%the numbers in \meta{number list}.
+%\cs{DLTminall} sets \meta{cmd} locally, while \cs{DTLgminall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLminall{\theMin}{25.1,45.2,35.6}\theMin
+%\end{verbatim}
+%produces:
+%\DTLminall{\theMin}{25.1,45.2,35.6}\theMin.
+%Note that if any of the numbers in \meta{number list} contain
+%a comma, you must group the number. Example:
+%\begin{verbatim}
+%\DTLminall{\theMin}{{1,525},{2,340},500}\theMin
+%\end{verbatim}
+%produces:
+%\DTLminall{\theMin}{{1,525},{2,340},500}\theMin.
+%
+%\DescribeMacro{\DTLmax}
+%\begin{definition}
+%\cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgmax}
+%\begin{definition}
+%\cs{DTLgmax}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the maximum of
+%\meta{num1} and \meta{num2}.
+%\cs{DLTmax} sets \meta{cmd} locally, while \cs{DTLgmax} sets
+%\meta{cmd} globally. For example:
+%\begin{verbatim}
+%\DTLmax{\result}{256}{32}\result
+%\end{verbatim}
+%produces:
+%\DTLmax{\result}{256}{32}\result.
+%Again, \meta{num1} and \meta{num2} may
+%be currency, but the same warnings for \cs{DTLmin} apply.
+%
+%\DescribeMacro{\DTLmaxall}
+%\begin{definition}
+%\cs{DTLmaxall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgmaxall}
+%\begin{definition}
+%\cs{DTLgmaxall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the maximum of all
+%the numbers in \meta{number list}.
+%\cs{DLTmaxall} sets \meta{cmd} locally, while \cs{DTLgmaxall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLmaxall{\theMax}{25.1,45.2,35.6}\theMax
+%\end{verbatim}
+%produces:
+%\DTLmaxall{\theMax}{25.1,45.2,35.6}\theMax.
+%Note that if any of the numbers in \meta{number list} contain
+%a comma, you must group the number. Example:
+%\begin{verbatim}
+%\DTLmaxall{\theMax}{{1,525},{2,340},500}\theMax
+%\end{verbatim}
+%produces:
+%\DTLmaxall{\theMax}{{1,525},{2,340},500}\theMax.
+%
+%\DescribeMacro{\DTLmeanforall}
+%\begin{definition}
+%\cs{DTLmeanforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgmeanall}
+%\begin{definition}
+%\cs{DTLgmeanforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the arithmetic mean of all
+%the numbers in \meta{number list}.
+%\cs{DLTmeanforall} sets \meta{cmd} locally, while \cs{DTLgmeanforall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLmeanforall{\theMean}{25.1,45.2,35.6}\theMean
+%\end{verbatim}
+%produces:
+%\DTLmeanforall{\theMean}{25.1,45.2,35.6}\theMean.
+%Note that if any of the numbers in \meta{number list} contain
+%a comma, you must group the number. Example:
+%\begin{verbatim}
+%\DTLmeanforall{\theMean}{{1,525},{2,340},500}\theMean
+%\end{verbatim}
+%produces:
+%\DTLmeanforall{\theMean}{{1,525},{2,340},500}\theMean.
+%
+%\DescribeMacro{\DTLvarianceforall}
+%\begin{definition}
+%\cs{DTLvarianceforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgvarianceforall}
+%\begin{definition}
+%\cs{DTLgvarianceforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the variance of all
+%the numbers in \meta{number list}.
+%\cs{DLTvarianceforall} sets \meta{cmd} locally, while \cs{DTLgvarianceforall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLvarianceforall{\theVar}{25.1,45.2,35.6}\theVar
+%\end{verbatim}
+%produces:
+%\DTLvarianceforall{\theVar}{25.1,45.2,35.6}\theVar.
+%Again note that if any of the numbers in \meta{number list}
+%contain a comma, you must group the number.
+%
+%\DescribeMacro{\DTLsdforall}
+%\begin{definition}
+%\cs{DTLsdforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgsdforall}
+%\begin{definition}
+%\cs{DTLgsdforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the standard deviation of all
+%the numbers in \meta{number list}.
+%\cs{DLTsdforall} sets \meta{cmd} locally, while \cs{DTLgsdforall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLsdforall{\theSD}{25.1,45.2,35.6}\theSD
+%\end{verbatim}
+%produces:
+%\DTLsdforall{\theSD}{25.1,45.2,35.6}\theSD.
+%Note that if any of the numbers in \meta{number list} contain
+%a comma, you must group the number. Example:
+%\begin{verbatim}
+%\DTLsdforall{\theSD}{{1,525},{2,340},500}\theSD
+%\end{verbatim}
+%produces:
+%\DTLsdforall{\theSD}{{1,525},{2,340},500}\theSD.
+%
+%\DescribeMacro{\DTLround}
+%\begin{definition}
+%\cs{DTLround}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+%\DescribeMacro{\DTLground}
+%\begin{definition}
+%\cs{DTLground}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+%This sets \meta{cmd} to \meta{num} rounded to \meta{num digits}
+%after the decimal character.
+%\cs{DLTround} sets \meta{cmd} locally, while \cs{DTLground} sets
+%\meta{cmd} globally.
+%
+%\DescribeMacro{\DTLtrunc}
+%\begin{definition}
+%\cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+%\DescribeMacro{\DTLgtrunc}
+%\begin{definition}
+%\cs{DTLgtrunc}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+%This sets \meta{cmd} to \meta{num} truncated to \meta{num digits}
+%after the decimal character.
+%\cs{DLTtrunc} sets \meta{cmd} locally, while \cs{DTLgtrunc} sets
+%\meta{cmd} globally.
+%
+%\DescribeMacro{\DTLclip}
+%\begin{definition}
+%\cs{DTLclip}\marg{cmd}\marg{num}
+%\end{definition}
+%\DescribeMacro{\DTLgclip}
+%\begin{definition}
+%\cs{DTLgclip}\marg{cmd}\marg{num}
+%\end{definition}
+%This sets \meta{cmd} to \meta{num} with all unnecessary 0's
+%removed.
+%\cs{DLTclip} sets \meta{cmd} locally, while \cs{DTLgclip} sets
+%\meta{cmd} globally.
+%
+%\section{Strings}
+%\label{sec:strings}
+%
+%Strings are considered to be anything non-numerical. The
+%\sty{datatool} package loads the \sty{substr} package, so
+%you can use the commands defined in that package to determine
+%if one string is contained in another string. In addition,
+%the \sty{datatool} provides the following macros:
+%
+%\DescribeMacro{\DTLsubstitute}
+%\begin{definition}
+%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement}
+%\end{definition}
+%This replaces the first occurrence of \meta{original} in
+%\meta{cmd} with \meta{replacement}. Note that \meta{cmd} must
+%be the name of a command. For example:
+%\begin{verbatim}
+%\def\mystr{abcdce}\DTLsubstitute{\mystr}{c}{z}\mystr
+%\end{verbatim}
+%produces:
+%\def\mystr{abcdce}\DTLsubstitute{\mystr}{c}{z}\mystr.
+%
+%\DescribeMacro{\DTLsubstituteall}
+%\begin{definition}
+%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement}
+%\end{definition}
+%This replaces all occurrences of \meta{original} in
+%\meta{cmd} with \meta{replacement}, where again, \meta{cmd} must
+%be the name of a command. For example:
+%\begin{verbatim}
+%\def\mystr{abcdce}\DTLsubstituteall{\mystr}{c}{z}\mystr
+%\end{verbatim}
+%produces:
+%\def\mystr{abcdce}\DTLsubstituteall{\mystr}{c}{z}\mystr.
+%
+%\DescribeMacro{\DTLsplitstring}
+%\begin{definition}
+%\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before
+%cmd}\marg{after cmd}
+%\end{definition}
+%This splits \meta{string} at the first occurrence of \meta{split text}
+%and stores the before part in the command \meta{before cmd} and
+%the after part in the command \meta{after cmd}. For example:
+%\begin{verbatim}
+%\DTLsplitstring{abcdce}{c}{\beforepart}{\afterpart}%
+%Before part: ``\beforepart''. After part: ``\afterpart''
+%\end{verbatim}
+%produces:
+%\DTLsplitstring{abcdce}{c}{\beforepart}{\afterpart}\relax
+%Before part: ``\beforepart''. After part: ``\afterpart''.
+%Note that for \cs{DTLsplitstring}, \meta{string} is not
+%expanded, so
+%\begin{verbatim}
+%\def\mystr{abcdce}%
+%\DTLsplitstring{\mystr}{c}{\beforepart}{\afterpart}%
+%Before part: ``\beforepart''. After part: ``\afterpart''
+%\end{verbatim}
+%produces:
+%\def\mystr{abcdce}\relax
+%\DTLsplitstring{\mystr}{c}{\beforepart}{\afterpart}%
+%Before part: ``\beforepart''. After part: ``\afterpart''. If you
+%want the string expanded, you will need to use \cs{expandafter}:
+%\begin{verbatim}
+%\def\mystr{abcdce}%
+%\expandafter\DTLsplitstring\expandafter
+%{\mystr}{c}{\beforepart}{\afterpart}%
+%Before part: ``\beforepart''. After part: ``\afterpart''
+%\end{verbatim}
+%which produces:
+%\def\mystr{abcdce}\relax
+%\expandafter\DTLsplitstring\expandafter
+%{\mystr}{c}{\beforepart}{\afterpart}\relax
+%Before part: ``\beforepart''. After part: ``\afterpart''.
+%
+%\DescribeMacro{\DTLinitials}
+%\begin{definition}
+%\cs{DTLinitials}\marg{string}
+%\end{definition}
+%This converts \meta{string} (typically a name) into initials.
+%For example:
+%\begin{verbatim}
+%\DTLinitials{Mary Ann}
+%\end{verbatim}
+%produces:
+%\DTLinitials{Mary Ann} (including the final full stop.) Note that
+%\begin{verbatim}
+%\DTLinitials{Mary-Ann}
+%\end{verbatim}
+%produces:
+%\DTLinitials{Mary-Ann} (including the final full stop.)
+%Be careful if the initial letter has an
+%accent. The accented letter needs to be placed in a group, if
+%you want the initial to also have an accent, otherwise the
+%accent command will be ignored. For example:
+%\begin{verbatim}
+%\DTLinitials{{\'E}lise Adams}
+%\end{verbatim}
+%produces:
+%\DTLinitials{{\'E}lise Adams}, whereas
+%\begin{verbatim}
+%\DTLinitials{\'Elise Adams}
+%\end{verbatim}
+%produces:
+%\DTLinitials{\'Elise Adams} In fact, any command which appears
+%at the start of the name that is not enclosed in a group will
+%be ignored. For example:
+%\begin{verbatim}
+%\DTLinitials{\MakeUppercase{m}ary ann}
+%\end{verbatim}
+%produces:
+%\DTLinitials{\MakeUppercase{m}ary ann}, whereas
+%\begin{verbatim}
+%\DTLinitials{{\MakeUppercase{m}}ary ann}
+%\end{verbatim}
+%produces:
+%\DTLinitials{{\MakeUppercase{m}}ary ann}, but note that
+%\begin{verbatim}
+%\DTLinitials{\MakeUppercase{mary ann}}
+%\end{verbatim}
+%produces:
+%\DTLinitials{\MakeUppercase{mary ann}}
+%
+%\DescribeMacro{\DTLstoreinitials}
+%\begin{definition}
+%\cs{DTLstoreinitials}\marg{string}\marg{cmd}
+%\end{definition}
+%This converts \meta{string} into initials and stores the
+%result in \meta{cmd} which must be a command name. The remarks
+%about \cs{DTLinitials} also relate to \cs{DTLstoreinitials}.
+%For example
+%\begin{verbatim}
+%\DTLstoreinitials{Marie-{\'E}lise del~Rosario}{\theInitials}\theInitials
+%\end{verbatim}
+%produces:
+%\DTLstoreinitials{Marie-{\'E}lise del~Rosario}{\theInitials}\theInitials
+%
+%Both the above commands rely on the following to format the
+%initials:
+%\DescribeMacro{\DTLafterinitials}
+%\begin{definition}
+%\cs{DTLafterinitials}
+%\end{definition}
+%This indicates what to do at the end of the initials. This
+%simply does a full stop by default.
+%
+%\DescribeMacro{\DTLbetweeninitials}
+%\begin{definition}
+%\cs{DTLbetweeninitials}
+%\end{definition}
+%This indicates what to do between initials. This does a
+%full stop by default.
+%
+%\DescribeMacro{\DTLinitialhyphen}
+%\begin{definition}
+%\cs{DTLinitialhyphen}
+%\end{definition}
+%This indicates what to do at a hyphen. This simply does a hyphen
+%by default, but can be redefined to do nothing to prevent the
+%hyphen appearing in the initials.
+%
+%\DescribeMacro{\DTLafterinitialbeforehyphen}
+%\begin{definition}
+%\cs{DTLafterinitialbeforehyphen}
+%\end{definition}
+%This indicates what to do between an initial and a hyphen.
+%This simply does a full stop by default.
+%
+%For example
+%\begin{verbatim}
+%\renewcommand*{\DTLafterinitialbeforehyphen}{}%
+%\DTLinitials{Marie-{\'E}lise del~Rosario}
+%\end{verbatim}
+%produces:
+%{\renewcommand*{\DTLafterinitialbeforehyphen}{}\relax
+%\DTLinitials{Marie-{\'E}lise del~Rosario}}
+%whereas
+%\begin{verbatim}
+%\renewcommand*{\DTLafterinitialbeforehyphen}{}%
+%\renewcommand*{\DTLafterinitials}{}%
+%\renewcommand*{\DTLbetweeninitials}{}%
+%\renewcommand*{\DTLinitialhyphen}{}%
+%\DTLinitials{Marie-{\'E}lise del~Rosario}
+%\end{verbatim}
+%produces:
+%{\renewcommand*{\DTLafterinitialbeforehyphen}{}\relax
+%\renewcommand*{\DTLafterinitials}{}\relax
+%\renewcommand*{\DTLbetweeninitials}{}\relax
+%\renewcommand*{\DTLinitialhyphen}{}\relax
+%\DTLinitials{Marie-{\'E}lise del~Rosario}}
+%
+%\section{Databases}
+%\label{sec:databases}
+%
+%The \sty{datatool} package provides a means of creating and
+%loading databases. Once a database has been created (or loaded),
+%it is possible to iterate through each row of data, to make it
+%easier to perform repetitive actions, such as mail merging.
+%
+%\subsection{Creating a New Database}
+%\label{sec:newdb}
+%
+%\DescribeMacro{\DTLnewdb}
+%\begin{definition}
+%\cs{DTLnewdb}\marg{db name}
+%\end{definition}
+%This command creates a new empty database called \meta{db name}. You
+%can test if a database is empty using:
+%\DescribeMacro{\DTLifdbempty}
+%\begin{definition}
+%\cs{DTLifdbempty}\marg{db name}\marg{true part}\marg{false part}
+%\end{definition}
+%If the database called \meta{db name} is empty, do \meta{true part},
+%otherwise do \meta{false part}.
+%
+%\DescribeMacro{\DTLrowcount}
+%\begin{definition}
+%\cs{DTLrowcount}\marg{db name}
+%\end{definition}
+%This command displays the number of rows in the database called
+%\meta{db name}.
+%
+%\DescribeMacro{\DTLnewrow}
+%\begin{definition}
+%\cs{DTLnewrow}\marg{db name}
+%\end{definition}
+%This command starts a new row in the database called \meta{db name}.
+%This new row becomes the current row when adding new entries.
+%
+%For example, the following creates an empty database called
+%\texttt{mydata}:
+%\begin{verbatim}
+%\DTLnewdb{mydata}
+%\end{verbatim}
+%\DTLnewdb{mydata}\relax
+%The following tests if the database is empty:
+%\begin{verbatim}
+%\DTLifdbempty{mydata}{empty}{not empty}!
+%\end{verbatim}
+%This produces:
+%\DTLifdbempty{mydata}{empty}{not empty}!
+%
+%The following adds an empty row to the database, this is the
+%first row of the database:
+%\begin{verbatim}
+%\DTLnewrow{mydata}
+%\end{verbatim}
+%\DTLnewrow{mydata}\relax
+%Note that even though the only row in the database is currently
+%empty, the database is no longer considered to be empty:
+%\begin{verbatim}
+%\DTLifdbempty{mydata}{empty}{not empty}!
+%\end{verbatim}
+%This now produces:
+%\DTLifdbempty{mydata}{empty}{not empty}! The row count is
+%given by
+%\begin{verbatim}
+%\DTLrowcount{mydata}
+%\end{verbatim}
+%which produces:
+%\DTLrowcount{mydata}.
+%
+%\DescribeMacro{\DTLnewdbentry}
+%\begin{definition}
+%\cs{DTLnewdbentry}\marg{db name}\marg{key}\marg{value}
+%\end{definition}
+%This creates a new entry with the identifier \meta{key} whose value
+%is \meta{value} and adds it to the last row of the database
+%called \meta{db name}. For example:
+%\begin{verbatim}
+%\DTLnewdbentry{mydata}{Surname}{Smith}
+%\DTLnewdbentry{mydata}{FirstName}{John}
+%\end{verbatim}
+%Adds an entry with identifier \texttt{Surname} and value
+%\texttt{Smith} to the last row of the database named
+%\texttt{mydata}, and then adds an entry with identifier
+%\texttt{FirstName} and value \texttt{John}.
+%
+%\importantpar Note that database entries can't contain paragraph
+%breaks as many of the macros used by \sty{datatool} are short
+%commands. If you do need a paragraph break in an entry, you can
+%instead use the command:
+%\DescribeMacro{\DTLpar}
+%\begin{definition}
+%\cs{DTLpar}
+%\end{definition}
+%
+%\DescribeMacro{\DTLaddentryforrow}
+%\begin{definition}
+%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value}
+%\end{definition}
+%This adds the entry with the key given by \meta{key} and value
+%given by \meta{value} to the first row in the database
+%\meta{db name} which satisfies the condition given by
+%\meta{condition}. The \meta{assign list} argument is the same
+%as for \cs{DTLforeach} (described in \autoref{sec:dbforeach})
+%and may be used to set the values which are to be tested in
+%\meta{condition} (where, again, \meta{condition} is the same
+%as for \cs{DTLforeach}).
+%
+%\subsection{Loading a Database from an External ASCII File}
+%\label{sec:loaddb}
+%
+%Instead of using the commands described in \autoref{sec:newdb}
+%to create a new database, you can load a database from an
+%external ASCII file using:
+%\DescribeMacro{\DTLloaddb}
+%\begin{definition}
+%\cs{DTLloaddb}\marg{db name}\marg{filename}
+%\end{definition}
+%This creates a new database called \meta{db name}, and fills
+%it with the entries given in the file \meta{filename}.
+%The filename must have a header row at the start of the file,
+%which provides the \meta{key} when creating a new database entry
+%using \ics{DTLnewdbentry}. By default, the entries in the database
+%must be separated by a comma, and optionally delimited by the
+%double quote character (\verb|"|). The separator can be changed
+%to a tab separator using the command:
+%\DescribeMacro{\DTLsettabseparator}
+%\begin{definition}
+%\cs{DTLsettabseparator}
+%\end{definition}
+%To set the separator to a character other than a tab, you need to use
+%\DescribeMacro{\DTLsetseparator}
+%\begin{definition}
+%\cs{DTLsetseparator}\marg{character}
+%\end{definition}
+%The delimiter can be changed using
+%\DescribeMacro{\DTLsetdelimiter}
+%\begin{definition}
+%\cs{DTLsetdelimiter}\marg{character}
+%\end{definition}
+%
+%For example, suppose you have a file called \texttt{mydata.csv}
+%which contains the following:
+%\begin{verbatim}
+%FirstName,Surname,Score
+%John,"Smith, Jr",68
+%Jane,Brown,75
+%Andy,Brown,42
+%Z\"oe,Adams,52
+%\end{verbatim}
+%then
+%\begin{verbatim}
+%\DTLloaddb{mydata}{mydata.csv}
+%\end{verbatim}
+%is equivalent to:
+%\begin{verbatim}
+%\DTLnewdb{mydata}
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{FirstName}{John}%
+%\DTLnewdbentry{mydata}{Surname}{Smith, Jr}%
+%\DTLnewdbentry{mydata}{Score}{68}%
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{FirstName}{Jane}%
+%\DTLnewdbentry{mydata}{Surname}{Brown}%
+%\DTLnewdbentry{mydata}{Score}{75}%
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{FirstName}{Andy}%
+%\DTLnewdbentry{mydata}{Surname}{Brown}%
+%\DTLnewdbentry{mydata}{Score}{42}%
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{FirstName}{Z\"oe}%
+%\DTLnewdbentry{mydata}{Score}{52}%
+%\DTLnewdbentry{mydata}{Surname}{Adams}%
+%\end{verbatim}
+%Note that the entry \texttt{Smith, Jr} had to be delimited in
+%\texttt{mydata.csv} using the double quote character since it
+%contained a comma which is used as the separator.
+%
+%The file used in the above example contained a \LaTeX\ command,
+%namely \verb|\"|. When using \ics{DTLloaddb} all the special
+%characters that appear in the command retain their \LaTeX\ meaning
+%when the file is loaded. It is likely however that the data file
+%may have been created by another application that is not \TeX-aware,
+%such as a spreadsheet application. For example, suppose you
+%have a file called, say, \texttt{products.csv} which looks
+%like:
+%\begin{verbatim}
+%Product,Cost
+%Fruit & Veg,$1.25
+%Stationary,$0.80
+%\end{verbatim}
+%This file contains two of \TeX's special characters, namely
+%"&" and \verb|$|. In this case, if you try to load the file
+%using \ics{DTLloaddb}, you will encounter errors. Instead you
+%can use:
+%\DescribeMacro{\DTLloadrawdb}
+%\begin{definition}
+%\cs{DTLloadrawdb}\marg{db name}\marg{filename}
+%\end{definition}
+%This is the same as \ics{DTLloaddb} except that it maps nine of
+%the ten special characters onto commands which produce that
+%symbol. The only character that retains its active state is the
+%backslash character, so you will still need to check the file
+%for backslash characters. The mappings used are listed in
+%\autoref{tab:rawmappings}. So using the file \texttt{products.csv},
+%as described above,
+%\begin{verbatim}
+%\DTLloadrawdb{mydata}{products.csv}
+%\end{verbatim}
+%is equivalent to:
+%\begin{verbatim}
+%\DTLnewdb{mydata}
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{Product}{Fruit \& Veg}%
+%\DTLnewdbentry{mydata}{Cost}{\$1.25}%
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{Product}{Stationary}%
+%\DTLnewdbentry{mydata}{Cost}{\$0.80}%
+%\end{verbatim}
+%
+%\begin{table}[htbp]
+%\caption[Special character mappings used by
+%\cs{DTLloadrawdb}]{Special character mappings used by
+%\cs{DTLloadrawdb} (note that the backslash retains its active state)}
+%\label{tab:rawmappings}
+%\begin{center}
+%\begin{tabular}{ll}
+%Character & Mapping\\
+%\verb|%| & \verb|\%|\\
+%\verb|$| & \verb|\$|\\
+%\verb|&| & \verb|\&|\\
+%\verb|#| & \verb|\#|\\
+%\verb|_| & \verb|\_|\\
+%\verb|{| & \verb|\{|\\
+%\verb|}| & \verb|\}|\\
+%\verb|~| & \cs{textasciitilde}\\
+%\verb|^| & \cs{textasciicircum}
+%\end{tabular}
+%\end{center}
+%\end{table}
+%
+%It may be that there are other characters that require mapping.
+%For example, the file \texttt{products.csv} may instead look like:\par
+%\vskip\baselineskip
+%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+%Product,Cost
+%Fruit \& Veg,\pounds1.25
+%Stationary,\pounds0.80
+%\end{ttfamily}
+%\vskip\baselineskip
+%The pound character is not an internationally standard keyboard
+%character, and does not generally achieve the desired effect when used
+%in a \LaTeX\ document. It will therefore be necessary to convert
+%this symbol to an appropriate control sequence. This can be done
+%using the command:
+%\DescribeMacro{\DTLrawmap}
+%\begin{definition}
+%\cs{DTLrawmap}\marg{string}\marg{replacement}
+%\end{definition}
+%For example:\par
+%\vskip\baselineskip
+%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+%\cs{DTLrawmap}\char`\{\pounds\char`\}\char`\{\cs{pounds}\char`\}
+%\end{ttfamily}
+%\vskip\baselineskip\noindent
+%will convert all occurrences\footnote{when it is loaded into the
+%\LaTeX\ database, it does not modify the data file!} of
+%\texttt{\pounds} with \cs{pounds}. Naturally, the mappings must be
+%set \emph{prior} to loading the data with \cs{DTLloadrawdb}.
+%
+%\importantpar Note that the warning in the previous section about no
+%paragraph breaks in an entry also applies to entries loaded from a
+%database. If you do need a paragraph break, use \ics{DTLpar} instead
+%of \cs{par}, but remember that each row of data in an external data
+%file must not have a line break.
+%
+%\subsection{Iterating Through a Database}
+%\label{sec:dbforeach}
+%
+%Once you have created a database, either loading it from an
+%external file, as described in \autoref{sec:loaddb}, or using the
+%commands described in \autoref{sec:newdb}, you can then iterate
+%through each row of the database and access elements in that row.
+%
+%\DescribeMacro{\DTLforeach}
+%\begin{definition}
+%\cs{DTLforeach}\oarg{condition}\marg{db name}\marg{assign list}\marg{text}
+%\end{definition}
+%\DescribeMacro{\DTLforeach*}
+%\begin{definition}
+%\cs{DTLforeach*}\oarg{condition}\marg{db name}\marg{assign list}\marg{text}
+%\end{definition}
+%This will iterate through each row of the database called
+%\meta{db name}, applying \meta{text} to each row of the database
+%where \meta{condition} is met. The argument \meta{assign list} is a
+%comma separated list of \meta{cmd}"="\meta{key} pairs. At the
+%start of each row, each command \meta{cmd} in \meta{assign list}
+%will be set to the value of the entry given by \meta{key}.
+%These commands may then be used in \meta{text}.
+%
+%\importantpar Note that this assignment is done globally to ensure
+%that \cs{DLTforeach} works correctly in a \env{tabular} environment.
+%Since you may want to use the same set of commands in a later
+%\cs{DTLforeach}, the commands are not checked to determine if they
+%already exist. It is therefore important that you check you are not
+%using an existing command whose value should not be changed.
+%
+%The optional argument \meta{condition} is a condition in the
+%form allowed by \cs{ifthenelse}. This includes the commands
+%provided by the \sty{ifthen} package, as well as the commands
+%described in \autoref{sec:ifthen}. The default value of
+%\meta{condition} is "\boolean{true}".
+%
+%The starred version \cs{DTLforeach*} is a read-only version.
+%If you want to modify the database using any of the commands
+%described in \autoref{sec:editdb}, you must use the unstarred
+%version. The starred version is slightly quicker, however the
+%difference will probably only be noticeable for very large
+%databases.
+%
+%\begin{example}{Student scores}{ex:scores}
+%Suppose you have a data file called \texttt{studentscores.csv} that
+%contains the following:
+%\begin{verbatim}
+%FirstName,Surname,StudentNo,Score
+%John,"Smith, Jr",102689,68
+%Jane,Brown,102647,75
+%Andy,Brown,103569,42
+%Z\"oe,Adams,105987,52
+%Roger,Brady,106872,58
+%Clare,Verdon,104356,45
+%\end{verbatim}
+%\DTLnewdb{scores}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{John}\relax
+%\DTLnewdbentry{scores}{Surname}{Smith, Jr}\relax
+%\DTLnewdbentry{scores}{StudentNo}{102689}\relax
+%\DTLnewdbentry{scores}{Score}{68}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{Jane}\relax
+%\DTLnewdbentry{scores}{Surname}{Brown}\relax
+%\DTLnewdbentry{scores}{StudentNo}{102647}\relax
+%\DTLnewdbentry{scores}{Score}{75}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{Andy}\relax
+%\DTLnewdbentry{scores}{Surname}{Brown}\relax
+%\DTLnewdbentry{scores}{StudentNo}{103569}\relax
+%\DTLnewdbentry{scores}{Score}{42}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{Z\"oe}\relax
+%\DTLnewdbentry{scores}{Score}{52}\relax
+%\DTLnewdbentry{scores}{StudentNo}{105987}\relax
+%\DTLnewdbentry{scores}{Surname}{Adams}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{Roger}\relax
+%\DTLnewdbentry{scores}{Score}{58}\relax
+%\DTLnewdbentry{scores}{StudentNo}{106872}\relax
+%\DTLnewdbentry{scores}{Surname}{Brady}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{Clare}\relax
+%\DTLnewdbentry{scores}{Score}{45}\relax
+%\DTLnewdbentry{scores}{StudentNo}{104356}\relax
+%\DTLnewdbentry{scores}{Surname}{Verdon}\relax
+%and you load the data into a database called "scores" using:
+%\begin{verbatim}
+%\DTLloaddb{scores}{studentscores.csv}
+%\end{verbatim}
+%you can then display the database in a table as follows:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student scores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:scores}. (Note that since I didn't
+%need the student registration number, I didn't bother to
+%assign a command to the key "StudentNo".)
+%
+%\begin{table}[htbp]
+%\caption[Student scores (displaying a database in a
+%table)]{Student scores}\label{tab:scores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
+%The macro \ics{DTLforeach} may be nested up to three times. Each
+%level uses the corresponding counters:
+%\counterfmt{DTLrowi},
+%\counterfmt{DTLrowii} and
+%\counterfmt{DTLrowiii} which keep track of
+%the current row.
+%
+%\importantpar Note that these counters are only incremented
+%when \meta{condition} is satisfied. These counters are incremented
+%using \cs{refstepcounter} before the start of \meta{text}, so they
+%may be referenced using \cs{label}, however remember that \cs{label}
+%references the last counter to be incremented using
+%\cs{refstepcounter} \emph{in the current scope}. The \cs{label}
+%should therefore be the first command in \meta{text} to ensure
+%that it references the current row counter.
+%
+%\DescribeMacro{\DTLcurrentindex}
+%\begin{definition}
+%\cs{DTLcurrentindex}
+%\end{definition}
+%At the start of each iteration, \cs{DTLcurrentindex} is set
+%to the arabic value of the current row counter.
+%
+%\DescribeMacro{\DTLforeachkeyinrow}
+%\begin{definition}
+%\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text}
+%\end{definition}
+%This iterates through each key in the current row, assigns
+%\meta{cmd} to the value of that key, and does \meta{text}.
+%(\meta{cmd} must be a control sequence.)
+%
+%\begin{example}{Student Scores---Labelling}{ex:label}
+%In the previous example, the student scores, stored in the
+%database "scores" were placed in a table. In this example the
+%table will be modified slightly to number each student according
+%to the row. Suppose I also want to identify which row Jane Brown
+%is in, and reference it in the text. The easiest way to do this
+%is to construct a label on each row which uniquely identifies
+%that student. The label can't simply be constructed from the
+%surname, as there are two students with the same surname. In order
+%to create a unique label, I can either construct a label from
+%both the surname and the first name, or I can use the student's
+%registration number, or I can use the student's score, since all
+%the scores are unique. The former method will cause a problem since
+%one of the names (Z\"oe) contains an accent command. Although
+%the registration numbers are all unique, they are not particularly
+%memorable, so I shall instead use the scores.
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student scores}
+%\centering
+%\begin{tabular}{cllc}
+%\bfseries Row &
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\label{row:\score}\\\theDTLrowi &
+%\firstname & \surname & \score}%
+%\end{tabular}
+%\end{table}
+%
+%Jane Brown scored the highest (75\%), her score can be seen on
+%row~\ref{row:75}.
+%\end{verbatim}
+%This produces \autoref{tab:scoreslab} and the following text:
+%Jane Brown scored the highest (75\%), her score can be seen on
+%row~\ref*{row:75}.
+%
+%\textbf{Note:} the \cs{label} command is placed before
+%"\\" to ensure that it is in the same scope as the command
+%"\refstepcounter{DTLrowi}".
+%
+%\begin{table}[htbp]
+%\caption[Student scores (labelling rows)]{Student
+%scores}\label{tab:scoreslab}
+%\centering
+%\begin{tabular}{cllc}
+%\bfseries Row &
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\label{row:\score}\\\theDTLrowi &
+%\firstname & \surname & \score}\relax
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
+%\DescribeMacro{\DTLsavelastrowcount}
+%\begin{definition}
+%\cs{DTLsavelastrowcount}\marg{cmd}
+%\end{definition}
+%This command will store the value of the row counter used in
+%the last occurrence of \ics{DTLforeach} in the control sequence
+%\meta{cmd}.
+%
+%\begin{example}{Filtering Rows}{ex:filter}
+%As mentioned earlier, the optional argument \meta{condition} of
+%\ics{DTLforeach} provides a means to exclude certain rows.
+%This example uses the database defined in \autoref{ex:scores},
+%but only displays the information for students whose marks are
+%above 60. At the end of the table, \cs{DTLsavelastrowcount}
+%is used to store the number of rows in the table. (Note that
+%\cs{DTLsavelastrowcount} is outside of \ics{DTLforeach}.)
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Top student scores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach[\DTLisgt{\score}{60}]{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%
+%\DTLsavelastrowcount{\n}%
+%\n\ students scored above 60\%.
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:topscores}. Note that in this example,
+%I could have specified the condition as "\score>60" since all
+%the scores are integers, however, as it's possible that an entry
+%may feasibly have a decimal score I have used \ics{DTLisgt} instead.
+%
+%\begin{table}[htbp]
+%\caption[Top student scores (filtering rows using
+%\cs{DTLisgt})]{Top student scores}\label{tab:topscores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach[\DTLisgt{\score}{60}]{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%
+%\DTLsavelastrowcount{\n}\relax
+%\n\ students scored above 60\%.
+%\end{table}
+%
+%Suppose now, I only want to display the scores for students whose
+%surname begins with `B'. I can do this as follows:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student scores (B)}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach[\DTLisopenbetween{\surname}{B}{C}]{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:Bscores}.
+%
+%\begin{table}[htbp]
+%\caption[Student scores (B) --- filtering rows using
+%\cs{DTLisopenbetween}]{Student scores (B)}\label{tab:Bscores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach[\DTLisopenbetween{\surname}{B}{C}]{scores}
+%{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%
+%\end{example}
+%
+%Within the body of \ics{DTLforeach} (i.e.\ within \meta{text})
+%the following conditionals may be used:
+%\DescribeMacro{\DTLiffirstrow}
+%\begin{definition}
+%\cs{DTLiffirstrow}\marg{true part}\marg{false part}
+%\end{definition}
+%If the current row is the first row, then do \meta{true part},
+%otherwise do \meta{false part}.
+%
+%\DescribeMacro{\DTLifoddrow}
+%\begin{definition}
+%\cs{DTLifoddrow}\marg{true part}\marg{false part}
+%\end{definition}
+%If the current row number is an odd number, then do \meta{true part},
+%otherwise do \meta{false part}.
+%
+%\begin{example}{Stripy Tables}{ex:stripy}
+%This example uses the same database as in the previous examples.
+%It requires the \sty{colortbl} package, which provides the
+%command \cs{rowcolor}. The command \cs{DTLifoddrow} is used
+%to produce a striped table.
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{A stripy table}\label{tab:stripy}
+%\centering
+%\begin{tabular}{llc}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\\DTLifoddrow{\rowcolor{blue}}{\rowcolor{green}}%
+%\firstname & \surname & \score}%
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:stripy}.
+%
+%\begin{table}[htbp]
+%\caption[A stripy table (illustrating the use of
+%\cs{DTLifoddrow})]{A stripy table}\label{tab:stripy}
+%\centering
+%\begin{tabular}{llc}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\\DTLifoddrow{\rowcolor{blue}}{\rowcolor{green}}\relax
+%\firstname & \surname & \score}\relax
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
+%\begin{example}{Two Database Rows per Tabular Row}{ex:2rows}
+%In order to save space, you may want two database rows per
+%tabular row, when displaying a database in a \env{tabular}
+%environment. This can be accomplished using \ics{DTLifoddrow}.
+%For example
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Two database rows per tabular row}
+%\centering
+%\begin{tabular}{llcllc}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%) &
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\DTLifoddrow{\\}{&}%
+%\firstname & \surname & \score}%
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%produces \autoref{tab:2rows}
+%
+%\begin{table}[htbp]
+%\caption[Two database rows per tabular row (illustrating the
+%use of\newline \cs{DTLifoddrow})]{Two database rows per tabular
+%row}\label{tab:2rows}
+%\centering
+%\begin{tabular}{llcllc}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%) &
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\DTLifoddrow{\\}{&}\relax
+%\firstname & \surname & \score}\relax
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
+%\begin{example}{Nested \cs{DTLforeach}}{ex:nested}
+%In this example I have a CSV file called "index.csv" which
+%contains:
+%\begin{verbatim}
+%File,Temperature,NaCl,pH
+%exp25a.csv,25,4.7,0.5
+%exp25b.csv,25,4.8,1.5
+%exp30a.csv,30,5.12,4.5
+%\end{verbatim}
+%\DTLnewdb{index}\relax
+%\DTLnewrow{index}\relax
+%\DTLnewdbentry{index}{File}{exp25a.csv}\relax
+%\DTLnewdbentry{index}{Temperature}{25}\relax
+%\DTLnewdbentry{index}{NaCl}{4.7}\relax
+%\DTLnewdbentry{index}{pH}{0.5}\relax
+%\DTLnewrow{index}\relax
+%\DTLnewdbentry{index}{File}{exp25b.csv}\relax
+%\DTLnewdbentry{index}{Temperature}{25}\relax
+%\DTLnewdbentry{index}{NaCl}{4.8}\relax
+%\DTLnewdbentry{index}{pH}{1.5}\relax
+%\DTLnewrow{index}\relax
+%\DTLnewdbentry{index}{File}{exp30a.csv}\relax
+%\DTLnewdbentry{index}{Temperature}{30}\relax
+%\DTLnewdbentry{index}{NaCl}{5.12}\relax
+%\DTLnewdbentry{index}{pH}{4.5}\relax
+%The first column of this file contains the name of another
+%CSV file which has the results of a time to growth experiment
+%performed at the given incubation temperature, salt concentration
+%and pH. The file "exp25a.csv" contains the following:
+%\begin{verbatim}
+%Time,Log Count
+%0,3.75
+%23,3.9
+%45,4.0
+%\end{verbatim}
+%\DTLnewdb{exp25a.csv}\relax
+%\DTLnewrow{exp25a.csv}\relax
+%\DTLnewdbentry{exp25a.csv}{Time}{0}\relax
+%\DTLnewdbentry{exp25a.csv}{Log Count}{3.75}\relax
+%\DTLnewrow{exp25a.csv}\relax
+%\DTLnewdbentry{exp25a.csv}{Time}{23}\relax
+%\DTLnewdbentry{exp25a.csv}{Log Count}{3.9}\relax
+%\DTLnewrow{exp25a.csv}\relax
+%\DTLnewdbentry{exp25a.csv}{Time}{45}\relax
+%\DTLnewdbentry{exp25a.csv}{Log Count}{4.0}\relax
+%The file "exp25b.csv" contains the following:
+%\begin{verbatim}
+%Time,Log Count
+%0,3.6
+%60,3.8
+%120,4.0
+%\end{verbatim}
+%\DTLnewdb{exp25b.csv}\relax
+%\DTLnewrow{exp25b.csv}\relax
+%\DTLnewdbentry{exp25b.csv}{Time}{0}\relax
+%\DTLnewdbentry{exp25b.csv}{Log Count}{3.6}\relax
+%\DTLnewrow{exp25b.csv}\relax
+%\DTLnewdbentry{exp25b.csv}{Time}{60}\relax
+%\DTLnewdbentry{exp25b.csv}{Log Count}{3.8}\relax
+%\DTLnewrow{exp25b.csv}\relax
+%\DTLnewdbentry{exp25b.csv}{Time}{120}\relax
+%\DTLnewdbentry{exp25b.csv}{Log Count}{4.0}\relax
+%The file "exp30a.csv" contains the following:
+%\begin{verbatim}
+%Time,Log Count
+%0,3.73
+%23,3.67
+%60,4.9
+%\end{verbatim}
+%\DTLnewdb{exp30a.csv}\relax
+%\DTLnewrow{exp30a.csv}\relax
+%\DTLnewdbentry{exp30a.csv}{Time}{0}\relax
+%\DTLnewdbentry{exp30a.csv}{Log Count}{3.73}\relax
+%\DTLnewrow{exp30a.csv}\relax
+%\DTLnewdbentry{exp30a.csv}{Time}{23}\relax
+%\DTLnewdbentry{exp30a.csv}{Log Count}{3.67}\relax
+%\DTLnewrow{exp30a.csv}\relax
+%\DTLnewdbentry{exp30a.csv}{Time}{60}\relax
+%\DTLnewdbentry{exp30a.csv}{Log Count}{4.9}\relax
+%Suppose I now want to iterate through "index.csv", load the given
+%file, and create a table for that data. I can do this using
+%nested \ics{DTLforeach} as follows:
+%\begin{verbatim}
+% % load index data file
+%\DTLloaddb{index}{index.csv}
+%
+% % iterate through index database
+%\DTLforeach{index}{\theFile=File,\theTemp=Temperature,%
+%\theNaCl=NaCl,\thepH=pH}{%
+% % load results file into database of the same name
+%\DTLloaddb{\theFile}{\theFile}%
+% % Create a table
+%\begin{table}[htbp]
+%\caption{Temperature = \theTemp, NaCl = \theNaCl,
+%pH = \thepH}\label{tab:\theFile}
+%\centering
+%\begin{tabular}{rl}
+%\bfseries Time & \bfseries Log Count
+%\DTLforeach{\theFile}{\theTime=Time,\theLogCount=Log Count}{%
+%\\\theTime & \theLogCount}%
+%\end{tabular}
+%\end{table}
+%}
+%\end{verbatim}
+%This creates \autoref{tab:exp25a.csv} to \autoref{tab:exp30a.csv}.
+%(Note that each table is given a label that is based on the
+%database name, to ensure that it is unique.)
+%
+%\DTLforeach{index}{\theFile=File,\theTemp=Temperature,\theNaCl
+%=NaCl,\thepH=pH}{
+%\begin{table}[htbp]
+%\caption[Temperature = \theTemp, NaCl = \theNaCl,
+%pH = \thepH\space (illustrating nested
+%\cs{DTLforeach})]{Temperature = \theTemp, NaCl = \theNaCl,
+%pH = \thepH}\label{tab:\theFile}
+%\centering
+%\begin{tabular}{rl}
+%\bfseries Time & \bfseries Log Count
+%\DTLforeach{\theFile}{\theTime=Time,\theLogCount=Log Count}{
+%\\\theTime & \theLogCount}%
+%\end{tabular}
+%\end{table}
+%}
+%\end{example}
+%
+%\subsection{Null Values}
+%If a database is created using \cs{DTLnewdb}, \cs{DTLnewrow}
+%and \cs{DTLnewdbentry} (rather than loading it from an ASCII
+%file), it is possible for some of the entries to have null values
+%when a value is not assigned to a given key for a given row.
+%
+%When you iterate through the database using \cs{DTLforeach}
+%(described in \autoref{sec:dbforeach}),
+%if an entry is missing for a given row, the associated command given
+%in the \meta{values} argument will be set to a null value. This
+%value depends on the data type associated with the given key.
+%
+%\DescribeMacro{\DTLstringnull}
+%\begin{definition}
+%\cs{DTLstringnull}
+%\end{definition}
+%This is the null value for a string.
+%
+%\DescribeMacro{\DTLnumbernull}
+%\begin{definition}
+%\cs{DTLnumbernull}
+%\end{definition}
+%This is the null value for a number.
+%
+%\DescribeMacro{\DTLifnull}
+%\begin{definition}
+%\cs{DTLifnull}\marg{cmd}\marg{true part}\marg{false part}
+%\end{definition}
+%This checks if \meta{cmd} is null where \meta{cmd} is a command name,
+%if it is, then \meta{true part}
+%is done, otherwise \meta{false part} is done. This macro is
+%illustrated in \autoref{ex:null} below.
+%
+%\begin{example}{Null Values}{ex:null}
+%Consider the following (which creates a database called "emailDB"):
+%\begin{verbatim}
+%\DTLnewdb{emailDB}
+%\DTLnewrow{emailDB}
+%\DTLnewdbentry{emailDB}{Surname}{Jones}
+%\DTLnewdbentry{emailDB}{FirstName}{Mary}
+%\DTLnewdbentry{emailDB}{Email1}{mj@my.uni.ac.uk}
+%\DTLnewdbentry{emailDB}{Email2}{mj@somewhere.com}
+%\DTLnewrow{emailDB}
+%\DTLnewdbentry{emailDB}{Surname}{Smith}
+%\DTLnewdbentry{emailDB}{FirstName}{Adam}
+%\DTLnewdbentry{emailDB}{Email1}{as@my.uni.ac.uk}
+%\DTLnewdbentry{emailDB}{RegNum}{12345}
+%\end{verbatim}
+%\DTLnewdb{emailDB}\relax
+%\DTLnewrow{emailDB}\relax
+%\DTLnewdbentry{emailDB}{Surname}{Jones}\relax
+%\DTLnewdbentry{emailDB}{FirstName}{Mary}\relax
+%\DTLnewdbentry{emailDB}{Email1}{mj@my.uni.ac.uk}\relax
+%\DTLnewdbentry{emailDB}{Email2}{mj@somewhere.com}\relax
+%\DTLnewrow{emailDB}\relax
+%\DTLnewdbentry{emailDB}{Surname}{Smith}\relax
+%\DTLnewdbentry{emailDB}{FirstName}{Adam}\relax
+%\DTLnewdbentry{emailDB}{Email1}{as@my.uni.ac.uk}\relax
+%\DTLnewdbentry{emailDB}{RegNum}{12345}\relax
+%In the above example, the first row of the database contains
+%an entry with the key "Email2", but the second row doesn't.
+%Whereas the second row contains an entry with the key "RegNum",
+%but the first row doesn't.
+%
+%The following code puts the information in a \env{tabular}
+%environment:
+%\begin{verbatim}
+%\begin{tabular}{lllll}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Email 1 &
+%\bfseries Email 2 &
+%\bfseries Reg Num%
+%\DTLforeach{emailDB}{\firstname=FirstName,\surname=Surname,%
+%\emailI=Email1,\emailII=Email2,\regnum=RegNum}{%
+%\\\firstname & \surname & \emailI & \emailII & \regnum}%
+%\end{tabular}
+%\end{verbatim}
+%This produces the following:\par\vskip\baselineskip\noindent
+%\begin{tabular}{lllll}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Email 1 &
+%\bfseries Email 2 &
+%\bfseries Reg Num\relax
+%\DTLforeach{emailDB}{\firstname=FirstName,\surname
+%=Surname,\emailI=Email1,\emailII=Email2,\regnum=RegNum}{\relax
+%\\\firstname & \surname & \emailI & \emailII & \regnum}\relax
+%\end{tabular}
+%\par\vskip\baselineskip
+%Note that on the first row of data, the registration number appears as
+%0, while on the next row, the second email address appears as
+%NULL. The \sty{datatool} package has identified the key "RegNum"
+%for this database as a numerical key, since all elements in the
+%database with that key are numerical, whereas it has
+%identified the key "Email2" as a string, since there is at least
+%one element in this database with that key that is a string.
+%Null numerical values are set to \cs{DTLnumbernull} (0),
+%and null strings are set to \cs{DTLstringnull} (NULL).
+%
+%The following code checks each value to determine whether it
+%is null using \cs{DTLifnull}. If it is, the text \emph{Missing}
+%is inserted, otherwise the value itself is used:
+%\begin{verbatim}
+%\begin{tabular}{lllll}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Email 1 &
+%\bfseries Email 2 &
+%\bfseries Reg Num%
+%\DTLforeach{emailDB}{\firstname=FirstName,\surname=Surname,%
+%\emailI=Email1,\emailII=Email2,\regnum=RegNum}{%
+%\\\DTLifnull{\firstname}{\emph{Missing}}{\firstname} &
+%\DTLifnull{\surname}{\emph{Missing}}{\surname} &
+%\DTLifnull{\emailI}{\emph{Missing}}{\emailI} &
+%\DTLifnull{\emailII}{\emph{Missing}}{\emailII} &
+%\DTLifnull{\regnum}{\emph{Missing}}{\regnum}}%
+%\end{tabular}
+%\end{verbatim}
+%This produces the following:\par\vskip\baselineskip\noindent
+%\begin{tabular}{lllll}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Email 1 &
+%\bfseries Email 2 &
+%\bfseries Reg Num\relax
+%\DTLforeach{emailDB}{\firstname=FirstName,\surname
+%=Surname,\emailI=Email1,\emailII=Email2,\regnum=RegNum}{\relax
+%\\\DTLifnull{\firstname}{\emph{Missing}}{\firstname} &
+%\DTLifnull{\surname}{\emph{Missing}}{\surname} &
+%\DTLifnull{\emailI}{\emph{Missing}}{\emailI} &
+%\DTLifnull{\emailII}{\emph{Missing}}{\emailII} &
+%\DTLifnull{\regnum}{\emph{Missing}}{\regnum}}\relax
+%\end{tabular}
+%\par\vskip\baselineskip\noindent
+%If you want to do this, you may find it easier to define a
+%convenience command that will display some appropriate text
+%if an entry is missing, for example:
+%\begin{verbatim}
+%\newcommand*{\checkmissing}[1]{\DTLifnull{#1}{---}{#1}}
+%\end{verbatim}
+%Then instead of typing, say,
+%\begin{verbatim}
+%\DTLifnull{\regnum}{---}{\regnum}
+%\end{verbatim}
+%you can instead type:
+%\begin{verbatim}
+%\checkmissing{\regnum}
+%\end{verbatim}
+%
+%Now suppose that instead of defining the database using \cs{DTLnewdb},
+%\cs{DTLnewrow} and \cs{DTLnewdbentry}, you have a file with the
+%contents:
+%\begin{ttfamily}\setlength{\parindent}{0pt}\par\vskip\baselineskip
+%Surname,FirstName,RegNum,Email1,Email2
+%
+%\DTLforeach{emailDB}{\surname=Surname,\firstname=FirstName,\regNo
+%=RegNum,\emailI=Email1,\emailII
+%=Email2}{\relax
+%\surname,\firstname,\DTLifnull{\regNo}{}{\regNo},\emailI,\DTLifnull{\emailII}{}{\emailII}\par
+%}
+%\end{ttfamily}\par\vskip\baselineskip\noindent
+%and you load the data from this file using \cs{DTLloaddb}
+%(defined in \autoref{sec:loaddb}). Now the
+%database has no null values, but has an empty value for the
+%key "RegNum" on the first row of the database, and an empty
+%value for the key "Email2" on the second row of the database.
+%Now, the following code
+%\begin{verbatim}
+%\begin{tabular}{lllll}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Email 1 &
+%\bfseries Email 2 &
+%\bfseries Reg Number%
+%\DTLforeach{emailDB}{\firstname=FirstName,\surname=Surname,%
+%\emailI=Email1,\emailII=Email2,\regnum=RegNum}{%
+%\\\DTLifnull{\firstname}{\emph{Missing}}{\firstname} &
+%\DTLifnull{\surname}{\emph{Missing}}{\surname} &
+%\DTLifnull{\emailI}{\emph{Missing}}{\emailI} &
+%\DTLifnull{\emailII}{\emph{Missing}}{\emailII} &
+%\DTLifnull{\regnum}{\emph{Missing}}{\regnum}}%
+%\end{tabular}
+%\end{verbatim}
+%produces:\par\vskip\baselineskip\noindent
+%\begin{tabular}{lllll}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Email 1 &
+%\bfseries Email 2 &
+%\bfseries Reg Number\relax
+%\DTLforeach{emailDB}{\firstname=FirstName,\surname
+%=Surname,\emailI=Email1,\emailII=Email2,\regnum=RegNum}{\relax
+%\\\firstname & \surname & \emailI & \DTLifnull{\emailII}{}{\emailII} & \DTLifnull{\regnum}{}{\regnum}}\relax
+%\end{tabular}
+%\end{example}
+%
+%\subsection{Editing Database Rows}
+%\label{sec:editdb}
+%
+%In the body of the \ics{DTLforeach} loop, you can use the following
+%to edit the current row:
+%\DescribeMacro{\DTLappendtorow}
+%\begin{definition}
+%\cs{DTLappendtorow}\marg{key}\marg{value}
+%\end{definition}
+%This appends a new entry with the given \meta{key} and \meta{value}
+%to the current row.
+%
+%\DescribeMacro{\DTLreplaceentryforrow}
+%\begin{definition}
+%\cs{DTLreplaceentryforrow}\marg{key}\marg{value}
+%\end{definition}
+%This replaces the entry for \meta{key} with \meta{value}.
+%
+%\DescribeMacro{\DTLremoveentryfromrow}
+%\begin{definition}
+%\cs{DTLremoveentryfromrow}\marg{key}
+%\end{definition}
+%This the entry for \meta{key} from the current row.
+%
+%\DescribeMacro{\DTLremovecurrentrow}
+%\begin{definition}
+%\cs{DTLremovecurrentrow}
+%\end{definition}
+%This removes the current row from the database.
+%
+%\begin{example}{Editing Database Rows}{ex:editdb}
+%In this example I have a CSV file called "marks.csv" that contains
+%student marks for three assignments:
+%\DTLnewdb{marks}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{John}\relax
+%\DTLnewdbentry{marks}{Surname}{Smith, Jr}\relax
+%\DTLnewdbentry{marks}{StudentNo}{102689}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{68}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{57}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{72}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{Jane}\relax
+%\DTLnewdbentry{marks}{Surname}{Brown}\relax
+%\DTLnewdbentry{marks}{StudentNo}{102647}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{75}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{84}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{80}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{Andy}\relax
+%\DTLnewdbentry{marks}{Surname}{Brown}\relax
+%\DTLnewdbentry{marks}{StudentNo}{103569}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{42}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{52}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{54}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{Z\"oe}\relax
+%\DTLnewdbentry{marks}{Surname}{Adams}\relax
+%\DTLnewdbentry{marks}{StudentNo}{105987}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{52}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{48}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{57}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{Roger}\relax
+%\DTLnewdbentry{marks}{Surname}{Brady}\relax
+%\DTLnewdbentry{marks}{StudentNo}{106872}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{58}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{60}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{62}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{Clare}\relax
+%\DTLnewdbentry{marks}{Surname}{Verdon}\relax
+%\DTLnewdbentry{marks}{StudentNo}{104356}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{45}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{50}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{48}\relax
+%\begin{ttfamily}\setlength{\parindent}{0pt}\par
+%Surname,FirstName,StudentNo,Assignment 1,Assignment 2,Assignment 3
+%
+%\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\regNo
+%=StudentNo,\assignI=Assignment 1,\assignII
+%=Assignment 2,\assignIII=Assignment 3}{\relax
+%\char`\"\surname\char`\",\DTLifstringeq{\firstname}{Zoe}{Z\string\"oe}{\firstname},\regNo,\assignI,\assignII,\assignIII\par
+%}
+%\end{ttfamily}\par\noindent
+%First load this into a database called "marks":
+%\begin{verbatim}
+%\DTLloaddb{marks}{marks.csv}
+%\end{verbatim}
+%Suppose now I want to compute the average mark for each
+%student, and append this to the database. I can do this as
+%follows:
+%\begin{verbatim}
+%\DTLforeach{marks}{%
+%\assignI=Assignment 1,%
+%\assignII=Assignment 2,%
+%\assignIII=Assignment 3}{%
+%\DTLmeanforall{\theMean}{\assignI,\assignII,\assignIII}%
+%\DTLappendtorow{Average}{\theMean}}
+%\end{verbatim}
+%\DTLforeach{marks}{\assignI=Assignment 1,\assignII
+%=Assignment 2,\assignIII=Assignment 3}{\relax
+%\DTLmeanforall{\theMean}{\assignI,\assignII,\assignIII}%
+%\DTLappendtorow{Average}{\theMean}}\relax
+%For each row in the "marks" database, I now have an extra key
+%called "Average" that contains the average mark over all three
+%assignments for a given student. I can now put this data into
+%a table:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student marks}
+%\centering
+%\begin{tabular}{llrrrr}
+%\bfseries Surname & \bfseries First Name &
+%\bfseries Assign 1 &
+%\bfseries Assign 2 &
+%\bfseries Assign 3 &
+%\bfseries Average Mark%
+%\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\average
+%=Average,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII
+%=Assignment 3}{\\\surname
+%& \firstname & \assignI & \assignII & \assignIII &
+%\DTLround{\average}{\average}{2}\average}\relax
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:meanmarks}.
+%
+%Note that if I only wanted the averages for the table and nothing
+%else, I could simply have computed the average in each row of the
+%table and displayed it without adding the information to the
+%database, however I am going to reuse this information in
+%\autoref{ex:multibar}, so adding it to the database means that
+%I don't need to recompute the mean.
+%
+%\begin{table}[htbp]
+%\caption[Student marks (with averages)]{Student
+%marks}\label{tab:meanmarks}
+%\centering
+%\begin{tabular}{llrrrr}
+%\bfseries Surname & \bfseries First Name &
+%\bfseries Assign 1 &
+%\bfseries Assign 2 &
+%\bfseries Assign 3 &
+%\bfseries Average Mark\relax
+%\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\average
+%=Average,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII
+%=Assignment 3}{\\\surname
+%& \firstname & \assignI & \assignII & \assignIII &
+%\DTLround{\average}{\average}{2}\average}\relax
+%\end{tabular}
+%\end{table}
+%
+%\end{example}
+%
+%\subsection{Arithmetical Computations on Database Entries}
+%
+%The commands used in \autoref{sec:fp} can be used on database
+%entries. You can, of course, directly use the commands provided
+%by the \sty{fp} package if you know that the values are in the
+%correct format (i.e.\ no currency symbols, no number group
+%separators and a full stop as the decimal point) but if this is
+%not the case, then you should use the commands described in
+%\autoref{sec:fp}. If you want to use a command provided by the
+%\sty{fp} package, that does not have a wrapper function in
+%\sty{datatool}, then you will need to convert the value using
+%\ics{DTLconverttodecimal}, and convert it back using either
+%\ics{DTLdecimaltolocale} or \ics{DTLdecimaltocurrency}.
+%
+%\begin{example}{Arithmetical Computations}{ex:mean}
+%In this example, I am going to produce a table similar to
+%\autoref{tab:scores}, except that I want to add an extra row at the
+%end which contains the average score.
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student scores}\label{tab:mean}
+%\centering
+%\def\total{0}%
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\firstname & \surname &
+%\DTLgadd{\total}{\score}{\total}%
+%\score
+%}\\
+%\multicolumn{2}{l}{\bfseries Average Score} &
+%\DTLsavelastrowcount{\n}%
+%\DTLdiv{\average}{\total}{\n}%
+%\DTLround{\average}{\average}{2}%
+%\average
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:mean}.
+%\textbf{Notes:}
+%\begin{itemize}
+%\item I had to use \ics{DTLgadd} rather than \ics{DTLadd} since it
+%occurs within a \env{tabular} environment which puts each entry
+%in a local scope.
+%
+%\item I used \ics{DTLsavelastrowcount} to store the number of
+%rows produced by \ics{DTLforeach} in the control sequence \cs{n}.
+%
+%\item I used \ics{DTLround} to round the average score to 2 decimal
+%places.
+%\end{itemize}
+%
+%\begin{table}[htbp]
+%\caption[Student scores (using arithmetic computations)]{Student
+%scores}\label{tab:mean}
+%\centering
+%\def\total{0}\relax
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\firstname & \surname &
+%\DTLgadd{\total}{\score}{\total}\relax
+%\score
+%}\\
+%\multicolumn{2}{l}{\bfseries Average Score} &
+%\DTLsavelastrowcount{\n}\relax
+%\DTLdiv{\average}{\total}{\n}\relax
+%\DTLround{\average}{\average}{2}\relax
+%\average
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
+%\DescribeMacro{\DTLsumforkeys}
+%\begin{definition}
+%\cs{DTLsumforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command sums all the entries over all the databases listed in
+%the comma separated list of database names \meta{db list} for each key in
+%\meta{key list} where the condition given by
+%\meta{condition} is true. The result is stored in \meta{cmd}
+%which must be a control sequence. For example:
+%\begin{verbatim}
+%\DTLsumforkeys{scores}{Score}{\total}
+%\end{verbatim}
+%sets \cs{total} to the sum of all the scores in the database
+%called "scores".
+%
+%\DescribeMacro{\DTLmeanforkeys}
+%\begin{definition}
+%\cs{DTLmeanforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command computes the arithmetic mean of all the entries over
+%all the databases listed in \meta{db list} for all keys in \meta{key list} where
+%the condition
+%given by \meta{condition} is true. The result is stored in \meta{cmd}
+%which must be a control sequence. For example:
+%\begin{verbatim}
+%\DTLmeanforkeys{scores}{Score}{\average}
+%\end{verbatim}
+%sets \cs{average} to the mean of all the scores in the database
+%called "scores".
+%
+%\DescribeMacro{\DTLvarianceforkeys}
+%\begin{definition}
+%\cs{DTLvarianceforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command computes the variance of all the entries over
+%all the databases listed in \meta{db list} for all keys in \meta{key list} where
+%the condition
+%given by \meta{condition} is true. The result is stored in \meta{cmd}
+%which must be a control sequence.
+%
+%\DescribeMacro{\DTLsdforkeys}
+%\begin{definition}
+%\cs{DTLsdforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command computes the standard deviation of all the entries over
+%all the databases listed in \meta{db list} for all keys in \meta{key list} where
+%the condition
+%given by \meta{condition} is true. The result is stored in \meta{cmd}
+%which must be a control sequence.
+%
+%\DescribeMacro{\DTLminforkeys}
+%\begin{definition}
+%\cs{DTLminforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command determines the minimum value over all entries
+%for all keys in \meta{key list} over all the databases listed in \meta{db list}
+%and stores
+%in \meta{cmd}, which must be a control sequence. For example
+%\begin{verbatim}
+%\DTLminforkeys{scores}{Score}{\theMin}
+%\end{verbatim}
+%sets \cs{theMin} to the minimum score in the database.
+%
+%\DescribeMacro{\DTLmaxforkeys}
+%\begin{definition}
+%\cs{DTLmaxforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command determines the maximum value over all entries
+%for all keys in \meta{key list} over all the databases listed in \meta{db list}
+%and stores
+%in \meta{cmd}, which must be a control sequence. For example
+%\begin{verbatim}
+%\DTLminforkeys{scores}{Score}{\theMax}
+%\end{verbatim}
+%sets \cs{theMax} to the minimum score in the database.
+%
+%\DescribeMacro{\DTLcomputebounds}
+%\begin{definition}
+%\cs{DTLcomputebounds}\marg{condition}\marg{db list}\marg{x key}\marg{y key}\marg{minX cmd}\marg{minY cmd}\marg{maxX cmd}\marg{maxY cmd}
+%\end{definition}
+%Computes the maximum and minimum $x$ and $y$ values over all
+%the databases listed in \meta{db list} where the $x$ value
+%is given by \meta{x key} and the $y$ value is given by
+%\meta{y key}. The results are stored in \meta{minX cmd},
+%\meta{minY cmd}, \meta{maxX cmd} and \meta{maxY cmd}.
+%
+%\begin{example}{Mail Merging}{ex:mailmerging}
+%This example uses the database given in \autoref{ex:scores} and
+%uses \ics{DTLmeanforkeys} to determine the average score. A letter
+%is then created for each student to inform them of their score
+%and the class average.
+%
+%\begin{verbatim}
+%\documentclass{letter}
+%
+%\usepackage{datatool}
+%
+%\begin{document}
+% % load database
+%\DTLloaddb{scores}{studentscores.csv}
+% % compute arithmetic mean for key `Score'
+%\DTLmeanforkeys{scores}{Score}{\average}
+% % Round the average to 2 decimal places
+%\DTLround{\average}{\average}{2}
+% % Save the highest score in \maxscore
+%\DTLmaxforkeys{scores}{Score}{\maxscore}
+%
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,%
+%\score=Score}{%
+%\begin{letter}{}
+%\opening{Dear \firstname\ \surname}
+%
+%\DTLifnumgt{\score}{60}{Congratulations you}{You} achieved a score
+%of \score\% which was \DTLifnumgt{\score}{\average}{above}{below}
+%the average of \average\%. \DTLifnumeq{\score}{\maxscore}{You
+%achieved the highest score}{The top score was \maxscore}.
+%
+%\closing{Yours Sincerely}
+%\end{letter}
+%}
+%\end{document}
+%\end{verbatim}
+%\end{example}
+%
+%\subsection{Sorting a Database}
+%\label{sec:sort}
+%
+%\DescribeMacro{\DTLsort}
+%\begin{definition}
+%\cs{DTLsort}\oarg{replacement key list}\marg{sort criteria}\marg{db name}
+%\end{definition}
+%\DescribeMacro{\DTLsort*}
+%\begin{definition}
+%\cs{DTLsort*}\oarg{replacement key list}\marg{sort criteria}\marg{db name}
+%\end{definition}
+%This will sort the database called \meta{db name} according to
+%the criteria given by \meta{sort criteria}, which must be a
+%comma separated list of keys and optionally "="\meta{order}, where
+%\meta{order} is either "ascending" or "descending". If the order
+%is omitted, "ascending" is assumed. The database keeps track of
+%the data type for a given key, and uses this to determine whether
+%an alphabetical or numerical sort is required. (String comparisons
+%are made using the command \cs{dtlcompare} or \cs{dtlicompare}
+%described in \autoref{src:dtlcompare}.)
+%
+%The optional argument \meta{replacement key list} is a list of
+%keys to use if the current key given in \meta{sort criteria}
+%is null for a given entry. Null keys are unlikely to occur if
+%you have loaded the database from an external ASCII file, but
+%may occur if the database is created using \cs{DTLnewdb},
+%\cs{DTLnewrow} and \cs{DTLnewdbentry}. For example:
+%\begin{verbatim}
+%\DTLsort[Editor,Organization]{Author}{mydata}
+%\end{verbatim}
+%will sort according to the "Author" key, but if that key is missing
+%for a given row of the database, the "Editor" key will be used,
+%and if the "Editor" key is missing, it will use the "Organization"
+%key. Note that this is not the same as:
+%\begin{verbatim}
+%\DTLsort{Author,Editor,Organization}{mydata}
+%\end{verbatim}
+%which will first compare the "Author" keys, but if the author names
+%are the same, it will then compare the "Editor" keys, and if the
+%editor names are also the same, it will then compare the
+%"Organization" keys.
+%
+%The unstarred version uses a case sensitive comparison for strings,
+%whereas the starred version ignores the case when comparing strings.
+%Note that the case sensitive comparison orders uppercase characters
+%before lowercase characters, so the letter B is considered to be
+%lower than the letter a.
+%
+%\begin{example}{Sorting a Database}{ex:sort}
+%This example uses the database called "scores" defined in
+%\autoref{ex:scores}. First, I am going to sort the database
+%according to the student scores in descending order (highest to
+%lowest) and display the database in a table
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student scores (sorted by score)}
+%\centering
+%\DTLsort{Score=descending}{scores}%
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:sortscores}.
+%
+%\begin{table}[htbp]
+%\caption{Student scores (sorted by score)}\label{tab:sortscores}
+%\centering
+%\DTLsort{Score=descending}{scores}\relax
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%
+%Now I am going to sort the database according to
+%surname and then first name, and display it in a table. Note that
+%since I want to sort in ascending order, I can omit the
+%"=ascending" part of the sort criteria. I have also decided to
+%reverse the first and second columns, so that the surname is
+%in the first column.
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student scores (sorted by name)}
+%\centering
+%\DTLsort{Surname,FirstName}{scores}%
+%\begin{tabular}{llr}
+%\bfseries Surname &
+%\bfseries First Name &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\surname & \firstname & \score}
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:sortname}.
+%\begin{table}[htbp]
+%\caption{Student scores (sorted by name)}\label{tab:sortname}
+%\centering
+%\DTLsort{Surname,FirstName}{scores}\relax
+%\begin{tabular}{llr}
+%\bfseries Surname &
+%\bfseries First Name &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\surname & \firstname & \score}
+%\end{tabular}
+%\end{table}
+%
+%Now suppose I add two new students to the database:
+%\begin{verbatim}
+%\DTLnewrow{scores}%
+%\DTLnewdbentry{scores}{Surname}{van der Mere}%
+%\DTLnewdbentry{scores}{FirstName}{Henk}%
+%\DTLnewdbentry{scores}{Score}{71}%
+%\DTLnewrow{scores}%
+%\DTLnewdbentry{scores}{Surname}{de la Mere}%
+%\DTLnewdbentry{scores}{FirstName}{Jos}%
+%\DTLnewdbentry{scores}{Score}{58}%
+%\end{verbatim}
+%\DTLnewrow{scores}
+%\DTLnewdbentry{scores}{Surname}{van der Mere}\relax
+%\DTLnewdbentry{scores}{FirstName}{Henk}\relax
+%\DTLnewdbentry{scores}{Score}{71}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{Surname}{de la Mere}\relax
+%\DTLnewdbentry{scores}{FirstName}{Jos}\relax
+%\DTLnewdbentry{scores}{Score}{58}\relax
+%and again I try sorting the database, and displaying the contents
+%as a table:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student scores (case sensitive sort)}
+%\centering
+%\DTLsort{Surname,FirstName}{scores}%
+%\begin{tabular}{llr}
+%\bfseries Surname &
+%\bfseries First Name &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\surname & \firstname & \score}
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:sortname2}. Notice that the surnames
+%aren't correctly ordered. This is because a case-sensitive
+%sort was used. Changing \cs{DTLsort} to \cs{DTLsort*} in the
+%above code produces \autoref{tab:sortname3}.
+%
+%\begin{table}[htbp]
+%\caption{Student scores (case sensitive sort)}\label{tab:sortname2}
+%\centering
+%\DTLsort{Surname,FirstName}{scores}\relax
+%\begin{tabular}{llr}
+%\bfseries Surname &
+%\bfseries First Name &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\surname & \firstname & \score}
+%\end{tabular}
+%\end{table}
+%
+%\begin{table}[htbp]
+%\caption{Student scores (case ignored when
+%sorting)}\label{tab:sortname3}
+%\centering
+%\DTLsort*{Surname,FirstName}{scores}\relax
+%\begin{tabular}{llr}
+%\bfseries Surname &
+%\bfseries First Name &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\surname & \firstname & \score}
+%\end{tabular}
+%\end{table}
+%
+%\end{example}
+%
+%\begin{example}{Influencing the sort order}{ex:sortswitchargs}
+%Consider the data displayed in \autoref{tab:sortname3}, suppose that
+%you want the names ``van der Mere'' and ``de la Mere'' sorted
+%according to the actual surname ``Mere'' rather than by the ``von
+%part''. There are two ways you can do this: firstly, you could store
+%the von part in a separate field, and then sort by surname, then von
+%part, then first name, or you could define a command called, say,
+%\cs{switchargs}, as follows:
+%\begin{verbatim}
+%\newcommand*{\switchargs}[2]{#2#1}
+%\end{verbatim}
+%\newcommand*{\switchargs}[2]{#2#1}\relax
+%then store the data as:
+%\begin{verbatim}
+%FirstName,Surname,StudentNo,Score
+%John,"Smith, Jr",102689,68
+%Jane,Brown,102647,75
+%Andy,Brown,103569,42
+%Z\"oe,Adams,105987,52
+%Roger,Brady,106872,58
+%Clare,Verdon,104356,45
+%Henk,\switchargs{Mere}{van der },106789,71
+%Jos,\switchargs{Mere}{de la },104256,58
+%\end{verbatim}
+%\DTLnewdb{scores2}\relax
+%\DTLnewrow{scores2}\relax
+%\DTLnewdbentry{scores2}{FirstName}{John}\relax
+%\DTLnewdbentry{scores2}{Surname}{Smith, Jr}\relax
+%\DTLnewdbentry{scores2}{StudentNo}{102689}\relax
+%\DTLnewdbentry{scores2}{Score}{68}\relax
+%\DTLnewrow{scores2}\relax
+%\DTLnewdbentry{scores2}{FirstName}{Jane}\relax
+%\DTLnewdbentry{scores2}{Surname}{Brown}\relax
+%\DTLnewdbentry{scores2}{StudentNo}{102647}\relax
+%\DTLnewdbentry{scores2}{Score}{75}\relax
+%\DTLnewrow{scores2}\relax
+%\DTLnewdbentry{scores2}{FirstName}{Andy}\relax
+%\DTLnewdbentry{scores2}{Surname}{Brown}\relax
+%\DTLnewdbentry{scores2}{StudentNo}{103569}\relax
+%\DTLnewdbentry{scores2}{Score}{42}\relax
+%\DTLnewrow{scores2}\relax
+%\DTLnewdbentry{scores2}{FirstName}{Z\"oe}\relax
+%\DTLnewdbentry{scores2}{Score}{52}\relax
+%\DTLnewdbentry{scores2}{StudentNo}{105987}\relax
+%\DTLnewdbentry{scores2}{Surname}{Adams}\relax
+%\DTLnewrow{scores2}\relax
+%\DTLnewdbentry{scores2}{FirstName}{Roger}\relax
+%\DTLnewdbentry{scores2}{Score}{58}\relax
+%\DTLnewdbentry{scores2}{StudentNo}{106872}\relax
+%\DTLnewdbentry{scores2}{Surname}{Brady}\relax
+%\DTLnewrow{scores2}\relax
+%\DTLnewdbentry{scores2}{FirstName}{Clare}\relax
+%\DTLnewdbentry{scores2}{Score}{45}\relax
+%\DTLnewdbentry{scores2}{StudentNo}{104356}\relax
+%\DTLnewdbentry{scores2}{Surname}{Verdon}\relax
+%\DTLnewrow{scores2}
+%\DTLnewdbentry{scores2}{Surname}{\switchargs{Mere}{van der }}\relax
+%\DTLnewdbentry{scores2}{FirstName}{Henk}\relax
+%\DTLnewdbentry{scores2}{Score}{71}\relax
+%\DTLnewrow{scores2}\relax
+%\DTLnewdbentry{scores2}{Surname}{\switchargs{Mere}{de la }}\relax
+%\DTLnewdbentry{scores2}{FirstName}{Jos}\relax
+%\DTLnewdbentry{scores2}{Score}{58}\relax
+%Now sort the data, and put it in table (this is the same code
+%as in the previous example:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student scores (influencing the sort order)}
+%\centering
+%\DTLsort*{Surname,FirstName}{scores}%
+%\begin{tabular}{llr}
+%\bfseries Surname &
+%\bfseries First Name &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\surname & \firstname & \score}
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:influencesort}.
+%
+%\begin{table}[htbp]
+%\caption{Student scores (influencing the sort order)}\label{tab:influencesort}
+%\centering
+%\DTLsort*{Surname,FirstName}{scores2}\relax
+%\begin{tabular}{llr}
+%\bfseries Surname &
+%\bfseries First Name &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores2}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\surname & \firstname & \score}
+%\end{tabular}
+%\end{table}
+%
+%\end{example}
+%
+%\subsection{Saving a Database to an External File}
+%\label{sec:savedb}
+%
+%\DescribeMacro{\DTLsavedb}
+%\begin{definition}
+%\cs{DTLsavedb}\marg{db name}\marg{filename}
+%\end{definition}
+%This writes the database called \meta{db name} to a file called
+%\meta{filename}. The separator and delimiter characters used
+%are as given by \ics{DTLsetseparator} (or \ics{DTLsettabseparator})
+%and \ics{DTLsetdelimiter}. For example:
+%\begin{verbatim}
+%\DTLsettabdelimiter
+%\DTLsavedb{scores}{scores.txt}
+%\end{verbatim}
+%will create a file called "scores.txt", and save the data in a
+%tab separated format. (The delimiters will only be used if a
+%given entry contains the separator character.)
+%
+%\DescribeMacro{\DTLsavetexdb}
+%\begin{definition}
+%\cs{DTLsavetexdb}\marg{db name}\marg{filename}
+%\end{definition}
+%This writes the database called \meta{db name} to a \LaTeX\ file
+%called \meta{filename}, where the database is stored as
+%a combination of \ics{DTLnewdb}, \ics{DTLnewrow} and
+%\ics{DTLnewdbentry} commands.
+%
+%\section{Pie Charts (\texorpdfstring{\sty{datapie}}{datapie} package)}
+%
+%The \sty{datapie} package is not loaded by the \sty{datatool} package,
+%so you need to load \sty{datapie} if you want to use any of the
+%commands defined in this section. You will need to have the
+%\sty{pgf}/\sty{tikz} packages installed. The \sty{datapie} package
+%may be given the following options:
+%\begin{description}
+%\item[{\pkgopt[datapie]{color}}] Colour option (default.)
+%\item[{\pkgopt[datapie]{monochrome}}] Monochrome option.
+%\item[{\pkgopt[datapie]{rotateinner}}]
+%Rotate inner labels so that they are aligned
+%with the pie chart radial axis.
+%\item[{\pkgopt[datapie]{norotateinner}}]
+%Don't rotate inner labels (default.)
+%\item[{\pkgopt[datapie]{rotateouter}}]
+%Rotate outer labels so that they are aligned
+%with the pie chart radial axis.
+%\item[{\pkgopt[datapie]{norotateouter}}]
+%Don't rotate outer labels (default.)
+%\end{description}
+%
+%Numerical information contained in a database created by the
+%\sty{datatool} package can be converted into a pie chart using
+%\DescribeMacro{\DTLpiechart}
+%\begin{definition}
+%\cs{DTLpiechart}\oarg{condition}\marg{settings list}\marg{db name}\marg{values}
+%\end{definition}\noindent
+%where \meta{db name} is the name of the database, and
+%\meta{condition} has the same form as the optional argument
+%to \ics{DTLforeach} described in \autoref{sec:dbforeach}. If
+%\meta{condition} is false, that information is omitted from the
+%construction of the pie chart. The argument \meta{values} is a
+%comma separated list of \meta{cmd}"="\meta{key} pairs, the same
+%as that required by the penultimate argument of \ics{DTLforeach}.
+%The \meta{settings list} is a comma separated list of
+%\meta{setting}=\meta{value} pairs, where \meta{setting} can be any of
+%the following:
+%\begin{description}
+%\item[\setting{DTLpiechart}{variable}]
+%This specifies the control sequence to use that
+%contains the value used to construct the pie chart. The control
+%sequence must be one of the control sequences to appear in
+%the assignment list \meta{values}. This setting is required.
+%
+%\item[\setting{DTLpiechart}{start}]
+%This is the starting angle of the first segment. The
+%value is 0 by default.
+%
+%\item[\setting{DTLpiechart}{radius}]
+%This is the radius of the pie chart. The default value
+%is 2cm.
+%
+%\item[\setting{DTLpiechart}{innerratio}]
+%The distance from the centre of the
+%pie chart to the point where the inner labels are placed is given
+%by this value multiplied by the ratio. The default value is 0.5.
+%
+%\item[\setting{DTLpiechart}{outerratio}]
+%The distance from the centre of the
+%pie chart to the point where the outer labels are placed is given
+%by this value multiplied by the ratio. The default value is 1.25.
+%
+%\item[\setting{DTLpiechart}{cutawayratio}]
+%The distance from the centre of the pie chart
+%to the point of cutaway segments is given by this value multiplied
+%by the ratio. The default value is 0.2.
+%
+%\item[\setting{DTLpiechart}{inneroffset}]
+%This is the absolute distance from the centre
+%of the pie chart to the point where the inner labels are placed.
+%You should use only one or other of \setting{DTLpiechart}{innerratio}
+%and \setting{DTLpiechart}{inneroffset}, not both. If you also want to
+%specify the radius, you must use \setting{DTLpiechart}{ratio}
+%before \setting{DTLpiechart}{inneroffset}. If omitted, the inner
+%offset is obtained from the ratio multiplied by the
+%\setting{DTLpiechart}{innerratio} value.
+%
+%\item[\setting{DTLpiechart}{outeroffset}]
+%This is the absolute distance from the centre
+%of the pie chart to the point where the outer labels are placed.
+%You should use only one or other of \setting{DTLpiechart}{outerratio}
+%and \setting{DTLpiechart}{outeroffset}, not both. If you also want to
+%specify the radius, you must use \setting{DTLpiechart}{ratio}
+%before \setting{DTLpiechart}{outeroffset}. If omitted, the outer
+%offset is obtained from the ratio multiplied by the
+%\setting{DTLpiechart}{outerratio} value.
+%
+%\item[\setting{DTLpiechart}{cutawayoffset}]
+%This is the absolute distance from the centre of
+%the pie chart to the point of the cutaway segments. You should use
+%only one or other of \setting{DTLpiechart}{cutawayratio} and
+%\setting{DTLpiechart}{cutawayoffset}, not both. If
+%you also want to specify the radius, you must use
+%\setting{DTLpiechart}{ratio} before
+%\setting{DTLpiechart}{cutawayoffset}. If omitted, the cutaway offset
+%is obtained from the ratio multiplied by the
+%\setting{DTLpiechart}{cutawayratio} value.
+%
+%\item[\setting{DTLpiechart}{cutaway}]
+%This is a list of cutaway segments. This should be
+%a comma separated list of individual numbers, or number ranges
+%(separated by a dash.) For example "cutaway={1,3}" will separate
+%the first and third segments from the rest of the pie chart, offset
+%by the value of the \setting{DTLpiechart}{cutawayoffset} setting,
+%whereas "cutaway={1-3}" will separate the
+%first three segments from the rest of the pie chart. If omitted,
+%the pie chart will be whole.
+%
+%\item[\setting{DTLpiechart}{innerlabel}]
+%The value of this is positioned in the middle of each segment at a
+%distance of \setting{DTLpiechart}{inneroffset} from the centre
+%of the pie chart. The default is the same as the value of
+%\setting{DTLpiechart}{variable}.
+%
+%\item[\setting{DTLpiechart}{outerlabel}]
+%The value of this is positioned at a distance of
+%\setting{DTLpiechart}{outeroffset} from the centre of the pie chart.
+%The default is empty.
+%
+%\item[\setting{DTLpiechart}{rotateinner}] This is a boolean setting,
+%so it can only take the values "true" and "false". If the value is
+%omitted "true" is assumed. If true, the inner labels are rotated
+%along the spokes of the pie chart, otherwise the inner labels are not
+%rotated. There are analogous package options
+%\pkgopt[datapie]{rotateinner} and \pkgopt[datapie]{norotateinner}.
+%
+%\item[\setting{DTLpiechart}{rotateouter}]
+%This is a boolean setting, so it can only take
+%the values "true" and "false". If the value is omitted "true" is
+%assumed. If true, the outer labels are rotated along the spokes of
+%the pie chart, otherwise the outer labels are not rotated.
+%There are analogous package options
+%\pkgopt[datapie]{rotateouter} and \pkgopt[datapie]{norotateouter}.
+%
+%\end{description}
+%
+%\begin{example}{A Pie Chart}{ex:piechart}
+%This example loads data from a file called "fruit.csv" which contains
+%the following:
+%\begin{verbatim}
+%Name,Quantity
+%"Apples",30
+%"Pears",25
+%"Lemons,Limes",40.5
+%"Peaches",34.5
+%"Cherries",20
+%\end{verbatim}
+%First load the data:
+%\begin{verbatim}
+%\DTLloaddb{fruit}{fruit.csv}
+%\end{verbatim}
+%\DTLnewdb{fruit}\relax
+%\DTLnewrow{fruit}\relax
+%\DTLnewdbentry{fruit}{Name}{Apples}\relax
+%\DTLnewdbentry{fruit}{Quantity}{30}\relax
+%\DTLnewrow{fruit}\relax
+%\DTLnewdbentry{fruit}{Name}{Pears}\relax
+%\DTLnewdbentry{fruit}{Quantity}{25}\relax
+%\DTLnewrow{fruit}\relax
+%\DTLnewdbentry{fruit}{Name}{Lemons,Limes}\relax
+%\DTLnewdbentry{fruit}{Quantity}{40.5}\relax
+%\DTLnewrow{fruit}\relax
+%\DTLnewdbentry{fruit}{Name}{Peaches}\relax
+%\DTLnewdbentry{fruit}{Quantity}{34.5}\relax
+%\DTLnewrow{fruit}\relax
+%\DTLnewdbentry{fruit}{Name}{Cherries}\relax
+%\DTLnewdbentry{fruit}{Quantity}{20}\relax
+%Now create a pie chart in a figure:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{A pie chart}
+%\end{figure}
+%\end{verbatim}
+%This creates \autoref{fig:piechart}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{A pie chart}
+%\label{fig:piechart}
+%\end{figure}
+%
+%There are no outer labels by default, but they can be set
+%using the \setting{DTLpiechart}{outerlabel} setting.
+%The following sets the outer label to the value of the "Name" key:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A pie chart (outer labels set)}
+%\end{figure}
+%\end{verbatim}
+%This creates \autoref{fig:piechartouter}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name}{fruit}
+%{\name=Name,\quantity=Quantity}
+%\caption{A pie chart (outer labels set)}
+%\label{fig:piechartouter}
+%\end{figure}
+%
+%You may prefer the labels to be rotated. The following
+%switches on the rotation for the inner and outer labels:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name,%
+%rotateinner,rotateouter}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A pie chart (rotation enabled)}
+%\end{figure}
+%\end{verbatim}
+%This creates \autoref{fig:piechartrot}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name
+%,rotateinner,rotateouter}{fruit}
+%{\name=Name,\quantity=Quantity}
+%\caption{A pie chart (rotation enabled)}
+%\label{fig:piechartrot}
+%\end{figure}
+%\end{example}
+%
+%\begin{example}{Separating Segments from the Pie Chart}{ex:cutaway}
+%You may want to separate one or more segments from the pie chart,
+%perhaps to emphasize them. You can do this using the
+%\setting{DTLpiechart}{cutaway}
+%setting. The following separates the first and third segments
+%from the pie chart:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name,%
+%cutaway={1,3}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A pie chart with cutaway segments}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:piecutaway}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name
+%,cutaway={1,3}}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{A pie chart with cutaway segments}
+%\label{fig:piecutaway}
+%\end{figure}
+%
+%Alternatively I can specify a range of segments. The following
+%separates the first two segments:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name,%
+%cutaway={1-2}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1-2\}})}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:piecutaway2}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name
+%,cutaway={1-2}}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1-2\}})}
+%\label{fig:piecutaway2}
+%\end{figure}
+%
+%Notice the difference between \autoref{fig:piecutaway2} and
+%\autoref{fig:piecutaway3} which was produced using:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name,%
+%cutaway={1,2}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1,2\}})}
+%\end{figure}
+%\end{verbatim}
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name
+%,cutaway={1,2}}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1,2\}})}
+%\label{fig:piecutaway3}
+%\end{figure}
+%
+%\end{example}
+%
+%\subsection{Pie Chart Variables}
+%
+%\DescribeMacro{\DTLpievariable}
+%\begin{definition}
+%\cs{DTLpievariable}
+%\end{definition}
+%This command is set to the variable given by the
+%\setting{DTLpiechart}{variable} setting in the \meta{settings list}
+%argument of \cs{DTLpiechart}. The \setting{DTLpiechart}{innerlabel}
+%is set to \cs{DTLpievariable} by default.
+%
+%\DescribeMacro{\DTLpiepercent}
+%\begin{definition}
+%\cs{DTLpiepercent}
+%\end{definition}
+%This command is set to the percentage value of \cs{DTLpievariable}.
+%The percentage value is rounded to \meta{n} digits, where \meta{n}
+%is the value of the \LaTeX\ counter
+%\counterfmt{DTLpieroundvar}.
+%
+%\begin{example}{Changing the Inner and Outer Labels}{ex:pielabels}
+%This example uses the database defined in \autoref{ex:piechart}.
+%The inner label is now set to the percentage value, rather than
+%the actual value, and the outer label is set to the name with
+%the actual value in parentheses.
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,%
+%innerlabel={\DTLpiepercent\%},%
+%outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A pie chart (changing the labels)}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:piechartlabels}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
+%\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A pie chart (changing the labels)}
+%\label{fig:piechartlabels}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Pie Chart Label Formatting}
+%
+%\DescribeMacro{\DTLdisplayinnerlabel}
+%\begin{definition}
+%\cs{DTLdisplayinnerlabel}\marg{text}
+%\end{definition}
+%This governs how the inner label is formatted, where \meta{text}
+%is the text of the inner label. The default is to just do \meta{text}.
+%
+%\DescribeMacro{\DTLdisplayouterlabel}
+%\begin{definition}
+%\cs{DTLdisplayouterlabel}\marg{text}
+%\end{definition}
+%This governs how the outer label is formatted, where \meta{text}
+%is the text of the outer label. The default is to just do \meta{text}.
+%
+%\begin{example}{Changing the Inner and Outer Label
+%Format}{ex:pielabelformat}
+%This example extends \autoref{ex:pielabels}.
+%The inner and outer labels are now both typeset in a sans-serif
+%font:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+%\renewcommand*{\DTLdisplayouterlabel}[1]{\textsf{#1}}
+%\DTLpiechart{variable=\quantity,%
+%innerlabel={\DTLpiepercent\%},%
+%outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A pie chart (changing the label format)}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:piechartlabelformat}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+%\renewcommand*{\DTLdisplayouterlabel}[1]{\textsf{#1}}
+%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
+%\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A pie chart (changing the label format)}
+%\label{fig:piechartlabelformat}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Pie Chart Colours}
+%
+%The \sty{datapie} package predefines colours for the first
+%eight segments of the pie chart. If you require more than
+%eight segments, you will need to use
+%\DescribeMacro{\DTLsetpiesegmentcolor}
+%\begin{definition}
+%\cs{DTLsetpiesegmentcolor}\marg{n}\marg{color}
+%\end{definition}\noindent
+%to set the colours for any additional segments, or you can use
+%it to change the default colours. The first argument \meta{n}
+%is the segment index (starting from 1), and the second argument
+%\meta{color} is a colour specifier as used in commands such as
+%\cs{color}.
+%
+%\DescribeMacro{\DTLdopiesegmentcolor}
+%\begin{definition}
+%\cs{DTLdopiesegmentcolor}\meta{n}
+%\end{definition}
+%This sets the current text colour to that of the \meta{n}th
+%segment.
+%
+%\DescribeMacro{\DTLdocurrentpiesegmentcolor}
+%\begin{definition}
+%\cs{DTLdocurrentpiesegmentcolor}
+%\end{definition}
+%This sets the current text colour to that of the current pie
+%segment. This command may only be used within a pie chart, or
+%within the body of \ics{DTLforeach}.
+%
+%\DescribeMacro{\DTLpieoutlinecolor}
+%\begin{definition}
+%\cs{DTLpieoutlinecolor}
+%\end{definition}
+%This sets the outline colour for the pie chart. The default is
+%black.
+%
+%\DescribeMacro{\DTLpieoutlinewidth}
+%\begin{definition}
+%\cs{DTLpieoutlinewidth}
+%\end{definition}
+%This is a length that governs the line width of the outline. The
+%default value is 0pt, but can be changed using \cs{setlength}.
+%The outline is only drawn if \cs{DTLpieoutlinewidth} is greater
+%than 0pt.
+%
+%\begin{example}{Pie Segment Colours}{ex:piecolours}
+%This example extends \autoref{ex:pielabelformat}.
+%It sets the outline thickness to 2pt, and
+%the outer label is now set in the same colour as the fill colour
+%of the segment to which it belongs.
+%In addition, a legend is created using
+%\ics{DTLforeach}.
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\setlength{\DTLpieoutlinewidth}{2pt}
+%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+%\renewcommand*{\DTLdisplayouterlabel}[1]{%
+%\DTLdocurrentpiesegmentcolor
+%\textsf{\shortstack{#1}}}
+%\DTLpiechart{variable=\quantity,%
+%innerlabel={\DTLpiepercent\%},%
+%outerlabel={\name\\(\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\begin{tabular}[b]{ll}
+%\DTLforeach{fruit}{\name=Name}{\DTLiffirstrow{}{\\}%
+%\DTLdocurrentpiesegmentcolor\rule{10pt}{10pt} &
+%\name
+%}
+%\end{tabular}
+%\caption{A pie chart (using segment colours and outline)}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:piesegcolour}. (The format of the
+%outer label has been changed to use \cs{shortstack} to
+%prevent the outer labels from taking up so much horizontal
+%space. The \setting{DTLpiechart}{outerlabel} setting has also been
+%modified to use "\\" after the name to move the percentage value onto
+%the next row.)
+%
+%\begin{figure}[htbp]
+%\centering
+%\setlength{\DTLpieoutlinewidth}{2pt}
+%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+%\renewcommand*{\DTLdisplayouterlabel}[1]{\relax
+%\DTLdocurrentpiesegmentcolor
+%\textsf{\shortstack{#1}}}
+%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
+%\%},outerlabel={\name\\(\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\begin{tabular}[b]{ll}
+%\DTLforeach{fruit}{\name=Name}{\DTLiffirstrow{}{\\}\relax
+%\DTLdocurrentpiesegmentcolor\rule{10pt}{10pt} &
+%\name
+%}
+%\end{tabular}
+%\caption{A pie chart (using segment colours and outline)}
+%\label{fig:piesegcolour}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Adding Extra Commands Before and After the Pie Chart}
+%
+%The pie charts created using \ics{DTLpiechart} are placed inside
+%a \env{tikzpicture} environment (defined by the \sty{tikz} package.)
+%
+%\DescribeMacro{\DTLpieatbegintikz}
+%\begin{definition}
+%\cs{DTLpieatbegintikz}
+%\end{definition}
+%The macro \cs{DTLpieatbegintikz} is called at the start of the
+%\env{tikzpicture} environment, allowing you to change the
+%\env{tikzpicture} settings. By default \cs{DTLpieatbegintikz}
+%does nothing, but you can redefine it to, say, scale the pie
+%chart.
+%
+%\DescribeMacro{\DTLpieatendtikz}
+%\begin{definition}
+%\cs{DTLpieatendtikz}
+%\end{definition}
+%The macro \cs{DTLpieatendtikz} is called at the end of the
+%\env{tikzpicture} environment, allowing you add additional
+%graphics to the pie chart. This does nothing by default.
+%
+%\begin{example}{Adding Information to the Pie Chart}{ex:piescale}
+%This example modifies \autoref{ex:piechart}. It redefines
+%\cs{DTLpieatendtikz} to add an annotated arrow.
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{An annotated pie chart}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:pieannote}. (Note that the centre
+%of the pie chart is the origin of the TikZ picture.)
+%
+%\begin{figure}[htbp]
+%\centering
+%\renewcommand*{\DTLpieatendtikz}{%
+%\draw[<-] (45:1.5cm) -- (40:2.5cm)node[right]{Apples};}
+%\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{An annotated pie chart}
+%\label{fig:pieannote}
+%\end{figure}
+%\end{example}
+%
+%\section{Scatter and Line Plots (\texorpdfstring{\sty{dataplot}}{dataplot}
+%package)}
+%
+%The \sty{dataplot} package provides commands for creating
+%scatter or line plots from databases. It uses the pgf/TikZ plot
+%handler library to create the plots. See the \sty{pgf} manual for
+%more detail on pgf streams and plot handles. The \sty{dataplot}
+%package is not loaded by \sty{datatool} so if you want to use
+%it you need to load it explicitly using "\usepackage{dataplot}".
+%
+%\DescribeMacro{\DTLplot}
+%\begin{definition}
+%\cs{DTLplot}\oarg{condition}\marg{db list}\marg{settings}
+%\end{definition}
+%This command creates a plot (inside a \env{tikzpicture} environment)
+%of all the data given in the databases listed in \meta{db list},
+%which should be a comma separated list of database names.
+%The optional argument \meta{condition} is the same as that for
+%\ics{DTLforeach}. The \meta{settings} argument is a comma separated
+%list of \meta{setting}"="\meta{value} pairs. There are two settings
+%that must be specified \setting{DTLplot}{x} and \setting{DTLplot}{y}.
+%The other settings are optional. Note that any value that contains
+%a comma, must be enclosed in braces. For example
+%"colors={red,cyan,blue}". Note where any setting requires
+%a number, or list of numbers (such as \setting{DTLplot}{bounds})
+%the number must be supplied in standard decimal notation (i.e.\
+%no currency, no number groups, and a full stop as the decimal
+%point.) Available settings are as follows:
+%\begin{description}
+%\item[\setting{DTLplot}{x}] The database key
+%that specifies the $x$ co-ordinates. This setting is required.
+%
+%\item[\setting{DTLplot}{y}] The database key that specifies
+%the $y$ co-ordinates. This setting is required.
+%
+%\item[\setting{DTLplot}{markcolors}] A comma separated list of colour
+%names for the markers. An empty value will use the current colour.
+%
+%\item[\setting{DTLplot}{linecolors}] A comma separated list of colour
+%names for the plot lines. An empty value will use the current colour.
+%
+%\item[\setting{DTLplot}{colors}] A comma separated list of colour
+%names for the lines and markers.
+%
+%\item[\setting{DTLplot}{marks}] A comma separated list of
+%code to generate plot marks. (This should typically be a list
+%of \cs{pgfuseplotmark} commands, see the \sty{pgf} manual for
+%further details.) You may use \cs{relax} as an element
+%of the list to suppress markers for the corresponding plot.
+%For example: "marks={\pgfuseplotmark{o},\relax}" will use an
+%open circle marker for the first database, and no markers for the
+%second database listed in \meta{db list}.
+%
+%\item[\setting{DTLplot}{lines}] A comma separated list of
+%line style settings. (This should typically be a list of
+%\cs{pgfsetdash} commands, see the \sty{pgf} manual for
+%further details on how to set the line style.) An empty value
+%will use the current line style.
+%You may use \cs{relax} as an element
+%of the list to suppress line for the corresponding plot.
+%For example: "lines={\relax,\pgfsetdash{}{0pt}}"
+%will have no lines for the first database, and a solid line
+%for the second database listed in \meta{db list}.
+%
+%\item[\setting{DTLplot}{width}] The width of the plot. This must
+%be a length. The plot width does not include outer tick marks or
+%labels.
+%
+%\item[\setting{DTLplot}{height}] The height of the plot. This must
+%be a length. The plot height does not include outer tick marks
+%or labels.
+%
+%\item[\setting{DTLplot}{style}] This setting governs whether
+%to use lines or markers in the plot, and may take one of
+%the following values: "both" (lines and markers),
+%"lines" (only lines) or "markers" (only markers.) The default is
+%"markers".
+%
+%\item[\setting{DTLplot}{axes}] This setting governs whether
+%to display the axes, and may take one of
+%the following values: "both", "x", "y" or "none". If no value
+%is specified, "both" is assumed.
+%
+%\item[\setting{DTLplot}{box}] This setting governs whether
+%or not to surround the plot in a box. It is a boolean setting,
+%taking only the values "true" and "false". If no value is
+%specified, "true" is assumed.
+%
+%\item[\setting{DTLplot}{xtics}] This setting governs whether
+%or not to display the $x$ tick marks. It is a boolean setting,
+%taking only the values "true" and "false". If no value is
+%specified "true" is assumed. If the \setting{DTLplot}{axes}
+%setting is set to "both" or "x", this value will automatically
+%be set to "true", otherwise it will be set to "false".
+%
+%\item[\setting{DTLplot}{ytics}] This setting governs whether
+%or not to display the $y$ ticks. It is a boolean setting,
+%taking only the values "true" and "false". If no value is
+%specified "true" is assumed. If the \setting{DTLplot}{axes}
+%setting is set to "both" or "y", this value will automatically
+%be set to "true", otherwise it will be set to "false".
+%
+%
+%\item[\setting{DTLplot}{xminortics}] This setting governs whether
+%or not to display the $x$ minor tick marks. It is a boolean
+%setting, taking only the values "true" and "false". If no value is
+%specified "true" is assumed. This setting also sets the
+%$x$ major tick marks on if the value is "true".
+%
+%\item[\setting{DTLplot}{yminortics}] This setting governs whether
+%or not to display the $y$ minor tick marks. It is a boolean
+%setting, taking only the values "true" and "false". If no value is
+%specified "true" is assumed. This setting also sets the
+%$y$ major tick marks on if the value is "true".
+%
+%\item[\setting{DTLplot}{xticdir}] This sets the $x$ tick direction,
+%and may only take the values "in" or "out".
+%
+%\item[\setting{DTLplot}{yticdir}] This sets the $y$ tick direction,
+%and may only take the values "in" or "out".
+%
+%\item[\setting{DTLplot}{ticdir}] This sets the $x$ and $y$ tick
+%direction, and may only take the values "in" or "out".
+%
+%\item[\setting{DTLplot}{bounds}] The value must be in the form
+%\meta{min x}","\meta{min y}","\meta{max x}","\meta{max y}. This
+%sets the graph bounds to the given values. If omitted the
+%bounds are computed from the maximum and minimum values of the
+%data. For example
+%\begin{verbatim}
+%\DTLplot{data1,data2}{x=Height,y=Weight,bounds={0,0,10,20}}
+%\end{verbatim}
+%Note that the \setting{DTLplot}{bounds} setting overrides
+%the \setting{DTLplot}{minx}, \setting{DTLplot}{maxx},
+%\setting{DTLplot}{miny} and \setting{DTLplot}{maxy} settings.
+%
+%\item[\setting{DTLplot}{minx}] The value is the minimum value
+%of the $x$ axis.
+%
+%\item[\setting{DTLplot}{miny}] The value is the minimum value
+%of the $y$ axis.
+%
+%\item[\setting{DTLplot}{maxx}] The value is the maximum value
+%of the $x$ axis.
+%
+%\item[\setting{DTLplot}{maxy}] The value is the maximum value
+%of the $y$ axis.
+%
+%\item[\setting{DTLplot}{xticpoints}] The value must be a comma
+%separated list of decimal numbers indicating where to put the
+%$x$ tick marks. If omitted, the $x$ tick marks are placed at
+%equal intervals along the $x$ axis such that each interval is
+%not less than the length given by \ics{DTLmintickgap}.
+%This setting overrides \setting{DTLplot}{xticgap}.
+%
+%\item[\setting{DTLplot}{xticgap}] This value specifies the
+%gap between the $x$ tick marks.
+%
+%\item[\setting{DTLplot}{yticpoints}] The value must be a comma
+%separated list of decimal numbers indicating where to put the
+%$y$ tick marks. If omitted, the $y$ tick marks are placed at
+%equal intervals along the $y$ axis such that each interval is
+%not less than the length given by \ics{DTLmintickgap}.
+%This setting overrides \setting{DTLplot}{yticgap}.
+%
+%\item[\setting{DTLplot}{yticgap}] This value specifies the
+%gap between the $y$ tick marks.
+%
+%\item[\setting{DTLplot}{grid}] This is a boolean value that
+%specifies whether or not to display the grid. If no value
+%is given, "true" is assumed. The minor grid lines are only
+%displayed if the minor tick marks are set.
+%
+%\item[\setting{DTLplot}{xticlabels}] The value must be a comma
+%separated list of labels for each $x$ tick mark. If omitted,
+%the labels are the value of the $x$ tick position, rounded
+%\meta{n} digits after the decimal point, where \meta{n} is
+%given by the value of the counter \counterfmt{DTLplotroundXvar}.
+%
+%\item[\setting{DTLplot}{yticlabels}] The value must be a comma
+%separated list of labels for each $y$ tick mark. If omitted,
+%the labels are the value of the $y$ tick position, rounded
+%\meta{n} digits after the decimal point, where \meta{n} is
+%given by the value of the counter \counterfmt{DTLplotroundYvar}.
+%
+%\item[\setting{DTLplot}{xlabel}] The value is the label for
+%the $x$ axis. If omitted, the axis has no label.
+%
+%\item[\setting{DTLplot}{ylabel}] The value is the label for
+%the $y$ axis. If omitted, the axis has no label.
+%
+%\item[\setting{DTLplot}{legend}] This setting governs whether
+%or not to display the legend, and where it should be displayed.
+%It may take one of the following values "none" (don't display
+%the legend), "north", "northeast", "east", "southeast", "south",
+%"southwest", "west" or "northwest". If the value is omitted,
+%"northeast" is assumed.
+%
+%\item[\setting{DTLplot}{legendlabels}] The value must be a comma
+%separated list of labels for the legend. If omitted, the database
+%names are used.
+%
+%\end{description}
+%
+%\begin{example}{A Basic Graph}{ex:basicplot}
+%Suppose you have a file called "groupa.csv" that contains the
+%following:
+%\DTLnewdb{groupa}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.55}\relax
+%\DTLnewdbentry{groupa}{Weight}{45.4}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.54}\relax
+%\DTLnewdbentry{groupa}{Weight}{48.0}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.56}\relax
+%\DTLnewdbentry{groupa}{Weight}{58.0}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.56}\relax
+%\DTLnewdbentry{groupa}{Weight}{50.2}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.57}\relax
+%\DTLnewdbentry{groupa}{Weight}{46.0}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.58}\relax
+%\DTLnewdbentry{groupa}{Weight}{48.3}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.59}\relax
+%\DTLnewdbentry{groupa}{Weight}{56.5}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.59}\relax
+%\DTLnewdbentry{groupa}{Weight}{58.1}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.60}\relax
+%\DTLnewdbentry{groupa}{Weight}{60.9}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.62}\relax
+%\DTLnewdbentry{groupa}{Weight}{56.3}\relax
+%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+%Height,Weight
+%\DTLforeach{groupa}{\x=Height,\y=Weight}{\x,\y
+%}\end{ttfamily}\par\noindent
+%First load this into a database called "groupa":
+%\begin{verbatim}
+%\DTLloaddb{groupa}{groupa.csv}
+%\end{verbatim}
+%The data can now be converted into a scatter plot as follows:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa}{x=Height,y=Weight}
+%\caption{A scatter plot}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:basicplot}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa}{x=Height,y=Weight}
+%\caption{A scatter plot}
+%\label{fig:basicplot}
+%\end{figure}
+%
+%Alternatively, you can use the \setting{DTLplot}{style} setting
+%to change it into a line plot:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa}{x=Height,y=Weight,style=lines}
+%\caption{A line plot}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:basiclineplot}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa}{x=Height,y=Weight,style=lines}
+%\caption{A line plot}
+%\label{fig:basiclineplot}
+%\end{figure}
+%\end{example}
+%
+%\begin{example}{Plotting Multiple Data Sets}{ex:2db}
+%In this example, I shall use the database called "groupa" defined
+%in \autoref{ex:basicplot}, and another database called "groupb"
+%which is loaded from the file "groupb.csv" which contains the
+%following:
+%\DTLnewdb{groupb}
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.54}\relax
+%\DTLnewdbentry{groupb}{Weight}{48.4}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.54}\relax
+%\DTLnewdbentry{groupb}{Weight}{42.0}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.55}\relax
+%\DTLnewdbentry{groupb}{Weight}{64.0}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.56}\relax
+%\DTLnewdbentry{groupb}{Weight}{58.2}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.56}\relax
+%\DTLnewdbentry{groupb}{Weight}{49.0}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.57}\relax
+%\DTLnewdbentry{groupb}{Weight}{40.3}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.58}\relax
+%\DTLnewdbentry{groupb}{Weight}{51.5}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.58}\relax
+%\DTLnewdbentry{groupb}{Weight}{63.1}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.59}\relax
+%\DTLnewdbentry{groupb}{Weight}{74.9}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.59}\relax
+%\DTLnewdbentry{groupb}{Weight}{59.3}\relax
+%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+%Height,Weight
+%\DTLforeach{groupb}{\x=Height,\y=Weight}{\x,\y
+%}\end{ttfamily}\par\noindent
+%First load this into a database called "groupb":
+%\begin{verbatim}
+%\DTLloaddb{groupb}{groupb.csv}
+%\end{verbatim}
+%I can now plot both groups in the same graph, but I want a smaller
+%graph than \autoref{fig:basicplot} and \autoref{fig:basiclineplot},
+%so I am going to set the plot width and height to 3in:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa,groupb}{x=Height,y=Weight,width=3in,height=3in}
+%\caption{A scatter plot}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:2db}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa,groupb}{x=Height,y=Weight,width=3in,height=3in}
+%\caption[A scatter plot (multiple datasets)]{A scatter plot}
+%\label{fig:2db}
+%\end{figure}
+%
+%Now let's add a legend using the \setting{DTLplot}{legend} setting,
+%with the legend labels "Group A" and "Group B",
+%and set the $x$ tick intervals using \setting{DTLplot}{xticpoints}
+%setting. I am also going to set the $x$ axis label to
+%"Height (m)" and the $y$ axis label to "Weight (kg)", and place
+%a box around the plot.
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa,groupb}{x=Height,y=Weight,
+%width=3in,height=3in,legend,legendlabels={Group A,Group B},
+%xlabel={Height (m)},ylabel={Weight (kg)},box,
+%xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}}
+%\caption{A scatter plot}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:legend}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa,groupb}{x=Height,y=Weight,legend,
+%width=3in,height=3in,legendlabels={Group A,Group B},
+%xlabel={Height (m)},ylabel={Weight (kg)},box,
+%xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}}
+%\caption[A scatter plot (with a legend)]{A scatter plot}
+%\label{fig:legend}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Adding Information to the Plot}
+%
+%The \sty{datatool} package provides two hooks used at the beginning
+%and end of the \env{tikzpicture} environment:
+%\DescribeMacro{\DTLplotatbegintikz}
+%\begin{definition}
+%\cs{DTLplotatbegintikz}
+%\end{definition}\noindent
+%and
+%\DescribeMacro{\DTLplotatendtikz}
+%\begin{definition}
+%\cs{DTLplotatendtikz}
+%\end{definition}
+%They are both defined to do nothing by default, but can be redefined
+%to add commands to the image. The unit vectors are set prior to
+%using these hooks, so you can use the same co-ordinates as those
+%in the data sets.
+%
+%\DescribeMacro{\DTLaddtoplotlegend}
+%\begin{definition}
+%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{text}
+%\end{definition}
+%This adds a new row to the plot legend where \meta{marker} is
+%code to produce the marker, \meta{line style} is code to set
+%the line style and \meta{text} is a textual label. You can
+%use \cs{relax} to suppress the marker or line. For example:
+%\begin{verbatim}
+%\DTLaddtoplotlegend{\pgfuseplotmark{x}}{\relax}{Some Data}
+%\end{verbatim}
+%Note that the legend is plotted before \cs{DTLplotatendtikz},
+%so if you want to add information to the legend you will need
+%to do the in \cs{DTLplotatstarttikz}.
+%
+%\begin{example}{Adding Information to a Plot}{ex:addtoplot}
+%Returning to the plots created in \autoref{ex:2db}, suppose
+%I now want to annotate the plot, say I want to draw your notice
+%to a particular point, say the point (1.58,48.3), then I can
+%redefine \cs{DTLplotatendtikz} to draw an annotated arrow to
+%that point:
+%\begin{verbatim}
+%\renewcommand*{\DTLplotatendtikz}{%
+%\draw[<-,line width=1pt] (1.58,48.3) -- (1.6,43)
+% node[below]{interesting point};
+%}
+%\end{verbatim}
+%So \autoref{fig:legend} now looks like \autoref{fig:annote}.
+%(Obviously, \cs{DTLplotatendtikz} needs to be redefined before
+%using \cs{DTLplot}.)
+%
+%\begin{figure}[htbp]
+%\renewcommand*{\DTLplotatendtikz}{%
+%\draw[<-,line width=1pt] (1.58,48.3) -- (1.6,43)
+% node[below]{interesting point};
+%}
+%\centering
+%\DTLplot{groupa,groupb}{x=Height,y=Weight,legend,
+%width=3in,height=3in,legendlabels={Group A,Group B},box,
+%xlabel={Height (m)},ylabel={Weight (kg)},
+%xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}}
+%\caption[A scatter plot (using the end plot hook to annotate the
+%plot)]{A scatter plot}
+%
+%\label{fig:annote}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Global Plot Settings}
+%
+%\subsubsection{Lengths}
+%This section describes the lengths that govern the appearance of
+%the plot created using \ics{DTLplot}. These lengths can be
+%changed using \cs{setlength}.
+%
+%\DescribeMacro{\DTLplotwidth}
+%\begin{definition}
+%\cs{DTLplotwidth}
+%\end{definition}
+%This length governs the length of the $x$ axis. Note that the plot
+%width does not include any outer tick marks or labels. The default
+%value is 4in.
+%
+%\DescribeMacro{\DTLplotheight}
+%\begin{definition}
+%\cs{DTLplotheight}
+%\end{definition}
+%This length governs the length of the $y$ axis. Note that the plot
+%height does not include any outer tick marks or labels. The default
+%value is 4in
+%
+%\DescribeMacro{\DTLticklength}
+%\begin{definition}
+%\cs{DTLticklength}
+%\end{definition}
+%This governs the length of the tick marks. The default value is
+%5pt.
+%
+%\DescribeMacro{\DTLminorticklength}
+%\begin{definition}
+%\cs{DTLminorticklength}
+%\end{definition}
+%This governs the length of the minor tick marks. The default value is
+%2pt.
+%
+%\DescribeMacro{\DTLticklabeloffset}
+%\begin{definition}
+%\cs{DTLticklabeloffset}
+%\end{definition}
+%This governs the distance from the axis to the tick labels. The
+%default value is 8pt.
+%
+%\DescribeMacro{\DTLmintickgap}
+%\begin{definition}
+%\cs{DTLmintickgap}
+%\end{definition}
+%This is the minimum distance allowed between tick marks. If the
+%plot width or height is less than this distance there will only
+%be tick marks at either end of the axis. The default value is
+%20pt.
+%
+%\DescribeMacro{\DTLlegendxoffset}
+%\begin{definition}
+%\cs{DTLlegendxoffset}
+%\end{definition}
+%This is the horizontal distance from the border of the plot to the
+%outer border of the legend. The default value is 10pt.
+%
+%\DescribeMacro{\DTLlegendyoffset}
+%\begin{definition}
+%\cs{DTLlegendyoffset}
+%\end{definition}
+%This is the vertical distance from the border of the plot to the
+%outer border of the legend. The default value is 10pt.
+%
+%\subsubsection{Counters}
+%These counters govern the appearance of plots
+%created using \ics{DTLplot}. The value of the counters can be
+%changed using \cs{setcounter}.
+%
+%\begin{definition}
+%\counterfmt{DTLplotroundXvar}
+%\end{definition}
+%Unless you specify your own tick labels, the $x$ tick labels will
+%be given by the tick points rounded to \meta{n} digits after the
+%decimal point, where \meta{n} is the value of the counter
+%\counterfmt{DTLplotroundXvar}.
+%
+%\begin{definition}
+%\counterfmt{DTLplotroundYvar}
+%\end{definition}
+%Unless you specify your own tick labels, the $y$ tick labels will
+%be given by the tick points rounded to \meta{n} digits after the
+%decimal point, where \meta{n} is the value of the counter
+%\counterfmt{DTLplotroundYvar}.
+%
+%\subsubsection{Macros}
+%These macros govern the appearance of plots created using
+%\ics{DTLplot}. They can be changed using \cs{renewcommand}.
+%
+%\DescribeMacro{\DTLplotmarks}
+%\begin{definition}
+%\cs{DTLplotmarks}
+%\end{definition}
+%This must be a comma separated list of \sty{pgf} code to create the
+%plot marks. \ics{DTLplot} cycles through this list for each
+%database listed. The \sty{pgf} package provides convenient commands
+%for generating plots using \cs{pgfuseplotmark}. See the \sty{pgf}
+%manual for more details.
+%
+%\DescribeMacro{\DTLplotmarkcolors}
+%\begin{definition}
+%\cs{DTLplotmarkcolors}
+%\end{definition}
+%This must be a comma separated list of defined colours to apply to the
+%plot marks. \ics{DTLplot} cycles through this list for each database
+%listed. If this macro is set to empty, the current colour will
+%be used instead.
+%
+%\DescribeMacro{\DTLplotlines}
+%\begin{definition}
+%\cs{DTLplotlines}
+%\end{definition}
+%This must be a comma separated list of \sty{pgf} code to set the
+%style of the plot lines. \ics{DTLplot} cycles through this list for
+%each database listed. Dash patterns can be set using \cs{pgfsetdash},
+%see the \sty{pgf} manual for more details. If \cs{DTLplotlines} is
+%set to empty the current line style will be used instead.
+%
+%\DescribeMacro{\DTLplotlinecolors}
+%\begin{definition}
+%\cs{DTLplotlinecolors}
+%\end{definition}
+%This must be a comma separated list of defined colours to apply to the
+%plot lines. \cs{DTLplot} cycles through this list for each database
+%listed. If this macro is set to empty, the current colour will
+%be used instead. The default is the same as \cs{DTLplotmarkcolors}.
+%
+%\DescribeMacro{\DTLXAxisStyle}
+%\begin{definition}
+%\cs{DTLxaxisstyle}
+%\end{definition}
+%This governs the style of the $x$ axis. It is passed as the optional
+%argument to the TikZ \cs{draw} command. By default it is just "-"
+%which is a solid line style with no start or end arrows. The $x$
+%axis line starts from the bottom left corner of the plot and extends
+%to the bottom right corner of the plot. So if you want the $x$ axis
+%to have an arrow head at the right end, you can do:
+%\begin{verbatim}
+%\renewcommand*{\DTLXAxisStyle}{->}
+%\end{verbatim}
+%
+%\DescribeMacro{\DTLYAxisStyle}
+%\begin{definition}
+%\cs{DTLyaxisstyle}
+%\end{definition}
+%This governs the style of the $y$ axis. It is analogous to
+%\cs{DTLxaxisstyle} described above.
+%
+%\DescribeMacro{\DTLmajorgridstyle}
+%\begin{definition}
+%\cs{DTLmajorgridstyle}
+%\end{definition}
+%This specifies the format of the major grid lines.
+%It may be set to any TikZ setting that you can pass to the
+%optional argument of \cs{draw}. The default value is
+%"color=gray,-" which indicates a grey solid line.
+%
+%\DescribeMacro{\DTLminorgridstyle}
+%\begin{definition}
+%\cs{DTLminorgridstyle}
+%\end{definition}
+%This specifies the format of the minor grid lines.
+%It may be set to any TikZ setting that you can pass to the
+%optional argument of \cs{draw}. The default value is
+%"color=gray,loosely dotted" which indicates a grey dotted line.
+%
+%\DescribeMacro{\DTLformatlegend}
+%\begin{definition}
+%\cs{DTLformatlegend}\marg{legend}
+%\end{definition}
+%This formats the entire legend, which is passed as the argument.
+%The default is to set the legend with
+%a white background, a black frame.
+%
+%\subsection{Adding to a Plot Stream}
+%\DescribeMacro{\DTLplotstream}
+%\begin{definition}
+%\cs{DTLplotstream}\oarg{condition}\marg{db name}\marg{x key}\marg{y key}
+%\end{definition}
+%This adds points to a stream from the database called \meta{db name}
+%where the $x$ co-ordinates are given by the key \meta{x key}
+%and the $y$ co-ordinates are given by the key \meta{y key}.
+%(\ics{DTLconverttodecimal} is used to convert locale dependent
+%values to a standard decimal that is recognised by the
+%\sty{pgf} package.)
+%The optional argument \meta{condition} is the same as that
+%for \ics{DTLforeach}.
+%
+%\begin{example}{Adding to a Plot Stream}{ex:plotstream}
+%Suppose you have a CSV file called "data.csv" containing the
+%following:
+%\begin{verbatim}
+%x,y
+%0,0
+%1,1
+%2,0.5
+%1.5,0.3
+%\end{verbatim}
+%\DTLnewdb{data}\relax
+%\DTLnewrow{data}\relax
+%\DTLnewdbentry{data}{x}{0}\relax
+%\DTLnewdbentry{data}{y}{0}\relax
+%\DTLnewrow{data}\relax
+%\DTLnewdbentry{data}{x}{1}\relax
+%\DTLnewdbentry{data}{y}{1}\relax
+%\DTLnewrow{data}\relax
+%\DTLnewdbentry{data}{x}{2}\relax
+%\DTLnewdbentry{data}{y}{0.5}\relax
+%\DTLnewrow{data}\relax
+%\DTLnewdbentry{data}{x}{1.5}\relax
+%\DTLnewdbentry{data}{y}{0.3}\relax
+%First load the file into a database called "data":
+%\begin{verbatim}
+%\DTLloaddb{data}{data.csv}
+%\end{verbatim}
+%Now create a figure containing this data:
+%\begin{verbatim}
+%\begin{figure}[tbhp]
+%\centering
+%\begin{tikzpicture}
+%\pgfplothandlermark{\pgfuseplotmark{o}}
+%\pgfplotstreamstart
+%\DTLplotstream{data}{x}{y}%
+%\pgfplotstreamend
+%\pgfusepath{stroke}
+%\end{tikzpicture}
+%\caption{Adding to a plot stream}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:plotstream}.
+%
+%\begin{figure}[tbhp]
+%\centering
+%\begin{tikzpicture}
+%\pgfplothandlermark{\pgfuseplotmark{o}}
+%\pgfplotstreamstart
+%\DTLplotstream{data}{x}{y}%
+%\pgfplotstreamend
+%\pgfusepath{stroke}
+%\end{tikzpicture}
+%\caption{Adding to a plot stream}
+%\label{fig:plotstream}
+%\end{figure}
+%\end{example}
+%
+%\begin{example}{Plotting Multiple Keys in the Same
+%Database}{ex:multikey}
+%Suppose I have conducted two time to growth experiments. For each
+%experiment, I have recorded the log count at set times, and I have
+%recorded this information in the same data file called, say,
+%"growth.csv" which contains the following:
+%\begin{verbatim}
+%Time,Experiment 1,Experiment 2
+%0,3.73,3.6
+%23,3.67,3.7
+%60,4.9,3.8
+%\end{verbatim}
+%\DTLnewdb{growth}\DTLnewrow{growth}\relax
+%\DTLnewdbentry{growth}{Time}{0}\relax
+%\DTLnewdbentry{growth}{Experiment 1}{3.73}\relax
+%\DTLnewdbentry{growth}{Experiment 2}{3.6}\relax
+%\DTLnewrow{growth}\relax
+%\DTLnewdbentry{growth}{Time}{23}\relax
+%\DTLnewdbentry{growth}{Experiment 1}{3.67}\relax
+%\DTLnewdbentry{growth}{Experiment 2}{3.7}\relax
+%\DTLnewrow{growth}\relax
+%\DTLnewdbentry{growth}{Time}{60}\relax
+%\DTLnewdbentry{growth}{Experiment 1}{4.9}\relax
+%\DTLnewdbentry{growth}{Experiment 2}{3.8}\relax
+%I can load the data into a database using:
+%\begin{verbatim}
+%\DTLloaddb{growth}{growth.csv}
+%\end{verbatim}
+%However, I'd like to plot both results on the same graph. Since they
+%are contained in the same database, I can't use the method I used
+%in \autoref{ex:2db}. Instead I can use a combination of
+%\ics{DTLplot} and \ics{DTLplotstream}:
+%\begin{verbatim}
+%\begin{figure}[tbhp]
+%\centering
+% % computer bounds
+%\DTLminforkeys{growth}{Time}{\minX}
+%\DTLminforkeys{growth}{Experiment 1,Experiment 2}{\minY}
+%\DTLmaxforkeys{growth}{Time}{\maxX}
+%\DTLmaxforkeys{growth}{Experiment 1,Experiment 2}{\maxY}
+% % round x tick labels
+%\setcounter{DTLplotroundXvar}{0}
+% % redefine \DTLplotatbegintikz to plot the data for Experiment 1
+%\renewcommand*{\DTLplotatbegintikz}{%
+% % set plot mark
+%\pgfplothandlermark{\color{green}\pgfuseplotmark{x}}
+% % start plot stream
+%\pgfplotstreamstart
+% % add data from Experiment 1 to plot stream
+%\DTLplotstream{growth}{Time}{Experiment 1}%
+% % end plot stream
+%\pgfplotstreamend
+% % stroke path
+%\pgfusepath{stroke}
+% % add information to legend (no line is require so use \relax)
+%\DTLaddtoplotlegend{\color{green}%
+%\pgfuseplotmark{x}}{\relax}{Experiment 1}
+%}
+% % now plot the data for Experiment 2
+%\DTLplot{growth}{x=Time,y=Experiment 2,legend,
+%width=3in,height=3in,bounds={\minX,\minY,\maxX,\maxY},
+%xlabel={Time},ylabel={Log Count},
+%legendlabels={Experiment 2}}
+%\caption{Time to growth data}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:multikey}.
+%Notes:
+%\begin{itemize}
+%\item I redefined \ics{DTLplotatbegintikz} in order to add
+%the new plot to the legend, since \ics{DTLplotatendtikz} is
+%used after the legend is plotted. The $x$ and $y$ unit vectors
+%are set before \ics{DTLplotatbegintikz} so I don't need to
+%worry about the co-ordinates.
+%\item I set the counter \counterfmt{DTLplotroundXvar} to zero
+%otherwise the $x$ axis would have looked too cluttered.
+%\item I have used \ics{DTLminforkeys} and \ics{DTLmaxforkeys} to
+%determine the bounds since \ics{DTLplot} won't take the data
+%for Experiment 1 into account when computing the bounds.
+%\end{itemize}
+%
+%\begin{figure}[htbp]
+%\DTLminforkeys{growth}{Time}{\minX}
+%\DTLminforkeys{growth}{Experiment 1,Experiment 2}{\minY}
+%\DTLmaxforkeys{growth}{Time}{\maxX}
+%\DTLmaxforkeys{growth}{Experiment 1,Experiment 2}{\maxY}
+%\setcounter{DTLplotroundXvar}{0}
+%\renewcommand*{\DTLplotatbegintikz}{%
+%\pgfplothandlermark{\color{green}\pgfuseplotmark{x}}
+%\pgfplotstreamstart
+%\DTLplotstream{growth}{Time}{Experiment 1}%
+%\pgfplotstreamend
+%\pgfusepath{stroke}
+%\DTLaddtoplotlegend{\color{green}\pgfuseplotmark{x}}{\relax}{Experiment 1}
+%}
+%\centering
+%\DTLplot{growth}{x=Time,y=Experiment 2,legend,
+%width=3in,height=3in,bounds={\minX,\minY,\maxX,\maxY},
+%xlabel={Time},ylabel={Log Count},
+%legendlabels={Experiment 2}}
+%\caption[Time to growth data (plotting from the same database using
+%different keys)]{Time to growth data}
+%\label{fig:multikey}
+%\end{figure}
+%\end{example}
+%
+%\section{Bar Charts (\texorpdfstring{\sty{databar}}{databar}
+%package)}
+%
+%The \sty{databar} package provides commands for creating bar charts.
+%It is not loaded by the \sty{datatool} package, so if you want to
+%use it you will need to load it explicitly using
+%"\usepackage{databar}".
+%
+%Bar charts can either be vertical or horizontal, the default is
+%vertical. In this section the $x$ axis refers to the horizontal
+%axis when plotting a vertical bar chart and to the vertical axis
+%when plotting a horizontal bar chart. The $x$ axis units are in
+%increments of one bar. The $y$ axis refers to the vertical axis
+%when plotting a vertical bar chart and to the horizontal axis when
+%plotting a horizontal bar chart. The $y$ axis uses the same
+%co-ordinates as the data. The bars may have an upper and lower
+%label. In a vertical bar chart, the lower label is placed below
+%the $x$ axis and the upper label is placed above the top of the bar.
+%In a horizontal bar chart, the lower label is placed to the left of
+%the $x$ axis and the upper label is placed to the right of the
+%end of the bar. (This is actually a misnomer as it is possible
+%for the ``upper'' label to be below the ``lower'' label if a
+%bar has a negative value, however the bars are considered to
+%be anchored on the $x$ axis, and the other end of the bar is
+%considered to be the ``upper'' end, regardless of its
+%direction.)
+%
+%The \sty{databar} package options are as follows:
+%\begin{description}
+%\item[{\pkgopt[databar]{color}}] Created coloured bar charts
+%(default.)
+%
+%\item[{\pkgopt[databar]{gray}}] Created grey scale bar charts.
+%
+%\item[{\pkgopt[databar]{vertical}}] Created vertical bar charts
+%(default.)
+%
+%\item[{\pkgopt[databar]{horizontal}}] Created horizontal bar charts.
+%\end{description}
+%
+%
+%\DescribeMacro{\DTLbarchart}
+%\begin{definition}
+%\cs{DTLbarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values}
+%\end{definition}
+%\DescribeMacro{\DTLmultibarchart}
+%\begin{definition}
+%\cs{DTLmultibarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values}
+%\end{definition}
+%These commands both create a bar chart from the information in
+%the database \meta{db name}, where \meta{condition} is the same
+%as the optional argument for \ics{DTLforeach} described in
+%\autoref{sec:dbforeach}, and \meta{values} is the same as the
+%penultimate argument of \ics{DTLforeach}. The \meta{settings}
+%argument is a \meta{setting}"="\meta{value} list of settings. The
+%first command, \cs{DLTbarchart}, will draw a bar chart for a
+%given column of data in the database, whereas the second command,
+%\cs{DTLmultibarchart}, will draw a bar chart that is divided into
+%groups of bars where each bar within a group represents data from
+%several columns of a given row in the database.
+%
+%The \setting{DTLbarchart}{variable} setting is
+%required for \cs{DTLbarchart} and the
+%\setting{DTLmultibarchart}{variables}, the other settings are
+%optional (though some may only be used for one of
+%\cs{DTLbarchart} and \cs{DLTmultibarchart}), and are as follows:
+%
+%\begin{description}
+%\item[\setting{DTLbarchart}{variable}]
+%This specifies the control sequence to use that
+%contains the value used to construct the bar chart. The control
+%sequence must be one of the control sequences to appear in
+%the assignment list \meta{values}. This setting is required
+%for \cs{DTLbarchart}, and is unavailable for \cs{DTLmultibarchart}.
+%
+%\item[\setting{DTLmultibarchart}{variables}]
+%This specifies a list of control sequences to use which
+%contain the values used to construct the bar chart. Each control
+%sequence must be one of the control sequences to appear in
+%the assignment list \meta{values}. This setting is required
+%for \cs{DTLmultibarchart}, and is unavailable for
+%\cs{DTLbarchart}.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{max}]
+%This specifies the maximum value on the $y$ axis. (This should
+%be a standard decimal value.)
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{length}]
+%This specifies the overall length of the $y$ axis, and must
+%be a dimension.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{maxdepth}]
+%This must be a zero or negative number. It specifies the maximum
+%depth of the $y$ axis. (This should be a standard decimal value.)
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{axes}]
+%This setting specifies which axes to display. This may take one
+%of the following values: "both", "x", "y" or "none".
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{barlabel}]
+%This setting specifies the lower bar label. When used with
+%\cs{DTLmultibarchart} it indicates the group label.
+%
+%\item[\setting{DTLmultibarchart}{multibarlabels}]
+%This setting should contain a comma separated list of labels
+%for each bar within a group for \cs{DTLmultibarchart}. This
+%setting is not available for \cs{DTLbarchart}.
+%
+%\item[\setting{DTLbarchart}{upperbarlabel}]
+%This setting specifies the upper bar label. This setting
+%is not available for \cs{DTLmultibarchart}.
+%
+%\item[\setting{DTLmultibarchart}{uppermultibarlabels}]
+%This setting must be a comma separated list of upper bar
+%labels for each bar within a group. This setting is not
+%available for \cs{DTLbarchart}.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{yticpoints}]
+%This must be a comma separated list of tick locations for the
+%$y$ axis. (These should be standard decimal values.)
+%This setting overrides \setting{DTLbarchart}{yticgap}.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{yticgap}]
+%This specifies the gap between the $y$ tick marks. (This should
+%be a standard decimal value.)
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{yticlabels}]
+%This must be a comma separated list of tick labels for the
+%$y$ axis.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{ylabel}]
+%This specifies the label for the $y$ axis.
+%
+%\item[\setting{DTLmultibarchart}{groupgap}] This specifies
+%the gap between groups when using \cs{DTLmultibarchart}.
+%This value is given as a multiple of the bar width. The
+%default value is 1, which indicates a gap of one bar width.
+%This setting is not available for \cs{DTLbarchart}.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{verticalbars}]
+%This is a boolean setting, so it can only take the values
+%"true" (do a vertical bar chart) or "false" (do a horizontal
+%bar chart.) If the value is omitted, "true" is assumed.
+%\end{description}
+%
+%\begin{example}{A Basic Bar Chart}{ex:barchart}
+%Recall \autoref{ex:piechart} defined a database called "fruit".
+%This example will be using that database to plot a bar chart.
+%The following plots a basic vertical bar chart:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLbarchart{variable=\theQuantity}{fruit}{\theQuantity=Quantity}
+%\caption{A basic bar chart}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:barchart}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLbarchart{variable=\theQuantity}{fruit}{\theQuantity=Quantity}
+%\caption{A basic bar chart}
+%\label{fig:barchart}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Changing the Appearance of a Bar Chart}
+%
+%\DescribeMacro{\DTLbarchartlength}
+%\begin{definition}
+%\cs{DTLbarchartlength}
+%\end{definition}
+%This specifies the total length of the $y$ axis. You must use
+%\cs{setlength} to change this value. The default value is 3in.
+%
+%\DescribeMacro{\DTLbarwidth}
+%\begin{definition}
+%\cs{DTLbarwidth}
+%\end{definition}
+%This specifies the width of each bar. You must use \cs{setlength}
+%to change this value. The default value is 1cm.
+%
+%\DescribeMacro{\DTLbarlabeloffset}
+%\begin{definition}
+%\cs{DTLbarlabeloffset}
+%\end{definition}
+%This specifies the distance from the $x$ axis to the lower bar label.
+%You must use \cs{setlength} to change this value. The default value
+%is 10pt.
+%
+%\begin{definition}
+%\counterfmt{DTLbarroundvar}
+%\end{definition}
+%The $y$ tick labels are rounded to \meta{n} digits after the
+%decimal point, where \meta{n} is given by the value of the
+%counter \counterfmt{DTLbarroundvar}. You must use \cs{setcounter}
+%to change this value.
+%
+%\DescribeMacro{\DTLsetbarcolor}
+%\begin{definition}
+%\cs{DTLsetbarcolor}\marg{n}\marg{color}
+%\end{definition}
+%This sets the \meta{n}th bar colour to \meta{color}.
+%Only the first eight bars have a colour defined by default. If you
+%need more than eight bars, you will need to define more bar colours.
+%
+%\DescribeMacro{\DTLdobarcolor}
+%\begin{definition}
+%\cs{DTLdobarcolor}\marg{n}
+%\end{definition}
+%This sets the current colour to the colour of the \meta{n}th bar.
+%
+%\DescribeMacro{\DTLbaroutlinecolor}
+%\begin{definition}
+%\cs{DTLbaroutlinecolor}
+%\end{definition}
+%This macro contains the colour of the bar outlines. This defaults
+%to "black".
+%
+%\DescribeMacro{\DTLbaroutlinewidth}
+%\begin{definition}
+%\cs{DTLbaroutlinewidth}
+%\end{definition}
+%This length specifies the line width for the bar outlines. If it
+%is 0pt, the outline is not drawn. The default value is 0pt.
+%
+%\DescribeMacro{\DTLbaratbegintikz}
+%\begin{definition}
+%\cs{DTLbaratbegintikz}
+%\end{definition}
+%This specifies any additional commands to add to the start of
+%the plot. It defaults to nothing, and is called after the
+%unit vectors are set.
+%
+%\DescribeMacro{\DTLbaratendtikz}
+%\begin{definition}
+%\cs{DTLbaratendtikz}
+%\end{definition}
+%This specifies any additional commands to add to the end of
+%the plot. It defaults to nothing.
+%
+%\DescribeMacro{\ifDTLverticalbars}
+%\begin{definition}
+%\cs{ifDTLverticalbars}
+%\end{definition}
+%This conditional governs whether the chart uses vertical or
+%horizontal bars.
+%
+%\DescribeMacro{\DTLbarXlabelalign}
+%\begin{definition}
+%\cs{DTLbarXlabelalign}
+%\end{definition}
+%This specifies the text alignment of the lower bar labels. This
+%defaults to "left,rotate=-90" if you use the \pkgopt[databar]{vertical}
+%package option or the \setting{DTLbarchart}{verticalbars} setting,
+%and defaults to "right" if you use the \pkgopt[databar]{horizontal}
+%package option or the \setting{DTLbarchart}{verticalbars}"=false"
+%setting.
+%
+%\DescribeMacro{\DTLbarYticklabelalign}
+%\begin{definition}
+%\cs{DTLbarYlabelalign}
+%\end{definition}
+%This specifies the text alignment of the $y$ axis labels. This
+%defaults to "right" for vertical bar charts and "center" for
+%horizontal bar charts.
+%
+%\DescribeMacro{\DTLbardisplayYticklabel}
+%\begin{definition}
+%\cs{DTLbardisplayYticklabel}\marg{text}
+%\end{definition}
+%This specifies how to display the $y$ tick label. The argument
+%is the tick label.
+%
+%\DescribeMacro{\DTLdisplaylowerbarlabel}
+%\begin{definition}
+%\cs{DTLdisplaylowerbarlabel}\marg{text}
+%\end{definition}
+%This specifies how to display the lower bar label for
+%\cs{DTLbarchart} and the lower bar group label for
+%\cs{DTLmultibarchart}. The argument is the label.
+%
+%\DescribeMacro{\DTLdisplaylowermultibarlabel}
+%\begin{definition}
+%\cs{DTLdisplaylowermultibarlabel}\marg{text}
+%\end{definition}
+%This specifies how to display the lower bar label for
+%\cs{DTLmultibarchart}. The argument is the label. This
+%command is ignored by \cs{DTLbarchart}.
+%
+%\DescribeMacro{\DTLdisplayupperbarlabel}
+%\begin{definition}
+%\cs{DTLdisplayupperbarlabel}\marg{text}
+%\end{definition}
+%This specifies how to display the upper bar label for
+%\cs{DTLbarchart} and the upper bar group label for
+%\cs{DTLmultibarchart}. The argument is the label.
+%
+%\DescribeMacro{\DTLdisplayuppermultibarlabel}
+%\begin{definition}
+%\cs{DTLdisplayuppermultibarlabel}\marg{text}
+%\end{definition}
+%This specifies how to display the upper bar label for
+%\cs{DTLmultibarchart}. The argument is the label. This
+%command is ignored by \cs{DTLbarchart}.
+%
+%\begin{example}{An Labelled Bar Chart}{ex:annotebarchart}
+%This example extends \autoref{ex:barchart} so that the chart is
+%a bit more informative (which is after all the whole point of
+%a chart.) This chart now has a label below each bar, as well
+%as a label above the bar. The lower label uses the value of the
+%"Name" key, and the upper label uses the quantity. I have also
+%set the outline width so each bar has a border.
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\setlength{\DTLbaroutlinewidth}{1pt}
+%\centering
+%\DTLbarchart{variable=\theQuantity,barlabel=\theName,%
+%upperbarlabel=\theQuantity}{fruit}{%
+%\theQuantity=Quantity,\theName=Name}
+%\caption{A bar chart}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:annotebarchart}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\setlength{\DTLbaroutlinewidth}{1pt}
+%\DTLbarchart{variable=\theQuantity,barlabel=\theName,
+%upperbarlabel=\theQuantity}{fruit}{%
+%\theQuantity=Quantity,\theName=Name}
+%\caption[A bar chart (labelled)]{A bar chart}
+%\label{fig:annotebarchart}
+%\end{figure}
+%\end{example}
+%
+%\begin{example}{Profit/Loss Bar Chart}{ex:profit}
+%Suppose I have a file called "profits.csv" that looks like:
+%\DTLnewdb{profits}
+%\DTLnewrow{profits}
+%\DTLnewdbentry{profits}{Year}{2000}\relax
+%\DTLnewdbentry{profits}{Profit}{\protect\pounds2,525}\relax
+%\DTLnewrow{profits}
+%\DTLnewdbentry{profits}{Year}{2001}\relax
+%\DTLnewdbentry{profits}{Profit}{\protect\pounds3,752}\relax
+%\DTLnewrow{profits}
+%\DTLnewdbentry{profits}{Year}{2002}\relax
+%\DTLnewdbentry{profits}{Profit}{-\protect\pounds1,520}\relax
+%\DTLnewrow{profits}
+%\DTLnewdbentry{profits}{Year}{2003}\relax
+%\DTLnewdbentry{profits}{Profit}{\protect\pounds1,270}\relax
+%\begin{verbatim}
+%Year,Profit
+%2000,\pounds2,535
+%2001,\pounds3,752
+%2002,-\pounds1,520
+%2003,\pounds1,270
+%\end{verbatim}
+%First I can load this file into a database called "profits":
+%\begin{verbatim}
+%\DTLloaddb{profits}{profits.csv}
+%\end{verbatim}
+%Now I can plot the data as a bar chart:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+% % Set the width of each bar to 10pt
+%\setlength{\DTLbarwidth}{10pt}
+% % Set the outline width to 1pt
+%\setlength{\DTLbaroutlinewidth}{1pt}
+% % Round the $y$ tick labels to integers
+%\setcounter{DTLbarroundvar}{0}
+% % Adjust the tick label offset
+%\setlength{\DTLticklabeloffset}{20pt}
+% % Change the y tick label alignment
+%\renewcommand*{\DTLbarYticklabelalign}{left}
+% % Rotate the y tick labels
+%\renewcommand*{\DTLbardisplayYticklabel}[1]{\rotatebox{-45}{#1}}
+% % Set the bar colours depending on the value of \theProfit
+%\DTLforeach{profits}{\theProfit=Profit}{%
+%\ifthenelse{\DTLislt{\theProfit}{0}}
+%{\DTLsetbarcolor{\DTLcurrentindex}{red}}
+%{\DTLsetbarcolor{\DTLcurrentindex}{blue}}}
+% % Do the bar chart
+%\DTLbarchart{variable=\theProfit,upperbarlabel=\theYear,
+%ylabel={Profit/Loss (\pounds)},verticalbars=false,
+%maxdepth=-2000,max=4000}{profits}
+%{\theProfit=Profit,\theYear=Year}
+%\caption{Profits for 2000--2003}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:profits}. Notes:
+%\begin{enumerate}
+%\item This example uses \cs{rotatebox}, so the \sty{graphics}
+%or \sty{graphicx} package is required.
+%\item The $y$ tick labels are too wide to fit horizontally
+%so they have been rotated to avoid overlapping with their
+%neighbour.
+%\item Rotating the $y$ tick labels puts them too close to
+%the $y$ axis, so \ics{DTLticklabeloffset} is made larger to
+%compensate.
+%\item Remember not to use \cs{year} as an assignment command
+%as this command already exists!
+%\item Before the bar chart is created I have iterated through
+%the database, setting the bar colour to red or blue
+%depending on the value of \cs{theProfit}.
+%\end{enumerate}
+%
+%Both \cs{DTLbarchart} and \cs{DTLmultibarchart} set the following
+%macros, which may be used in \cs{DTLbaratbegintikz} and
+%\cs{DTLbaratendtikz}:
+%\DescribeMacro{\DTLbarchartwidth}
+%\begin{definition}
+%\cs{DTLbarchartwidth}
+%\end{definition}
+%This is the overall width of the bar chart. In the case of
+%\cs{DTLbarchart} this is just the number of bars. In the case
+%of \cs{DTLmultibarchart} it is computed as:
+%\begin{displaymath}
+%m \times n + (m-1)\times g
+%\end{displaymath}
+%where $m$ is the number of bar groups (i.e.\ the number of rows
+%of data), $n$ is the number of bars within a group (i.e.\
+%the number of commands listed in the
+%\setting{DTLmultibarchart}{variables}) setting and $g$ is the
+%group gap (as specified by the \setting{DTLmultibarchart}{groupgap} setting.)
+%
+%\DescribeMacro{\DTLnegextent}
+%\begin{definition}
+%\cs{DTLnegextent}
+%\end{definition}
+%This is set to the negative extent of the bar chart. (This value
+%may either be zero or negative, and corresponds to the
+%\setting{DTLbarchart,DTLmultibarchart}{maxdepth} setting.)
+%
+%\DescribeMacro{\DTLbarmax}
+%\begin{definition}
+%\cs{DTLbarmax}
+%\end{definition}
+%This is set to the maximum extent of the bar chart. (This value
+%corresponds to the
+%\setting{DTLbarchart,DTLmultibarchart}{max} setting.)
+%
+%\begin{figure}[htbp]
+%\centering
+%\setlength{\DTLbarwidth}{10pt}
+%\setlength{\DTLbaroutlinewidth}{1pt}
+%\setlength{\DTLticklabeloffset}{20pt}
+%\setcounter{DTLbarroundvar}{0}
+%\renewcommand*{\DTLbarYticklabelalign}{left}
+%\renewcommand*{\DTLbardisplayYticklabel}[1]{\rotatebox{-45}{#1}}
+%\DTLforeach{profits}{\theProfit=Profit}{\relax
+%\ifthenelse{\DTLislt{\theProfit}{0}}
+%{\DTLsetbarcolor{\DTLcurrentindex}{red}}
+%{\DTLsetbarcolor{\DTLcurrentindex}{blue}}}
+%\DTLbarchart{variable=\theProfit,upperbarlabel=\theYear,
+%ylabel={Profit/Loss (\pounds)},verticalbars=false,
+%maxdepth=-2000,max=4000
+%}{profits}
+%{\theProfit=Profit,\theYear=Year}
+%\caption[Profits for 2000--2003 (a horizontal bar chart)]{Profits for
+%2000--2003}
+%\label{fig:profits}
+%\end{figure}
+%
+%\end{example}
+%
+%\begin{example}{A Multi-Bar Chart}{ex:multibar}
+%This example uses the "marks" database described in
+%\autoref{ex:editdb}.
+%Recall that this database stores student marks for three
+%assignments. The keys for the assignment marks are
+%\texttt{Assignment 1}, \texttt{Assignment 2} and
+%\texttt{Assignment 3}, respectively. I can convert this
+%data into a bar chart using the following:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+%barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+%barlabel={\firstname\ \surname}}{marks}{%
+%\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,%
+%\assignII=Assignment 2,\assignIII=Assignment 3}
+%\caption{Student marks}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:multibar}. Notes:
+%\begin{enumerate}
+%\item I used "variables={\assignI,\assignII,\assignIII}" to
+%set the variable to use for each bar within a group. This means
+%that there will be three bars in each group.
+%\item I have set the bar width to 10pt, otherwise the chart
+%will be too wide.
+%\item I used "uppermultibarlabels={\assignI,\assignII,\assignIII}"
+%to set the upper labels for each bar within a group. This
+%will print the assignment mark above the relevant bar.
+%\item I used "barlabel={\firstname\ \surname}" to place the
+%student's name below the group corresponding to that student.
+%\end{enumerate}
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+%barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+%barlabel={\firstname\ \surname}}{marks}
+%{\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII=Assignment 3}
+%\caption[Student marks (a multi-bar chart)]{Student
+%marks}\label{fig:multibar}
+%\end{figure}
+%
+%Recall that \autoref{ex:editdb} computed the average score over
+%for each student, and saved it with the key "Average". This
+%information can be added to the bar chart. It might also be
+%useful to compute the average over all students and add this
+%information to the chart. This is done as follows:
+%\begin{verbatim}
+% \begin{figure}[htbp]
+% \centering
+% % compute the overall mean
+% \DTLmeanforkeys{marks}{Average}{\overallmean}
+% % round it to 2 decimal places
+% \DTLround{\overallmean}{\overallmean}{2}
+% % draw a grey dotted line indicating the overall mean
+% % covering the entire width of the bar chart
+% \renewcommand*{\DTLbaratendtikz}{%
+% \draw[lightgray,loosely dotted] (0,\overallmean) --
+% (\DTLbarchartwidth,\overallmean)
+% node[right,black]{Average (\overallmean)};}
+% % Set the lower bar labels to draw a brace across the current
+% % group, along with the student's name and average score
+% \renewcommand*{\DTLdisplaylowerbarlabel}[1]{%
+% \tikz[baseline=(current bounding box.center)]{
+% \draw[snake=brace,rotate=-90](0,0) -- (\DTLbargroupwidth,0);}
+% \DTLround{\theMean}{\theMean}{2}%
+% \shortstack{#1\\(Average: \theMean)}}
+% % draw the bar chart
+% \DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+% barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+% barlabel={\firstname\ \surname}}{marks}
+% {\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,%
+% \assignII=Assignment 2,\assignIII=Assignment 3,\theMean=Average}
+% \caption{Student marks}
+% \end{figure}
+%\end{verbatim}
+%which produces \autoref{fig:multibarmean}. Notes:
+%\begin{enumerate}
+%\item I've used the TikZ snake library to create a brace, so
+%I need to put
+%\begin{verbatim}
+%\usetikzlibrary{snakes}
+%\end{verbatim}
+%in the preamble. See the \sty{pgf} manual for more details on
+%how to use this library.
+%
+%\item I used \ics{DTLbargroupwidth} to indicate the width of
+%each bar group.
+%
+%\item I used \ics{DTLbarchartwidth} to indicate the width of the
+%entire bar chart
+%\end{enumerate}
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLmeanforkeys{marks}{Average}{\overallmean}
+%\DTLround{\overallmean}{\overallmean}{2}
+%\renewcommand*{\DTLbaratendtikz}{\draw[lightgray,loosely dotted] (0,\overallmean) --
+%(\DTLbarchartwidth,\overallmean) node[right,black]{Average (\overallmean)};}
+%\renewcommand*{\DTLdisplaylowerbarlabel}[1]{\relax
+%\tikz[baseline=(current bounding box.center)]{
+%\draw[snake=brace,rotate=-90](0,0) -- (\DTLbargroupwidth,0);}
+%\DTLround{\theMean}{\theMean}{2}\relax
+%\shortstack{#1\\(Average: \theMean)}}
+%\DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+%barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+%barlabel={\firstname\ \surname}}{marks}
+%{\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII=Assignment 3,\theMean=Average}
+%\caption[Student marks (annotating a bar chart)]{Student marks}
+%\label{fig:multibarmean}
+%\end{figure}
+%\end{example}
+%
+%\section{Converting a \texorpdfstring{\BibTeX}{BibTeX} database
+%into a datatool database
+%(\texorpdfstring{\sty{databib}}{databib} package)}
+%\label{sec:databib}
+%
+%The \sty{databib} package provides the means of converting a \BibTeX\
+%database into a \sty{datatool} database. The database can then be
+%sorted using \cs{DTLsort}, described in \autoref{sec:sort}.
+%For example, you may want to sort the bibliography in
+%reverse chronological order. Once you have sorted the bibliography,
+%you can display it using \cs{DTLbibliography}, described in
+%\autoref{sec:thebib}, or you can iterate through the database
+%using \cs{DTLforeachbib}, described in \autoref{sec:foreachbib}.
+%
+%Note that the \sty{databib}
+%package is not automatically loaded by \sty{datatool}, so if
+%you want to use it, you must load it using
+%"\usepackage{databib}".
+%
+%\importantpar The purpose of this package is to provide a means for
+%authors to format their own bibliography style where there is no
+%bibliography style file available that produces the desired results.
+%The \cs{DTLsort} macro uses a much less efficient sorting algorithm
+%than \BibTeX, and loading the bibliography as a \sty{datatool}
+%database is much slower than loading a standard \ext{bbl} file. If
+%you have a large database, and you are worried that \LaTeX\ may have
+%become stuck, try using the \pkgopt{verbose} option to \sty{datatool}
+%or use the command \cs{dtlverbosetrue}. This will print informative
+%messages to the console and transcript file, to let you know what's
+%going on.
+%
+%\subsection{\texorpdfstring{\BibTeX}{BibTeX}: An Overview}
+%\label{sec:bibtex}
+%This document assumes that you have at least some passing
+%familiarity with \BibTeX, but here follows a brief refresher.
+%
+%\BibTeX\ is an external application used in conjunction with \LaTeX.
+%When you run \BibTeX, you need to specify the name of the document's
+%auxiliary file (without the \ext{aux} extension.) \BibTeX\ then reads
+%this file and looks for the commands \cs{bibstyle} (which indicates
+%which bibliography style (\ext{bst}) file to load), \cs{bibdata}
+%(which indicates which bibliography database (\ext{bib}) files to
+%load) and \cs{citation} (produced by \cs{cite} and \cs{nocite}, which
+%indicates which entries should be included in the bibliography.)
+%\BibTeX\ then creates a file with the extension \ext{bbl} which
+%contains the bibliography, formatted according to the layout defined
+%in the bibliography style file.
+%
+%In general, given a document called, say, \texttt{mydoc.tex}, you
+%will have to perform the following steps to ensure that the
+%bibliography and all citations are up-to-date:
+%\begin{enumerate}
+%\item
+%\begin{verbatim}
+%latex mydoc
+%\end{verbatim}
+%This writes the citation information to the auxiliary file.
+%The bibliography currently doesn't exists, so it isn't displayed.
+%Citations will appear in the document as ?? since the internal
+%cross-references don't exist yet.
+%
+%\item
+%\begin{verbatim}
+%bibtex mydoc
+%\end{verbatim}
+%This reads the auxiliary file, and creates a file with the extension
+%\ext{bbl} which typically contains the typeset bibliography.
+%
+%\item
+%\begin{verbatim}
+%latex mydoc
+%\end{verbatim}
+%Now that the \ext{bbl} file exists, the bibliography can be input
+%into the document. The internal cross-referencing information for the
+%bibliography can now be written to the auxiliary file.
+%
+%\item
+%\begin{verbatim}
+%latex mydoc
+%\end{verbatim}
+%The cross-referencing information can be read from the auxiliary
+%file.
+%\end{enumerate}
+%
+%\subsubsection{\texorpdfstring{\BibTeX}{BibTeX} database}
+%
+%The bibliographic data required by \BibTeX\ must be stored in
+%a file with the extension \ext{bib}, where each entry is stored
+%in the form:\par\vskip\baselineskip\noindent
+%{\obeylines
+%\noindent\texttt{@}\meta{entry\_type}\verb|{|\meta{cite\_key}\texttt,
+% \meta{field\_name} \texttt{=} \char`\"\meta{value}\char`\"\texttt,
+% \mbox{}\vdots
+% \meta{field\_name} \texttt{=} \char`\"\meta{value}\char`\"
+%\noindent\verb|}|
+%}
+%\par\vskip\baselineskip\noindent
+%Note that curly braces "{" and "}" may be used instead of \verb|"|
+%and \verb|"|.
+%
+%The entry type, given by \meta{entry\_type} above, indicates
+%the type of document. This may be one of: "article", "book",
+%"booklet", "inbook", "incollection", "inproceedings"\footnote
+%{Note that \texttt{conference} is a synonym for \texttt{inproceedings}.},
+%"manual",
+%"mastersthesis", "misc", "phdthesis", "proceedings", \linebreak
+%"techreport" or "unpublished".
+%
+%The \meta{cite\_key} above is a unique label identifying this
+%entry, and is the label used in the argument of \cs{cite} or
+%\cs{nocite}. The available fields depends on the entry type, for
+%example, the field "journal" is required for the "article" entry
+%type, but is ignored for the "inproceedings" entry type. The standard
+%fields are: "address", "author", "booktitle", "chapter", "edition",
+%"editor", "howpublished", "institution", "journal", "key", "month",
+%"note", "number", "organization", "pages", "publisher", "school",
+%"series", "title", "type", "volume" and "year".
+%
+%Author and editor names must be entered in one of the following
+%ways:
+%\begin{enumerate}
+%\item \meta{First names} \meta{von part} \meta{Surname}, \meta{Jr part}
+%
+%The \meta{von part} is optional and is identified by the name(s)
+%starting with lowercase letters. The final comma followed by
+%\meta{Jr part} is also optional. Examples:
+%\begin{verbatim}
+%author = "Henry James de Vere"
+%\end{verbatim}
+%In the above, the first names are Henry James, the ``von part'' is
+%de and the surname is Vere. There is no ``junior part''.
+%\begin{verbatim}
+%author = "Mary-Jane Brown, Jr"
+%\end{verbatim}
+%In the above, the first name is Mary-Jane, there is no von part,
+%the surname is Brown and the junior part is Jr.
+%\begin{verbatim}
+%author = "Peter {Murphy Allen}"
+%\end{verbatim}
+%In the above, the first name is Peter, and the surname is Murphy
+%Allen. Note that in this case, the surname must be grouped, otherwise
+%Murphy would be considered part of the forename.
+%\begin{verbatim}
+%author = "Maria Eliza {\uppercase{d}e La} Cruz"
+%\end{verbatim}
+%In the above, the first name is Maria Eliza, the von part is
+%De La, and the surname is Cruz. In this case, the von part starts
+%with an uppercase letter, but specifying
+%\begin{verbatim}
+%author = "Maria Eliza De La Cruz"
+%\end{verbatim}
+%would make \BibTeX\ incorrectly classify ``Maria Eliza De La'' as
+%the first names, and the von part would be empty. Since \BibTeX\
+%doesn't understand \LaTeX\ commands, using "{\uppercase{d}e La}"
+%will trick \BibTeX\ into thinking that it starts with a lower
+%case letter.
+%
+%\item \meta{von part} \meta{Surname}, \meta{Forenames}
+%
+%Again the \meta{von part} is optional, and is determined by the
+%case of the first letter. For example:
+%\begin{verbatim}
+%author = "de Vere, Henry James"
+%\end{verbatim}
+%\end{enumerate}
+%
+%Multiple authors or editors should be separated by the key word
+%"and", for example:
+%\begin{verbatim}
+%author = "Michel Goossens and Frank Mittlebach and Alexander Samarin"
+%\end{verbatim}
+%
+%Below is an example of a book entry:
+%\begin{verbatim}
+%@book{latexcomp,
+% title = "The \LaTeX\ Companion",
+% author = "Michel Goossens and Frank Mittlebach and
+% Alexander Samarin",
+% publisher = "Addison-Wesley",
+% year = 1994
+%}
+%\end{verbatim}
+%Note that numbers may be entered without delimiters, as in "year = 1994".
+%There are also some predefined strings, including those for the month
+%names. You should always use these strings instead of the actual
+%month name, as the way the month name is displayed depends on the
+%bibliography style. For example:
+%\begin{verbatim}
+%@article{Cawley2007b,
+%author = "Gavin C. Cawley and Nicola L. C. Talbot",
+%title = "Preventing over-fitting in model selection via {B}ayesian
+% regularisation of the hyper-parameters",
+%journal = "Journal of Machine Learning Research",
+%volume = 8,
+%pages = "841--861",
+%month = APR,
+%year = 2007
+%}
+%\end{verbatim}
+%
+%You can concatenate strings using the "#" character, for example:
+%\begin{verbatim}
+%month = JUL # "~31~--~" # AUG # "~4",
+%\end{verbatim}
+%Depending on the bibliography style, this may be displayed as:
+%July~31~--~August~4, or it may be displayed as:
+%Jul~31~--~Aug~4. For further information, see~\cite{Goossens}.
+%
+%\subsection{Loading a \texorpdfstring{\sty{databib}}{databib}
+%database}
+%\label{sec:loadbbl}
+%
+%The \sty{databib} package always requires the \texttt{databib.bst}
+%bibliography style file (which is supplied with this bundle.)
+%You need to use \cs{cite} or \cs{nocite} as usual. If you want to
+%add all entries in the \ext{bib} file to the \sty{datatool} database,
+%you can use "\nocite{*}".
+%
+%\DescribeMacro{\DTLloadbbl}
+%\begin{definition}
+%\cs{DTLloadbbl}\oarg{bbl name}\marg{db name}\marg{bib list}
+%\end{definition}
+%This command performs several functions:
+%
+%\begin{enumerate}
+%\item it writes the following line in the auxiliary file:
+%\begin{verbatim}
+%\bibstyle{databib}
+%\end{verbatim}
+%which tells \BibTeX\ to use the \texttt{databib.bst}
+%\BibTeX\ style file,
+%
+%\item it writes \cs{bibdata}\marg{bib list} to the
+%auxiliary file, which tells \BibTeX\ which \ext{bib} files to use,
+%
+%\item it creates a \sty{datatool} database called \meta{db name},
+%
+%\item it loads the file \meta{bbl name} if it exists. (The value
+%defaults to \cs{jobname}".bbl", which is the usual name for
+%a \ext{bbl} file.) If the \ext{bbl} file doesn't exist, the
+%database \meta{db name} will remain empty.
+%\end{enumerate}
+%
+%You then need to run your document through \LaTeX\ (or PDF\LaTeX)
+%and then run \BibTeX\ on the auxiliary file, as described in
+%\autoref{sec:bibtex}. This will create a \ext{bbl} file which
+%contains all the commands required to add the bibliography information
+%to the \sty{datatool} database called \meta{db name}. The next
+%time you \LaTeX\ your document, this file will be read, and the
+%information will be added to \meta{db name}.
+%
+%\importantpar Note that
+%\cs{DTLloaddb} doesn't generate any text. Once you have loaded
+%the data, you can display the bibliography uses
+%\cs{DTLbibliography} (described below) or you can iterate
+%through it using \cs{DTLforeachbibentry} described in
+%\autoref{sec:foreachbib}.
+%
+%Note that the \texttt{databib.bst} \BibTeX\ style file provides
+%the following additional fields: "isbn", "doi", "pubmed", "url"
+%and "abstract".
+%However these fields are ignored by the three predefined
+%\sty{databib} styles ("plain", "abbrv" and "alpha".) If you
+%want these fields to be displayed in the bibliography you will
+%need to modify the bibliography style (see \autoref{sec:modbibstyle}.)
+%
+%\subsection{Displaying a \texorpdfstring{\sty{databib}}{databib}
+%database}
+%\label{sec:thebib}
+%
+%A \sty{databib} database which has been loaded using
+%\cs{DTLloaddb} (described in \autoref{sec:loadbbl}) can be
+%displayed using:
+%\begin{definition}
+%\cs{DTLbibliography}\oarg{conditions}\marg{db name}
+%\end{definition}\noindent
+%where \meta{db name} is the name of the database.
+%
+%Within the optional argument \meta{condition}, you may use any of the
+%commands that may be used within the optional argument of
+%\cs{DTLforeach} \emph{In addition}, you may use the following
+%commands:
+%
+%\DescribeMacro{\DTLbibfieldexists}
+%\begin{definition}
+%\cs{DTLbibfieldexists}\marg{field label}
+%\end{definition}
+%This tests whether the field with the given label exists for the
+%current entry.
+%The field label may be one of: "Address", "Author",
+%"BookTitle", "Chapter", "Edition", "Editor", "HowPublished",
+%"Institution", "Journal", "Key", "Month", "Note", "Number",
+%"Organization", "Pages", "Publisher", "School", "Series",
+%"Title", "Type", "Volume", "Year", "ISBN", "DOI", "PubMed",
+%"Abstract" or "Url".
+%
+%For example, suppose you have loaded a \sty{databib} database
+%called "mybib" using \cs{DTLloadbbl} (described in
+%\autoref{sec:loadbbl}) then the following bibliography will only
+%include those entries which have a "Year" field:
+%\begin{verbatim}
+%\DTLbibliography[\DTLbibfieldexists{Year}]{mybib}
+%\end{verbatim}
+%
+%\DescribeMacro{\DTLbibfieldiseq}
+%\begin{definition}
+%\cs{DTLbibfieldiseq}\marg{field label}\marg{value}
+%\end{definition}
+%This tests whether the value of the field given by
+%\meta{field label} equals \meta{value}. If the field doesn't
+%exist for the current entry, this evaluates to false.
+%For example, the following will produce a bibliography which
+%only contains entries which have the "Year" field set to 2004:
+%\begin{verbatim}
+%\DTLbibliography[\DTLbibfieldiseq{Year}{2004}]{mybib}
+%\end{verbatim}
+%
+%\DescribeMacro{\DTLbibfieldcontains}
+%\begin{definition}
+%\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string}
+%\end{definition}
+%This tests whether the value of the field given by \meta{field label}
+%contains \meta{sub string}. For example, the following will produce
+%a bibliography which only contains entries where the author field
+%contains the name "Knuth":
+%\begin{verbatim}
+%\DTLbibliography[\DTLbibfieldcontains{Author}{Knuth}]{mybib}
+%\end{verbatim}
+%
+%\DescribeMacro{\DTLbibfieldislt}
+%\begin{definition}
+%\cs{DTLbibfieldislt}\marg{field label}\marg{value}
+%\end{definition}
+%This tests whether the value of the field given by \meta{field label}
+%is less than \meta{value}. If the field doesn't exist for the
+%current entry, this evaluates to false.
+%For example, the following will produce a bibliography which only
+%contains entries whose "Year" field is less than 1983:
+%\begin{verbatim}
+%\DTLbibliography[\DTLbibfieldislt{Year}{1983}]{mybib}
+%\end{verbatim}
+%
+%\DescribeMacro{\DTLbibfieldisle}
+%\begin{definition}
+%\cs{DTLbibfieldisle}\marg{field label}\marg{value}
+%\end{definition}
+%This tests whether the value of the field given by \meta{field label}
+%is less than or equal to \meta{value}. If the field doesn't exist
+%for the current entry, this evaluates to false.
+%For example, the following will produce a bibliography which only
+%contains entries whose "Year" field is less than or equal to 1983:
+%\begin{verbatim}
+%\DTLbibliography[\DTLbibfieldisle{Year}{1983}]{mybib}
+%\end{verbatim}
+%
+%\DescribeMacro{\DTLbibfieldisgt}
+%\begin{definition}
+%\cs{DTLbibfieldisgt}\marg{field label}\marg{value}
+%\end{definition}
+%This tests whether the value of the field given by \meta{field label}
+%is greater than \meta{value}. If the field doesn't exist for the
+%current entry, this evaluates to false.
+%For example, the following will produce a bibliography which only
+%contains entries whose "Year" field is greater than 1983:
+%\begin{verbatim}
+%\DTLbibliography[\DTLbibfieldisgt{Year}{1983}]{mybib}
+%\end{verbatim}
+%
+%\DescribeMacro{\DTLbibfieldisge}
+%\begin{definition}
+%\cs{DTLbibfieldisge}\marg{field label}\marg{value}
+%\end{definition}
+%This tests whether the value of the field given by \meta{field label}
+%is greater than or equal to \meta{value}. If the field doesn't exist
+%for the current entry, this evaluates to false.
+%For example, the following will produce a bibliography which only
+%contains entries whose "Year" field is greater than or equal to 1983:
+%\begin{verbatim}
+%\DTLbibliography[\DTLbibfieldisge{Year}{1983}]{mybib}
+%\end{verbatim}
+%
+%Note that \cs{DTLbibliography} uses \cs{DTLforeachbibentry}
+%(described in \autoref{sec:foreachbib}) so you may also use
+%test the value of the counter \counterfmt{DTLbibrow} within
+%\meta{conditions}.
+%
+%\begin{example}{Creating a list of publications since a given year}{ex:bibsince2000}
+%Suppose my boss has asked me to produce a list of my
+%publications in reverse chronological order, but doesn't want any
+%publications published prior
+%to the year 2000. I have a file called "nlct.bib" which contains
+%all my publications which I keep in the directory
+%\verb!$HOME/texmf/bibtex/bib/!. I could look through this file,
+%work out the labels for all the publications whose year field
+%is greater or equal to 2000, and
+%create a file with a \cs{nocite} command containing all those labels
+%in a comma separated list in reverse chronological order,
+%but I really can't be bothered to do that.
+%Instead, I can create the following document:
+%\begin{verbatim}
+%\documentclass{article}
+%\usepackage{databib}
+%\begin{document}
+%\nocite{*}
+%\DTLloadbbl{mybib}{nlct}
+%\DTLsort{Year=descending,Month=descending}{mybib}
+%\DTLbibliography[\DTLbibfieldisge{Year}{2000}]{mybib}
+%\end{document}
+%\end{verbatim}
+%Suppose I save this file as "mypubs.tex", then I need to do:
+%\begin{verbatim}
+%latex mypubs
+%bibtex mypubs
+%latex mypubs
+%\end{verbatim}
+%Notes:
+%\begin{enumerate}
+%\item "\nocite{*}" is used to add all the citations in the
+%bibliography file ("nlct.bib" in this case) to the \sty{databib}
+%database.
+%
+%\item "\DTLloadbbl{mybib}{nlct}" does the following:
+%\begin{enumerate}
+%\item writes the line
+%\begin{verbatim}
+%\bibstyle{databib}
+%\end{verbatim}
+%to the auxiliary file. This tells \BibTeX\ to use "databib.bst"
+%(which is supplied with this package.) You therefore shouldn't
+%use \cs{bibliographystyle}.
+%
+%\item writes the line
+%\begin{verbatim}
+%\bibdata{nlct}
+%\end{verbatim}
+%to the auxiliary file. This tells \BibTeX\ that the bibliography
+%data is stored in the file "nlct.bib". Since I have placed this
+%file in \TeX's search path, \BibTeX\ will be able to find it.
+%
+%\item creates a \sty{datatool} database called "mybib".
+%
+%\item if the \ext{bbl} file ("mypubs.bbl" in this example) exists,
+%it loads this file (which adds the bibliography data to the
+%database), otherwise it does nothing further.
+%
+%\end{enumerate}
+%
+%\item In my \BibTeX\ database ("nlct.bib" in this example), I
+%have remember to use the \BibTeX\ month macros: "jan", "feb"
+%etc. This means that the months are stored in the database in
+%the form \cs{DTLmonthname}\marg{nn}, where \meta{nn} is a two
+%digit number from 01 to 12. \cs{DTLsort} ignores command names
+%when it compares strings, which means I can not only sort by
+%year, but also by month\footnote{as long as I haven't put anything
+%before the month name in the bibliography file, e.g.\
+%\mbox{\texttt{month = "2~" \# apr}} will sort by 2~03, instead of
+%03}.
+%
+%\item Once I have loaded and sorted my database, I can then
+%display it using \cs{DTLbibliography}. This uses the style
+%given by the \sty{databib} \pkgopt[databib]{style} package option,
+%or the \cs{DTLbibliographystyle} command, both of which are
+%described in \autoref{sec:bibstyle}.
+%
+%\item I have filtered the bibliography using the optional
+%argument\linebreak "[\DTLbibfieldisge{Year}{2000}]", which checks if the
+%year field of the current entry is greater than or equal to
+%2000. (Note that if an entry has no year field, the condition
+%evaluates to false, and the entry will be omitted from the
+%bibliography.)
+%
+%\item If the bibliography database is large, sorting and creating
+%the bibliography may take a while. Using \sty{databib} is much
+%slower than using a standard \BibTeX\ style file.
+%\end{enumerate}
+%\end{example}
+%
+%\begin{example}{Creating a list of my 10 most recent
+%publications}{ex:top10bib}
+%Suppose now my boss has asked me to produce a list of my ten most
+%recent publications (in reverse chronological order).
+%As in the previous example, I have a file called "nlct.bib"
+%which contains all my publications. I can create the required
+%document as follows:
+%\begin{verbatim}
+%\documentclass{article}
+%\usepackage{databib}
+%\begin{document}
+%\nocite{*}
+%\DTLloadbbl{mybib}{nlct}
+%\DTLsort{Year=descending,Month=descending}{mybib}
+%\DTLbibliography[\value{DTLbibrow}<11]{mybib}
+%\end{document}
+%\end{verbatim}
+%\end{example}
+%
+%\subsection{Changing the bibliography style}
+%\label{sec:bibstyle}
+%The style of the bibliography produced using \cs{DTLbibliography}
+%depends on the \pkgopt[databib]{style}
+%package option, or can be set using
+%\begin{definition}
+%\cs{DTLbibliographystyle}\marg{style}
+%\end{definition}
+%Note that this is \emph{not} the same as \cs{bibliographystyle},
+%as the \sty{databib} package uses its custom \texttt{databib.bst}
+%bibliography style file.
+%
+%Example:
+%\begin{verbatim}
+%\usepackage[style=plain]{databib}
+%\end{verbatim}
+%This sets the plain bibliography style. This is, in fact, the
+%default style, so it need not be specified.
+%
+%Available styles are: "plain", "abbrv" and "alpha". These are similar to the
+%standard \BibTeX\ styles of the same name, but are by no means
+%identical. The most notable difference is that these styles
+%do not sort the bibliography. It is up to you to sort the
+%bibliography using \cs{DTLsort} (described in \autoref{sec:sort}.)
+%
+%\subsubsection{Modifying an existing style}
+%\label{sec:modbibstyle}
+%
+%This section describes some of the commands which are used to
+%format the bibliography. You can choose whichever predefined
+%style best fits your required style, and then modify the commands
+%described in this section. A description of the remaining
+%commands not listed in this section can be found in
+%\autoref{sec:src:bibnames}, \autoref{sec:src:displaybib}
+%and \autoref{sec:src:bibstyle}.
+%
+%\DescribeMacro{\DTLformatauthor}
+%\begin{definition}
+%\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{jr part}\marg{forenames}
+%\end{definition}
+%\DescribeMacro{\DTLformateditor}
+%\begin{definition}
+%\cs{DTLformateditor}\marg{von part}\marg{surname}\marg{jr part}\marg{forenames}
+%\end{definition}
+%These commands are used to format an author/editor's name,
+%respectively. The list of authors and editors are stored in
+%the \sty{databib} database as a comma separated list of
+%\marg{von part}\marg{surname}\marg{jr part}\marg{forenames}
+%data. This ensures that when you sort on the Author or Editor
+%field, the names will be sorted by the first author or editor's
+%surname.
+%
+%Within \cs{DTLformatauthor} and \cs{DTLformateditor}, you may
+%use the following commands:
+%\DescribeMacro{\DTLformatforenames}
+%\begin{definition}
+%\cs{DTLformatforenames}\marg{forenames}
+%\end{definition}
+%This is used by the "plain" style to display the author's
+%forenames\footnote{It also checks
+%whether \meta{forenames} ends with a full stop using
+%\cs{DTLcheckendsperiod} to prevent a sentence ending full stop
+%from following an abbreviation full stop}.
+%
+%\DescribeMacro{\DTLformatabbrvforenames}
+%\begin{definition}
+%\cs{DTLformatabbrvforenames}\marg{forenames}
+%\end{definition}
+%This is used by the "abbrv" style to display the author's
+%initials (which are determined from \meta{forenames}.)
+%Note that if any of the authors has a name starting with an
+%accent, the accented letter must be grouped in order for this
+%command to work. For example:
+%\begin{verbatim}
+%author = "{\'E}lise {\"E}awyn Edwards",
+%\end{verbatim}
+%The initials are formed using \cs{DTLstoreinitials} described
+%in \autoref{sec:strings}, so if you want to change the way the
+%initials are displayed (e.g.\ put a space between them) you will
+%need to redefine the commands used by \cs{DTLstoreinitials} (such
+%as \cs{DTLbetweeninitials}.)
+%
+%\DescribeMacro{\DTLformatsurname}
+%\begin{definition}
+%\cs{DTLformatsurname}\marg{surname}
+%\end{definition}
+%This displays its argument by default\footnote{It also checks
+%whether the surname ends with a full stop using
+%\cs{DTLcheckendsperiod}}.
+%
+%\DescribeMacro{\DTLformatvon}
+%\begin{definition}
+%\cs{DTLformatvon}\marg{von part}
+%\end{definition}
+%If the \meta{von part} is empty, this command does nothing,
+%otherwise it displays its argument followed by a
+%non-breakable space.
+%\DescribeMacro{\DTLformatjr}
+%\begin{definition}
+%\cs{DTLformatjr}\marg{jr part}
+%\end{definition}
+%If the \meta{jr part} is empty, this command displays nothing,
+%otherwise it displays a comma followed by its argument\footnote
+%{again, it also checks \meta{jr part} to determine if it ends
+%with a full stop}.
+%
+%For example, suppose you want the author's surname to appear
+%first in small capitals, followed by a comma and the forenames. This
+%can be achieved by redefining \cs{DTLformatauthor} as follows:
+%\begin{verbatim}
+%\renewcommand*{\DTLformatauthor}[4]{%
+%\textsc{\DTLformatvon{#1}%
+%\DTLformatsurname{#2}\DTLformatjr{#3}},
+%\DTLformatforenames{#4}%
+%}
+%\end{verbatim}
+%
+%\begin{definition}
+%\counterfmt{DTLmaxauthors}
+%\end{definition}
+%The counter \counterfmt{DTLmaxauthors} is used to determine the
+%maximum number of authors to display for a given entry. If the
+%entry's author list contains more than that number of authors,
+%\cs{etalname} is used, the definition of which is given in
+%\autoref{sec:src:bibnames}. The default value of
+%\counterfmt{DTLmaxauthors} is \theDTLmaxauthors.
+%
+%\begin{definition}
+%\counterfmt{DTLmaxeditors}
+%\end{definition}
+%The \counterfmt{DTLmaxeditors} counter is analogous to the
+%\counterfmt{DTLmaxauthors} counter. It is used to determine the
+%maximum number of editor names to display. The default value
+%of \counterfmt{DTLmaxeditors} is \theDTLmaxeditors.
+%
+%\DescribeMacro{\DTLandlast}
+%Within a list of author or editor names, \cs{DTLandlast} is
+%used between the last two names, otherwise
+%\DescribeMacro{\DTLandnotlast}\cs{DTLandnotlast} is used between
+%names.
+%However, if there are only two author or editor names,
+%\DescribeMacro{\DTLtwoand}\cs{DTLtwoand}
+%is used instead of \cs{DTLandlast}.
+%
+%\DescribeMacro{\DTLendbibitem}
+%The command \cs{DTLendbibitem} is a hook provided to add
+%additional information at the end of each bibliography item.
+%This does nothing by default, but if you want to display the
+%additional fields provided by the "databib.bst" style file,
+%you can redefine \cs{DTLendbibitem} so that it displays a
+%particular field, if it is defined. Within this command, you
+%may use the commands \cs{DTLbibfield}, \cs{DTLifbibfieldexist}
+%and \cs{DTLifanybibfieldexist}, which are described in
+%\autoref{sec:foreachbib}. For example, if you have used the
+%"abstract" field in any of your entries, you can display the
+%abstract as follows:
+%\begin{verbatim}
+%\renewcommand{\DTLendbibitem}{%
+%\DTLifbibfieldexists{Abstract}{\DTLpar\textbf{Abstract}
+%\begin{quote}\DTLbibfield{Abstract}\end{quote}}{}}
+%\end{verbatim}
+%(Note that \cs{DTLpar} needs to be used instead of
+%\cs{par}.)
+%
+%\begin{example}{Compact bibliography}{ex:compactbib}
+%Suppose I don't have much space in my document, and I need to
+%produce a compact bibliography. Firstly, I can use the
+%bibliography style "abbrv", either through the package option:
+%\begin{verbatim}
+%\usepackage[style=abbrv]{databib}
+%\end{verbatim}
+%or using:
+%\begin{verbatim}
+%\DTLbibliographystyle{abbrv}
+%\end{verbatim}
+%Once I have set the style, I can further modify it thus:
+%\begin{verbatim}
+%\renewcommand*{\andname}{\&}
+%\renewcommand*{\editorname}{ed.}
+%\renewcommand*{\editorsname}{eds.}
+%\renewcommand*{\pagesname}{pp.}
+%\renewcommand*{\pagename}{p.}
+%\renewcommand*{\volumename}{vol.}
+%\renewcommand*{\numbername}{no.}
+%\renewcommand*{\editionname}{ed.}
+%\renewcommand*{\techreportname}{T.R.}
+%\renewcommand*{\mscthesisname}{MSc thesis}
+%\end{verbatim}
+%Now I can load\footnote{I can load the bibliography earlier, but
+%obviously the bibliography should only be displayed after the
+%bibliography styles have been set, otherwise they will have no
+%effect} and display the bibliography:
+%\begin{verbatim}
+% % create a database called mybib from the information given
+% % in mybib1.bib and mybib2.bib
+% \DTLloadbbl{mybib}{mybib1,mybib2}
+% % display the bibliography
+% \DTLbibliography{mybib}
+%\end{verbatim}
+%\end{example}
+%
+%\begin{example}{Highlighting a given author}{ex:highlightauthor}
+%Suppose my boss wants me to produce a list of all my publications
+%(which I have stored in the file "nlct.bib", as in
+%\autoref{ex:bibsince2000}.) Most of my
+%publications have multiple co-authors, but suppose my boss would
+%like me to highlight my name so that when he skims through
+%the document, he can easily see my name in the list of
+%co-authors. I can do this by redefining \cs{DTLformatauthor}
+%so that it checks if the given surname matches mine. (This
+%assumes that none of the other co-author's share my surname.)
+%\begin{verbatim}
+%\renewcommand*{\DTLformatauthor}[4]{%
+%{\DTLifstringeq{#2}{Talbot}{\bfseries }{}%
+%\DTLformatforenames{#4}
+%\DTLformatvon{#1}%
+%\DTLformatsurname{#2}%
+%\DTLformatjr{#3}}}
+%\end{verbatim}
+%Notes:
+%\begin{enumerate}
+%\item I have used \cs{DTLifstringeq} (described in
+%\autoref{sec:ifconditions}) to perform the string comparison.
+%\item If one or more of my co-authors shared the same surname as
+%me, I would also have had to check the first name, however there
+%is regrettably a lack of consistency in my \ext{bib} file when
+%it comes to my forenames. Sometimes my name is given as
+%\texttt{Nicola L. C. Talbot}, sometimes the middle initials
+%are omitted, \texttt{Nicola Talbot}, or sometimes, just initials
+%are used, \texttt{N. L. C. Talbot}. This can cause problems
+%when checking the forenames, but as long as the other authors
+%who share the same surname as me, don't also share the same
+%first initial, I can use \cs{DTLifStartsWith} or \cs{DTLisPrefix},
+%which are described in \autoref{sec:ifconditions} and
+%\autoref{sec:ifthen}, respectively. Using the first approach
+%I can do:
+%\begin{verbatim}
+%\renewcommand*{\DTLformatauthor}[4]{%
+%{\DTLifstringeq{#2}{Talbot}{\DTLifStartsWith{#4}{N}{\bfseries }{}}{}%
+%\DTLformatforenames{#4}
+%\DTLformatvon{#1}%
+%\DTLformatsurname{#2}%
+%\DTLformatjr{#3}}}
+%\end{verbatim}
+%Using the second approach I can do:
+%\begin{verbatim}
+%\renewcommand*{\DTLformatauthor}[4]{%
+%{\ifthenelse{\DTLiseq{#2}{Talbot}\and
+%\DTLisPrefix{#4}{N}}{\bfseries }{}%
+%\DTLformatforenames{#4}
+%\DTLformatvon{#1}%
+%\DTLformatsurname{#2}%
+%\DTLformatjr{#3}}}
+%\end{verbatim}
+%
+%\item I have used a group to localise the effect of \cs{bfseries}.
+%\end{enumerate}
+%\end{example}
+%
+%\subsection{Iterating through a
+%\texorpdfstring{\sty{databib}}{databib} database}
+%\label{sec:foreachbib}
+%
+%\cs{DTLbibliography} (described in \autoref{sec:thebib}) may still
+%not meet your needs. For example, you may be required
+%to list journal papers and conference proceedings in separate
+%sections. In which case, you may find it easier to iterate through
+%the bibliography using:
+%\DescribeMacro{\DTLforeachbib}
+%\begin{definition}
+%\cs{DTLforeachbib}\oarg{condition}\marg{db name}\marg{text}
+%\end{definition}
+%\DescribeMacro{\DTLforeachbib*}
+%\begin{definition}
+%\cs{DTLforeachbib*}\oarg{condition}\marg{db name}\marg{text}
+%\end{definition}
+%This iterates through the \sty{databib} database called
+%\meta{db name} and does \meta{text} if \meta{condition} is met.
+%As with \cs{DTLforeach}, the starred version is read-only.
+%
+%For each row of the database, the following commands are set:
+%\begin{itemize}
+%\item \cs{DBIBcitekey} \DescribeMacro{\DBIBcitekey}This is the
+%unique label which identifies the current entry (as used in the
+%argument of \cs{cite} and \cs{nocite}.)
+%
+%\item \cs{DBIBentrytype} \DescribeMacro{\DBIBentrytype}This
+%is the current entry type, and will be one of: "article", "book",
+%"booklet", "inbook", "incollection", "inproceedings",
+%"manual", "mastersthesis", "misc", "phdthesis", "proceedings",
+%"techreport" or "unpublished". (Note that even if you used the
+%entry type "conference" in your \ext{bib} file, its entry type
+%will be set to "inproceedings".)
+%\end{itemize}
+%
+%The remaining fields may be accessed using:
+%\DescribeMacro{\DTLbibfield}
+%\begin{definition}
+%\cs{DTLbibfield}\marg{field label}
+%\end{definition}\noindent
+%where \meta{field label} may be one of: "Address", "Author",
+%"BookTitle", "Chapter", "Edition", "Editor", "HowPublished",
+%"Institution", "Journal", "Key", "Month", "Note", "Number",
+%"Organization", "Pages", "Publisher", "School", "Series",
+%"Title", "Type", "Volume", "Year", "ISBN", "DOI", "PubMed",
+%"Abstract" or "Url".
+%
+%You can determine if a field exists for a given entry using
+%\DescribeMacro{\DTLifbibfieldexists}
+%\begin{definition}
+%\cs{DTLifbibfieldexists}\marg{field label}\marg{true part}\marg{false
+%part}
+%\end{definition}
+%If the field given by \meta{field label} exists for the current
+%bibliography entry, it does \meta{true part}, otherwise it
+%does \meta{false part}.
+%
+%\DescribeMacro{\DTLifbibanyfieldexists}
+%\begin{definition}
+%\cs{DTLifanybibfieldexists}\marg{field label list}\marg{true
+%part}\marg{false part}
+%\end{definition}
+%This is similar to \cs{DTLifbibfieldexists} except that the
+%first argument is a list of field names. If one or more of
+%the fields given in \meta{field label list} exists for the
+%current bibliography item, this does \meta{true part}, otherwise
+%it does \meta{false part}.
+%
+%\DescribeMacro{\DTLformatbibentry}
+%\begin{definition}
+%\cs{DTLformatbibentry}
+%\end{definition}
+%This formats the bibliography entry for the current row. It
+%checks for the existence of the command
+%\cs{DTLformat}\meta{entry type}, where \meta{entry type}
+%is given by \cs{DBIBentrytype}. These commands are defined
+%by the bibliography style.
+%
+%\DescribeMacro{\DTLcomputewidestbibentry}
+%\begin{definition}
+%\cs{DTLcomputewidestbibentry}\marg{conditions}\marg{db
+%name}\marg{bib label}\marg{cmd}
+%\end{definition}
+%This computes the widest bibliography entry over all entries
+%satisfying \meta{conditions} in the database \meta{db name},
+%where the label is given by \meta{bib label}, and the result
+%is stored in \meta{cmd}, which may then be used in the
+%argument of the \env{thebibliography} environment.
+%
+%The counter \counterfmt{DTLbibrow} keeps track of the current
+%bibliography entry. This is reset at the start of each
+%\cs{DTLforeachbib} and is incremented if \meta{conditions}
+%is met.
+%
+%Within the optional argument \meta{condition}, you may use any of the
+%commands that may be used within the optional argument of
+%\cs{DTLbibliography}, described in \autoref{sec:thebib}.
+%
+%\begin{example}{Separate List of Journals and Conference Papers}{ex:jcbib}
+%Suppose now my boss has decided that I need to produce a list
+%of all my publications, but they need to be separated so that
+%all the journal papers appear in one section, and all the
+%conference papers appear in another section. The journal papers
+%need to be labelled [J1], [J2] and so on, while the conference
+%papers need to be labelled [C1], [C2] and so on. (My boss isn't
+%interested in any of my other publications!) Again, all my
+%publications are stored in the \BibTeX\ database "nlct.bib". The
+%following creates the required document:
+%\begin{verbatim}
+%\documentclass{article}
+%\usepackage{databib}
+%\begin{document}
+%\nocite{*}
+%\DTLloadbbl{mybib}{nlct}
+%
+%\renewcommand*{\refname}{Journal Papers}
+%\DTLcomputewidestbibentry{\equal{\DBIBentrytype}{article}}
+%{mybib}{J\theDTLbibrow}{\widest}
+%
+%\begin{thebibliography}{\widest}
+%\DTLforeachbibentry[\equal{\DBIBentrytype}{article}]{mybib}{%
+%\bibitem[J\theDTLbibrow]{\DBIBcitekey} \DTLformatbibentry}
+%\end{thebibliography}
+%
+%\renewcommand*{\refname}{Conference Papers}
+%\DTLcomputewidestbibentry{\equal{\DBIBentrytype}{inproceedings}}
+%{mybib}{C\theDTLbibrow}{\widest}
+%
+%\begin{thebibliography}{\widest}
+%\DTLforeachbibentry[\equal{\DBIBentrytype}{inproceedings}]{mybib}{%
+%\bibitem[C\theDTLbibrow]{\DBIBcitekey} \DTLformatbibentry}
+%\end{thebibliography}
+%
+%\end{document}
+%\end{verbatim}
+%\end{example}
+%
+% \StopEventually{\clearpage\phantomsection
+%\addcontentsline{toc}{section}{\refname}
+% \DTLbibliography{docbib}
+%\phantomsection
+%\addcontentsline{toc}{section}{Change History}\PrintChanges
+%\phantomsection
+%\addcontentsline{toc}{section}{Index}\PrintIndex
+%}
+%
+%
+%
+%\section{datatool.sty}
+%\iffalse
+% \begin{macrocode}
+%<*datatool.sty>
+% \end{macrocode}
+%\fi
+%\subsection{Package Declaration}
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{datatool}[2007/08/17 v1.01 (NLCT)]
+% \end{macrocode}
+% Load required packages:
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+\RequirePackage{ifthen}
+\RequirePackage{xfor}
+\RequirePackage{fp}
+\RequirePackage{substr}
+% \end{macrocode}
+%
+%\subsection{Package Options}
+%\begin{macro}{\@dtl@separator}
+% The data separator character (comma by default) is stored in
+% \cs{@dtl@separator}.
+% This is the separator used in external data files, not in the
+% \LaTeX\ code, which always uses a comma separator.
+% \begin{macrocode}
+\newcommand*{\@dtl@separator}{,}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsetseparator}
+%\begin{definition}
+%\cs{DTLsetseparator}\marg{char}
+%\end{definition}
+% The sets \cs{@dtl@separator}, and constructs the relevent macros
+% that require this character to be hardcoded into their definition.
+% \begin{macrocode}
+\newcommand*{\DTLsetseparator}[1]{%
+\renewcommand*{\@dtl@separator}{#1}%
+\@dtl@construct@lopoffs
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsettabseparator}
+%\cs{DTLsettabseparator} makes it easier to set a tab separator.
+% \begin{macrocode}
+\begingroup
+\catcode`\ 12
+\gdef\DTLsettabseparator{%
+ \catcode`\ 12
+ \DTLsetseparator{ }%
+}
+\endgroup
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@delimiter}
+% The data delimiter character (double quote by default) is stored
+% in \cs{@dtl@delimiter}. This is used in external data files, not
+% in the \LaTeX\ code.
+% \begin{macrocode}
+\begingroup
+\catcode`\"12\relax
+\gdef\@dtl@delimiter{"}
+\endgroup
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsetdelimiter}
+%\begin{definition}
+%\cs{DTLsetdelimiter}\marg{char}
+%\end{definition}
+% This sets the delimiter.
+% \begin{macrocode}
+\newcommand*\DTLsetdelimiter[1]{%
+\renewcommand*{\@dtl@delimiter}{#1}%
+\@dtl@construct@lopoffs}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@construct@lopoff}
+%\begin{definition}
+%\cs{@dtl@construct@lopoff}\meta{separator char}\meta{delimiter char}
+%\end{definition}
+% This defines
+%\begin{definition}
+% \cs{@dtl@lopoff}\meta{first element}\meta{sep}\meta{rest of list}\cs{to}\meta{cmd1}\meta{cmd2}
+%\end{definition}\noindent
+%for the current separator and delimiter.
+% \begin{macrocode}
+\edef\@dtl@construct@lopoff#1#2{%
+\noexpand\long\noexpand\def\noexpand\@dtl@lopoff#1##1##2\noexpand
+\to##3##4{%
+\noexpand\ifx#2##1\noexpand\relax
+\noexpand\@dtl@qlopoff#1##1##2\noexpand\to##3##4\relax
+\noexpand\else
+\noexpand\@dtl@lop@ff#1##1##2\noexpand\to##3##4\relax
+\noexpand\fi
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@construct@qlopoff}
+%\begin{definition}
+% \cs{@dtl@construct@qlopoff}\meta{separator char}\meta{delimiter char}
+%\end{definition}
+% This constructs \cs{@dtl@qlopoff} to be used
+% when the entry is surrounded by the current delimiter value.
+% \begin{macrocode}
+\edef\@dtl@construct@qlopoff#1#2{%
+\noexpand\long\noexpand\def\noexpand\@dtl@qlopoff#1#2##1#2#1##2\noexpand
+\to##3##4{%
+\noexpand\def##4{##1}\noexpand\def##3{#1##2}%
+}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@construct@lop@ff}
+%\begin{definition}
+% \cs{@dtl@construct@lop@ff}\meta{separator char}
+%\end{definition}
+% This constructs \cs{@dtl@lop@ff} to be used when
+% the entry isn't surrouded by the delimiter.
+% \begin{macrocode}
+\edef\@dtl@construct@lop@ff#1{%
+\noexpand\long\noexpand\def\noexpand\@dtl@lop@ff#1##1#1##2\noexpand
+\to##3##4{%
+\noexpand\def##4{##1}\noexpand\def##3{#1##2}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@construct@lopoffs}
+%\begin{definition}
+%\cs{@dtl@construct@lopoffs}
+%\end{definition}
+% This constructs all the lopoff macros
+% using the given separator and delimiter characters.
+% \begin{macrocode}
+\newcommand{\@dtl@construct@lopoffs}{%
+\edef\@dtl@chars{{\@dtl@separator}{\@dtl@delimiter}}%
+\expandafter\@dtl@construct@lopoff\@dtl@chars
+\expandafter\@dtl@construct@qlopoff\@dtl@chars
+\expandafter\@dtl@construct@lop@ff\expandafter{\@dtl@separator}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@decimal}
+% The current decimal character is stored in \cs{@dtl@decimal}.
+% \begin{macrocode}
+\newcommand*{\@dtl@decimal}{.}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@numbergroupchar}
+% The current number group character is stored in
+% \cs{@dtl@numbergroupchar}.
+% \begin{macrocode}
+\newcommand*{\@dtl@numbergroupchar}{,}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsetnumberchars}
+%\begin{definition}
+%\cs{DTLsetnumberchars}\marg{number group char}\marg{decimal char}
+%\end{definition}
+% This sets the decimal character and number group
+% characters.
+% \begin{macrocode}
+\newcommand*{\DTLsetnumberchars}[2]{%
+\renewcommand*{\@dtl@numbergroupchar}{#1}%
+\renewcommand*{\@dtl@decimal}{#2}%
+\@dtl@construct@getnums
+\@dtl@construct@stripnumgrpchar{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@construct@getintfrac}
+%\begin{definition}
+%\cs{@dtl@construct@getintfrac}\marg{char}
+%\end{definition}
+% This constructs the macros for extracting integer and
+% fractional parts from a real number using the decimal character
+% \meta{char}.
+%
+%\begin{definition}
+% \cs{DTLconverttodecimal}\marg{num}\marg{cmd}
+%\end{definition}
+% \cs{DTLconverttodecimal} will convert locale dependent \meta{num}
+% a decimal number in a form that can be used in the
+% macros defined in the \sty{fp} package. The resulting
+% number is stored in \meta{cmd}. This command has to be redefined
+% whenever the decimal and number group characters are changed
+% as they form part of the command definitions.
+% \begin{macrocode}
+\edef\@dtl@construct@getintfrac#1{%
+\noexpand\def\noexpand\@dtl@getintfrac##1#1##2\noexpand\relax{%
+\noexpand\@dtl@get@intpart{##1}%
+\noexpand\def\noexpand\@dtl@fracpart{##2}%
+\noexpand\ifx\noexpand\@empty\noexpand\@dtl@fracpart
+ \noexpand\def\noexpand\@dtl@fracpart{0}%
+\noexpand\else
+ \noexpand\@dtl@getfracpart##2\noexpand\relax
+ \noexpand\@dtl@choptrailingzeroes{\noexpand\@dtl@fracpart}%
+\noexpand\fi
+}%
+\noexpand\def\noexpand\@dtl@getfracpart##1#1\noexpand\relax{%
+\noexpand\def\noexpand\@dtl@fracpart{##1}%
+}%
+\noexpand\def\noexpand\DTLconverttodecimal##1##2{%
+\noexpand\dtl@ifsingle{##1}%
+{\noexpand\expandafter\noexpand\toks@\noexpand\expandafter{##1}%
+\noexpand\edef\noexpand\@dtl@tmp{\noexpand\the\noexpand\toks@}}%
+{\noexpand\def\noexpand\@dtl@tmp{##1}}%
+ \noexpand\@dtl@standardize@currency\noexpand\@dtl@tmp
+ \noexpand\ifx\noexpand\@dtl@org@currency\noexpand\@empty
+ \noexpand\else
+ \noexpand\let\noexpand\@dtl@currency\noexpand\@dtl@org@currency
+ \noexpand\fi
+\noexpand\expandafter
+\noexpand\@dtl@getintfrac\noexpand\@dtl@tmp#1\noexpand\relax
+\noexpand\edef##2{\noexpand\@dtl@intpart.\noexpand\@dtl@fracpart}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@construct@getnums}
+% The following calls the above with the relevant
+% decimal character:
+% \begin{macrocode}
+\newcommand*{\@dtl@construct@getnums}{%
+\expandafter\@dtl@construct@getintfrac\expandafter{\@dtl@decimal}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@get@intpart}
+% The following gets the integer part (adjusting for
+% repeating +/- signs if necessary.)
+% Sets \cs{@dtl@intpart}.
+% \begin{macrocode}
+\newcommand*{\@dtl@get@intpart}[1]{%
+\@dtl@tmpcount=1\relax
+\def\@dtl@intpart{#1}%
+\ifx\@dtl@intpart\@empty
+ \def\@dtl@intpart{0}%
+\else
+ \def\@dtl@intpart{}%
+ \@dtl@get@int@part#1.\relax%
+\fi
+\ifnum\@dtl@tmpcount<0\relax
+ \edef\@dtl@intpart{-\@dtl@intpart}%
+\fi
+\@dtl@strip@numgrpchar{\@dtl@intpart}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@get@int@part}
+% \begin{macrocode}
+\def\@dtl@get@int@part#1#2\relax{%
+\def\@dtl@argi{#1}%
+\def\@dtl@argii{#2}%
+\ifx\protect#1\relax%
+ \let\@dtl@get@nextintpart=\@dtl@get@int@part
+\else
+ \expandafter\ifx\@dtl@argi\$%
+ \let\@dtl@get@nextintpart=\@dtl@get@int@part
+ \else
+ \ifx-#1%
+ \multiply\@dtl@tmpcount by -1\relax
+ \let\@dtl@get@nextintpart=\@dtl@get@int@part
+ \else
+ \if\@dtl@argi+%
+ \let\@dtl@get@nextintpart=\@dtl@get@int@part
+ \else
+ \def\@dtl@intpart{#1}%
+ \ifx.\@dtl@argii
+ \let\@dtl@get@nextintpart=\@gobble
+ \else
+ \let\@dtl@get@nextintpart=\@dtl@get@next@intpart
+ \fi
+ \fi
+ \fi
+ \fi
+\fi
+\@dtl@get@nextintpart#2\relax
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@get@next@intpart}
+% \begin{macrocode}
+\def\@dtl@get@next@intpart#1.\relax{%
+\edef\@dtl@intpart{\@dtl@intpart#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@choptrailingzeroes}
+%\begin{definition}
+% \cs{@dtl@choptrailingzeroes}\marg{cmd}
+%\end{definition}
+% Chops trailing zeroes from number given by \meta{cmd}.
+% \begin{macrocode}
+\newcommand*{\@dtl@choptrailingzeroes}[1]{%
+\def\@dtl@tmpcpz{}%
+\expandafter\@dtl@chop@trailingzeroes#1\@nil%
+\let#1=\@dtl@tmpcpz
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@chop@trailingzeroes}
+% Trailing zeroes are chopped using a recursive algorithm.
+% \cs{@dtl@tmpcpz} needs to be set before using this. (The chopped
+% number is put in this control sequence.)
+% \begin{macrocode}
+\def\@dtl@chop@trailingzeroes#1#2\@nil{%
+\FPifeq{#2}{0}%
+ \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}%
+ \let\@dtl@chopzeroesnext=\@dtl@gobbletonil
+\else
+ \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}%
+ \let\@dtl@chopzeroesnext=\@dtl@chop@trailingzeroes
+\fi
+\@dtl@chopzeroesnext#2\@nil
+}
+% \end{macrocode}
+%\end{macro}
+% No-op macro to end recursion:
+%\begin{macro}{\@dtl@gobbletonil}
+% \begin{macrocode}
+\def\@dtl@gobbletonil#1\@nil{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@truncatedecimal}
+%\begin{definition}
+%\cs{dtl@truncatedecimal}\meta{cmd}
+%\end{definition}
+%Truncates decimal given by \meta{cmd} to an integer (assumes the
+% number is in decimal format with full stop as decimal point.)
+% \begin{macrocode}
+\newcommand*{\dtl@truncatedecimal}[1]{%
+\expandafter\@dtl@truncatedecimal#1.\@nil#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@truncatedecimal}
+% \begin{macrocode}
+\def\@dtl@truncatedecimal#1.#2\@nil#3{%
+\def#3{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@strip@numgrpchar}
+%\begin{definition}
+% \cs{@dtl@strip@numgrpchar}\marg{cmd}
+%\end{definition}
+% Strip the number group character from the number given by
+% \meta{cmd}.
+% \begin{macrocode}
+\newcommand*{\@dtl@strip@numgrpchar}[1]{%
+\def\@dtl@stripped{}%
+\edef\@dtl@do@stripnumgrpchar{%
+\noexpand\@@dtl@strip@numgrpchar#1\@dtl@numbergroupchar
+\noexpand\relax}%
+\@dtl@do@stripnumgrpchar
+\let#1=\@dtl@stripped
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@construct@stripnumgrpchar}
+% The following macro constructs \cs{@@dtl@strip@numgrpchar}.
+% \begin{macrocode}
+\edef\@dtl@construct@stripnumgrpchar#1{%
+\noexpand\def\noexpand\@@dtl@strip@numgrpchar##1#1##2\noexpand\relax{%
+\noexpand\expandafter\noexpand\toks@\noexpand\expandafter
+{\noexpand\@dtl@stripped}%
+\noexpand\edef\noexpand\@dtl@stripped{\noexpand\the\noexpand\toks@
+##1}%
+\noexpand\def\noexpand\@dtl@tmp{##2}%
+\noexpand\ifx\noexpand\@dtl@tmp\noexpand\@empty
+ \noexpand\let\noexpand\@dtl@next=\noexpand\relax
+\noexpand\else
+ \noexpand\let\noexpand\@dtl@next=\noexpand\@@dtl@strip@numgrpchar
+\noexpand\fi
+\noexpand\@dtl@next##2\noexpand\relax
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdecimaltolocale}
+%\begin{definition}
+% \cs{DTLdecimaltolocale}\marg{number}\marg{cmd}
+%\end{definition}
+% Define command to convert a decimal number into the locale
+% dependent format. Stores result in \meta{cmd} which must be
+% a control sequence.
+% \begin{macrocode}
+\newcommand*{\DTLdecimaltolocale}[2]{%
+\edef\@dtl@tmpdtl{#1}%
+\expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax
+\FPifeq{\@dtl@fracpart}{0}%
+ \edef#2{\@dtl@intpart}%
+\else
+ \edef#2{\@dtl@intpart\@dtl@decimal\@dtl@fracpart}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@decimaltolocale}
+% Convert the integer part (store in \cs{@dtl@intpart})
+% \begin{macrocode}
+\def\@dtl@decimaltolocale#1.#2\relax{%
+\@dtl@decimaltolocaleint{#1}%
+\def\@dtl@fracpart{#2}%
+\ifx\@dtl@fracpart\@empty
+ \def\@dtl@fracpart{0}%
+\else
+ \@dtl@decimaltolocalefrac#2\relax
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@decimaltolocaleint}
+% \begin{macrocode}
+\def\@dtl@decimaltolocaleint#1{%
+\@dtl@tmpcount=0\relax
+\@dtl@countdigits#1.\relax
+\@dtl@numgrpsepcount=\@dtl@tmpcount\relax
+\divide\@dtl@numgrpsepcount by 3\relax
+\multiply\@dtl@numgrpsepcount by 3\relax
+\advance\@dtl@numgrpsepcount by -\@dtl@tmpcount\relax
+\ifnum\@dtl@numgrpsepcount<0\relax
+ \advance\@dtl@numgrpsepcount by 3\relax
+\fi
+\def\@dtl@intpart{}%
+\@dtl@decimal@to@localeint#1.\relax
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@countdigits}
+% Counts the number of digits until "#2" is a full stop.
+% (increments \cs{@dtl@tmpcount}.)
+% \begin{macrocode}
+\def\@dtl@countdigits#1#2\relax{%
+\advance\@dtl@tmpcount by 1\relax
+\ifx.#2\relax
+ \let\@dtl@countnext=\@gobble
+\else
+ \let\@dtl@countnext=\@dtl@countdigits
+\fi
+\@dtl@countnext#2\relax
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@decimal@to@localeint}
+% \begin{macrocode}
+\def\@dtl@decimal@to@localeint#1#2\relax{%
+\advance\@dtl@numgrpsepcount by 1\relax
+\ifx.#2\relax
+ \edef\@dtl@intpart{\@dtl@intpart#1}%
+ \let\@dtl@localeintnext=\@gobble
+\else
+ \ifnum\@dtl@numgrpsepcount=3\relax
+ \edef\@dtl@intpart{\@dtl@intpart#1\@dtl@numbergroupchar}%
+ \@dtl@numgrpsepcount=0\relax
+ \else
+ \ifnum\@dtl@numgrpsepcount>3\relax
+ \@dtl@numgrpsepcount=0\relax
+ \fi
+ \edef\@dtl@intpart{\@dtl@intpart#1}%
+ \fi
+ \let\@dtl@localeintnext=\@dtl@decimal@to@localeint
+\fi
+\@dtl@localeintnext#2\relax
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@decimaltolocalefrac}
+% Convert the fractional part (store in \cs{@dtl@fracpart})
+% \begin{macrocode}
+% \end{macrocode}
+\def\@dtl@decimaltolocalefrac#1.\relax{%
+\def\@dtl@fracpart{#1}%
+\@dtl@choptrailingzeroes{\@dtl@fracpart}%
+}
+%\end{macro}
+%
+%\begin{macro}{\DTLdecimaltocurrency}
+%\begin{definition}
+% \cs{DTLdecimaltocurrency}\marg{number}\marg{cmd}
+%\end{definition}
+% This converts a decimal number into the locale
+% dependent currency format. Stores result in \meta{cmd} which must be
+% a control sequence.
+% \begin{macrocode}
+\newcommand*{\DTLdecimaltocurrency}[2]{%
+\edef\@dtl@tmpdtl{#1}%
+\expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax
+\dtl@truncatedecimal\@dtl@tmpdtl
+\@dtl@tmpcount=\@dtl@tmpdtl\relax
+\expandafter\@dtl@toks\expandafter{\@dtl@currency}%
+\FPifeq{\@dtl@fracpart}{0}%
+ \ifnum\@dtl@tmpcount<0\relax
+ \@dtl@tmpcount = -\@dtl@tmpcount\relax
+ \edef#2{-\the\@dtl@toks\the\@dtl@tmpcount\@dtl@decimal00}%
+ \else
+ \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal00}%
+ \fi
+\else
+ \ifnum\@dtl@tmpcount<0\relax
+ \@dtl@tmpcount = -\@dtl@tmpcount\relax
+ \ifnum\@dtl@fracpart<10\relax
+ \edef#2{-\the\@dtl@toks\number\@dtl@tmpcount
+ \@dtl@decimal\@dtl@fracpart0}%
+ \else
+ \edef#2{-\the\@dtl@toks\number\@dtl@tmpcount
+ \@dtl@decimal\@dtl@fracpart}%
+ \fi
+ \else
+ \ifnum\@dtl@fracpart<10\relax
+ \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal\@dtl@fracpart0}%
+ \else
+ \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal\@dtl@fracpart}%
+ \fi
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Set the defaults:
+% \begin{macrocode}
+\@dtl@construct@lopoffs
+\@dtl@construct@getnums
+\expandafter\@dtl@construct@stripnumgrpchar\expandafter
+{\@dtl@numbergroupchar}
+% \end{macrocode}
+% Define key for package option \pkgopt{separator}.
+% \begin{macrocode}
+\define@key{datatool.sty}{separator}{%
+\DTLsetseparator{#1}}
+% \end{macrocode}
+% Define key for package option \pkgopt{delimiter}.
+% \begin{macrocode}
+\define@key{datatool.sty}{delimiter}{%
+\DTLsetdelimiter{#1}}
+% \end{macrocode}
+% Define key for package option \pkgopt{verbose}. (This also
+% switches the \sty{fp} messages on/off)
+% \begin{macrocode}
+\define@boolkey{datatool.sty}[dtl]{verbose}[true]{%
+\ifdtlverbose \FPmessagestrue\else \FPmessagesfalse\fi}
+% \end{macrocode}
+%\begin{macro}{\dtl@message}
+%\begin{definition}
+%\cs{dtl@message}\marg{message string}
+%\end{definition}
+% Displays message only if the verbose option is set.
+% \begin{macrocode}
+\newcommand*{\dtl@message}[1]{%
+\ifdtlverbose\typeout{#1}\fi}
+% \end{macrocode}
+%\end{macro}
+% Process package options:
+% \begin{macrocode}
+\ProcessOptionsX
+% \end{macrocode}
+%
+%\begin{macro}{\DTLpar}
+% Many of the commands used by this package are short commands.
+% This means that you can't use \cs{par}
+% in the data. To get around this, define the robust command
+% \cs{DTLpar} to use instead.
+% \begin{macrocode}
+\DeclareRobustCommand\DTLpar{\@par}
+% \end{macrocode}
+%\end{macro}
+%
+% \subsection{Determining Data Types}
+% The control sequence \cs{@dtl@checknumerical} checks the data
+% type of its argument, and sets \cs{@dtl@datatype} to 0 if
+% the argument is a string, 1 if the argument is an integer
+% or 2 if the argument is a real number. First define
+% \cs{@dtl@datatype}:
+%\begin{macro}{\@dtl@datatype}
+% \begin{macrocode}
+\newcount\@dtl@datatype
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@tmpcount}
+% Define temporary count register
+% \begin{macrocode}
+\newcount\@dtl@tmpcount
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@tmplength}
+% Define temporary length register:
+% \begin{macrocode}
+\newlength\dtl@tmplength
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@numgrpsepcount}
+% Define count register to count the digits between the number
+% group separators.
+% \begin{macrocode}
+\newcount\@dtl@numgrpsepcount
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@checknumerical}
+%\begin{definition}
+%\cs{@dtl@checknumerical}\marg{arg}
+%\end{definition}
+% Checks if \meta{arg} is numerical
+% (includes decimal numbers, but not scientific notation.)
+% Sets \cs{@dtl@datatype}, as described above.
+% \begin{macrocode}
+\newcommand{\@dtl@checknumerical}[1]{%
+\@dtl@numgrpsepfalse
+\def\@dtl@tmp{#1}%
+\ifx\@empty#1\@empty
+ \@dtl@datatype=0\relax
+\else
+ \dtl@ifsingle{#1}%
+ {\expandafter\toks@\expandafter{#1}%
+ \edef\@dtl@tmp{\the\toks@}}%
+ {\def\@dtl@tmp{#1}}%
+ \@dtl@tmpcount=0\relax
+ \@dtl@datatype=0\relax
+ \@dtl@numgrpsepcount=2\relax
+ \@dtl@standardize@currency\@dtl@tmp
+ \ifx\@dtl@org@currency\@empty
+ \else
+ \let\@dtl@currency\@dtl@org@currency
+ \fi
+ \expandafter\@dtl@checknumericalstart\@dtl@tmp\@nil\@nil
+\fi
+\ifnum\@dtl@numgrpsepcount>-1\relax
+ \if@dtl@numgrpsep
+ \ifnum\@dtl@numgrpsepcount=3\relax
+ \else
+ \@dtl@datatype=0\relax
+ \fi
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@checknumericalstart}
+% Check first character for checknumerical process to see if
+% it's a plus or minus sign.
+% \begin{macrocode}
+\def\@dtl@checknumericalstart#1#2\@nil\@nil{%
+\ifx#1\protect
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+\else
+ \ifx-#1\relax
+ \def\@dtl@tmp{#2}%
+ \ifx\@empty\@dtl@tmp
+ \@dtl@datatype=0\relax
+ \else
+ \ifnum\@dtl@datatype=0\relax
+ \@dtl@datatype=1\relax
+ \fi
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+ \fi
+ \else
+ \ifx+#1\relax
+ \def\@dtl@tmp{#2}%
+ \ifx\@empty\@dtl@tmp
+ \@dtl@datatype=0\relax
+ \else
+ \ifnum\@dtl@datatype=0\relax
+ \@dtl@datatype=1\relax
+ \fi
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+ \fi
+ \else
+ \def\@dtl@tmp{#1}%
+ \ifx#1\$\relax
+ \@dtl@datatype=3\relax
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+ \else
+ \ifx\@empty\@dtl@tmp
+ \@dtl@datatype=0\relax
+ \else
+ \ifnum\@dtl@datatype=0\relax
+ \@dtl@datatype=1\relax
+ \fi
+ \@dtl@checknumericalloop#1#2\@nil\@nil\relax
+ \fi
+ \fi
+ \fi
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\if@dtl@numgrpsep}
+% The conditional \cs{if@dtl@numgrpsep} is set the first time
+% \cs{@dtl@checknumericalloop} encounters the number group
+% separator.
+% \begin{macrocode}
+\newif\if@dtl@numgrpsep
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@ifDigitOrDecimalSep}
+% Check if argument is either a digit or the decimal separator.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@ifDigitOrDecimalSep}[3]{%
+\ifx0#1\relax
+ #2%
+\else
+ \ifx1#1\relax
+ #2%
+ \else
+ \ifx2#1\relax
+ #2%
+ \else
+ \ifx3#1\relax
+ #2%
+ \else
+ \ifx4#1\relax
+ #2%
+ \else
+ \ifx5#1\relax
+ #2%
+ \else
+ \ifx6#1\relax
+ #2%
+ \else
+ \ifx7#1\relax
+ #2%
+ \else
+ \ifx8#1\relax
+ #2%
+ \else
+ \ifx9#1\relax
+ #2%
+ \else
+ \expandafter\ifx\@dtl@decimal#1\relax
+ #2%
+ \else
+ #3%
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@checknumericalloop}
+% Check numerical loop. This iterates through each character
+% until \cs{@nil} is reached, or invalid character found.
+% Increments \cs{@dtl@tmpcount} each time it encounters a
+% decimal character.\changes{1.01}{2007 Aug 17}{fixed bug caused
+% by commands occuring within text being tested}
+% \begin{macrocode}
+\def\@dtl@checknumericalloop#1#2\@nil{%
+\def\@dtl@tmp{#1}%
+\ifx\@nnil\@dtl@tmp\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop%
+\else
+ \@dtl@ifDigitOrDecimalSep{#1}{%
+ \let\@dtl@chcknumnext=\@dtl@checknumericalloop%
+ \expandafter\ifx\@dtl@decimal#1\relax
+ \if@dtl@numgrpsep
+ \ifnum\@dtl@numgrpsepcount=3\relax
+ \@dtl@numgrpsepcount=-1\relax
+ \else
+ \@dtl@datatype=0\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop
+ \fi
+ \else
+ \@dtl@numgrpsepcount=-1\relax
+ \fi
+ \else
+ \ifnum\@dtl@numgrpsepcount=-1\relax
+ \else
+ \advance\@dtl@numgrpsepcount by 1\relax
+ \fi
+ \fi
+}{%
+\ifx\@dtl@numbergroupchar\@dtl@tmp\relax
+ \@dtl@numgrpseptrue
+ \ifnum\@dtl@numgrpsepcount<3\relax
+ \@dtl@datatype=0\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop
+ \else
+ \@dtl@numgrpsepcount=0\relax
+ \fi
+\else
+ \@dtl@datatype=0\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop
+\fi
+}%
+ \ifx\@dtl@decimal\@dtl@tmp\relax
+ \ifnum\@dtl@datatype<3\relax
+ \@dtl@datatype=2\relax
+ \fi
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount>1\relax
+ \@dtl@datatype=0\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop%
+ \fi
+ \fi
+\fi
+\@dtl@chcknumnext#2\@nil
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@checknumericalnoop}
+% End loop
+% \begin{macrocode}
+\def\@dtl@checknumericalnoop#1\@nil#2{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumerical}
+%\begin{definition}
+%\cs{DTLifnumerical}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% Tests the first argument, if
+% its numerical do second argument, otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\DTLifnumerical}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=0\relax#3\else#2\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifreal}
+%\begin{definition}
+%\cs{DTLifreal}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% Tests the first argument, if
+% it's a real number (not an integer) do second argument,
+% otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\DTLifreal}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=2\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifint}
+%\begin{definition}
+%\cs{DTLifint}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% Tests the first argument, if
+% it's an integer do second argument,
+% otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\DTLifint}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=1\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstring}
+%\begin{definition}
+%\cs{DTLifstring}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% Tests the first argument, if
+% it's a string do second argument,
+% otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\DTLifstring}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=0\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifcurrency}
+%\begin{definition}
+%\cs{DTLifcurrency}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% Tests the first argument, if
+% it starts with the currency symbol do second argument,
+% otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\DTLifcurrency}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=3\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifcurrencyunit}
+%\begin{definition}
+%\cs{DTLifcurrencyunit}\marg{arg}\marg{symbol}\marg{true
+% part}\marg{false part}
+%\end{definition}
+% This tests if \meta{arg} is currency, and uses the currency unit
+% \meta{symbol}. If true do third argument, otherwise
+% do fourth argument.
+% \begin{macrocode}
+\newcommand*{\DTLifcurrencyunit}[4]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=3\relax
+ \ifthenelse{\equal{\@dtl@org@currency}{#2}}{#3}{#4}%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifcasedatatype}
+%\begin{definition}
+%\cs{DTLifcasedatatype}\marg{arg}\marg{string case}\marg{int
+%case}\marg{real case}\marg{currency case}
+%\end{definition}
+% If \meta{arg} is a string, do \meta{string case}, if \meta{arg}
+% is an integer do \meta{int case}, if \meta{arg} is a real number,
+% do \meta{real case}, if \meta{arg} is currency, do \meta{curreny
+%case}.
+% \begin{macrocode}
+\newcommand{\DTLifcasedatatype}[5]{%
+\@dtl@checknumerical{#1}%
+\ifcase\@dtl@datatype
+ #2% string
+\or
+ #3% integer
+\or
+ #4% number
+\or
+ #5% currency
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testbothnumerical}
+%\begin{definition}
+%\cs{dtl@testbothnumerical}\marg{arg1}\marg{arg2}
+%\end{definition}
+% Tests if both arguments are numerical. This sets
+% the conditional \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testbothnumerical}[2]{%
+\dtl@ifsingle{#1}{%
+ \edef\@dtl@tmp{#1}}{%
+ \def\@dtl@tmp{#1}}%
+\expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+\edef\@dtl@firsttype{\number\@dtl@datatype}%
+\dtl@ifsingle{#2}{%
+ \edef\@dtl@tmp{#2}}{%
+ \def\@dtl@tmp{#2}}%
+\expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+\multiply\@dtl@datatype by \@dtl@firsttype\relax
+\ifnum\@dtl@datatype>0\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumlt}
+%\begin{definition}
+%\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \marg{num1} $<$ \marg{num2}. Both numbers
+% need to have the decimal separator changed to a dot
+% to ensure that it works with \cs{FPiflt}
+% \begin{macrocode}
+\newcommand*{\DTLifnumlt}[4]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \FPiflt{\@dtl@numi}{\@dtl@numii}%
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\label{src:dtlcompare}
+%\begin{macro}{\dtlcompare}
+%\begin{definition}
+%\cs{dtlcompare}\marg{count}\marg{string1}\marg{string2}
+%\end{definition}
+% Compares \meta{string1} and \meta{string2}, and stores the
+% result in the count register \meta{count}. The result may be
+% one of:
+%\par\vskip\baselineskip\noindent
+%\begin{tabular}{rl}
+%-1 & if \meta{string1} is considered to be less than
+%\meta{string2}\\
+%0 & if \meta{string1} is considered to be the same as
+%\meta{string2}\\
+%1 & if \meta{string1} is considered to be greater than
+%\meta{string2}
+%\end{tabular}
+%\par\vskip\baselineskip\noindent
+%Note that for the purposes of string comparisons, commands within
+%\meta{string1} and \meta{string2} are ignored, except for
+%\cs{space} and "~", which are both treated as a space (character
+%code 32.) The following
+%examples assume that the count register \cs{mycount} has been
+%defined as follows:
+%\begin{verbatim}
+%\newcount\mycount
+%\end{verbatim}
+%\newcount\mycount\par\noindent
+%\textbf{Examples:}
+%\begin{enumerate}
+%\item
+%\begin{verbatim}
+%\dtlcompare{\mycount}{Z\"oe}{Zoe}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{Z\"oe}{Zoe}\number\mycount, since the accent
+%command is ignored.
+%
+%\item
+%\begin{verbatim}
+%\dtlcompare{\mycount}{foo}{Foo}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{foo}{Foo}\number\mycount, since the comparison
+%is case sensitive, however, note the following example:
+%\item
+%\begin{verbatim}
+%\dtlcompare{\mycount}{foo}{\uppercase{f}oo}\number\mycount
+%\end{verbatim}
+%which produces:
+%\dtlcompare{\mycount}{foo}{\uppercase{f}oo}\number\mycount, since
+%the \cs{uppercase} command is ignored.
+%
+%\item You can ``trick'' \cs{dtlcompare} using a command which doesn't
+%output any text. Suppose you have defined the following command:
+%\begin{verbatim}
+%\newcommand*{\noopsort}[1]{}
+%\end{verbatim}
+%\providecommand*{\noopsort}[1]{}
+%then "\noopsort{a}foo" produces the text: \noopsort{a}foo, however
+%the following
+%\begin{verbatim}
+%\dtlcompare{\mycount}{\noopsort{a}foo}{bar}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{\noopsort{a}foo}{bar}\number\mycount,
+%since the command \cs{noopsort} is disregarded when the comparison
+%is made, so \cs{dtlcompare} just compares "{a}foo" with "bar", and
+%since "a" is less than "b", the first string is considered to be less
+%than the second string.
+%
+%\item Note that this also means that:
+%\begin{verbatim}
+%\def\mystr{abc}%
+%\dtlcompare{\mycount}{\mystr}{abc}\number\mycount
+%\end{verbatim}
+%produces:
+%\def\mystr{abc}\relax
+%\dtlcompare{\mycount}{\mystr}{abc}\number\mycount, since the command
+%\cs{mystr} is disregarded, which means that \cs{dtlcompare} is
+%comparing an empty string with the string "abc".
+%
+%\item Spaces count in the comparison:
+%\begin{verbatim}
+%\dtlcompare{\mycount}{ab cd}{abcd}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{ab cd}{abcd}\number\mycount,
+%but sequential spaces are treated as a single space:
+%\begin{verbatim}
+%\dtlcompare{\mycount}{ab cd}{ab cd}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{ab cd}{ab cd}\number\mycount.
+%
+%\item As usual, spaces following command names are ignored, so
+%\begin{verbatim}
+%\dtlcompare{\mycount}{ab\relax cd}{ab cd}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{ab\relax cd}{ab cd}\number\mycount.
+%
+%\item "~" and \cs{space} are considered to be the same as a
+% space:
+%\begin{verbatim}
+%\dtlcompare{\mycount}{ab cd}{ab~cd}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{ab cd}{ab~cd}\number\mycount.
+%\end{enumerate}
+%\changes{1.01}{2007 Aug 17}{replaces \cs{compare} (no
+% longer using compare.tex)}
+% \begin{macrocode}
+\newcommand*{\dtlcompare}[3]{%
+\dtl@subnobrsp{#2}{\@dtl@argA}%
+\dtl@subnobrsp{#3}{\@dtl@argB}%
+\ifx\@dtl@argA\@empty
+ \ifx\@dtl@argB\@empty
+ #1=0\relax
+ \else
+ #1=-1\relax
+ \fi
+\else
+ \ifx\@dtl@argB\@empty
+ #1=1\relax
+ \else
+ \DTLsubstituteall{\@dtl@argA}{ }{\space }%
+ \DTLsubstituteall{\@dtl@argB}{ }{\space }%
+ \expandafter\dtl@getfirst\@dtl@argA\end
+ \let\dtl@firstA=\dtl@first
+ \let\dtl@restA=\dtl@rest
+ \expandafter\dtl@getfirst\@dtl@argB\end
+ \let\dtl@firstB=\dtl@first
+ \let\dtl@restB=\dtl@rest
+ \expandafter\dtl@ifsingle\expandafter{\dtl@firstA}{%
+ \expandafter\dtl@ifsingle\expandafter{\dtl@firstB}{%
+ \expandafter\dtl@setcharcode\expandafter{\dtl@firstA}{\dtl@codeA}%
+ \expandafter\dtl@setcharcode\expandafter{\dtl@firstB}{\dtl@codeB}%
+ \ifnum\dtl@codeA=-1\relax
+ \ifnum\dtl@codeB=-1\relax
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlcompare{\noexpand#1}{\dtl@restA}{\dtl@restB}}%
+ \dtl@donext
+ \else
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}{\dtl@restA}{\dtl@firstB\dtl@restB}}%
+ \dtl@donext
+ \fi
+ \else
+ \ifnum\dtl@codeB=-1\relax
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@restB}}%
+ \dtl@donext
+ \else
+ \ifnum\dtl@codeA<\dtl@codeB
+ #1=-1\relax
+ \else
+ \ifnum\dtl@codeA>\dtl@codeB
+ #1=1\relax
+ \else
+ \ifx\dtl@restA\@empty
+ \ifx\dtl@restB\@empty
+ #1=0\relax
+ \else
+ #1=-1\relax
+ \fi
+ \else
+ \ifx\restB\@empty
+ #1=1\relax
+ \else
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}{\dtl@restA}{\dtl@restB}}%
+ \dtl@donext
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ }{%
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}%
+ \dtl@donext
+ }}{%
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}%
+ \dtl@donext
+ }%
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@getfirst}
+% Gets the first object, and stores in \cs{dtl@first}. The remainder
+% is stored in \cs{dtl@rest}.
+% \begin{macrocode}
+\def\dtl@getfirst#1#2\end{%
+\def\dtl@first{#1}%
+\ifx\dtl@first\@empty
+ \def\dtl@rest{#2}%
+\else
+ \dtl@ifsingle{#1}{\def\dtl@rest{#2}}{\dtl@getfirst#1#2\end}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Count registers to store character codes:
+% \begin{macrocode}
+\newcount\dtl@codeA
+\newcount\dtl@codeB
+% \end{macrocode}
+%\begin{macro}{\dtl@setcharcode}
+%\begin{definition}
+%\cs{dtl@setcharcode}\marg{c}\marg{count register}
+%\end{definition}
+% Sets \meta{count register} to the character code of \meta{c}, or to
+% -1 if \meta{c} is a control sequence, unless \meta{c} is either
+% \cs{space} or |~| in which case it sets \meta{count register}
+% to the character code of the space character.
+% \begin{macrocode}
+\newcommand*{\dtl@setcharcode}[2]{%
+\def\@dtl@tmp{#1}%
+\ifx\@dtl@tmp\@empty
+ #2=-1\relax
+\else
+ \ifx#1\space\relax
+ #2=`\ \relax
+ \else
+ \ifx#1~\relax
+ #2=`\ \relax
+ \else
+ \ifcat\noexpand#1\relax%
+ #2=-1\relax
+ \else
+ #2=`#1\relax
+ \fi
+ \fi
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@setlccharcode}
+%\begin{definition}
+%\cs{dtl@setlccharcode}\marg{c}\marg{count register}
+%\end{definition}
+% As \cs{dtl@setlccharcode} except it sets \meta{count register}
+% to the lower case character code of \meta{c}, unless \meta{c}
+% is a control sequence, in which case it does the same as
+% \cs{dtl@setcharcode}.
+% \begin{macrocode}
+\newcommand*{\dtl@setlccharcode}[2]{%
+\def\@dtl@tmp{#1}%
+\ifx\@dtl@tmp\@empty
+ #2=-1\relax
+\else
+ \ifx#1\space\relax
+ #2=`\ \relax
+ \else
+ \ifx#1~\relax
+ #2=`\ \relax
+ \else
+ \ifcat\noexpand#1\relax%
+ #2=-1\relax
+ \else
+ #2=\lccode`#1\relax
+ \fi
+ \fi
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlicompare}
+%\begin{definition}
+%\cs{dtlicompare}\marg{count}\marg{string1}\marg{string2}
+%\end{definition}
+% As \cs{dtlcompare} but ignores case.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\dtlicompare}[3]{%
+\dtl@subnobrsp{#2}{\@dtl@argA}%
+\dtl@subnobrsp{#3}{\@dtl@argB}%
+\ifx\@dtl@argA\@empty
+ \ifx\@dtl@argB\@empty
+ #1=0\relax
+ \else
+ #1=-1\relax
+ \fi
+\else
+ \ifx\@dtl@argB\@empty
+ #1=1\relax
+ \else
+ \DTLsubstituteall{\@dtl@argA}{ }{\space }%
+ \DTLsubstituteall{\@dtl@argB}{ }{\space }%
+ \expandafter\dtl@getfirst\@dtl@argA\end
+ \let\dtl@firstA=\dtl@first
+ \let\dtl@restA=\dtl@rest
+ \expandafter\dtl@getfirst\@dtl@argB\end
+ \let\dtl@firstB=\dtl@first
+ \let\dtl@restB=\dtl@rest
+ \expandafter\dtl@ifsingle\expandafter{\dtl@firstA}{%
+ \expandafter\dtl@ifsingle\expandafter{\dtl@firstB}{%
+ \expandafter\dtl@setlccharcode\expandafter{\dtl@firstA}{\dtl@codeA}%
+ \expandafter\dtl@setlccharcode\expandafter{\dtl@firstB}{\dtl@codeB}%
+ \ifnum\dtl@codeA=-1\relax
+ \ifnum\dtl@codeB=-1\relax
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlicompare{\noexpand#1}{\dtl@restA}{\dtl@restB}}%
+ \dtl@donext
+ \else
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlicompare
+ {\noexpand#1}{\dtl@restA}{\dtl@firstB\dtl@restB}}%
+ \dtl@donext
+ \fi
+ \else
+ \ifnum\dtl@codeB=-1\relax
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlicompare
+ {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@restB}}%
+ \dtl@donext
+ \else
+ \ifnum\dtl@codeA<\dtl@codeB
+ #1=-1\relax
+ \else
+ \ifnum\dtl@codeA>\dtl@codeB
+ #1=1\relax
+ \else
+ \ifx\dtl@restA\@empty
+ \ifx\dtl@restB\@empty
+ #1=0\relax
+ \else
+ #1=-1\relax
+ \fi
+ \else
+ \ifx\restB\@empty
+ #1=1\relax
+ \else
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlicompare
+ {\noexpand#1}{\dtl@restA}{\dtl@restB}}%
+ \dtl@donext
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ }{%
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlicompare
+ {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}%
+ \dtl@donext
+ }}{%
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlicompare
+ {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}%
+ \dtl@donext
+ }%
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstringlt}
+%\begin{definition}
+%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison (Starred version ignores case)
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifstringlt}{\@ifstar\@sDTLifstringlt\@DTLifstringlt}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifstringlt}[4]{%
+\protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+\@dtl@tmpcmp
+\ifnum\@dtl@tmpcount<0\relax
+ #3%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifstringlt}[4]{%
+\protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+\@dtl@tmpcmp
+\ifnum\@dtl@tmpcount<0\relax
+ #3%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLiflt}
+%\begin{definition}
+%\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+% Does \cs{DTLifnumlt} if both \meta{arg1} and \meta{arg2} are
+% numerical, otherwise do \cs{DTLifstringlt} (unstarred version)
+% or \cs{DTLifstringlt*} (starred version).
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLiflt}{\@ifstar\@sDTLiflt\@DTLiflt}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLiflt}[4]{%
+\dtl@testbothnumerical{#1}{#2}%
+\if@dtl@condition
+ \DTLifnumlt{#1}{#2}{#3}{#4}%
+\else
+ \@DTLifstringlt{#1}{#2}{#3}{#4}%
+\fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLiflt}[4]{%
+\dtl@testbothnumerical{#1}{#2}%
+\if@dtl@condition
+ \DTLifnumlt{#1}{#2}{#3}{#4}%
+\else
+ \@sDTLifstringlt{#1}{#2}{#3}{#4}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumgt}
+%\begin{definition}
+%\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \marg{num1} $>$ \marg{num2}. Both numbers
+% need to have the decimal separator changed to a dot
+% to ensure that it works with \cs{FPifgt}
+% \begin{macrocode}
+\newcommand*{\DTLifnumgt}[4]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \FPifgt{\@dtl@numi}{\@dtl@numii}%
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstringgt}
+%\begin{definition}
+%\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison (starred version ignores case)
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifstringgt}{\@ifstar\@sDTLifstringgt\@DTLifstringgt}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifstringgt}[4]{%
+\protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+\@dtl@tmpcmp
+\ifnum\@dtl@tmpcount>0\relax
+ #3%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifstringgt}[4]{%
+\protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+\@dtl@tmpcmp
+\ifnum\@dtl@tmpcount>0\relax
+ #3%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifgt}
+%\begin{definition}
+%\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+% Does \cs{DTLifnumgt} if both \meta{arg1} and \meta{arg2} are
+% numerical, otherwise do \cs{DTLifstringgt} or \cs{DTLifstringgt*}.
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifgt}{\@ifstar\@sDTLifgt\@DTLifgt}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifgt}[4]{%
+\dtl@testbothnumerical{#1}{#2}%
+\if@dtl@condition
+ \DTLifnumgt{#1}{#2}{#3}{#4}%
+\else
+ \@DTLifstringgt{#1}{#2}{#3}{#4}%
+\fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifgt}[4]{%
+\dtl@testbothnumerical{#1}{#2}%
+\if@dtl@condition
+ \DTLifnumgt{#1}{#2}{#3}{#4}%
+\else
+ \@sDTLifstringgt{#1}{#2}{#3}{#4}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumeq}
+%\begin{definition}
+%\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \marg{num1} = \marg{num2}. Both numbers
+% need to have the decimal separator changed to a dot
+% to ensure that it works with \cs{FPifeq}
+% \begin{macrocode}
+\newcommand*{\DTLifnumeq}[4]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \FPifeq{\@dtl@numi}{\@dtl@numii}%
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstringeq}
+%\begin{definition}
+%\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison (starred version ignores case)
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifstringeq}{\@ifstar\@sDTLifstringeq\@DTLifstringeq}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifstringeq}[4]{%
+\protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+\@dtl@tmpcmp
+\ifnum\@dtl@tmpcount=0\relax
+ #3%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifstringeq}[4]{%
+\protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+\@dtl@tmpcmp
+\ifnum\@dtl@tmpcount=0\relax
+ #3%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifeq}
+%\begin{definition}
+%\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+% Does \cs{DTLifnumeq} if both \meta{arg1} and \meta{arg2} are
+% numerical, otherwise do \cs{DTLifstringeq} or \cs{DTLifstringeq*}.
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifeq}{\@ifstar\@sDTLifeq\@DTLifeq}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifeq}[4]{%
+\dtl@testbothnumerical{#1}{#2}%
+\if@dtl@condition
+ \DTLifnumeq{#1}{#2}{#3}{#4}%
+\else
+ \@DTLifstringeq{#1}{#2}{#3}{#4}%
+\fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifeq}[4]{%
+\dtl@testbothnumerical{#1}{#2}%
+\if@dtl@condition
+ \DTLifnumeq{#1}{#2}{#3}{#4}%
+\else
+ \@sDTLifstringeq{#1}{#2}{#3}{#4}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifSubString}
+%\begin{definition}
+%\cs{DTLifSubString}\marg{string}\marg{sub string}\marg{true
+%part}\marg{false part}
+%\end{definition}
+% If \meta{sub string} is contained in \meta{string} does
+%\meta{true part}, otherwise does \meta{false part}.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLifSubString}[4]{%
+\protected@edef\@dtl@tmp{\noexpand\dtl@testifsubstring
+{#1}{#2}}%
+\@dtl@tmp
+\if@dtl@condition
+ #3%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testifsubstring}
+% \begin{macrocode}
+\newcommand*{\dtl@testifsubstring}[2]{%
+\dtl@subnobrsp{#1}{\@dtl@argA}%
+\dtl@subnobrsp{#2}{\@dtl@argB}%
+\ifx\@dtl@argB\@empty
+ \@dtl@conditiontrue
+\else
+ \ifx\@dtl@argA\@empty
+ \@dtl@conditionfalse
+ \else
+ \dtl@teststartswith{#1}{#2}%
+ \if@dtl@condition
+ \else
+ \DTLsubstituteall{\@dtl@argA}{ }{\space }%
+ \expandafter\dtl@getfirst\@dtl@argA\end
+ \expandafter\dtl@ifsingle\expandafter{\dtl@first}{%
+ \expandafter\dtl@testifsubstring\expandafter{\dtl@rest}{#2}%
+ }{%
+ \protected@edef\@dtl@donext{\noexpand\dtl@testifsubstring
+ {\dtl@first\dtl@rest}{\@dtl@argB}}%
+ \@dtl@donext
+ }%
+ \fi
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifStartsWith}
+%\begin{definition}
+%\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true
+%part}\marg{false part}
+%\end{definition}
+%If \meta{string} starts with \meta{substring}, this does
+%\meta{true part}, otherwise it does \meta{false part}.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLifStartsWith}[4]{%
+\@dtl@conditionfalse
+\protected@edef\@dtl@tmp{\noexpand\dtl@teststartswith{#1}{#2}}%
+\@dtl@tmp
+\if@dtl@condition
+ #3%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@teststartswith}
+%\begin{definition}
+%\cs{dtl@teststartswith}\marg{string}\marg{prefix}
+%\end{definition}
+% Tests if \meta{string} starts with \meta{prefix}. This sets
+% \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@teststartswith}[2]{%
+\dtl@subnobrsp{#1}{\@dtl@argA}%
+\dtl@subnobrsp{#2}{\@dtl@argB}%
+\ifx\@dtl@argA\@empty
+ \ifx\@dtl@argB\@empty
+ \@dtl@conditiontrue
+ \else
+ \@dtl@conditionfalse
+ \fi
+\else
+ \ifx\@dtl@argB\@empty
+ \@dtl@conditiontrue
+ \else
+ \DTLsubstituteall{\@dtl@argA}{ }{\space }%
+ \DTLsubstituteall{\@dtl@argB}{ }{\space }%
+ \expandafter\dtl@getfirst\@dtl@argA\end
+ \let\dtl@firstA=\dtl@first
+ \let\dtl@restA=\dtl@rest
+ \expandafter\dtl@getfirst\@dtl@argB\end
+ \let\dtl@firstB=\dtl@first
+ \let\dtl@restB=\dtl@rest
+ \expandafter\dtl@ifsingle\expandafter{\dtl@firstA}{%
+ \expandafter\dtl@ifsingle\expandafter{\dtl@firstB}{%
+ \expandafter\dtl@setcharcode\expandafter{\dtl@firstA}{\dtl@codeA}%
+ \expandafter\dtl@setcharcode\expandafter{\dtl@firstB}{\dtl@codeB}%
+ \ifnum\dtl@codeA=-1\relax
+ \ifnum\dtl@codeB=-1\relax
+ \protected@edef\dtl@donext{%
+ \noexpand\dtl@teststartswith{\dtl@restA}{\dtl@restB}}%
+ \dtl@donext
+ \else
+ \protected@edef\dtl@donext{%
+ \noexpand\dtl@teststartswith
+ {\dtl@restA}{\dtl@firstB\dtl@restB}}%
+ \dtl@donext
+ \fi
+ \else
+ \ifnum\dtl@codeB=-1\relax
+ \protected@edef\dtl@donext{%
+ \noexpand\dtl@teststartswith
+ {\dtl@firstA\dtl@restA}{\dtl@restB}}%
+ \dtl@donext
+ \else
+ \ifnum\dtl@codeA=\dtl@codeB
+ \protected@edef\dtl@donext{%
+ \noexpand\dtl@teststartswith{\dtl@restA}{\dtl@restB}}%
+ \dtl@donext
+ \else
+ \@dtl@conditionfalse
+ \fi
+ \fi
+ \fi
+ }{%
+ \protected@edef\dtl@donext{%
+ \noexpand\dtl@teststartswith
+ {\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}%
+ \dtl@donext
+ }}{%
+ \protected@edef\dtl@donext{%
+ \noexpand\dtl@teststartswith
+ {\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}%
+ }%
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumclosedbetween}
+%\begin{definition}
+%\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}.
+% \begin{macrocode}
+\newcommand*{\DTLifnumclosedbetween}[5]{%
+\DTLconverttodecimal{#1}{\@dtl@numi}%
+\DTLconverttodecimal{#2}{\@dtl@numii}%
+\DTLconverttodecimal{#3}{\@dtl@numiii}%
+\DTLifFPclosedbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstringclosedbetween}
+%\begin{definition}
+%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison (starred version ignores case)
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifstringclosedbetween}{%
+\@ifstar\@sDTLifstringclosedbetween\@DTLifstringclosedbetween}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifstringclosedbetween}[5]{%
+\protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+\@dtl@tmpcmp
+\let\@dtl@dovalue\relax
+\ifnum\@dtl@tmpcount<0\relax
+ \def\@dtl@dovalue{#5}%
+\fi
+\ifx\@dtl@dovalue\relax
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#3}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount>0\relax
+ \def\@dtl@dovalue{#5}%
+ \else
+ \def\@dtl@dovalue{#4}%
+ \fi
+\fi
+\@dtl@dovalue
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifstringclosedbetween}[5]{%
+\protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+\@dtl@tmpcmp
+\let\@dtl@dovalue\relax
+\ifnum\@dtl@tmpcount<0\relax
+ \def\@dtl@dovalue{#5}%
+\fi
+\ifx\@dtl@dovalue\relax
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#3}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount>0\relax
+ \def\@dtl@dovalue{#5}%
+ \else
+ \def\@dtl@dovalue{#4}%
+ \fi
+\fi
+\@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifclosedbetween}
+%\begin{definition}
+%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Does \cs{DTLifnumclosedbetween} if \marg{arg}, \meta{min} and \meta{max} are
+% numerical, otherwise do \cs{DTLifstringclosedbetween}
+% or \cs{DTLifstringclosedbetween*}.
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifclosedbetween}{%
+\@ifstar\@sDTLifclosedbetween\@DTLifclosedbetween}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifclosedbetween}[5]{%
+\dtl@testbothnumerical{#2}{#3}%
+\if@dtl@condition
+ \dtl@ifsingle{#1}{%
+ \edef\@dtl@tmp{#1}}{%
+ \def\@dtl@tmp{#1}}%
+ \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+ \ifnum\@dtl@datatype>0\relax
+ \DTLifnumclosedbetween{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \@DTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+\else
+ \@DTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}%
+\fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifclosedbetween}[5]{%
+\dtl@testbothnumerical{#2}{#3}%
+\if@dtl@condition
+ \dtl@ifsingle{#1}{%
+ \edef\@dtl@tmp{#1}}{%
+ \def\@dtl@tmp{#1}}%
+ \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+ \ifnum\@dtl@datatype>0\relax
+ \DTLifnumclosedbetween{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \@sDTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+\else
+ \@sDTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumopenbetween}
+%\begin{definition}
+%\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max}.
+% \begin{macrocode}
+\newcommand*{\DTLifnumopenbetween}[5]{%
+\DTLconverttodecimal{#1}{\@dtl@numi}%
+\DTLconverttodecimal{#2}{\@dtl@numii}%
+\DTLconverttodecimal{#3}{\@dtl@numiii}%
+\DTLifFPopenbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstringopenbetween}
+%\begin{definition}
+%\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison (starred version ignores case)
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifstringopenbetween}{%
+\@ifstar\@sDTLifstringopenbetween\@DTLifstringopenbetween}
+% \end{macrocode}
+% Unstarred version:
+% \begin{macrocode}
+\newcommand*{\@DTLifstringopenbetween}[5]{%
+\protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+\@dtl@tmpcmp
+\let\@dtl@dovalue\relax
+\ifnum\@dtl@tmpcount>0\relax
+\else
+ \def\@dtl@dovalue{#5}%
+\fi
+\ifx\@dtl@dovalue\relax
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#3}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount<0\relax
+ \def\@dtl@dovalue{#4}%
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+\fi
+\@dtl@dovalue
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifstringopenbetween}[5]{%
+\protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+\@dtl@tmpcmp
+\let\@dtl@dovalue\relax
+\ifnum\@dtl@tmpcount>0\relax
+\else
+ \def\@dtl@dovalue{#5}%
+\fi
+\ifx\@dtl@dovalue\relax
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#3}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount<0\relax
+ \def\@dtl@dovalue{#4}%
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+\fi
+\@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifopenbetween}
+%\begin{definition}
+%\cs{DTLifopenbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Does \cs{DTLifnumopenbetween} if \marg{arg}, \meta{min} and \meta{max} are
+% numerical, otherwise do \cs{DTLifstringopenbetween}
+% or \cs{DTLifstringopenbetween*}.
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifopenbetween}{%
+\@ifstar\@sDTLifopenbetween\@DTLifopenbetween}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifopenbetween}[5]{%
+\dtl@testbothnumerical{#2}{#3}%
+\if@dtl@condition
+ \dtl@ifsingle{#1}{%
+ \edef\@dtl@tmp{#1}}{%
+ \def\@dtl@tmp{#1}}%
+ \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+ \ifnum\@dtl@datatype>0\relax
+ \DTLifnumopenbetween{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \@DTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+\else
+ \@DTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}%
+\fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifopenbetween}[5]{%
+\dtl@testbothnumerical{#2}{#3}%
+\if@dtl@condition
+ \dtl@ifsingle{#1}{%
+ \edef\@dtl@tmp{#1}}{%
+ \def\@dtl@tmp{#1}}%
+ \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+ \ifnum\@dtl@datatype>0\relax
+ \DTLifnumopenbetween{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \@sDTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+\else
+ \@sDTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifFPopenbetween}
+%\begin{definition}
+%\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max} where
+% all arguments are in standard fixed point notation.
+% \begin{macrocode}
+\newcommand*{\DTLifFPopenbetween}[5]{%
+ \let\@dtl@dovalue\relax
+ \FPifgt{#1}{#2}%
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \FPiflt{#1}{#3}%
+ \ifx\@dtl@dovalue\relax
+ \def\@dtl@dovalue{#4}%
+ \fi
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+\@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifFPclosedbetween}
+%\begin{definition}
+%\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}.
+% \begin{macrocode}
+\newcommand*{\DTLifFPclosedbetween}[5]{%
+ \let\@dtl@dovalue\relax
+ \FPifgt{#1}{#3}%
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \FPiflt{#1}{#2}%
+ \ifx\@dtl@dovalue\relax
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \else
+ \def\@dtl@dovalue{#4}%
+ \fi
+\@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+% The following conditionals are only meant to be used within
+% \cs{DTLforeach} as they depend on the counter
+% \texttt{DTLrow}\meta{n}.
+%
+%\begin{macro}{\DTLiffirstrow}
+%\begin{definition}
+%\cs{DTLiffirstrow}\marg{true part}\marg{false part}
+%\end{definition}
+% Test if the current row is the first row. (This takes
+% \meta{condition}, the optional argument of \cs{DTLforeach},
+% into account.)
+% \begin{macrocode}
+\newcommand{\DTLiffirstrow}[2]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLiffirstrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+\expandafter\ifnum\csname c@DTLrow\romannumeral
+\dtlforeachlevel\endcsname
+=1\relax#1\else#2\fi
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLiflastrow}
+%\begin{definition}
+%\cs{DTLiflastrow}\marg{true part}\marg{false part}
+%\end{definition}
+% Checks if the current row is the last row of the database.
+% It doesn't take the condition (the optional argument of
+% \cs{DTLforeach}) into account, so its possible it may never
+% do \meta{true part}, as the last row of the database may not
+% meet the condition. It is therefore not very useful and is
+% confusing since it behaves differently to \cs{DTLiffirstrow}
+% which does take the condition into account, so I have removed
+% its description from the main part of the manual. If you need
+% to use the optional argument of \cs{DTLforeach}, you will first
+% have to iterate through the database to count up the number
+% of rows which meet the condition, and then do another pass,
+% checking if the current row has reached that number.
+% This command requires at least v1.02 of the \sty{xfor} package.
+%\changes{1.01}{2007 Aug 17}{fixed bug}
+% \begin{macrocode}
+\newcommand{\DTLiflastrow}[2]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLiflastrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+\ifx\@dtl@nextrow\@nnil
+#1\else #2\fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifoddrow}
+%\begin{definition}
+%\cs{DTLifoddrow}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines whether the current row is odd (takes the optional
+% argument of \cs{DTLforeach} into account.)
+% \begin{macrocode}
+\newcommand{\DTLifoddrow}[2]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLifoddrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+\expandafter\ifodd\csname c@DTLrow\romannumeral
+\dtlforeachlevel\endcsname
+#1\else #2\fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+% \subsection{ifthen Conditionals}
+% The following commands provide conditionals \cs{DTLis}\ldots\
+% which can be used in \cs{ifthenelse}. First need to define
+% a new conditional:
+%\begin{macro}{\if@dtl@condition}
+% \begin{macrocode}
+\newif\if@dtl@condition
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testlt}
+% Command to test if first argument is less than second argument.
+% If either argument is a string, a case sensitive string comparison
+% is used instead.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testlt}[2]{%
+\DTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLislt}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLislt}[2]{%
+\TE@throw\noexpand\dtl@testlt{#1}{#2}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testiclt}
+% Command to test if first argument is less than second argument.
+% If either argument is a string, a case insensitive string comparison
+% is used instead.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testiclt}[2]{%
+\@sDTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLisilt}
+% Provide conditional command for use in \cs{ifthenelse}
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisilt}[2]{%
+\TE@throw\noexpand\dtl@testiclt{#1}{#2}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testgt}
+% Command to test if first number is greater than second number.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testgt}[2]{%
+\DTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisgt}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisgt}[2]{%
+\TE@throw\noexpand\dtl@testgt{#1}{#2}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testicgt}
+% Command to test if first number is greater than second number
+% (ignores case).
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testicgt}[2]{%
+\@sDTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisigt}
+% Provide conditional command for use in \cs{ifthenelse}
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisigt}[2]{%
+\TE@throw\noexpand\dtl@testicgt{#1}{#2}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testeq}
+% Command to test if first number is equal to the second number.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testeq}[2]{%
+\DTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLiseq}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLiseq}[2]{%
+\TE@throw\noexpand\dtl@testeq{#1}{#2}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testiceq}
+% Command to test if first number is equal to the second number
+% (ignores case).
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testiceq}[2]{%
+\@sDTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisieq}
+% Provide conditional command for use in \cs{ifthenelse}
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisieq}[2]{%
+\TE@throw\noexpand\dtl@testiceq{#1}{#2}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLisSubString}
+% Tests if second argument is contained in first argument.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisSubString}[2]{%
+\TE@throw\noexpand\dtl@testifsubstring{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLisPrefix}
+% Tests if first argument starts with second argument.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisPrefix}[2]{%
+\TE@throw\noexpand\dtl@teststartswith{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testclosedbetween}
+% Command to test if first value lies between second and third
+% values. (End points included, case sensitive.)
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testclosedbetween}[3]{%
+\DTLifclosedbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisclosedbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisclosedbetween}[3]{%
+\TE@throw\noexpand\dtl@testclosedbetween{#1}{#2}{#3}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testiclosedbetween}
+% Command to test if first value lies between second and third
+% values. (End points included, case ignored.)
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testiclosedbetween}[3]{%
+\@sDTLifclosedbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisiclosedbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisiclosedbetween}[3]{%
+\TE@throw\noexpand\dtl@testiclosedbetween{#1}{#2}{#3}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testopenbetween}
+% Command to test if first value lies between second and third
+% values. (End points excluded, case sensitive.)
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testopenbetween}[3]{%
+\DTLifopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue
+}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisopenbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisopenbetween}[3]{%
+\TE@throw\noexpand\dtl@testopenbetween{#1}{#2}{#3}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testiopenbetween}
+% Command to test if first value lies between second and third
+% values. (End points excluded, case ignored.)
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testiopenbetween}[3]{%
+\@sDTLifopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue
+}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisiopenbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisiopenbetween}[3]{%
+\TE@throw\noexpand\dtl@testiopenbetween{#1}{#2}{#3}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testclosedbetween}
+% Command to test if first number lies between second and third
+% numbers. (End points included, all arguments are fixed point
+% numbers in standard format.) This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPclosedbetween}[3]{%
+\DTLifFPclosedbetween{#1}{#2}{#3}%
+{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisFPclosedbetween}
+% \begin{macrocode}
+\newcommand*{\DTLisFPclosedbetween}[3]{%
+\TE@throw\noexpand\dtl@testFPclosedbetween{#1}{#2}{#3}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testopenbetween}
+% Command to test if first number lies between second and third
+% numbers. (End points excluded, all arguments are fixed point
+% numbers in standard format.) This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPopenbetween}[3]{%
+\DTLifFPopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPopenbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPopenbetween}[3]{%
+\TE@throw\noexpand\dtl@testFPopenbetween{#1}{#2}{#3}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testFPislt}
+% Command to test if first number is less than second
+% number where both numbers are in standard format.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPislt}[2]{%
+\FPiflt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPlt}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPlt}[2]{%
+\TE@throw\noexpand\dtl@testFPislt{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testFPisgt}
+% Command to test if first number is greater than second
+% number where both numbers are in standard format.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPisgt}[2]{%
+\FPifgt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPgt}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPgt}[2]{%
+\TE@throw\noexpand\dtl@testFPisgt{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testFPiseq}
+% Command to test if two numbers are equal, where both numbers
+% are in standard decimal format
+% \begin{macrocode}
+\newcommand*{\dtl@testFPiseq}[2]{%
+\FPifeq{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPeq}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPeq}[2]{%
+\TE@throw\noexpand\dtl@testFPiseq{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testFPislteq}
+% Command to test if first number is less than or equal to second
+% number where both numbers are in standard format.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPislteq}[2]{%
+\FPiflt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi
+\if@dtl@condition
+\else
+ \dtl@testFPiseq{#1}{#2}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPlteq}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPlteq}[2]{%
+\TE@throw\noexpand\dtl@testFPislteq{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testFPisgteq}
+% Command to test if first number is greater than or equal to second
+% number where both numbers are in standard format.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPisgteq}[2]{%
+\FPifgt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi
+\if@dtl@condition
+\else
+ \dtl@testFPiseq{#1}{#2}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPgteq}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPgteq}[2]{%
+\TE@throw\noexpand\dtl@testFPisgteq{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@teststring}
+% Command to test if argument is a string. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@teststring}[1]{%
+\DTLifstring{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisstring}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisstring}[1]{%
+\TE@throw\noexpand\dtl@teststring{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testnumerical}
+% Command to test if argument is a numerical. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@testnumerical}[1]{%
+\DTLifnumerical{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisnumerical}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisnumerical}[1]{%
+\TE@throw\noexpand\dtl@testnumerical{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testint}
+% Command to test if argument is an integer. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@testint}[1]{%
+\DTLifint{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisint}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisint}[1]{%
+\TE@throw\noexpand\dtl@testint{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testreal}
+% Command to test if argument is a real. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@testreal}[1]{%
+\DTLifreal{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisreal}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisreal}[1]{%
+\TE@throw\noexpand\dtl@testreal{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testcurrency}
+% Command to test if argument is a currency. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@testcurrency}[1]{%
+\DTLifcurrency{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLiscurrency}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLiscurrency}[1]{%
+\TE@throw\noexpand\dtl@testcurrency{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testcurrencyunit}
+% Command to test if argument is a currency with given unit. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@testcurrencyunit}[2]{%
+\DTLifcurrencyunit{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLiscurrencyunit}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLiscurrencyunit}[2]{%
+\TE@throw\noexpand\dtl@testcurrencyunit{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% \subsection{Defining New Databases}
+% A database is stored internally as a list of lists, where each list
+% is a row of data. The data is stored as a comma separated list of
+% \marg{id}\marg{value} pairs, where \meta{id} is an
+% identifier
+% and \meta{value} is the value.
+%
+%\begin{macro}{\DTLnewdb}
+% \cs{DTLnewdb}\marg{name}
+% initialises a database called \meta{name}. The keys associated
+% with this database are stored in \cs{dtlkeys@}\meta{name}
+% A new count register \cs{dtlrows@}\meta{db name} is created.
+% This stores the total number of rows in the data base.
+% \begin{macrocode}
+\newcommand*{\DTLnewdb}[1]{%
+\DTLifdbexists{#1}{%
+\PackageError{datatool}{Database `#1' already exists}{}}{%
+\dtl@message{Creating database `#1'}%
+\expandafter\gdef\csname dtldb@#1\endcsname{}%
+\expandafter\gdef\csname dtlkeys@#1\endcsname{}%
+\expandafter\global\expandafter\newcount\csname dtlrows@#1\endcsname}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLrowcount}
+%\begin{definition}
+% \cs{DTLrowcount}\marg{db name}
+%\end{definition}
+% The number of rows in the database called \meta{db name}.
+% \begin{macrocode}
+\newcommand*{\DTLrowcount}[1]{%
+\expandafter\number\csname dtlrows@#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifdbempty}
+%\begin{definition}
+% \cs{DTLifempty}\marg{name}\marg{true part}\marg{false part}
+%\end{definition}
+% Check if named database is empty (i.e.\ no rows have been added.)
+% \begin{macrocode}
+\newcommand{\DTLifdbempty}[3]{%
+\DTLifdbexists{#1}{%
+\expandafter\ifx\csname dtldb@#1\endcsname\@empty
+ #2%
+\else
+ #3%
+\fi}{%
+\PackageError{Database `#1' doesn't exist}{}{}}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLnewrow}
+%\begin{definition}
+% \cs{DTLnewrow}\marg{db name}
+%\end{definition}
+% Add a new row to named database.
+% \begin{macrocode}
+\newcommand*{\DTLnewrow}[1]{%
+\DTLifdbempty{#1}{%
+ \expandafter\gdef\csname dtldb@#1\endcsname{{}}%
+ \expandafter\global\expandafter\advance
+ \csname dtlrows@#1\endcsname by 1\relax
+ \dtl@message{New row added to database `#1'}%
+}{%
+ \expandafter\let\expandafter\@dtl@olddb\csname dtldb@#1\endcsname%
+ \expandafter\toks@\expandafter{\@dtl@olddb,{}}%
+ \expandafter\xdef\csname dtldb@#1\endcsname{\the\toks@}%
+ \expandafter\global\expandafter\advance
+ \csname dtlrows@#1\endcsname by 1\relax
+ \dtl@message{New row added to database `#1'}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLnewdbentry}
+%\begin{definition}
+% \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}.
+%\end{definition}
+% Adds an entry to the last row (adds new row if database is empty.)
+%
+% When a new entry is added, the control sequence
+% \cs{@dtl@idtype@}\meta{db name}\texttt{@}\meta{id} is checked.
+% This keeps track of the type of all the entries with the given ID
+% for the given database. If this control
+% sequence doesn't exist, a new one is created, and set to the
+% relevant type: 0 (string), 1 (int) or 2 (real). If it exists,
+% then it is set as follows: if has a value of 0 (string), it
+% remains unchanged. If it has another value, then it is set to
+% 2 (real) if it was either 1 or 2 and \meta{value} is 2, it is
+% set to 1 if \meta{value} is 1, otherwise it remains unchanged.
+% \begin{macrocode}
+\newcommand{\DTLnewdbentry}[3]{%
+% \end{macrocode}
+% Set \cs{@dtl@dbvalue} to the value of this entry.
+% \begin{macrocode}
+\@dtl@toks{#3}%
+\edef\@dtl@dbvalue{\the\@dtl@toks}%
+% \end{macrocode}
+% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow
+% for the ID to be stored in a control sequence.
+% \begin{macrocode}
+\edef\@dtl@dbid{#2}%
+% \end{macrocode}
+% Set up the correct entry format:
+% \begin{macrocode}
+\edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+% \end{macrocode}
+% If database is empty, add new row.
+% \begin{macrocode}
+\DTLifdbempty{#1}{\DTLnewrow{#1}}{}%
+% \end{macrocode}
+% Add the entry to the last row of the database:
+% Split the database into the last row
+% (\cs{@dtl@dblastrow}), and everything except the last row
+% (\cs{@dtl@dbrest}.)
+% \begin{macrocode}
+\expandafter\dtl@choplast\expandafter{%
+\csname dtldb@#1\endcsname}{\@dtl@dbrest}{\@dtl@dblastrow}%
+% \end{macrocode}
+% Check if the last row already contains an entry with this ID.
+% If so, generate an error, otherwise append this entry to the
+% row, and reconstruct database list.
+% \begin{macrocode}
+\dtl@ifrowcontains{#2}{\@dtl@dblastrow}{%
+\PackageError{datatool}{Can't add entry with ID `#2' to current
+row of database `#1'}{There is already an entry with this ID on
+the current row}}{%
+% \end{macrocode}
+% Append entry to last row
+% \begin{macrocode}
+\expandafter\@dtl@toks\expandafter{\@dtl@dbentry}%
+\ifthenelse{\equal{}{\@dtl@dblastrow}}{%
+ \edef\@dtl@dblastrow{\the\@dtl@toks}%
+}{%
+ \expandafter\toks@\expandafter{\@dtl@dblastrow}%
+ \edef\@dtl@dblastrow{\the\toks@,\the\@dtl@toks}%
+}%
+% \end{macrocode}
+% Reconstruct list.
+% \begin{macrocode}
+\expandafter\@dtl@toks\expandafter{\@dtl@dblastrow}%
+\ifthenelse{\equal{}{\@dtl@dbrest}}{%
+ \expandafter\long\expandafter\xdef\csname dtldb@#1\endcsname{%
+ {\the\@dtl@toks}}%
+}{%
+ \expandafter\toks@\expandafter{\@dtl@dbrest}%
+ \expandafter\long\expandafter\xdef\csname dtldb@#1\endcsname{%
+ \the\toks@,{\the\@dtl@toks}}%
+}%
+% \end{macrocode}
+% Set the keys
+% \begin{macrocode}
+\@dtl@setidtype{#1}{#2}{#3}%
+\expandafter\@dtl@setkeys\expandafter{#2}{#1}%
+}%
+\dtl@message{Added #2\space -> #3\space to database `#1'}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@setidtype}
+%\begin{definition}
+% \cs{@dtl@setidtype}\marg{db name}\marg{id}\marg{value}
+%\end{definition}
+% Set the type for \meta{id} according to \meta{value}.
+% If \meta{value} is empty, leave \cs{@dtl@idtype}\meta{id}
+% unchanged (if defined) or define as empty if not defined.
+%\changes{1.01}{2007 Aug 17}{Added currency check}
+%\changes{1.01}{2007 Aug 17}{Fixed bug when setting
+% \cs{@dtl@tmpcount}}
+% \begin{macrocode}
+\newcommand{\@dtl@setidtype}[3]{%
+% \end{macrocode}
+% Check the data type of this value.
+% \begin{macrocode}
+\@dtl@checknumerical{#3}%
+% \end{macrocode}
+% Store value if \cs{@dtl@value} to make it easier to test if it
+% is empty.
+% \begin{macrocode}
+\def\@dtl@value{#3}%
+% \end{macrocode}
+% Determine if this key already has a data type assigned to it.
+% \begin{macrocode}
+\@ifundefined{@dtl@idtype@#1@#2}{%
+% \end{macrocode}
+% This key doesn't have an associated data type, so set it to
+% this value's data type, unless the value is empty.
+% \begin{macrocode}
+\ifx\@dtl@value\@empty
+ \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{}%
+\else
+ \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
+ \the\@dtl@datatype}%
+\fi
+}{%
+% \end{macrocode}
+% This key already has an associated data type, but may need updating.
+% \begin{macrocode}
+\ifx\@dtl@value\@empty
+% \end{macrocode}
+% The value is empty, so do nothing.
+% \begin{macrocode}
+\else
+ \expandafter\ifx\csname @dtl@idtype@#1@#2\endcsname\@empty
+% \end{macrocode}
+% The data type is currently unset (all previous values for this
+% key were empty) so set the data type for this key to the data type
+% of the given value.
+% \begin{macrocode}
+ \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
+ \the\@dtl@datatype}%
+ \else
+% \end{macrocode}
+% Store the data type currently associated with this key in
+% \cs{@dtl@tmpcount}.
+% \begin{macrocode}
+ \expandafter\@dtl@tmpcount\expandafter=
+ \csname @dtl@idtype@#1@#2\endcsname\relax
+% \end{macrocode}
+% Determine whether to update the data type associated with this key.
+% \begin{macrocode}
+ \ifcase\@dtl@tmpcount
+% \end{macrocode}
+% The current data type is a string, so leave as it is
+% (string overrides all the other types.)
+% \begin{macrocode}
+ \or
+% \end{macrocode}
+% The current data type is an int, so set the data type of the given
+% value (all other data types override int.)
+% \begin{macrocode}
+ \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
+ \the\@dtl@datatype}%
+ \or
+% \end{macrocode}
+% The current data type is a real, set to real unless the given value
+% is a string or currency (real overrides int, but not string or
+% currency.)
+% \begin{macrocode}
+ \ifnum\@dtl@datatype=0\relax
+ \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}%
+ \else
+ \ifnum\@dtl@datatype=3\relax
+ \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{3}%
+ \else
+ \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{2}%
+ \fi
+ \fi
+ \or
+% \end{macrocode}
+% The current data type is currency, so set to currency unless
+% the given value is a string (currency overrides real and int,
+% but not string.)
+% \begin{macrocode}
+ \ifnum\@dtl@datatype=0\relax
+ \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}%
+ \else
+ \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{3}%
+ \fi
+ \fi
+ \fi
+\fi
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@setkeys}
+%\begin{definition}
+%\cs{@dtl@setkeys}\marg{key}\marg{db name}
+%\end{definition}
+% Adds \marg{key} to \cs{dtlkeys@}\meta{db name} if not already
+% in it.
+% \begin{macrocode}
+\newcommand*{\@dtl@setkeys}[2]{%
+\edef\@dtl@tmp{\csname dtlkeys@#2\endcsname}%
+\expandafter\@dtl@toks\expandafter{\@dtl@tmp}%
+\expandafter\ifx\csname dtlkeys@#2\endcsname\@empty
+ \expandafter\gdef\csname dtlkeys@#2\endcsname{#1}%
+\else
+ \@for\dtl@key:=\@dtl@tmp\do{%
+ \ifthenelse{\equal{\dtl@key}{#1}}{\@endfortrue}{}%
+ }%
+ \if@endfor
+ \else
+ \expandafter\xdef\csname dtlkeys@#2\endcsname{\the\@dtl@toks,#1}%
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@getidtype}
+%\begin{definition}
+% \cs{@dtl@getidtype}\marg{db name}\marg{id}
+%\end{definition}
+% Gets the data type for \meta{id} in given database.
+% \begin{macrocode}
+\newcommand*{\@dtl@getidtype}[2]{%
+\csname @dtl@idtype@#1@#2\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifdbexists}
+%\begin{definition}
+%\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part}
+%\end{definition}
+% Checks if a data base with the given name exists.
+% \begin{macrocode}
+\newcommand{\DTLifdbexists}[3]{%
+\@ifundefined{dtldb@#1}{#3}{#2}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@ifrowcontains}
+%\begin{definition}
+% \cs{dtl@ifrowcontains}\meta{id}\meta{cmd}\meta{true part}\meta{false
+%part}
+%\end{definition}
+% Checks to see if the row given by \meta{cmd} contains an
+% entry with ID given by \meta{id}. If true, do \meta{true part},
+% otherwise do \meta{false part}.
+% \begin{macrocode}
+\newcommand{\dtl@ifrowcontains}[4]{%
+\@for\@dtl@element:=#2\do{%
+\dtl@getentryid{\@dtl@element}{\@dtl@entryid}%
+\ifthenelse{\equal{#1}{\@dtl@entryid}}{\@endfortrue}{}%
+}%
+\if@endfor #3\else #4\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@getentryid}
+%\begin{definition}
+% \cs{dtl@getentryid}\meta{entry cmd}\meta{id cmd}
+%\end{definition}
+% Gets the ID for an entry given by \meta{entry cmd}, and stores in
+% in \meta{id cmd}.
+% \begin{macrocode}
+\newcommand*{\dtl@getentryid}[2]{\expandafter\@dtl@getentryid#1#2}
+\long\def\@dtl@getentryid#1#2#3{\def#3{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@getentryvalue}
+%\begin{definition}
+% \cs{dtl@getentryvalue}\meta{entry cmd}\meta{cmd}
+%\end{definition}
+% Stores the entry value in \meta{cmd} for
+% entry given by \meta{entry cmd}.
+% \begin{macrocode}
+\newcommand*{\dtl@getentryvalue}[2]{%
+\expandafter\@dtl@getentryvalue#1#2}
+\long\def\@dtl@getentryvalue#1#2#3{\gdef#3{#2}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlforeachlevel}
+%\cs{DTLforeach} can only be nested up to three levels.
+% \cs{dtlforeachlevel} keeps track of the current level.
+% \begin{macrocode}
+\global\newcount\dtlforeachlevel
+% \end{macrocode}
+%\end{macro}
+%
+% The counter DTLrow\meta{n} keeps track of each row of data during
+% the \meta{n} nested \cs{DTLforeach}. It is only incremented in the
+% conditions (given by the optional argument) are met.
+% \begin{macrocode}
+\newcounter{DTLrowi}
+\newcounter{DTLrowii}
+\newcounter{DTLrowiii}
+% \end{macrocode}
+% Keep \sty{hyperref} happy
+% \begin{macrocode}
+\newcounter{DTLrow}
+\def\theHDTLrow{\arabic{DTLrow}}
+\def\theHDTLrowi{\theHDTLrow.\arabic{DTLrowi}}
+\def\theHDTLrowii{\theHDTLrowi.\arabic{DTLrowii}}
+\def\theHDTLrowiii{\theHDTLrowii.\arabic{DTLrowiii}}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLsaverowcount}
+%\begin{definition}
+%\cs{DTLsavelastrowcount}\marg{cmd}
+%\end{definition}
+% Stores the maximum row count for the last \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLsavelastrowcount}[1]{%
+\ifnum\dtlforeachlevel>2\relax
+ \def#1{0}%
+\else
+ \ifnum\dtlforeachlevel<0\relax
+ \def#1{0}%
+ \else
+ \@dtl@tmpcount=\dtlforeachlevel
+ \advance\@dtl@tmpcount by 1\relax
+ \edef#1{\expandafter\number
+ \csname c@DTLrow\romannumeral\@dtl@tmpcount\endcsname}%
+ \fi
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLforeach}
+%\begin{definition}
+% \cs{DTLforeach}\oarg{conditions}\marg{db name}\marg{values}\marg{text}
+%\end{definition}
+% For each row of data in the database given by \meta{db name},
+% do \meta{text}, if the specified conditions are satisfied.
+% The argument \marg{values} is a comma separated list of
+% \meta{cmd}\texttt{=}\meta{key} pairs. At the start of each row,
+% each of the commands in this list are set to the value of the
+% entry with the corresponding key \meta{key}.
+% (\cs{gdef} is used to ensure \cs{DTLforeach} works in a tabular
+% environment.) The database may be edited in the unstarred
+% version, in the starred version the database is read only.
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLforeach}{\@ifstar\@sDTLforeach\@DTLforeach}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLforeach}
+% \cs{@DTLforeach} is the unstarred version of \cs{DTLforeach}.
+% The database is reconstructed to allow for rows to be edited.
+% \begin{macrocode}
+\newcommand{\@DTLforeach}[4][\boolean{true}]{%
+% \end{macrocode}
+% Check database exists
+% \begin{macrocode}
+\DTLifdbexists{#2}{%
+% \end{macrocode}
+% Keep \sty{hyperref} happy
+% \begin{macrocode}
+\refstepcounter{DTLrow}%
+\global\c@DTLrow=\c@DTLrow
+% \end{macrocode}
+% Store database name
+% \begin{macrocode}
+\gdef\@dtl@dbname{#2}%
+% \end{macrocode}
+% Increment level and check not exceeded 3
+% \begin{macrocode}
+\global\advance\dtlforeachlevel by 1\relax
+\ifnum\dtlforeachlevel>3\relax
+ \PackageError{datatool}{\string\DTLforeach\space nested too
+deeply}{}%
+\else
+% \end{macrocode}
+% Set level dependent information (needs to be global to ensure
+% it works in the \env{tabular} environment.) Row counter:
+% \begin{macrocode}
+ \expandafter\global
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax
+% \end{macrocode}
+% Construct updated database:
+% \begin{macrocode}
+ \expandafter\global\expandafter\let
+ \csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
+ =\@empty
+% \end{macrocode}
+% Database name:
+% \begin{macrocode}
+ \expandafter\global\expandafter\let
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ =\@dtl@dbname
+% \end{macrocode}
+% Iterate through each row
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+% \end{macrocode}
+% Set current row macro for this level
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel
+ \endcsname=\@dtl@currentrow
+% \end{macrocode}
+% Globally assign next element (note that there is no check to
+% determine if the next element will be skipped.)
+%\changes{1.01}{2007 Aug 17}{set \cs{@dtl@nextrow}}
+% \begin{macrocode}
+ \global\let\@dtl@nextrow\@xfor@nextelement
+% \end{macrocode}
+% Assign commands to the required entries
+% \begin{macrocode}
+ \ifx\relax#3\relax
+ \else
+ \@dtl@assign{#3}%
+ \fi
+% \end{macrocode}
+% Do the main body of text if condition is satisfied
+% \begin{macrocode}
+ \ifthenelse{#1}{%
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex\expandafter
+ {\arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+ }{}%
+% \end{macrocode}
+% Reconstruct database
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thiscurrentrow
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Don't add this row if it is now empty
+% \begin{macrocode}
+ \ifx\@dtl@thiscurrentrow\@empty
+ \else
+ \expandafter\@dtl@toks\expandafter{\@dtl@thiscurrentrow}%
+ \expandafter
+ \ifx
+ \csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
+ \@empty
+ \expandafter
+ \xdef\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname{%
+ {\the\@dtl@toks}}%
+ \else
+ \expandafter\let\expandafter\@dtl@foreachrows\expandafter
+ =\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
+ \expandafter\toks@\expandafter{\@dtl@foreachrows}%
+ \expandafter
+ \xdef\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname{%
+ \the\toks@,{\the\@dtl@toks}}%
+ \fi
+ \fi
+\@endforfalse
+}%
+\expandafter\let\expandafter\@dtl@foreachrows\expandafter
+ =\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
+\expandafter\global
+ \expandafter\let\csname dtldb@#2\endcsname=\@dtl@foreachrows
+\fi
+\global\advance\dtlforeachlevel by -1\relax
+}{%
+\PackageError{datatool}{Database `#2' doesn't exist}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sDTLforeach}
+% \cs{@sDTLforeach} is the starred version of \cs{DTLforeach}.
+% The database rows can't be edited.
+% \begin{macrocode}
+\newcommand{\@sDTLforeach}[4][\boolean{true}]{%
+% \end{macrocode}
+% Check database exists
+% \begin{macrocode}
+\DTLifdbexists{#2}{%
+% \end{macrocode}
+% Keep \sty{hyperref} happy
+% \begin{macrocode}
+\refstepcounter{DTLrow}%
+\global\c@DTLrow=\c@DTLrow
+% \end{macrocode}
+% Store database name
+% \begin{macrocode}
+\gdef\@dtl@dbname{#2}%
+% \end{macrocode}
+% Increment level and check not exceeded 3
+% \begin{macrocode}
+\global\advance\dtlforeachlevel by 1\relax
+\ifnum\dtlforeachlevel>3\relax
+ \PackageError{datatool}{\string\DTLforeach\space nested too
+deeply}{}%
+\else
+% \end{macrocode}
+% Set level dependent information (needs to be global to ensure
+% it works in the \env{tabular} environment.) Row counter:
+% \begin{macrocode}
+ \expandafter\global
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax
+% \end{macrocode}
+% Set database name to \cs{@nnil} to indicate that this is read only:
+% \begin{macrocode}
+ \expandafter\global\expandafter\let
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ =\@nnil
+% \end{macrocode}
+% Iterate through each row
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+% \end{macrocode}
+% Set current row macro for this level
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel
+ \endcsname=\@dtl@currentrow
+% \end{macrocode}
+% Globally assign next element (note that there is no check to
+% determine if the next element will be skipped.)
+%\changes{1.01}{2007 Aug 17}{set \cs{@dtl@nextrow}}
+% \begin{macrocode}
+ \global\let\@dtl@nextrow\@xfor@nextelement
+% \end{macrocode}
+% Assign commands to the required entries
+% \begin{macrocode}
+ \ifx\relax#3\relax
+ \else
+ \@dtl@assign{#3}%
+ \fi
+% \end{macrocode}
+% Do the main body of text if condition is satisfied
+% \begin{macrocode}
+ \ifthenelse{#1}{%
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex\expandafter
+ {\arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+ }{}%
+% \end{macrocode}
+% \begin{macrocode}
+\@endforfalse
+}%
+\fi
+\global\advance\dtlforeachlevel by -1\relax
+}{%
+\PackageError{datatool}{Database `#2' doesn't exist}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLappendtorow}
+%\begin{definition}
+%\cs{DTLappendtorow}\marg{key}\marg{value}
+%\end{definition}
+% Appends entry to current row. (The current row is given by
+% \cs{@dtl@thiscurrentrow@}\meta{n} where \meta{n} is roman
+% numeral value of \cs{dtlforeachlevel}.
+% \begin{macrocode}
+\newcommand*{\DTLappendtorow}[2]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLappendtorow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+% \end{macrocode}
+% Set \cs{@dtl@thisdb} to the current database name:
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check this isn't in \cs{DTLforeach*}
+% \begin{macrocode}
+ \ifx\@dtl@thisdb\@nnil
+ \PackageError{datatool}{\string\DTLappendtorow\space can't
+ be used inside \string\DTLforeach*}{The starred version of
+ \string\DTLforeach\space is read only}%
+ \else
+% \end{macrocode}
+% Set \cs{@dtl@dbvalue} to the value of this entry
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{#2}%
+ \edef\@dtl@dbvalue{\the\@dtl@toks}%
+% \end{macrocode}
+% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow
+% for the ID to be stored in a control sequence.
+% \begin{macrocode}
+ \edef\@dtl@dbid{#1}%
+% \end{macrocode}
+% Set up the correct entry format:
+% \begin{macrocode}
+ \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+% \end{macrocode}
+% Set \cs{@dtl@thisrow} to the current row.
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisrow
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check if there is already an entry with this key
+% \begin{macrocode}
+ \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
+ \PackageError{datatool}{Can't add entry with ID `#1' to current
+ row of database `\@dtl@thisdb'}{There is already an entry with
+ this ID on the current row}}{%
+% \end{macrocode}
+% Append entry to last row
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{\@dtl@dbentry}%
+ \ifx\@dtl@thisrow\@empty
+ \expandafter
+ \xdef\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname{%
+ \the\@dtl@toks}%
+ \else
+ \expandafter\toks@\expandafter{\@dtl@thisrow}%
+ \expandafter
+ \xdef\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname{%
+ \the\toks@,\the\@dtl@toks}%
+ \fi
+ }
+% \end{macrocode}
+% Update key list
+% \begin{macrocode}
+ \@dtl@setidtype{\@dtl@thisdb}{#1}{#2}%
+ \expandafter\@dtl@setkeys\expandafter{#1}{\@dtl@thisdb}%
+% \end{macrocode}
+% end the \cs{ifx} and \cs{ifnum}
+% \begin{macrocode}
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLremoveentryfromrow}
+%\begin{definition}
+%\cs{DTLremoveentryfromrow}\marg{key}
+%\end{definition}
+% Removes entry given by \meta{key} from current row.
+% (The current row is given by
+% \cs{@dtl@thiscurrentrow@}\meta{n} where \meta{n} is roman
+% numeral value of \cs{dtlforeachlevel}.
+% \begin{macrocode}
+\newcommand*{\DTLremoveentryfromrow}[1]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremoveentryfromrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+% \end{macrocode}
+% Set \cs{@dtl@thisdb} to the current database name:
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check this isn't in \cs{DTLforeach*}
+% \begin{macrocode}
+ \ifx\@dtl@thisdb\@nnil
+ \PackageError{datatool}{\string\DTLremoveentryfromrow\space can't
+ be used inside \string\DTLforeach*}{The starred version of
+ \string\DTLforeach\space is read only}%
+ \else
+% \end{macrocode}
+% Set \cs{@dtl@thisrow} to the current row.
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisrow
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check row contains an entry with this key
+% \begin{macrocode}
+ \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
+% \end{macrocode}
+% Split row list
+% \begin{macrocode}
+ \let\@dtl@pre=\@empty
+ \@for\dtl@thisentry:=\@dtl@thisrow\do{%
+ \dtl@getentryid\dtl@thisentry\@dtl@id
+ \ifthenelse{\equal{\@dtl@id}{#1}}{%
+ }{%
+ \expandafter\@dtl@toks\expandafter{\dtl@thisentry}%
+ \ifx\@dtl@pre\@empty
+ \edef\@dtl@pre{{\the\@dtl@toks}}%
+ \else
+ \expandafter\toks@\expandafter{\@dtl@pre}%
+ \edef\@dtl@pre{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+ }
+ }%
+ \expandafter\let
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ =\@dtl@pre
+ }{%
+ \PackageError{datatool}{Can't remove entry given by key `#1'
+ from current row in database `\@dtl@thisdb', no such entry}{}%
+ }%
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLreplaceentryforrow}
+%\begin{definition}
+%\cs{DTLreplaceentryforrow}\marg{key}\marg{value}
+%\end{definition}
+% Replaces entry given by \meta{key} in current row with
+% \meta{value}.
+% (The current row is given by
+% \cs{@dtl@thiscurrentrow@}\meta{n} where \meta{n} is roman
+% numeral value of \cs{dtlforeachlevel}.
+% \begin{macrocode}
+\newcommand*{\DTLreplaceentryforrow}[2]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+% \end{macrocode}
+% Set \cs{@dtl@thisdb} to the current database name:
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check this isn't in \cs{DTLforeach*}
+% \begin{macrocode}
+ \ifx\@dtl@thisdb\@nnil
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space can't
+ be used inside \string\DTLforeach*}{The starred version of
+ \string\DTLforeach\space is read only}%
+ \else
+% \end{macrocode}
+% Set \cs{@dtl@dbvalue} to the value of this entry
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{#2}%
+ \edef\@dtl@dbvalue{\the\@dtl@toks}%
+% \end{macrocode}
+% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow
+% for the ID to be stored in a control sequence.
+% \begin{macrocode}
+ \edef\@dtl@dbid{#1}%
+% \end{macrocode}
+% Set up the correct entry format:
+% \begin{macrocode}
+ \edef\dtl@newentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+% \end{macrocode}
+% Set \cs{@dtl@thisrow} to the current row.
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisrow
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check row contains an entry with this key
+% \begin{macrocode}
+ \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
+% \end{macrocode}
+% Split row list
+% \begin{macrocode}
+ \let\@dtl@pre=\@empty
+ \@for\dtl@thisentry:=\@dtl@thisrow\do{%
+ \dtl@getentryid\dtl@thisentry\@dtl@id
+ \ifthenelse{\equal{\@dtl@id}{#1}}{%
+ \expandafter\@dtl@toks\expandafter{\dtl@newentry}%
+ }{%
+ \expandafter\@dtl@toks\expandafter{\dtl@thisentry}%
+ }
+ \ifx\@dtl@pre\@empty
+ \edef\@dtl@pre{{\the\@dtl@toks}}%
+ \else
+ \expandafter\toks@\expandafter{\@dtl@pre}%
+ \edef\@dtl@pre{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+ }%
+ \expandafter\let
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ =\@dtl@pre
+ }{%
+ \PackageError{datatool}{Can't remove entry given by key `#1'
+ from current row in database `\@dtl@thisdb', no such entry}{}%
+ }%
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLremovecurrentrow}
+%\begin{definition}
+%\cs{DTLremovecurrentrow}
+%\end{definition}
+% Removes current row. This just sets the current row to empty
+%\changes{1.01}{2007 Aug 17}{fix bug caused by missing \cs{fi}
+% and unrequired argument}
+% \begin{macrocode}
+\newcommand*{\DTLremovecurrentrow}{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremovecurrentrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+% \end{macrocode}
+% Check this isn't in \cs{DTLforeach*}
+% \begin{macrocode}
+ \expandafter\ifx
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname\@nnil
+ \PackageError{datatool}{\string\DTLremovecurrentrow\space can't
+ be used inside \string\DTLforeach*}{The starred version of
+ \string\DTLforeach\space is read only}%
+ \else
+% \end{macrocode}
+% Set current row to empty.
+% \begin{macrocode}
+ \expandafter\let
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ =\@empty
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLforeachkeyinrow}
+%\begin{definition}
+%\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text}
+%\end{definition}
+% Iterates through each key in the current row of \cs{DTLforeach},
+% and does \meta{text}.
+% \begin{macrocode}
+\newcommand*{\DTLforeachkeyinrow}[2]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+% \end{macrocode}
+% Set \cs{@dtl@thisrow} to the current row.
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisrow
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Iterate through the row
+% \begin{macrocode}
+ \@for\dtl@thisentry:=\@dtl@thisrow\do{%
+ \dtl@getentryvalue\dtl@thisentry{#1}%
+ #2%
+ }%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddentryforrow}
+%\begin{definition}
+%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value}
+%\end{definition}
+% Adds the entry with key given by \meta{key} and value given by
+% \meta{value} to the first row in the database \meta{db name}
+% which satisfies the condition given by \meta{condition}. The
+% \meta{assign list} is the same as for \cs{DTLforeach} and may
+% be used to set the values which are to be tested in \meta{condition}.
+% \begin{macrocode}
+\newcommand{\DTLaddentryforrow}[5]{%
+\gdef\@dtl@dbname{#1}%
+\DTLifdbexists{#1}{%
+% \end{macrocode}
+% Set \cs{@dtl@dbvalue} to the value of this entry
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{#5}%
+ \edef\@dtl@dbvalue{\the\@dtl@toks}%
+% \end{macrocode}
+% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow
+% for the ID to be stored in a control sequence.
+% \begin{macrocode}
+ \edef\@dtl@dbid{#4}%
+% \end{macrocode}
+% Set up the correct entry format:
+% \begin{macrocode}
+ \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+% \end{macrocode}
+% Store the database in \cs{@dtl@db}
+% \begin{macrocode}
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
+ \let\@dtl@prerow=\@empty
+% \end{macrocode}
+% Iterate through each row of the database
+% \begin{macrocode}
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \@dtl@assign{#2}%
+ \ifthenelse{#3}{%
+ \expandafter\@dtl@toks\expandafter{\@dtl@dbentry}%
+ \ifx\@dtl@currentrow\@empty
+ \edef\@dtl@currentrow{{\the\@dtl@toks}}%
+ \else
+ \expandafter\toks@\expandafter{\@dtl@currentrow}%
+ \edef\@dtl@currentrow{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+ \@endfortrue
+ }{%
+ }%
+ \expandafter\@dtl@toks\expandafter{\@dtl@currentrow}%
+ \ifx\@dtl@prerow\@empty
+ \edef\@dtl@prerow{{\the\@dtl@toks}}%
+ \else
+ \expandafter\toks@\expandafter{\@dtl@prerow}%
+ \edef\@dtl@prerow{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+}%
+\if@endfor
+ \expandafter\@dtl@toks\expandafter{\@forremainder}%
+ \expandafter\toks@\expandafter{\@dtl@prerow}%
+ \edef\@dtl@prerow{\the\toks@,{\the\@dtl@toks}}%
+ \expandafter\global\expandafter
+ \let\csname dtldb@\@dtl@dbname\endcsname=\@dtl@prerow
+\else
+ \PackageError{datatool}{Unable to add `#5' for key `#4' - condition
+ not met for any row in database `#1'}{}%
+\fi
+\@endforfalse
+}{%
+\PackageError{datatool}{Database `#1' doesn't exist}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@assign}
+%\begin{definition}
+%\cs{@dtl@assign}\oarg{row}\marg{values}
+%\end{definition}
+% Assigns each command in
+% \meta{values} (see above) to the value of the corresponding
+% ID for the row given by \meta{row} (which defaults to
+% \cs{@dtl@currentrow} if absent.)
+% \begin{macrocode}
+\newcommand*{\@dtl@assign}[2][\@dtl@currentrow]{%
+\@dtl@assigncmd#2,\relax\@@{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@assigncmd}
+%\begin{definition}
+% \cs{\@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil}
+%\end{definition}
+% Assign \meta{cmd} to value given by \meta{id}
+% \begin{macrocode}
+\def\@dtl@assigncmd#1=#2,#3\@@#4{%
+\@for\@dtl@entry:=#4\do{%
+\dtl@getentryid\@dtl@entry\@dtl@id
+\ifthenelse{\equal{\@dtl@id}{#2}}{%
+\dtl@getentryvalue\@dtl@entry#1%
+\@endfortrue}{}%
+}%
+\if@endfor
+\else
+ \@dtl@setnull{#1}{#2}%
+\fi
+\@endforfalse
+\ifx\relax#3%
+ \let\@dtl@next=\@dtl@assigncmdnoop
+\else
+ \let\@dtl@next=\@dtl@assigncmd
+\fi
+\@dtl@next#3\@@{#4}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@assigncmdnoop}
+% End loop
+% \begin{macrocode}
+\def\@dtl@assigncmdnoop#1\@@#2{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@setnull}
+%\cs{@dtl@setnull}\marg{cmd}\marg{id} sets \meta{cmd} to either
+% \cs{DTLstringnull} or \cs{DTLnumbernull} depending on the data
+% type for \meta{id}. (Database
+% name should be stored in \cs{@dtl@dbname} prior to use.
+% \begin{macrocode}
+\newcommand*{\@dtl@setnull}[2]{%
+\@ifundefined{@dtl@idtype@\@dtl@dbname @#2}{%
+\global\let#1=\DTLstringnull}{%
+\edef\@dtl@tmp{0\@dtl@getidtype{\@dtl@dbname}{#2}}%
+\expandafter\ifnum\@dtl@tmp=0\relax
+ \global\let#1=\DTLstringnull
+\else
+ \global\let#1=\DTLnumbernull
+\fi
+}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLstringnull}
+% String null value:
+% \begin{macrocode}
+\newcommand*{\DTLstringnull}{NULL}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnumbernull}
+% Number null value:
+% \begin{macrocode}
+\newcommand*{\DTLnumbernull}{0}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLifnull}
+%\begin{definition}
+%\cs{DTLifnull}\marg{value}\marg{true part}\marg{false part}
+%\end{definition}
+% Checks if \meta{value} is null (either \cs{DTLstringnull} or
+% \cs{DTLnumbernull}) if true, does \meta{true part} otherwise
+% does \meta{false part}.
+% \begin{macrocode}
+\newcommand*{\DTLifnull}[3]{%
+\ifx\DTLstringnull#1\relax
+ #2%
+\else
+ \ifx\DTLnumbernull#1\relax
+ #2%
+ \else
+ #3%
+ \fi
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@gathervalues}
+%\begin{definition}
+%\cs{dtl@gathervalues}\oarg{label}\marg{db name}\marg{row}
+%\end{definition}
+% Stores each element of \meta{row} in \meta{db name} into
+% the command \cs{@dtl@}\meta{label}\texttt{@}\meta{key},
+% where \meta{key} is the
+% key for that element, and \meta{label} defaults to "key".
+% \begin{macrocode}
+\newcommand{\dtl@gathervalues}[3][key]{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname dtlkeys@#2\endcsname%
+\def\@dtl@list{}%
+\@for\dtl@key:=\@dtl@tmp\do{%
+ \expandafter\@dtl@setnull\expandafter{%
+ \csname @dtl@#1@\dtl@key\endcsname}{\dtl@key}%
+ \@for\dtl@thiselement:=#3\do{%
+ \dtl@getentryid\dtl@thiselement\@dtl@id
+ \ifthenelse{\equal{\@dtl@id}{\dtl@key}}{%
+ \dtl@getentryvalue\dtl@thiselement\@dtl@value%
+ \expandafter\toks@\expandafter{\@dtl@value}%
+ \expandafter\edef\csname @dtl@#1@\dtl@key\endcsname{%
+ \the\toks@}%
+ \@endfortrue}{}%
+ }%
+\@endforfalse
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsumforkeys}
+%\begin{definition}
+%\cs{DTLsumforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Sums all entries for key \meta{key} over all databases listed
+% in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLsumforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\def#4{0}%
+\@for\@dtl@dbname:=#2\do{%
+ \DTLifdbexists{\@dtl@dbname}{%
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
+ \@for\@dtl@key:=#3\do{%
+ \protected@edef\DTLthisval{%
+ \csname @dtl@key@\@dtl@key\endcsname}%
+ \ifthenelse{#1}{\DTLadd{#4}{#4}{\DTLthisval}}{}%
+ }}%
+ }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+ }%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmeanforkeys}
+%\begin{definition}
+%\cs{DTLmeanforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Computes the arithmetic mean of all entries for each key in
+% \meta{key list} over all databases in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLmeanforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\def#4{0}%
+\def\dtl@n{0}%
+\@for\@dtl@dbname:=#2\do{%
+\DTLifdbexists{\@dtl@dbname}{%
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
+ \@for\@dtl@key:=#3\do{%
+ \protected@edef\DTLthisval{%
+ \csname @dtl@key@\@dtl@key\endcsname}%
+ \ifthenelse{#1}{%
+ \DTLadd{#4}{#4}{\DTLthisval}%
+ \DTLadd{\dtl@n}{\dtl@n}{1}%
+ }{}%
+ }}%
+}{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}}}%
+\ifnum\dtl@n=0\relax
+ \PackageError{datatool}{Can't compute mean, no data!}{}%
+\else
+ \DTLdiv{#4}{#4}{\dtl@n}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLvarianceforkeys}
+%\begin{definition}
+%\cs{DTLvarianceforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Computes the variance of all entries for each key in
+% \meta{key list} over all databases in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLvarianceforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\DTLmeanforkeys[#1]{#2}{#3}{\dtl@mean}%
+\def#4{0}%
+\@for\@dtl@dbname:=#2\do{%
+ \DTLifdbexists{\@dtl@dbname}{%
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
+ \@for\@dtl@key:=#3\do{%
+ \protected@edef\DTLthisval{%
+ \csname @dtl@key@\@dtl@key\endcsname}%
+ \ifthenelse{#1}{%
+ \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
+ \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
+ \DTLadd{#4}{#4}{\dtl@diff}%
+ }{}%
+ }}%
+ }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+ }%
+}%
+\ifnum\dtl@n=0\relax
+ \PackageError{datatool}{Can't compute variance, no data!}{}%
+\else
+ \DTLdiv{#4}{#4}{\dtl@n}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsdforkeys}
+%\begin{definition}
+%\cs{DTLsdforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Computes the standard deviation of all entries for each key in
+% \meta{key list} over all databases in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLsdforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\DTLvarianceforkeys[#1]{#2}{#3}{#4}%
+\DTLsqrt{#4}{#4}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLminforkeys}
+%\begin{definition}
+%\cs{DTLminforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Determines the minimum over all entries for each key in
+% \meta{key list} over all databases in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLminforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\def#4{}%
+\@for\@dtl@dbname:=#2\do{%
+\DTLifdbexists{\@dtl@dbname}{%
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
+ \@for\@dtl@key:=#3\do{%
+ \protected@edef\DTLthisval{%
+ \csname @dtl@key@\@dtl@key\endcsname}%
+ \ifthenelse{#1}{%
+ \ifx#4\@empty
+ \let#4=\DTLthisval
+ \else
+ \DTLmin{#4}{#4}{\DTLthisval}%
+ \fi
+ }{}%
+}}%
+ }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+ }%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmaxforkeys}
+%\begin{definition}
+%\cs{DTLmaxforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Determines the maximum over all entries for each key in
+% \meta{key list} over all databases in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLmaxforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\def#4{}%
+\@for\@dtl@dbname:=#2\do{%
+\DTLifdbexists{\@dtl@dbname}{%
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
+ \@for\@dtl@key:=#3\do{%
+ \protected@edef\DTLthisval{%
+ \csname @dtl@key@\@dtl@key\endcsname}%
+ \ifthenelse{#1}{%
+ \ifx#4\@empty
+ \let#4=\DTLthisval
+ \else
+ \DTLmax{#4}{#4}{\DTLthisval}%
+ \fi
+ }{}%
+}}%
+ }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+ }%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLcomputebounds}
+%\begin{definition}
+%\cs{DTLcomputebounds}\oarg{condition}\marg{db list}\marg{x key}\marg{y key}\marg{minX cmd}\marg{minY cmd}\marg{maxX cmd}\marg{maxY cmd}
+%\end{definition}
+% Computes the maximum and minimum $x$ and $y$ values over all
+% the databases listed in \meta{db list} where the $x$ value
+% is given by \meta{x key} and the $y$ value is given by
+% \meta{y key}. The results are stored in \meta{minX cmd},
+% \meta{minY cmd}, \meta{maxX cmd} and \meta{maxY cmd} in
+% standard decimal format.
+% \begin{macrocode}
+\newcommand*{\DTLcomputebounds}[8][\boolean{true}]{%
+\let#5=\relax
+\let#6=\relax
+\let#7=\relax
+\let#8=\relax
+\@for\dtl@thisdb:=#2\do{%
+ \@sDTLforeach[#1]{\dtl@thisdb}{\DTLthisX=#3,\DTLthisY=#4}{%
+ \DTLconverttodecimal{\DTLthisX}{\dtl@decx}%
+ \DTLconverttodecimal{\DTLthisY}{\dtl@decy}%
+ \ifx#5\relax
+ \let#5=\dtl@decx
+ \let#6=\dtl@decy
+ \let#7=\dtl@decx
+ \let#8=\dtl@decy
+ \else
+ \FPmin{#5}{#5}{\dtl@decx}%
+ \FPmin{#6}{#6}{\dtl@decy}%
+ \FPmax{#7}{#7}{\dtl@decx}%
+ \FPmax{#8}{#8}{\dtl@decy}%
+ \fi
+ }%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetvalueforkey}
+%\begin{definition}
+%\cs{DTLgetvalueforkey}\marg{cmd}\marg{key}\marg{db name}\marg{ref
+% key}\marg{ref value}
+%\end{definition}
+% This (globally) sets \meta{cmd} (a control sequence) to the
+% value of the key specified by \meta{key} in the first row
+% of the database called \meta{db name} which contains the key
+% \meta{ref key} which has the value \meta{value}.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLgetvalueforkey}[5]{%
+{%
+\global\let#1=\DTLstringnull
+\@sDTLforeach{#3}{\dtl@valueA=#2,\dtl@refvalue=#4}{%
+\DTLifnull{\dtl@refvalue}{}{%
+\ifthenelse{\equal{\dtl@refvalue}{#5}}{%
+\global\let#1=\dtl@valueA
+\@endfortrue
+}{}}}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetrowforkey}
+%\begin{definition}
+%\cs{DTLgetrowforkey}\marg{cmd}\marg{db name}\marg{ref
+% key}\marg{ref value}
+%\end{definition}
+% This (globally) sets \meta{cmd} (a control sequence) to the
+% first row
+% of the database called \meta{db name} which contains the key
+% \meta{ref key} which has the value \meta{value}.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLgetrowforkey}[4]{%
+{%
+\global\let#1=\@empty
+\@sDTLforeach{#2}{\dtl@refvalue=#3}{%
+\DTLifnull{\dtl@refvalue}{}{%
+\ifthenelse{\equal{\dtl@refvalue}{#4}}{%
+\expandafter\global\expandafter\let\expandafter#1
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+\@endfortrue
+}{}}}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsort}
+%\begin{definition}
+% \cs{DTLsort}\oarg{replacement keys}\marg{sort criteria}\marg{db name}
+%\end{definition}
+% Sorts database \meta{db name} according to \marg{sort criteria},
+% which must be a comma separated list of keys, and optionally
+% \texttt{=}\meta{order}, where \meta{order} is either
+% "ascending" or "descending". The optional argument is a list of
+% keys to uses if the given key has a null value. The starred
+% version uses a case insensitive string comparison.
+%\changes{1.01}{2007 Aug 17}{added optional argument}
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLsort}{\@ifstar\@sDTLsort\@DTLsort}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLsort}
+% Unstarred (case sensitive) version.
+% \begin{macrocode}
+\newcommand*{\@DTLsort}[3][]{%
+\edef\@dtl@replacementkeys{#1}%
+\edef\@dtl@sortorder{#2}%
+\edef\@dtl@dbname{#3}%
+\let\@dtl@comparecs=\dtlcompare
+\expandafter\let\expandafter\@dtl@list\csname dtldb@#3\endcsname
+\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}%
+\expandafter\global\expandafter
+ \let\csname dtldb@#3\endcsname=\@dtl@list}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@sDTLsort}
+% Starred (case insensitive) version.
+% \begin{macrocode}
+\newcommand*{\@sDTLsort}[3][]{%
+\edef\@dtl@replacementkeys{#1}%
+\edef\@dtl@sortorder{#2}%
+\edef\@dtl@dbname{#3}%
+\let\@dtl@comparecs=\dtlicompare
+\expandafter\let\expandafter\@dtl@list\csname dtldb@#3\endcsname
+\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}%
+\expandafter\global\expandafter
+ \let\csname dtldb@#3\endcsname=\@dtl@list}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@sortcriteria}
+%\begin{definition}
+% \cs{@dtl@sortcriteria}\marg{a}\marg{b}
+%\end{definition}
+% Sort criteria. \cs{@dtl@dbname} and
+% \cs{@dtl@sortorder} must be set before use.
+% \begin{macrocode}
+\newcommand{\@dtl@sortcriteria}[2]{%
+\@for\@dtl@level:=\@dtl@sortorder\do{%
+ \expandafter\@dtl@getsortdirection\@dtl@level=\relax%
+ \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@key}{%
+ \ifx\@dtl@replacementkeys\@empty
+ \PackageError{datatool}{Unknown key `\@dtl@key' for database
+ `\@dtl@dbname'}{}%
+ \else
+ \dtl@gathervalues[keya]{\@dtl@dbname}{#1}%
+ \dtl@gathervalues[keyb]{\@dtl@dbname}{#2}%
+ \@ifundefined{@dtl@keya@\@dtl@key}{%
+ \@dtl@setnull{\@dtl@tmpa}{\@dtl@key}%
+ }{%
+ \expandafter\let\expandafter\@dtl@tmpa\expandafter
+ =\csname @dtl@keya@\@dtl@key\endcsname}%
+ \@ifundefined{@dtl@keyb@\@dtl@key}{%
+ \@dtl@setnull{\@dtl@tmpb}{\@dtl@key}%
+ }{%
+ \expandafter\let\expandafter\@dtl@tmpb\expandafter
+ =\csname @dtl@keyb@\@dtl@key\endcsname}%
+ \let\@dtl@keya=\@dtl@key
+ \let\@dtl@keyb=\@dtl@key
+ \DTLifnull{\@dtl@tmpa}{%
+ % find first non null key in list of replacement keys
+ \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
+ \@ifundefined{@dtl@keya@\@dtl@keya}{}{%
+ \expandafter\let\expandafter\@dtl@tmpa\expandafter
+ =\csname @dtl@keya@\@dtl@keya\endcsname
+ \DTLifnull{\@dtl@tmpa}{}{\@endfortrue}}%
+ }%
+ \if@endfor \else\let\@dtl@keya=\@dtl@key \fi
+ \@endforfalse
+ }{}%
+ \DTLifnull{\@dtl@tmpb}{%
+ % find first non null key in list of replacement keys
+ \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
+ \@ifundefined{@dtl@keyb@\@dtl@keyb}{}{%
+ \expandafter\let\expandafter\@dtl@tmpb\expandafter
+ =\csname @dtl@keyb@\@dtl@keyb\endcsname
+ \DTLifnull{\@dtl@tmpb}{}{\@endfortrue}}%
+ }%
+ \if@endfor \else\let\@dtl@keyb=\@dtl@key \fi
+ \@endforfalse
+ }{}%
+ \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keya}{%
+ \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keyb}{%
+ \dtl@sortresult=0\relax}{\dtl@sortresult=-1\relax}%
+ }{%
+ \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keyb}{%
+ \dtl@sortresult=1\relax}{%
+ \dtl@compare@{\@dtl@keya}{\@dtl@keyb}{#1}{#2}%
+ }%
+ }%
+ \fi
+ }{%
+ \ifx\@dtl@replacementkeys\@empty
+ \dtl@compare{\@dtl@key}{#1}{#2}%
+ \else
+ \dtl@gathervalues[keya]{\@dtl@dbname}{#1}%
+ \dtl@gathervalues[keyb]{\@dtl@dbname}{#2}%
+ \@ifundefined{@dtl@keya@\@dtl@key}{%
+ \@dtl@setnull{\@dtl@tmpa}{\@dtl@key}%
+ }{%
+ \expandafter\let\expandafter\@dtl@tmpa\expandafter
+ =\csname @dtl@keya@\@dtl@key\endcsname}%
+ \@ifundefined{@dtl@keyb@\@dtl@key}{%
+ \@dtl@setnull{\@dtl@tmpb}{\@dtl@key}%
+ }{%
+ \expandafter\let\expandafter\@dtl@tmpb\expandafter
+ =\csname @dtl@keyb@\@dtl@key\endcsname}%
+ \let\@dtl@keya=\@dtl@key
+ \let\@dtl@keyb=\@dtl@key
+ \DTLifnull{\@dtl@tmpa}{%
+ % find first non null key in list of replacement keys
+ \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
+ \@ifundefined{@dtl@keya@\@dtl@keya}{}{%
+ \expandafter\let\expandafter\@dtl@tmpa\expandafter
+ =\csname @dtl@keya@\@dtl@keya\endcsname
+ \DTLifnull{\@dtl@tmpa}{}{\@endfortrue}}%
+ }%
+ \if@endfor \else\let\@dtl@keya=\@dtl@key \fi
+ \@endforfalse
+ }{}%
+ \DTLifnull{\@dtl@tmpb}{%
+ % find first non null key in list of replacement keys
+ \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
+ \@ifundefined{@dtl@keyb@\@dtl@keyb}{}{%
+ \expandafter\let\expandafter\@dtl@tmpb\expandafter
+ =\csname @dtl@keyb@\@dtl@keyb\endcsname
+ \DTLifnull{\@dtl@tmpb}{}{\@endfortrue}}%
+ }%
+ \if@endfor \else\let\@dtl@keyb=\@dtl@key \fi
+ \@endforfalse
+ }{}%
+ \dtl@compare@{\@dtl@keya}{\@dtl@keyb}{#1}{#2}%
+ \fi
+ \multiply\dtl@sortresult by \@dtl@sortdirection\relax
+ \ifnum\dtl@sortresult=0\relax
+ \else
+ \@endfortrue
+ \fi
+ }%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@getsortdirection}
+% Get the direction from either \meta{key} or
+% \meta{key}=\meta{direction}. Sets \cs{@dtl@sortdirection} to
+% either -1 (ascending) or 1 (descending).
+% \begin{macrocode}
+\def\@dtl@getsortdirection#1=#2\relax{%
+\def\@dtl@key{#1}%
+\def\@dtl@sortdirection{#2}%
+\ifx\@dtl@sortdirection\@empty
+ \def\@dtl@sortdirection{-1}%
+\else
+ \@dtl@get@sortdirection#2%
+ \ifthenelse{\equal{\@dtl@sortdirection}{ascending}}{%
+ \def\@dtl@sortdirection{-1}}{%
+ \ifthenelse{\equal{\@dtl@sortdirection}{descending}}{%
+ \def\@dtl@sortdirection{1}}{%
+ \PackageError{datatool}{Invalid sort direction
+ `\@dtl@sortdirection'}{%
+ The sort direction can only be one of `ascending' or
+ `descending'}\def\@dtl@sortdirection{-1}}}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@get@sortdirection}
+% Get direction
+% \begin{macrocode}
+\def\@dtl@get@sortdirection#1={\def\@dtl@sortdirection{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@compare}
+%\begin{definition}
+%\cs{dtl@compare}\marg{key}\marg{a}\marg{b}
+%\end{definition}
+% Compares \meta{a} and \meta{b} according to \meta{key} of
+% database given by \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}.
+% \cs{@dtl@comparecs} must be set to the required comparison macro.
+% \begin{macrocode}
+\newtoks\@dtl@toksA\newtoks\@dtl@toksB
+\newcommand{\dtl@compare}[3]{%
+\dtl@gathervalues{\@dtl@dbname}{#2}%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\@dtl@toksA\expandafter{\@dtl@tmp}%
+\edef\@dtl@a{\the\@dtl@toksA}%
+\dtl@gathervalues{\@dtl@dbname}{#3}%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\@dtl@toksB\expandafter{\@dtl@tmp}%
+\edef\@dtl@b{\the\@dtl@toksB}%
+\expandafter\@dtl@datatype\expandafter=
+ \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax
+\ifnum\@dtl@datatype=0\relax
+ \edef\@dtl@tmpcmp{%
+ \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
+ {\the\@dtl@toksA}{\the\@dtl@toksB}}%
+ \@dtl@tmpcmp
+\else
+ \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{%
+ \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{%
+ \dtl@sortresult=0\relax}}%
+\fi
+\ifdtlverbose
+\@onelevel@sanitize\@dtl@a
+\@onelevel@sanitize\@dtl@b
+\fi
+\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@compare@}
+%\begin{definition}
+%\cs{dtl@compare@}\marg{keya}\marg{keyb}\marg{a}\marg{b}
+%\end{definition}
+% Compare \meta{a} and \meta{b} according to \meta{keya}
+% and \meta{keyb} of
+% database given by \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}.
+% \cs{@dtl@comparecs} must be set.
+% \begin{macrocode}
+\newcommand{\dtl@compare@}[4]{%
+\dtl@gathervalues{\@dtl@dbname}{#3}%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\@dtl@toksA\expandafter{\@dtl@tmp}%
+\edef\@dtl@a{\the\@dtl@toksA}%
+\dtl@gathervalues{\@dtl@dbname}{#4}%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#2\endcsname
+\expandafter\@dtl@toksB\expandafter{\@dtl@tmp}%
+\edef\@dtl@b{\the\@dtl@toksB}%
+\expandafter\@dtl@tmpcount\expandafter=
+ \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax
+\expandafter\@dtl@datatype\expandafter=
+ \csname @dtl@idtype@\@dtl@dbname @#2\endcsname\relax
+\multiply\@dtl@datatype by \@dtl@tmpcount\relax
+\ifnum\@dtl@datatype=0\relax
+ \edef\@dtl@tmpcmp{%
+ \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
+ {\the\@dtl@toksA}{\the\@dtl@toksB}}%
+ \@dtl@tmpcmp
+\else
+ \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{%
+ \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{%
+ \dtl@sortresult=0\relax}}%
+\fi
+\ifdtlverbose
+\@onelevel@sanitize\@dtl@a
+\@onelevel@sanitize\@dtl@b
+\fi
+\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{General List Utilities}
+%
+%\begin{macro}{\dtl@choplast}
+%\begin{definition}
+% \cs{dtl@choplast}\marg{list}\marg{rest}\marg{last}
+%\end{definition}
+% Chops the last element off a comma separated list, putting the
+% last element in the control sequence \meta{last} and putting
+% the rest in the control sequence \meta{rest}. The control
+% sequence \meta{list} is unchanged. If the list is empty, both
+% \meta{last} and \meta{rest} will be empty.
+% \begin{macrocode}
+\newcommand*{\dtl@choplast}[3]{%
+% \end{macrocode}
+% Set \meta{rest} to empty:
+% \begin{macrocode}
+\let#2\@empty
+% \end{macrocode}
+% Set \meta{last} to empty:
+% \begin{macrocode}
+\let#3\@empty
+% \end{macrocode}
+% Iterate through \meta{list}:
+% \begin{macrocode}
+\@for\@dtl@element:=#1\do{%
+\ifx#3\@empty
+% \end{macrocode}
+% First iteration, don't set \meta{rest}.
+% \begin{macrocode}
+\else
+ \ifx#2\@empty
+% \end{macrocode}
+% Second iteration, set \meta{rest} to \meta{last} (which is
+% currently set to the previous value:
+% \begin{macrocode}
+ \expandafter\toks@\expandafter{#3}%
+ \edef#2{{\the\toks@}}%
+ \else
+% \end{macrocode}
+% Subsequent iterations, set \meta{rest} to \meta{rest},\meta{last}
+% (\meta{last} is currently set to the previous value):
+% \begin{macrocode}
+ \expandafter\toks@\expandafter{#3}%
+ \expandafter\@dtl@toks\expandafter{#2}%
+ \edef#2{\the\@dtl@toks,{\the\toks@}}%
+ \fi
+\fi
+% \end{macrocode}
+% Now set \meta{last} to current element.
+% \begin{macrocode}
+\let#3=\@dtl@element%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@chopfirst}
+%\begin{definition}
+% \cs{dtl@chopfirst}\marg{list}\marg{first}\marg{rest}
+%\end{definition}
+% Chops first element off \meta{list} and store in \meta{first}.
+% The remainder of the list is stored in \meta{rest}. (\meta{list}
+% remains unchanged.)
+% \begin{macrocode}
+\newcommand*{\dtl@chopfirst}[3]{%
+\let#2=\@empty
+\let#3=\@empty
+\@for\@dtl@element:=#1\do{%
+ \let#2=\@dtl@element
+ \@endfortrue
+}%
+\if@endfor
+ \let#3=\@forremainder
+\fi
+\@endforfalse
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@sortlist}
+%\begin{definition}
+% \cs{dtl@sortlist}\marg{list}\marg{criteria cmd}
+%\end{definition}
+% Performs an insertion sort on \meta{list}, where \meta{criteria cmd}
+% is a macro which takes two arguments \meta{a} and \meta{b}.
+% \meta{criteria cmd} must set the count register \cs{dtl@sortresult}
+% to either -1 (\meta{a} less than \meta{b}), 0 (\meta{a} is
+% equal to \meta{b}) or 1 (\meta{a} is greater than \meta{b}.)
+% \begin{macrocode}
+\newcommand{\dtl@sortlist}[2]{%
+\def\@dtl@sortedlist{}%
+\@for\@dtl@currentrow:=#1\do{%
+\expandafter\dtl@insertinto\expandafter
+ {\@dtl@currentrow}{\@dtl@sortedlist}{#2}%
+\@endforfalse}%
+\let#1=\@dtl@sortedlist
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@insertinto}
+%\begin{definition}
+% \cs{dtl@insertinto}\marg{element}\marg{sorted-list}\marg{criteria cmd}
+%\end{definition}
+% Inserts \meta{element} into the sorted list \meta{sorted-list}
+% according to the criteria given by \meta{criteria cmd} (see above.)
+% \begin{macrocode}
+\newtoks\@dtl@toks
+\newcommand{\dtl@insertinto}[3]{%
+\def\@dtl@newsortedlist{}%
+\@dtl@insertdonefalse
+\@for\dtl@srtelement:=#2\do{%
+\if@dtl@insertdone
+ \expandafter\toks@\expandafter{\dtl@srtelement}%
+ \edef\@dtl@newstuff{{\the\toks@}}%
+\else
+ \expandafter#3\expandafter{\dtl@srtelement}{#1}%
+ \ifnum\dtl@sortresult<0\relax
+ \expandafter\toks@\expandafter{\dtl@srtelement}%
+ \@dtl@toks{#1}%
+ \edef\@dtl@newstuff{{\the\@dtl@toks},{\the\toks@}}%
+ \@dtl@insertdonetrue
+ \else
+ \expandafter\toks@\expandafter{\dtl@srtelement}%
+ \edef\@dtl@newstuff{{\the\toks@}}%
+ \fi
+\fi
+\ifx\@dtl@newsortedlist\@empty
+ \expandafter\toks@\expandafter{\@dtl@newstuff}%
+ \edef\@dtl@newsortedlist{\the\toks@}%
+\else
+ \expandafter\toks@\expandafter{\@dtl@newsortedlist}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@newstuff}%
+ \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}%
+\fi
+\@endforfalse
+}%
+ \ifx\@dtl@newsortedlist\@empty
+ \@dtl@toks{#1}%
+ \edef\@dtl@newsortedlist{{\the\@dtl@toks}}%
+ \else
+ \if@dtl@insertdone
+ \else
+ \expandafter\toks@\expandafter{\@dtl@newsortedlist}%
+ \@dtl@toks{#1}%
+ \edef\@dtl@newsortedlist{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+ \fi
+\global\let#2=\@dtl@newsortedlist
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\if@dtl@insertdone}
+% Define conditional to indicate whether the new entry has
+% been inserted into the sorted list.
+% \begin{macrocode}
+\newif\if@dtl@insertdone
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@sortresult}
+% Define \cs{dtl@sortresult} to be set by comparision macro.
+% \begin{macrocode}
+\newcount\dtl@sortresult
+% \end{macrocode}
+%\end{macro}
+%
+% \subsection{Floating Point Arithmetic}
+% The commands defined in this section all use the equivalent
+% commands provided by the \sty{fp} package, but first convert
+% the decimal number into the required format.
+%
+%\begin{macro}{\DTLadd}
+%\begin{definition}
+% \cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} + \meta{num2}
+% \begin{macrocode}
+\newcommand*{\DTLadd}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\FPadd{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgadd}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgadd}[3]{%
+\DTLadd{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddall}
+%\begin{definition}
+%\cs{DTLaddall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Sums all the values in \meta{num list} and stores in
+% \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLaddall}[2]{%
+\def\@dtl@sum{0}%
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \FPadd{\@dtl@sum}{\@dtl@sum}{\@dtl@num}%
+}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@sum}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@sum}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgaddall}
+%\begin{definition}
+%\cs{DTLgaddall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgaddall}[2]{%
+\DTLaddall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsub}
+%\begin{definition}
+% \cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} - \meta{num2}
+% \begin{macrocode}
+\newcommand*{\DTLsub}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\FPsub{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgsub}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgsub}[3]{%
+\DTLsub{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmul}
+%\begin{definition}
+% \cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} $\times$ \meta{num2}
+% \begin{macrocode}
+\newcommand*{\DTLmul}[3]{%
+\let\@dtl@thisreplaced=\@empty
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\ifx\@dtl@replaced\@empty
+\else
+ \let\@dtl@thisreplaced=\@dtl@replaced
+\fi
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\ifx\@dtl@replaced\@empty
+\else
+ \let\@dtl@thisreplaced=\@dtl@replaced
+\fi
+\FPmul{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+\ifx\@dtl@thisreplaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgmul}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgmul}[3]{%
+\DTLmul{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdiv}
+%\begin{definition}
+% \cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} / \meta{num2}
+% \begin{macrocode}
+\newcommand*{\DTLdiv}[3]{%
+\let\@dtl@thisreplaced=\@empty
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\ifx\@dtl@replaced\@empty
+\else
+ \let\@dtl@thisreplaced=\@dtl@replaced
+\fi
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\FPdiv{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+\ifx\@dtl@thisreplaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \ifx\@dtl@thisreplaced\@dtl@replaced
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ \else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgdiv}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgdiv}[3]{%
+\DTLdiv{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLabs}
+%\begin{definition}
+% \cs{DTLabs}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} = abs(\meta{num})
+% \begin{macrocode}
+\newcommand*{\DTLabs}[2]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FPabs{\@dtl@tmp}{\@dtl@numi}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgabs}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgabs}[2]{%
+\DTLabs{\@dtl@tmpii}{#2}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLneg}
+%\begin{definition}
+% \cs{DTLneg}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} = -\meta{num}
+% \begin{macrocode}
+\newcommand*{\DTLneg}[2]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FPneg{\@dtl@tmp}{\@dtl@numi}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgneg}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgneg}[2]{%
+\DTLneg{\@dtl@tmpii}{#2}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsqrt}
+%\begin{definition}
+% \cs{DTLsqrt}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} = sqrt(\meta{num})
+% \begin{macrocode}
+\newcommand*{\DTLsqrt}[2]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FProot{\@dtl@tmpi}{\@dtl@numi}{2}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmpi}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmpi}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgsqrt}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgsqrt}[2]{%
+\DTLsqrt{\@dtl@tmpii}{#2}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmin}
+%\begin{definition}
+% \cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = min(\meta{num1}, \meta{num2})
+% \begin{macrocode}
+\newcommand*{\DTLmin}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\FPiflt{\@dtl@numi}{\@dtl@numii}%
+ \dtl@ifsingle{#2}{%
+ \let#1=#2}{%
+ \def#1{#2}}%
+\else
+ \dtl@ifsingle{#3}{%
+ \let#1=#3}{%
+ \def#1{#3}}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgmin}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgmin}[3]{%
+\DTLmin{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLminall}
+%\begin{definition}
+%\cs{DTLminall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Finds the minimum value in \meta{num list} and stores in
+% \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLminall}[2]{%
+\let\@dtl@min=\@empty
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \ifx\@dtl@min\@empty
+ \let\@dtl@min=\@dtl@num
+ \else
+ \FPmin{\@dtl@min}{\@dtl@min}{\@dtl@num}%
+ \fi
+}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@min}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@min}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgminall}
+%\begin{definition}
+%\cs{DTLgminall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgminall}[2]{%
+\DTLminall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmax}
+%\begin{definition}
+% \cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = max(\meta{num1}, \meta{num2})
+% \begin{macrocode}
+\newcommand*{\DTLmax}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\FPmax{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+\FPifgt{\@dtl@numi}{\@dtl@numii}%
+ \dtl@ifsingle{#2}{%
+ \let#1=#2}{%
+ \def#1{#2}}%
+\else
+ \dtl@ifsingle{#3}{%
+ \let#1=#3}{%
+ \def#1{#3}}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgmax}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgmax}[3]{%
+\DTLmax{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmaxall}
+%\begin{definition}
+%\cs{DTLmaxall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Finds the maximum value in \meta{num list} and stores in
+% \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLmaxall}[2]{%
+\let\@dtl@max=\@empty
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \ifx\@dtl@max\@empty
+ \let\@dtl@max\@dtl@num
+ \else
+ \FPmax{\@dtl@max}{\@dtl@max}{\@dtl@num}%
+ \fi
+}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@max}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@max}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgmaxall}
+%\begin{definition}
+%\cs{DTLgmaxall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgmaxall}[2]{%
+\DTLmaxall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmeanforall}
+%\begin{definition}
+%\cs{DTLmeanforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Computes the arithmetic mean of all the values in \meta{num list}
+% and stores in \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLmeanforall}[2]{%
+\def\@dtl@mean{0}%
+\def\@dtl@n{0}%
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}%
+ \FPadd{\@dtl@n}{\@dtl@n}{1}%
+}%
+\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@mean}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@mean}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgmeanforall}
+%\begin{definition}
+%\cs{DTLgmeanforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgmeanforall}[2]{%
+\DTLmeanforall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLvarianceforall}
+%\begin{definition}
+%\cs{DTLvarianceforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Computes the variance of all the values in \meta{num list}
+% and stores in \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{fixed bug}
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLvarianceforall}[2]{%
+\def\@dtl@mean{0}%
+\def\@dtl@n{0}%
+\let\@dtl@decvals=\@empty
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \ifx\@dtl@decvals\@empty
+ \let\@dtl@decvals=\@dtl@num
+ \else
+ \expandafter\toks@\expandafter{\@dtl@decvals}%
+ \edef\@dtl@decvals{\the\toks@,\@dtl@num}%
+ \fi
+ \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}%
+ \FPadd{\@dtl@n}{\@dtl@n}{1}%
+}%
+\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}%
+\def\@dtl@var{0}%
+\@for\@dtl@num:=\@dtl@decvals\do{%
+ \FPsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}%
+ \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}%
+ \FPadd{\@dtl@var}{\@dtl@var}{\@dtl@diff}%
+}%
+\FPdiv{\@dtl@var}{\@dtl@var}{\@dtl@n}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@var}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@var}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgvarianceforall}
+%\begin{definition}
+%\cs{DTLgvarianceforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgvarianceforall}[2]{%
+\DTLvarianceforall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsdforall}
+%\begin{definition}
+%\cs{DTLsdforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Computes the standard deviation of all the values in \meta{num list}
+% and stores in \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{fixed bug}
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLsdforall}[2]{%
+\def\@dtl@mean{0}%
+\def\@dtl@n{0}%
+\let\@dtl@decvals=\@empty
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \ifx\@dtl@decvals\@empty
+ \let\@dtl@decvals=\@dtl@num
+ \else
+ \expandafter\toks@\expandafter{\@dtl@decvals}%
+ \edef\@dtl@decvals{\the\toks@,\@dtl@num}%
+ \fi
+ \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}%
+ \FPadd{\@dtl@n}{\@dtl@n}{1}%
+}%
+\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}%
+\def\@dtl@sd{0}%
+\@for\@dtl@num:=\@dtl@decvals\do{%
+ \FPsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}%
+ \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}%
+ \FPadd{\@dtl@sd}{\@dtl@sd}{\@dtl@diff}%
+}%
+\FPdiv{\@dtl@sd}{\@dtl@sd}{\@dtl@n}%
+\FProot{\@dtl@sd}{\@dtl@sd}{2}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@sd}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@sd}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgsdforall}
+%\begin{definition}
+%\cs{DTLgsdforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgsdforall}[2]{%
+\DTLsdforall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLround}
+%\begin{definition}
+% \cs{DTLround}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+% Sets \meta{cmd} to \meta{num} rounded to \meta{num digits}
+% digits after the decimal character.
+% \begin{macrocode}
+\newcommand*{\DTLround}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FPround{\@dtl@tmp}{\@dtl@numi}{#3}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLground}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLground}[3]{%
+\DTLround{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtrunc}
+%\begin{definition}
+% \cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+% Sets \meta{cmd} to \meta{num} truncated to \meta{num digits}
+% digits after the decimal character.
+% \begin{macrocode}
+\newcommand*{\DTLtrunc}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FPtrunc{\@dtl@tmp}{\@dtl@numi}{#3}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgtrunc}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgtrunc}[3]{%
+\DTLtrunc{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLclip}
+%\begin{definition}
+% \cs{DTLclip}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} to \meta{num} with all unnecessary 0's removed.
+% \begin{macrocode}
+\newcommand*{\DTLclip}[2]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FPclip{\@dtl@tmp}{\@dtl@numi}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgclip}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgclip}[3]{%
+\DTLclip{\@dtl@tmpii}{#2}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLinitials}
+%\subsection{String Macros}
+%\begin{definition}
+%\cs{DTLinitials}\marg{string}
+%\end{definition}
+% Convert a string into initials.
+% (Any "~" character found is first converted into a space.)
+%\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol}
+%\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}}
+% \begin{macrocode}
+\newcommand*\DTLinitials[1]{%
+\def\dtl@initialscmd{}%
+\dtl@subnobrsp{#1}{\dtl@string}%
+\DTLsubstituteall{\dtl@string}{~}{ }%
+\DTLsubstituteall{\dtl@string}{\ }{ }%
+\DTLsubstituteall{\dtl@string}{\space}{ }%
+\expandafter\dtl@initials\dtl@string{} \@nil%
+\dtl@initialscmd}%
+% \end{macrocode}
+%\end{macro}
+% The following substitutes "\protect \nobreakspace {}" with
+% a space. (Note that in this case the space following
+% "\nobreakspace" forms part of the command.)
+% \begin{macrocode}
+\edef\dtl@construct@subnobrsp{%
+\noexpand\def\noexpand\@dtl@subnobrsp##1\noexpand\protect
+\expandafter\noexpand\csname nobreakspace \endcsname ##2{%
+\noexpand\toks@{##1}%
+\noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{%
+\noexpand\@dtl@string}%
+\noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks
+\noexpand\the\noexpand\toks@}%
+\noexpand\def\noexpand\@dtl@tmp{##2}%
+\noexpand\ifx\noexpand\@dtl@tmp\noexpand\@nnil
+ \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\relax
+\noexpand\else
+ \noexpand\toks@{ }%
+ \noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{%
+ \noexpand\@dtl@string}%
+ \noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks
+ \noexpand\the\noexpand\toks@}%
+ \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\@dtl@subnobrsp
+\noexpand\fi
+\noexpand\@dtl@subnobrspnext
+}%
+\noexpand\def\noexpand\dtl@subnobrsp##1##2{%
+\noexpand\def\noexpand\@dtl@string{}%
+\noexpand\@dtl@subnobrsp ##1\noexpand\protect\expandafter\noexpand
+\csname nobreakspace \endcsname \noexpand\@nil
+\noexpand\let##2=\noexpand\@dtl@string
+}}
+\dtl@construct@subnobrsp
+% \end{macrocode}
+%
+%\begin{macro}{\DTLstoreinitials}
+%\begin{definition}
+%\cs{DTLstoreinitials}\marg{string}\marg{cmd}
+%\end{definition}
+% Convert a string into initials and store in \meta{cmd}.
+% (Any "~" character found is first converted into a space.)
+%\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol}
+%\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}}
+% \begin{macrocode}
+\newcommand*{\DTLstoreinitials}[2]{%
+\def\dtl@initialscmd{}%
+\dtl@subnobrsp{#1}{\dtl@string}%
+\DTLsubstituteall{\dtl@string}{~}{ }%
+\DTLsubstituteall{\dtl@string}{\ }{ }%
+\DTLsubstituteall{\dtl@string}{\space}{ }%
+\expandafter\dtl@initials\dtl@string{} \@nil
+\let#2=\dtl@initialscmd
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@initials}
+% \begin{macrocode}
+\def\dtl@initials#1#2 #3{%
+\dtl@ifsingle{#1}{%
+\ifcat\noexpand#1\relax\relax
+ \def\@dtl@donextinitials{\@dtl@initials#2 {#3}}%
+\else
+ \def\@dtl@donextinitials{\@dtl@initials#1#2 {#3}}%
+\fi
+}{%
+ \def\@dtl@donextinitials{\@dtl@initials{#1}#2 {#3}}%
+}%
+\@dtl@donextinitials
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@initials}
+% \begin{macrocode}
+\def\@dtl@initials#1#2 #3{%
+\dtl@initialshyphen#2-{}\dtl@endhyp
+\expandafter\@dtl@toks\expandafter{\dtl@initialscmd}%
+\toks@{#1}%
+\ifx\dtl@inithyphen\@empty
+\else
+ \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@}%
+ \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}%
+ \expandafter\toks@\expandafter{\dtl@inithyphen}%
+\fi
+\def\dtl@tmp{#3}%
+\ifx\@nnil\dtl@tmp
+ \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLafterinitials}%
+ \let\dtl@initialsnext=\@gobble
+\else
+ \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLbetweeninitials}%
+ \let\dtl@initialsnext=\dtl@initials
+\fi
+\dtl@initialsnext{#3}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@initialshyphen}
+% \begin{macrocode}
+\def\dtl@initialshyphen#1-#2#3\dtl@endhyp{%
+\def\dtl@inithyphen{#2}%
+\ifx\dtl@inithyphen\@empty
+\else
+ \edef\dtl@inithyphen{%
+ \DTLafterinitialbeforehyphen\DTLinitialhyphen#2}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLafterinitials}
+% Defines what to do after the final initial.
+% \begin{macrocode}
+\newcommand*{\DTLafterinitials}{.}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLbetweeninitials}
+% Defines what to do between initials.
+% \begin{macrocode}
+\newcommand*{\DTLbetweeninitials}{.}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLafterinitialbeforehyphen}
+% Defines what to do before a hyphen.
+% \begin{macrocode}
+\newcommand*{\DTLafterinitialbeforehyphen}{.}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLinitialhyphen}
+%Defines what to do at the hyphen
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLinitialhyphen}{-}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifAllUpperCase}
+%\begin{definition}
+%\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part}
+%\end{definition}
+% If \meta{string} only contains uppercase characters do \meta{true
+%part}, otherwise do \meta{false part}.
+% \begin{macrocode}
+\newcommand*{\DTLifAllUpperCase}[3]{%
+\protected@edef\dtl@tuc{#1}%
+\expandafter\dtl@testifuppercase\dtl@tuc\@nil\relax
+\if@dtl@condition#2\else#3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testifalluppercase}
+% \begin{macrocode}
+\def\dtl@testifuppercase#1#2{%
+\def\dtl@argi{#1}%
+\def\dtl@argii{#2}%
+\def\dtl@tc@rest{}%
+\ifx\dtl@argi\@nnil
+ \let\dtl@testifuppernext=\@nnil
+\else
+ \ifx#1\protect
+ \let\dtl@testifuppernext=\dtl@testifuppercase
+ \else
+ \ifx\uppercase#1\relax
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testifuppernext=\relax
+ \else
+ \edef\dtl@tc@arg{\string#1}%
+ \expandafter\dtl@test@ifuppercase\dtl@tc@arg\end
+ \ifx\dtl@argii\@nnil
+ \let\dtl@testifuppernext=\@dtl@gobbletonil
+ \fi
+ \fi
+ \fi
+\fi
+\ifx\dtl@testifuppernext\relax
+ \edef\dtl@dotestifuppernext{%
+ \noexpand\dtl@testifuppercase}%
+\else
+ \ifx\dtl@testifuppernext\@nnil
+ \edef\dtl@dotestifuppernext{#2}%
+ \else
+ \expandafter\toks@\expandafter{\dtl@tc@rest}%
+ \@dtl@toks{#2}%
+ \edef\dtl@dotestifuppernext{%
+ \noexpand\dtl@testifuppernext\the\toks@\the\@dtl@toks}%
+ \fi
+\fi
+\dtl@dotestifuppernext
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@test@ifalluppercase}
+% \begin{macrocode}
+\def\dtl@test@ifuppercase#1#2\end{%
+\def\dtl@tc@rest{#2}%
+\IfSubStringInString{\string\MakeUppercase}{#1#2}{%
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testifuppernext=\relax
+}{%
+ \IfSubStringInString{\string\MakeTextUppercase}{#1#2}{%
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testifuppernext=\relax
+ }{%
+ \edef\dtl@uccode{\the\uccode`#1}%
+ \edef\dtl@code{\number`#1}%
+ \ifnum\dtl@code=\dtl@uccode\relax
+ \@dtl@conditiontrue
+ \let\dtl@testifuppernext=\dtl@testifuppercase
+ \else
+ \ifnum\dtl@uccode=0\relax
+ \@dtl@conditiontrue
+ \let\dtl@testifuppernext=\dtl@testifuppercase
+ \else
+ \@dtl@conditionfalse
+ \let\dtl@testifuppernext=\@dtl@gobbletonil
+ \fi
+ \fi
+}}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLifAllLowerCase}
+%\begin{definition}
+%\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part}
+%\end{definition}
+% If \meta{string} only contains lowercase characters do \meta{true
+%part}, otherwise do \meta{false part}.
+% \begin{macrocode}
+\newcommand*{\DTLifAllLowerCase}[3]{%
+\protected@edef\dtl@tlc{#1}%
+\expandafter\dtl@testiflowercase\dtl@tlc\@nil\relax
+\if@dtl@condition#2\else#3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testifalllowercase}
+% \begin{macrocode}
+\def\dtl@testiflowercase#1#2{%
+\def\dtl@argi{#1}%
+\def\dtl@argii{#2}%
+\ifx\dtl@argi\@nnil
+ \let\dtl@testiflowernext=\@nnil
+\else
+ \ifx#1\protect
+ \let\dtl@testiflowernext=\dtl@testiflowercase
+ \else
+ \ifx\lowercase#1\relax
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testiflowernext=\relax
+ \else
+ \edef\dtl@tc@arg{\string#1}%
+ \expandafter\dtl@test@iflowercase\dtl@tc@arg\end
+ \ifx\dtl@argii\@nnil
+ \let\dtl@testiflowernext=\@dtl@gobbletonil
+ \fi
+ \fi
+ \fi
+\fi
+\ifx\dtl@testiflowernext\relax
+ \edef\dtl@dotestiflowernext{%
+ \noexpand\dtl@testiflowercase}%
+\else
+ \ifx\dtl@testiflowernext\@nnil
+ \edef\dtl@dotestiflowernext{#2}%
+ \else
+ \expandafter\toks@\expandafter{\dtl@tc@rest}%
+ \@dtl@toks{#2}%
+ \edef\dtl@dotestiflowernext{%
+ \noexpand\dtl@testiflowernext\the\toks@\the\@dtl@toks}%
+ \fi
+\fi
+\dtl@dotestiflowernext
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@test@ifalllowercase}
+% \begin{macrocode}
+\def\dtl@test@iflowercase#1#2\end{%
+\def\dtl@tc@rest{#2}%
+\IfSubStringInString{\string\MakeLowercase}{#1#2}{%
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testiflowernext=\relax
+}{%
+ \IfSubStringInString{\string\MakeTextLowercase}{#1#2}{%
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testiflowernext=\relax
+ }{%
+ \edef\dtl@lccode{\the\lccode`#1}%
+ \edef\dtl@code{\number`#1}%
+ \ifnum\dtl@code=\dtl@lccode\relax
+ \@dtl@conditiontrue
+ \let\dtl@testiflowernext=\dtl@testiflowercase
+ \else
+ \ifnum\dtl@lccode=0\relax
+ \@dtl@conditiontrue
+ \let\dtl@testiflowernext=\dtl@testiflowercase
+ \else
+ \@dtl@conditionfalse
+ \let\dtl@testiflowernext=\@dtl@gobbletonil
+ \fi
+ \fi
+}}}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Saving a database to an external file}
+%
+%\begin{macro}{\@dtl@write}
+% \begin{macrocode}
+\newwrite\@dtl@write
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsavedb}
+%\begin{definition}
+% \cs{DTLsavedb}\marg{db name}\marg{filename}
+%\end{definition}
+% Save a database as an ASCII data file using the separator
+% and delimiter given by \cs{@dtl@separator} and \cs{@dtl@delimiter}.
+% \begin{macrocode}
+\newcommand*{\DTLsavedb}[2]{%
+\DTLifdbexists{#1}{%
+\openout\@dtl@write=#2%
+\edef\@dtl@keys{\csname dtlkeys@#1\endcsname}%
+\def\@dtl@header{}%
+\@for\@dtl@key:=\@dtl@keys\do{%
+\expandafter\@dtl@toks\expandafter{\@dtl@header}%
+\ifx\@dtl@header\@empty
+ \IfSubStringInString{\@dtl@separator}{\@dtl@key}{%
+ \protected@edef\@dtl@header{%
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ }{%
+ \protected@edef\@dtl@header{\@dtl@key}%
+ }%
+\else
+ \IfSubStringInString{\@dtl@separator}{\@dtl@key}{%
+ \protected@edef\@dtl@header{\the\@dtl@toks\@dtl@separator
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ }{%
+ \protected@edef\@dtl@header{\the\@dtl@toks\@dtl@separator
+ \@dtl@key}%
+ }%
+\fi
+}%
+\protected@write\@dtl@write{}{\@dtl@header}%
+\expandafter\let\expandafter\@dtl@db\csname dtldb@#1\endcsname%
+\@for\@dtl@currentrow:=\@dtl@db\do{%
+\dtl@gathervalues{#1}{\@dtl@currentrow}%
+\def\@dtl@outputrow{}%
+\@for\@dtl@key:=\@dtl@keys\do{%
+\protected@edef\@dtl@element{\csname @dtl@key@\@dtl@key\endcsname}%
+\expandafter\@dtl@toks\expandafter{\@dtl@outputrow}%
+\ifx\@dtl@outputrow\@empty
+ \IfSubStringInString{\@dtl@separator}{\@dtl@element}{%
+ \protected@edef\@dtl@outputrow{%
+ \@dtl@delimiter\@dtl@element\@dtl@delimiter}%
+ }{%
+ \protected@edef\@dtl@outputrow{\@dtl@element}%
+ }%
+\else
+ \IfSubStringInString{\@dtl@separator}{\@dtl@element}{%
+ \protected@edef\@dtl@outputrow{\the\@dtl@toks\@dtl@separator
+ \@dtl@delimiter\@dtl@element\@dtl@delimiter}%
+ }{%
+ \protected@edef\@dtl@outputrow{\the\@dtl@toks\@dtl@separator
+ \@dtl@element}%
+ }%
+\fi
+}%
+\protected@write\@dtl@write{}{\@dtl@outputrow}%
+}%
+\closeout\@dtl@write
+}{%
+\PackageError{datatool}{Database `#1' doesn't exist}{}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsavetexdb}
+%\begin{definition}
+% \cs{DTLsavetexdb}\marg{db name}\marg{filename}
+%\end{definition}
+% Save a database as a \LaTeX\ file.
+% \begin{macrocode}
+\newcommand*{\DTLsavetexdb}[2]{%
+\DTLifdbexists{#1}{%
+\def\@dtl@dbname{#1}%
+\openout\@dtl@write=#2%
+\edef\@dtl@keys{\csname dtlkeys@#1\endcsname}%
+\protected@write\@dtl@write{}{\string\DTLnewdb{#1}}%
+\expandafter\let\expandafter\@dtl@db\csname dtldb@#1\endcsname%
+\@for\@dtl@currentrow:=\@dtl@db\do{%
+\dtl@gathervalues{#1}{\@dtl@currentrow}%
+\protected@write\@dtl@write{}{\string\DTLnewrow{#1}}%
+\@for\@dtl@key:=\@dtl@keys\do{%
+\expandafter\DTLifnull\csname @dtl@key@\@dtl@key\endcsname
+{}{%
+\protected@edef\@dtl@element{\csname @dtl@key@\@dtl@key\endcsname}%
+\protected@write\@dtl@write{}{\string\DTLnewdbentry
+ {#1}{\@dtl@key}{\@dtl@element}}%
+}%
+}%
+}%
+\closeout\@dtl@write
+}{%
+\PackageError{datatool}{Database `#1' doesn't exist}{}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Loading a database from an external file}
+%
+%\begin{macro}{\@dtl@read}
+% \begin{macrocode}
+\newread\@dtl@read
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@entrycr}
+% Keep track of current column in data file
+% \begin{macrocode}
+\newcount\dtl@entrycr
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLloaddb}
+%\begin{definition}
+% \cs{DTLloaddb}\marg{db name}\marg{filename}
+%\end{definition}
+% Creates a new database called \meta{db name}, and load the data in
+% \meta{filename} into it. The separator and delimiter used in
+% the file must match \cs{@dtl@separator} and \cs{@dtl@delimiter}.
+% \begin{macrocode}
+\gdef\DTLloaddb#1#2{%
+\IfFileExists{#2}{%
+\begingroup
+\catcode`\"12\relax
+\openin\@dtl@read=#2%
+\dtl@message{Reading `#2'}%
+\DTLnewdb{#1}%
+\ifeof\@dtl@read
+\else
+ \loop
+ \@dtl@conditionfalse
+ \ifeof\@dtl@read
+ \else
+ \read\@dtl@read to \@dtl@line
+ \dtl@trim\@dtl@line
+ \if\@dtl@line\par
+ \@dtl@conditiontrue
+ \fi
+ \fi
+ \if@dtl@condition
+ \repeat
+ \ifeof\@dtl@read
+ \else
+ \protected@edef\@dtl@lin@{\@dtl@separator\@dtl@line\@dtl@separator}%
+ \@dtl@tmpcount=0\relax
+ \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
+ \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key
+ \advance\@dtl@tmpcount by 1\relax
+ \expandafter\@dtl@toks\expandafter{\@dtl@key}%
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral\@dtl@tmpcount\endcsname{%
+ \the\@dtl@toks}%
+ }%
+ \ifeof\@dtl@read
+ \else
+ \@dtl@conditiontrue
+ \loop
+ \read\@dtl@read to \@dtl@line
+ \dtl@trim\@dtl@line
+ \ifthenelse{\equal{\@dtl@line}{}}{}%
+ {%
+ \DTLnewrow{#1}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@line}%
+ \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks
+ \@dtl@separator}%
+ \dtl@entrycr=0\relax
+ \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
+ \expandafter\@dtl@lopoff\@dtl@lin@\to
+ \@dtl@lin@\@dtl@thisentry
+ \advance\dtl@entrycr by 1\relax
+ \edef\@dtl@thiskey{%
+ \csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
+ \edef\@do@dtlnewentry{\noexpand\DTLnewdbentry
+ {#1}{\@dtl@thiskey}{\the\@dtl@toks}}%
+ \@do@dtlnewentry
+ }%
+ }%
+ \ifeof\@dtl@read \@dtl@conditionfalse\fi
+ \if@dtl@condition
+ \repeat
+ \fi
+ \fi
+\fi
+\closein\@dtl@read
+\endgroup
+}{%
+\PackageError{datatool}{Can't load database `#1' (file `#2'
+doesn't exist)}{}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@trim}
+%\begin{definition}
+%\cs{dtl@trim}\marg{line}
+%\end{definition}
+% Trims the trailing space from \meta{line}.
+% \begin{macrocode}
+\newcommand{\dtl@trim}[1]{%
+\def\@dtl@trmstr{}%
+\expandafter\@dtl@starttrim#1\@nil%
+\let#1=\@dtl@trmstr
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@starttrim}
+% Start trimming
+% \begin{macrocode}
+\long\def\@dtl@starttrim#1#2{%
+\ifx\par#1%
+ \def\@dtl@dotrim{\@dtl@trim{} #2}%
+\else
+ \def\@dtl@dotrim{\@dtl@trim#1#2}%
+\fi
+\@dtl@dotrim%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@trim}
+% \begin{macrocode}
+\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLloadrawdb}
+%\begin{definition}
+%\cs{DTLloadrawdb}\marg{db name}\marg{filename}
+%\end{definition}
+% Loads a raw database (substitutes "%" $\to$ "\%",
+% "$" $\to$ "\$", "&" $\to$ "\&", "#" $\to$ "\#",
+% "~" $\to$ "\textasciitilde", "_" $\to$ "\_"
+% and "^" $\to$ "\textasciicircum".)
+% \begin{macrocode}
+\gdef\DTLloadrawdb#1#2{%
+\IfFileExists{#2}{%
+\openin\@dtl@read=#2%
+\dtl@message{Reading `#2'}%
+\DTLnewdb{#1}%
+\ifeof\@dtl@read
+\else
+ \loop
+ \@dtl@conditionfalse
+ \ifeof\@dtl@read
+ \else
+ \@dtl@rawread\@dtl@read to\@dtl@line
+ \dtl@trim\@dtl@line
+ \if\@dtl@line\par
+ \@dtl@conditiontrue
+ \fi
+ \fi
+ \if@dtl@condition
+ \repeat
+ \ifeof\@dtl@read
+ \else
+ \dtl@domappings\@dtl@line
+ \protected@edef\@dtl@lin@{\@dtl@separator\@dtl@line\@dtl@separator}%
+ \@dtl@tmpcount=0\relax
+ \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
+ \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key
+ \advance\@dtl@tmpcount by 1\relax
+ \expandafter\@dtl@toks\expandafter{\@dtl@key}%
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral\@dtl@tmpcount\endcsname{%
+ \the\@dtl@toks}%
+ }%
+ \ifeof\@dtl@read
+ \else
+ \@dtl@conditiontrue
+ \loop
+ \@dtl@rawread\@dtl@read to\@dtl@line
+ \dtl@trim\@dtl@line
+ \ifthenelse{\equal{\@dtl@line}{}}{}%
+ {%
+ \DTLnewrow{#1}%
+ \dtl@domappings\@dtl@line
+ \expandafter\@dtl@toks\expandafter{\@dtl@line}%
+ \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks
+ \@dtl@separator}%
+ \dtl@entrycr=0\relax
+ \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
+ \expandafter\@dtl@lopoff\@dtl@lin@\to
+ \@dtl@lin@\@dtl@thisentry
+ \advance\dtl@entrycr by 1\relax
+ \edef\@dtl@thiskey{%
+ \csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
+ \edef\@do@dtlnewentry{\noexpand\DTLnewdbentry
+ {#1}{\@dtl@thiskey}{\the\@dtl@toks}}%
+ \@do@dtlnewentry
+ }%
+ }%
+ \ifeof\@dtl@read \@dtl@conditionfalse\fi
+ \if@dtl@condition
+ \repeat
+ \fi
+ \fi
+\fi
+\closein\@dtl@read
+}{%
+\PackageError{datatool}{Can't load database `#1' (file `#2'
+doesn't exist)}{}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@rawread}
+%\begin{definition}
+% \cs{@dtl@rawread}\meta{number}to\meta{cmd}
+%\end{definition}
+% Reads in a raw line from file given by \meta{number}
+% converts special characters and stores in \meta{cmd}
+% \begin{macrocode}
+\begingroup
+\catcode`\%=\active
+\catcode`$=\active
+\catcode`&=\active
+\catcode`~=\active
+\catcode`_=\active
+\catcode`^=\active
+\catcode`#=\active
+\catcode`?=6\relax
+\catcode`<=1\relax
+\catcode`>=2\relax
+\catcode`\{=\active
+\catcode`\}=\active
+\gdef\@dtl@rawread?1to?2<\relax
+<<\catcode`\%=\active
+\catcode`$=\active
+\catcode`&=\active
+\catcode`~=\active
+\catcode`_=\active
+\catcode`^=\active
+\catcode`#=\active
+\catcode`\{=\active
+\catcode`\}=\active
+\def%<\noexpand\%>\relax
+\def$<\noexpand\$>\relax
+\def&<\&>\relax
+\def#<\#>\relax
+\def~<\noexpand\textasciitilde>\relax
+\def_<\noexpand\_>\relax
+\def^<\noexpand\textasciicircum>\relax
+\@dtl@activatebraces
+\@dtl@doreadraw?1?2>>>
+\gdef\@dtl@doreadraw?1?2<\relax
+\read?1 to \tmp
+\xdef?2<\tmp>\relax
+>
+\endgroup
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@activatebraces}
+% \cs{@dtl@activatebraces} resets braces for \cs{@dtl@rawread}
+% \begin{macrocode}
+\begingroup
+\catcode`\{=\active
+\catcode`\}=\active
+\catcode`<=1\relax
+\catcode`>=2\relax
+\gdef\@dtl@activatebraces<%
+ \catcode`\{=\active
+ \catcode`\}=\active
+ \def{<\noexpand\{>%
+ \def}<\noexpand\}>%
+>%
+\endgroup
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLrawmap}
+%\begin{definition}
+%\cs{DTLrawmap}\marg{string}\marg{replacement}
+%\end{definition}
+% Additional mappings to perform when reading a raw data file
+% \begin{macrocode}
+\newcommand*{\DTLrawmap}[2]{%
+\expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}%
+\ifx\@dtl@rawmappings\@empty
+ \def\@dtl@rawmappings{{#1}{#2}}%
+\else
+ \def\@dtl@tmp{{#1}{#2}}
+ \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp}
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@rawmappings}
+% List of mappings.
+% \begin{macrocode}
+\newcommand*{\@dtl@rawmappings}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@domappings}
+%\begin{definition}
+% \cs{dtl@domappings}\marg{cmd}
+%\end{definition}
+% Do all mappings in string given by \meta{cmd}.
+% \begin{macrocode}
+\newcommand*{\dtl@domappings}[1]{%
+\@for\@dtl@map:=\@dtl@rawmappings\do{%
+ \expandafter\DTLsubstitute\expandafter#1\@dtl@map
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsubstitute}
+%\begin{definition}
+%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement}
+%\end{definition}
+% Substitutes first occurence of \meta{original} with
+% \marg{replacement} within the string given by \meta{cmd}
+% \begin{macrocode}
+\newcommand{\DTLsubstitute}[3]{%
+\expandafter\DTLsplitstring\expandafter
+ {#1}{#2}{\@dtl@beforepart}{\@dtl@afterpart}%
+\ifx\@dtl@replaced\@empty
+\else
+ \def#1{}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@beforepart}%
+ \expandafter\toks@\expandafter{#1}%
+ \protected@edef#1{\the\toks@\the\@dtl@toks#3}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@afterpart}%
+ \expandafter\toks@\expandafter{#1}%
+ \edef#1{\the\toks@\the\@dtl@toks}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsplitstring}
+%\begin{definition}
+%\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before
+%cmd}\marg{after cmd}
+%\end{definition}
+% Splits string at \meta{split text} stores the pre split text
+% in \meta{before cmd} and the post split text in \meta{after cmd}.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLsplitstring}[4]{%
+\def\dtl@splitstr##1#2##2\@nil{%
+\def#3{##1}%
+\def#4{##2}%
+\ifx#4\@empty
+ \let\@dtl@replaced=\@empty
+\else
+ \def\@dtl@replaced{#2}%
+ \dtl@split@str##2\@nil
+\fi
+}%
+\def\dtl@split@str##1#2\@nil{%
+\def#4{##1}}%
+\dtl@splitstr#1#2\@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsubstituteall}
+%\begin{definition}
+%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement}
+%\end{definition}
+% Substitutes all occurences of \meta{original} with
+% \marg{replacement} within the string given by \meta{cmd}
+%\changes{1.01}{2007 Aug 17}{fixed bug caused when certain commands
+% occur in the string}
+% \begin{macrocode}
+\newcommand{\DTLsubstituteall}[3]{%
+\def\@dtl@splitsubstr{}%
+\let\@dtl@afterpart=#1\relax
+\@dtl@dosubstitute{#2}{#3}%
+\expandafter\toks@\expandafter{\@dtl@splitsubstr}%
+\expandafter\@dtl@toks\expandafter{\@dtl@afterpart}%
+\edef#1{\the\toks@\the\@dtl@toks}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@dosubstitute}
+% Recursive substitution macro.
+% \begin{macrocode}
+\def\@dtl@dosubstitute#1#2{%
+\expandafter\DTLsplitstring\expandafter
+ {\@dtl@afterpart}{#1}{\@dtl@beforepart}{\@dtl@afterpart}%
+\expandafter\toks@\expandafter{\@dtl@splitsubstr}%
+\expandafter\@dtl@toks\expandafter{\@dtl@beforepart}%
+\edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}%
+\ifx\@dtl@replaced\@empty
+ \let\@dtl@dosubstnext=\@dtl@dosubstitutenoop
+\else
+ \expandafter\toks@\expandafter{\@dtl@splitsubstr}%
+ \@dtl@toks{#2}%
+ \edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}%
+ \let\@dtl@dosubstnext=\@dtl@dosubstitute
+\fi
+\@dtl@dosubstnext{#1}{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@dosubstitutenoop}
+% Terminates recursive substitution macro.
+% \begin{macrocode}
+\def\@dtl@dosubstitutenoop#1#2{}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Currencies}
+%\begin{macro}{\@dtl@currencies}
+% \cs{@dtl@currencies} stores all known currencies.
+% \begin{macrocode}
+\newcommand*{\@dtl@currencies}{\$,\pounds}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnewcurrencysymbol}
+%\begin{definition}
+% \cs{DTLaddcurrency}\marg{symbol}
+%\end{definition}
+% Adds \meta{symbol} to the list of known currencies
+% \begin{macrocode}
+\newcommand*{\DTLnewcurrencysymbol}[1]{%
+\expandafter\toks@\expandafter{\@dtl@currencies}%
+\@dtl@toks{#1}%
+\edef\@dtl@currencies{\the\@dtl@toks,\the\toks@}%
+}
+% \end{macrocode}
+%\end{macro}
+% If any of the following currency commands have been defined,
+% add them to the list:
+% \begin{macrocode}
+\AtBeginDocument{%
+\@ifundefined{texteuro}{}{\DTLnewcurrencysymbol{\texteuro}}%
+\@ifundefined{textdollar}{}{\DTLnewcurrencysymbol{\textdollar}}%
+\@ifundefined{textstirling}{}{\DTLnewcurrencysymbol{\textstirling}}%
+\@ifundefined{textyen}{}{\DTLnewcurrencysymbol{\textyen}}%
+\@ifundefined{textwon}{}{\DTLnewcurrencysymbol{\textwon}}%
+\@ifundefined{textcurrency}{}{\DTLnewcurrencysymbol{\textcurrency}}%
+\@ifundefined{euro}{}{\DTLnewcurrencysymbol{\euro}}%
+\@ifundefined{yen}{}{\DTLnewcurrencysymbol{\yen}}%
+}
+% \end{macrocode}
+%\begin{macro}{\@dtl@standardize@currency}
+%\begin{definition}
+%\cs{@dtl@standardize@currency}\marg{cmd}
+%\end{definition}
+% Substitutes the first currency symbol found in \meta{cmd}
+% with "\$". This is used when testing text to determine
+% if it is currency. The original currency symbol is stored
+% in \cs{@dtl@org@currency}, so that it can be replaced later.
+% If no currency symbol is found, \cs{@dtl@org@currency} will
+% be empty.
+% \begin{macrocode}
+\newcommand{\@dtl@standardize@currency}[1]{%
+\def\@dtl@org@currency{}%
+\@for\@dtl@thiscurrency:=\@dtl@currencies\do{%
+ \expandafter\toks@\expandafter{\@dtl@thiscurrency}%
+ \edef\@dtl@dosubs{\noexpand\DTLsubstitute{\noexpand#1}%
+ {\the\toks@}{\noexpand\$}}%
+ \@dtl@dosubs
+ \ifx\@dtl@replaced\@empty
+ \else
+ \let\@dtl@org@currency=\@dtl@replaced
+ \@endfortrue
+ \fi
+}%
+\@endforfalse}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@currency}
+%\cs{@dtl@currency} is set by \cs{DTLlocaltodecimal} and
+%\cs{@dtl@checknumerical}. It is used by \cs{DTLdecimaltocurrency}.
+% Set to "\$" by default.
+% \begin{macrocode}
+\newcommand*{\@dtl@currency}{\$}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsetdefaultcurrency}
+%\cs{DTLsetdefaultcurrency}\marg{symbol} sets the default currency.
+% \begin{macrocode}
+\newcommand*{\DTLsetdefaultcurrency}[1]{%
+\renewcommand*{\@dtl@currency}{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@ifsingle}
+%\begin{definition}
+%\cs{dtl@ifsingle}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% If there is only one object in \meta{arg} (without expansion)
+% do \meta{true part}, otherwise do false part.
+% \begin{macrocode}
+\newcommand{\dtl@ifsingle}[3]{%
+\def\@dtl@arg{#1}%
+\ifx\@dtl@arg\@empty
+ #3%
+\else
+ \@dtl@ifsingle#1\@nil{#2}{#3}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@ifsingle}
+% \begin{macrocode}
+\def\@dtl@ifsingle#1#2\@nil#3#4{%
+\def\dtl@sg@arg{#2}%
+\ifx\dtl@sg@arg\@empty
+ #3%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Debugging commands}
+% These commands are provided to assist debugging
+%\begin{macro}{\dtlshowdb}
+%\begin{definition}
+%\cs{dtlshowdb}\marg{db name}
+%\end{definition}
+% Shows the database.
+% \begin{macrocode}
+\newcommand*{\dtlshowdb}[1]{%
+\expandafter\show\csname dtldb@#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlshowdbkeys}
+%\begin{definition}
+%\cs{dtlshowdbkeys}\marg{db name}
+%\end{definition}
+% Shows the key list for the named database.
+% \begin{macrocode}
+\newcommand*{\dtlshowdbkeys}[1]{%
+\expandafter\show\csname dtlkeys@#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlshowtype}
+%\begin{definition}
+%\cs{dtlshowtype}\marg{db name}\marg{key}
+%\end{definition}
+% Show the data type for given key in the named database.
+% This should be an integer from 0 to 3.
+% \begin{macrocode}
+\newcommand*{\dtlshowtype}[2]{%
+\expandafter\show\csname @dtl@idtype@#1@#2\endcsname}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</datatool.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*datapie.sty>
+% \end{macrocode}
+%\fi
+%\section{datapie.sty}
+% Declare package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{datapie}[2007/08/17 v1.01 (NLCT)]
+% \end{macrocode}
+% Require \sty{xkeyval} package
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+% \end{macrocode}
+%\begin{macro}{\ifDTLcolorpiechart}
+% The conditional \cs{ifDTLcolorpiechart} is to determine
+% whether to use colour or grey scale.
+% \begin{macrocode}
+\newif\ifDTLcolorpiechart
+\DTLcolorpiecharttrue
+% \end{macrocode}
+%\end{macro}
+% Package options to change the conditional:
+% \begin{macrocode}
+\DeclareOption{color}{\DTLcolorpiecharttrue}
+\DeclareOption{gray}{\DTLcolorpiechartfalse}
+% \end{macrocode}
+%\begin{macro}{\ifDTLrotateinner}
+% Define boolean keys to govern label rotations.
+% \begin{macrocode}
+\define@boolkey{datapie}[DTL]{rotateinner}[true]{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLrotateouter}
+% \begin{macrocode}
+\define@boolkey{datapie}[DTL]{rotateouter}[true]{}
+% \end{macrocode}
+%\end{macro}
+% Set defaults:
+% \begin{macrocode}
+\DTLrotateinnerfalse
+\DTLrotateouterfalse
+% \end{macrocode}
+% Package options to change \cs{DTLrotateinner}
+% \begin{macrocode}
+\DeclareOption{rotateinner}{\DTLrotateinnertrue}
+\DeclareOption{norotateinner}{\DTLrotateinnerfalse}
+% \end{macrocode}
+% Package options to change \cs{DTLrotateouter}
+% \begin{macrocode}
+\DeclareOption{rotateouter}{\DTLrotateoutertrue}
+\DeclareOption{norotateouter}{\DTLrotateouterfalse}
+% \end{macrocode}
+% Process options:
+% \begin{macrocode}
+\ProcessOptions
+% \end{macrocode}
+% Required packages:
+% \begin{macrocode}
+\RequirePackage{datatool}
+\RequirePackage{tikz}
+% \end{macrocode}
+% Define some variables that govern the appearance of the pie
+% chart.
+%
+%\begin{macro}{\DTLradius}
+% The radius of the pie chart is given by \cs{DTLradius}.
+% \begin{macrocode}
+\newlength\DTLradius
+\DTLradius=2cm
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLinnerratio}
+% The inner label offset ratio is given by \cs{DTLinnerratio}
+% \begin{macrocode}
+\newcommand*{\DTLinnerratio}{0.5}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLouterratio}
+% The outer label offset ratio is given by \cs{DTLouterratio}.
+% \begin{macrocode}
+\newcommand*{\DTLouterratio}{1.25}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLcutawayratio}
+% The cutaway offset ratio is given by \cs{DTLcutawayratio}.
+% \begin{macrocode}
+\newcommand*\DTLcutawayratio{0.2}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLstartangle}
+% The angle of the first segment is given by \cs{DTLstartangle}.
+% \begin{macrocode}
+\newcommand*{\DTLstartangle}{0}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@inneroffset}
+% \begin{macrocode}
+\newlength\dtl@inneroffset
+\dtl@inneroffset=\DTLinnerratio\DTLradius
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@outeroffset}
+% \begin{macrocode}
+\newlength\dtl@outeroffset
+\dtl@outeroffset=\DTLouterratio\DTLradius
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@cutawayoffset}
+% \begin{macrocode}
+\newlength\dtl@cutawayoffset
+\dtl@cutawayoffset=\DTLcutawayratio\DTLradius
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@piecutaways}
+% \cs{dtl@piecutaways} is a comma separated list of segments that
+% need to be cut away from the pie chart.
+% \begin{macrocode}
+\newcommand*{\dtl@piecutaways}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@innerlabel}
+% \cs{dtl@innerlabel} specifies the label to appear inside
+% the segment. By default this is the variable used to create
+% the pie chart.
+% \begin{macrocode}
+\def\dtl@innerlabel{\DTLpievariable}%
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@outerlabel}
+% \begin{macrocode}
+\def\dtl@outerlabel{}%
+% \end{macrocode}
+%\end{macro}
+% \counterfmt{DTLpieroundvar} is a counter governing the number of digits
+% to round to when using \cs{FPround}.
+% \begin{macrocode}
+\newcounter{DTLpieroundvar}
+\setcounter{DTLpieroundvar}{1}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLdisplayinnerlabel}
+%\begin{definition}
+%\cs{DTLdisplayinnerlabel}\marg{label}
+%\end{definition}
+% This is used to format the inner label. This just does the
+% label by default.
+% \begin{macrocode}
+\newcommand*{\DTLdisplayinnerlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdisplayouterlabel}
+%\begin{definition}
+%\cs{DTLdisplayouterlabel}\marg{label}
+%\end{definition}
+% This is used to format the outer label. This just does the
+% label by default.
+% \begin{macrocode}
+\newcommand*{\DTLdisplayouterlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLpiepercent}
+%\cs{DTLpiepercent}
+% returns the percentage value of the current segment.
+% \begin{macrocode}
+\newcommand*{\DTLpiepercent}{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datapie}{Can't use
+ \string\DTLpiepercent\space outside
+ \string\DTLpiechart}{}%
+\else
+ \csname dtl@piepercent@\romannumeral\@dtl@seg\endcsname
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLpieatbegintikz}
+% \cs{DTLpieatbegintikz} specifies any commands
+% to apply at the start of the \env{tikzpicture} environment.
+% By default it does nothing.
+% \begin{macrocode}
+\newcommand*{\DTLpieatbegintikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLpieatendtikz}
+% \cs{DTLpieatendtikz} specifies any commands
+% to apply at the end of the \env{tikzpicture} environment.
+% By default it does nothing.
+% \begin{macrocode}
+\newcommand*{\DTLpieatendtikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsetpiesegmentcolor}
+%\begin{definition}
+% \cs{DTLsetpiesegmentcolor}\marg{n}\marg{color}
+%\end{definition}
+% Assign colour name \meta{color} to the \meta{n}th segment.
+% \begin{macrocode}
+\newcommand*{\DTLsetpiesegmentcolor}[2]{%
+\expandafter\def\csname dtlpie@segcol\romannumeral#1\endcsname{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetpiesegmentcolor}
+%\begin{definition}
+%\cs{DTLgetpiesegmentcolor}\marg{n}
+%\end{definition}
+% Get the colour specification for segment \meta{n}
+% \begin{macrocode}
+\newcommand*{\DTLgetpiesegmentcolor}[1]{%
+\csname dtlpie@segcol\romannumeral#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdopiesegmentcolor}
+%\begin{definition}
+%\cs{DTLdopiesegmentcolor}\marg{n}
+%\end{definition}
+% Set the colour to that for segment \meta{n}
+% \begin{macrocode}
+\newcommand*{\DTLdopiesegmentcolor}[1]{%
+\expandafter\color\expandafter
+{\csname dtlpie@segcol\romannumeral#1\endcsname}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLdocurrentpiesegmentcolor}
+%\cs{DTLdocurrentpiesegmentcolor}
+% sets the colour to that of the current segment.
+% \begin{macrocode}
+\newcommand*{\DTLdocurrentpiesegmentcolor}{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datapie}{Can't use
+ \string\DTLdocurrentpiesegmentcolor\space outside
+ \string\DTLpiechart}{}%
+\else
+ \expandafter\DTLdopiesegmentcolor\expandafter{%
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLpieoutlinecolor}
+%\cs{DTLpieoutlinecolor} specifies what colour to draw the
+% outline.
+% \begin{macrocode}
+\newcommand*{\DTLpieoutlinecolor}{black}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLpieoutlinewidth}
+%\cs{DTLpieoutlinewidth} specifies the line width of the outline:
+% Outline is only drawn if the linewidth is greater than 0pt.
+% \begin{macrocode}
+\newlength\DTLpieoutlinewidth
+\DTLpieoutlinewidth=0pt
+% \end{macrocode}
+%\end{macro}
+%
+% Set the default colours. If there are more than eight segments,
+% more colours will need to be defined.
+% \begin{macrocode}
+\ifDTLcolorpiechart
+ \DTLsetpiesegmentcolor{1}{red}
+ \DTLsetpiesegmentcolor{2}{green}
+ \DTLsetpiesegmentcolor{3}{blue}
+ \DTLsetpiesegmentcolor{4}{yellow}
+ \DTLsetpiesegmentcolor{5}{magenta}
+ \DTLsetpiesegmentcolor{6}{cyan}
+ \DTLsetpiesegmentcolor{7}{orange}
+ \DTLsetpiesegmentcolor{8}{white}
+\else
+ \DTLsetpiesegmentcolor{1}{black!15}
+ \DTLsetpiesegmentcolor{2}{black!25}
+ \DTLsetpiesegmentcolor{3}{black!35}
+ \DTLsetpiesegmentcolor{4}{black!45}
+ \DTLsetpiesegmentcolor{5}{black!55}
+ \DTLsetpiesegmentcolor{6}{black!65}
+ \DTLsetpiesegmentcolor{7}{black!75}
+ \DTLsetpiesegmentcolor{8}{black!85}
+\fi
+% \end{macrocode}
+% Define keys for \cs{DTLpiechart} optional argument.
+% Set the starting angle of the first segment.
+% \begin{macrocode}
+\define@key{datapie}{start}{\def\DTLstartangle{#1}}
+% \end{macrocode}
+% Set the radius of the pie chart (must be set prior to
+% inneroffset and outeroffset keys.)
+% \begin{macrocode}
+\define@key{datapie}{radius}{\DTLradius=#1\relax
+\dtl@inneroffset=\DTLinnerratio\DTLradius
+\dtl@outeroffset=\DTLouterratio\DTLradius
+\dtl@cutawayoffset=\DTLcutawayratio\DTLradius}
+% \end{macrocode}
+% Set the inner ratio.
+% \begin{macrocode}
+\define@key{datapie}{innerratio}{%
+\def\DTLinnerratio{#1}%
+\dtl@inneroffset=\DTLinnerratio\DTLradius}
+% \end{macrocode}
+% Set the outer ratio
+% \begin{macrocode}
+\define@key{datapie}{outerratio}{%
+\def\DTLouterratio{#1}%
+\dtl@outeroffset=\DTLouterratio\DTLradius}
+% \end{macrocode}
+% The cutaway offset ratio
+% \begin{macrocode}
+\define@key{datapie}{cutawayratio}{%
+\def\DTLcutawayratio{#1}%
+\dtl@cutawayoffset=\DTLcutawayratio\DTLradius}
+% \end{macrocode}
+% Set the inner offset as an absolute value (not dependent
+% on the radius.)
+% \begin{macrocode}
+\define@key{datapie}{inneroffset}{%
+\dtl@inneroffset=#1}
+% \end{macrocode}
+% Set the outer offset as an absolute value (not dependent
+% on the radius.)
+% \begin{macrocode}
+\define@key{datapie}{outeroffset}{%
+\dtl@outeroffset=#1}
+% \end{macrocode}
+% Set the cutaway offset as an absolute value (not dependent
+% on the radius.)
+% \begin{macrocode}
+\define@key{datapie}{cutawayoffset}{%
+\dtl@cutawayoffset=#1}
+% \end{macrocode}
+% List of cut away segments.
+% \begin{macrocode}
+\define@key{datapie}{cutaway}{%
+\renewcommand*{\dtl@piecutaways}{#1}}
+% \end{macrocode}
+% Variable used to create the pie chart. (Must be a control
+% sequence.)
+% \begin{macrocode}
+\define@key{datapie}{variable}{%
+\def\DTLpievariable{#1}}
+% \end{macrocode}
+% Inner label
+% \begin{macrocode}
+\define@key{datapie}{innerlabel}{%
+\def\dtl@innerlabel{#1}}
+% \end{macrocode}
+% Outer label
+% \begin{macrocode}
+\define@key{datapie}{outerlabel}{%
+\def\dtl@outerlabel{#1}}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLpiechart}
+%\begin{definition}
+% \cs{DTLpiechart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list}
+%\end{definition}
+% Make a pie chart from data given in data base \meta{db name},
+% where \meta{assign list} is a comma-separated list of
+% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must
+% include \texttt{variable}\texttt{=}\meta{cmd}, where \meta{cmd}
+% is included in \meta{assign list}. The optional argument
+% \meta{conditions} is the same as that for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLpiechart}[4][\boolean{true}]{%
+{\let\DTLpievariable=\relax
+\setkeys{datapie}{#2}%
+\ifx\DTLpievariable\relax
+ \PackageError{datapie}{\string\DTLpiechart\space missing variable}{}%
+\else
+% \end{macrocode}
+% Compute the total.
+%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of
+%\cs{DTLforeach}}
+% \begin{macrocode}
+\def\dtl@total{0}%
+\@sDTLforeach[#1]{#3}{#4}{%
+\let\dtl@oldtotal=\dtl@total
+\expandafter\DTLconverttodecimal\expandafter
+ {\DTLpievariable}{\dtl@variable}%
+\FPadd{\dtl@total}{\dtl@variable}{\dtl@total}%
+}%
+% \end{macrocode}
+% Compute the angles
+% \begin{macrocode}
+\expandafter\DTLconverttodecimal\expandafter
+ {\DTLstartangle}{\@dtl@start}%
+\@sDTLforeach[#1]{#3}{#4}{%
+\expandafter\DTLconverttodecimal\expandafter
+ {\DTLpievariable}{\dtl@variable}%
+\dtl@computeangles{%
+\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}{%
+\dtl@variable}%
+\expandafter\@dtl@seg\expandafter=
+\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname%
+\FPmul{\dtl@tmp}{\dtl@variable}{100}%
+\let\dtl@old=\dtl@tmp
+\FPdiv{\dtl@tmp}{\dtl@old}{\dtl@total}%
+\expandafter\FPround
+\csname dtl@piepercent@\romannumeral\@dtl@seg\endcsname\dtl@tmp
+\c@DTLpieroundvar
+}%
+% \end{macrocode}
+% Compute the offsets for each cut away segment
+% \begin{macrocode}
+\@for\dtl@row:=\dtl@piecutaways\do{%
+\expandafter\@dtl@set@off\dtl@row-\relax
+}%
+% \end{macrocode}
+% Set the starting angle
+% \begin{macrocode}
+\let\dtl@start=\DTLstartangle
+% \end{macrocode}
+% Do the pie chart
+% \begin{macrocode}
+\begin{tikzpicture}
+\DTLpieatbegintikz
+\@sDTLforeach[#1]{#3}{#4}{%
+% \end{macrocode}
+% Store the segment number in \cs{@dtl@seg}
+% \begin{macrocode}
+\expandafter\@dtl@seg\expandafter=
+\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname%
+% \end{macrocode}
+% Set the start angle.
+% \begin{macrocode}
+\edef\dtl@start{\csname dtl@sang@\romannumeral\@dtl@seg\endcsname}%
+% \end{macrocode}
+% Set the extent
+% \begin{macrocode}
+\edef\dtl@extent{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}%
+% \end{macrocode}
+% Compute the end angle
+% \begin{macrocode}
+\FPadd{\dtl@endangle}{\dtl@start}{\dtl@extent}%
+% \end{macrocode}
+% Compute the shift.
+% \begin{macrocode}
+\edef\dtl@angle{\csname dtl@cut@angle@\romannumeral\@dtl@seg\endcsname}%
+\let\dtl@old=\dtl@angle
+\dtl@truncatedecimal\dtl@angle
+\ifnum\dtl@angle>180
+ \FPsub{\dtl@angle}{\dtl@old}{360}%
+ \dtl@truncatedecimal\dtl@angle
+\fi
+\edef\dtl@cutlen{%
+\csname dtl@cut@len@\romannumeral\@dtl@seg\endcsname}
+\edef\@dtl@shift{(\dtl@angle:\dtl@cutlen)}%
+% \end{macrocode}
+% Compute the mid way angle.
+% \begin{macrocode}
+\FPmul{\dtl@angle}{\dtl@extent}{0.5}%
+\FPadd{\dtl@midangle}{\dtl@angle}{\dtl@start}%
+% \end{macrocode}
+% Draw the segment.
+% \begin{macrocode}
+\begin{scope}[shift={\@dtl@shift}]%
+\dtl@truncatedecimal\dtl@start
+\dtl@truncatedecimal\dtl@endangle
+\fill[color=\DTLgetpiesegmentcolor\@dtl@seg] (0,0) --
+(\dtl@start:\DTLradius)
+arc (\dtl@start:\dtl@endangle:\DTLradius) -- cycle;
+% \end{macrocode}
+% Draw the outline if required:
+% \begin{macrocode}
+\ifdim\DTLpieoutlinewidth>0pt\relax
+\draw[color=\DTLpieoutlinecolor,line width=\DTLpieoutlinewidth]
+(0,0) -- (\dtl@start:\DTLradius)
+arc (\dtl@start:\dtl@endangle:\DTLradius) -- cycle;
+\fi
+% \end{macrocode}
+% Convert decimal to an integer
+% \begin{macrocode}
+\dtl@truncatedecimal\dtl@midangle
+% \end{macrocode}
+% Determine whether to rotate inner labels
+% \begin{macrocode}
+\ifDTLrotateinner
+% \end{macrocode}
+% If the mid way angle is between 90 and 270, the text will look
+% upside-down, so adjust accordingly.
+% \begin{macrocode}
+\ifthenelse{\(\dtl@midangle > 90 \and \dtl@midangle < 270\)
+\TE@or \dtl@midangle < -90}{%
+ \FPsub{\dtl@labelangle}{\dtl@midangle}{180}%
+ \dtl@truncatedecimal\dtl@labelangle
+ \edef\dtl@innernodeopt{anchor=east,rotate=\dtl@labelangle}%
+}{%
+ \edef\dtl@innernodeopt{anchor=west,rotate=\dtl@midangle}%
+}%
+% \end{macrocode}
+% Don't rotate inner labels
+% \begin{macrocode}
+\else
+ \edef\dtl@innernodeopt{anchor=center}%
+\fi
+% \end{macrocode}
+% Determine whether to rotate outer labels
+% \begin{macrocode}
+\ifDTLrotateouter
+% \end{macrocode}
+% If the mid way angle is between 90 and 270, the text will look
+% upside-down, so adjust accordingly.
+% \begin{macrocode}
+\ifthenelse{\(\dtl@midangle > 90 \and \dtl@midangle < 270\)
+\TE@or \dtl@midangle < -90}{%
+ \FPsub{\dtl@labelangle}{\dtl@midangle}{180}%
+ \dtl@truncatedecimal\dtl@labelangle
+ \edef\dtl@outernodeopt{anchor=east,rotate=\dtl@labelangle}%
+}{%
+ \edef\dtl@outernodeopt{anchor=west,rotate=\dtl@midangle}%
+}%
+% \end{macrocode}
+% Don't rotate outer labels
+% \begin{macrocode}
+\else
+ \ifthenelse{\(\dtl@midangle<45\and\dtl@midangle>-45\)
+ \TE@or \dtl@midangle=45
+ \TE@or \dtl@midangle>315}{%
+ % east quadrant
+ \edef\dtl@outernodeopt{anchor=west}%
+ }{%
+ \ifthenelse{\(\dtl@midangle<135\and\dtl@midangle>45\)
+ \TE@or \dtl@midangle=135}{%
+ % north quadrant
+ \edef\dtl@outernodeopt{anchor=south}%
+ }{%
+ \ifthenelse{\(\dtl@midangle<225\and\dtl@midangle>135\)
+ \TE@or \dtl@midangle=225
+ \TE@or \dtl@midangle=-135
+ \TE@or \dtl@midangle<-135}{%
+ % west quadrant
+ \edef\dtl@outernodeopt{anchor=east}%
+ }{%
+ \edef\dtl@outernodeopt{anchor=north}%
+ }%
+ }
+ }
+\fi
+% \end{macrocode}
+% Draw inner and outer labels
+% \begin{macrocode}
+\edef\@dtl@dolabel{%
+\noexpand\draw (\dtl@midangle:\the\dtl@inneroffset)
+node[\dtl@innernodeopt]{%
+\noexpand\DTLdisplayinnerlabel{\noexpand\dtl@innerlabel}};}%
+\@dtl@dolabel
+\edef\@dtl@dolabel{%
+\noexpand\draw (\dtl@midangle:\the\dtl@outeroffset)
+node[\dtl@outernodeopt]{%
+\noexpand\DTLdisplayouterlabel{\noexpand\dtl@outerlabel}};}%
+\@dtl@dolabel
+\end{scope}
+}%
+\DTLpieatendtikz
+\end{tikzpicture}
+\fi
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@computeangles}
+%\begin{definition}
+%\cs{dtl@computeangles}\marg{n}\marg{variable}
+%\end{definition}
+% Compute the angles for segment \meta{n}. This sets
+% \cs{dtl@sang@}\meta{n} (start angle),
+% \cs{dtl@angle@}\meta{n} (extent angle),
+% \cs{dtl@cut@angle@}\meta{n} (cut away angle) and
+% \cs{dtl@cut@len@}\meta{n} (cut away length).
+% \begin{macrocode}
+\newcommand*{\dtl@computeangles}[2]{%
+\FPifgt{\@dtl@start}{180}%
+% if startangle > 180
+ \let\dtl@old=\@dtl@start
+% startangle = startangle - 360
+ \FPsub{\@dtl@start}{\dtl@old}{360}%
+\fi
+\FPiflt{\@dtl@start}{-180}%
+% if startangle < -180
+ \let\dtl@old=\@dtl@start
+% startangle = startangle + 360
+ \FPadd{\@dtl@start}{\dtl@old}{360}%
+\fi
+\expandafter\edef\csname dtl@sang@\romannumeral#1\endcsname{%
+\@dtl@start}%
+\FPmul{\dtl@angle}{360}{#2}%
+\let\dtl@old=\dtl@angle
+\FPdiv{\dtl@angle}{\dtl@old}{\dtl@total}%
+\expandafter\let\csname dtl@angle@\romannumeral#1\endcsname=\dtl@angle
+\let\dtl@old=\@dtl@start
+\FPadd{\@dtl@start}{\dtl@old}{\dtl@angle}%
+\expandafter\def\csname dtl@cut@angle@\romannumeral#1\endcsname{0}%
+\expandafter\def\csname dtl@cut@len@\romannumeral#1\endcsname{0cm}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Set the offset angles.
+%\begin{macro}{\@dtl@set@off}
+% \begin{macrocode}
+\def\@dtl@set@off#1-#2\relax{%
+\ifthenelse{\equal{#2}{}}{%
+\@@dtl@set@off{#1}}{%
+\@@dtl@set@offr#1-#2\relax}%
+}
+% \end{macrocode}
+%\end{macro}
+% Set offset for individual segment:
+%\begin{macro}{\@@dtl@set@off}
+% \begin{macrocode}
+\newcommand*{\@@dtl@set@off}[1]{%
+\edef\dtl@old{\csname dtl@angle@\romannumeral#1\endcsname}%
+\FPmul{\dtl@angle}{\dtl@old}{0.5}%
+\let\dtl@old=\dtl@angle
+\edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}%
+\FPadd{\dtl@angle}{\dtl@old}{\dtl@sang}%
+\expandafter\edef\csname dtl@cut@angle@\romannumeral#1\endcsname{%
+\dtl@angle}%
+\expandafter\edef\csname dtl@cut@len@\romannumeral#1\endcsname{%
+ \the\dtl@cutawayoffset}
+}
+% \end{macrocode}
+%\end{macro}
+% Define count register to keep track of segments
+%\begin{macro}{\@dtl@seg}
+% \begin{macrocode}
+\newcount\@dtl@seg
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@@dtl@setoffr}
+% Set offset for a range of segments
+% \begin{macrocode}
+\def\@@dtl@set@offr#1-#2-\relax{%
+\ifnum#1>#2\relax
+ \PackageError{datapie}{Segment ranges must go in ascending order}{%
+Try #2-#1 instead of #1-#2}%
+\else
+ \def\dtl@angle{0}%
+ \@dtl@seg=#1\relax
+ \whiledo{\not\(\@dtl@seg > #2\)}{%
+ \let\dtl@old=\dtl@angle
+ \edef\dtl@segang{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}%
+ \FPadd{\dtl@angle}{\dtl@old}{\dtl@segang}%
+ \advance\@dtl@seg by 1\relax
+ }%
+ \let\dtl@old=\dtl@angle
+ \FPmul{\dtl@angle}{\dtl@old}{0.5}%
+ \edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}%
+ \let\dtl@old=\dtl@angle
+ \FPadd{\dtl@angle}{\dtl@old}{\dtl@sang}%
+ \@dtl@seg=#1\relax
+ \whiledo{\not\(\@dtl@seg > #2\)}{%
+ \expandafter
+ \let\csname dtl@cut@angle@\romannumeral\@dtl@seg\endcsname
+ =\dtl@angle
+ \expandafter
+ \edef\csname dtl@cut@len@\romannumeral\@dtl@seg\endcsname{%
+ \the\dtl@cutawayoffset}
+ \advance\@dtl@seg by 1\relax
+ }%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</datapie.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*dataplot.sty>
+% \end{macrocode}
+%\fi
+%\section{dataplot.sty}
+% Declare package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{dataplot}[2007/08/17 v1.01 (NLCT)]
+% \end{macrocode}
+% Required packages
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+\RequirePackage{tikz}
+\RequirePackage{datatool}
+% \end{macrocode}
+% Load TikZ plot libraries
+% \begin{macrocode}
+\usetikzlibrary{plotmarks}
+\usetikzlibrary{plothandlers}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLplotstream}
+%\begin{definition}
+%\cs{DTLplotstream}\oarg{condition}\marg{db name}\marg{x key}\marg{y key}
+%\end{definition}
+% Add points to a stream from the database called \meta{db name}
+% where the $x$ co-ordinates are given by the key \meta{x key}
+% and the $y$ co-ordinates are given by the key \meta{y key}.
+% The optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}
+%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of
+%\cs{DTLforeach}}
+% \begin{macrocode}
+\newcommand*{\DTLplotstream}[4][\boolean{true}]{%
+\@sDTLforeach[#1]{#2}{\dtl@x=#3,\dtl@y=#4}{%
+\DTLconverttodecimal{\dtl@x}{\dtl@decx}%
+\DTLconverttodecimal{\dtl@y}{\dtl@decy}%
+\pgfplotstreampoint{\pgfpointxy{\dtl@decx}{\dtl@decy}}}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLplotmarks}
+%\cs{DTLplotmarks} contains a list of plot marks used by
+%\cs{DTLplot}.
+% \begin{macrocode}
+\newcommand*{\DTLplotmarks}{%
+\pgfuseplotmark{o},%
+\pgfuseplotmark{x},%
+\pgfuseplotmark{+},%
+\pgfuseplotmark{square},%
+\pgfuseplotmark{triangle},%
+\pgfuseplotmark{diamond},%
+\pgfuseplotmark{pentagon},%
+\pgfuseplotmark{asterisk},%
+\pgfuseplotmark{star}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLplotmarkcolors}
+%\cs{DTLplotmarkcolors} contains a list of the plot mark colours.
+% \begin{macrocode}
+\newcommand*{\DTLplotmarkcolors}{%
+red,%
+green,%
+blue,%
+yellow,%
+magenta,%
+cyan,%
+orange,%
+black,%
+gray}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLplotlines}
+%\cs{DTLplotlines} contains a list of dash patterns used by
+%\cs{DLTplot}.
+% \begin{macrocode}
+\newcommand*{\DTLplotlines}{%
+\pgfsetdash{}{{0pt}},% solid line
+\pgfsetdash{{10pt}{5pt}}{0pt},%
+\pgfsetdash{{5pt}{5pt}}{0pt},%
+\pgfsetdash{{1pt}{5pt}}{0pt},%
+\pgfsetdash{{5pt}{5pt}{1pt}{5pt}}{0pt},%
+\pgfsetdash{{1pt}{3pt}}{0pt},%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLplotlinecolors}
+%\cs{DTLplotlinecolors} contains a list of the plot line colours.
+% \begin{macrocode}
+\newcommand*{\DTLplotlinecolors}{%
+red,%
+green,%
+blue,%
+yellow,%
+magenta,%
+cyan,%
+orange,%
+black,%
+gray}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLplotwidth}
+% The default total plot width is stored in the length
+% \cs{dtlplotwidth}
+% \begin{macrocode}
+\newlength\DTLplotwidth
+\setlength\DTLplotwidth{4in}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLplotheight}
+% The default total plot height is stored in the length
+% \cs{dtlplotheight}
+% \begin{macrocode}
+\newlength\DTLplotheight
+\setlength\DTLplotheight{4in}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLticklength}
+% The length of the tick marks is given by \cs{DTLticklength}
+% \begin{macrocode}
+\newlength\DTLticklength
+\setlength\DTLticklength{5pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLminorticklength}
+% The length of the minor tick marks is given by
+% \cs{DTLminorticklength}.
+% \begin{macrocode}
+\newlength\DTLminorticklength
+\setlength\DTLminorticklength{2pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLticklabeloffset}
+% The offset from the axis to the tick label is given by
+% \cs{DTLticklabeloffset}.
+% \begin{macrocode}
+\newlength\DTLticklabeloffset
+\setlength\DTLticklabeloffset{8pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@xticlabelheight}
+% \cs{dtl@xticlabelheight} is used to store the height of
+% the $x$ tick labels.
+% \begin{macrocode}
+\newlength\dtl@xticlabelheight
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@yticlabelwidth}
+% \cs{dtl@yticlabelwidth} is used to store the width of
+% the $y$ tick labels.
+% \begin{macrocode}
+\newlength\dtl@yticlabelwidth
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLmintickgap}
+% \cs{DTLmintickgap} stores the suggested minimum distance between
+% tick marks where the gap is not specified.
+% \begin{macrocode}
+\newlength\DTLmintickgap
+\setlength\DTLmintickgap{20pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLminminortickgap}
+% The suggested minimum distance between minor tick marks where the
+% gap is not specified is given by \cs{DTLminminortickgap}.
+% \begin{macrocode}
+\newlength\DTLminminortickgap
+\setlength\DTLminminortickgap{5pt}
+% \end{macrocode}
+%\end{macro}
+% Round $x$ tick labels to the number of digits given by
+% the counter \counterfmt{DTLplotroundXvar}.
+% \begin{macrocode}
+\newcounter{DTLplotroundXvar}
+\setcounter{DTLplotroundXvar}{2}
+% \end{macrocode}
+% Round $y$ tick labels to the number of digits given by
+% the counter \counterfmt{DTLplotroundYvar}.
+% \begin{macrocode}
+\newcounter{DTLplotroundYvar}
+\setcounter{DTLplotroundYvar}{2}
+% \end{macrocode}
+%\begin{macro}{\ifDTLxaxis}
+% The conditional \cs {ifDTLxaxis} is used to determine whether or
+% not to display the $x$ axis.
+% \begin{macrocode}
+\newif\ifDTLxaxis
+\DTLxaxistrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLXAxisStyle}
+% The style of the $x$ axis is given by \cs{DTLXAxisStyle}. This
+% is just a solid line by default.
+% \begin{macrocode}
+\newcommand*{\DTLXAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLyaxis}
+% The conditional \cs{ifDTLyaxis} is used to determine whether or
+% not to display the $y$ axis
+% \begin{macrocode}
+\newif\ifDTLyaxis
+\DTLyaxistrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLYAxisStyle}
+% The style of the $y$ axis is given by \cs{DTLYAxisStyle}. This
+% is just a solid line by default.
+% \begin{macrocode}
+\newcommand*{\DTLYAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLmajorgridstyle}
+% The style of the major grid lines is given by
+% \cs{DTLmajorgridstyle}.
+% \begin{macrocode}
+\newcommand*{\DTLmajorgridstyle}{color=gray,-}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLminorgridstyle}
+% The style of the minor grid lines is given by
+% \cs{DTLminorgridstyle}.
+% \begin{macrocode}
+\newcommand*{\DTLminorgridstyle}{color=gray,loosely dotted}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLxticsin}
+% The conditional \cs{ifDTLxticsin} is used to determine whether
+% the $x$ tics should point in or out.
+% \begin{macrocode}
+\newif\ifDTLxticsin
+\DTLxticsintrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLyticsin}
+% The conditional \cs{ifDTLyticsin} is used to determine whether
+% the $y$ tics should point in or out.
+% \begin{macrocode}
+\newif\ifDTLyticsin
+\DTLyticsintrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@legendsetting}
+% The legend setting is stored in the count register
+% \cs{dtl@legendsetting}.
+% \begin{macrocode}
+\newcount\dtl@legendsetting
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLlegendxoffset}
+% The gap between the border of plot and legend is given by the
+% lengths \cs{DTLlegendxoffset} and \cs{DTLlegendyoffset}
+% \begin{macrocode}
+\newlength\DTLlegendxoffset
+\setlength\DTLlegendxoffset{10pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLlegendyoffset}
+% \begin{macrocode}
+\newlength\DTLlegendyoffset
+\setlength\DTLlegendyoffset{10pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatlegend}
+%\begin{definition}
+%\cs{DTLformatlegend}\marg{legend}
+%\end{definition}
+% This formats the legend.
+% \begin{macrocode}
+\newcommand*{\DTLformatlegend}[1]{%
+\setlength{\fboxrule}{1.1pt}%
+\fcolorbox{black}{white}{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLshowmarkers}
+% The conditional \cs{ifDTLshowmarkers} is used to specify
+% whether or not to use markers.
+% \begin{macrocode}
+\newif\ifDTLshowmarkers
+\DTLshowmarkerstrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLshowlines}
+% The conditional \cs{ifDTLshowlines} is used to specify
+% whether or not to use lines.
+% \begin{macrocode}
+\newif\ifDTLshowlines
+\DTLshowlinesfalse
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLplotatbegintikz}
+% \cs{DTLplotatbegintikz} is a hook to insert stuff at the
+% start of the \env{tikzpicture}
+% environment (after the unit vectors have been set).
+% \begin{macrocode}
+\newcommand*{\DTLplotatbegintikz}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLplotatendtikz}
+% \cs{DTLplotatendtikz} is a hook to insert stuff at the end
+% of the \env{tikzpicture} environment.
+% \begin{macrocode}
+\newcommand*{\DTLplotatendtikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+% Plot settings. The database key for the $x$ value is
+% given by the "x" setting:
+% \begin{macrocode}
+\define@key{dataplot}{x}{%
+\def\dtl@xkey{#1}}
+% \end{macrocode}
+% The database key for the $y$ value is given by the "y" setting:
+% \begin{macrocode}
+\define@key{dataplot}{y}{%
+\def\dtl@ykey{#1}}
+% \end{macrocode}
+% The list of plot mark colours is given by the "markcolors" setting.
+% (This should be a comma separated list of colour names.)
+% \begin{macrocode}
+\define@key{dataplot}{markcolors}{%
+\def\DTLplotmarkcolors{#1}}
+% \end{macrocode}
+% The list of plot line colours is given by the "linecolors" setting.
+% (This should be a comma separated list of colour names.)
+% \begin{macrocode}
+\define@key{dataplot}{linecolors}{%
+\def\DTLplotlinecolors{#1}}
+% \end{macrocode}
+% The list of plot mark and line colours is given by the "colors"
+% setting. (This should be a comma separated list of colour names.)
+% \begin{macrocode}
+\define@key{dataplot}{colors}{%
+\def\DTLplotmarkcolors{#1}%
+\def\DTLplotlinecolors{#1}}
+% \end{macrocode}
+% The list of plot marks is given by the "marks" setting. (This
+% should be a comma separated list of code that generates
+% pgf plot marks.)
+% \begin{macrocode}
+\define@key{dataplot}{marks}{%
+\def\DTLplotmarks{#1}}
+% \end{macrocode}
+% The list of plot line styles is given by the "lines" setting. (This
+% should be a comma separated list of code that sets the line
+% style.) An empty set will create solid lines.
+% \begin{macrocode}
+\define@key{dataplot}{lines}{%
+\def\DTLplotlines{#1}}
+% \end{macrocode}
+% The total width of the plot is given by the "width" setting.
+% \begin{macrocode}
+\define@key{dataplot}{width}{%
+\setlength\DTLplotwidth{#1}}
+% \end{macrocode}
+% The total height of the plot is given by the "height" setting.
+% \begin{macrocode}
+\define@key{dataplot}{height}{%
+\setlength\DTLplotheight{#1}}
+% \end{macrocode}
+% Determine whether to show lines, markers or both
+% \begin{macrocode}
+\define@choicekey{dataplot}{style}[\val\nr]{both,lines,markers}{%
+\ifcase\nr\relax
+ \DTLshowlinestrue
+ \DTLshowmarkerstrue
+\or
+ \DTLshowlinestrue
+ \DTLshowmarkersfalse
+\or
+ \DTLshowmarkerstrue
+ \DTLshowlinesfalse
+\fi}
+% \end{macrocode}
+% Determine whether or not to display the axes
+% \begin{macrocode}
+\define@choicekey{dataplot}{axes}[\val\nr]{both,x,y,none}[both]{%
+\ifcase\nr\relax
+ % both
+ \DTLxaxistrue
+ \DTLxticstrue
+ \DTLyaxistrue
+ \DTLyticstrue
+\or % x
+ \DTLxaxistrue
+ \DTLxticstrue
+ \DTLyaxisfalse
+ \DTLyticsfalse
+\or % y
+ \DTLxaxisfalse
+ \DTLxticsfalse
+ \DTLyaxistrue
+ \DTLyticstrue
+\or % none
+ \DTLxaxisfalse
+ \DTLxticsfalse
+ \DTLyaxisfalse
+ \DTLyticsfalse
+\fi
+}
+% \end{macrocode}
+%\begin{macro}{\ifDTLbox}
+% Enclose plot in a box
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{box}[true]{}
+\DTLboxfalse
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLxticstrue}
+% Condition to determine whether to show the $x$ tick marks
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{xtics}[true]{}
+\DTLxticstrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLyticstrue}
+% Condition to determine whether to show the $y$ tick marks
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{ytics}[true]{}
+\DTLyticstrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLxminortics}
+% Condition to determine whether to show the $x$ minor tick marks
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{xminortics}[true]{%
+\ifDTLxminortics \DTLxticstrue\fi}
+\DTLxminorticsfalse
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLyminortics}
+% Condition to determine whether to show the $y$ minor tick marks
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{yminortics}[true]{%
+\ifDTLyminortics \DTLyticstrue\fi}
+\DTLyminorticsfalse
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLgrid}
+% Determine whether to draw the grid
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{grid}[true]{}
+% \end{macrocode}
+%\end{macro}
+% Determine whether the $x$ tick marks should point
+% in or out:
+% \begin{macrocode}
+\define@choicekey{dataplot}{xticdir}[\val\nr]{in,out}{%
+\ifcase\nr\relax
+ \DTLxticsintrue
+\or
+ \DTLxticsinfalse
+\fi
+}
+% \end{macrocode}
+% Determine whether the $y$ tick marks should point
+% in or out:
+% \begin{macrocode}
+\define@choicekey{dataplot}{yticdir}[\val\nr]{in,out}{%
+\ifcase\nr\relax
+ \DTLyticsintrue
+\or
+ \DTLyticsinfalse
+\fi
+}
+% \end{macrocode}
+% Determine whether the $x$ and $y$ tick marks should point
+% in or out;
+% \begin{macrocode}
+\define@choicekey{dataplot}{ticdir}[\val\nr]{in,out}{%
+\ifcase\nr\relax
+ \DTLxticsintrue
+ \DTLyticsintrue
+\or
+ \DTLxticsinfalse
+ \DTLyticsinfalse
+\fi
+}
+% \end{macrocode}
+% Set the bounds of the graph (value must be in the form
+% \meta{min x}","\meta{min y}","\meta{max x}","\meta{max y}
+% (bounds overrides minx, miny, maxx and maxy settings.)
+% \begin{macrocode}
+\define@key{dataplot}{bounds}{%
+\def\dtl@bounds{#1}}
+\let\dtl@bounds=\relax
+% \end{macrocode}
+% Set only the lower $x$ bound
+% \begin{macrocode}
+\define@key{dataplot}{minx}{%
+\def\dtl@minx{#1}}
+\let\dtl@minx=\relax
+% \end{macrocode}
+% Set only the upper $x$ bound:
+% \begin{macrocode}
+\define@key{dataplot}{maxx}{%
+\def\dtl@maxx{#1}}
+\let\dtl@maxx=\relax
+% \end{macrocode}
+% Set only the lower $y$ bound:
+% \begin{macrocode}
+\define@key{dataplot}{miny}{%
+\def\dtl@miny{#1}}
+\let\dtl@miny=\relax
+% \end{macrocode}
+% Set only the upper $y$ bound:
+% \begin{macrocode}
+\define@key{dataplot}{maxy}{%
+\def\dtl@maxy{#1}}
+\let\dtl@maxy=\relax
+% \end{macrocode}
+% Define list of points for $x$ ticks. (Must be a comma separated
+% list of decimal numbers.)
+% \begin{macrocode}
+\define@key{dataplot}{xticpoints}{%
+\def\dtl@xticlist{#1}\DTLxticstrue\DTLxaxistrue}
+\let\dtl@xticlist=\relax
+% \end{macrocode}
+% Define list of points for $y$ ticks. (Must be a comma separated
+% list of decimal numbers.)
+% \begin{macrocode}
+\define@key{dataplot}{yticpoints}{%
+\def\dtl@yticlist{#1}\DTLyticstrue\DTLyaxistrue}
+\let\dtl@yticlist=\relax
+% \end{macrocode}
+% Define a the gap between $x$ tick marks (xticpoints overrides
+% xticgap)
+% \begin{macrocode}
+\define@key{dataplot}{xticgap}{\def\dtl@xticgap{#1}%
+\DTLxticstrue\DTLxaxistrue}
+\let\dtl@xticgap=\relax
+% \end{macrocode}
+% Define a the gap between $y$ tick marks (yticpoints overrides
+% yticgap)
+% \begin{macrocode}
+\define@key{dataplot}{yticgap}{\def\dtl@yticgap{#1}%
+\DTLyticstrue\DTLyaxistrue}
+\let\dtl@yticgap=\relax
+% \end{macrocode}
+% Define comma separated list of labels for $x$ ticks.
+% \begin{macrocode}
+\define@key{dataplot}{xticlabels}{%
+\def\dtl@xticlabels{#1}\DTLxticstrue\DTLxaxistrue}
+\let\dtl@xticlabels=\relax
+% \end{macrocode}
+% Define comma separated list of labels for $y$ ticks.
+% \begin{macrocode}
+\define@key{dataplot}{yticlabels}{%
+\def\dtl@yticlabels{#1}\DTLyticstrue\DTLyaxistrue}
+\let\dtl@yticlabels=\relax
+% \end{macrocode}
+% Define $x$ axis label
+% \begin{macrocode}
+\define@key{dataplot}{xlabel}{%
+\def\dtl@xlabel{#1}}
+\let\dtl@xlabel=\relax
+% \end{macrocode}
+% Define $y$ axis label
+% \begin{macrocode}
+\define@key{dataplot}{ylabel}{%
+\def\dtl@ylabel{#1}}
+\let\dtl@ylabel=\relax
+% \end{macrocode}
+% The legend setting may be one of: "none" (don't show it),
+% "north", "northeast", "east", "southeast", "south", "southwest",
+% "west", or "northwest". These set the count register
+% \cs{dtl@legendsetting}.
+% \begin{macrocode}
+\define@choicekey{dataplot}{legend}[\val\nr]{none,north,northeast,%
+east,southeast,south,southwest,west,northwest}[northeast]{%
+\dtl@legendsetting=\nr\relax
+}
+% \end{macrocode}
+% Legend labels (comma separated list). If omitted, the database
+% name is used.
+% \begin{macrocode}
+\define@key{dataplot}{legendlabels}{\def\dtl@legendlabels{#1}}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLplot}
+%\begin{definition}
+%\cs{DTLplot}\oarg{condition}\marg{db list}\marg{settings}
+%\end{definition}
+% Creates a plot (inside a \env{tikzpicture} environment) of all
+% the data given in the databases listed in \meta{db list}.
+% \begin{macrocode}
+\newcommand*{\DTLplot}[3][\boolean{true}]{{%
+\let\dtl@xkey=\relax
+\let\dtl@ykey=\relax
+\let\dtl@legendlabels=\relax
+\setkeys{dataplot}{#3}%
+\let\dtl@plotmarklist=\DTLplotmarks
+\let\dtl@plotlinelist=\DTLplotlines
+\let\dtl@plotmarkcolorlist=\DTLplotmarkcolors
+\let\dtl@plotlinecolorlist=\DTLplotlinecolors
+\def\dtl@legend{}%
+\ifx\dtl@legendlabels\relax
+ \edef\dtl@legendlabels{#2}%
+\fi
+\ifx\dtl@xkey\relax
+ \PackageError{dataplot}{Missing x setting for
+ \string\DTLplot}{}%
+\else
+ \ifx\dtl@ykey\relax
+ \PackageError{dataplot}{Missing y setting for
+ \string\DTLplot}{}%
+ \else
+% \end{macrocode}
+% If user didn't specified bounds,
+% compute the maximum and minimum $x$ and $y$ values over
+% all the databases listed.
+% \begin{macrocode}
+ \ifx\dtl@bounds\relax
+ \DTLcomputebounds[#1]{#2}{\dtl@xkey}{\dtl@ykey}
+ {\DTLminX}{\DTLminY}{\DTLmaxX}{\DTLmaxY}%
+ \ifx\dtl@minx\relax
+ \else
+ \let\DTLminX=\dtl@minx
+ \fi
+ \ifx\dtl@maxx\relax
+ \else
+ \let\DTLmaxX=\dtl@maxx
+ \fi
+ \ifx\dtl@miny\relax
+ \else
+ \let\DTLminY=\dtl@miny
+ \fi
+ \ifx\dtl@maxy\relax
+ \else
+ \let\DTLmaxY=\dtl@maxy
+ \fi
+% \end{macrocode}
+% Otherwise extract information from \cs{dtl@bounds}
+% \begin{macrocode}
+ \else
+ \expandafter\dtl@getbounds\dtl@bounds\@nil
+ \fi
+% \end{macrocode}
+% Determine scaling factors.
+% \begin{macrocode}
+ \@dtl@tmpcount=\DTLplotwidth
+ \FPsub{\dtl@dx}{\DTLmaxX}{\DTLminX}%
+ \FPdiv{\dtl@unit@x}{\number\@dtl@tmpcount}{\dtl@dx}%
+ \@dtl@tmpcount=\DTLplotheight
+ \FPsub{\dtl@dy}{\DTLmaxY}{\DTLminY}%
+ \FPdiv{\dtl@unit@y}{\number\@dtl@tmpcount}{\dtl@dy}%
+% \end{macrocode}
+% If x tics specified, construct a list of x tic points if not
+% already specified.
+% \begin{macrocode}
+ \ifDTLxtics
+ \ifx\dtl@xticlist\relax
+ \ifx\dtl@xticgap\relax
+ \dtl@constructticklist\DTLminX\DTLmaxX
+ \dtl@unit@x\dtl@xticlist
+ \else
+ \DTLifFPopenbetween{0}{\DTLminX}{\DTLmaxX}{%
+ \dtl@constructticklistwithgapz
+ \DTLminX\DTLmaxX\dtl@xticlist\dtl@xticgap}{%
+ \dtl@constructticklistwithgap
+ \DTLminX\DTLmaxX\dtl@xticlist\dtl@xticgap}%
+ \fi
+ \fi
+% \end{macrocode}
+% Construct a list of $x$ minor tick points if required
+% \begin{macrocode}
+ \let\dtl@xminorticlist\@empty
+ \ifDTLxminortics
+ \let\dtl@prevtick=\relax
+ \@for\dtl@nexttick:=\dtl@xticlist\do{%
+ \ifx\dtl@prevtick\relax
+ \else
+ \dtl@constructminorticklist
+ \dtl@prevtick\dtl@nexttick\dtl@unit@x\dtl@xminorticlist
+ \fi
+ \let\dtl@prevtick=\dtl@nexttick
+ }%
+ \fi
+% \end{macrocode}
+% Determine the height of the $x$ tick labels.
+% \begin{macrocode}
+ \ifx\dtl@xticlabels\relax
+ \settoheight{\dtl@xticlabelheight}{\dtl@xticlist}%
+ \else
+ \settoheight{\dtl@xticlabelheight}{\dtl@xticlabels}%
+ \fi
+ \else
+ \setlength{\dtl@xticlabelheight}{0pt}%
+ \fi
+% \end{macrocode}
+% If y tics specified, construct a list of y tic points if not
+% already specified.
+% \begin{macrocode}
+ \setlength{\dtl@yticlabelwidth}{0pt}%
+ \ifDTLytics
+ \ifx\dtl@yticlist\relax
+ \ifx\dtl@yticgap\relax
+ \dtl@constructticklist\DTLminY\DTLmaxY
+ \dtl@unit@y\dtl@yticlist
+ \else
+ \DTLifFPopenbetween{0}{\DTLminY}{\DTLmaxY}{%
+ \dtl@constructticklistwithgapz
+ \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}{%
+ \dtl@constructticklistwithgap
+ \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}%
+ \fi
+ \fi
+% \end{macrocode}
+% Construct a list of $y$ minor tick points if required
+% \begin{macrocode}
+ \let\dtl@yminorticlist\@empty
+ \ifDTLyminortics
+ \let\dtl@prevtick=\relax
+ \@for\dtl@nexttick:=\dtl@yticlist\do{%
+ \ifx\dtl@prevtick\relax
+ \else
+ \dtl@constructminorticklist
+ \dtl@prevtick\dtl@nexttick\dtl@unit@y\dtl@yminorticlist
+ \fi
+ \let\dtl@prevtick=\dtl@nexttick
+ }%
+ \fi
+% \end{macrocode}
+% Determine the width of the $y$ tick labels.
+% \begin{macrocode}
+ \ifx\dtl@ylabel\relax
+ \else
+ \ifx\dtl@yticlabels\relax
+ \@for\dtl@thislabel:=\dtl@yticlist\do{%
+ \FPround{\dtl@thislabel}{\dtl@thislabel}
+ {\c@DTLplotroundYvar}%
+ \settowidth{\dtl@tmplength}{\dtl@thislabel}%
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \else
+ \@for\dtl@thislabel:=\dtl@yticlabels\do{%
+ \settowidth{\dtl@tmplength}{\dtl@thislabel}%
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \fi
+ \fi
+% \end{macrocode}
+% Start the picture.
+% \begin{macrocode}
+ \begin{tikzpicture}
+% \end{macrocode}
+% Set the $x$ and $y$ unit vectors.
+% \begin{macrocode}
+ \pgfsetxvec{\pgfpoint{\dtl@unit@x sp}{0pt}}%
+ \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit@y sp}}%
+% \end{macrocode}
+% Add any extra information the user requires
+% \begin{macrocode}
+ \DTLplotatbegintikz
+% \end{macrocode}
+% Determine whether to put a box around the plot
+% \begin{macrocode}
+ \ifDTLbox
+ \draw (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY) --
+ (\DTLmaxX,\DTLmaxY) -- (\DTLminX,\DTLmaxY) --
+ cycle;
+ \else
+% \end{macrocode}
+% Plot $x$ axis if required.
+% \begin{macrocode}
+ \ifDTLxaxis
+ \expandafter\draw\expandafter[\DTLXAxisStyle]
+ (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY);
+ \fi
+% \end{macrocode}
+% Plot $y$ axis if required.
+% \begin{macrocode}
+ \ifDTLyaxis
+ \expandafter\draw\expandafter[\DTLYAxisStyle]
+ (\DTLminX,\DTLminY) -- (\DTLminX,\DTLmaxY);
+ \fi
+ \fi
+% \end{macrocode}
+% Plot grid if required
+% \begin{macrocode}
+ \ifDTLgrid
+ \ifDTLxminortics
+ \@for\dtl@thistick:=\dtl@xminorticlist\do{%
+ \expandafter\draw\expandafter[\DTLminorgridstyle]
+ (\dtl@thistick,\DTLminY) -- (\dtl@thistick,\DTLmaxY);
+ }%
+ \fi
+ \ifDTLyminortics
+ \@for\dtl@thistick:=\dtl@yminorticlist\do{%
+ \expandafter\draw\expandafter[\DTLminorgridstyle]
+ (\DTLminX,\dtl@thistick) -- (\DTLmaxX,\dtl@thistick);
+ }%
+ \fi
+ \@for\dtl@thistick:=\dtl@xticlist\do{%
+ \expandafter\draw\expandafter[\DTLmajorgridstyle]
+ (\dtl@thistick,\DTLminY) -- (\dtl@thistick,\DTLmaxY);
+ }%
+ \@for\dtl@thistick:=\dtl@yticlist\do{%
+ \expandafter\draw\expandafter[\DTLmajorgridstyle]
+ (\DTLminX,\dtl@thistick) -- (\DTLmaxX,\dtl@thistick);
+ }%
+ \fi
+% \end{macrocode}
+% Plot $x$ tics if required.
+% \begin{macrocode}
+ \ifDTLxtics
+ \addtolength\dtl@xticlabelheight{\DTLticklabeloffset}%
+ \@for\dtl@thistick:=\dtl@xticlist\do{%
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ \ifDTLxticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ {\pgfpoint{0pt}{\DTLticklength}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ {\pgfpoint{0pt}{-\DTLticklength}}}
+ \fi
+ \ifDTLbox
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ \ifDTLxticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ {\pgfpoint{0pt}{-\DTLticklength}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ {\pgfpoint{0pt}{\DTLticklength}}}
+ \fi
+ \fi
+ \pgfusepath{stroke}%
+% \end{macrocode}
+% Plot the tick labels
+% \begin{macrocode}
+ \ifx\dtl@xticlabels\relax
+ \FPround{\dtl@thislabel}{\dtl@thistick}
+ {\c@DTLplotroundXvar}%
+ \else
+ \dtl@chopfirst\dtl@xticlabels\dtl@thislabel\dtl@rest
+ \let\dtl@xticlabels=\dtl@rest
+ \fi
+ \pgftext[base,center,at={\pgfpointadd
+ {\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ {\pgfpoint{0pt}{-\dtl@xticlabelheight}}}]
+ {\dtl@thislabel}
+ }%
+ \fi
+% \end{macrocode}
+% Plot $x$ label if required.
+% \begin{macrocode}
+ \ifx\dtl@xlabel\relax
+ \else
+ \addtolength{\dtl@xticlabelheight}{\baselineskip}%
+ \setlength{\dtl@tmplength}{0.5\DTLplotwidth}
+ \pgftext[base,center,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLminY}}%
+ {\pgfpoint{\dtl@tmplength}{-\dtl@xticlabelheight}}}]{%
+ \dtl@xlabel}
+ \fi
+% \end{macrocode}
+% Plot the $x$ minor ticks if required
+% \begin{macrocode}
+ \ifDTLxminortics
+ \@for\dtl@thistick:=\dtl@xminorticlist\do{%
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ \ifDTLxticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ {\pgfpoint{0pt}{\DTLminorticklength}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ {\pgfpoint{0pt}{-\DTLminorticklength}}}
+ \fi
+ \ifDTLbox
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ \ifDTLxticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ {\pgfpoint{0pt}{-\DTLminorticklength}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ {\pgfpoint{0pt}{\DTLminorticklength}}}
+ \fi
+ \fi
+ }%
+ \fi
+% \end{macrocode}
+% Plot $y$ tics if required.
+% \begin{macrocode}
+ \ifDTLytics
+ \@for\dtl@thistick:=\dtl@yticlist\do{%
+ \pgfpathmoveto{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ \ifDTLyticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ {\pgfpoint{\DTLticklength}{0pt}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ {\pgfpoint{-\DTLticklength}{0pt}}}
+ \fi
+ \ifDTLbox
+ \pgfpathmoveto{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ \ifDTLyticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ {\pgfpoint{-\DTLticklength}{0pt}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ {\pgfpoint{\DTLticklength}{0pt}}}
+ \fi
+ \fi
+ \pgfusepath{stroke}
+% \end{macrocode}
+% Plot the $y$ tick labels if required
+% \begin{macrocode}
+ \ifx\dtl@yticlabels\relax
+ \FPround{\dtl@thislabel}{\dtl@thistick}
+ {\c@DTLplotroundYvar}%
+ \else
+ \dtl@chopfirst\dtl@yticlabels\dtl@thislabel\dtl@rest
+ \let\dtl@yticlabels=\dtl@rest
+ \fi
+ \pgftext[right,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ {\pgfpoint{-\DTLticklabeloffset}{0pt}}}]
+ {\dtl@thislabel}
+ }%
+ \fi
+% \end{macrocode}
+% Plot $y$ label if required.
+% \begin{macrocode}
+ \ifx\dtl@ylabel\relax
+ \else
+ \addtolength{\dtl@yticlabelwidth}{\baselineskip}%
+ \setlength{\dtl@tmplength}{0.5\DTLplotheight}
+ \pgftext[bottom,center,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLminY}}%
+ {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}},
+ rotate=90]{%
+ \dtl@ylabel}
+ \fi
+% \end{macrocode}
+% Plot the $y$ minor ticks if required
+% \begin{macrocode}
+ \ifDTLyminortics
+ \@for\dtl@thistick:=\dtl@yminorticlist\do{%
+ \pgfpathmoveto{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ \ifDTLyticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ {\pgfpoint{\DTLminorticklength}{0pt}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ {\pgfpoint{-\DTLminorticklength}{0pt}}}
+ \fi
+ \ifDTLbox
+ \pgfpathmoveto{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ \ifDTLyticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ {\pgfpoint{-\DTLminorticklength}{0pt}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ {\pgfpoint{\DTLminorticklength}{0pt}}}
+ \fi
+ \fi
+ \pgfusepath{stroke}
+ }%
+ \fi
+% \end{macrocode}
+% Iterate through each database
+% \begin{macrocode}
+ \@for\dtl@thisdb:=#2\do{%
+% \end{macrocode}
+% Get the current plot mark colour.
+% \begin{macrocode}
+ \ifx\dtl@plotmarkcolorlist\@empty
+ \let\dtl@plotmarkcolorlist=\DTLplotmarkcolors
+ \fi
+ \dtl@chopfirst\dtl@plotmarkcolorlist\dtl@thisplotmarkcolor
+ \dtl@remainder
+ \let\dtl@plotmarkcolorlist=\dtl@remainder
+% \end{macrocode}
+% Get the current plot mark, and store in \cs{dtl@mark}
+% \begin{macrocode}
+ \ifDTLshowmarkers
+ \ifx\dtl@plotmarklist\@empty
+ \let\dtl@plotmarklist=\DTLplotmarks
+ \fi
+ \dtl@chopfirst\dtl@plotmarklist\dtl@thisplotmark
+ \dtl@remainder
+ \let\dtl@plotmarklist=\dtl@remainder
+ \ifx\dtl@thisplotmark\relax
+ \let\dtl@mark=\relax
+ \else
+ \expandafter\toks@\expandafter{\dtl@thisplotmark}%
+ \ifx\dtl@thisplotmarkcolor\@empty
+ \edef\dtl@mark{\the\toks@}%
+ \else
+ \edef\dtl@mark{%
+ \noexpand\color{\dtl@thisplotmarkcolor}%
+ \the\toks@}%
+ \fi
+ \fi
+ \else
+ \let\dtl@mark=\relax
+ \fi
+% \end{macrocode}
+% Get the current plot line colour.
+% \begin{macrocode}
+ \ifx\dtl@plotlinecolorlist\@empty
+ \let\dtl@plotlinecolorlist=\DTLplotlinecolors
+ \fi
+ \dtl@chopfirst\dtl@plotlinecolorlist\dtl@thisplotlinecolor
+ \dtl@remainder
+ \let\dtl@plotlinecolorlist=\dtl@remainder
+% \end{macrocode}
+% Get the current line style, and store in \cs{dtl@linestyle}
+% \begin{macrocode}
+ \ifDTLshowlines
+ \ifx\dtl@plotlinelist\@empty
+ \let\dtl@plotlinelist=\DTLplotlines
+ \fi
+ \dtl@chopfirst\dtl@plotlinelist\dtl@thisplotline
+ \dtl@remainder
+ \let\dtl@plotlinelist=\dtl@remainder
+ \expandafter\ifx\dtl@thisplotline\relax
+ \let\dtl@linestyle=\relax
+ \else
+ \expandafter\toks@\expandafter{\dtl@thisplotline}%
+ \ifx\dtl@thisplotlinecolor\@empty
+ \edef\dtl@linestyle{\the\toks@}%
+ \else
+ \edef\dtl@linestyle{%
+ \noexpand\color{\dtl@thisplotlinecolor}%
+ \the\toks@}%
+ \fi
+ \fi
+ \else
+ \let\dtl@linestyle=\relax
+ \fi
+% \end{macrocode}
+% Append this plot setting to the legend.
+% \begin{macrocode}
+ \ifnum\dtl@legendsetting>0\relax
+ \dtl@chopfirst\dtl@legendlabels\dtl@thislabel\dtl@rest
+ \let\dtl@legendlabels=\dtl@rest
+ \expandafter\toks@\expandafter{\dtl@mark}%
+ \expandafter\@dtl@toks\expandafter{\dtl@linestyle}%
+ \edef\dtl@addtolegend{\noexpand\DTLaddtoplotlegend
+ {\the\toks@}{\the\@dtl@toks}{\dtl@thislabel}}%
+ \dtl@addtolegend
+ \fi
+% \end{macrocode}
+% Store stream in \cs{dtl@stream}
+% \begin{macrocode}
+ \def\dtl@stream{\pgfplotstreamstart}%
+% \end{macrocode}
+% Only plot points that lie inside bounds.
+%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of
+%\cs{DTLforeach}}
+% \begin{macrocode}
+ \@sDTLforeach[#1]{\dtl@thisdb}{\dtl@x=\dtl@xkey,%
+ \dtl@y=\dtl@ykey}{%
+ \DTLconverttodecimal{\dtl@x}{\dtl@decx}%
+ \DTLconverttodecimal{\dtl@y}{\dtl@decy}%
+ \ifthenelse{%
+ \DTLisclosedbetween{\dtl@x}{\DTLminX}{\DTLmaxX}%
+ \and
+ \DTLisclosedbetween{\dtl@y}{\DTLminY}{\DTLmaxY}%
+ }{%
+ \expandafter\toks@\expandafter{\dtl@stream}%
+ \edef\dtl@stream{\the\toks@
+ \noexpand\pgfplotstreampoint
+ {\noexpand\pgfpointxy{\dtl@decx}{\dtl@decy}}}%
+ }{}%
+ }%
+ \expandafter\toks@\expandafter{\dtl@stream}%
+ \edef\dtl@stream{\the\toks@\noexpand\pgfplotstreamend}%
+% \end{macrocode}
+% End plot stream and draw path.
+% \begin{macrocode}
+ \ifx\dtl@linestyle\relax
+ \else
+ \begin{scope}
+ \dtl@linestyle
+ \pgfplothandlerlineto
+ \dtl@stream
+ \pgfusepath{stroke}
+ \end{scope}
+ \fi
+ \ifx\dtl@mark\relax
+ \else
+ \begin{scope}
+ \pgfplothandlermark{\dtl@mark}%
+ \dtl@stream
+ \pgfusepath{stroke}
+ \end{scope}
+ \fi
+ }%
+% \end{macrocode}
+% Plot legend if required.
+% \begin{macrocode}
+ \ifcase\dtl@legendsetting
+ % none
+ \or % north
+ \pgftext[top,center,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLmaxY}}
+ {\pgfpoint{0.5\DTLplotwidth}{-\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % north east
+ \pgftext[top,right,at={\pgfpointadd
+ {\pgfpointxy{\DTLmaxX}{\DTLmaxY}}
+ {\pgfpoint{-\DTLlegendxoffset}{-\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % east
+ \pgftext[center,right,at={\pgfpointadd
+ {\pgfpointxy{\DTLmaxX}{\DTLminY}}
+ {\pgfpoint{-\DTLlegendxoffset}{0.5\DTLplotheight}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % south east
+ \pgftext[bottom,right,at={\pgfpointadd
+ {\pgfpointxy{\DTLmaxX}{\DTLminY}}
+ {\pgfpoint{-\DTLlegendxoffset}{\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % south
+ \pgftext[center,bottom,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLminY}}
+ {\pgfpoint{0.5\DTLplotwidth}{\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % south west
+ \pgftext[bottom,left,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLminY}}
+ {\pgfpoint{\DTLlegendxoffset}{\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % west
+ \pgftext[center,left,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLminY}}
+ {\pgfpoint{\DTLlegendxoffset}{0.5\DTLplotheight}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % north west
+ \pgftext[top,left,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLmaxY}}
+ {\pgfpoint{\DTLlegendxoffset}{-\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \fi
+ \DTLplotatendtikz
+ \end{tikzpicture}
+ \fi
+ \fi
+\fi
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@getbounds}
+% Extract bounds:
+% \begin{macrocode}
+\def\dtl@getbounds#1,#2,#3,#4\@nil{%
+\def\DTLminX{#1}%
+\def\DTLminY{#2}%
+\def\DTLmaxX{#3}%
+\def\DTLmaxY{#4}%
+\FPifgt{\DTLminX}{\DTLmaxX}
+ \PackageError{dataplot}{Min X > Max X in bounds #1,#2,#3,#4}{%
+ The bounds must be specified as minX,minY,maxX,maxY}%
+\fi
+\FPifgt{\DTLminY}{\DTLmaxY}
+ \PackageError{dataplot}{Min Y > Max Y in bounds #1,#2,#3,#4}{%
+ The bounds must be specified as minX,minY,maxX,maxY}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@constructticklist}
+%\begin{definition}
+%\cs{dtl@constructticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list}
+%\end{definition}
+% Constructs a list of tick points between \meta{min} and \meta{max}
+% and store in \meta{list} (a control sequence.)
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklist}[4]{%
+\DTLifFPopenbetween{0}{#1}{#2}{%
+ \FPsub{\@dtl@width}{0}{#1}%
+ \FPmul{\@dtl@width}{\@dtl@width}{#3}%
+ \FPdiv{\@dtl@neggap}{\@dtl@width}{10}%
+ \setlength\dtl@tmplength{\@dtl@neggap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@neggap}{\@dtl@width}{4}%
+ \setlength\dtl@tmplength{\@dtl@neggap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@neggap}{\@dtl@width}{2}%
+ \setlength\dtl@tmplength{\@dtl@neggap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \let\@dtl@neggap=\@dtl@width
+ \fi
+ \fi
+ \fi
+ \FPmul{\@dtl@width}{#2}{#3}%
+ \FPdiv{\@dtl@posgap}{\@dtl@width}{10}%
+ \setlength\dtl@tmplength{\@dtl@posgap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@posgap}{\@dtl@width}{4}%
+ \setlength\dtl@tmplength{\@dtl@posgap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@posgap}{\@dtl@width}{2}%
+ \setlength\dtl@tmplength{\@dtl@posgap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \let\@dtl@posgap=\@dtl@width
+ \fi
+ \fi
+ \fi
+ \FPmax{\@dtl@gap}{\@dtl@neggap}{\@dtl@posgap}%
+ \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}%
+ \dtl@constructticklistwithgapz{#1}{#2}{#4}{\@dtl@gap}%
+}{%
+ \FPsub{\@dtl@width}{#2}{#1}%
+ \FPmul{\@dtl@width}{\@dtl@width}{#3}%
+ \FPdiv{\@dtl@gap}{\@dtl@width}{10}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@gap}{\@dtl@width}{4}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@gap}{\@dtl@width}{2}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \let\@dtl@gap=\@dtl@width
+ \fi
+ \fi
+ \fi
+ \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}%
+ \dtl@constructticklistwithgap{#1}{#2}{#4}{\@dtl@gap}%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@constructticklistwithgap}
+%\begin{definition}
+%\cs{dtl@constructticklistwithgap}\marg{min}\marg{max}\marg{list}\marg{gap}
+%\end{definition}
+% Constructs a list of tick points between \meta{min} and \meta{max}
+% and store in \meta{list} (a control sequence) using the gap given
+% by \meta{gap} where the gap is given in user co-ordinates.
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklistwithgap}[4]{%
+\edef\@dtl@thistick{#1}%
+\edef#3{#1}%
+\FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{#2}}{%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \edef#3{#3,\the\toks@}%
+ \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+}%
+\expandafter\toks@\expandafter{#2}%
+\edef#3{#3,\the\toks@}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@constructticklistwithgapz}
+%\begin{definition}
+%\cs{dtl@constructticklistwithgapz}\marg{min}\marg{max}\marg{list}\marg{gap}
+%\end{definition}
+% Constructs a list of tick points between \meta{min} and \meta{max}
+% and store in \meta{list} (a control sequence) using the gap given
+% by \meta{gap} where the tick list straddles zero.
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklistwithgapz}[4]{%
+\edef\@dtl@thistick{0}%
+\edef#3{0}%
+\FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{0}{#2}}{%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \edef#3{#3,\the\toks@}%
+ \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+}%
+\expandafter\toks@\expandafter{#2}%
+\edef#3{#3,\the\toks@}%
+\FPifeq{#1}{0}%
+\else
+\edef\@dtl@thistick{0}%
+ \FPsub{\@dtl@thistick}{\@dtl@thistick}{#4}%
+ \whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{0}}{%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \edef#3{\the\toks@,#3}%
+ \FPsub{\@dtl@thistick}{\@dtl@thistick}{#4}%
+ }%
+ \expandafter\toks@\expandafter{#1}%
+ \edef#3{\the\toks@,#3}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@constructminorticklist}
+%\begin{definition}
+%\cs{dtl@constructminorticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list}
+%\end{definition}
+% Constructs a list of minor tick points between \meta{min} and \meta{max}
+% and append to \meta{list} (a control sequence.)
+% \begin{macrocode}
+\newcommand*{\dtl@constructminorticklist}[4]{%
+ \FPsub{\@dtl@width}{#2}{#1}%
+ \FPmul{\@dtl@width}{\@dtl@width}{#3}%
+ \FPdiv{\@dtl@gap}{\@dtl@width}{10}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLminminortickgap
+ \FPdiv{\@dtl@gap}{\@dtl@width}{4}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLminminortickgap
+ \FPdiv{\@dtl@gap}{\@dtl@width}{2}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLminminortickgap
+ \let\@dtl@gap=\@dtl@width
+ \fi
+ \fi
+ \fi
+ \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}%
+ \dtl@constructticklistwithgapex{#1}{#2}{\dtl@tmp}{\@dtl@gap}%
+ \ifx#4\@empty
+ \let#4=\dtl@tmp
+ \else
+ \expandafter\toks@\expandafter{#4}%
+ \edef#4{#4,\dtl@tmp}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@constructticklistwithgapex}
+%\begin{definition}
+%\cs{dtl@constructticklistwithgapex}\marg{min}\marg{max}\marg{list}\marg{gap}
+%\end{definition}
+% Constructs a list of tick points between \meta{min} and \meta{max}
+% and store in \meta{list} (a control sequence) using the gap given
+% by \meta{gap} where the gap is given in user co-ordinates.
+% The end points are excluded from the list.
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklistwithgapex}[4]{%
+\edef\@dtl@thistick{#1}%
+\let#3=\@empty
+\FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{#2}}{%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \ifx#3\@empty
+ \edef#3{\the\toks@}%
+ \else
+ \edef#3{#3,\the\toks@}%
+ \fi
+ \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddtoplotlegend}
+%\begin{definition}
+%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{label}
+%\end{definition}
+% Adds entry to legend.
+% \begin{macrocode}
+\newcommand*{\DTLaddtoplotlegend}[3]{%
+\def\dtl@legendline{}%
+\ifx\relax#2\relax
+\else
+ \toks@{#2%
+ \pgfpathmoveto{\pgfpoint{-10pt}{0pt}}%
+ \pgfpathlineto{\pgfpoint{10pt}{0pt}}%
+ \pgfusepath{stroke}}%
+ \edef\dtl@legendline{\the\toks@}%
+\fi
+\ifx\relax#1\relax
+\else
+ \toks@{#1}%
+ \expandafter\@dtl@toks\expandafter{\dtl@legendline}%
+ \edef\dtl@legendline{\the\@dtl@toks\the\toks@}%
+\fi
+\expandafter\toks@\expandafter{\dtl@legendline}%
+\ifx\dtl@legend\@empty
+ \edef\dtl@legend{\noexpand\tikz\the\toks@; \noexpand& #3}%
+\else
+ \expandafter\@dtl@toks\expandafter{\dtl@legend}%
+ \edef\dtl@legend{\the\@dtl@toks\noexpand\\%
+ \noexpand\tikz\the\toks@; \noexpand& #3}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</dataplot.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*databar.sty>
+% \end{macrocode}
+%\fi
+%\section{databar.sty}
+% Declare package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{databar}[2007/08/17 v1.01 (NLCT)]
+% \end{macrocode}
+% Require \sty{xkeyval} package
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+% \end{macrocode}
+% Require \sty{dataplot} package
+% \begin{macrocode}
+\RequirePackage{dataplot}
+% \end{macrocode}
+%\begin{macro}{\ifDTLcolorbarchart}
+% The conditional \cs{ifDTLcolorbarchart} is used to determine
+% whether to use colour or grey scale.
+% \begin{macrocode}
+\newif\ifDTLcolorbarchart
+\DTLcolorbarcharttrue
+% \end{macrocode}
+%\end{macro}
+% Package options to change the conditional:
+% \begin{macrocode}
+\DeclareOption{color}{\DTLcolorbarcharttrue}
+\DeclareOption{gray}{\DTLcolorbarchartfalse}
+% \end{macrocode}
+%\cs{DTLbarXlabelalign} specifies the alignment
+% for the $x$ axis labels.
+% \begin{macrocode}
+\newcommand*{\DTLbarXlabelalign}{left,rotate=-90}
+% \end{macrocode}
+%\cs{DTLbarYticklabelalign} specifies the alignment
+% for the $x$ axis labels.
+% \begin{macrocode}
+\newcommand*{\DTLbarYticklabelalign}{right}
+% \end{macrocode}
+%\begin{macro}{\ifDTLverticalbars}
+% Define boolean keys to govern bar chart orientation.
+% \begin{macrocode}
+\define@boolkey{databar}[DTL]{verticalbars}[true]{%
+\ifDTLverticalbars
+ \def\DTLbarXlabelalign{left,rotate=-90}%
+ \def\DTLbarYticklabelalign{right}
+\else
+ \def\DTLbarXlabelalign{right}%
+ \def\DTLbarYticklabelalign{center}
+\fi}
+% \end{macrocode}
+%\end{macro}
+% Set defaults:
+% \begin{macrocode}
+\DTLverticalbarstrue
+% \end{macrocode}
+% Package options to change \cs{ifDTLverticalbars}
+% \begin{macrocode}
+\DeclareOption{vertical}{\DTLverticalbarstrue
+ \def\DTLbarXlabelalign{left,rotate=-90}%
+ \def\DTLbarYticklabelalign{right}
+}
+\DeclareOption{horizontal}{\DTLverticalbarsfalse
+ \def\DTLbarXlabelalign{right}%
+ \def\DTLbarYticklabelalign{center}
+}
+% \end{macrocode}
+% Process options:
+% \begin{macrocode}
+\ProcessOptions
+% \end{macrocode}
+% Required packages:
+% \begin{macrocode}
+\RequirePackage{datatool}
+\RequirePackage{tikz}
+% \end{macrocode}
+% Define some variables that govern the appearance of the bar
+% chart.
+%
+%\begin{macro}{\DTLbarchartlength}
+% The total height of the bar chart is given by \cs{DTLbarchartheight}
+% \begin{macrocode}
+\newlength\DTLbarchartlength
+\DTLbarchartlength=3in
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbarwidth}
+% The width of each bar is given by \cs{DTLbarwidth}.
+% \begin{macrocode}
+\newlength\DTLbarwidth
+\DTLbarwidth=1cm
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbarlabeloffset}
+% The offset from the $x$ axis to the bar label if given by
+% \cs{DTLbarlabeloffset}.
+% \begin{macrocode}
+\newlength\DTLbarlabeloffset
+\setlength\DTLbarlabeloffset{10pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLBarXAxisStyle}
+% The style of the $x$ axis is given by \cs{DTLBarXAxisStyle}
+% \begin{macrocode}
+\newcommand*{\DTLBarXAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLBarYAxisStyle}
+% The style of the $y$ axis is given by \cs{DTLBarYAxisStyle}.
+% \begin{macrocode}
+\newcommand*{\DTLBarYAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+%
+% \counterfmt{DTLbarroundvar} is a counter governing the number of digits
+% to round to when using \cs{FPround}.
+% \begin{macrocode}
+\newcounter{DTLbarroundvar}
+\setcounter{DTLbarroundvar}{1}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLbardisplayYticklabel}
+%\cs{DTLbardisplayYticklabel} governs how the $y$ tick labels appear.
+% \begin{macrocode}
+\newcommand*{\DTLbardisplayYticklabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLdisplaylowerbarlabel}
+%\cs{DTLdisplaylowerbarlabel} governs how the lower bar labels appear.
+% \begin{macrocode}
+\newcommand*{\DTLdisplaylowerbarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLdisplaylowermultibarlabel}
+%\cs{DTLdisplaylowermultibarlabel} governs how the lower multi bar labels appear.
+% \begin{macrocode}
+\newcommand*{\DTLdisplaylowermultibarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLdisplayupperbarlabel}
+%\cs{DTLdisplayupperbarlabel} governs how the upper bar labels
+% appear.
+% \begin{macrocode}
+\newcommand*{\DTLdisplayupperbarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLdisplayuppermultibarlabel}
+%\cs{DTLdisplayuppermultibarlabel} governs how the upper multi bar
+% labels appear.
+% \begin{macrocode}
+\newcommand*{\DTLdisplayuppermultibarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbaratbegintikz}
+% \cs{DTLbaratbegintikz} specifies any commands
+% to apply at the start of the \env{tikzpicture} environment.
+% By default it does nothing.
+% \begin{macrocode}
+\newcommand*{\DTLbaratbegintikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbaratendtikz}
+% \cs{DTLbaratendtikz} specifies any commands
+% to apply at the end of the \env{tikzpicture} environment.
+% By default it does nothing.
+% \begin{macrocode}
+\newcommand*{\DTLbaratendtikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLbarxaxis}
+% The conditional \cs{ifDTLbarxaxis} is used to determine
+% whether or not to display the $x$ axis
+% \begin{macrocode}
+\newif\ifDTLbarxaxis
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLbaryaxis}
+% The conditional \cs{ifDTLbaryaxis} is used to determine
+% whether or not to display the $y$ axis.
+% \begin{macrocode}
+\newif\ifDTLbaryaxis
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLbarytics}
+% The conditional \cs{ifDTLbarytics} to determine whether
+% or not to display the $y$ tick marks.
+% \begin{macrocode}
+\newif\ifDTLbarytics
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@barcount}
+% The count register \cs{@dtl@barcount} is used to store
+% the current bar index.
+% \begin{macrocode}
+\newcount\@dtl@barcount
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsetbarcolor}
+%\begin{definition}
+% \cs{DTLsetbarcolor}\marg{n}\marg{color}
+%\end{definition}
+% Assigns colour name \meta{color} to the \meta{n}th bar.
+% \begin{macrocode}
+\newcommand*{\DTLsetbarcolor}[2]{%
+\expandafter\def\csname dtlbar@segcol\romannumeral#1\endcsname{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetbarcolor}
+%\begin{definition}
+%\cs{DTLgetbarcolor}\marg{n}
+%\end{definition}
+% Gets the colour specification for the \meta{n}th bar.
+% \begin{macrocode}
+\newcommand*{\DTLgetbarcolor}[1]{%
+\csname dtlbar@segcol\romannumeral#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdobarcolor}
+%\begin{definition}
+%\cs{DTLdobarcolor}\marg{n}
+%\end{definition}
+% Sets the colour to that for the \meta{n}th bar.
+% \begin{macrocode}
+\newcommand*{\DTLdobarcolor}[1]{%
+\expandafter\color\expandafter
+{\csname dtlbar@segcol\romannumeral#1\endcsname}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdocurrentbarcolor}
+%\cs{DTLdocurrentbarcolor}
+% sets the colour to that of the current bar.
+% \begin{macrocode}
+\newcommand*{\DTLdocurrentbarcolor}{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{databar}{Can't use
+ \string\DTLdocurrentbarcolor\space outside
+ \string\DTLbarchart}{}%
+\else
+ \expandafter\DTLdobarcolor\expandafter{%
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbaroutlinecolor}
+%\cs{DTLbaroutlinecolor} specifies what colour to draw the
+% outline.
+% \begin{macrocode}
+\newcommand*{\DTLbaroutlinecolor}{black}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbaroutlinewidth}
+%\cs{DTLbaroutlinewidth} specifies the line width of the outline:
+% Outline is only drawn if the linewidth is greater than 0pt.
+% \begin{macrocode}
+\newlength\DTLbaroutlinewidth
+\DTLbaroutlinewidth=0pt
+% \end{macrocode}
+%\end{macro}
+%
+% Set the default colours. If there are more than eight bars,
+% more colours will need to be defined.
+% \begin{macrocode}
+\ifDTLcolorbarchart
+ \DTLsetbarcolor{1}{red}
+ \DTLsetbarcolor{2}{green}
+ \DTLsetbarcolor{3}{blue}
+ \DTLsetbarcolor{4}{yellow}
+ \DTLsetbarcolor{5}{magenta}
+ \DTLsetbarcolor{6}{cyan}
+ \DTLsetbarcolor{7}{orange}
+ \DTLsetbarcolor{8}{white}
+\else
+ \DTLsetbarcolor{1}{black!15}
+ \DTLsetbarcolor{2}{black!25}
+ \DTLsetbarcolor{3}{black!35}
+ \DTLsetbarcolor{4}{black!45}
+ \DTLsetbarcolor{5}{black!55}
+ \DTLsetbarcolor{6}{black!65}
+ \DTLsetbarcolor{7}{black!75}
+ \DTLsetbarcolor{8}{black!85}
+\fi
+% \end{macrocode}
+%
+% Define keys for \cs{DTLbarchart} optional argument.
+% Set the maximum value of the $y$ axis.
+% \begin{macrocode}
+\define@key{databar}{max}{\def\DTLbarmax{#1}}
+% \end{macrocode}
+% Set the total length of the bar chart
+% \begin{macrocode}
+\define@key{databar}{length}{\DTLbarchartlength=#1\relax
+}
+% \end{macrocode}
+% Set the maximum depth (negative extent)
+% \begin{macrocode}
+\define@key{databar}{maxdepth}{%
+\ifnum#1>0\relax
+ \PackageError{databar}{depth must be zero or negative}{}%
+\else
+ \def\DTLnegextent{#1}%
+\fi}
+% \end{macrocode}
+% Determine which axes should be shown
+% \begin{macrocode}
+\define@choicekey{databar}{axes}[\var\nr]{both,x,y,none}{%
+\ifcase\nr\relax
+ % both
+ \DTLbarxaxistrue
+ \DTLbaryaxistrue
+ \DTLbaryticstrue
+\or
+ % x only
+ \DTLbarxaxistrue
+ \DTLbaryaxisfalse
+ \DTLbaryticsfalse
+\or
+ % y only
+ \DTLbarxaxisfalse
+ \DTLbaryaxistrue
+ \DTLbaryticstrue
+\or
+ % neither
+ \DTLbarxaxisfalse
+ \DTLbaryaxisfalse
+ \DTLbaryticsfalse
+\fi
+}
+% \end{macrocode}
+% Variable used to create the bar chart. (Must be a control
+% sequence.)
+% \begin{macrocode}
+\define@key{databar}{variable}{%
+\def\DTLbarvariable{#1}}
+% \end{macrocode}
+% Variables used to create the multi bar chart. (Must be a
+% comma separated list of control sequences.)
+% \begin{macrocode}
+\define@key{databar}{variables}{%
+\def\dtlbar@variables{#1}}
+% \end{macrocode}
+% Bar width
+% \begin{macrocode}
+\define@key{databar}{barwidth}{\setlength{\DTLbarwidth}{#1}}
+% \end{macrocode}
+% Lower bar labels
+% \begin{macrocode}
+\define@key{databar}{barlabel}{%
+\def\dtl@barlabel{#1}}
+\def\dtl@barlabel{}
+% \end{macrocode}
+% Lower bar labels for multi-bar charts
+% \begin{macrocode}
+\define@key{databar}{multibarlabels}{%
+\def\dtl@multibarlabels{#1}}
+\def\dtl@multibarlabels{}
+% \end{macrocode}
+% Gap between groups in multi-bar charts (This should be in $x$ units
+% where 1 $x$ unit is the width of a bar.)
+% \begin{macrocode}
+\define@key{databar}{groupgap}{\def\dtlbar@groupgap{#1}}
+\def\dtlbar@groupgap{1}
+% \end{macrocode}
+% Upper bar labels
+% \begin{macrocode}
+\define@key{databar}{upperbarlabel}{%
+\def\dtl@upperbarlabel{#1}}
+\def\dtl@upperbarlabel{}
+% \end{macrocode}
+% Upper bar labels for multi-bar charts
+% \begin{macrocode}
+\define@key{databar}{uppermultibarlabels}{%
+\def\dtl@uppermultibarlabels{#1}}
+\def\dtl@uppermultibarlabels{}
+% \end{macrocode}
+% Define list of points for $y$ tics. (Must be a comma separated list
+% of decimal numbers.)
+% \begin{macrocode}
+\define@key{databar}{yticpoints}{%
+\def\dtlbar@yticlist{#1}\DTLbaryticstrue\DTLbaryaxistrue}
+\let\dtlbar@yticlist=\relax
+% \end{macrocode}
+% Set the $y$ tick gap:
+% \begin{macrocode}
+\define@key{databar}{yticgap}{%
+\def\dtlbar@yticgap{#1}\DTLbaryticstrue\DTLbaryaxistrue}
+\let\dtlbar@yticgap=\relax
+% \end{macrocode}
+% Define list of labels for $y$ tics.
+% \begin{macrocode}
+\define@key{databar}{yticlabels}{%
+\def\dtlbar@yticlabels{#1}\DTLbaryticstrue\DTLbaryaxistrue}
+\let\dtlbar@yticlabels=\relax
+% \end{macrocode}
+% Define $y$ axis label.
+% \begin{macrocode}
+\define@key{databar}{ylabel}{%
+\def\dtlbar@ylabel{#1}}
+\let\dtlbar@ylabel=\relax
+% \end{macrocode}
+%
+%\begin{macro}{\DTLbarchart}
+%\begin{definition}
+% \cs{DTLbarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list}
+%\end{definition}
+% Make a bar chart from data given in data base \meta{db name},
+% where \meta{assign list} is a comma-separated list of
+% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must
+% include \texttt{variable}\texttt{=}\meta{cmd}, where \meta{cmd}
+% is included in \meta{assign list}. The optional argument
+% \meta{conditions} is the same as that for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLbarchart}[4][\boolean{true}]{%
+{\let\DTLbarvariable=\relax
+\let\DTLbarmax=\relax
+\let\DTLnegextent=\relax
+\disable@keys{databar}{variables,multibarlabels,%
+uppermultibarlabels,groupgap}%
+\setkeys{databar}{#2}%
+\ifx\DTLbarvariable\relax
+ \PackageError{databar}{\string\DTLbarchart\space missing variable}{}%
+\else
+% \end{macrocode}
+% Compute the maximum bar height, unless \cs{DTLbarmax} has been
+% set.
+%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of
+%\cs{DTLforeach}}
+% \begin{macrocode}
+ \ifx\DTLbarmax\relax
+ \@sDTLforeach[#1]{#3}{#4}{%
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@barvar}%
+ \ifx\DTLbarmax\relax
+ \let\DTLbarmax=\dtl@barvar
+ \else
+ \let\dtl@old=\DTLbarmax
+ \FPmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}%
+ \fi
+ }%
+ \ifx\dtlbar@yticgap\relax
+ \else
+ \let\dtl@thistick=\dtlbar@yticgap%
+ \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{%
+ \FPadd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}%
+ }%
+ \let\DTLbarmax=\dtl@thistick
+ \fi
+ \fi
+% \end{macrocode}
+% Compute the bar depth, unless \cs{DTLnegextent} has been
+% set.
+% \begin{macrocode}
+ \ifx\DTLnegextent\relax
+ \def\DTLnegextent{0}%
+ \@sDTLforeach[#1]{#3}{#4}{%
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@barvar}%
+ \let\dtl@old=\DTLnegextent
+ \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}%
+ }%
+ \ifx\dtlbar@yticgap\relax
+ \else
+ \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}{%
+ \edef\dtl@thistick{0}%
+ \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{%
+ \FPsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}%
+ }%
+ \let\DTLnegextent=\dtl@thistick
+ }{}%
+ \fi
+ \fi
+% \end{macrocode}
+% Determine scaling factor
+% \begin{macrocode}
+ \@dtl@tmpcount=\DTLbarchartlength
+ \FPsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}%
+ \FPdiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}%
+% \end{macrocode}
+% Construct $y$ tick list if required
+% \begin{macrocode}
+ \setlength{\dtl@yticlabelwidth}{0pt}%
+ \ifDTLbarytics
+ \ifx\dtlbar@yticlist\relax
+ \ifx\dtlbar@yticgap\relax
+ \dtl@constructticklist\DTLnegextent\DTLbarmax
+ \dtl@unit\dtlbar@yticlist
+ \else
+ \dtl@constructticklistwithgapz
+ \DTLnegextent\DTLbarmax\dtlbar@yticlist\dtlbar@yticgap
+ \fi
+ \fi
+ \ifx\dtlbar@ylabel\relax
+ \else
+ \ifx\dtlbar@yticlabels\relax
+ \@for\dtl@thislabel:=\dtlbar@yticlist\do{%
+ \FPround{\dtl@thislabel}{\dtl@thislabel}
+ {\c@DTLbarroundvar}%
+ \ifDTLverticalbars
+ \settowidth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \else
+ \settoheight{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \edef\@dtl@h{\the\dtl@tmplength}%
+ \settodepth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \addtolength{\dtl@tmplength}{\@dtl@h}%
+ \addtolength{\dtl@tmplength}{\baselineskip}%
+ \fi
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \else
+ \@for\dtl@thislabel:=\dtlbar@yticlabels\do{%
+ \ifDTLverticalbars
+ \settowidth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \else
+ \settoheight{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \edef\@dtl@h{\the\dtl@tmplength}%
+ \settodepth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \addtolength{\dtl@tmplength}{\@dtl@h}%
+ \addtolength{\dtl@tmplength}{\baselineskip}%
+ \fi
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \fi
+ \fi
+ \fi
+% \end{macrocode}
+% Store the width of the bar chart in \cs{DTLbarchartwidth}
+% \begin{macrocode}
+\edef\DTLbarchartwidth{\expandafter\number\csname dtlrows@#3\endcsname}
+% \end{macrocode}
+% Do the bar chart
+% \begin{macrocode}
+\begin{tikzpicture}
+% \end{macrocode}
+% Set unit vectors
+% \begin{macrocode}
+\ifDTLverticalbars
+ \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit sp}}%
+ \pgfsetxvec{\pgfpoint{\DTLbarwidth}{0pt}}%
+\else
+ \pgfsetxvec{\pgfpoint{\dtl@unit sp}{0pt}}%
+ \pgfsetyvec{\pgfpoint{0pt}{\DTLbarwidth}}%
+\fi
+% \end{macrocode}
+% Begin hook
+% \begin{macrocode}
+\DTLbaratbegintikz
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+\def\@dtl@start{0}%
+% \end{macrocode}
+% Iterate through data
+% \begin{macrocode}
+\@sDTLforeach[#1]{#3}{#4}{%
+% \end{macrocode}
+% Store the bar number in \cs{@dtl@bar}
+% \begin{macrocode}
+\expandafter\let\expandafter\@dtl@bar
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname%
+% \end{macrocode}
+% Convert variable to decimal
+% \begin{macrocode}
+\expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@variable}%
+% \end{macrocode}
+% Draw bars
+% \begin{macrocode}
+\begin{scope}
+ \DTLdocurrentbarcolor
+ \ifDTLverticalbars
+ \fill (\@dtl@start,0) -- (\@dtl@start,\dtl@variable)
+ -- (\@dtl@bar,\dtl@variable) -- (\@dtl@bar,0) -- cycle;
+ \else
+ \fill (0,\@dtl@start) -- (\dtl@variable,\@dtl@start)
+ -- (\dtl@variable,\@dtl@bar) -- (0,\@dtl@bar) -- cycle;
+ \fi
+\end{scope}
+% \end{macrocode}
+% Draw outline
+% \begin{macrocode}
+\begin{scope}
+\ifdim\DTLbaroutlinewidth>0pt
+ \expandafter\color\expandafter{\DTLbaroutlinecolor}
+ \ifDTLverticalbars
+ \draw (\@dtl@start,0) -- (\@dtl@start,\dtl@variable)
+ -- (\@dtl@bar,\dtl@variable) -- (\@dtl@bar,0) -- cycle;
+ \else
+ \draw (0,\@dtl@start) -- (\dtl@variable,\@dtl@start)
+ -- (\dtl@variable,\@dtl@bar) -- (0,\@dtl@bar) -- cycle;
+ \fi
+\fi
+\end{scope}
+% \end{macrocode}
+% Draw lower $x$ labels
+% \begin{macrocode}
+\ifDTLverticalbars
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@start.5}{0}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}},
+ \DTLbarXlabelalign
+ }%
+\else
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\@dtl@start.5}}
+ {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}},
+ \DTLbarXlabelalign
+ }%
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplaylowerbarlabel{\dtl@barlabel}}
+% \end{macrocode}
+% Draw upper $x$ labels
+% \begin{macrocode}
+\ifDTLverticalbars
+ \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
+ {
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}
+ }%
+ }{%
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}
+ {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}}
+ }%
+ }
+\else
+ \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
+ {
+ \edef\dtl@textopt{right,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}
+ {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}
+ }%
+ }{%
+ \edef\dtl@textopt{left,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}
+ {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}}
+ }%
+ }
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplayupperbarlabel{\dtl@upperbarlabel}}
+% \end{macrocode}
+% End of loop
+% \begin{macrocode}
+ \edef\@dtl@start{\number\@dtl@bar}%
+}
+% \end{macrocode}
+% Draw $x$ axis
+% \begin{macrocode}
+\ifDTLbarxaxis
+ \ifDTLverticalbars
+ \expandafter\draw\expandafter[\DTLBarXAxisStyle]
+ (0,0) -- (\DTLbarchartwidth,0);
+ \else
+ \expandafter\draw\expandafter[\DTLBarXAxisStyle]
+ (0,0) -- (0,\DTLbarchartwidth);
+ \fi
+\fi
+% \end{macrocode}
+% Draw $y$ axis
+% \begin{macrocode}
+\ifDTLbaryaxis
+ \ifDTLverticalbars
+ \expandafter\draw\expandafter[\DTLBarYAxisStyle]
+ (0,\DTLnegextent) -- (0,\DTLbarmax);
+ \else
+ \expandafter\draw\expandafter[\DTLBarYAxisStyle]
+ (\DTLnegextent,0) -- (\DTLbarmax,0);
+ \fi
+\fi
+% \end{macrocode}
+% Plot $y$ tick marks if required
+% \begin{macrocode}
+\ifx\dtlbar@yticlist\relax
+\else
+ \@for\dtl@thistick:=\dtlbar@yticlist\do{%
+ \ifDTLverticalbars
+ \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}}
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}}
+ {\pgfpoint{-\DTLticklength}{0pt}}}
+ \else
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}}
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}}
+ {\pgfpoint{0pt}{-\DTLticklength}}}
+ \fi
+ \pgfusepath{stroke}
+ \ifx\dtlbar@yticlabels\relax
+ \FPround{\dtl@thislabel}{\dtl@thistick}
+ {\c@DTLbarroundvar}%
+ \else
+ \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest
+ \let\dtlbar@yticlabels=\dtl@rest
+ \fi
+ \ifDTLverticalbars
+ \edef\dtl@textopt{\DTLbarYticklabelalign,%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\dtl@thistick}}
+ {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}},
+ }}%
+ \else
+ \edef\dtl@textopt{\DTLbarYticklabelalign,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@thistick}{0}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}}
+ }}%
+ \fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}
+ }%
+\fi
+% \end{macrocode}
+% Plot the $y$ label if required
+% \begin{macrocode}
+\ifx\dtlbar@ylabel\relax
+\else
+ \addtolength{\dtl@yticlabelwidth}{\baselineskip}%
+ \setlength{\dtl@tmplength}{0.5\DTLbarchartlength}
+ \ifDTLverticalbars
+ \pgftext[bottom,center,at={\pgfpointadd
+ {\pgfpointxy{0}{\DTLnegextent}}%
+ {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}},
+ rotate=90]{%
+ \dtlbar@ylabel}
+ \else
+ \pgftext[bottom,center,at={\pgfpointadd
+ {\pgfpointxy{\DTLnegextent}{0}}%
+ {\pgfpoint{\dtl@tmplength}{-\dtl@yticlabelwidth}}}]{%
+ \dtlbar@ylabel}
+ \fi
+\fi
+% \end{macrocode}
+% Finish bar chart
+% \begin{macrocode}
+\DTLbaratendtikz
+\end{tikzpicture}
+\fi
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmultibarchart}
+%\begin{definition}
+% \cs{DTLmultibarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list}
+%\end{definition}
+% Make a multi-bar chart from data given in data base \meta{db name},
+% where \meta{assign list} is a comma-separated list of
+% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must
+% include the \texttt{variables} key which must be a comma separated
+% list of commands, where each command
+% is included in \meta{assign list}. The optional argument
+% \meta{conditions} is the same as that for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLmultibarchart}[4][\boolean{true}]{%
+{\let\dtlbar@variables=\relax
+\let\DTLbarmax=\relax
+\let\DTLnegextent=\relax
+\disable@keys{databar}{variable,upperbarlabel}%
+\setkeys{databar}{#2}%
+\ifx\dtlbar@variables\relax
+ \PackageError{databar}{\string\DTLmultibarchart\space missing variables setting}{}%
+\else
+% \end{macrocode}
+% Compute the maximum bar height, unless \cs{DTLbarmax} has been
+% set.
+%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of
+%\cs{DTLforeach}}
+% \begin{macrocode}
+ \ifx\DTLbarmax\relax
+ \@sDTLforeach[#1]{#3}{#4}{%
+ \@for\DTLbarvariable:=\dtlbar@variables\do{%
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@barvar}%
+ \ifx\DTLbarmax\relax
+ \let\DTLbarmax=\dtl@barvar
+ \else
+ \let\dtl@old=\DTLbarmax
+ \FPmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}%
+ \fi
+ }%
+ }%
+ \ifx\dtlbar@yticgap\relax
+ \else
+ \let\dtl@thistick=\dtlbar@yticgap%
+ \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{%
+ \FPadd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}%
+ }%
+ \let\DTLbarmax=\dtl@thistick
+ \fi
+ \fi
+% \end{macrocode}
+% Compute the bar depth, unless \cs{DTLnegextent} has been
+% set.
+% \begin{macrocode}
+ \ifx\DTLnegextent\relax
+ \def\DTLnegextent{0}%
+ \@sDTLforeach[#1]{#3}{#4}{%
+ \@for\DTLbarvariable:=\dtlbar@variables\do{%
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@barvar}%
+ \let\dtl@old=\DTLnegextent
+ \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}%
+ }%
+ }%
+ \ifx\dtlbar@yticgap\relax
+ \else
+ \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}{%
+ \edef\dtl@thistick{0}%
+ \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{%
+ \FPsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}%
+ }%
+ \let\DTLnegextent=\dtl@thistick
+ }{}%
+ \fi
+ \fi
+% \end{macrocode}
+% Determine scaling factor
+% \begin{macrocode}
+ \@dtl@tmpcount=\DTLbarchartlength
+ \FPsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}%
+ \FPdiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}%
+% \end{macrocode}
+% Construct $y$ tick list if required
+% \begin{macrocode}
+ \setlength{\dtl@yticlabelwidth}{0pt}%
+ \ifDTLbarytics
+ \ifx\dtlbar@yticlist\relax
+ \ifx\dtlbar@yticgap\relax
+ \dtl@constructticklist\DTLnegextent\DTLbarmax
+ \dtl@unit\dtlbar@yticlist
+ \else
+ \dtl@constructticklistwithgapz
+ \DTLnegextent\DTLbarmax\dtlbar@yticlist\dtlbar@yticgap
+ \fi
+ \fi
+ \ifx\dtlbar@ylabel\relax
+ \else
+ \ifx\dtlbar@yticlabels\relax
+ \@for\dtl@thislabel:=\dtlbar@yticlist\do{%
+ \FPround{\dtl@thislabel}{\dtl@thislabel}
+ {\c@DTLbarroundvar}%
+ \ifDTLverticalbars
+ \settowidth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \else
+ \settoheight{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \edef\@dtl@h{\the\dtl@tmplength}%
+ \settodepth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \addtolength{\dtl@tmplength}{\@dtl@h}%
+ \addtolength{\dtl@tmplength}{\baselineskip}%
+ \fi
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \else
+ \@for\dtl@thislabel:=\dtlbar@yticlabels\do{%
+ \ifDTLverticalbars
+ \settowidth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \else
+ \settoheight{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \edef\@dtl@h{\the\dtl@tmplength}%
+ \settodepth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \addtolength{\dtl@tmplength}{\@dtl@h}%
+ \addtolength{\dtl@tmplength}{\baselineskip}%
+ \fi
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \fi
+ \fi
+ \fi
+% \end{macrocode}
+% Calculate the offset for the lower label and number of labels
+% \begin{macrocode}
+\dtl@xticlabelheight=0pt\relax
+\@dtl@tmpcount=0\relax
+\@for\dtl@thislabel:=\dtl@multibarlabels\do{%
+ \advance\@dtl@tmpcount by 1\relax
+ \settoheight{\dtl@tmplength}{\tikz\expandafter\pgftext\expandafter
+ [\DTLbarXlabelalign]{\DTLdisplaylowerbarlabel{\dtl@thislabel}};}%
+ \edef\@dtl@h{\the\dtl@tmplength}%
+ \settodepth{\dtl@tmplength}{\tikz\expandafter\pgftext\expandafter
+ [\DTLbarXlabelalign]{\DTLdisplaylowerbarlabel{\dtl@thislabel}};}%
+ \addtolength{\dtl@tmplength}{\@dtl@h}%
+ \addtolength{\dtl@tmplength}{\baselineskip}%
+ \ifdim\dtl@tmplength>\dtl@xticlabelheight
+ \setlength{\dtl@xticlabelheight}{\dtl@tmplength}%
+ \fi
+}
+% \end{macrocode}
+% Calculate number of bars per group
+% \begin{macrocode}
+\@dtl@tmpcount=0\relax
+\@for\dtl@this:=\dtlbar@variables\do{%
+ \advance\@dtl@tmpcount by 1\relax
+}%
+\edef\DTLbargroupwidth{\number\@dtl@tmpcount}%
+% \end{macrocode}
+% Compute the total width of the bar chart (in terms of
+% the $x$ unit vector.)
+% \begin{macrocode}
+\edef\dtl@n{\expandafter\number\csname dtlrows@#3\endcsname}
+\FPmul{\dtl@tmpi}{\dtl@n}{\DTLbargroupwidth}
+\FPsub{\dtl@tmpii}{\dtl@n}{1}%
+\FPmul{\dtl@tmpii}{\dtl@tmpii}{\dtlbar@groupgap}%
+\FPadd{\DTLbarchartwidth}{\dtl@tmpi}{\dtl@tmpii}
+% \end{macrocode}
+% Do the bar chart
+% \begin{macrocode}
+\begin{tikzpicture}
+% \end{macrocode}
+% Set unit vectors
+% \begin{macrocode}
+\ifDTLverticalbars
+ \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit sp}}%
+ \pgfsetxvec{\pgfpoint{\DTLbarwidth}{0pt}}%
+\else
+ \pgfsetxvec{\pgfpoint{\dtl@unit sp}{0pt}}%
+ \pgfsetyvec{\pgfpoint{0pt}{\DTLbarwidth}}%
+\fi
+% \end{macrocode}
+% Begin hook
+% \begin{macrocode}
+\DTLbaratbegintikz
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+\def\@dtl@start{0}%
+% \end{macrocode}
+% Iterate through data
+% \begin{macrocode}
+\@sDTLforeach[#1]{#3}{#4}{%
+% \end{macrocode}
+% Store the bar number in \cs{@dtl@bar}
+% \begin{macrocode}
+\@dtl@barcount = 1\relax
+% \end{macrocode}
+% Set the multibar label lists
+% \begin{macrocode}
+\let\dtl@multibar@labels=\dtl@multibarlabels
+\let\dtl@uppermultibar@labels=\dtl@uppermultibarlabels
+% \end{macrocode}
+% Compute mid point over group
+% \begin{macrocode}
+\FPmul{\dtl@multimidpt}{\DTLbargroupwidth}{0.5}%
+\FPadd{\dtl@multimidpt}{\dtl@multimidpt}{\@dtl@start}%
+% \end{macrocode}
+% Iterate through each variable
+% \begin{macrocode}
+\@for\DTLbarvariable:=\dtlbar@variables\do{%
+% \end{macrocode}
+% Set end point
+% \begin{macrocode}
+\FPadd{\@dtl@endpt}{\@dtl@start}{1}%
+% \end{macrocode}
+% Convert variable to decimal
+% \begin{macrocode}
+\expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@variable}%
+% \end{macrocode}
+% Get the current lower label:
+% \begin{macrocode}
+\dtl@chopfirst\dtl@multibar@labels\dtl@thisbarlabel\dtl@rest
+\let\dtl@multibar@labels=\dtl@rest
+% \end{macrocode}
+% Get the current upper label:
+% \begin{macrocode}
+\dtl@chopfirst\dtl@uppermultibar@labels\dtl@thisupperbarlabel\dtl@rest
+\let\dtl@uppermultibar@labels=\dtl@rest
+% \end{macrocode}
+% Draw bars
+% \begin{macrocode}
+\begin{scope}
+ \expandafter\color\expandafter{\DTLgetbarcolor{\@dtl@barcount}}%
+ \ifDTLverticalbars
+ \fill (\@dtl@start,0) -- (\@dtl@start,\dtl@variable)
+ -- (\@dtl@endpt,\dtl@variable) -- (\@dtl@endpt,0) -- cycle;
+ \else
+ \fill (0,\@dtl@start) -- (\dtl@variable,\@dtl@start)
+ -- (\dtl@variable,\@dtl@endpt) -- (0,\@dtl@endpt) -- cycle;
+ \fi
+\end{scope}
+% \end{macrocode}
+% Draw outline
+% \begin{macrocode}
+\begin{scope}
+\ifdim\DTLbaroutlinewidth>0pt
+ \expandafter\color\expandafter{\DTLbaroutlinecolor}
+ \ifDTLverticalbars
+ \draw (\@dtl@start,0) -- (\@dtl@start,\dtl@variable)
+ -- (\@dtl@endpt,\dtl@variable) -- (\@dtl@endpt,0) -- cycle;
+ \else
+ \draw (0,\@dtl@start) -- (\dtl@variable,\@dtl@start)
+ -- (\dtl@variable,\@dtl@endpt) -- (0,\@dtl@endpt) -- cycle;
+ \fi
+\fi
+\end{scope}
+% \end{macrocode}
+% Calculate mid point
+% \begin{macrocode}
+\FPadd{\@dtl@midpt}{\@dtl@start}{0.5}%
+% \end{macrocode}
+% Draw lower $x$ labels
+% \begin{macrocode}
+\ifDTLverticalbars
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@midpt}{0}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}},
+ \DTLbarXlabelalign
+ }%
+\else
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\@dtl@midpt}}
+ {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}},
+ \DTLbarXlabelalign
+ }%
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplaylowermultibarlabel{\dtl@thisbarlabel}}
+% \end{macrocode}
+% Draw upper $x$ labels
+% \begin{macrocode}
+\ifDTLverticalbars
+ \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
+ {
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}
+ }%
+ }{%
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}
+ {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}}
+ }%
+ }
+\else
+ \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
+ {
+ \edef\dtl@textopt{right,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}
+ {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}
+ }%
+ }{%
+ \edef\dtl@textopt{left,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}
+ {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}}
+ }%
+ }
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplayuppermultibarlabel{\dtl@thisupperbarlabel}}
+% \end{macrocode}
+% End of loop increment loop variables
+% \begin{macrocode}
+ \FPadd{\@dtl@start}{\@dtl@start}{1}%
+ \advance\@dtl@barcount by 1\relax
+}%
+% Draw lower group $x$ labels
+% \begin{macrocode}
+\setlength{\dtl@tmplength}{\DTLbarlabeloffset}%
+\addtolength{\dtl@tmplength}{\dtl@xticlabelheight}%
+\ifDTLverticalbars
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@multimidpt}{0}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\dtl@tmplength}}},
+ \DTLbarXlabelalign
+ }%
+\else
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\dtl@multimidpt}}
+ {\noexpand\pgfpoint{-\noexpand\dtl@tmplength}{0pt}}},
+ \DTLbarXlabelalign
+ }%
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplaylowerbarlabel{\dtl@barlabel}}
+% \end{macrocode}
+% Increment starting position by \cs{dtlbar@groupgap}
+% \begin{macrocode}
+ \FPadd{\@dtl@start}{\@dtl@start}{\dtlbar@groupgap}%
+}
+% \end{macrocode}
+% Draw $x$ axis
+% \begin{macrocode}
+\ifDTLbarxaxis
+ \ifDTLverticalbars
+ \expandafter\draw\expandafter[\DTLBarXAxisStyle]
+ (0,0) -- (\DTLbarchartwidth,0);
+ \else
+ \expandafter\draw\expandafter[\DTLBarXAxisStyle]
+ (0,0) -- (0,\DTLbarchartwidth);
+ \fi
+\fi
+% \end{macrocode}
+% Draw $y$ axis
+% \begin{macrocode}
+\ifDTLbaryaxis
+ \ifDTLverticalbars
+ \expandafter\draw\expandafter[\DTLBarYAxisStyle]
+ (0,\DTLnegextent) -- (0,\DTLbarmax);
+ \else
+ \expandafter\draw\expandafter[\DTLBarYAxisStyle]
+ (\DTLnegextent,0) -- (\DTLbarmax,0);
+ \fi
+\fi
+% \end{macrocode}
+% Plot $y$ tick marks if required
+% \begin{macrocode}
+\ifx\dtlbar@yticlist\relax
+\else
+ \@for\dtl@thistick:=\dtlbar@yticlist\do{%
+ \ifDTLverticalbars
+ \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}}
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}}
+ {\pgfpoint{-\DTLticklength}{0pt}}}
+ \else
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}}
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}}
+ {\pgfpoint{0pt}{-\DTLticklength}}}
+ \fi
+ \pgfusepath{stroke}
+ \ifx\dtlbar@yticlabels\relax
+ \FPround{\dtl@thislabel}{\dtl@thistick}
+ {\c@DTLbarroundvar}%
+ \else
+ \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest
+ \let\dtlbar@yticlabels=\dtl@rest
+ \fi
+ \ifDTLverticalbars
+ \edef\dtl@textopt{\DTLbarYticklabelalign,%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\dtl@thistick}}
+ {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}},
+ }}%
+ \else
+ \edef\dtl@textopt{\DTLbarYticklabelalign,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@thistick}{0}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}}
+ }}%
+ \fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}
+ }%
+\fi
+% \end{macrocode}
+% Plot the $y$ label if required
+% \begin{macrocode}
+\ifx\dtlbar@ylabel\relax
+\else
+ \addtolength{\dtl@yticlabelwidth}{\baselineskip}%
+ \setlength{\dtl@tmplength}{0.5\DTLbarchartlength}
+ \ifDTLverticalbars
+ \pgftext[bottom,center,at={\pgfpointadd
+ {\pgfpointxy{0}{\DTLnegextent}}%
+ {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}},
+ rotate=90]{%
+ \dtlbar@ylabel}
+ \else
+ \pgftext[bottom,center,at={\pgfpointadd
+ {\pgfpointxy{\DTLnegextent}{0}}%
+ {\pgfpoint{\dtl@tmplength}{-\dtl@yticlabelwidth}}}]{%
+ \dtlbar@ylabel}
+ \fi
+\fi
+% \end{macrocode}
+% Finish bar chart
+% \begin{macrocode}
+\DTLbaratendtikz
+\end{tikzpicture}
+\fi
+}}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</databar.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*databib.sty>
+% \end{macrocode}
+%\fi
+%\section{databib.sty}
+%\label{sec:src:databib}
+%\subsection{Package Declaration}
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{databib}[2007/08/17 v1.0 (NLCT)]
+% \end{macrocode}
+% Load required packages:
+% \begin{macrocode}
+\RequirePackage{datatool}
+% \end{macrocode}
+%\subsection{Package Options}
+%\begin{macro}{\dtlbib@style}
+%The default bib style is stored in \cs{dtlbib@style}.
+% \begin{macrocode}
+\newcommand*{\dtlbib@style}{plain}
+% \end{macrocode}
+%\end{macro}
+% The \pkgopt[databib]{style} package option sets \cs{dtlbib@style}.
+% \begin{macrocode}
+\define@choicekey{databib.sty}{style}{plain,abbrv,alpha}{%
+\def\dtlbib@style{#1}}
+% \end{macrocode}
+% Process package options:
+% \begin{macrocode}
+\ProcessOptionsX
+% \end{macrocode}
+%\subsection{Loading BBL file}
+%\begin{macro}{\DTLloadbbl}
+%\begin{definition}
+%\cs{DTLloadbib}\oarg{bbl file}\marg{db name}\marg{bib list}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\DTLloadbbl}[3][\jobname.bbl]{%
+\bibliographystyle{databib}%
+\if@filesw
+ \immediate\write\@auxout{\string\bibdata{#3}}%
+\fi
+\DTLnewdb{#2}%
+\edef\DTLBIBdbname{#2}%
+\@input@{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnewbibrow}
+% \cs{DTLnewbibrow} adds a new row to the bibliography database.
+% (\cs{DTLBIBdbname} must be set prior to use to the name
+% of the \sty{datatool} database.)
+% \begin{macrocode}
+\newcommand*{\DTLnewbibrow}{\DTLnewrow{\DTLBIBdbname}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnewbibitem}
+%\begin{definition}
+%\cs{DTLnewbibitem}\marg{key}\marg{value}
+%\end{definition}
+% Adds a new database entry with the given key and value.
+% \begin{macrocode}
+\newcommand*{\DTLnewbibitem}[2]{%
+\DTLnewdbentry{\DTLBIBdbname}{#1}{#2}}
+% \end{macrocode}
+%\end{macro}
+%\subsection{Predefined text}
+%\label{sec:src:bibnames}
+%\begin{macro}{\andname}
+% \begin{macrocode}
+\providecommand*{\andname}{and}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ofname}
+% \begin{macrocode}
+\providecommand*{\ofname}{of}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\inname}
+% \begin{macrocode}
+\providecommand*{\inname}{in}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\etalname}
+% \begin{macrocode}
+\providecommand*{\etalname}{et al.}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\editorname}
+% \begin{macrocode}
+\providecommand*{\editorname}{editor}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\editorsname}
+% \begin{macrocode}
+\providecommand*{\editorsname}{editors}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\volumename}
+% \begin{macrocode}
+\providecommand*{\volumename}{volume}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\numbername}
+% \begin{macrocode}
+\providecommand*{\numbername}{number}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pagesname}
+% \begin{macrocode}
+\providecommand*{\pagesname}{pages}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pagename}
+% \begin{macrocode}
+\providecommand*{\pagename}{page}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\editionname}
+% \begin{macrocode}
+\providecommand*{\editionname}{edition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\techreportname}
+% \begin{macrocode}
+\providecommand*{\techreportname}{Technical report}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\mscthesisname}
+% \begin{macrocode}
+\providecommand*{\mscthesisname}{Master's thesis}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\phdthesisname}
+% \begin{macrocode}
+\providecommand*{\phdthesisname}{PhD thesis}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\subsection{Displaying the bibliography}
+%\label{sec:src:displaybib}
+%\begin{definition}
+%\cs{DTLbibliography}\marg{bib dbname}
+%\end{definition}
+% Displays the bibliography for the database \meta{bib dbname}
+% which must have previously been loaded using
+% \cs{DTLloadbbl}.
+%\begin{macro}{\DTLbibliography}
+% \begin{macrocode}
+\newcommand*{\DTLbibliography}[2][\boolean{true}]{%
+\begin{DTLthebibliography}[#1]{#2}%
+\DTLforeachbibentry[#1]{#2}{%
+\DTLbibitem \DTLformatbibentry \DTLendbibitem
+}%
+\end{DTLthebibliography}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatbibentry}
+%\begin{definition}
+%\cs{DTLformatbibentry}
+%\end{definition}
+% Formats the current bib entry.
+% \begin{macrocode}
+\newcommand*{\DTLformatbibentry}{%
+\@ifundefined{DTLformat\DBIBentrytype}{%
+\PackageError{databib}{Don't know how to format bibliography entries
+of type `\DBIBentrytype'}{}}{%
+\dtl@message{[\DBIBcitekey]}%
+\DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse
+\csname DTLformat\DBIBentrytype\endcsname}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLendbibitem}
+% Hook to add extra information at the end of a bibliography item.
+% This does nothing by default.
+% \begin{macrocode}
+\newcommand*{\DTLendbibitem}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLwidest}
+%Define a length to store the widest bib entry label
+% \begin{macrocode}
+\newlength\dtl@widest
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLcomputewidestbibentry}
+%\begin{definition}
+%\cs{DTLcomputewidestbibentry}\marg{conditions}\marg{db
+%name}\marg{bib label}\marg{cmd}
+%\end{definition}
+%Computes the widest bibliography entry over all entries satisfying
+%\meta{condition} for the database called \meta{db name}, where
+% the bibliography label is formated according to \meta{bib label} and
+% stores the result in \meta{cmd} which must be a command name.
+% \begin{macrocode}
+\newcommand*{\DTLcomputewidestbibentry}[4]{%
+\dtl@widest=0pt\relax
+\let#4=\@empty
+\DTLforeachbibentry[#1]{#2}{%
+\settowidth{\dtl@tmplength}{#3}%
+\ifdim\dtl@tmplength>\dtl@widest\relax
+ \dtl@widest=\dtl@tmplength
+ \protected@edef#4{#3}%
+\fi
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLforeachbibentry}
+%\begin{definition}
+%\cs{DTLforeachbibentry}\oarg{condition}\marg{db name}\marg{text}
+%\end{definition}
+%\begin{definition}
+%\cs{DTLforeachbibentry*}\oarg{condition}\marg{db name}\marg{text}
+%\end{definition}
+% Iterates through the database called \meta{db name} and does
+% \meta{text} if \meta{condition} is met. As with
+% \cs{DTLforeach}, the starred version is read only.
+% \begin{macrocode}
+\newcommand*{\DTLforeachbibentry}{%
+\@ifstar\@DTLforeachbibentry\@DTLforeachbibentry}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@DTLforeachbibentry}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLforeachbibentry}[3][\boolean{true}]{%
+\edef\DBIBname{#2}\setcounter{DTLbibrow}{0}%
+\@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype
+=EntryType}{\dtl@gathervalues{#2}{\@dtl@currentrow}%
+\ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@sDTLforeachbibentry}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLforeachbibentry}[3][\boolean{true}]{%
+\edef\DBIBname{#2}\setcounter{DTLbibrow}{0}%
+\@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype
+=EntryType}{\dtl@gathervalues{#2}{\@dtl@currentrow}%
+\ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}}}
+% \end{macrocode}
+%\end{macro}
+%
+%The counter \counterfmt{DTLbibrow} keeps track of the current
+%row in the body of \cs{DTLforeachbibentry}. (You can't rely on
+%\counterfmt{DTLrowi}, \counterfmt{DTLrowii} and
+% \counterfmt{DTLrowiii}, as \cs{DTLforeachbibentry} pass the
+% conditions to the optional argument of \cs{DTLforeach}, but
+% instead uses \cs{ifthenelse}, which means that \counterfmt{DTLrowi}
+% etc will be incremented, even when the given condition is not met.)
+% \begin{macrocode}
+\newcounter{DTLbibrow}
+% \end{macrocode}
+% Keep \sty{hyperref} happy:
+% \begin{macrocode}
+\def\theHDTLbibrow{\theHDTLrow.bib.\arabic{DTLbibrow}}%
+% \end{macrocode}
+%
+%\begin{macro}{\DTLbibfield}
+%\begin{definition}
+%\cs{DTLbibfield}\marg{field name}
+%\end{definition}
+% Gets the value assigned to the field \meta{field name} for
+% the current row of \cs{DTLforeachbibentry}. (Doesn't check if
+% the field exists, or if it is being used within
+% \cs{DTLforeachbibentry}.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfield}[1]{\csname @dtl@key@#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifbibfieldexists}
+%\begin{definition}
+%\cs{DTLifbibfieldexists}\marg{field name}\marg{true part}\marg{false
+%part}
+%\end{definition}
+%Determines whether the given field name exists for the current
+% row of \cs{DTLforeachbibentry}.
+% \begin{macrocode}
+\newcommand*{\DTLifbibfieldexists}[3]{%
+\@ifundefined{@dtl@key@#1}{#3}{%
+\expandafter\DTLifnull\csname @dtl@key@#1\endcsname
+{#3}{#2}}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifanybibfieldexists}
+%\begin{definition}
+%\cs{DTLifanybibfieldexists}\marg{list of field name}\marg{true part}\marg{false
+%part}
+%\end{definition}
+% Determines whether any of the listed fields exist for the current
+% row of \cs{DTLforeachbibentry}.
+% \begin{macrocode}
+\newcommand*{\DTLifanybibfieldexists}[3]{%
+\@for\dtl@thisfield:=#1\do{%
+\@ifundefined{@dtl@key@\dtl@thisfield}{}{%
+\expandafter\DTLifnull\csname @dtl@key@\dtl@thisfield\endcsname
+{}{%
+\@endfortrue}}}%
+\if@endfor
+ #2%
+\else
+ #3%
+\fi
+\@endforfalse
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLperiod}
+% The conditional \cs{ifDTLperiod} is used to keep track of any
+% abbreviations ending with a period, this is to ensure that
+% abbreviations aren't followed by a full stop if they already
+% have a full stop terminating the abbreviation.
+% \begin{macrocode}
+\newif\ifDTLperiod
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLcheckendsperiod}
+%\begin{definition}
+%\cs{DTLcheckendperiod}\marg{string}
+%\end{definition}
+% Checks if \meta{string} ends with a full stop. This sets
+% \cs{ifDTLperiod}.
+% \begin{macrocode}
+\newcommand*{\DTLcheckendsperiod}[1]{%
+\dtl@checkendsperiod#1\@nil\relax}
+% \end{macrocode}
+% \begin{macrocode}
+\def\dtl@checkendsperiod#1#2{%
+\def\@dtl@argi{#1}\def\@dtl@argii{#2}%
+\def\@dtl@period{.}%
+\ifx\@dtl@argi\@nnil
+ \global\DTLperiodfalse
+ \let\@dtl@donext=\relax
+\else
+ \ifx\@dtl@argii\@nnil
+ \ifx\@dtl@argi\@dtl@period
+ \global\DTLperiodtrue
+ \else
+ \global\DTLperiodfalse
+ \fi
+ \let\@dtl@donext=\@gobble
+ \else
+ \let\@dtl@donext=\dtl@checkendsperiod
+ \fi
+\fi
+\@dtl@donext{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLcheckbibfieldendsperiod}
+%\begin{definition}
+%\cs{DTLcheckbibfieldendperiod}\marg{label}
+%\end{definition}
+% Checks if the bib field \meta{label} ends with a full stop.
+% This sets \cs{ifDTLperiod}.
+% \begin{macrocode}
+\newcommand*{\DTLcheckbibfieldendsperiod}[1]{%
+\protected@edef\@dtl@tmp{\DTLbibfield{#1}}%
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLmidsentence}
+%\begin{definition}
+%\cs{ifDTLmidsentence}
+%\end{definition}
+% Determine whether we are in the middle
+% of a sentence.
+% \begin{macrocode}
+\newif\ifDTLmidsentence
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLstartsentence}
+%\begin{definition}
+%\cs{ifDTLstartsentence}
+%\end{definition}
+% Determine whether we are at the start
+% of a sentence.
+% \begin{macrocode}
+\newif\ifDTLstartsentence
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddperiod}
+%\begin{definition}
+%\cs{DTLaddperiod}
+%\end{definition}
+%Adds a full stop and sets \cs{DTLmidsentencefalse},
+%\cs{DTLstartsentencetrue} and
+%\cs{DTLperiodfalse}.
+% \begin{macrocode}
+\newcommand*{\DTLaddperiod}{\DTLmidsentencefalse\DTLperiodfalse
+\DTLstartsentencetrue
+\ifDTLperiod\else.\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddcomma}
+%\begin{definition}
+%\cs{DTLaddcomma}
+%\end{definition}
+%Adds a comma and sets \cs{DTLmidsentencetrue}, \cs{DTLperiodfalse}
+%and \cs{DTLstartsentencefalse}
+% \begin{macrocode}
+\newcommand*{\DTLaddcomma}{, \DTLmidsentencetrue
+\DTLperiodfalse\DTLstartsentencefalse}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLstartsentencespace}
+%Adds a space if at the start of the sentence, otherwise does
+% nothing. (The space between sentences is added this way, rather
+% than in \cs{DTLaddperiod} otherwise spurious extra space can
+% occur at the end of the bib item. The spacefactor needs to be
+% set manually, because there's stuff in the way of the previous
+% sentence's full stop and this space which confuses the inter
+% sentence spacing (and, of course, the previous sentence could
+% have ended with a capital letter.)
+% \begin{macrocode}
+\newcommand*{\DTLstartsentencespace}{%
+\ifDTLstartsentence\spacefactor=\sfcode`\.\relax\space
+\fi\DTLstartsentencefalse}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtwoand}
+% In a list of only two author (or editor) names, the text between the
+% two names is given by \cs{DTLtwoand}:
+% \begin{macrocode}
+\newcommand*{\DTLtwoand}{\ \andname\ }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLandlast}
+% In a list of author (or editor) names, the text between the
+% penultimate and last name is given by \cs{DTLandlast}:
+% \begin{macrocode}
+\newcommand*{\DTLandlast}{, \andname\ }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLandnotlast}
+% In a list of author (or editor) names, the text between the
+% names (except the penultimate and last name) is given by
+% \cs{DTLandnotlast}:
+% \begin{macrocode}
+\newcommand*{\DTLandnotlast}{, }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@authorcount}
+% Define a count register to keep track of the number of authors:
+% \begin{macrocode}
+\newcount\@dtl@authorcount
+% \end{macrocode}
+%\end{macro}
+% The counter \counterfmt{DTLmaxauthors} indicates the maximum number of
+% author names to display, if there are more than that number,
+% \cs{etalname} is used.
+% \begin{macrocode}
+\newcounter{DTLmaxauthors}
+\setcounter{DTLmaxauthors}{10}
+% \end{macrocode}
+%\begin{macro}{\DTLformatauthorlist}
+% Format a list of author names (the list is stored in
+% \cs{@dtl@key@Author}):
+% \begin{macrocode}
+\newcommand*{\DTLformatauthorlist}{%
+\DTLifbibfieldexists{Author}{%
+\DTLstartsentencespace
+\@dtl@authorcount=0\relax
+\@for\@dtl@author:=\@dtl@key@Author\do{%
+\advance\@dtl@authorcount by 1\relax}%
+\@dtl@tmpcount=0\relax
+\ifnum\@dtl@authorcount>\c@DTLmaxauthors
+{%
+ \@for\@dtl@author:=\@dtl@key@Author\do{%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount=1\relax
+ \expandafter\DTLformatauthor\@dtl@author
+ \else
+ \ifnum\@dtl@tmpcount>\c@DTLmaxauthors
+ \DTLandnotlast \etalname
+ \expandafter\DTLcheckendsperiod\expandafter{\etalname}%
+ \@endfortrue
+ \else
+ \DTLandnotlast \expandafter\DTLformatauthor\@dtl@author
+ \fi
+ \fi
+ }%
+}%
+\else
+ \@for\@dtl@author:=\@dtl@key@Author\do{%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount=1\relax
+ \expandafter\DTLformatauthor\@dtl@author
+ \else
+ \ifnum\@dtl@tmpcount=\@dtl@authorcount
+ \ifnum\@dtl@authorcount=2\relax
+ \DTLtwoand
+ \else
+ \DTLandlast
+ \fi
+ \expandafter\DTLformatauthor\@dtl@author
+ \else
+ \DTLandnotlast \expandafter\DTLformatauthor\@dtl@author
+ \fi
+ \fi
+ }%
+\fi
+}{}%
+}
+% \end{macrocode}
+%\end{macro}
+% The counter \counterfmt{DTLmaxeditors} indicates the maximum number of
+% editor names to display, if there are more than that number,
+% \cs{etalname} is used.
+% \begin{macrocode}
+\newcounter{DTLmaxeditors}
+\setcounter{DTLmaxeditors}{10}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLformateditorlist}
+% Format a list of editor names (the list is stored in
+% \cs{@dtl@key@Editor}):
+% \begin{macrocode}
+\newcommand*{\DTLformateditorlist}{%
+\DTLifbibfieldexists{Editor}{%
+\DTLstartsentencespace
+\@dtl@authorcount=0\relax
+\@for\@dtl@author:=\@dtl@key@Editor\do{%
+\advance\@dtl@authorcount by 1\relax}%
+\@dtl@tmpcount=0\relax
+\ifnum\@dtl@authorcount>\c@DTLmaxeditors
+{%
+ \@for\@dtl@author:=\@dtl@key@Editor\do{%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount=1\relax
+ \expandafter\DTLformateditor\@dtl@author
+ \else
+ \ifnum\@dtl@tmpcount>\c@DTLmaxeditors
+ \DTLandnotlast \etalname
+ \expandafter\DTLcheckendsperiod\expandafter{\etalname}%
+ \@endfortrue
+ \else
+ \DTLandnotlast \expandafter\DTLformateditor\@dtl@author
+ \fi
+ \fi
+ }%
+}%
+\else
+\@for\@dtl@author:=\@dtl@key@Editor\do{%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount=1\relax
+ \expandafter\DTLformateditor\@dtl@author
+ \else
+ \ifnum\@dtl@tmpcount=\@dtl@authorcount
+ \ifnum\@dtl@authorcount=2\relax
+ \DTLtwoand
+ \else
+ \DTLandlast
+ \fi
+ \expandafter\DTLformateditor\@dtl@author
+ \else
+ \DTLandnotlast \expandafter\DTLformateditor\@dtl@author
+ \fi
+ \fi
+ }%
+\fi
+,
+\ifnum\@dtl@authorcount=1\relax
+ \editorname
+ \expandafter\DTLcheckendsperiod\expandafter{\editorname}%
+\else
+ \editorsname
+ \expandafter\DTLcheckendsperiod\expandafter{\editorsname}%
+\fi
+}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatsurnameonly}
+%\begin{definition}
+%\cs{DTLformatsurnameonly}\marg{von part}\marg{surname}\marg{jr
+%part}\marg{forenames}
+%\end{definition}
+% This is used when only the surname should be displayed. (The
+% final argument, \meta{forenames}, is ignored.)
+% \begin{macrocode}
+\newcommand*{\DTLformatsurnameonly}[4]{%
+\DTLstartsentencespace
+\def\@dtl@tmp{#1}%
+\ifx\@dtl@tmp\@empty\else#1~\fi
+#2%
+\def\@dtl@tmp{#3}%
+\ifx\@dtl@tmp\@empty
+ \DTLcheckendsperiod{#2}%
+\else
+ , #3%
+ \DTLcheckendsperiod{#3}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatforenames}
+%\begin{definition}
+%\cs{DTLformatforenames}\marg{forenames}
+%\end{definition}
+% The format of an author/editor's forenames. If the forenames
+% occur at the start of sentence, a new sentence space is added.
+% The argument is checked to determine whether it ends with a
+% full stop (sometimes the forenames may include initials.)
+% \begin{macrocode}
+\newcommand*{\DTLformatforenames}[1]{%
+\DTLstartsentencespace
+#1%
+\DTLcheckendsperiod{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatabbrvforenames}
+%\begin{definition}
+%\cs{DTLformatabbrvforenames}\marg{forenames}
+%\end{definition}
+% The format of an author/editor's abbreviated forenames. The initials
+% may or may not end in a full stop depending on the commands
+% governing the format of \cs{DTLstoreinitials}, so the initials
+% need to be check using \cs{DTLcheckendsperiod}.
+% \begin{macrocode}
+\newcommand*{\DTLformatabbrvforenames}[1]{%
+\DTLstartsentencespace
+\DTLstoreinitials{#1}{\@dtl@tmp}\@dtl@tmp
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatvon}
+%\begin{definition}
+%\cs{DTLformatvon}\marg{von part}
+%\end{definition}
+% The format of the ``von'' part. This does nothing if the argument
+% is empty, otherwise it does the argument followed by a
+% non-breakable space.
+% \begin{macrocode}
+\newcommand*{\DTLformatvon}[1]{%
+\DTLstartsentencespace
+\def\@dtl@tmp{#1}%
+\ifx\@dtl@tmp\@empty
+\else
+ #1~%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatsurname}
+%\begin{definition}
+%\cs{DTLformatsurname}\marg{surname}
+%\end{definition}
+% The format of an author/editor's surname.
+% \begin{macrocode}
+\newcommand*{\DTLformatsurname}[1]{%
+\DTLstartsentencespace
+#1\DTLcheckendsperiod{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatjr}
+%\begin{definition}
+%\cs{DTLformatjr}\marg{jr part}
+%\end{definition}
+% The format of the ``jr'' part. This does nothing if the
+% argument is empty.
+% \begin{macrocode}
+\newcommand*{\DTLformatjr}[1]{%
+\DTLstartsentencespace
+\def\@dtl@tmp{#1}%
+\ifx\@dtl@tmp\@empty
+\else
+ , #1\DTLcheckendsperiod{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatcrossrefeditor}
+% Format cross reference editors:
+% \begin{macrocode}
+\newcommand*{\DTLformatcrossrefeditor}{%
+\DTLifbibfieldexists{Editor}{%
+\DTLstartsentencespace
+\@dtl@authorcount=0\relax
+\@for\@dtl@author:=\@dtl@key@Editor\do{%
+\advance\@dtl@authorcount by 1\relax}%
+{\@dtl@tmpcount=0\relax
+\@for\@dtl@author:=\@dtl@key@Editor\do{%
+\ifnum\@dtl@authorcount=1\relax
+ \expandafter\DTLformatsurnameonly\@dtl@author
+\else
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount=1\relax
+ \expandafter\DTLformatsurnameonly\@dtl@author
+ \else
+ \ifnum\@dtl@authorcount=2\relax
+ \ \andname\ \expandafter\DTLformatsurnameonly\@dtl@author
+ \else
+ \ \etalname
+ \expandafter\DTLcheckendsperiod\expandafter{\etalname}
+ \fi
+ \@endfortrue
+ \fi
+\fi
+}}%
+}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatvolnumpages}
+% Format volume, number and pages (of an article).
+% \begin{macrocode}
+\newcommand*{\DTLformatvolnumpages}{%
+\DTLifbibfieldexists{Volume}{%
+\DTLstartsentencespace
+\DTLbibfield{Volume}\DTLperiodfalse}{}%
+\DTLifbibfieldexists{Number}{%
+\DTLstartsentencespace
+(\DTLbibfield{Number})\DTLperiodfalse}{}%
+\DTLifbibfieldexists{Pages}{%
+\DTLifanybibfieldexists{Volume,Number}{:}{%
+\DTLstartsentencespace
+\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}%
+\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~}%
+\DTLbibfield{Pages}\DTLperiodfalse}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatbvolume}
+% Format book volume.
+% \begin{macrocode}
+\newcommand*{\DTLformatbvolume}{%
+\DTLifbibfieldexists{Volume}{%
+\ifDTLmidsentence
+ \volumename
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\volumename
+\fi
+~\DTLbibfield{Volume}%
+\DTLifbibfieldexists{Series}{\ \ofname\
+{\em\DTLbibfield{Series}}\DTLcheckbibfieldendsperiod{Series}}{%
+\DTLcheckbibfieldendsperiod{Volume}}%
+}{}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatchapterpages}
+% Format chapter and pages:
+% \begin{macrocode}
+\newcommand*{\DTLformatchapterpages}{%
+\DTLifbibfieldexists{Chapter}{%
+\DTLifbibfieldexists{Type}{%
+\DTLstartsentencespace
+\DTLbibfield{Type}}{%
+\DTLstartsentencespace
+\chaptername}~\DTLbibfield{Chapter}%
+\DTLifbibfieldexists{Pages}{\DTLaddcomma}{%
+\DTLcheckbibfieldendsperiod{Chapter}}}{}%
+\DTLstartsentencespace
+\DTLformatpages}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatpages}
+% Format pages:
+% \begin{macrocode}
+\newcommand*{\DTLformatpages}{%
+\DTLifbibfieldexists{Pages}{%
+\DTLstartsentencespace
+\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}%
+\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~%
+\DTLbibfield{Pages}\DTLcheckbibfieldendsperiod{Pages}}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatnumberseries}
+% Format number and series (of book)
+% \begin{macrocode}
+\newcommand*{\DTLformatnumberseries}{%
+\DTLifbibfieldexists{Volume}{}{%
+\DTLifbibfieldexists{Number}{%
+\ifDTLmidsentence
+ \numbername
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\numbername
+\fi~\DTLbibfield{Number}%
+\DTLifbibfieldexists{Series}{\ \inname\ \DTLbibfield{Series}%
+\DTLcheckbibfieldendsperiod{Series}}{%
+\DTLcheckbibfieldendsperiod{Number}}%
+}{%
+\DTLifbibfieldexists{Series}{%
+\DTLstartsentencespace
+\DTLbibfield{Series}%
+\DTLcheckbibfieldendsperiod{Series}}{}}%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatbookcrossref}
+% Format a book cross reference.
+% \begin{macrocode}
+\newcommand*{\DTLformatbookcrossref}{%
+\DTLifbibfieldexists{Volume}{%
+\ifDTLmidsentence
+ \volumename
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\volumename
+\fi
+~\DTLbibfield{Volume}\ \ofname\
+}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi\ }%
+\DTLifbibfieldexists{Editor}{\DTLformatcrossrefeditor}{%
+\DTLifbibfieldexists{Key}{%
+\DTLbibfield{Key}}{%
+\DTLifbibfieldexists{Series}{%
+{\em\DTLbibfield{Series}}}{}%
+}%
+}%
+\edef\@dtl@tmp{\DTLbibfield{CrossRef}}%
+~\cite{\@dtl@tmp}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatincollproccrossref}
+% Format `incollections' cross reference.
+% \begin{macrocode}
+\newcommand*{\DTLformatincollproccrossref}{%
+\DTLifbibfieldexists{Editor}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi\
+\DTLformatcrossrefeditor
+}{%
+\DTLifbibfieldexists{Key}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi\ \DTLbibfield{Key}%
+}{%
+\DTLifbibfieldexists{BookTitle}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi\ {\em\DTLbibfield{BookTitle}}}{}%
+}}%
+\edef\@dtl@tmp{\DTLbibfield{CrossRef}}%
+~\cite{\@dtl@tmp}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatinedbooktitle}
+%Format editor and booktitle:
+% \begin{macrocode}
+\newcommand*{\DTLformatinedbooktitle}{%
+\DTLifbibfieldexists{BookTitle}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi\
+\DTLifbibfieldexists{Editor}{%
+\DTLformateditorlist\DTLaddcomma {\em\DTLbibfield{BookTitle}}%
+\DTLcheckbibfieldendsperiod{BookTitle}%
+}{{\em\DTLbibfield{BookTitle}}%
+\DTLcheckbibfieldendsperiod{BookTitle}%
+}}{}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatdate}
+%Format date.
+% \begin{macrocode}
+\newcommand*{\DTLformatdate}{%
+\DTLifbibfieldexists{Year}{%
+\DTLifbibfieldexists{Month}{%
+\protected@edef\@dtl@tmp{\DTLbibfield{Month}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\@dtl@tmp
+\fi\
+\DTLmidsentencefalse}{}%
+\DTLstartsentencespace
+\DTLbibfield{Year}}{%
+\DTLifbibfieldexists{Month}{%
+\protected@edef\@dtl@tmp{\DTLbibfield{Month}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\@dtl@tmp
+\fi
+\DTLcheckbibfieldendsperiod{Month}%
+}{}}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatarticlecrossref}
+% Format article cross reference.
+% \begin{macrocode}
+\newcommand*{\DTLformatarticlecrossref}{%
+\DTLifbibfieldexists{Key}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi
+\ {\em\DTLbibfield{Key}}}{%
+\DTLifbibfieldexists{Journal}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi
+\ {\em\DTLbibfield{Journal}}}{}}%
+\edef\@dtl@tmp{\DTLbibfield{CrossRef}}%
+~\cite{\@dtl@tmp}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsubsection{ifthen conditionals}
+% The conditionals defined in this section may be used in the
+% optional argument of \cs{DTLforeachbib}. They may also be
+% used in the first argument of \cs{ifthenelse}, but only if the
+% command occurs within the body of \cs{DTLforeachbib}.
+%
+%\begin{macro}{\DTLbibfieldexists}
+%\begin{definition}
+%\cs{DTLbibfieldexists}\marg{field label}
+%\end{definition}
+% Checks if named bib field exists for current entry
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldexists}[1]{%
+\TE@throw\noexpand\dtl@testbibfieldexists{#1}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldexists}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldexists}[1]{%
+\DTLifbibfieldexists{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldiseq}
+%\begin{definition}
+%\cs{DTLbibfieldiseq}\marg{field label}\marg{value}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% is equal to \meta{value}. (Uses \cs{dtlcompare} to determine if
+% the values are equal. If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldiseq}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldiseq{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldiseq}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldiseq}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\toks@\expandafter{\@dtl@tmp}%
+\@dtl@toks{#2}%
+\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}%
+{\the\toks@}{\the\@dtl@toks}}%
+\@dtl@docompare
+\ifnum\@dtl@tmpcount=0\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}{%
+\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldislt}
+%\begin{definition}
+%\cs{DTLbibfieldislt}\marg{field label}\marg{value}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% is less than \meta{value}. (If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldislt}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldislt{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldislt}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldislt}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\toks@\expandafter{\@dtl@tmp}%
+\@dtl@toks{#2}%
+\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}%
+{\the\toks@}{\the\@dtl@toks}}%
+\@dtl@docompare
+\ifnum\@dtl@tmpcount=-1\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}{%
+\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldisle}
+%\begin{definition}
+%\cs{DTLbibfieldisle}\marg{field label}\marg{value}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% is less than or equal to \meta{value}.
+% (If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldisle}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldisle{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldisle}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldisle}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\toks@\expandafter{\@dtl@tmp}%
+\@dtl@toks{#2}%
+\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}%
+{\the\toks@}{\the\@dtl@toks}}%
+\@dtl@docompare
+\ifnum\@dtl@tmpcount<1\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}{%
+\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldisgt}
+%\begin{definition}
+%\cs{DTLbibfieldisgt}\marg{field label}\marg{value}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% is greater than \meta{value}. (If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldisgt}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldisgt{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldisgt}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldisgt}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\toks@\expandafter{\@dtl@tmp}%
+\@dtl@toks{#2}%
+\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}%
+{\the\toks@}{\the\@dtl@toks}}%
+\@dtl@docompare
+\ifnum\@dtl@tmpcount=1\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}{%
+\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldisge}
+%\begin{definition}
+%\cs{DTLbibfieldisge}\marg{field label}\marg{value}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% is less than or equal to \meta{value}.
+% (If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldisge}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldisge{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldisge}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldisge}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\toks@\expandafter{\@dtl@tmp}%
+\@dtl@toks{#2}%
+\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}%
+{\the\toks@}{\the\@dtl@toks}}%
+\@dtl@docompare
+\ifnum\@dtl@tmpcount>-1\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}{%
+\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldcontains}
+%\begin{definition}
+%\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% contains \meta{sub string}.
+% (If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldcontains}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldcontains{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldcontains}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldcontains}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\dtl@testifsubstring\expandafter{\@dtl@tmp}{#2}%
+}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Bibliography Style Macros}
+%\label{sec:src:bibstyle}
+% The macros defined in this section should be redefined by
+% bibliography styles.
+%
+%\begin{environment}{DTLthebibliography}
+% How to format the entire bibliography:
+% \begin{macrocode}
+\newenvironment{DTLthebibliography}[2][\boolean{true}]{%
+\@dtl@tmpcount=0\relax
+\@sDTLforeach[#1]{#2}{}{\advance\@dtl@tmpcount by 1\relax}%
+\begin{thebibliography}{\number\@dtl@tmpcount}
+}{\end{thebibliography}}
+% \end{macrocode}
+%\end{environment}
+%\begin{macro}{\DTLmonthname}
+% The monthname style. The argument must be a number from~1
+% to~12. By default, uses \cs{dtl@monthname}.
+% \begin{macrocode}
+\newcommand*{\DTLmonthname}[1]{%
+\dtl@monthname{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@monthname}
+% Full month names:
+% \begin{macrocode}
+\newcommand*{\dtl@monthname}[1]{%
+\ifcase#1%
+\or January%
+\or February%
+\or March%
+\or April%
+\or May%
+\or June%
+\or July%
+\or August%
+\or September%
+\or October%
+\or November%
+\or December%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@abbrvmonthname}
+% Abbreviated months:
+% \begin{macrocode}
+\newcommand*{\dtl@abbrvmonthname}[1]{%
+\ifcase#1%
+\or Jan.%
+\or Feb.%
+\or Mar.%
+\or Apr.%
+\or May%
+\or June%
+\or July%
+\or Aug.%
+\or Sept.%
+\or Oct.%
+\or Nov.%
+\or Dec.%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibitem}
+% Define how to start a new bibitem:
+% \begin{macrocode}
+\newcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatauthor}
+%\begin{definition}
+%\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{junior
+%part}\marg{forenames}
+%\end{definition}
+% The format of an author's name.
+% \begin{macrocode}
+\newcommand*{\DTLformatauthor}[4]{%
+\DTLformatforenames{#4}
+\DTLformatvon{#1}%
+\DTLformatsurname{#2}%
+\DTLformatjr{#3}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformateditor}
+% The format of an editor's name.
+% \begin{macrocode}
+\newcommand*{\DTLformateditor}[4]{%
+\DTLformatforenames{#4}
+\DTLformatvon{#1}%
+\DTLformatsurname{#2}%
+\DTLformatjr{#3}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatedition}
+% The format of an edition:
+% \begin{macrocode}
+\newcommand*{\DTLformatedition}[1]{#1 \editionname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatarticle}
+% The format of an article:
+% \begin{macrocode}
+\newcommand{\DTLformatarticle}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatbook}
+% The format of a book:
+% \begin{macrocode}
+\newcommand{\DTLformatbook}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatbooklet}
+% The format of a booklet:
+% \begin{macrocode}
+\newcommand{\DTLformatbooklet}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatinbook}
+% The format of an ``inbook'' type:
+% \begin{macrocode}
+\newcommand{\DTLformatinbook}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatincollection}
+% The format of an ``incollection'' type:
+% \begin{macrocode}
+\newcommand{\DTLformatincollection}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatinproceedings}
+% The format of an ``inproceedings'' type:
+% \begin{macrocode}
+\newcommand{\DTLformatinproceedings}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatmanual}
+% The format of a manual:
+% \begin{macrocode}
+\newcommand{\DTLformatmanual}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatmastersthesis}
+% The format of a master's thesis:
+% \begin{macrocode}
+\newcommand{\DTLformatmastersthesis}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatmisc}
+% The format of a miscellaneous entry:
+% \begin{macrocode}
+\newcommand{\DTLformatmisc}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatphdthesis}
+% The format of a Ph.D. thesis:
+% \begin{macrocode}
+\newcommand{\DTLformatphdthesis}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatproceedings}
+% The format of a proceedings:
+% \begin{macrocode}
+\newcommand{\DTLformatproceedings}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformattechreport}
+% The format of a technical report:
+% \begin{macrocode}
+\newcommand{\DTLformattechreport}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatunpublished}
+% The format of an unpublished work:
+% \begin{macrocode}
+\newcommand{\DTLformatunpublished}{}
+% \end{macrocode}
+%\end{macro}
+%
+% Predefined names (these correspond to the standard \BibTeX\
+% predefined strings of the same name without the leading
+% \cs{DTL}):
+%\begin{macro}{\DTLacmcs}
+% \begin{macrocode}
+\newcommand*{\DTLacmcs}{ACM Computing Surveys}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLacta}
+% \begin{macrocode}
+\newcommand*{\DTLacta}{Acta Informatica}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLcacm}
+% \begin{macrocode}
+\newcommand*{\DTLcacm}{Communications of the ACM}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLibmjrd}
+% \begin{macrocode}
+\newcommand*{\DTLibmjrd}{IBM Journal of Research and Development}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLibmsj}
+% \begin{macrocode}
+\newcommand*{\DTLibmsj}{IBM Systems Journal}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLieeese}
+% \begin{macrocode}
+\newcommand*{\DTLieeese}{IEEE Transactions on Software Engineering}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLieeetc}
+% \begin{macrocode}
+\newcommand*{\DTLieeetc}{IEEE Transactions on Computers}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLieeetcad}
+% \begin{macrocode}
+\newcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design
+of Integrated Circuits}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLipl}
+% \begin{macrocode}
+\newcommand*{\DTLipl}{Information Processing Letters}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLjacm}
+% \begin{macrocode}
+\newcommand*{\DTLjacm}{Journal of the ACM}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLjcss}
+% \begin{macrocode}
+\newcommand*{\DTLjcss}{Journal of Computer and System Sciences}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLscp}
+% \begin{macrocode}
+\newcommand*{\DTLscp}{Science of Computer Programming}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsicomp}
+% \begin{macrocode}
+\newcommand*{\DTLsicomp}{SIAM Journal on Computing}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtocs}
+% \begin{macrocode}
+\newcommand*{\DTLtocs}{ACM Transactions on Computer Systems}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtods}
+% \begin{macrocode}
+\newcommand*{\DTLtods}{ACM Transactions on Database Systems}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtog}
+% \begin{macrocode}
+\newcommand*{\DTLtog}{ACM Transactions on Graphics}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtoms}
+% \begin{macrocode}
+\newcommand*{\DTLtoms}{ACM Transactions on Mathematical Software}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtoois}
+% \begin{macrocode}
+\newcommand*{\DTLtoois}{ACM Transactions on Office Information
+Systems}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtoplas}
+% \begin{macrocode}
+\newcommand*{\DTLtoplas}{ACM Transactions on Programming Languages
+and Systems}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtcs}
+% \begin{macrocode}
+\newcommand*{\DTLtcs}{Theoretical Computer Science}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Bibliography Styles}
+% Each bibliography style is set by the command
+% \cs{dtlbst@}\meta{style}, where \meta{style} is the name
+% of the bibliography style.
+%
+%\begin{macro}{\dtlbst@plain}
+% The `plain' style:
+% \begin{macrocode}
+\newcommand{\dtlbst@plain}{%
+% \end{macrocode}
+% Set how to format the entire bibliography:
+% \begin{macrocode}
+\renewenvironment{DTLthebibliography}[2][\boolean{true}]{%
+\@dtl@tmpcount=0\relax
+\@sDTLforeach[##1]{##2}{}{\advance\@dtl@tmpcount by 1\relax}%
+\begin{thebibliography}{\number\@dtl@tmpcount}%
+}{\end{thebibliography}}%
+% \end{macrocode}
+% Set how to start the bibliography entry:
+% \begin{macrocode}
+\renewcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}%
+% \end{macrocode}
+% Sets the author name format.
+% \begin{macrocode}
+\renewcommand*{\DTLformatauthor}[4]{%
+\DTLformatforenames{##4}
+\DTLformatvon{##1}%
+\DTLformatsurname{##2}%
+\DTLformatjr{##3}}
+% \end{macrocode}
+% Sets the editor name format.
+% \begin{macrocode}
+\renewcommand*{\DTLformateditor}[4]{%
+\DTLformatforenames{##4}
+\DTLformatvon{##1}%
+\DTLformatsurname{##2}%
+\DTLformatjr{##3}}
+% \end{macrocode}
+% Sets the edition format.
+% \begin{macrocode}
+\renewcommand*{\DTLformatedition}[1]{##1 \editionname}%
+% \end{macrocode}
+% Sets the monthname format.
+% \begin{macrocode}
+\let\DTLmonthname\dtl@monthname
+% \end{macrocode}
+% Sets other predefined names:
+% \begin{macrocode}
+\renewcommand*{\DTLacmcs}{ACM Computing Surveys}
+\renewcommand*{\DTLacta}{Acta Informatica}
+\renewcommand*{\DTLcacm}{Communications of the ACM}
+\renewcommand*{\DTLibmjrd}{IBM Journal of Research and Development}
+\renewcommand*{\DTLibmsj}{IBM Systems Journal}
+\renewcommand*{\DTLieeese}{IEEE Transactions on Software Engineering}
+\renewcommand*{\DTLieeetc}{IEEE Transactions on Computers}
+\renewcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design
+of Integrated Circuits}
+\renewcommand*{\DTLipl}{Information Processing Letters}
+\renewcommand*{\DTLjacm}{Journal of the ACM}
+\renewcommand*{\DTLjcss}{Journal of Computer and System Sciences}
+\renewcommand*{\DTLscp}{Science of Computer Programming}
+\renewcommand*{\DTLsicomp}{SIAM Journal on Computing}
+\renewcommand*{\DTLtocs}{ACM Transactions on Computer Systems}
+\renewcommand*{\DTLtods}{ACM Transactions on Database Systems}
+\renewcommand*{\DTLtog}{ACM Transactions on Graphics}
+\renewcommand*{\DTLtoms}{ACM Transactions on Mathematical Software}
+\renewcommand*{\DTLtoois}{ACM Transactions on Office Information
+Systems}
+\renewcommand*{\DTLtoplas}{ACM Transactions on Programming Languages
+and Systems}
+\renewcommand*{\DTLtcs}{Theoretical Computer Science}
+% \end{macrocode}
+% The format of an article.
+% \begin{macrocode}
+\renewcommand*{\DTLformatarticle}{%
+\DTLformatauthorlist
+\DTLifbibfieldexists{Author}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{CrossRef}{%
+% cross ref field
+\DTLformatarticlecrossref
+\DTLifbibfieldexists{Pages}{\DTLaddcomma}{}%
+\DTLformatpages
+\DTLaddperiod
+}{% no cross ref field
+\DTLifbibfieldexists{Journal}{\DTLstartsentencespace
+{\em\DTLbibfield{Journal}}%
+\DTLcheckbibfieldendsperiod{Journal}%
+\DTLifanybibfieldexists{Number,Volume,Pages,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatvolnumpages
+\DTLifanybibfieldexists{Volume,Number,Pages}{%
+\DTLifanybibfieldexists{Year,Month}{\DTLaddcomma}{%
+\DTLaddperiod}%
+\DTLmidsentencefalse}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}%
+}%
+\DTLifbibfieldexists{Note}{\DTLstartsentencespace\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}
+% \end{macrocode}
+% The format of a book.
+% \begin{macrocode}
+\renewcommand*{\DTLformatbook}{%
+\DTLifbibfieldexists{Author}{%
+\DTLformatauthorlist\DTLaddperiod
+}{\DTLformateditorlist\DTLifbibfieldexists{Editor}{%
+\DTLaddperiod}{}}%
+\DTLifbibfieldexists{Title}{\DTLstartsentencespace
+{\em\DTLbibfield{Title}}%
+\DTLcheckbibfieldendsperiod{Title}}{}%
+\DTLifbibfieldexists{CrossRef}{%
+% cross ref field
+\DTLifbibfieldexists{Title}{\DTLaddperiod}{}%
+\DTLformatbookcrossref
+\DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}%
+}{% no cross ref field
+\DTLifbibfieldexists{Title}{%
+\DTLifbibfieldexists{Volume}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatbvolume
+\DTLformatnumberseries
+\DTLifanybibfieldexists{Number,Series,Volume}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Publisher}{\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLifbibfieldexists{Address}{\DTLaddcomma}{%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}%
+}}{}%
+\DTLifbibfieldexists{Address}{\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+}%
+\DTLifbibfieldexists{Edition}{%
+\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace\expandafter\MakeUppercase\@dtl@tmp
+\fi
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}%
+}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a booklet.
+% \begin{macrocode}
+\renewcommand*{\DTLformatbooklet}{%
+\DTLifbibfieldexists{Author}{%
+\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{HowPublished}{%
+\DTLstartsentencespace\DTLbibfield{HowPublished}%
+\DTLcheckbibfieldendsperiod{HowPublished}%
+\DTLifanybibfieldexists{Address,Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{\DTLstartsentencespace\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of an `inbook' entry.
+% \begin{macrocode}
+\renewcommand*{\DTLformatinbook}{%
+\DTLifbibfieldexists{Author}{%
+\DTLformatauthorlist\DTLaddperiod}{%
+\DTLifbibfieldexists{Editor}{\DTLformateditorlist\DTLaddperiod}{}}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+{\em\DTLbibfield{Title}}%
+\DTLcheckbibfieldendsperiod{Title}%
+}{}%
+\DTLifbibfieldexists{CrossRef}{%
+% Cross ref entry
+\DTLifbibfieldexists{Title}{%
+\DTLifbibfieldexists{Chapter}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatchapterpages
+\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}%
+\DTLformatbookcrossref
+}{% no cross ref
+\DTLifbibfieldexists{Title}{%
+\DTLifanybibfieldexists{Chapter,Volume}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLformatbvolume
+\DTLifanybibfieldexists{Volume,Series}{%
+\DTLifanybibfieldexists{Chapter,Pages}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatchapterpages
+\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLifbibfieldexists{Address}{\DTLaddcomma}{}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}}{}%
+}%
+\DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}%
+\DTLifbibfieldexists{Edition}{%
+\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\@dtl@tmp
+\fi
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}%
+}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of an `incollection' entry.
+% \begin{macrocode}
+\renewcommand*{\DTLformatincollection}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{CrossRef}{%
+% cross ref entry
+\DTLformatincollproccrossref
+\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddcomma}{}%
+\DTLformatchapterpages\DTLaddperiod
+}{% no cross ref entry
+\DTLformatinedbooktitle
+\DTLifbibfieldexists{BookTitle}{%
+\DTLifanybibfieldexists{Volume,Series,Chapter,Pages,Number}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatbvolume
+\DTLifbibfieldexists{Volume}{%
+\DTLifanybibfieldexists{Number,Series,Chapter,Pages}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatnumberseries
+\DTLifanybibfieldexists{Number,Series}{%
+\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLformatchapterpages
+\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLifanybibfieldexists{Address,Edition,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Edition,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Edition}{%
+\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\@dtl@tmp
+\fi
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}%
+}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of an `inproceedings' entry.
+% \begin{macrocode}
+\renewcommand*{\DTLformatinproceedings}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{CrossRef}{%
+% cross ref entry
+\DTLformatincollproccrossref
+\DTLifbibfieldexists{Pages}{\DTLaddcomma}{%
+\DTLaddperiod}%
+\DTLformatpages
+\DTLifbibfieldexists{Pages}{\DTLaddperiod}{}%
+}{% no cross ref
+\DTLformatinedbooktitle
+\DTLifbibfieldexists{BookTitle}{%
+\DTLifanybibfieldexists{Volume,Series,Pages,Number,Address,%
+Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatbvolume
+\DTLifbibfieldexists{Volume}{%
+\DTLifanybibfieldexists{Number,Series,Pages,Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatnumberseries
+\DTLifanybibfieldexists{Number,Series}{%
+\DTLifanybibfieldexists{Pages,Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatpages
+\DTLifbibfieldexists{Pages}{%
+\DTLifanybibfieldexists{Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifbibfieldexists{Publisher}{\DTLaddcomma}{%
+\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLaddperiod}{}%
+}{%
+\DTLifanybibfieldexists{Publisher,Organization}{%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifanybibfieldexists{Publisher,Month,Year}{%
+\DTLaddcomma}{}}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+}%
+}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a manual.
+% \begin{macrocode}
+\renewcommand*{\DTLformatmanual}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist
+\DTLaddperiod}{%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifbibfieldexists{Address}{\DTLaddcomma \DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+}{}%
+\DTLaddperiod}{}%
+}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+{\em\DTLbibfield{Title}}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLifbibfieldexists{Author}{%
+\DTLifanybibfieldexists{Organization,Address}{%
+\DTLaddperiod}{\DTLaddcomma}}{%
+\DTLifanybibfieldexists{Organization,Address,Edition,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}}{}%
+\DTLifbibfieldexists{Author}{%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifanybibfieldexists{Address,Edition,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Edition,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+}{%
+\DTLifbibfieldexists{Organization}{}{%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}}{}}%
+}%
+\DTLifbibfieldexists{Edition}{%
+\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\@dtl@tmp
+\fi
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a master's thesis.
+% \begin{macrocode}
+\renewcommand*{\DTLformatmastersthesis}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Type}{%
+\DTLstartsentencespace
+\DTLbibfield{Type}%
+\DTLcheckbibfieldendsperiod{Type}%
+\DTLifanybibfieldexists{School,Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{School}{%
+\DTLstartsentencespace
+\DTLbibfield{School}%
+\DTLcheckbibfieldendsperiod{School}%
+\DTLifanybibfieldexists{Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a miscellaneous entry.
+% \begin{macrocode}
+\renewcommand*{\DTLformatmisc}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLifbibfieldexists{HowPublished}{\DTLaddperiod}{%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}%
+}%
+\DTLmidsentencefalse}{}%
+\DTLifbibfieldexists{HowPublished}{%
+\DTLstartsentencespace
+\DTLbibfield{HowPublished}%
+\DTLcheckbibfieldendsperiod{HowPublished}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a PhD thesis.
+% \begin{macrocode}
+\renewcommand*{\DTLformatphdthesis}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+{\em\DTLbibfield{Title}}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Type}{%
+\DTLstartsentencespace
+\DTLbibfield{Type}%
+\DTLcheckbibfieldendsperiod{Type}%
+\DTLifanybibfieldexists{School,Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{School}{%
+\DTLstartsentencespace
+\DTLbibfield{School}%
+\DTLcheckbibfieldendsperiod{School}%
+\DTLifanybibfieldexists{Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a proceedings.
+% \begin{macrocode}
+\renewcommand*{\DTLformatproceedings}{%
+\DTLifbibfieldexists{Editor}{%
+\DTLformateditorlist\DTLaddperiod}{%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLaddperiod}{}}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+{\em\DTLbibfield{Title}}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLifanybibfieldexists{Volume,Number,Address,Editor,Publisher,%
+Month,Year}{\DTLaddcomma}{\DTLaddperiod}%
+}{}%
+\DTLformatbvolume
+\DTLifbibfieldexists{Volume}{%
+\DTLifanybibfieldexists{Number,Address,Editor,Publisher,%
+Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatnumberseries
+\DTLifbibfieldexists{Number}{%
+\DTLifanybibfieldexists{Address,Editor,Publisher,%
+Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Editor}{\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLaddcomma}{\DTLaddperiod}}{}}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLaddperiod
+}{}%
+}{% no address
+\DTLifbibfieldexists{Editor}{%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifanybibfieldexists{Publisher,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a technical report.
+% \begin{macrocode}
+\renewcommand*{\DTLformattechreport}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Type}{%
+\DTLstartsentencespace
+\DTLbibfield{Type}%
+\DTLcheckbibfieldendsperiod{Type}%
+\DTLifbibfieldexists{Number}{~}{}}{}%
+\DTLifbibfieldexists{Number}{%
+\DTLstartsentencespace
+\DTLbibfield{Number}%
+\DTLcheckbibfieldendsperiod{Number}%
+}{}%
+\DTLifanybibfieldexists{Type,Number}{%
+\DTLifanybibfieldexists{Institution,Address,Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Institution}{%
+\DTLstartsentencespace
+\DTLbibfield{Institution}%
+\DTLcheckbibfieldendsperiod{Institution}%
+\DTLifanybibfieldexists{Address,Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of an unpublished work.
+% \begin{macrocode}
+\renewcommand*{\DTLformatunpublished}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% End of `plain' style.
+% \begin{macrocode}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlbst@abbrv}
+% Define `abbrv' style. This is similar to `plain' except that
+% some of the values are abbreviated
+% \begin{macrocode}
+\newcommand{\dtlbst@abbrv}{%
+% \end{macrocode}
+% Base this style on `plain':
+% \begin{macrocode}
+\dtlbst@plain
+% \end{macrocode}
+% Sets the author name format.
+% \begin{macrocode}
+\renewcommand*{\DTLformatauthor}[4]{%
+\DTLformatabbrvforenames{##4}
+\DTLformatvon{##1}%
+\DTLformatsurname{##2}%
+\DTLformatjr{##3}}
+% \end{macrocode}
+% Sets the editor name format.
+% \begin{macrocode}
+\renewcommand*{\DTLformateditor}[4]{%
+\DTLformatabbrvforenames{##4}
+\DTLformatvon{##1}%
+\DTLformatsurname{##2}%
+\DTLformatjr{##3}}
+% \end{macrocode}
+% Sets the monthname format.
+% \begin{macrocode}
+\let\DTLmonthname\dtl@abbrvmonthname
+% \end{macrocode}
+% Sets other predefined names:
+% \begin{macrocode}
+\renewcommand*{\DTLacmcs}{ACM Comput.\ Surv.}
+\renewcommand*{\DTLacta}{Acta Inf.}
+\renewcommand*{\DTLcacm}{Commun.\ ACM}
+\renewcommand*{\DTLibmjrd}{IBM J.\ Res.\ Dev.}
+\renewcommand*{\DTLibmsj}{IBM Syst.~J.}
+\renewcommand*{\DTLieeese}{IEEE Trans. Softw.\ Eng.}
+\renewcommand*{\DTLieeetc}{IEEE Trans.\ Comput.}
+\renewcommand*{\DTLieeetcad}{IEEE Trans.\ Comput.-Aided Design
+Integrated Circuits}
+\renewcommand*{\DTLipl}{Inf.\ Process.\ Lett.}
+\renewcommand*{\DTLjacm}{J.~ACM}
+\renewcommand*{\DTLjcss}{J.~Comput.\ Syst.\ Sci.}
+\renewcommand*{\DTLscp}{Sci.\ Comput.\ Programming}
+\renewcommand*{\DTLsicomp}{SIAM J.~Comput.}
+\renewcommand*{\DTLtocs}{ACM Trans.\ Comput.\ Syst.}
+\renewcommand*{\DTLtods}{ACM Trans.\ Database Syst.}
+\renewcommand*{\DTLtog}{ACM Trans.\ Gr.}
+\renewcommand*{\DTLtoms}{ACM Trans.\ Math. Softw.}
+\renewcommand*{\DTLtoois}{ACM Trans. Office Inf.\ Syst.}
+\renewcommand*{\DTLtoplas}{ACM Trans.\ Prog. Lang.\ Syst.}
+\renewcommand*{\DTLtcs}{Theoretical Comput.\ Sci.}
+% \end{macrocode}
+% End of `abbrv' style.
+% \begin{macrocode}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlbst@alpha}
+% Define `alpha' style. This is similar to `plain' except that
+% the labels are strings rather than numerical.
+% \begin{macrocode}
+\newcommand{\dtlbst@alpha}{%
+% \end{macrocode}
+% Base this style on `plain':
+% \begin{macrocode}
+\dtlbst@plain
+% \end{macrocode}
+% Set how to format the entire bibliography:
+% \begin{macrocode}
+\renewenvironment{DTLthebibliography}[2][\boolean{true}]{%
+\dtl@createalphabiblabels{##1}{##2}%
+\begin{thebibliography}{\@dtl@widestlabel}%
+}{\end{thebibliography}}%
+% \end{macrocode}
+% Set how to start the bibliography entry:
+% \begin{macrocode}
+\renewcommand*{\DTLbibitem}{%
+\expandafter\bibitem\expandafter
+ [\csname dtl@biblabel@\DBIBcitekey\endcsname]{\DBIBcitekey}}%
+% \end{macrocode}
+% \begin{macrocode}
+% \end{macrocode}
+% End of `alpha' style.
+% \begin{macrocode}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{dtl@createalphabiblabels}
+%\begin{definition}
+%\cs{dtl@createalphabiblabels}\marg{condition}\marg{db name}
+%\end{definition}
+% Constructs the alpha style bib labels for the given database.
+% (Labels are stored in the control sequence
+%\cs{dtl@biblabel@}\meta{citekey}.) This also sets
+% \cs{@dtl@widestlabel} to the widest label.
+% \begin{macrocode}
+\newcommand*{\dtl@createalphabiblabels}[2]{%
+\dtl@message{Creating bib labels}%
+\begingroup
+\gdef\@dtl@widestlabel{}%
+\dtl@widest=0pt\relax
+\DTLforeachbibentry[#1]{#2}{%
+\dtl@message{\DBIBcitekey}%
+\DTLifbibfieldexists{Author}{%
+ \dtl@listgetalphalabel{\@dtl@thislabel}{\@dtl@key@Author}%
+}{%
+\DTLifbibfieldexists{Editor}{%
+ \dtl@listgetalphalabel{\@dtl@thislabel}{\@dtl@key@Editor}%
+ }{%
+ \DTLifbibfieldexists{Key}{%
+ \expandafter\dtl@get@firstthree\expandafter
+ {\@dtl@key@Key}{\@dtl@thislabel}%
+ }{%
+ \DTLifbibfieldexists{Organization}{%
+ \expandafter\dtl@get@firstthree\expandafter
+ {\@dtl@key@Organization}{\@dtl@thislabel}%
+ }{%
+ \expandafter\dtl@get@firstthree\expandafter
+ {\DBIBentrytype}{\@dtl@thislabel}%
+ }%
+ }}}%
+\DTLifbibfieldexists{Year}{}{\DTLifbibfieldexists{CrossRef}{%
+\DTLgetvalueforkey{\@dtl@key@Year}{Year}{#2}{CiteKey}{%
+\@dtl@key@CrossRef}}{}}%
+\DTLifbibfieldexists{Year}{%
+\expandafter\dtl@get@yearsuffix\expandafter{\@dtl@key@Year}%
+\expandafter\toks@\expandafter{\@dtl@thislabel}%
+\expandafter\@dtl@toks\expandafter{\@dtl@year}%
+\edef\@dtl@thislabel{\the\toks@\the\@dtl@toks}%
+}{}%
+\let\@dtl@s@thislabel=\@dtl@thislabel
+\@onelevel@sanitize\@dtl@s@thislabel
+\@ifundefined{c@biblabel@\@dtl@s@thislabel}{%
+\newcounter{biblabel@\@dtl@s@thislabel}%
+\setcounter{biblabel@\@dtl@s@thislabel}{1}%
+\expandafter\edef\csname @dtl@bibfirst@\@dtl@s@thislabel\endcsname{%
+\DBIBcitekey}%
+\expandafter\global
+\expandafter\let\csname dtl@biblabel@\DBIBcitekey\endcsname=
+ \@dtl@thislabel
+}{%
+\expandafter\ifnum\csname c@biblabel@\@dtl@s@thislabel\endcsname=1\relax
+ \expandafter\let\expandafter\@dtl@tmp
+ \csname @dtl@bibfirst@\@dtl@s@thislabel\endcsname
+ \expandafter\protected@xdef\csname dtl@biblabel@\@dtl@tmp\endcsname{%
+ \@dtl@thislabel a}%
+\fi
+\stepcounter{biblabel@\@dtl@s@thislabel}%
+\expandafter\protected@xdef\csname dtl@biblabel@\DBIBcitekey\endcsname{%
+ \@dtl@thislabel\alph{biblabel@\@dtl@s@thislabel}}%
+}%
+\settowidth{\dtl@tmplength}{%
+ \csname dtl@biblabel@\DBIBcitekey\endcsname}%
+\ifdim\dtl@tmplength>\dtl@widest
+ \dtl@widest=\dtl@tmplength
+ \expandafter\global\expandafter\let\expandafter\@dtl@widestlabel
+ \expandafter=\csname dtl@biblabel@\DBIBcitekey\endcsname
+\fi
+}%
+\endgroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@listgetalphalabel}
+% Determine the alpha style label from a list of authors/editors
+% (the first argument must be a control sequence (in which the
+% label is stored), the second argument must be the list of names.)
+% \begin{macrocode}
+\newcommand*{\dtl@listgetalphalabel}[2]{%
+\@dtl@authorcount=0\relax
+\@for\@dtl@author:=#2\do{%
+\advance\@dtl@authorcount by 1\relax}%
+\ifnum\@dtl@authorcount=1\relax
+ \expandafter\dtl@getsinglealphalabel#2{#1}\relax
+\else
+ {%
+ \xdef#1{}%
+ \@dtl@tmpcount=0\relax
+ \def\DTLafterinitials{}\def\DTLbetweeninitials{}%
+ \def\DTLafterinitialbeforehyphen{}\def\DTLinitialhyphen{}%
+ \@for\@dtl@author:=#2\do{%
+ \expandafter\dtl@getauthorinitial\@dtl@author
+ \expandafter\toks@\expandafter{\@dtl@tmp}%
+ \expandafter\@dtl@toks\expandafter{#1}%
+ \xdef#1{\the\@dtl@toks\the\toks@}%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount>2\relax\@endfortrue\fi
+ }}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Get author's initial (stores in \cs{@dtl@tmp}):
+% \begin{macrocode}
+\newcommand*{\dtl@getauthorinitial}[4]{%
+\def\@dtl@vonpart{#1}%
+\ifx\@dtl@vonpart\@empty
+ \DTLstoreinitials{#2}{\@dtl@tmp}%
+\else
+ \DTLstoreinitials{#1 #2}{\@dtl@tmp}%
+\fi}
+% \end{macrocode}
+% Get label for single author (last argument is control sequence
+% in which to store the label):
+% \begin{macrocode}
+\newcommand*{\dtl@getsinglealphalabel}[5]{%
+\def\@dtl@vonpart{#1}%
+\ifx\@dtl@vonpart\@empty
+ \DTLifSubString{#2}{-}{%
+ {\def\DTLafterinitials{}\def\DTLbetweeninitials{}%
+ \def\DTLafterinitialbeforehyphen{}%
+ \def\DTLinitialhyphen{}%
+ \DTLstoreinitials{#2}{\@dtl@tmp}\global\let#5=\@dtl@tmp}%
+ }{%
+ \dtl@getfirstthree{#5}#2{}{}{}{}\@nil
+ }
+\else
+ {\def\DTLafterinitials{}\def\DTLbetweeninitials{}%
+ \def\DTLafterinitialbeforehyphen{}%
+ \def\DTLinitialhyphen{}%
+ \DTLstoreinitials{#1 #2}{\@dtl@tmp}\global\let#5=\@dtl@tmp}%
+\fi
+}
+% \end{macrocode}
+%Get first three letters from the given string:
+% \begin{macrocode}
+\def\dtl@getfirstthree#1#2#3#4#5\@nil{%
+ \def#1{#2#3#4}%
+}
+\newcommand*{\dtl@get@firstthree}[2]{%
+\dtl@getfirstthree#2#1{}{}{}{}{}\@nil}
+% \end{macrocode}
+%Get year suffix:
+% \begin{macrocode}
+\newcommand*{\dtl@get@yearsuffix}[1]{%
+\dtl@getyearsuffix#1\@nil\relax\relax}
+
+\def\dtl@getyearsuffix#1#2#3{%
+\def\@dtl@argi{#1}\def\@dtl@argii{#2}%
+\def\@dtl@argiii{#3}%
+\ifx\@dtl@argi\@nnil
+ \def\@dtl@year{}%
+ \let\@dtl@donext=\relax
+\else
+ \ifx\@dtl@argii\@nnil
+ \dtl@ifsingle{#1}{%
+ \def\@dtl@year{#1}%
+ \let\@dtl@donext=\relax
+ }{%
+ \def\@dtl@donext{\dtl@getyearsuffix#1#2#3}%
+ }%
+ \else
+ \ifx\@dtl@argiii\@nnil
+ \dtl@ifsingle{#1}{%
+ \dtl@ifsingle{#2}{%
+ \def\@dtl@year{#1#2}%
+ \let\@dtl@donext=\relax
+ }{%
+ \def\@dtl@donext{\dtl@getyearsuffix#2#3}%
+ }%
+ }{%
+ \def\@dtl@donext{\dtl@getyearsuffix#2#3}%
+ }%
+ \else
+ \def\@dtl@donext{\dtl@getyearsuffix{#2}{#3}}%
+ \fi
+ \fi
+\fi
+\@dtl@donext
+}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLbibliographystyle}
+%\begin{definition}
+%\cs{DTLbibliographystyle}\marg{style}
+%\end{definition}
+% Sets the bibliography style.
+% \begin{macrocode}
+\newcommand*{\DTLbibliographystyle}[1]{%
+\@ifundefined{dtlbst@#1}{\PackageError{databib}{Unknown
+bibliography style `#1'}{}}{\csname dtlbst@#1\endcsname}}
+% \end{macrocode}
+%\end{macro}
+%Set the default bibliography style:
+% \begin{macrocode}
+\DTLbibliographystyle{\dtlbib@style}
+% \end{macrocode}
+%\iffalse
+% \begin{macrocode}
+%</databib.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*databib.bst>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+% \begin{macrocode}
+% Bibliography style `databib'
+% This style is provided for use with the databib package.
+
+ENTRY
+ { address
+ author
+ booktitle
+ chapter
+ edition
+ editor
+ howpublished
+ institution
+ journal
+ key
+ month
+ note
+ number
+ organization
+ pages
+ publisher
+ school
+ series
+ title
+ type
+ volume
+ year
+ isbn
+ doi
+ pubmed
+ url
+ abstract
+ }
+ {}
+ { label }
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+ #1 'mid.sentence :=
+ #2 'after.sentence :=
+ #3 'after.block :=
+}
+
+STRINGS { s t }
+
+FUNCTION {output.nonnull}
+{ 's :=
+% output.state mid.sentence =
+% { "%" * write$
+% newline$
+% }
+% { output.state after.block =
+% { add.period$ write$
+% newline$
+% }
+ %{
+ output.state before.all =
+ {
+ "%" * write$
+ newline$
+ }
+ { newline$
+ %add.period$ " " * write$
+ }
+ if$
+% }
+ % if$
+ % mid.sentence 'output.state :=
+ % }
+ %if$
+ s
+}
+
+FUNCTION {output}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.check}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ {
+ output.nonnull
+ }
+ if$
+}
+
+FUNCTION {output.bibitem}
+{ "\DTLnewbibrow" write$
+ newline$
+ "\DTLnewbibitem {CiteKey}{" write$
+ cite$ write$
+ "}%" write$
+ newline$
+ ""
+ before.all 'output.state :=
+}
+
+FUNCTION {fin.entry}
+{ "%" *
+ write$
+ newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+ 'skip$
+ { after.block 'output.state := }
+ if$
+}
+
+FUNCTION {new.sentence}
+{ output.state after.block =
+ 'skip$
+ { output.state before.all =
+ 'skip$
+ { after.sentence 'output.state := }
+ if$
+ }
+ if$
+}
+
+FUNCTION {not}
+{ { #0 }
+ { #1 }
+ if$
+}
+
+FUNCTION {and}
+{ 'skip$
+ { pop$ #0 }
+ if$
+}
+
+FUNCTION {or}
+{ { pop$ #1 }
+ 'skip$
+ if$
+}
+
+FUNCTION {new.block.checka}
+{ empty$
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.block.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.sentence.checka}
+{ empty$
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {new.sentence.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+ { pop$ "" }
+ 'skip$
+ if$
+}
+
+FUNCTION {emphasize}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{\em " swap$ * "}" * }
+ if$
+}
+
+FUNCTION {group}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{" swap$ * "}" * }
+ if$
+}
+
+INTEGERS { nameptr namesleft numnames }
+
+FUNCTION {format.names}
+{
+ 's :=
+ #1 'nameptr :=
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ {
+ %s nameptr "{vv,}{ll,}{jj,}{ff}" format.name$ 't :=
+ "{" *
+ s nameptr "{vv}" format.name$ 't :=
+ t * "}" *
+ "{" *
+ s nameptr "{ll}" format.name$ 't :=
+ t * "}{" *
+ s nameptr "{jj}" format.name$ 't :=
+ t * "}" *
+ "{" *
+ s nameptr "{ff}" format.name$ 't :=
+ t * "}" *
+ s nameptr "" format.name$ 't :=
+ namesleft #1 >
+ { "," * }
+ { }
+ if$
+ nameptr #1 >
+ {
+ t *
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+ "}" *
+}
+
+FUNCTION {format.authors}
+{
+ author empty$
+ { "" }
+ { author
+ "\DTLnewbibitem {Author}{" write$
+ format.names }
+ if$
+}
+
+FUNCTION {format.editors}
+{ editor empty$
+ { "" }
+ { editor
+ "\DTLnewbibitem {Editor}{" write$
+ format.names
+ }
+ if$
+}
+
+FUNCTION {format.title}
+{ title empty$
+ { "" }
+ {
+ "\DTLnewbibitem {Title}"
+ title "t" change.case$ group *
+ }
+ if$
+}
+
+FUNCTION {format.howpublished}
+{ howpublished empty$
+ { "" }
+ {
+ howpublished
+ "\DTLnewbibitem {HowPublished}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.organization}
+{ organization empty$
+ { "" }
+ {
+ organization
+ "\DTLnewbibitem {Organization}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.institution}
+{ institution empty$
+ { "" }
+ {
+ institution
+ "\DTLnewbibitem {Institution}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.key}
+{ key empty$
+ { "" }
+ {
+ key
+ "\DTLnewbibitem {Key}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.note}
+{ note empty$
+ { "" }
+ {
+ note
+ "\DTLnewbibitem {Note}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.isbn}
+{ isbn empty$
+ { "" }
+ {
+ isbn
+ "\DTLnewbibitem {ISBN}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.doi}
+{ doi empty$
+ { "" }
+ {
+ doi
+ "\DTLnewbibitem {DOI}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.pubmed}
+{ pubmed empty$
+ { "" }
+ {
+ pubmed
+ "\DTLnewbibitem {PubMed}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.abstract}
+{ abstract empty$
+ { "" }
+ {
+ abstract
+ "\DTLnewbibitem {Abstract}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.url}
+{ url empty$
+ { "" }
+ {
+ url
+ "\DTLnewbibitem {Url}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.address}
+{ address empty$
+ { "" }
+ {
+ address
+ "\DTLnewbibitem {Address}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.school}
+{ school empty$
+ { "" }
+ {
+ school
+ "\DTLnewbibitem {School}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.publisher}
+{ publisher empty$
+ { "" }
+ {
+ publisher
+ "\DTLnewbibitem {Publisher}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {n.dashify}
+{ 't :=
+ ""
+ { t empty$ not }
+ { t #1 #1 substring$ "-" =
+ { t #1 #2 substring$ "--" = not
+ { "--" *
+ t #2 global.max$ substring$ 't :=
+ }
+ { { t #1 #1 substring$ "-" = }
+ { "-" *
+ t #2 global.max$ substring$ 't :=
+ }
+ while$
+ }
+ if$
+ }
+ { t #1 #1 substring$ *
+ t #2 global.max$ substring$ 't :=
+ }
+ if$
+ }
+ while$
+}
+
+FUNCTION {format.date}
+{ year empty$
+ { month empty$
+ { "" }
+ { "there's a month but no year in " cite$ * warning$
+ "\DTLnewbibitem {Month}" *
+ month group
+ }
+ if$
+ }
+ { month empty$
+ { }
+ { "\DTLnewbibitem {Month}{" * month * "}" * }
+ if$
+ "\DTLnewbibitem {Year}{" * year * "}"
+ }
+ if$
+}
+
+FUNCTION {format.btitle}
+{ title
+ "\DTLnewbibitem {Title}{" swap$ *
+ "}" *
+}
+
+FUNCTION {tie.or.space.connect}
+{ duplicate$ text.length$ #3 <
+ { "~" }
+ { " " }
+ if$
+ swap$ * *
+}
+
+FUNCTION {either.or.check}
+{ empty$
+ 'pop$
+ { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+ if$
+}
+
+FUNCTION {format.bvolume}
+{ volume empty$
+ { "" }
+ {
+ "\DTLnewbibitem {Volume}{" volume * "}" *
+ series empty$
+ 'skip$
+ {
+ "\DTLnewbibitem {Series}" * series group *
+ }
+ if$
+ "volume and number" number either.or.check
+ }
+ if$
+}
+
+FUNCTION {format.number.series}
+{ volume empty$
+ { number empty$
+ {
+ %series field.or.null group
+ series empty$
+ { "" }
+ { "\DTLnewbibitem {Series}" * series group }
+ if$
+ }
+ {
+ "\DTLnewbibitem {Number}" number group *
+ series empty$
+ { "there's a number but no series in " cite$ * warning$ }
+ { "\DTLnewbibitem {Series}{" * series * "}" * }
+ if$
+ }
+ if$
+ }
+ { "" }
+ if$
+}
+
+FUNCTION {format.edition}
+{ edition empty$
+ { "" }
+ {
+ "\DTLnewbibitem {Edition}"
+ edition "l" change.case$ group *
+ }
+ if$
+}
+
+INTEGERS { multiresult }
+
+FUNCTION {multi.page.check}
+{ 't :=
+ #0 'multiresult :=
+ { multiresult not
+ t empty$ not
+ and
+ }
+ { t #1 #1 substring$
+ duplicate$ "-" =
+ swap$ duplicate$ "," =
+ swap$ "+" =
+ or or
+ { #1 'multiresult := }
+ { t #2 global.max$ substring$ 't := }
+ if$
+ }
+ while$
+ multiresult
+}
+
+FUNCTION {format.pages}
+{ pages empty$
+ { "" }
+ { pages multi.page.check
+ { "\DTLnewbibitem {Pages}" pages n.dashify
+ group * }
+ { "\DTLnewbibitem {Pages}" pages
+ group *}
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.vol.num.pages}
+{
+ volume empty$
+ { "" }
+ {
+ "\DTLnewbibitem {Volume}{" volume * "}" *
+ }
+ if$
+ number empty$
+ 'skip$
+ { "\DTLnewbibitem {Number}{" number * "}\relax " * *
+ volume empty$
+ { "there's a number but no volume in " cite$ * warning$ }
+ 'skip$
+ if$
+ }
+ if$
+ pages empty$
+ 'skip$
+ { duplicate$ empty$
+ { pop$ format.pages }
+ { "\DTLnewbibitem {Pages}" * pages n.dashify group * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.chapter.pages}
+{ chapter empty$
+ 'format.pages
+ { type empty$
+ { "\DTLnewbibitem {Type}{chapter}" }
+ { "\DTLnewbibitem {Type}" type "l" change.case$ group *}
+ if$
+ "\DTLnewbibitem {Chapter}{" * chapter * "}" *
+ pages empty$
+ 'skip$
+ { format.pages * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.in.ed.booktitle}
+{ booktitle empty$
+ { "" }
+ {
+ "\DTLnewbibitem {BookTitle}" booktitle group *
+ editor empty$
+ {}
+ {
+ "\DTLnewbibitem {Editor}{" *
+ editor format.names *
+ }
+ if$
+ }
+ if$
+}
+
+FUNCTION {empty.misc.check}
+{ author empty$ title empty$ howpublished empty$
+ month empty$ year empty$ note empty$
+ and and and and and
+ { "all relevant fields are empty in " cite$ * warning$ }
+ 'skip$
+ if$
+}
+
+FUNCTION {format.thesis.type}
+{ type empty$
+ 'skip$
+ { pop$
+ type "t" change.case$
+ "\DTLnewbibitem {Type}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.tr.number}
+{
+ type empty$
+ { "\techreportname " }
+ 'type
+ if$
+ number empty$
+ { "t" change.case$ "\DTLnewbibitem {Type}" swap$ group *}
+ { "\DTLnewbibitem {Type}" swap$ group *
+ "\DTLnewbibitem {Number}" *
+ number group * }
+ if$
+}
+
+FUNCTION {format.article.crossref}
+{ key empty$
+ { journal empty$
+ { "need key or journal for " cite$ * " to crossref " * crossref *
+ warning$
+ ""
+ }
+ {
+ "\DTLnewbibitem {Journal}" journal group *
+ }
+ if$
+ }
+ {
+ ""
+ }
+ if$
+ "\DTLnewbibitem {CrossRef}{" * crossref * "}" *
+}
+
+FUNCTION {format.crossref.editor}
+{ format.editors
+% editor #1 "{vv~}{ll}" format.name$
+% editor num.names$ duplicate$
+% #2 >
+% { pop$ " et~al." * }
+% { #2 <
+% 'skip$
+% { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+% { " et~al." * }
+% { " and " * editor #2 "{vv~}{ll}" format.name$ * }
+% if$
+% }
+% if$
+% }
+% if$
+}
+
+FUNCTION {format.book.crossref}
+{ volume empty$
+ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+ }
+ {
+ "\DTLnewbibitem {Volume}"
+ volume group *
+ }
+ if$
+ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { series empty$
+ { "need editor, key, or series for " cite$ * " to crossref " *
+ crossref * warning$
+ "" *
+ }
+ {
+ "\DTLnewbibitem {Series}{" * series *
+ "}" *
+ }
+ if$
+ }
+ { ""
+ }
+ if$
+ }
+ {
+ format.crossref.editor *
+ }
+ if$
+ "\DTLnewbibitem {CrossRef}{" * crossref * "}" *
+}
+
+FUNCTION {format.incoll.inproc.crossref}
+{ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { booktitle empty$
+ { "need editor, key, or booktitle for " cite$ * " to crossref " *
+ crossref * warning$
+ ""
+ }
+ { "\DTLnewbibitem {BookTitle}{" booktitle * "}" * }
+ if$
+ }
+ { "" }
+ if$
+ }
+ {
+ "\DTLnewbibitem {Editor}{" *
+ editor format.names
+ }
+ if$
+ "\DTLnewbibitem {CrossRef}{" * crossref * "}" *
+}
+
+FUNCTION {article}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{article}%" write$
+ newline$
+ format.authors "author"
+ output.check
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ {
+ "\DTLnewbibitem {Journal}" *
+ journal group "journal" output.check
+ format.vol.num.pages output
+ format.date "year" output.check
+ }
+ { format.article.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {book}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{book}%" write$
+ newline$
+ author empty$
+ { format.editors "author and editor" output.check }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check
+ }
+ 'skip$
+ if$
+ }
+ if$
+ new.block
+ format.btitle "title" output.check
+ crossref missing$
+ { format.bvolume output
+ new.block
+ format.number.series output
+ %new.sentence
+ format.publisher "publisher" output.check
+ format.address output
+ }
+ { new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.edition output
+ format.date "year" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {booklet}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{booklet}%" write$
+ newline$
+ format.authors output
+ new.block
+ format.title "title" output.check
+ howpublished address new.block.checkb
+ format.howpublished output
+ format.address output
+ format.date output
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{inbook}%" write$
+ newline$
+ author empty$
+ { format.editors "author and editor" output.check }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ new.block
+ format.btitle "title" output.check
+ crossref missing$
+ { format.bvolume output
+ format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.number.series output
+ new.sentence
+ format.publisher "publisher" output.check
+ format.address output
+ }
+ { format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.edition output
+ format.date "year" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {incollection}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{incollection}%" write$
+ newline$
+ format.authors "author" output.check
+ format.title "title" output.check
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.chapter.pages output
+ new.sentence
+ format.publisher "publisher" output.check
+ format.address output
+ format.edition output
+ format.date "year" output.check
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.chapter.pages output
+ }
+ if$
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {inproceedings}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{inproceedings}%" write$
+ newline$
+ format.authors "author" output.check
+ format.title "title" output.check
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.pages output
+ address empty$
+ { %organization publisher new.sentence.checkb
+ format.organization write$
+ format.publisher output
+ }
+ { format.address write$
+ new.sentence
+ format.organization output
+ format.publisher output
+ }
+ if$
+ format.date "year" output.check
+ }
+ {
+ format.incoll.inproc.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {conference} { inproceedings }
+
+FUNCTION {manual}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{manual}%" write$
+ newline$
+ author empty$
+ { organization empty$
+ 'skip$
+ { format.organization output
+ format.address output
+ }
+ if$
+ }
+ { format.authors output }
+ if$
+ new.block
+ format.btitle "title" output.check
+ author empty$
+ { organization empty$
+ { address new.block.checka
+ address output
+ }
+ 'skip$
+ if$
+ }
+ { %organization address new.block.checkb
+ format.organization output
+ format.address output
+ }
+ if$
+ format.edition output
+ format.date output
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{mastersthesis}%" write$
+ newline$
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ "\DTLnewbibitem {Type}{\mscthesisname }"
+ format.thesis.type output.nonnull
+ format.school "school" output.check
+ format.address output
+ format.date "year" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {misc}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{misc}%" write$
+ newline$
+ format.authors output
+ title howpublished new.block.checkb
+ format.title output
+ %howpublished new.block.checka
+ format.howpublished output
+ format.date output
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+ empty.misc.check
+}
+
+FUNCTION {phdthesis}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{phdthesis}%" write$
+ newline$
+ format.authors "author" output.check
+ new.block
+ format.btitle "title" output.check
+ new.block
+ "\DTLnewbibitem {Type}{\phdthesisname }"
+ format.thesis.type output.nonnull
+ format.school "school" output.check
+ format.address output
+ format.date "year" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{proceedings}%" write$
+ newline$
+ editor empty$
+ { format.organization output }
+ { format.editors output.nonnull }
+ if$
+ new.block
+ format.btitle "title" output.check
+ format.bvolume output
+ format.number.series output
+ address empty$
+ { editor empty$
+ { publisher new.sentence.checka }
+ { organization publisher new.sentence.checkb
+ format.organization output
+ }
+ if$
+ format.publisher output
+ format.date "year" output.check
+ }
+ { format.address output
+ format.date "year" output.check
+ new.sentence
+ editor empty$
+ 'skip$
+ { format.organization output }
+ if$
+ format.publisher output
+ }
+ if$
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{techreport}%" write$
+ newline$
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ format.tr.number output.nonnull
+ format.institution "institution" output.check
+ format.address output
+ format.date "year" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ fin.entry
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{unpublished}%" write$
+ newline$
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.date output
+ fin.entry
+}
+
+FUNCTION {default.type} { misc }
+
+MACRO {jan} {"\DTLmonthname{01}"}
+
+MACRO {feb} {"\DTLmonthname{02}"}
+
+MACRO {mar} {"\DTLmonthname{03}"}
+
+MACRO {apr} {"\DTLmonthname{04}"}
+
+MACRO {may} {"\DTLmonthname{05}"}
+
+MACRO {jun} {"\DTLmonthname{06}"}
+
+MACRO {jul} {"\DTLmonthname{07}"}
+
+MACRO {aug} {"\DTLmonthname{08}"}
+
+MACRO {sep} {"\DTLmonthname{09}"}
+
+MACRO {oct} {"\DTLmonthname{10}"}
+
+MACRO {nov} {"\DTLmonthname{11}"}
+
+MACRO {dec} {"\DTLmonthname{12}"}
+
+MACRO {acmcs} {"\DTLacmcs "}
+
+MACRO {acta} {"\DTLacta "}
+
+MACRO {cacm} {"\DTLcacm "}
+
+MACRO {ibmjrd} {"\DTLibmjrd "}
+
+MACRO {ibmsj} {"\DTLibmsj "}
+
+MACRO {ieeese} {"\DTLieeese "}
+
+MACRO {ieeetc} {"\DTLieeetc "}
+
+MACRO {ieeetcad} {"\DTLieeetcad "}
+
+MACRO {ipl} {"\DTLipl "}
+
+MACRO {jacm} {"\DTLjacm "}
+
+MACRO {jcss} {"\DTLjcss "}
+
+MACRO {scp} {"\DTLscp "}
+
+MACRO {sicomp} {"\DTLsicomp "}
+
+MACRO {tocs} {"\DTLtocs "}
+
+MACRO {tods} {"\DTLtods "}
+
+MACRO {tog} {"\DTLtog "}
+
+MACRO {toms} {"\DTLtoms "}
+
+MACRO {toois} {"\DTLtoois "}
+
+MACRO {toplas} {"\DTLtoplas "}
+
+MACRO {tcs} {"\DTLtcs "}
+
+READ
+
+STRINGS { longest.label }
+
+INTEGERS { number.label longest.label.width }
+
+FUNCTION {initialize.longest.label}
+{ "" 'longest.label :=
+ #1 'number.label :=
+ #0 'longest.label.width :=
+}
+
+FUNCTION {longest.label.pass}
+{ number.label int.to.str$ 'label :=
+ number.label #1 + 'number.label :=
+ label width$ longest.label.width >
+ { label 'longest.label :=
+ label width$ 'longest.label.width :=
+ }
+ 'skip$
+ if$
+}
+
+EXECUTE {initialize.longest.label}
+
+ITERATE {longest.label.pass}
+
+FUNCTION {begin.bib}
+{ preamble$ empty$
+ 'skip$
+ { preamble$ write$ newline$ }
+ if$
+}
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION {end.bib}
+{
+}
+
+EXECUTE {end.bib}
+% \end{macrocode}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</databib.bst>
+% \end{macrocode}
+%\fi
+%\Finale
+\endinput