% \iffalse
%******************************************************************************
% File:     @(#)$OrigId: docversion.sty,v 1.8 2009-10-30 07:31:14+01 martin Rel $
% Contents: LaTeX package "docversion"
% Author:   Martin Lottermoser (Martin.Lottermoser at t-online.de)
%
%******************************************************************************
%
%	Copyright (C) 2009 by Martin Lottermoser
%	All rights reserved
%
%******************************************************************************
%
% In order to extract the documentation from this file, create a driver file
% like
%
%   \documentclass[a4paper]{article}
%   \usepackage{doc}
%   \begin{document}
%   \DocInput{docversion.sty}
%   \end{document}
%
% and process it with LaTeX. If you need a variant with the comments stripped
% for performance reasons, create a subdirectory named, e.g., "source", put
% this file into it, create a new file in the present directory named, e.g.,
% "ds.tex", containing
%
%   \def\batchfile{ds.tex}
%   \input docstrip.tex
%   \generateFile{docversion.sty}{f}{\from{source/docversion.sty}{}}
%
% and run it through LaTeX; this will give a reduced file "docversion.sty" in
% the current directory.
%
%******************************************************************************
% \fi
%
% \def\RCSDate$#1: #2 #3${\ignorespaces#2}
% \MakeShortVerb{\|}
% \CodelineNumbered
%
% \def\atsign{@}	^^A anti-spam measure
% \title{Docversion:
%   Macros for Describing and Determining the Version of a Document}
% \author{Martin Lottermoser\\
%   \texttt{Martin.Lottermoser\atsign t-online.de}}
% \date{\RCSDate$OrigDate: 2009-10-30 07:31:14+01 $}
% \maketitle
% \abstract{This \LaTeX\ package defines macros for describing the version of
%   a document and provides an extensible interface for obtaining the values
%   for these macros from a configuration management system.}
%
% ^^A This must be placed after the \abstract call:
% \setlength{\parindent}{0mm}
% \setlength{\parskip}{\smallskipamount}
%
% \advance\skip\footins by \bigskipamount
%
% \tableofcontents
%
% \bigbreak
%
% ^^A**************************************************************************
%
% \section{Preliminaries}
%
% \subsection{Package Identification}
%
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{docversion}[2009/10/30 Document version macros]
%    \end{macrocode}
%
% If the \texttt{sourceid} package has been read, I'm using it for
% recording file version information:
%    \begin{macrocode}
\ifx\@undefined\sourceidentification\else\sourceidentification{\whatstring
  $OrigId: docversion.sty,v 1.8 2009-10-30 07:31:14+01 martin Rel $}\fi
%    \end{macrocode}
%
% ^^A==========================================================================
%
% \subsection{License}
%
% It cannot be applied exactly, but you should consider this file to be usable
% in the spirit of the GNU Lesser General Public License, version~2.1
% (LGPLv2.1; see http://www.gnu.org/licenses/lgpl-2.1.html). Basically, I do
% not claim to have any rights in the documents you create with this software,
% you don't have to distribute my macros with your documents, but if you copy
% or modify the macros and offer this derived version for distribution you have
% to do this under the same license and it must be apparent what you have
% modified.
%
% If you have questions concerning this license, contact me for clarification.
%
% ^^A==========================================================================
%
% \subsection{Concepts and Goals}
%
% Many documents evolve over time and exist therefore in various versions.
% To avoid misunderstanding, the version should then be apparent from the
% document's visible content.\footnote{If you are interested in means of
%   identification which are invisible to the reader and more useful to the
%   author, see the ``sourceid'' package.}
%
% For \TeX\ documents, the final representation is generated from a possibly
% large number of files (bibliography files, illustrations, macro packages,
% font files, configuration files, \textellipsis).
% In most cases, however, what one might call the content proper (in particular
% the body text of the document) is contained in a much smaller number of
% \TeX\ files created by the author specifically for this document.
% Let these be called the ``source files''.
% For the purposes of the present package, the state of these files determines
% what is called here the ``version'' of the document.
%
% If a document evolves linearly (i.e., without branches),
% one possibility to identify the version is to show the moment this version
% was created.
% The granularity of this specification should be sufficiently fine
% to uniquely identify all versions which need to be distinguished.
% This means that, while in some situations month and year are sufficient,
% in others you might have to add the day, the hour, and the minute.
% Although the time of the \TeX\ run can be used for this purpose,
% it also gives different identities to two copies of the same version of the
% document if two \TeX\ runs were made at different times but with the same
% source file state.
% In order to reliably identify two versions as being the same,
% the displayed moment of creation should therefore be the last moment one of
% the source files was modified.
% In case these files are stored in a configuration management (CM) system,
% mistakes can be prevented if this value can be determined automatically from
% information provided by the CM system.
%
% Another possibility of identifying a document's version is to use some kind
% of sequence number; with suitable conventions, this works even for branches.
% In case of books this is usually the edition number;
% for documents where there is a single source file which is held in a
% CM system,
% a suitable choice is the version number assigned by that system.
% If the CM system offers global numbering of versions across all files in a
% repository,
% a single CM-specific version number can also be used to identify the state of
% a collection of source files;
% most CM systems support at least the assignment of global names (``labels'')
% to CM versions of each file,
% in which case such a name can be used to identify a collection's state.
%
% As can be seen from the preceding discussion,
% for people using CM systems some support for determining document properties
% automatically from information provided by the CM system would be helpful,
% if only to prevent mistakes in case of frequently edited documents.
% Solutions for this problem are usually simple to implement but depend on the
% CM system used.
% If one is working with several systems in parallel (in my case I have at
% present to deal with five) this can be very annoying, in particular when
% moving files between systems with different conventions or
% when constructing a document from files held in different systems.
%
% The goal of this package is therefore to offer functionality for determining
% and describing a document's version in such a manner that the dependence on a
% particular CM system is restricted to as few places as possible.
%
% ^^A==========================================================================
%
% \subsection{Assumptions}
%
% A fundamental assumption in this package is that the configuration management
% system you are using is capable of modifying the content of files.
%
% Best results are obtained if your CM system can modify certain
% ``substitution strings'' in a file as follows:
% \begin{itemize}
%   \item If you check in a file to be stored permanently and later someone
%     retrieves this version, strings have been modified at some stage of this
%     chain of events to identify the version fetched.
%   \item If you check out a file for editing it, substitutions occur from
%     which it can be deduced that this copy is in a state between identifiable
%     versions.
% \end{itemize}
% The first of these conditions is more important than the second because,
% if it is not satisfied and the author of the file forgets to edit the file
% appropriately before checkin, this mistake affects more people.
% In contrast, missing functionality for satisfying the second condition is
% only annoying to the person(s) editing the file and is also simple to fix
% manually, even if initially forgotten.
% ^^A Well, there is a minor exception: CM systems which make intermediate
% ^^A versions accessible to others (yes, they exist).
% ^^A However, although this might affect other people besides the author,
% ^^A such system will (or at least should) make it apparent at their interface
% ^^A that this is an intermediate state.
% ^^A In addition, a belated manual fix is also possible in this situation.
%
% ^^A==========================================================================
%
% \subsection{Simple Example}
%
% For those who prefer a simple example of using these macros to reading the
% documentation, here is an example for the case of a document with a single
% source file:
% \begin{quote}\begin{verbatim}
%   ...
%   \usepackage[CMS]{docversion}
%   \setfileinfoCMS{....}
%   ...
%   \setdocversiontimezone{+0000}
%   \date{\documentdate\ (version \documentversion)}
%   ...
%   \begin{document}
%   ...
% \end{verbatim}\end{quote}
% {\sloppypar
% The string ``\texttt{CMS}'' in the |\usepackage| and |\setfileinfoCMS| calls
% must be replaced by a name for which a supplementary file
% \texttt{docversion-\textit{CMS}.def} can be found and which in this example
% must define the macro |\setfileinfoCMS|;
% such files are intended for CM-system-specific macro definitions
% (see section~\ref{options}).
% Irrespective of the CM system used, this document will display its date
% after checkin
% with respect to Coordinated Universal Time (UTC; timezone +0000).
% \par}
%
% ^^A==========================================================================
%
% \subsection{History}
%
% \begin{tabular}{lll}
%   Date& Version& Features\\
%   \hline
%   \noalign{\smallskip}
%   2009-10-06& 1.5& First public release\\
%   2009-10-19& 1.7& Time zone conversions added
% \end{tabular}
%
% ^^A**************************************************************************
%
% \section{Other Packages Needed}
%
% We require the \texttt{ifthen} package:
%    \begin{macrocode}
\ifx\@undefined\setboolean
\RequirePackage{ifthen}
\ifx\@undefined\packagesourceidentification\else
  \packagesourceidentification{ifthen}\fi
\fi
%    \end{macrocode}
% {\sloppypar
% The outer |\ifx| check is used to avoid an unnecessary call to
% |\packagesourceidentification|.
% \par}
%
% ^^A**************************************************************************
%
% \section{Information on the Document}
%
% This section defines an interface for obtaining information about the version
% of the document.
% This interface is meant for composing text to be displayed;
% it consists of definitions yielding information about the document and
% control sequences for configuring how the information should be collected.
%
% The information-yielding definitions may not be executed (expanded or used
% for decisions) before the |\begin{document}| call when the main auxiliary
% file will be read.
% ^^A Because there is no value "uninitialized" for boolean variables.
% Note that this does not forbid using the definitions in calls to macros like
% |\date| which merely store their arguments without executing them.
%
% ^^A==========================================================================
%
% \subsection{Version ID}
%
% \DescribeMacro{\docversionid}
% \DescribeMacro{\setdefaultdocversionid}
% The version identifier of the document is just a string:
%    \begin{macrocode}
\newcommand*{\dv@noversion}{(no version)}
\newcommand*{\docversionid}{\dv@noversion}
\newcommand*{\setdefaultdocversionid}[1]{\def\dv@noversion{#1}}
%    \end{macrocode}
% The convention is that |\docversionid| expands to a sequence of tokens
% without any \TeX\ primitives and without any characters with special category
% codes;
% whether the characters will be displayed as intended depends on the
% output encoding (font encoding) chosen by the author.
% The macro |\setdefaultdocversionid| can be used to provide other text for a
% default version if needed;
% CM-system-specific macro packages may call that macro in order to provide an
% identification which, in case of a newly-created single file, will be
% visually similar to the one determined after checkin.
%
% \DescribeMacro{docisbetweenids}
% A document can be printed or distributed electronically while it is in a
% state between identifiable versions.
% Such a situation should therefore be apparent from the document's version
% information.
% This package defines a boolean variable for this purpose:
%    \begin{macrocode}
\newboolean{docisbetweenids}
\setboolean{docisbetweenids}{true}
%    \end{macrocode}
% The final value for |docisbetweenids| will be deduced from the corresponding
% values for individual files.
%
% \DescribeMacro{docidisnextversion}
% There is at least one CM system which on checkout for editing already inserts
% the version identifier of the \emph{next} version into the file;
% some users may prefer this also for manually-set version identifiers.
% This property should then be available to code displaying the state of a
% document being edited.
%    \begin{macrocode}
\newboolean{docidisnextversion}
\setboolean{docidisnextversion}{false}
%    \end{macrocode}
% The value of |docidisnextversion| is irrelevant if |docisbetweenids| is
% false.
%
% Because there is no unified way to derive the version ID of the document from
% data for more than one source file, the user must be able to set this value.
% The following auxiliary macro will be needed for that and also in other
% places:
%    \begin{macrocode}
\newcommand*{\dv@defharmless}[2]{\xdef#1{#2}\ifx\@empty#1\else
  {\escapechar=-1 \xdef#1{\expandafter\string\csname#2\endcsname}}\fi}
%    \end{macrocode}
% This macro expects as its first argument a control sequence;
% the second argument should expand to a sequence of tokens without
% \TeX\ primitives; the control sequence will be redefined to expand to the
% token sequence given in the second argument but with all special category
% codes replaced by harmless ones.
%
% \DescribeMacro{\setdocversionid}
% The following macro |\setdocversionid| should only be called in the
% document's preamble:
%    \begin{macrocode}
\newboolean{dv@versionspecified}
\setboolean{dv@versionspecified}{false}
\newcommand*{\setdocversionid}[2][false]{\setboolean{dv@versionspecified}{true}%
  \setboolean{docidisnextversion}{#1}\dv@defharmless{\docversionid}{#2}}
%    \end{macrocode}
% The optional first argument to |\setdocversionid| must either be |true| or
% |false| and is copied to |docidisnextversion|;
% this means that \emph{every} call to |\setdocversionid| overrides
% the previous value of |docidisnextversion|.
% The second argument must not expand to contain \TeX\ primitives but may
% contain characters with some special category codes which will be converted
% to harmless codes.
%
% ^^A==========================================================================
%
% \subsection{Date and Time of Last Version}
%
% \DescribeMacro{\docversiondate}\DescribeMacro{\docversiontime}
% The following macros expand to the date and time of the last identifiable
% version of the document;
% this is independent of the value of |docidisnextversion|:
%    \begin{macrocode}
\newcommand*{\docversiondate}{00000101}
\newcommand*{\docversiontime}{000000}
%    \end{macrocode}
% The conventions for the values of these macros are:
% \begin{itemize}
%   \item |\docversiondate| expands to eight digits \texttt{YYYYMMDD} denoting
%     a day in the Gregorian calendar.
%   \item |\docversiontime| expands to six digits \texttt{HHMMSS} denoting a
%     moment on the day |\docversiondate|.
% \end{itemize}
% The values will be derived from information for individual files.
%
% \DescribeMacro{\docversiontimezone}\DescribeMacro{\setdocversiontimezone}
% The time zone for |\docversiondate| and |\docversiontime| can be chosen by
% calling |\setdocversiontimezone|:
%    \begin{macrocode}
\newcommand*{\docversiontimezone}{}
\newcommand*{\setdocversiontimezone}[1]{\edef\docversiontimezone{#1}}
%    \end{macrocode}
% ^^A I might also have explicitly allowed redefining \docversiontimezone.
% ^^A The present solution seems cleaner, though, because it separates input
% ^^A from output control sequences.
% The argument for |\setdocversiontimezone| should expand either to an empty
% token sequence or to an offset given as \texttt{+HHMM} or \texttt{-HHMM};
% the sign of the offset is positive in case of timezones for eastern
% longitudes and negative for western longitudes
% (as in ISO~8601 and RFC~822, opposite to UNIX sign conventions);
% a zero offset should get a plus sign, i.e., \texttt{+0000}.
% The chief purpose of |\docversiontimezone| is to pass information to
% |\setfileinfo| (see section~\ref{file-information}),
% hence any call to |\setdocversiontimezone| should happen before the
% first |\setfileinfo...| call in the document.
% An empty time zone value means that |\setfileinfo| need
% not bother about converting the data to refer to a specific
% time zone.
%
% ^^A==========================================================================
%
% \subsection{Convenience Macros}
%
% While an author may use any of the individual definitions above directly,
% in most cases the information to be displayed is expected to be constructed
% from a particular combination of these building blocks,
% taking the value of |docisbetweenids| into account.
%
% \DescribeMacro{\documentversion}
% The next macro expands to the document's version identifier,
% followed by a suffix if the document is being edited:
%    \begin{macrocode}
\newcommand{\documentversion}{\docversionid
  \ifdocisbetweenids \ifdocidisnextversion-\else+\fi \fi}
%    \end{macrocode}
% Using |\ifdocisbetweenids| etc.\ here instead of |\ifthenelse| gives a
% control sequence where macro expansion results in a sequence of tokens
% without any \TeX\ primitives or special characters.
% The trailing characters denoting a state between versions are chosen because
% they are understandable by themselves and are available in the
% Computer Modern Roman fonts.
% ^^A I had first thought to use "<" or ">" as a prefix in these cases, but
% ^^A they are not available in CMR, and \textless or \textgreater leave TeX
% ^^A primitives behind.
% You might consider defining your own variant or redefining this macro if your
% |\docversionid| values can terminate in characters which can participate in
% ligatures with ``|-|'' or ``|+|''.
%
% This package assumes that |\today| is a macro which generates a
% representation of the date presently stored in |\year|, |\month|, and |\day|
% in some format chosen by the user through a redefinition of |\today|
% (see, e.g., ``babel'' or ``isodate'' for prepackaged solutions).
% The following macro is used to convert from this package's internal
% convention for dates (\texttt{YYYYMMDD}) to the user's preferred
% representation:
%    \begin{macrocode}
\newcommand*{\dv@printdate}[8]{{\year=#1#2#3#4\month=#5#6\day=#7#8\relax\today}}
%    \end{macrocode}
% The |\relax| call is needed in case |\today| starts with a digit after
% macro expansion (remember that |\number| will be expanded).
%
% \DescribeMacro{\documentdate}
% The following macro resolves to the current date in the local time zone if
% the document is between versions and to the version's date if it is not:
%    \begin{macrocode}
\newcommand{\documentdate}{\ifdocisbetweenids\today\else
  \expandafter\dv@printdate\docversiondate\fi}
%    \end{macrocode}
% On expansion, this macro will yield \TeX\ primitives.
%
% \DescribeMacro{\documenttime}
% Similar to |\documentdate|, we also provide a macro |\documenttime|
% resolving to the document's time specification and taking the editing state
% into account:
%    \begin{macrocode}
\newcounter{dv@counter}
\newcommand*{\dv@printtime}[6]{#1#2:#3#4:#5#6}
\newcommand{\documenttime}{\ifdocisbetweenids
    \setcounter{dv@counter}{\time}\divide\c@dv@counter by 60
    \two@digits\c@dv@counter:\multiply\c@dv@counter by -60
    \advance\c@dv@counter by \time\two@digits\c@dv@counter:00%
  \else\expandafter\dv@printtime\docversiontime\fi}
%    \end{macrocode}
% The counter |dv@counter| will also be used in other contexts.
%
% \DescribeMacro{\documenttimezone}
% And finally, a macro for the time zone:
%    \begin{macrocode}
\newcommand{\documenttimezone}{\ifdocisbetweenids LOCAL\else \docversiontimezone \fi}
%    \end{macrocode}
% Note that |\documentdate| and |\documenttime| for a document being edited
% refer to the local time zone.
% I haven't finally decided whether this is a good idea or not,
% but |\documenttimezone| will remain consistent with whatever convention I
% might choose in the future.
%
% ^^A**************************************************************************
%
% \section{Information on Files}	\label{file-information}
%
% This section defines an interface for contributing file-specific information
% to the document information macros defined in the previous section.
% None of the macros here is expected to be called directly from a document.
% Instead, this part is mainly of interest to people implementing
% CM-system-specific extensions to ``docversion''.
%
% The key macro is |\setfileinfo| which is intended to be called from a
% CM-system-specific macro which the author \emph{has} to invoke in the file.
% The CM-system-specific macro should collect the necessary information from
% elsewhere (typically its arguments will contain substitution strings)
% and pass it to |\setfileinfo|.
% See the file \texttt{docversion-RCS.def} for an example.
%
% ^^A =========================================================================
%
% \subsection{Auxiliary Macros}
%
% First we need some definitions:
%    \begin{macrocode}
\newboolean{dv@atleastonebetweenids} \setboolean{dv@atleastonebetweenids}{true}
\newboolean{dv@file@betweenids} \setboolean{dv@file@betweenids}{true}
\newboolean{dv@file@idisnext}
\edef\dv@lastrecordeddate{\docversiondate}
\edef\dv@lastrecordedtime{\docversiontime}
%    \end{macrocode}
% The meaning of the three boolean variables should be apparent from their
% names; the value of the first will be accumulated across all files,
% the other two refer to the current file.
% The two |\dv@lastrecorded...| macros will be used to discover whether
% \TeX\ should be run again in order to show consistent data for
% |\docversiondate| and |\docversiontime| through all of the document.
%
% Then we need a macro for comparing the current values of |\docversiondate|
% and |\docversiontime| with another specification and ensuring that after the
% call the former refer to the later of the two moments (same time zone
% assumed).
%    \begin{macrocode}
\newcommand*{\dv@updatedatetime}[2]{%
  \ifthenelse{\docversiondate < #1}%
    {\xdef\docversiondate{#1}\xdef\docversiontime{#2}}%
    {\ifthenelse{\(\docversiondate = #1\) \and
     \(\docversiontime < #2\)}{\xdef\docversiontime{#2}}{}}%
}
%    \end{macrocode}
% The |\xdef| calls are necessary because this macro will also be called in
% the main auxiliary file (see below).
%
% We also have to handle different time zone specifications for the
% document and a particular file.
% This problem is independent of the CM system used and should therefore be
% solved in this package.
% The solution I've chosen is somewhat pedestrian and is limited to offsets
% which do not alter the date by more than one day;
% this is sufficient for this package, though, and has the additional
% advantage of keeping numbers small and thereby avoiding overflows.
%
% First we need some variables and macros for parsing and composing internal
% date representations:
%    \begin{macrocode}
\newcounter{dv@year}
\newcounter{dv@month}
\newcounter{dv@day}
\def\dv@splitdate#1#2#3#4#5#6#7\dv@end{\setcounter{dv@year}{#1#2#3#4}%
  \setcounter{dv@month}{#5#6}\setcounter{dv@day}{#7}}
\newcommand{\dv@composedate}[1]{\edef#1{\two@digits\c@dv@year
  \two@digits\c@dv@month\two@digits\c@dv@day}}
%    \end{macrocode}
% Then we need macros to convert a time zone offset or an internal time
% designation (\texttt{HHMMSS}) into minutes since 00:00~hours,
% and we also need something to split off the seconds from an internal
% designation (treated separately because time zones can differ only by
% entire minutes):
%    \begin{macrocode}
\def\dv@tztomin#1#2#3#4\dv@end{\setcounter{dv@counter}{#2#3}\multiply
  \c@dv@counter by 60 \advance\c@dv@counter by #4
  \ifx-#1\multiply \c@dv@counter by -1 \fi}
\def\dv@hhmmsstomin#1#2#3#4#5\dv@end{\setcounter{dv@counter}{#1#2}\multiply
  \c@dv@counter by 60 \advance\c@dv@counter by #3#4}
\def\dv@extracts#1#2#3#4#5\dv@end{\setcounter{dv@counter}{#5}}
%    \end{macrocode}
% Note that all three macros expect expanded arguments as input and return the
% result in |dv@counter|.
% We also need the converse operation: it transforms its input value (second
% argument) given as \emph{seconds} since 00:00~hours into the internal
% representation and defines the control sequence passed in the first argument
% as that value:
%    \begin{macrocode}
\newcommand*{\dv@defhhmmss}[2]{%
  \setcounter{dv@counter}{#2}\divide\c@dv@counter by 3600
  \edef\dv@tmp{\two@digits\c@dv@counter}%
  \multiply\c@dv@counter by -60
  \count255=#2\divide\count255 by 60 \advance\count255 by \c@dv@counter
  \edef\dv@tmp{\dv@tmp\two@digits{\count255}}%
  \setcounter{dv@counter}{#2}\divide\c@dv@counter by 60
  \multiply\c@dv@counter by -60
  \advance\c@dv@counter by #2%
  \edef#1{\dv@tmp\two@digits\c@dv@counter}%
}
%    \end{macrocode}
% This macro uses |dv@counter| as a scratch register.
%
% Then we must have a macro which sets |\dv@lastdayinmonth| to the last day
% of the month stored in |dv@month|, taking the value of |dv@year| into account
% in order to recognize leap years (divisible by four and (either divisible
% by 400 or not divisible by 100)):
%    \begin{macrocode}
\newcommand{\dv@setlastdayinmonth}{%
  \c@dv@counter=28	% days in February
  \count255=\c@dv@year \divide\count255 by 4 \multiply\count255 by -4
  \advance\count255 by \c@dv@year
  \ifnum\count255=0
    \count255=\c@dv@year \divide\count255 by 100 \multiply\count255 by -100
    \advance\count255 by \c@dv@year
    \ifnum\count255=0
      \count255=\c@dv@year \divide\count255 by 400 \multiply\count255 by -400
      \advance\count255 by \c@dv@year
      \ifnum\count255=0 \c@dv@counter=29 \fi
    \else \c@dv@counter=29 \fi
  \fi
  \edef\dv@lastdayinmonth{\ifcase\c@dv@month 32\or 31\or \the\c@dv@counter
    \or 31\or 30\or 31\or 30\or 31\or 31\or 30\or 31\or 30\or 31\else 32\fi}%
  \count255=\dv@lastdayinmonth\relax
  \ifnum\count255 > 31 \PackageError{docversion}%
    {Invalid month (\the\c@dv@month)}%
    {You can proceed, but expect the document date to be wrong.}\fi
}
%    \end{macrocode}
% Now we can construct two macros which modify a reference date by one day:
%    \begin{macrocode}
\newcommand*{\dv@previousday}[1]{%
  \expandafter\dv@splitdate#1\dv@end
  \advance\c@dv@day by -1
  \ifnum\c@dv@day < 1
    \advance\c@dv@month by -1
    \ifnum\c@dv@month < 1
      \advance\c@dv@year by -1
      \c@dv@month=12
      \c@dv@day=31
    \else
      \dv@setlastdayinmonth
      \c@dv@day=\dv@lastdayinmonth
    \fi
  \fi
  \dv@composedate{#1}%
}
\newcommand*{\dv@nextday}[1]{%
  \expandafter\dv@splitdate#1\dv@end
  \advance\c@dv@day by 1
  \dv@setlastdayinmonth
  \ifnum\c@dv@day > \dv@lastdayinmonth
    \c@dv@day=1
    \advance\c@dv@month by 1
    \ifnum\c@dv@month > 12
      \advance\c@dv@year by 1
      \c@dv@month=1
    \fi
  \fi
  \dv@composedate{#1}%
}
%    \end{macrocode}
% The argument in both cases is a macro expanding to the reference date.
% This macro will be redefined to refer to the previous or the next day,
% respectively.
%
% The next definitions will be needed in a moment:
%    \begin{macrocode}
\newcounter{dv@min}
\newcommand*{\dv@tzwarning}[2]{\PackageWarning{docversion}{Could not handle
  time zone specification ``#2'' for file ``#1''}}
%    \end{macrocode}
%
% The arguments to the following macro |\dv@handletimezone| are:
% \begin{enumerate}
%   \item The name of the file.		^^A pathname or not is irrelevant.
%   \item A time zone specification as defined for |\docversiontimezone|
%     except that the value may not be empty.
%   \item A control sequence which expands to a date in the format defined for
%     |\docversiondate|, referring to the time zone specified in the second
%     argument.
%   \item A control sequence which expands to a time in the format defined for
%     |\docversiontime|, referring to the time zone specified in the second
%     argument.
% \end{enumerate}
% The macro does nothing if |\docversiontimezone| is empty or
% the given time zone specification agrees with |\docversiontimezone|;
% if there is a discrepancy, the control sequences given for date and time
% will be redefined to refer to |\docversiontimezone|.
%    \begin{macrocode}
\newcommand*{\dv@handletimezone}[4]{%
  \ifx\@empty\docversiontimezone\else
    \expandafter\dv@tztomin\docversiontimezone\dv@end
    \c@dv@min=\c@dv@counter
    \expandafter\dv@tztomin#2\dv@end
    \advance\c@dv@min by -\c@dv@counter
    \ifnum\c@dv@min=0\else
      \ifnum\c@dv@min<-1440 \dv@tzwarning{#1}{#2}\else
	\ifnum\c@dv@min>1439 \dv@tzwarning{#1}{#2}\else
	  \expandafter\dv@hhmmsstomin#4\dv@end
	  \advance\c@dv@min by \c@dv@counter
	  \ifnum\c@dv@min<0
	    \advance\c@dv@min by 1440 \dv@previousday{#3}%
	  \else \ifnum\c@dv@min>1439
	      \advance\c@dv@min by -1440 \dv@nextday{#3}\fi
	  \fi
	  \multiply\c@dv@min by 60
	  \expandafter\dv@extracts#4\dv@end
	  \advance\c@dv@min by \c@dv@counter
	  \dv@defhhmmss{#4}{\c@dv@min}%
	\fi
      \fi
    \fi
  \fi}
%    \end{macrocode}
%
% ^^A =========================================================================
%
% \subsection{Principal Interface}
%
% \DescribeMacro{\setfileinfo}
% The following macro |\setfileinfo| is to be called from CM-system-specific
% macros.
% Its seven arguments are:
% \begin{enumerate}
%   \item File name (should not be a pathname).
%   \item A boolean value denoting whether this file is currently in a state
%     between identifiable versions.
%   \item A version identifier for the file.
%   \item A boolean value denoting whether, in case the file is currently
%     between identifiable versions, the version identifier given as the
%     third argument is the identifier for the next version.
%   \item A time zone value with syntax as defined for |\docversiontimezone|.
%     If the value is empty, the time zone is unspecified and will be assumed
%     to be identical to the current value of |\docversiontimezone|.
%   \item The date of the last checked-in version of this file, specified in
%     the time zone given as the fifth argument.
%   \item The time of the last checked-in version of this file, specified in
%     the time zone given as the fifth argument and referring to the day in the
%     previous argument.
% \end{enumerate}
% Calling this macro (which must occur at the outermost level of grouping) has
% the following consequences:
% \begin{itemize}
%   \sloppy
%   \item If there is only one call to |\setfileinfo| and no call to
%     |\setdocversionid|,
%     |\docversionid| and |docidisnextversion| are set to the corresponding
%     properties of the file.
%     For this to work correctly,
%     the call must occur in the document's preamble.  ^^A because of the ID
%   \item For any number of calls to |\setfileinfo|, |\docversiondate| and
%     |\docversiontime| are set to the latest value across all files.
%   \item If any file is between version IDs, the value of |docisbetweenids|
%     will become |true|, otherwise it will become |false|.
%   \item If the ``sourceid'' package has been included,
%     every call to |\setfileinfo| will generate a \texttt{what}-conforming
%     call to |\sourceidentification| with some of the file data.
% \end{itemize}
%    \begin{macrocode}
\newcommand*{\setfileinfo}[7]{%
  \dv@defharmless{\dv@file@name}{#1}\setboolean{dv@file@betweenids}{#2}%
  \dv@defharmless{\dv@file@version}{#3}\setboolean{dv@file@idisnext}{#4}%
  \ifx\@undefined\dv@file@date
    % First call: copy some information to document macros.
    \setboolean{dv@atleastonebetweenids}{false}%
    \ifthenelse{\boolean{dv@versionspecified}}{}{%
      \edef\docversionid{\dv@file@version}\setboolean{docidisnextversion}{#4}}%
  \else
    % Second or later call: undo first call partially.
    \ifthenelse{\boolean{dv@versionspecified}}{}%
      {\def\docversionid{\dv@noversion}}%
  \fi
  \edef\dv@file@timezone{#5}\edef\dv@file@date{#6}\edef\dv@file@time{#7}%
  % Record version information if possible:
  \ifx\@undefined\sourceidentification\else
    \sourceidentification{\whatstring \dv@file@name\space \dv@file@version\space
      \ifdv@file@betweenids
	\ifdv@file@idisnext\else \dv@file@date\space \dv@file@time\space
	  \ifx\@empty\dv@file@timezone\else \dv@file@timezone\space \fi\fi
	(being modified)%
      \else
	\dv@file@date\space \dv@file@time
	\ifx\@empty\dv@file@timezone\else \space\dv@file@timezone \fi
      \fi}%
  \fi
  % Normalize date and time
  \ifx\@empty\dv@file@timezone\else \dv@handletimezone{\dv@file@name}%
    {\dv@file@timezone}{\dv@file@date}{\dv@file@time}\fi
  % Accumulate editing and modification time information:
  \ifthenelse{\boolean{dv@file@betweenids}}%
    {\setboolean{dv@atleastonebetweenids}{true}}{}%
  \dv@updatedatetime{\dv@file@date}{\dv@file@time}%
}
%    \end{macrocode}
%
% ^^A =========================================================================
%
% \subsection{Accumulated Information}
%
% As usual in case of accumulated information, we have to write the accumulated
% data into the main auxiliary file in order to create consistent values
% throughout the document.
% The user should also be warned if another \TeX\ run is needed in order to
% achieve consistency.
%    \begin{macrocode}
\AtEndDocument{%
  \ifthenelse{\docversiondate = \dv@lastrecordeddate}{%
    \ifthenelse{\docversiontime = \dv@lastrecordedtime}{}{%
      \PackageWarningNoLine{docversion}{The value of
        \string\docversiontime\space is not consistent within the document;
	rerun TeX to correct this}}%
    }{%
    \PackageWarningNoLine{docversion}{The value of \string\docversiondate\space
      is not consistent within the document; rerun TeX to correct this}}%
  \ifthenelse{\(\boolean{docisbetweenids} \and
        \not\boolean{dv@atleastonebetweenids}\) %
      \or \(\not\boolean{docisbetweenids} \and
	\boolean{dv@atleastonebetweenids}\)}%
    {\PackageWarningNoLine{docversion}{The value of ``docisbetweenids'' is
      not consistent within the document; rerun TeX to correct this}}{}%
  \immediate\write\@mainaux{%
    \string\dv@updatedatetime{\docversiondate}{\docversiontime}^^J%
    \string\gdef\string\dv@lastrecordeddate{\docversiondate}^^J%
    \string\gdef\string\dv@lastrecordedtime{\docversiontime}^^J%
    \string\global \ifdv@atleastonebetweenids \string\docisbetweenidstrue\else
      \string\docisbetweenidsfalse\fi
  }}
%    \end{macrocode}
% The |\(...\)| parentheses in |\ifthenelse| for |docisbetweenids| are
% necessary; otherwise the comparison would give a wrong result.
%
% Note that there is no provision for storing |\docversionid| in the file.
% The user is responsible for ensuring that the value has been correctly
% initialized by either calling |\setfileinfo...| (single-file case) or
% |\setdocversionid| before the value of |\docversionid| is used for the first
% time.
% However, if a CM system uses global version identifiers,
% the CM-system-specific extension should offer the functionality of deriving a
% document version ID from a number of file version IDs;
% in that case an appropriate definition should be written to the auxiliary
% file, to be executed only if the user has not called |\setdocversionid| in
% the preamble.
%
% ^^A**************************************************************************
%
% \section{Package Options}	\label{options}
%
% Options are handled last because they identify supplementary macro files to
% be loaded, usually specific to a particular CM system.
%    \begin{macrocode}
\DeclareOption*{\InputIfFileExists{docversion-\CurrentOption.def}{}{%
  \PackageError{docversion}{Could not find the file
    ``docversion-\CurrentOption.def''}{%
    You can proceed, but expect errors if your document uses definitions from
    the missing file.}}}
\ProcessOptions
%    \end{macrocode}
%
% It is recommended that every such supplementary file
% \texttt{docversion-\textit{CMS}.def} should define at least a macro
% \texttt{\char`\\setfileinfo\textit{CMS}} where \texttt{\textit{CMS}} is a
% name for the CM system.
% This macro should receive certain CM-system-specific substitution strings as
% arguments, process them, and call |\setfileinfo| appropriately as described
% in section~\ref{file-information}.
% For an example of such an extension,
% see the file \texttt{docversion-RCS.def}.
%
% If a document is constructed from files using ``docversion'' and residing in
% different CM systems,
% the (single) |\usepackage| call should have an accumulated option list
% containing every option needed by at least one of these systems.
% The preferred system should be last.
%
% ^^A**************************************************************************
%
% \section{Termination}
%
%    \begin{macrocode}
\endinput
%    \end{macrocode}
