From 83266032c26012f162e65d1177e5d3f77eee458e Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 23 Mar 2011 22:59:55 +0000 Subject: new latex package filemod (23mar11) git-svn-id: svn://tug.org/texlive/trunk@21813 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/latex/filemod/README | 20 + Master/texmf-dist/doc/latex/filemod/filemod.pdf | Bin 0 -> 631673 bytes Master/texmf-dist/source/latex/filemod/filemod.dtx | 1277 ++++++++++++++++++++ .../tex/latex/filemod/filemod-expmin.sty | 55 + Master/texmf-dist/tex/latex/filemod/filemod.sty | 334 +++++ Master/tlpkg/bin/tlpkg-ctan-check | 3 +- Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc | 1 + Master/tlpkg/tlpsrc/filemod.tlpsrc | 0 8 files changed, 1689 insertions(+), 1 deletion(-) create mode 100644 Master/texmf-dist/doc/latex/filemod/README create mode 100644 Master/texmf-dist/doc/latex/filemod/filemod.pdf create mode 100644 Master/texmf-dist/source/latex/filemod/filemod.dtx create mode 100644 Master/texmf-dist/tex/latex/filemod/filemod-expmin.sty create mode 100644 Master/texmf-dist/tex/latex/filemod/filemod.sty create mode 100644 Master/tlpkg/tlpsrc/filemod.tlpsrc diff --git a/Master/texmf-dist/doc/latex/filemod/README b/Master/texmf-dist/doc/latex/filemod/README new file mode 100644 index 00000000000..61f1f3455b1 --- /dev/null +++ b/Master/texmf-dist/doc/latex/filemod/README @@ -0,0 +1,20 @@ +The filemod Package +~~~~~~~~~~~~~~~~~~~ +Copyright (C) Martin Scharrer +Version v1.0 -- 2011/03/23 + +This package provides macros to read and compare the modification dates +of files. These files can be .tex files, images or other files as long as they can be +found by the LaTeX compiler. It uses the \pdffilemoddate primitive of pdfLaTeX +to receive the file modification date as PDF date string, parses it and returns +the value to the user. This package will also work for DVI output with recent +versions of the LaTeX compiler which uses pdfLTEX in DVI mode. The functionality +is provided by purely expandable macros or by faster but non-expandable ones. + +Examples: + % Prints file modification date and time of main file + \filemodprint{\jobname} + + % Include newest of a set of files: + \input{\filemodNewest{{file1}{file2}{file3}}} + diff --git a/Master/texmf-dist/doc/latex/filemod/filemod.pdf b/Master/texmf-dist/doc/latex/filemod/filemod.pdf new file mode 100644 index 00000000000..33f844aa323 Binary files /dev/null and b/Master/texmf-dist/doc/latex/filemod/filemod.pdf differ diff --git a/Master/texmf-dist/source/latex/filemod/filemod.dtx b/Master/texmf-dist/source/latex/filemod/filemod.dtx new file mode 100644 index 00000000000..7ec285e7c26 --- /dev/null +++ b/Master/texmf-dist/source/latex/filemod/filemod.dtx @@ -0,0 +1,1277 @@ +% \iffalse meta-comment +%<*COPYRIGHT> +%% Copyright (C) 2011 by Martin Scharrer +%% --------------------------------------------------------------------------- +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `maintained'. +%% +%% The Current Maintainer of this work is Martin Scharrer. +%% +%% This work consists of the files filemod.dtx and filemod.ins +%% and the derived filebase filemod.sty. +% +% \fi +% +% \iffalse +%<*dtx> +\begingroup +% +%<*install> +\input docstrip.tex +\keepsilent +\askforoverwritefalse +\generate{% + \file{filemod.sty} {\nopreamble\from{filemod.dtx} {COPYRIGHT,package,parse,exp,exe,display,aux}}% + \file{filemod-expmin.sty} {\nopreamble\from{filemod.dtx} {COPYRIGHT,expmin}}% +} +% +%\endbatchfile +%<*dtx> +\endgroup +% +% \fi +% +% \iffalse +%<*dtx> +\ProvidesFile{filemod.dtx}[% +% +%\ProvidesPackage{filemod}[% +%\ProvidesPackage{filemod-expmin}[% +%<*dtx|package|expmin> + 2011/03/23 v1.0 +% +%<*dtx|package> + Get and compare file modification times] +% +% Get and compare file modification times (expandable; minimal)] +% +%<*dtx> +\documentclass{ydoc} +\usepackage{filemod}[2011/03/23] +\usepackage{multicol} +\usepackage{csquotes} +\MakeShortMacroArgs\`\relax +\EnableCrossrefs +\CodelineIndex +\RecordChanges +\setcounter{tocdepth}{2} +\begin{document} + \DocInput{filemod.dtx} + \PrintChanges + \PrintIndex +\end{document} +% +% \fi +% +% \CheckSum{566} +% +% \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 \~} +% +% +% \changes{v1.0}{2011/03/23}{First release} +% +% \DoNotIndex{\newcommand,\newenvironment} +% +% \GetFileInfo{filemod.dtx} +% \author{Martin Scharrer} +% \email{martin@scharrer-online.de} +% \maketitle +% +% \begin{abstract} +% This package provides macros to read and compare the modification dates of files. +% These files can be |.tex| files, images or other files as long as they can be found by the \LaTeX\ compiler. +% It uses the |\pdffilemoddate| primitive of pdf\LaTeX\ to receive the file modification date as PDF +% date string, parses it and returns the value to the user. +% This package will also work for DVI output with recent versions of the \LaTeX\ compiler which uses pdf\LaTeX\ in DVI mode. +% The functionality is provided by purely expandable macros or by faster but non-expandable ones. +% \end{abstract} +% +% \begin{multicols}{2} +% \tableofcontents +% \end{multicols} +% +% \section{Introduction} +% This package provides several macros to read and compare the modification dates of files. +% The same functionality is provided by two groups of macros: +% The macros of the first group all start with a lower case letter and are fully expandable. +% This means they can be used in places where a string must be provided, like in `|\input` or `|\includegraphics`. +% Because assignments are not expandable some of these macros, like the ones for comparisons, need to reread and re-parse the +% file modification dates if they are required in more than one place inside the macro. +% +% The macros of the second group all start with a upper case letter and are not expandable because assignments are used internally. +% However, this allows techniques which speed up the processing of these macros, making this macros faster than the expandable counterparts. +% If expandability is not required these macros should be preferred. +% +% +% \section{Usage} +% The following macros are provided by this package: +% +% \subsection{Print File Modification Date and Time} +% The following macros can be used to print (i.e.\ typeset) the file modification date and time of files in the document. +% The \Macro\formatdate and \Macro\formattime macros of the \pkg{datetime}\footnote{CTAN: \url{http://www.ctan.org/pkg/datetime}} can be used in addition to format the dates and times +% in a language specific format. +% See also the \pkg{getfiledate}\footnote{CTAN: \url{http://www.ctan.org/pkg/getfiledate}} package which also prints file modification dates including adding fancy frames around it. +% +% \DescribeMacro{\filemodprint}{<\/filename>} +% Prints the file modifications date and time using `|\filemodparse` and `|\thefilemod`. +% +% +% \DescribeMacro{\filemodprintdate}{<\/filename>} +% Prints the file modifications date using `|\filemodparse` and `|\thefilemoddate`. +% +% +% \DescribeMacro{\filemodprinttime}{<\/filename>} +% Prints the file modifications time using `|\filemodparse` and `|\thefilemodtime`. +% +% +% \DescribeMacro{\thefilemod} +% Reads the date and time as seven arguments and typesets it. This macro can be redefined to a custom format.\\ +% By default it simple uses `|\thefilemoddate` and `|\thefilemodtime` separated by `|\filemodsep` (a space by default): +% \enquote{\filemodprint{\jobname.dtx}} +% +% +% \DescribeMacro{\thefilemoddate} +% Receives the date as three arguments YYYY, MM and DD and typesets it. This macro can be redefined to a custom format.\\ +% Default format: \enquote{\filemodprintdate{\jobname.dtx}} +% +% It could be redefined to use the `|\formatdate` macro of the \pkg{datetime}:\\ +% |\renewcommand*{\thefilemoddate}[3]{\formatdate{#3}{#2}{#1}}| +% +% +% \DescribeMacro{\thefilemodtime} +% Receives the time and timezone as four arguments HH, mm, SS and TZ and typesets it. This macro can be redefined to a custom format.\\ +% Default format: \enquote{\filemodprinttime{\jobname.dtx}} +% +% It could be redefined to use the `|\formattime` macro of the \pkg{datetime}:\\ +% |\renewcommand*{\thefilemodtime}[4]{\formattime{#1}{#2}{#3}}| +% +% +% +% +% \subsection{Get File Modification Date and Time as Number} +% The following macros return both the file modification date and time as an integer number which is in the valid range for \TeX. +% They can be used for numerical operations and are used internally by the comparison macros. +% +% \DescribeMacro{\filemodnumdate}{<\/filename>} +% Expands to an integer of the form |YYYYMMDD| which can be used for numeric comparisons like `|\ifnum`. +% This macros uses `|\filemodparse` and `|\filemodnotexists` will be used if the file does not exist. +% +% \DescribeMacro{\filemodnumtime}{<\/filename>} +% Expands to an integer of the form |HHmmSS| which can be used for numeric comparisons like `|\ifnum`. +% This macros uses `|\filemodparse` and `|\filemodnotexists` will be used if the file does not exist. +% +% \DescribeMacro{\filemodNumdate}{<\/filename>} +% Expands to an integer of the form |YYYYMMDD| which can be used for numeric comparisons like `|\ifnum`. +% Parses the file modification date by itself and will return |00000000| if the file does not exist. +% +% \DescribeMacro{\filemodNumtime}{<\/filename>} +% Expands to an integer of the form |HHmmSS| which can be used for numeric comparisons like `|\ifnum`. +% Parses the file modification date by itself and will return |000000| if the file does not exist. +% +% +% \DescribeMacro{\Filemodgetnum}{<\/filename>} +% Stores the file modification date and time as numbers (|YYYYMMDD| and |HHmmSS|) as well the timezone string +% into the macros `|\filemoddate`, `|\filemodtime` and `|\filemodtz`. +% +% +% +% \subsection{Compare File Modification Date/Time} +% The following macros allow the comparison of the file modification date/time of two files. +% +% \DescribeMacro{\filemodcmp}[]{<\/filename 1>}{<\/filename 2>}{}{}!\optional!{} +% This macro compares the file modification date and time of the two given files and expands to the clause of the +% newest file. An numerical optional argument can be given to determine the outcome if both files have the exact same +% modification date/time (or both do not exists). If `` is 0, no clause will be expanded, i.e.\ the macro expands +% to an empty text. If `` is 1 (default) or 2 the macro expands to the corresponding clause. +% However if `` is 3, the macro will await a third clause and expands to it if both files modification dates are equal. +% +% This macro is fully expandable even when the optional argument is used. However, `<\/filename 1>` must not be equal to "[". +% +% +% \DescribeMacro{\filemodCmp}{<\/filename 1>}{<\/filename 2>}{}{} +% This is a simpler and therefore faster version of `|\filemodcmp`. It is fully expandable, does not take any optional +% arguments and will always expand to the first clause if both file modification dates are equal (or both files do not exist). +% The `|\filemodNumdate` and `|\filemodNumtime` macros are used in the comparison. +% These three macros are also provided by the sub-package \pkg{filemod-expmin}. +% +% +% \DescribeMacro{\Filemodcmp}[]{<\/filename 1>}{<\/filename 2>}{}{}!\optional!{} +% This macro provides the same functionality as `|\filemodcmp`. +% It is not expandable but will be processed faster. The optional +% argument is processed like normally. +% +% \DescribeMacro{\FilemodCmp}[]{<\/filename 1>}{<\/filename 2>} +% This macro will compare the two file modification dates like `|\Filemodcmp` and `|\filemodcmp` but does not take +% the possible clauses as arguments, instead it stores the result into the expandable macro `|\filemodcmpresult` +% which then takes `{}!\linebreak[3]!{}` (and also `{}` if `` was 3) as arguments and expand to the one +% corresponding to the newest file. +% This set of macros gives the user the speed benefit of `|\Filemodcmp` while still be able to use the result in an expandable context. +% +% +% \DescribeMacro{\filemodoptdefault} +% Holds the default number (i.e.\ 1) for the optional argument of the previous and following macros. +% This macro can be redefined with a number or a numeric expression valid for |\ifcase|. It should not contain any +% trailing spaces. Note that some commands only accept 1 or 2 as valid optional argument. +% +% +% +% \subsection{Return Newest or Oldest File from a List} +% The following macros return the newest or oldest file. +% Note that the optional arguments of the following macros should only be either 1 or 2. +% If no optional argument is provided the value of `|\filemodoptdefault` is used. +% +% \DescribeMacro{\filemodnewest}[]{<\/filename 1>}{<\/filename 2>} +% Expands the filename of the newest given file or filename `` if both file modification dates are identical. +% The catcode of the filenames is not changed. +% +% \DescribeMacro{\filemodoldest}[]{<\/filename 1>}{<\/filename 2>} +% Expands the filename of the oldest given file or filename `` if both file modification dates are identical. +% The catcode of the filenames is not changed. +% +% +% \DescribeMacro{\filemodNewest}[]{{<\/filename 1>}{<\/filename 2>}'...'{<\/filename n>}} +% Expands the filename of the newest given file. +% The filename will have catcode 12 except in the case when only one filename was given which is returned unchanged. +% The files are compared in pairs of two in the given order (i.e.\ first 1 and 2 and the result with 3 etc.) +% The optional argument `` can be used to indicate which filename should be used if both file modification dates are identical. +% +% +% \DescribeMacro{\filemodOldest}[]{{<\/filename 1>}{<\/filename 2>}'...'{<\/filename n>}} +% Expands the filename of the oldest given file. +% The filename will have catcode 12 except in the case when only one filename was given which is returned unchanged. +% The files are compared in pairs of two in the given order (i.e.\ first 1 and 2 and the result with 3 etc.) +% The optional argument `` can be used to indicate which filename should be used if both file modification dates are identical. +% +% +% +% \DescribeMacro{\Filemodnewest}[]{<\/filename 1>}{<\/filename 2>} +% Same as `|\filemodnewest` just not expandable but faster. +% Stores the newer of the two file names in `|\filemodresultfile`. Its file modification date and time is stored +% in `|\filemodresultdate` and `|\filemodresulttime`. +% The catcode of the filenames is not changed. +% +% +% \DescribeMacro{\Filemodoldest}[]{<\/filename 1>}{<\/filename 2>} +% Same as `|\filemodoldest` just not expandable but faster. +% Stores the older of the two file names in `|\filemodresultfile`. Its file modification date and time is stored +% in `|\filemodresultdate` and `|\filemodresulttime`. +% The catcode of the filenames is not changed. +% +% +% \DescribeMacro{\FilemodNewest}[]{{<\/filename 1>}{<\/filename 2>}'...'{<\/filename n>}} +% Same as `|\filemodNewest` just not expandable but faster. +% Stores the newest of the given file names in `|\filemodresultfile`. Its file modification date and time is stored +% in `|\filemodresultdate` and `|\filemodresulttime`. +% The catcode of the filenames is not changed. +% +% +% \DescribeMacro{\FilemodOldest}[]{{<\/filename 1>}{<\/filename 2>}'...'{<\/filename n>}} +% Same as `|\filemodOldest` just not expandable but faster. +% Stores the oldest of the given file names in `|\filemodresultfile`. Its file modification date and time is stored +% in `|\filemodresultdate` and `|\filemodresulttime`. +% The catcode of the filenames is not changed. +% +% +% +% +% \subsection{Parsing of the file modification date} +% The format returned by the |\pdffilemoddate| primitive is \enquote{\texttt{D:}} followed by a number in the format \enquote{\texttt{YYYYMMDDHHmmSST}} which needs to be parsed before +% it is useful. The letters have the following meaning: \texttt{Y} = year, \texttt{M} = month, \texttt{D} = day, \texttt{H} = hour, \texttt{mm} = minutes, \texttt{S} = seconds, \texttt{T} or \texttt{TZ} = timezone string. The number of letters indicates the length except for the timezone which is of variable length. +% An example is \enquote{\texttt{\pdffilemoddate{\jobname.dtx}}} which is the file modification date of the source file of this manual. +% Unfortunately this number is to large for TeX to be taken as an integer for numerical comparisons, so it is broken into two numbers (\texttt{YYYYMMDD} and \texttt{HHmmSS}) which are compared +% in multiple steps. +% +% \DescribeMacro{\filemodparse}{}{<\/filename>} +% Parses the file modification datetime of the given file and passes the result to the given macro. +% The macro will receive seven arguments: +% \begin{quote} +% `{}{}{
}{}{}{}{}` +% \end{quote} +% i.e.\ year, month, day, hour, minutes, seconds and the timezone as signed offset +% or `Z` (catcode 12). +% +% +% \DescribeMacro{\filemodnotexists}{} +% This macro will be called by `|\filemodparse` with the original given macro when the given file does not exists. By default +% it contains all zeros except `Z` (catcode 12) as timezone: +% +% \begin{quote} +% `!\#1!{0000}{00}{00}{00}{00}{00}{Z}` +% \end{quote} +% The user can redefine this macro to a different content, e.g.\ to a different fall-back value or to display a warning. +% Note if this macro contains non-expandable code the macros which uses it aren't expandable anymore. +% +% +% +% \subsection{Auxiliary Macros} +% +% \DescribeMacro{\filemodZ} +% Defined to "Z" with catcode 12 as it is returned as timezone. +% This might be useful for comparisons or custom definitions. +% +% \DescribeMacro{\filemodz} +% Let (`|\let`) to "Z" with catcode 12 as it is returned as timezone. +% This might be useful for comparisons or custom definitions. +% +% +% \StopEventually{} +% +% \clearpage +% \section{Implementation} +% +% \iffalse +%<*parse> +% \fi +% \subsection{Parser} +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \begin{macro}{\filemodparse}[2]{Macro or tokens to process result}{file name} +% \begin{macrocode} +\newcommand*\filemodparse[2]{% + \expandafter\filemod@parse\pdffilemoddate{#2}\relax{#1}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@parse}[2]{Expanded file mod date}{Macro} +% \begin{macrocode} +\def\filemod@parse#1\relax#2{% + \ifx\relax#1\relax + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi + {\filemodnotexists{#2}}% + {\filemod@parse@#1\empty{#2}\relax}% +} +% \end{macrocode} +% \end{macro} +% +% +% +% The "D", ":" and "Z" characters are changed to catcode 12 because this is how they appear in the string +% returned by `|\pdffilemoddate`. +% \begin{macrocode} +\begingroup +\@makeother\D +\@makeother\Z +\@makeother: +% \end{macrocode} +% +% \begin{macro}{\filemod@parse@}[9]{Y1}{Y2}{Y3}{Y4}{M1}{M2}{D1}{D2}{Rest} +% \begin{macrocode} +\gdef\filemod@parse@ D:#1#2#3#4#5#6#7#8#9\relax{% + \filemod@parse@@{{#1#2#3#4}{#5#6}{#7#8}}#9\relax +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemodnotexists}[1]{Macro provided to \Macro\filemodparse} +% Macro which is used for non-existing files. +% \begin{macrocode} +\gdef\filemodnotexists#1{% + #1{0000}{00}{00}{00}{00}{00}{Z}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\endgroup +% \end{macrocode} +% +% +% +% \begin{macro}{\filemod@parse@@}[9]{\{YYYY\}\{MM\}\{DD\}}{H1}{H2}{m1}{m2}{S1}{S2}{TZ}{Macro} +% Reads the rest of the file mod date and places the resulting arguments in front of the given macro. +% \begin{macrocode} +\def\filemod@parse@@#1#2#3#4#5#6#7#8\empty#9\relax{% + #9#1{#2#3}{#4#5}{#6#7}{#8}% +} +% \end{macrocode} +% \end{macro} +% +% \iffalse +% +% \fi +% +% \iffalse +%<*expmin> +% \fi +% +% \subsection{Minimal set of expandable Macros} +% +% +% The "D", ":" and "Z" characters are changed to catcode 12 because this is how they appear in the string +% returned by `|\pdffilemoddate`. +% \begin{macrocode} +\begingroup +\@makeother\D +\@makeother\Z +\@makeother: +% \end{macrocode} +% +% \begin{macro}{\filemodNumdate} +% \begin{macrocode} +\gdef\filemodNumdate#1{% + \expandafter\filemod@Numdate\pdffilemoddate{#1}D:00000000000000Z\relax +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\filemod@Numdate} +% \begin{macrocode} +\gdef\filemod@Numdate D:#1#2#3#4#5#6#7#8#9\relax{% + #1#2#3#4#5#6#7#8% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\filemodNumtime} +% \begin{macrocode} +\gdef\filemodNumtime#1{% + \expandafter\filemod@Numtime\pdffilemoddate{#1}D:00000000000000Z\relax +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\filemod@Numtime} +% \begin{macrocode} +\gdef\filemod@Numtime D:#1#2#3#4#5#6#7#8#9\relax{% + \filemod@@Numtime#9\relax +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\filemod@@Numtime} +% \begin{macrocode} +\gdef\filemod@@Numtime#1#2#3#4#5#6#7\relax{% + #1#2#3#4#5#6% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\endgroup +% \end{macrocode} +% +% \begin{macro}{\filemodCmp} +% \begin{macrocode} +\newcommand*\filemodCmp[2]{% + \ifcase0% + \ifnum\filemodNumdate{#2}>\filemodNumdate{#1} 1\else + \ifnum\filemodNumdate{#2}=\filemodNumdate{#1} % + \ifnum\filemodNumtime{#2}>\filemodNumtime{#1} 1\fi + \fi + \fi + \space + \expandafter\@firstoftwo + \or + \expandafter\@secondoftwo + \fi +} +% \end{macrocode} +% \end{macro} +% +% \iffalse +% +% \fi +% +% \iffalse +%<*package> +% \fi +% \begin{macrocode} +\RequirePackage{filemod-expmin} +% \end{macrocode} +% \iffalse +% +% \fi +% +% \iffalse +%<*exp> +% \fi +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Expandable Macros} +% +% \subsubsection{Numeric macros} +% +% \begin{macro}{\filemodnumdate} +% Simply calls the parse macro. +% \begin{macrocode} +\newcommand*\filemodnumdate{\filemodparse\filemod@numdate} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@numdate}[7]{YYYY}{MM}{DD}{HH}{mm}{SS}{TZ} +% \begin{macrocode} +% Gobbles everything except "YYYYMMDD" which is returned as number without the braces. +\def\filemod@numdate#1#2#3#4#5#6#7{#1#2#3} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\filemodnumtime} +% Simply calls the parse macro. +% \begin{macrocode} +\newcommand*\filemodnumtime{\filemodparse\filemod@numtime} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@numtime}[7]{YYYY}{MM}{DD}{HH}{mm}{SS}{TZ} +% Gobbles everything except "HHmmSS" which is returned as number without the braces. +% \begin{macrocode} +\def\filemod@numtime#1#2#3#4#5#6#7{#4#5#6} +% \end{macrocode} +% \end{macro} +% +% +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsubsection{Optional argument handler} +% +% \begin{macro}{\filemod@opt}[3]{Macro to read optional argument when present}{Next macro which receives default optional argument as first normal argument}{\texttt{[} or first mandatory argument} +% This macro checks if an optional argument is present. Here |#1| and |#2| are handlers and |#3| is the first balanced text which followed the macro, i.e.\ either "[" or the first +% mandatory argument. +% The |\ifx| compares "[" and the first token of |#3|. There are three possible cases: +% \begin{enumerate} +% \item If they do not match everything until and including |\else| is skipped. +% Then |\remove@to@nnil@exec| is expanded which removes the following |\@nnil|. This leaves |\empty| and the rest of the \emph{false} clause. +% The |\fi| is removed using |\expandafter| and the trailing |{#3}| is read by |#2| as normal argument. +% \item If |#3| is exactly "[" the |\ifx[#3| part is removed by \TeX. The |\remove@to@nnil@exec| removes the |\@nnil| and the |\remove@to@nnil| because there was nothing before |\@nnil|. +% Therefore |\expandafter#1| is executed which triggers |\else| which removes everything up to and including |\fi|. +% Then the optional argument handler |#1| is expanded which receives the "[" as "{[}" which is then gobbled. +% \item The |#3| starts with "[" but contains more material, i.e.\ was original a mandatory argument. Then |\ifx| expands to the \emph{true} clause and removes +% the first token of |#3|. The |\remove@to@nnil@exec| gobbles the rest of |#3| but reads and reinserts |\remove@to@nnil| which gobbles everything to the next |\@nnil| +% after |\else| and therefore jumps to the \emph{false} clause. This clause is executed like normal, i.e.\ |#2| is called with the default optional argument and |{#3}| as second argument. +% \end{enumerate} +% \begin{macrocode} +\def\filemod@opt#1#2#3{% + \expandafter + \remove@to@nnil@exec + \ifx[#3\@nnil\remove@to@nnil + \expandafter#1% + \else\@nnil\empty + \expandafter#2% + \expandafter\filemodoptdefault + \fi + {#3}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\remove@to@nnil@exec}[2]{Tokens to remove}{Following token} +% Removes everything to |\@nnil| and executes the next token except if |#1| was empty. +% \begin{macrocode} +\def\remove@to@nnil@exec#1\@nnil#2{% + \ifx\@nnil#1\@nnil\else + \expandafter#2 + \fi +} +% \end{macrocode} +% \end{macro} +% +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \subsubsection{Compare file dates} +% +% \begin{macro}{\filemodcmp} +% Compare two file mod dates. +% Calls macros to check for an optional argument in an expandable way. +% \begin{macrocode} +\newcommand*\filemodcmp{% + \filemod@opt\filemod@cmp@opt\filemod@cmp +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemodoptdefault} +% The default optional argument which is used if none is provided. +% \begin{macrocode} +\newcommand*\filemodoptdefault{1} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@cmp@opt}[2]{"[" wrapped in \{\}}{Content of optional argument} +% Removes the brackets from the optional argument. +% \begin{macrocode} +\def\filemod@cmp@opt#1#2]{% + \filemod@cmp{#2}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@cmp} +% This saves several |\expandafter|'s in \Macro\filemod@opt. +% \begin{macrocode} +\def\filemod@cmp{\filemod@@cmp>} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@@cmp}[4]{Compare sign: \texttt{>} or \texttt{<}}{Optional argument}{File name 1}{File name 2} +% Compares the dates and times of the two files. The three cases are (0) file 1 newer than file 2, (1) file 2 newer than file 1, +% (2) both files have the same date. +% +% In (2) the optional argument |#2| determines which clause is executed. +% \begin{macrocode} +\def\filemod@@cmp#1#2#3#4{% + \ifcase0% + \ifnum\filemodnumdate{#4}#1\filemodnumdate{#3} 1\else + \ifnum\filemodnumdate{#4}=\filemodnumdate{#3} % + \ifnum\filemodnumtime{#4}#1\filemodnumtime{#3} 1\else + \ifnum\filemodnumtime{#4}=\filemodnumtime{#3} 2\fi + \fi + \fi + \fi + \space + \csname @firstoft\ifnum#2>2 hree\else wo\fi\expandafter\endcsname + \or + \csname @secondoft\ifnum#2>2 hree\else wo\fi\expandafter\endcsname + \else + \csname @% + \ifcase#2% + gobbletwo% + \or + firstoftwo% + \or + secondoftwo% + \else + thirdofthree% + \fi + \expandafter + \endcsname + \fi +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@firstofthree} +% Expands to the first of the next three arguments. +% \begin{macrocode} +\long\def\@firstofthree#1#2#3{#1} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@secondofthree} +% Expands to the second of the next three arguments. +% \begin{macrocode} +\long\def\@secondofthree#1#2#3{#2} +% \end{macrocode} +% \end{macro} +% +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \subsubsection{Compare file mod times and return file name} +% +% +% \begin{macro}{\filemodnewest} +% First a macro is called to handle an optional argument in an expandable way. +% \begin{macrocode} +\newcommand*\filemodnewest{% + \filemod@opt\filemod@newest@opt\filemod@newest +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@newest@opt}[2]{The "[" wrapped in \{\}}{Content of optional argument} +% Removes braces around the optional argument. +% \begin{macrocode} +\def\filemod@newest@opt#1#2]{% + \filemod@newest{#2}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@newest}[3]{optional argument}{file name 1}{file name 2} +% Uses the normal (internal) compare macro with the file names as the result clauses. +% \begin{macrocode} +\def\filemod@newest#1#2#3{% + \filemod@@cmp>{#1}{#2}{#3}{#2}{#3}% +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{macro}{\filemodoldest} +% First a macro is called to handle an optional argument in an expandable way. +% \begin{macrocode} +\newcommand*\filemodoldest{% + \filemod@opt\filemod@oldest@opt\filemod@oldest +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@oldest@opt}[2]{The "[" wrapped in \{\}}{Content of optional argument} +% Removes braces around the optional argument. +% \begin{macrocode} +\def\filemod@oldest@opt#1#2]{% + \filemod@oldest{#2}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@oldest}[3]{optional argument}{file name 1}{file name 2} +% Uses the normal (internal) compare macro with the file names as the result clauses. +% \begin{macrocode} +\def\filemod@oldest#1#2#3{% + \filemod@@cmp<{#1}{#2}{#3}{#2}{#3}% +} +% \end{macrocode} +% \end{macro} +% +% +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsubsection{Newest and oldest file of a list of files} +% +% \begin{macro}{\filemodNewest}[1]{Tokens between macros and opening brace} +% Checks for an optional argument and substitutes the default if it is missing. +% \begin{macrocode} +\newcommand*\filemodNewest{} +\def\filemodNewest#1#{% + \expandafter\expandafter + \expandafter\@filemodNewest + \csname + @% + \ifx\@nnil#1\@nnil + first% + \else + second% + \fi + oftwo% + \endcsname + {[\filemodoptdefault]}% + {#1}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemodOldest}[1]{Tokens between macros and opening brace} +% Like \Macro\filemodNewest but returns the oldest file in the given list. +% It and its sub-macros are simply copies of minor changes of the |Newest| counterparts. +% This is done for the benefit of expansion speed versus memory usage. +% Future versions might use common code instead. +% \begin{macrocode} +\newcommand*\filemodOldest{} +\def\filemodOldest#1#{% + \expandafter\expandafter + \expandafter\@filemodOldest + \csname + @% + \ifx\@nnil#1\@nnil + first% + \else + second% + \fi + oftwo% + \endcsname + {[\filemodoptdefault]}% + {#1}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@filemodNewest}[2]{Optional argument}{File name list} +% Removes "[]" from first and braces from the second argument (the filename list). +% \begin{macrocode} +\def\@filemodNewest[#1]#2{% + \@@filemodNewest{#1}#2\filemod@end +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@filemodOldest}[2]{Optional argument}{File name list} +% Like \Macro\@filemodNewest. +% \begin{macrocode} +\def\@filemodOldest[#1]#2{% + \@@filemodOldest{#1}#2\filemod@end +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@filemodNewest}[2]{Optional argument}{First file name} +% Reads the optional argument as |#1| and the first filename as |#2|. +% It then reverses the order for the processing loop. +% \begin{macrocode} +\def\@@filemodNewest#1#2{% + \filemod@Newest{#2}{#1}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@filemodOldest}[2]{Optional argument}{First file name} +% \begin{macrocode} +\def\@@filemodOldest#1#2{% + \filemod@Oldest{#2}{#1}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@Newest}[3]{First file name}{Optional argument}{Second file name} +% Checks if the second filename is the end marker. In this case the first filename is returned (i.e.\ expanded to). +% Otherwise expands the compare macro. This is done in one step using |\csname| which is then turned into a string +% which |\| is gobbled. Because of the required expandability the |\escapechar| can't be changed. +% Finally it calls itself recursively with the expanded result. +% \begin{macrocode} +\def\filemod@Newest#1#2#3{% + \iffilemod@end{#3}% + {#1}% + {% + \expandafter\expandafter + \expandafter\expandafter + \expandafter\expandafter + \expandafter\filemod@Newest + \expandafter\expandafter + \expandafter\expandafter + \expandafter\expandafter + \expandafter{% + \expandafter\expandafter + \expandafter\@gobble + \expandafter\string\csname\filemod@@cmp>{#2}{#1}{#3}{#1}{#3}\endcsname}{#2}}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@Oldest}[3]{First file name}{Optional argument}{Second file name} +% Like \Macro\filemode@Newest but with different compare operator. +% \begin{macrocode} +\def\filemod@Oldest#1#2#3{% + \iffilemod@end{#3}% + {#1}% + {% + \expandafter\expandafter + \expandafter\expandafter + \expandafter\expandafter + \expandafter\filemod@Oldest + \expandafter\expandafter + \expandafter\expandafter + \expandafter\expandafter + \expandafter{% + \expandafter\expandafter + \expandafter\@gobble + \expandafter\string\csname\filemod@@cmp<{#2}{#1}{#3}{#1}{#3}\endcsname}{#2}}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\iffilemod@end}[1]{Next filename or end marker} +% Checks if the argument is the \Macro\filemod@end marker. +% \begin{macrocode} +\def\iffilemod@end#1{% + \ifx\filemod@end#1% + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@end} +% Unique end marker which would expand to nothing. +% Could be replaced with |\@nnil|. +% \begin{macrocode} +\def\filemod@end{\@gobble{filemod@end}} +% \end{macrocode} +% \end{macro} +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \iffalse +% +% \fi +% +% +% \iffalse +%<*exe> +% \fi +% +% \subsection{Non-Expandable Macros} +% The following macros are not expandable but contain assignments which must be +% executed. This makes them faster because information can be buffered. +% Some of them can return expandable results. +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsubsection{Get Numeric Representation of File Modification Date} +% +% \begin{macro}{\Filemodgetnum} +% \begin{macrocode} +\newcommand*\Filemodgetnum{\filemodparse\Filemod@getnum} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\Filemod@getnum} +% \begin{macrocode} +\def\Filemod@getnum#1#2#3#4#5#6#7{% + \def\filemoddate{#1#2#3}% + \def\filemodtime{#4#5#6}% + \def\filemodtz{#7}% +} +% \end{macrocode} +% \end{macro} +% +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsubsection{Compare Two File Modification Dates} +% +% \begin{macro}{\Filemodcmp}[1]{Optional argument (default: "1")} +% Calls \Macro\Filemod@cmp to execute the result at the end. +% \begin{macrocode} +\newcommand\Filemodcmp[1][1]{% + \def\filemod@next{\filemodcmpresult}% + \Filemod@cmp{#1}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\FilemodCmp} +% Calls \Macro\Filemod@cmp to not execute the result at the end. +% Instead the user must use \Macro\filemodcmpresult explicitly. +% \begin{macrocode} +\newcommand\FilemodCmp[1][1]{% + \let\filemod@next\empty + \Filemod@cmp{#1}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\Filemod@cmp}[3]{Optional argument}{File name 1}{File name 2} +% Compares both files and defines \Macro\filemodcmpresult so that it expands +% to the winning clause. It might be directly executed at the end or not depending +% on the definition of \Macro\filemod@next which is set by the user level macros +% which use this macro. +% \begin{macrocode} +\def\Filemod@cmp#1#2#3{% + \Filemodgetnum{#2}% + \let\filemoddatea\filemoddate + \let\filemodtimea\filemodtime + \Filemodgetnum{#3}% + \ifcase0% + \ifnum\filemoddate>\filemoddatea\space1\else + \ifnum\filemoddate=\filemoddatea\space + \ifnum\filemodtime>\filemodtimea\space1\else + \ifnum\filemodtime=\filemodtimea\space2\fi + \fi + \fi + \fi + \relax +% \end{macrocode} +% First file is newer: +% \begin{macrocode} + \def\filemodresultfile{#1}% + \ifnum#1>2\relax + \def\filemodcmpresult##1##2##3{##1}% + \else + \let\filemodcmpresult\@firstoftwo + \fi + \or +% \end{macrocode} +% Second file is newer: +% \begin{macrocode} + \def\filemodresultfile{#2}% + \ifnum#1>2\relax + \def\filemodcmpresult##1##2##3{##2}% + \else + \let\filemodcmpresult\@secondoftwo + \fi + \else +% \end{macrocode} +% File mod dates are equal. The optional argument determines which clause is used. +% \begin{macrocode} + \ifcase#1\relax + \let\filemodresultfile\empty + \let\filemodcmpresult\@gobbletwo + \or + \def\filemodresultfile{#1}% + \let\filemodcmpresult\@firstoftwo + \or + \def\filemodresultfile{#2}% + \let\filemodcmpresult\@secondoftwo + \else + \let\filemodresultfile\empty + \let\filemodcmpresult\@thirdofthree + \fi + \fi + \filemod@next +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\filemodcmpresult} +% Defined above. +% \end{macro} +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsubsection{Compare file mod times and return file name} +% +% \begin{macro}{\Filemodnewest} +% Simply uses \Macro\FilemodNewest. +% \begin{macrocode} +\newcommand*\Filemodnewest[3][\filemodoptdefault]{\FilemodNewest[{#1}]{{#2}{#3}}} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\Filemodoldest} +% Simply uses \Macro\FilemodOldest. +% \begin{macrocode} +\newcommand*\Filemodoldest[3][\filemodoptdefault]{\FilemodOldest[{#1}]{{#2}{#3}}} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\FilemodNewest} +% Uses \Macro\Filemod@est with a different compare sign. +% Stores the optional argument for later processing. This avoids the need to pass it around as an argument. +% \begin{macrocode} +\newcommand*\FilemodNewest[2][\filemodoptdefault]{% + \def\filemode@tie{#1}% + \def\filemod@gl{>}% + \Filemod@est#2\filemod@end +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\FilemodOldest} +% Uses \Macro\Filemod@est with a different compare sign. +% Stores the optional argument for later processing. This avoids the need to pass it around as an argument. +% \begin{macrocode} +\newcommand*\FilemodOldest[2][\filemodoptdefault]{% + \def\filemode@tie{#1}% + \def\filemod@gl{<}% + \Filemod@est#2\filemod@end +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\Filemod@est}[1]{file name 1} +% Initiates the macros with the name, date and time of the first file. +% Then the recursive part is called. +% \begin{macrocode} +\def\Filemod@est#1{% + \def\filemodresultfile{#1}% + \Filemodgetnum{#1}% + \let\filemodresultdate\filemoddate + \let\filemodresulttime\filemodtime + \Filemod@@est +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\Filemod@@est}[1]{Next filename or end marker} +% Recursive part. Simple aborts (expands to nothing) if |#1| is the end-marker. +% Then the resulting file is in \Macro\filemodresultfile and the date and time are in +% \Macro\filemodresultdate and \Macro\filemodresulttime, respectively. +% \begin{macrocode} +\def\Filemod@@est#1{% + \iffilemod@end{#1}{}{% + \Filemodgetnum{#1}% + \ifcase0% + \ifnum\filemoddate\filemod@gl\filemodresultdate\space1\else + \ifnum\filemoddate=\filemodresultdate\space + \ifnum\filemodtime\filemod@gl\filemodresulttime\space1\else + \ifnum\filemodtime=\filemodresulttime\space + \ifnum\filemode@tie=1\else 1\fi + \fi + \fi + \fi + \fi + \else + \def\filemodresultfile{#1}% + \let\filemodresultdate\filemoddate + \let\filemodresulttime\filemodtime + \fi + \Filemod@@est + }% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemod@gl} +% Initial value of compare sign. Not really required to be defined here because +% it is defined to the required sign every time it is used. +% \begin{macrocode} +\def\filemod@gl{>} +% \end{macrocode} +% \end{macro} +% +% \iffalse +% +% \fi +% +% \iffalse +%<*display> +% \fi +% +% +% \subsection{Display Macros} +% +% \begin{macro}{\filemodprint} +% \begin{macrocode} +\newcommand*\filemodprint{\filemodparse\thefilemod} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemodprintdate} +% \begin{macrocode} +\newcommand*\filemodprintdate{\filemodparse\the@filemoddate} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\filemodprinttime} +% \begin{macrocode} +\newcommand*\filemodprinttime{\filemodparse\the@filemodtime} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\thefilemod} +% \begin{macrocode} +\newcommand*\thefilemod[7]{% + \thefilemoddate{#1}{#2}{#3}% + \filemodsep + \thefilemodtime{#4}{#5}{#6}{#7}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\let\filemodsep\space +% \end{macrocode} +% +% \begin{macro}{\thefilemoddate} +% \begin{macrocode} +\newcommand*\thefilemoddate[3]{% + #1/#2/#3% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\thefilemodtime} +% \begin{macrocode} +\newcommand*\thefilemodtime[4]{% + #1:#2:#3~#4% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\the@filemoddate} +% \begin{macrocode} +\def\the@filemoddate#1#2#3#4#5#6#7{% + \thefilemoddate{#1}{#2}{#3}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\the@filemodtime} +% \begin{macrocode} +\def\the@filemodtime#1#2#3{% + \thefilemodtime +} +% \end{macrocode} +% \end{macro} +% +% \iffalse +% +% \fi +% +% \iffalse +%<*aux> +% \fi +% +% \subsection{Auxiliary Macros} +% +% The "Z" characters are changed to catcode 12 because this is how they appear in the string +% returned by `|\pdffilemoddate`. +% \begin{macrocode} +\begingroup +\@makeother\D +% \end{macrocode} +% +% \begin{macro}{\filemodZ} +% Holds "Z" with catcode 12 (\emph{other}) like it is returned by `|\pdffilemoddate`. +% Requires use of |\csname| because "Z" isn't a letter at the moment. +% \begin{macrocode} +\expandafter\gdef\csname filemodZ\endcsname{Z}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\filemodz} +% \begin{macrocode} +\let\filemodz=Z\relax +% \end{macrocode} +% \end{macro} +% +% +% \begin{macrocode} +\endgroup +% \end{macrocode} +% +% \iffalse +% +% \fi +% +% \Finale +% \endinput diff --git a/Master/texmf-dist/tex/latex/filemod/filemod-expmin.sty b/Master/texmf-dist/tex/latex/filemod/filemod-expmin.sty new file mode 100644 index 00000000000..beae7a20b60 --- /dev/null +++ b/Master/texmf-dist/tex/latex/filemod/filemod-expmin.sty @@ -0,0 +1,55 @@ +%% Copyright (C) 2011 by Martin Scharrer +%% --------------------------------------------------------------------------- +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `maintained'. +%% +%% The Current Maintainer of this work is Martin Scharrer. +%% +%% This work consists of the files filemod.dtx and filemod.ins +%% and the derived filebase filemod.sty. +\ProvidesPackage{filemod-expmin}[% + 2011/03/23 v1.0 + Get and compare file modification times (expandable; minimal)] +\begingroup +\@makeother\D +\@makeother\Z +\@makeother: +\gdef\filemodNumdate#1{% + \expandafter\filemod@Numdate\pdffilemoddate{#1}D:00000000000000Z\relax +} +\gdef\filemod@Numdate D:#1#2#3#4#5#6#7#8#9\relax{% + #1#2#3#4#5#6#7#8% +} +\gdef\filemodNumtime#1{% + \expandafter\filemod@Numtime\pdffilemoddate{#1}D:00000000000000Z\relax +} +\gdef\filemod@Numtime D:#1#2#3#4#5#6#7#8#9\relax{% + \filemod@@Numtime#9\relax +} +\gdef\filemod@@Numtime#1#2#3#4#5#6#7\relax{% + #1#2#3#4#5#6% +} +\endgroup +\newcommand*\filemodCmp[2]{% + \ifcase0% + \ifnum\filemodNumdate{#2}>\filemodNumdate{#1} 1\else + \ifnum\filemodNumdate{#2}=\filemodNumdate{#1} % + \ifnum\filemodNumtime{#2}>\filemodNumtime{#1} 1\fi + \fi + \fi + \space + \expandafter\@firstoftwo + \or + \expandafter\@secondoftwo + \fi +} +\endinput +%% +%% End of file `filemod-expmin.sty'. diff --git a/Master/texmf-dist/tex/latex/filemod/filemod.sty b/Master/texmf-dist/tex/latex/filemod/filemod.sty new file mode 100644 index 00000000000..cb90336c925 --- /dev/null +++ b/Master/texmf-dist/tex/latex/filemod/filemod.sty @@ -0,0 +1,334 @@ +%% Copyright (C) 2011 by Martin Scharrer +%% --------------------------------------------------------------------------- +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `maintained'. +%% +%% The Current Maintainer of this work is Martin Scharrer. +%% +%% This work consists of the files filemod.dtx and filemod.ins +%% and the derived filebase filemod.sty. +\ProvidesPackage{filemod}[% + 2011/03/23 v1.0 + Get and compare file modification times] +\newcommand*\filemodparse[2]{% + \expandafter\filemod@parse\pdffilemoddate{#2}\relax{#1}% +} +\def\filemod@parse#1\relax#2{% + \ifx\relax#1\relax + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi + {\filemodnotexists{#2}}% + {\filemod@parse@#1\empty{#2}\relax}% +} +\begingroup +\@makeother\D +\@makeother\Z +\@makeother: +\gdef\filemod@parse@ D:#1#2#3#4#5#6#7#8#9\relax{% + \filemod@parse@@{{#1#2#3#4}{#5#6}{#7#8}}#9\relax +} +\gdef\filemodnotexists#1{% + #1{0000}{00}{00}{00}{00}{00}{Z}% +} +\endgroup +\def\filemod@parse@@#1#2#3#4#5#6#7#8\empty#9\relax{% + #9#1{#2#3}{#4#5}{#6#7}{#8}% +} +\RequirePackage{filemod-expmin} +\newcommand*\filemodnumdate{\filemodparse\filemod@numdate} +\def\filemod@numdate#1#2#3#4#5#6#7{#1#2#3} +\newcommand*\filemodnumtime{\filemodparse\filemod@numtime} +\def\filemod@numtime#1#2#3#4#5#6#7{#4#5#6} +\def\filemod@opt#1#2#3{% + \expandafter + \remove@to@nnil@exec + \ifx[#3\@nnil\remove@to@nnil + \expandafter#1% + \else\@nnil\empty + \expandafter#2% + \expandafter\filemodoptdefault + \fi + {#3}% +} +\def\remove@to@nnil@exec#1\@nnil#2{% + \ifx\@nnil#1\@nnil\else + \expandafter#2 + \fi +} +\newcommand*\filemodcmp{% + \filemod@opt\filemod@cmp@opt\filemod@cmp +} +\newcommand*\filemodoptdefault{1} +\def\filemod@cmp@opt#1#2]{% + \filemod@cmp{#2}% +} +\def\filemod@cmp{\filemod@@cmp>} +\def\filemod@@cmp#1#2#3#4{% + \ifcase0% + \ifnum\filemodnumdate{#4}#1\filemodnumdate{#3} 1\else + \ifnum\filemodnumdate{#4}=\filemodnumdate{#3} % + \ifnum\filemodnumtime{#4}#1\filemodnumtime{#3} 1\else + \ifnum\filemodnumtime{#4}=\filemodnumtime{#3} 2\fi + \fi + \fi + \fi + \space + \csname @firstoft\ifnum#2>2 hree\else wo\fi\expandafter\endcsname + \or + \csname @secondoft\ifnum#2>2 hree\else wo\fi\expandafter\endcsname + \else + \csname @% + \ifcase#2% + gobbletwo% + \or + firstoftwo% + \or + secondoftwo% + \else + thirdofthree% + \fi + \expandafter + \endcsname + \fi +} +\long\def\@firstofthree#1#2#3{#1} +\long\def\@secondofthree#1#2#3{#2} +\newcommand*\filemodnewest{% + \filemod@opt\filemod@newest@opt\filemod@newest +} +\def\filemod@newest@opt#1#2]{% + \filemod@newest{#2}% +} +\def\filemod@newest#1#2#3{% + \filemod@@cmp>{#1}{#2}{#3}{#2}{#3}% +} +\newcommand*\filemodoldest{% + \filemod@opt\filemod@oldest@opt\filemod@oldest +} +\def\filemod@oldest@opt#1#2]{% + \filemod@oldest{#2}% +} +\def\filemod@oldest#1#2#3{% + \filemod@@cmp<{#1}{#2}{#3}{#2}{#3}% +} +\newcommand*\filemodNewest{} +\def\filemodNewest#1#{% + \expandafter\expandafter + \expandafter\@filemodNewest + \csname + @% + \ifx\@nnil#1\@nnil + first% + \else + second% + \fi + oftwo% + \endcsname + {[\filemodoptdefault]}% + {#1}% +} +\newcommand*\filemodOldest{} +\def\filemodOldest#1#{% + \expandafter\expandafter + \expandafter\@filemodOldest + \csname + @% + \ifx\@nnil#1\@nnil + first% + \else + second% + \fi + oftwo% + \endcsname + {[\filemodoptdefault]}% + {#1}% +} +\def\@filemodNewest[#1]#2{% + \@@filemodNewest{#1}#2\filemod@end +} +\def\@filemodOldest[#1]#2{% + \@@filemodOldest{#1}#2\filemod@end +} +\def\@@filemodNewest#1#2{% + \filemod@Newest{#2}{#1}% +} +\def\@@filemodOldest#1#2{% + \filemod@Oldest{#2}{#1}% +} +\def\filemod@Newest#1#2#3{% + \iffilemod@end{#3}% + {#1}% + {% + \expandafter\expandafter + \expandafter\expandafter + \expandafter\expandafter + \expandafter\filemod@Newest + \expandafter\expandafter + \expandafter\expandafter + \expandafter\expandafter + \expandafter{% + \expandafter\expandafter + \expandafter\@gobble + \expandafter\string\csname\filemod@@cmp>{#2}{#1}{#3}{#1}{#3}\endcsname}{#2}}% +} +\def\filemod@Oldest#1#2#3{% + \iffilemod@end{#3}% + {#1}% + {% + \expandafter\expandafter + \expandafter\expandafter + \expandafter\expandafter + \expandafter\filemod@Oldest + \expandafter\expandafter + \expandafter\expandafter + \expandafter\expandafter + \expandafter{% + \expandafter\expandafter + \expandafter\@gobble + \expandafter\string\csname\filemod@@cmp<{#2}{#1}{#3}{#1}{#3}\endcsname}{#2}}% +} +\def\iffilemod@end#1{% + \ifx\filemod@end#1% + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi +} +\def\filemod@end{\@gobble{filemod@end}} +\newcommand*\Filemodgetnum{\filemodparse\Filemod@getnum} +\def\Filemod@getnum#1#2#3#4#5#6#7{% + \def\filemoddate{#1#2#3}% + \def\filemodtime{#4#5#6}% + \def\filemodtz{#7}% +} +\newcommand\Filemodcmp[1][1]{% + \def\filemod@next{\filemodcmpresult}% + \Filemod@cmp{#1}% +} +\newcommand\FilemodCmp[1][1]{% + \let\filemod@next\empty + \Filemod@cmp{#1}% +} +\def\Filemod@cmp#1#2#3{% + \Filemodgetnum{#2}% + \let\filemoddatea\filemoddate + \let\filemodtimea\filemodtime + \Filemodgetnum{#3}% + \ifcase0% + \ifnum\filemoddate>\filemoddatea\space1\else + \ifnum\filemoddate=\filemoddatea\space + \ifnum\filemodtime>\filemodtimea\space1\else + \ifnum\filemodtime=\filemodtimea\space2\fi + \fi + \fi + \fi + \relax + \def\filemodresultfile{#1}% + \ifnum#1>2\relax + \def\filemodcmpresult##1##2##3{##1}% + \else + \let\filemodcmpresult\@firstoftwo + \fi + \or + \def\filemodresultfile{#2}% + \ifnum#1>2\relax + \def\filemodcmpresult##1##2##3{##2}% + \else + \let\filemodcmpresult\@secondoftwo + \fi + \else + \ifcase#1\relax + \let\filemodresultfile\empty + \let\filemodcmpresult\@gobbletwo + \or + \def\filemodresultfile{#1}% + \let\filemodcmpresult\@firstoftwo + \or + \def\filemodresultfile{#2}% + \let\filemodcmpresult\@secondoftwo + \else + \let\filemodresultfile\empty + \let\filemodcmpresult\@thirdofthree + \fi + \fi + \filemod@next +} +\newcommand*\Filemodnewest[3][\filemodoptdefault]{\FilemodNewest[{#1}]{{#2}{#3}}} +\newcommand*\Filemodoldest[3][\filemodoptdefault]{\FilemodOldest[{#1}]{{#2}{#3}}} +\newcommand*\FilemodNewest[2][\filemodoptdefault]{% + \def\filemode@tie{#1}% + \def\filemod@gl{>}% + \Filemod@est#2\filemod@end +} +\newcommand*\FilemodOldest[2][\filemodoptdefault]{% + \def\filemode@tie{#1}% + \def\filemod@gl{<}% + \Filemod@est#2\filemod@end +} +\def\Filemod@est#1{% + \def\filemodresultfile{#1}% + \Filemodgetnum{#1}% + \let\filemodresultdate\filemoddate + \let\filemodresulttime\filemodtime + \Filemod@@est +} +\def\Filemod@@est#1{% + \iffilemod@end{#1}{}{% + \Filemodgetnum{#1}% + \ifcase0% + \ifnum\filemoddate\filemod@gl\filemodresultdate\space1\else + \ifnum\filemoddate=\filemodresultdate\space + \ifnum\filemodtime\filemod@gl\filemodresulttime\space1\else + \ifnum\filemodtime=\filemodresulttime\space + \ifnum\filemode@tie=1\else 1\fi + \fi + \fi + \fi + \fi + \else + \def\filemodresultfile{#1}% + \let\filemodresultdate\filemoddate + \let\filemodresulttime\filemodtime + \fi + \Filemod@@est + }% +} +\def\filemod@gl{>} +\newcommand*\filemodprint{\filemodparse\thefilemod} +\newcommand*\filemodprintdate{\filemodparse\the@filemoddate} +\newcommand*\filemodprinttime{\filemodparse\the@filemodtime} +\newcommand*\thefilemod[7]{% + \thefilemoddate{#1}{#2}{#3}% + \filemodsep + \thefilemodtime{#4}{#5}{#6}{#7}% +} +\let\filemodsep\space +\newcommand*\thefilemoddate[3]{% + #1/#2/#3% +} +\newcommand*\thefilemodtime[4]{% + #1:#2:#3~#4% +} +\def\the@filemoddate#1#2#3#4#5#6#7{% + \thefilemoddate{#1}{#2}{#3}% +} +\def\the@filemodtime#1#2#3{% + \thefilemodtime +} +\begingroup +\@makeother\D +\expandafter\gdef\csname filemodZ\endcsname{Z}% +\let\filemodz=Z\relax +\endgroup +\endinput +%% +%% End of file `filemod.sty'. diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 9e9a12d2b6d..7bf20330f96 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -144,7 +144,8 @@ my @TLP_working = qw( fancybox fancyhdr fancynum fancypar fancyref fancytooltips fancyvrb FAQ-en fbithesis fbs featpost fenixpar feyn feynmf fge fig4latex figbas figbib figflow figsize - filecontents filehook fileinfo findhyph fink finstrut first-latex-doc + filecontents filehook fileinfo filemod + findhyph fink finstrut first-latex-doc fix2col fixfoot fixlatvian fixme fixpdfmag fjodor flabels flacards flagderiv flashcards flashmovie flippdf float floatrow diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc index b50cfad39f4..1662a2f4923 100644 --- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc @@ -232,6 +232,7 @@ depend figsize depend filecontents depend filehook depend fileinfo +depend filemod depend fink depend finstrut depend fixfoot diff --git a/Master/tlpkg/tlpsrc/filemod.tlpsrc b/Master/tlpkg/tlpsrc/filemod.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d -- cgit v1.2.3