% \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}