2515 lines
82 KiB
Plaintext
2515 lines
82 KiB
Plaintext
eval '(exit $?0)' && eval 'exec perl -x -S $0 ${1+"$@"}' &&
|
|
eval 'exec perl -x -S $0 $argv:q'
|
|
if 0;
|
|
#!/usr/bin/perl -w
|
|
#!/opt/local/bin/perl -w
|
|
#!/usr/local/bin/perl -w
|
|
|
|
# The above code allows this script to be run under UNIX/LINUX without
|
|
# the need to adjust the path to the perl program in a "shebang" line.
|
|
# (The location of perl changes between different installations, and
|
|
# may even be different when several computers running different
|
|
# flavors of UNIX/LINUX share a copy of latex or other scripts.) The
|
|
# script is started under the default command interpreter sh, and the
|
|
# evals in the first two lines restart the script under perl, and work
|
|
# under various flavors of sh. The -x switch tells perl to start the
|
|
# script at the first #! line containing "perl". The "if 0;" on the
|
|
# 3rd line converts the first two lines into a valid perl statement
|
|
# that does nothing.
|
|
|
|
# To do:
|
|
# Rationalize again handling of include files.
|
|
# Perhaps use kpsewhich to do searches.
|
|
# (How do I avoid getting slowed down too much?)
|
|
# Better parsing of log file for includes.
|
|
# Do I handle the recursive dependence of bbl and aux files sensibly.
|
|
# Perhaps some appropriate touching of the .aux and .bbl files would help?
|
|
# Document the assumptions at each stage of processing algorithm.
|
|
# What are proper command defaults under cygwin?
|
|
# It's got unix-y filenames and some unix-y commands, but the
|
|
# underlying OS is MSWindows.
|
|
# The TeX system may be native Windows or cygwin'ed.
|
|
# Cygwin's perl is cygwin'ed but understands MSWindows filenames.
|
|
# But the user may use a native MSW perl
|
|
# Are TEXINPUTS and BIBINPUTS environment variables written MSW or
|
|
# UNIX style?
|
|
# Probably best to treat as MSWindows, and let the user customize.
|
|
# Maybe not?
|
|
# Option to restart previewer automatically, if it dies under -pvc
|
|
# Test for already running previewer gets wrong answer if another
|
|
# process has the viewed file in its command line
|
|
|
|
$version_num = '3.04';
|
|
$version_details = 'latexmk, John Collins, 24 November 2001';
|
|
|
|
use File::Copy;
|
|
use File::Basename;
|
|
use FileHandle;
|
|
|
|
## Copyright John Collins 1998-2001
|
|
## (collins@phys.psu.edu)
|
|
## (and thanks to David Coppit (david@coppit.org) for suggestions)
|
|
## Copyright Evan McLean
|
|
## (modifications up to version 2)
|
|
## Copyright 1992 by David J. Musliner and The University of Michigan.
|
|
## (original version)
|
|
##
|
|
## This program is free software; you can redistribute it and/or modify
|
|
## it under the terms of the GNU General Public License as published by
|
|
## the Free Software Foundation; either version 2 of the License, or
|
|
## (at your option) any later version.
|
|
##
|
|
## This program is distributed in the hope that it will be useful,
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
## GNU General Public License for more details.
|
|
##
|
|
## You should have received a copy of the GNU General Public License
|
|
## along with this program; if not, write to the Free Software
|
|
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
|
|
|
|
##
|
|
##
|
|
## For Win95 et al.:
|
|
## 1. See specific flags
|
|
## 2. Use of cp -p. DONE
|
|
## 3. Use of '/' for path separator
|
|
## 4. Tail of commands for redirecting stdout and stderr to null. Not needed. DONE
|
|
## 5. diff command. Need to have internal subroutine. Or else
|
|
## a more complicated command for WIN95. DONE
|
|
## 6. Need to check out all calls to system
|
|
## 7. Need to change algorithm for running latex. DONE.
|
|
## 8. Now check that I do the bibtex and index stuff correctly.
|
|
## 9. Convert routines to have arguments.
|
|
## 10. Make dummy .aux.bak. DONE
|
|
## 11. Auto-switch between UNIX and Windows variables. DONE
|
|
## 12. Need to have default filetypes for graphics includes.
|
|
## To make that rational, the find_file routine, etc must be modified,
|
|
## otherwise there will be much duplication of code.
|
|
## 13. Original criterion for needing another run is wrong.
|
|
## I have started to do the changes, but I need to use the algorithm
|
|
## in latexn. DONE
|
|
##
|
|
##
|
|
## NEW FEATURES, since v. 2.0:
|
|
## 1. Correct algorithm for deciding how many times to run latex:
|
|
## based on whether the aux file changes between runs
|
|
## 2. Continuous preview works, and can be of ps file or dvi file
|
|
## 3. pdf creation by pdflatex possible
|
|
## 4. Defaults for commands are OS dependent.
|
|
## 5. Parsing of log file instead of source file is used to
|
|
## obtain dependencies, by default.
|
|
## 6. Meta-commands in source file
|
|
##
|
|
## %#{}raw
|
|
## %#{}begin.raw
|
|
## Start section of raw LaTeX: treat as %#{latex}begin.ignore.
|
|
##
|
|
## %#{}end.raw
|
|
## End section of raw LaTeX: treat as %#{latex}end.ignore.
|
|
##
|
|
## %#{latexmk}ignore
|
|
## %#{latexmk}begin.ignore
|
|
## Start section that is to be ignored in scanning dependencies.
|
|
## %#{latexmk}end.ignore
|
|
## End section that is to be ignored in scanning dependencies.
|
|
##
|
|
## %#{latexmk}include.file FILE
|
|
## Add FILE to list of include files. (FILE is separated from
|
|
## the keyword "include.file" by white space, and is terminated
|
|
## by end-of-line or whitespace.)
|
|
##
|
|
##
|
|
##
|
|
## Modified
|
|
##
|
|
##
|
|
## 24 Nov 2001, John Collins
|
|
## 18 Nov 2001, John Collins
|
|
## Correct parsing of log file for include file: pdftex may put
|
|
## a "{" after the file name instead of "[", so add "{" to
|
|
## the delimiters.
|
|
## 24 Oct 2001, John Collins
|
|
## 23 Oct 2001, John Collins
|
|
## 22 Oct 2001, John Collins
|
|
## Handle multiple aux files with include, at least with log file
|
|
## --silent and --verbose switches
|
|
## 9 Oct 2001, John Collins
|
|
## Try and fix conditions for running makeindex
|
|
## 8 Oct 2001, John Collins
|
|
## Modify #! lines
|
|
## 6 Oct 2001, John Collins
|
|
## Extra switches
|
|
## Remove slide_mode etc
|
|
## 6 Oct 2001, John Collins
|
|
## Correct bugs in search-path handling
|
|
## 1. BIBINPUTS was set equal to TEXINPUTS if the
|
|
## env. variable BIBINPUTS did not exist.
|
|
## 2. Separator should be ';', not ':' under MSDOS.
|
|
## Remove slitex mode. It's obsolete. Slitex no longer exists
|
|
## Miktex now appears to use almost same algorithm for extensions
|
|
## as teTeX. (Change from 1.20d to 1.20e!)
|
|
## Change to GPL, with permission of previous authors
|
|
## 27 Sep 2001, John Collins
|
|
## Correct small bug in print_commands
|
|
## 10 Aug 2001, John Collins
|
|
## Handle differences in extension handling of different
|
|
## versions of tex. So far, OK for MikTeX 1.20d and Web2C 7.3.1
|
|
## Deal with sending of SIGUSR1 to force xdvi to update.
|
|
## Other viewers don't like SIGUSR1, or can't use it, or don't need it.
|
|
## 19 Jul 2001, John Collins
|
|
## Handle cygwin
|
|
## 11,16 Jul 2001, John Collins
|
|
## Fix bug with undefined citations in bibtex:
|
|
## Ignore errors from run of bibtex before 1st latex.
|
|
## 10 Jul 2001, John Collins
|
|
## Correct message
|
|
## 9 Jul 2001, John Collins
|
|
## Correct \providecommand to \\providecommand
|
|
## 11 Jun 2001, John Collins
|
|
## Ver. 3.00. Misc cleanup.
|
|
##
|
|
## 1998-2001, John Collins. Many improvements and fixes.
|
|
##
|
|
## Modified by Evan McLean (no longer available for support)
|
|
## Original script (RCS version 2.3) called "go" written by David J. Musliner
|
|
##
|
|
## 2.0 - Final release, no enhancements. LatexMk is no longer supported
|
|
## by the author.
|
|
## 1.9 - Fixed bug that was introduced in 1.8 with path name fix.
|
|
## - Fixed buglet in man page.
|
|
## 1.8 - Add not about announcement mailling list above.
|
|
## - Added texput.dvi and texput.aux to files deleted with -c and/or
|
|
## the -C options.
|
|
## - Added landscape mode (-l option and a bunch of RC variables).
|
|
## - Added sensing of "\epsfig{file=...}" forms in dependency generation.
|
|
## - Fixed path names when specified tex file is not in the current
|
|
## directory.
|
|
## - Fixed combined use of -pvc and -s options.
|
|
## - Fixed a bunch of speling errors in the source. :-)
|
|
## - Fixed bugs in xdvi patches in contrib directory.
|
|
## 1.7 - Fixed -pvc continuous viewing to reattach to pre-existing
|
|
## process correctly.
|
|
## - Added $pscmd to allow changing process grepping for different
|
|
## systems.
|
|
## 1.6 - Fixed buglet in help message
|
|
## - Fixed bugs in detection of input and include files.
|
|
## 1.5 - Removed test message I accidentally left in version 1.4
|
|
## - Made dvips use -o option instead of stdout redirection as some
|
|
## people had problems with dvips not going to stdout by default.
|
|
## - Fixed bug in input and include file detection
|
|
## - Fixed dependency resolution process so it detects new .toc file
|
|
## and makeindex files properly.
|
|
## - Added dvi and postscript filtering options -dF and -pF.
|
|
## - Added -v version commmand.
|
|
## 1.4 - Fixed bug in -pvc option.
|
|
## - Made "-F" option include non-existant file in the dependency list.
|
|
## (RC variable: $force_include_mode)
|
|
## - Added .lot and .lof files to clean up list of extentions.
|
|
## - Added file "texput.log" to list of files to clean for -c.
|
|
## - LatexMk now handles file names in a similar fashion to latex.
|
|
## The ".tex" extention is no longer enforced.
|
|
## - Added $texfile_search RC variable to look for default files.
|
|
## - Fixed \input and \include so they add ".tex" extention if necessary.
|
|
## - Allow intermixing of file names and options.
|
|
## - Added "-d" and banner options (-bm, -bs, and -bi).
|
|
## (RC variables: $banner, $banner_message, $banner_scale,
|
|
## $banner_intensity, $tmpdir)
|
|
## - Fixed "-r" option to detect an command line syntax errors better.
|
|
## 1.3 - Added "-F" option, patch supplied by Patrick van der Smagt.
|
|
## 1.2 - Added "-C" option.
|
|
## - Added $clean_ext and $clean_full_ext variables for RC files.
|
|
## - Added custom dependency generation capabilities.
|
|
## - Added command line and variable to specify custom RC file.
|
|
## - Added reading of rc file in current directly.
|
|
## 1.1 - Fixed bug where Dependency file generation header is printed
|
|
## rependatively.
|
|
## - Fixed bug where TEXINPUTS path is searched for file that was
|
|
## specified with absolute an pathname.
|
|
## 1.0 - Ripped from script by David J. Musliner (RCS version 2.3) called "go"
|
|
## - Fixed a couple of file naming bugs
|
|
## e.g. when calling latex, left the ".tex" extention off the end
|
|
## of the file name which could do some interesting things
|
|
## with some file names.
|
|
## - Redirected output of dvips. My version of dvips was a filter.
|
|
## - Cleaned up the rc file mumbo jumbo and created a dependency file
|
|
## instead. Include dependencies are always searched for if a
|
|
## dependency file doesn't exist. The -i option regenerates the
|
|
## dependency file.
|
|
## Getting rid of the rc file stuff also gave the advantage of
|
|
## not being restricted to one tex file per directory.
|
|
## - Can specify multiple files on the command line or no files
|
|
## on the command line.
|
|
## - Removed lpr options stuff. I would guess that generally,
|
|
## you always use the same options in which case they can
|
|
## be set up from an rc file with the $lpr variable.
|
|
## - Removed the dviselect stuff. If I ever get time (or money :-) )
|
|
## I might put it back in if I find myself needing it or people
|
|
## express interest in it.
|
|
## - Made it possible to view dvi or postscript file automatically
|
|
## depending on if -ps option selected.
|
|
## - Made specification of dvi file viewer seperate for -pv and -pvc
|
|
## options.
|
|
##-----------------------------------------------------------------------
|
|
|
|
# Set flags for properties of OS:
|
|
if ( $^O eq "MSWin32" ) {
|
|
$msdos = 1;
|
|
$mswin32 = 1;
|
|
$cygwin = 0;
|
|
}
|
|
elsif ( $^O eq "cygwin" ) {
|
|
# UNIX/POSIX emulation under MSWin.
|
|
# Underlying file system is MSWin
|
|
# Perl sees a UNIX-like environment, e.g., for filenames, and
|
|
# running commands detached.
|
|
# Programs (latex, dvips, etc) may be native Win or cygwin.
|
|
$msdos = 1;
|
|
$mswin32 = 1;
|
|
$cygwin = 1;
|
|
}
|
|
else {
|
|
# Assume anything else is UNIX or clone
|
|
$msdos = 0;
|
|
$mswin32 = 0;
|
|
$cygwin = 0;
|
|
}
|
|
|
|
#print "msdos = $msdos\n";
|
|
#print "mswin32 = $mswin32\n";
|
|
|
|
|
|
#Line length in log file that indicates wrapping.
|
|
$log_wrap = 80;
|
|
|
|
#########################################################################
|
|
## Default document processing programs, normally same on all systems:
|
|
|
|
$latex = 'latex';
|
|
$pdflatex = 'pdflatex';
|
|
$latex_silent = 'latex -interaction=batchmode';
|
|
$pdflatex_silent = 'pdflatex -interaction=batchmode';
|
|
|
|
$bibtex = 'bibtex -min-crossrefs=10';
|
|
# Switch(es) to make bibtex silent:
|
|
$bibtex_silent = '-terse';
|
|
|
|
$makeindex = 'makeindex';
|
|
|
|
$dvips = 'dvips';
|
|
$dvips_landscape = 'dvips -tlandscape';
|
|
# Switch(es) to make dvips silent:
|
|
$dvips_silent = '-q';
|
|
|
|
## Which treatment of default extensions and filenames with
|
|
## multiple extensions is used, for given filename on
|
|
## tex/latex's command line? See sub find_basename for the
|
|
## possibilities.
|
|
## Current tex's treat extensions like UNIX teTeX:
|
|
$extension_treatment = 'unix';
|
|
|
|
#########################################################################
|
|
|
|
# System-dependent overrides:
|
|
if ($msdos) {
|
|
## Configuration parameters:
|
|
$tmpdir = "$ENV{TEMP}\\";
|
|
|
|
## List of possibilities for the system-wide initialization file.
|
|
## The first one found (if any) is used.
|
|
@rc_system_files = ( 'C:/latexmk/LatexMk' );
|
|
|
|
$search_path_separator = ';'; # Separator of elements in search_path
|
|
|
|
# For both fptex and miktex, the following makes error messages explicit:
|
|
$latex_silent = 'latex -interaction=batchmode -c-style-errors';
|
|
$pdflatex_silent = 'pdflatex -interaction=batchmode -c-style-errors';
|
|
|
|
# For a pdf-file, "start x.pdf" starts the pdf viewer associated with
|
|
# pdf files, so no program name is needed:
|
|
$pdf_previewer = 'start';
|
|
$ps_previewer = 'start c:/gstools/gsview/gsview32';
|
|
$ps_previewer_landscape = "$ps_previewer";
|
|
$dvi_previewer = 'start yap';
|
|
$dvi_previewer_landscape = "$dvi_previewer";
|
|
# Viewer update methods:
|
|
# 0 => auto update: viewer watches file (e.g., gv)
|
|
# 1 => manual update: user must do something: e.g., click on window.
|
|
# (e.g., ghostview, MSWIN previewers, acroread under UNIX)
|
|
# 2 => send SIGUSR1 signal (xdvi)
|
|
# 3 => viewer can't update, because it locks the file and the file
|
|
# cannot be updated. (acroread under MSWIN)
|
|
$dvi_update_method = 1;
|
|
$ps_update_method = 1;
|
|
$pdf_update_method = 3; # acroread locks the pdf file
|
|
$lpr = 'NONE lpr'; # Use NONE as flag that I am not implementing this
|
|
# The $pscmd below holds a command to list running processes. It
|
|
# is used to find the process ID of the viewer looking at the
|
|
# current output file. The output of the command must include the
|
|
# process number and the command line of the processes, since the
|
|
# relevant process is identified by the name of file to be viewed.
|
|
# Its use is not essential.
|
|
$pscmd = 'NONE pscmd'; # Use NONE as flag that I am not implementing this
|
|
$pid_position = -1; # offset of PID in output of pscmd.
|
|
# Negative means I cannot use ps
|
|
} else {
|
|
# UNIX:
|
|
|
|
## Configuration parameters:
|
|
$tmpdir = '/tmp/';
|
|
|
|
## List of possibilities for the system-wide initialization file.
|
|
## The first one found (if any) is used.
|
|
## Normally on a UNIX it will be in a subdirectory of /opt/local/share or
|
|
## /usr/local/share, depending on the local conventions.
|
|
## /usr/local/lib/latexmk/LatexMk is put in the list for
|
|
## compatibility with older versions of latexmk.
|
|
@rc_system_files =
|
|
( '/opt/local/share/latexmk/LatexMk',
|
|
'/usr/local/share/latexmk/LatexMk',
|
|
'/usr/local/lib/latexmk/LatexMk' );
|
|
|
|
## Which treatment of default extensions and filenames with
|
|
## multiple extensions is used, for given filename on
|
|
## tex/latex's command line? See sub find_basename for the
|
|
## possibilities.
|
|
$search_path_separator = ':'; # Separator of elements in search_path
|
|
## default document processing programs.
|
|
$pdf_previewer = 'start acroread';
|
|
## The following are corrects for the SUNs at phys.psu.edu:
|
|
#$ps_previewer = 'start ghostview';
|
|
#$ps_previewer_landscape = 'start ghostview -swap';
|
|
$ps_previewer = 'start gv -watch';
|
|
$ps_previewer_landscape = 'start gv -swap -watch';
|
|
$dvi_previewer = 'start xdvi';
|
|
$dvi_previewer_landscape = 'start xdvi -paper usr';
|
|
# Viewer update methods:
|
|
# 0 => auto update: viewer watches file (e.g., gv)
|
|
# 1 => manual update: user must do something: e.g., click on window.
|
|
# (e.g., ghostview, MSWIN previewers, acroread under UNIX)
|
|
# 2 => send SIGUSR1 signal (xdvi)
|
|
# 3 => viewer can't update, because it locks the file and the file
|
|
# cannot be updated. (acroread under MSWIN)
|
|
$dvi_update_method = 2; # xdvi responds to SIGUSR1 to update
|
|
$ps_update_method = 0; # gv -watch watches the ps file
|
|
$pdf_update_method = 1;
|
|
$lpr = 'lpr';
|
|
# The $pscmd below holds a command to list running processes. It
|
|
# is used to find the process ID of the viewer looking at the
|
|
# current output file. The output of the command must include the
|
|
# process number and the command line of the processes, since the
|
|
# relevant process is identified by the name of file to be viewed.
|
|
# Uses:
|
|
# 1. In preview_continuous mode, to save running a previewer
|
|
# when one is already running on the relevant file.
|
|
# 2. With xdvi in preview_continuous mode, xdvi must be
|
|
# signalled to make it read a new dvi file.
|
|
#
|
|
# The following works on Solaris, LINUX, HP-UX, IRIX
|
|
# Use -f to get full listing, including command line arguments.
|
|
# Use -u $ENV{CMD} to get all processes started by current user (not just
|
|
# those associated with current terminal), but none of other users'
|
|
# processes.
|
|
$pscmd = "ps -f -u $ENV{USER}";
|
|
$pid_position = 1; # offset of PID in output of pscmd; first item is 0.
|
|
}
|
|
|
|
## default parameters
|
|
$max_repeat = 5; # Maximum times I repeat latex. Normally
|
|
# 3 would be sufficient: 1st run generates aux file,
|
|
# 2nd run picks up aux file, and maybe toc, lof which
|
|
# contain out-of-date information, e.g., wrong page
|
|
# references in toc, lof and index, and unresolved
|
|
# references in the middle of lines. But the
|
|
# formatting is more-or-less correct. On the 3rd
|
|
# run, the page refs etc in toc, lof, etc are about
|
|
# correct, but some slight formatting changes may
|
|
# occur, which mess up page numbers in the toc and lof,
|
|
# Hence a 4th run is conceivably necessary. Needing
|
|
# further runs is an indication of a problem.
|
|
$clean_ext = ""; # space separated extensions of files that are
|
|
# to be deleted when doing cleanup, beyond
|
|
# standard set
|
|
$clean_full_ext = ""; # space separated extensions of files that are
|
|
# to be deleted when doing cleanup_full, beyond
|
|
# standard set and those in $clean_ext
|
|
@cus_dep_list = (); # Custom dependency list
|
|
$texfile_search = ""; #
|
|
|
|
## default flag settings.
|
|
$silent = 0; # silence latex's messages?
|
|
$bibtex_mode = 0; # is there a bibliography needing bibtexing?
|
|
$index_mode = 0; # is there an index needing makeindex run?
|
|
$landscape_mode = 0; # default to portrait mode
|
|
# Which kinds of file do I have requests to make?
|
|
# If no requests at all are made, then I will make dvi file
|
|
# If particular requests are made then other files may also have to be
|
|
# made. E.g., ps file requires a dvi file
|
|
$dvi_mode = 0; # No dvi file requested
|
|
$postscript_mode = 0; # No postscript file requested
|
|
$pdf_mode = 0; # No pdf file requested to be made by pdflatex
|
|
$view = 'default'; # Default preview is of highest of dvi, ps, pdf
|
|
$sleep_time = 2; # time to sleep b/w checks for file changes in -pvc mode
|
|
$banner = 0; # Non-zero if we have a banner to insert
|
|
$banner_scale = 220; # Original default scale
|
|
$banner_intensity = 0.95; # Darkness of the banner message
|
|
$banner_message = 'DRAFT'; # Original default message
|
|
$cleanup_mode = 0; # No cleanup of nonessential files.
|
|
# $cleanup_mode = 0: no cleanup
|
|
# $cleanup_mode = 1: full cleanup
|
|
# $cleanup_mode = 2: cleanup except for dvi and ps
|
|
# $cleanup_mode = 3: cleanup except for dep and aux
|
|
$diagnostics = 0;
|
|
$dvi_filter = ''; # DVI filter command
|
|
$ps_filter = ''; # Postscript filter command
|
|
|
|
$includes_from_log = 1; # =1 to work on log file to find dependencies
|
|
$force_mode = 0; # =1 to force processing past errors
|
|
$force_include_mode = 0;# =1 to ignore non-existent files when making
|
|
# dependency files.
|
|
$go_mode = 0; # =1 to force processing regardless of time-stamps
|
|
$preview_mode = 0;
|
|
$preview_continuous_mode = 0;
|
|
$bib_files = '';
|
|
$updated = 0; # Flags when something has been remade
|
|
|
|
# Used for some results of parsing log file:
|
|
$reference_changed = 0;
|
|
$bad_reference = 0;
|
|
$bad_citation = 0;
|
|
|
|
# get search paths for includes.
|
|
$TEXINPUTS = $ENV{'TEXINPUTS'};
|
|
if (!$TEXINPUTS) { $TEXINPUTS = '.'; }
|
|
$BIBINPUTS = $ENV{'BIBINPUTS'};
|
|
if (!$BIBINPUTS) { $BIBINPUTS = '.'; }
|
|
|
|
@psfigsearchpath = ('.');
|
|
# Convert search paths to arrays:
|
|
@BIBINPUTS = &split_search_path( $search_path_separator, ".", $BIBINPUTS );
|
|
@TEXINPUTS = &split_search_path( $search_path_separator, ".", $TEXINPUTS );
|
|
|
|
warn "This is $version_details, version: $version_num.\n";
|
|
warn "******************************************************************\n";
|
|
warn "**** Report bugs etc to John Collins <collins\@phys.psu.edu>. ****\n";
|
|
warn "******************************************************************\n";
|
|
|
|
## Read rc files.
|
|
SYSTEM_RC_FILE:
|
|
foreach $rc_file ( @rc_system_files )
|
|
{
|
|
# print "===Testing for system rc file \"$rc_file\" ...\n";
|
|
if ( -e $rc_file )
|
|
{
|
|
# print "===Reading system rc file \"$rc_file\" ...\n";
|
|
# Read the system rc file
|
|
do "$rc_file";
|
|
last SYSTEM_RC_FILE;
|
|
}
|
|
}
|
|
|
|
# Read user rc file.
|
|
$rc_file = "$ENV{'HOME'}/.latexmkrc";
|
|
if ( -e $rc_file )
|
|
{
|
|
# Read the user rc file
|
|
do "$rc_file";
|
|
}
|
|
|
|
# Read rc file in current directory.
|
|
$rc_file = "latexmkrc";
|
|
if ( -e $rc_file )
|
|
{
|
|
# Read the user rc file
|
|
do "$rc_file";
|
|
}
|
|
|
|
## Process command line args.
|
|
@the_file_list = ( );
|
|
while ($_ = $ARGV[0])
|
|
{
|
|
shift;
|
|
if (/^-c$/) { $cleanup_mode = 2; }
|
|
elsif (/^--commands$/) { &print_commands; exit; }
|
|
elsif (/^-C$/) { $cleanup_mode = 1; }
|
|
elsif (/^-c1$/) { $cleanup_mode = 3; }
|
|
elsif (/^-d$/) { $banner = 1; }
|
|
elsif (/^-dvi$/) { $dvi_mode = 1; }
|
|
elsif (/^-dvi-$/){ $dvi_mode = 0; }
|
|
elsif (/^-f$/) { $force_mode = 1; }
|
|
elsif (/^-F$/) { $force_include_mode = 1; }
|
|
elsif (/^-g$/) { $go_mode = 1; }
|
|
elsif ( /^-h$/ || /^--help$/ ) { &print_help; }
|
|
elsif (/^-il$/) { $includes_from_log = 1; }
|
|
elsif (/^-it$/) { $includes_from_log = 0; }
|
|
elsif (/^-i$/) { $generate_and_save_includes = 1; }
|
|
elsif (/^-I$/) { $force_generate_and_save_includes = 1; }
|
|
elsif (/^--diagnostics/) { $diagnostics = 1; }
|
|
elsif (/^-l$/) { $landscape_mode = 1; }
|
|
elsif (/^-pvc$/) { $preview_continuous_mode = 1; }
|
|
elsif (/^-pv$/) { $preview_mode = 1; }
|
|
elsif (/^-pdf$/) { $pdf_mode = 1; }
|
|
elsif (/^-pdf-$/){ $pdf_mode = 0; }
|
|
elsif (/^-ps$/) { $postscript_mode = 1; }
|
|
elsif (/^-ps-$/) { $postscript_mode = 0; }
|
|
elsif (/^-p$/) { $printout_mode = 1; }
|
|
elsif (/^-p-$/) { $printout_mode = 0; }
|
|
elsif (/^--silent$/) { $silent = 1; }
|
|
elsif (/^-v$/ || /^--version$/) { warn "\nLatexmk $version_num\n"; exit; }
|
|
elsif (/^--verbose$/) { $silent = 0; }
|
|
elsif (/^--view=default$/) { $view = "default";}
|
|
elsif (/^--view=dvi$/) { $view = "dvi";}
|
|
elsif (/^--view=ps$/) { $view = "ps";}
|
|
elsif (/^--view=pdf$/) { $view = "pdf";}
|
|
elsif (/^-r$/) { if ( $ARGV[0] eq '' ) {
|
|
warn "Latexmk: No RC file specified\n"; &print_help; }
|
|
if ( -e $ARGV[0] ) {
|
|
do "$ARGV[0]"; } else {
|
|
die "Latexmk: RC file [$ARGV[0]] does not exist\n"; }
|
|
shift; }
|
|
elsif (/^-bm$/) { if ( $ARGV[0] eq '' ) {
|
|
warn "Latexmk: No message specified\n"; &print_help; }
|
|
$banner = 1; $banner_message = $ARGV[0];
|
|
shift; }
|
|
elsif (/^-bi$/) { if ( $ARGV[0] eq '' ) {
|
|
warn "Latexmk: No intensity specified\n"; &print_help; }
|
|
$banner_intensity = $ARGV[0];
|
|
shift; }
|
|
elsif (/^-bs$/) { if ( $ARGV[0] eq '' ) {
|
|
warn "Latexmk: No scale specified\n"; &print_help; }
|
|
$banner_scale = $ARGV[0];
|
|
shift; }
|
|
elsif (/^-dF$/) { if ( $ARGV[0] eq '' ) {
|
|
warn "Latexmk: No dvi filter specified\n"; &print_help; }
|
|
$dvi_filter = $ARGV[0];
|
|
shift; }
|
|
elsif (/^-pF$/) { if ( $ARGV[0] eq '' ) {
|
|
warn "Latexmk: No ps filter specified\n"; &print_help; }
|
|
$ps_filter = $ARGV[0];
|
|
shift; }
|
|
elsif (/^-/) { warn "Latexmk: $_ bad option\n"; }
|
|
else { @the_file_list = ( @the_file_list, $_ ); }
|
|
}
|
|
@ARGV = @the_file_list;
|
|
# Check we haven't selected mutually exclusive modes.
|
|
# Note that -c overides all other options, but doesn't cause
|
|
# an error if they are selected.
|
|
if (($printout_mode && ( $preview_mode || $preview_continuous_mode ))
|
|
|| ( $preview_mode && $preview_continuous_mode ))
|
|
{
|
|
warn "Latexmk: Conflicting options (-p, -pv, -pvc) selected\n";
|
|
&print_help;
|
|
}
|
|
|
|
|
|
# If seleced a previewer mode, make sure one and only one filename was specified
|
|
if ($preview_mode || $preview_continuous_mode)
|
|
{
|
|
if ($#ARGV != 0)
|
|
{
|
|
warn"Latexmk: Need to specify one and only one filename for previewer mode\n";
|
|
&print_help;
|
|
}
|
|
}
|
|
|
|
# If no files specified, try and find some
|
|
if ( !@ARGV )
|
|
{
|
|
@ARGV=<*.tex $texfile_search>;
|
|
}
|
|
# If still no files, exit.
|
|
if ( !@ARGV )
|
|
{
|
|
warn "Latexmk: No file name specified\n";
|
|
&print_help; ## print_help function exits.
|
|
}
|
|
|
|
if ( $silent ) { $bibtex .= " $bibtex_silent"; }
|
|
|
|
# If landscape mode, change modes
|
|
if ( $landscape_mode )
|
|
{
|
|
$dvips = $dvips_landscape;
|
|
$dvi_previewer = $dvi_previewer_landscape;
|
|
$ps_previewer = $ps_previewer_landscape;
|
|
}
|
|
if ( $silent ) { $dvips .= " $dvips_silent"; }
|
|
|
|
# Which files do we need to make?
|
|
$need_dvi = 0;
|
|
$need_ps = 0;
|
|
$need_pdf = 0;
|
|
# If default viewer requested, use "highest" of dvi, ps and pdf
|
|
# that was requested by user:
|
|
if ( $view eq "default" ) {
|
|
# Default:
|
|
$view = "dvi";
|
|
if ( $postscript_mode ) { $view = "ps"; }
|
|
if ( $pdf_mode ) { $view = "pdf"; }
|
|
}
|
|
|
|
$file_requested = 0;
|
|
if ( $dvi_mode ) {$need_dvi = 1; $file_requested = 1; }
|
|
if ( $postscript_mode ) {$need_ps = 1; $file_requested = 1; }
|
|
if ( $pdf_mode ) {$need_pdf = 1; $file_requested = 1; }
|
|
if ( $view eq "dvi" ) {$need_dvi = 1; }
|
|
if ( $view eq "ps" ) {$need_ps = 1; }
|
|
if ( $view eq "pdf" ) {$need_pdf = 1; }
|
|
|
|
|
|
# If no files requested, default to dvi:
|
|
if ( ! $file_requested ) { $need_dvi = 1; }
|
|
|
|
if ( length($dvi_filter) != 0 ) {$need_dvi = 1; }
|
|
if ( length($ps_filter) != 0 ) {$need_ps = 1; }
|
|
|
|
# banner => need ps
|
|
if ( $banner ) { $need_ps = 1; }
|
|
# printout => need ps
|
|
if ( $printout_mode ) { $need_ps = 1; }
|
|
|
|
# postscript file => dvi file needed.
|
|
if ( $need_ps ) { $need_dvi = 1; }
|
|
|
|
# Process for each file.
|
|
# The value of $bibtex_mode set in an initialization file may get
|
|
# overridden, during file processing, so save it:
|
|
$save_bibtex_mode = $bibtex_mode;
|
|
foreach $filename ( @ARGV )
|
|
{
|
|
$bibtex_mode = $save_bibtex_mode;
|
|
## remove extention from filename if was given.
|
|
if ( &find_basename($filename, $root_filename, $texfile_name) )
|
|
{
|
|
die "Latexmk: Could not find file [$texfile_name]\n";
|
|
}
|
|
|
|
if ($cleanup_mode > 0)
|
|
{
|
|
## Do clean if necessary
|
|
&cleanup_basic;
|
|
if ( $cleanup_mode != 2 ) { &cleanup_dvi_ps_pdf; }
|
|
if ( $cleanup_mode != 3 ) { &cleanup_aux_dep; }
|
|
}
|
|
else
|
|
{
|
|
#Default aux file list:
|
|
@aux_files = ("$root_filename.aux");
|
|
## Make file. ##
|
|
## Find includes.
|
|
$includes = '';
|
|
$read_depend = 0; # True to read depend file, false to generate it.
|
|
$dep_file = "$root_filename.dep";
|
|
|
|
## Figure out if we read the dependency file or generate a new one.
|
|
if ( ! $force_generate_and_save_includes )
|
|
{
|
|
if ( $generate_and_save_includes )
|
|
{
|
|
if ( -e $dep_file )
|
|
{
|
|
# Compare timestamp of dependency file and root tex file.
|
|
$dep_mtime = &get_mtime("$dep_file");
|
|
$tex_mtime = &get_mtime("$texfile_name");
|
|
if ( $tex_mtime < $dep_mtime )
|
|
{
|
|
$read_depend = 1;
|
|
}
|
|
}
|
|
}
|
|
elsif ( -e $dep_file ) # If dependency file already exists.
|
|
{
|
|
$read_depend = 1;
|
|
}
|
|
}
|
|
|
|
if ( $includes_from_log )
|
|
{
|
|
$got_includes_from_log = &parse_log;
|
|
if ( $got_includes_from_log ) {
|
|
@aux_files = @aux_files1;
|
|
}
|
|
$includes = $includes_in_log;
|
|
if ( $force_generate_and_save_includes
|
|
|| ($generate_and_save_includes && $read_depend == 0 )
|
|
)
|
|
{
|
|
&update_depend_file;
|
|
}
|
|
}
|
|
elsif ( $read_depend )
|
|
{
|
|
# Read the dependency file
|
|
open(dep_file) || die "Latexmk: Couldn't open dependency file [$root_filename.dep]\n";
|
|
while(<dep_file>) { eval; }
|
|
close(dep_file);
|
|
}
|
|
else
|
|
{
|
|
# Generate dependency file.
|
|
&scan_for_includes("$texfile_name");
|
|
&update_depend_file;
|
|
}
|
|
|
|
## put root tex file into list of includes.
|
|
$includes .= " $texfile_name";
|
|
|
|
#************************************************************
|
|
|
|
# Ensure bbl file up-to-date.
|
|
# Also remake the bbl file if there is a bad citation, or if we
|
|
# use go_mode (which says to remake everything)
|
|
# The call to &make_bbl will also remake the bbl file if it is
|
|
# out-of-date with respect to the bib files
|
|
# But ignore the return code from make_bbl, since the bbl file depends
|
|
# on the aux file, which may in fact be out of date if the tex file has
|
|
# changed, and we are about to re-latex it.
|
|
if ($bibtex_mode) {
|
|
&make_bbl($bad_citation || $go_mode);
|
|
}
|
|
|
|
# Similarly for ind file. This is simpler because it only depends
|
|
# on the idx file.
|
|
if ($index_mode) {
|
|
&make_ind($go_mode);
|
|
}
|
|
|
|
&make_files;
|
|
if ( $preview_continuous_mode) { &make_preview_continous; }
|
|
if ( $preview_mode ) { &make_preview; }
|
|
if ( $printout_mode) { &make_printout; }
|
|
}
|
|
}
|
|
|
|
#************************************************************
|
|
#### Subroutines
|
|
#************************************************************
|
|
|
|
sub make_files
|
|
{
|
|
&make_dependents($includes);
|
|
if ($need_dvi)
|
|
{
|
|
&make_latex_dvi_pdf('dvi');
|
|
&make_dvi_filtered;
|
|
}
|
|
if ( $need_ps ) {&make_postscript; }
|
|
if ( $need_pdf ) {&make_latex_dvi_pdf('pdf'); }
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub make_latex_dvi_pdf
|
|
{
|
|
my $dest_type = $_[0];
|
|
my $dest;
|
|
my $processor;
|
|
if ( $dest_type eq 'dvi' ) {
|
|
$dest = "$root_filename.dvi";
|
|
if ( $silent ) { $processor = " $latex_silent"; }
|
|
else { $processor = $latex; }
|
|
} elsif ( $dest_type eq 'pdf' ) {
|
|
$dest = "$root_filename.pdf";
|
|
if ( $silent ) { $processor = " $pdflatex_silent"; }
|
|
else { $processor = $pdflatex; }
|
|
} else {
|
|
die("Latexmk: BUG: undefined destination type $dest_type in make_latex_dvi_pdf\n");
|
|
}
|
|
|
|
|
|
## get initial last modified times.
|
|
my $tex_mtime = &get_latest_mtime($includes);
|
|
my $dest_mtime= &get_mtime("$dest");
|
|
my $aux_mtime = &get_mtime("$root_filename.aux");
|
|
my $bib_mtime = &get_latest_mtime($bib_files);
|
|
my $bbl_mtime = &get_mtime("$root_filename.bbl");
|
|
my $ilg_mtime = &get_mtime("$root_filename.ilg");
|
|
my $ind_mtime = &get_mtime("$root_filename.ind");
|
|
|
|
## - if no dvi file, or .aux older than tex file or bib file, run latex.
|
|
if ( $go_mode
|
|
|| !(-e "$root_filename.aux")
|
|
|| ($aux_mtime < $tex_mtime)
|
|
|| !(-e "$dest")
|
|
|| ( (-e "$root_filename.bbl") && ($aux_mtime < $bbl_mtime) )
|
|
|| ($dest_mtime < $tex_mtime)
|
|
|| ( (-e "$root_filename.ilg") && ($aux_mtime < $ilg_mtime) )
|
|
|| ( (-e "$root_filename.ind") && ($aux_mtime < $ind_mtime) )
|
|
|| ( $includes_from_log && !$got_includes_from_log )
|
|
)
|
|
{ &build_latex_dvi_pdf($processor);
|
|
}
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub build_latex_dvi_pdf {
|
|
# Argument: 0 = processor (e.g., 'latex' or 'pdflatex')
|
|
#
|
|
# I don't need to know whether I run latex or pdflatex!
|
|
#
|
|
# Repeat running latex as many times as needed to resolve cross
|
|
# references, also running bibtex and makeindex as necessary. The
|
|
# algorithm for determining whether latex needs to be run again is
|
|
# whether certain generated files have changed since the previous
|
|
# run. A limit (contained in $max_repeat) is applied on the
|
|
# number of runs, to avoid infinite loops in pathological cases or
|
|
# in the case of a bug. $max_repeat should be at least 4, to
|
|
# allow for the maximum number of repeats under normal
|
|
# circumstances, which is 3, plus one for unusual cases of page
|
|
# breaks moving around.
|
|
#
|
|
# The criterion for needing a rerun is that one or both of the
|
|
# .aux file and the .idx file has changed. To prove this: observe
|
|
# that reruns are necessary because information that needs to be
|
|
# read in from a file does not correspond to the current
|
|
# conditions. The relevant files are: the .aux file, and possibly
|
|
# one or more of: the index files, the table of contents file
|
|
# (.toc), the list of figures file (.lof), the list of tables file
|
|
# (.lot). The information read in is: cross reference
|
|
# definitions, page references, tables of contents, figures and
|
|
# tables. Note that the list of figures (for example) may itself
|
|
# contain undefined references or incorrect page references. If
|
|
# there is any incorrectness, changed information will be written
|
|
# to the corresponding file on the current run, and therefore one
|
|
# or more of the auxiliary files will have changed.
|
|
#
|
|
# In fact the lines in the .toc, .lof and .lot files correspond to
|
|
# entries in the .aux file, so it is not necessary to check the
|
|
# .toc, .lof and .lot files (if any). Therefore a correct
|
|
# algorithm is to require a rerun if either of the following is
|
|
# true:
|
|
#
|
|
# 1. The .aux file has changed from the previous version.
|
|
# 2. The .idx file has changed from the previous version.
|
|
#
|
|
# Of course, if a previous version of one of these files did not
|
|
# exist (as on a first run), then that implies a rerun is
|
|
# necessary. And if a .aux file or a .idx file is not generated,
|
|
# there is no point in testing it against a previous version.
|
|
#
|
|
# Assume on entry that the .ind and .bbl files are up-to-date with
|
|
# respect to the already existing .idx and .aux files. This will
|
|
# be the case if latexmk was used to make them.
|
|
|
|
my $aux_file;
|
|
my $processor = $_[0];
|
|
|
|
my $count_latex = 0;
|
|
my $repeat = 0;
|
|
|
|
do {
|
|
# Arrival here means that a new run of latex/pdflatex is requested
|
|
# Assume that the .ind file (if any) corresponds to the .idx file
|
|
# from the previous run
|
|
# and that the .bbl file (if any) correspons to the .aux file from
|
|
# the previous run.
|
|
|
|
$repeat = 0; # Assume no repeat necessary.
|
|
$count_latex++; # Count the number of passes through latex
|
|
warn "------------\nRun number $count_latex of ",
|
|
"$processor [$texfile_name]\n------------\n";
|
|
foreach $aux_file (@aux_files)
|
|
{
|
|
if ( -e $aux_file ) {
|
|
warn "Saving old .aux file \"$aux_file\"\n" if !$silent;
|
|
copy_file ( "$aux_file", "$aux_file.bak");
|
|
}
|
|
}
|
|
if ( (! -e "$root_filename.aux") && (! -e "$root_filename.aux.bak") ) {
|
|
# Arrive here if neither of the .aux and the .aux.bak files exists
|
|
# for the base file.
|
|
# I make minimal .aux.bak file, containing a single line "\relax "
|
|
# This is the same as the aux file generated for a latex file
|
|
# which does not need any cross references, etc. Generating this
|
|
# .aux.bak file will save a pass through latex on simple files.
|
|
local $aux_bak_file = ">$root_filename.aux.bak";
|
|
open(aux_bak_file) || die "Cannot write file $aux_bak_file\n";
|
|
print aux_bak_file "\\relax \n";
|
|
close(aux_bak_file);
|
|
}
|
|
if ( (-e "$root_filename.aux") && $bibtex_mode) {
|
|
# We have assumed that the bbl file is up-to-date
|
|
# with respect to the previous aux file. However
|
|
# it may be out-of-date with respect to the bib file(s).
|
|
# So run bibtex in this case
|
|
my $bibtex_return_code = &make_bbl(0);
|
|
if ( ($bibtex_return_code eq 2) && !$force_mode )
|
|
{
|
|
&exit_msg('Bibtex reported an error');
|
|
}
|
|
}
|
|
|
|
if ( -e "$root_filename.idx" ) {
|
|
warn "Saving old .idx file\n" if !$silent;
|
|
copy_file ( "$root_filename.idx", "$root_filename.idx.bak");
|
|
}
|
|
|
|
my $return = &Run("$processor $texfile_name");
|
|
$updated = 1; # Flag that some dependent file has been remade
|
|
if ($return) {
|
|
if (!$force_mode) {
|
|
&exit_msg('Latex encountered an error',1);
|
|
}
|
|
elsif ($silent) {
|
|
# User may not have seen error
|
|
warn "====Latex encountered an error: see .log file====\n";
|
|
}
|
|
}
|
|
$return = &parse_log;
|
|
my $aux_changed = 0;
|
|
my $idx_changed = 0;
|
|
|
|
if ( $return == 0 )
|
|
{
|
|
&exit_msg('Latex failed to generate a log file', 1);
|
|
}
|
|
if ( $includes_from_log )
|
|
{
|
|
$got_includes_from_log = 1;
|
|
$includes = $includes_in_log;
|
|
if ( @aux_files ne @aux_files1 ){
|
|
$aux_changed = 1;
|
|
warn "List of .aux files has changed. ",
|
|
"I must run latex again\n";
|
|
@aux_files = @aux_files1;
|
|
}
|
|
}
|
|
|
|
if ( !$aux_changed )
|
|
{
|
|
# Look for changes in the individual aux files.
|
|
foreach $aux_file (@aux_files)
|
|
{
|
|
if ( -e "$aux_file" ) {
|
|
if ( &diff ("$aux_file", "$aux_file.bak") ) {
|
|
warn ".aux file \"$aux_file\" changed. ",
|
|
"I must run latex again\n";
|
|
$aux_changed = 1;
|
|
last;
|
|
}
|
|
else {
|
|
warn "File \"$aux_file\" has not changed, ",
|
|
"so it is valid\n" if !$silent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( (!-e "$root_filename.aux") && (-e "$root_filename.aux.bak") ) {
|
|
warn "No aux file was generated, so I don't need .aux.bak file\n"
|
|
if !$silent;
|
|
unlink ("$root_filename.aux.bak");
|
|
}
|
|
|
|
if ( (-e "$root_filename.aux") && $aux_changed && $bibtex_mode) {
|
|
# Note running bibtex only makes sense if the aux file exists.
|
|
# If any aux file has changed, then the citations may
|
|
# have changed and we must run bibtex.
|
|
# The argument to &make_bbl forces this.
|
|
# &make_bbl also checks whether the bbl file is
|
|
# out-of-date with respect to the bib files.
|
|
my $bibtex_return_code = &make_bbl($aux_changed);
|
|
if ( ($bibtex_return_code eq 2) && !$force_mode )
|
|
{
|
|
&exit_msg('Bibtex reported an error');
|
|
}
|
|
}
|
|
|
|
if ( -e "$root_filename.idx" ) {
|
|
if ( &diff ("$root_filename.idx", "$root_filename.idx.bak") ) {
|
|
warn "The .idx file changed. I must run latex again\n";
|
|
# idx file exists and has changed
|
|
# implies idx file written
|
|
# implies indexing being used
|
|
$index_mode = 1;
|
|
$idx_changed = 1;
|
|
} else {
|
|
warn "The .idx file has not changed, so it is valid\n"
|
|
if !$silent;
|
|
}
|
|
if ($index_mode) {
|
|
my $makeindex_return_code = &make_ind($idx_changed);
|
|
if ( ($makeindex_return_code eq 2) && !$force_mode ) {
|
|
&exit_msg('Makeindex encountered an error');
|
|
}
|
|
}
|
|
} else {
|
|
if ($index_mode) {
|
|
warn "No .idx file was generated, but index_mode is set; ",
|
|
"I will unset it";
|
|
$index_mode = 0;
|
|
}
|
|
if ( -e "$root_filename.idx.bak") {
|
|
warn "No idx file was generated. ",
|
|
"So I delete unneeded .idx.bak file\n"
|
|
if !$silent;
|
|
unlink ("$root_filename.idx.bak");
|
|
}
|
|
}
|
|
|
|
if ( $aux_changed || $idx_changed ) {
|
|
$repeat = 1;
|
|
}
|
|
|
|
if ( $count_latex ge $max_repeat ) {
|
|
# Avoid infinite loop by having a maximum repeat count
|
|
# Getting here represents some kind of weird error.
|
|
if ($repeat ) {
|
|
warn "Maximum runs of latex reached ",
|
|
"without correctly resolving cross references\n";
|
|
}
|
|
$repeat = 0;
|
|
}
|
|
} until ($repeat == 0);
|
|
|
|
if ($bibtex_mode) {
|
|
if (&check_for_bibtex_warnings) {
|
|
print "See $root_filename.blg for details\n";
|
|
}
|
|
}
|
|
|
|
if (!$force_mode && $bad_reference) {
|
|
&exit_msg('Latex could not resolve all references');
|
|
}
|
|
|
|
if (!$force_mode && $bad_citation) {
|
|
&exit_msg('Latex could not resolve all citations or labels');
|
|
}
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub make_dvi_filtered
|
|
{
|
|
return if ( length($dvi_filter) == 0 );
|
|
warn "------------\nRunning $dvi_filter [$root_filename]\n------------\n";
|
|
&Run("$dvi_filter < $root_filename.dvi > $root_filename.dviF");
|
|
$updated = 1;
|
|
}
|
|
|
|
#************************************************************
|
|
# Finds the basename of the root file
|
|
# Arguments:
|
|
# 1 - Filename to breakdown
|
|
# 2 - Where to place base file
|
|
# 3 - Where to place tex file
|
|
# Returns non-zero if tex file does not exist
|
|
#
|
|
# The rules for determining this depend on the implementation of TeX.
|
|
# The variable $extension_treatment determines which rules are used.
|
|
|
|
sub find_basename
|
|
{
|
|
local($given_name, $base_name, $ext, $path, $tex_name);
|
|
$given_name = $_[0];
|
|
if ( "$extension_treatment" eq "miktex_old" ) {
|
|
# Miktex v. 1.20d:
|
|
# 1. If the filename has an extension, then use it.
|
|
# 2. Else append ".tex".
|
|
# 3. The basename is obtained from the filename by
|
|
# removing the path component, and the extension, if it
|
|
# exists. If a filename has a multiple extension, then
|
|
# all parts of the extension are removed.
|
|
# 4. The names of generated files (log, aux) are obtained by
|
|
# appending .log, .aux, etc to the basename. Note that
|
|
# these are all in the CURRENT directory, and the drive/path
|
|
# part of the originally given filename is ignored.
|
|
#
|
|
# Thus when the given filename is "\tmp\a.b.c", the tex
|
|
# filename is the same, and the basename is "a".
|
|
|
|
($base_name, $path, $ext) = fileparse ($given_name, '\..*');
|
|
if ( "$ext" eq "") { $tex_name = "$given_name.tex"; }
|
|
else { $tex_name = $given_name; }
|
|
$_[1] = $base_name;
|
|
$_[2] = $tex_name;
|
|
}
|
|
elsif ( "$extension_treatment" eq "unix" ) {
|
|
# unix (at least web2c 7.3.1) =>
|
|
# 1. If filename.tex exists, use it,
|
|
# 2. else if filename exists, use it.
|
|
# 3. The base filename is obtained by deleting the path
|
|
# component and, if an extension exists, the last
|
|
# component of the extension, even if the extension is
|
|
# null. (A name ending in "." has a null extension.)
|
|
# 4. The names of generated files (log, aux) are obtained by
|
|
# appending .log, .aux, etc to the basename. Note that
|
|
# these are all in the CURRENT directory, and the drive/path
|
|
# part of the originally given filename is ignored.
|
|
#
|
|
# Thus when the given filename is "/tmp/a.b.c", there are two
|
|
# cases:
|
|
# a. /tmp/a.b.c.tex exists. Then this is the tex file,
|
|
# and the basename is "a.b.c".
|
|
# b. /tmp/a.b.c.tex does not exist. Then the tex file is
|
|
# "/tmp/a.b.c", and the basename is "a.b".
|
|
|
|
if ( -e "$given_name.tex" ) {
|
|
$tex_name = "$given_name.tex";
|
|
}
|
|
else {
|
|
$tex_name = "$given_name";
|
|
}
|
|
($base_name, $path, $ext) = fileparse ($tex_name, '\.[^\.]*');
|
|
$_[1] = $base_name;
|
|
$_[2] = $tex_name;
|
|
}
|
|
else {
|
|
die "Latexmk: Incorrect configuration gives \$extension_treatment=",
|
|
"\"$extension_treatment\"\n";
|
|
}
|
|
if ($diagnostics) {
|
|
print "Given=\"$given_name\", tex=\"$tex_name\", base=\"$base_name\"\n";
|
|
}
|
|
return ! -e $tex_name;
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub make_bbl {
|
|
# If necessary, make bbl file. Assume bibtex mode on.
|
|
# Force run if first argument is non-zero.
|
|
# Return 0 if nothing made,
|
|
# 1 if bbl file made,
|
|
# 2 if bibtex reported an error
|
|
my $bib_mtime = &get_latest_mtime($bib_files);
|
|
my $bbl_mtime = &get_mtime("$root_filename.bbl");
|
|
## if no .bbl or .bib changed since last bibtex run, run bibtex.
|
|
if ( !-e "$root_filename.aux" )
|
|
{
|
|
# bibtex reads aux file, so if there is no aux file, there is
|
|
# nothing to do
|
|
return 0;
|
|
}
|
|
if (($_[0] != 0)
|
|
|| !(-e "$root_filename.bbl")
|
|
|| ($bbl_mtime < $bib_mtime)
|
|
)
|
|
{
|
|
warn "------------\nRunning $bibtex [$root_filename]",
|
|
"\n------------\n";
|
|
my $return = &Run("$bibtex $root_filename");
|
|
$updated = 1;
|
|
$bbl_mtime = &get_mtime("$root_filename.bbl");
|
|
if ( &check_for_bibtex_errors || ($return != 0) )
|
|
{ return 2; }
|
|
else
|
|
{ return 1; }
|
|
}
|
|
else
|
|
{ return 0; }
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub make_ind {
|
|
# If necessary, make ind file. Assume makeindex mode on.
|
|
# Force run if first argument is non-zero.
|
|
# Return 0 if nothing made,
|
|
# 1 if ind file made,
|
|
# 2 if makeindex reported an error
|
|
if ( !-e "$root_filename.idx" )
|
|
{
|
|
# makeindex reads idx file, so if there is no idx file, there is
|
|
# nothing to do
|
|
return 0;
|
|
}
|
|
if ( ($_[0] != 0) || !(-e "$root_filename.ind") )
|
|
{
|
|
warn "------------\nRunning $makeindex [$root_filename]",
|
|
"\n------------\n";
|
|
my $return = &Run("$makeindex $root_filename");
|
|
$updated = 1;
|
|
if ($return)
|
|
{ return 2; }
|
|
else
|
|
{ return 1; }
|
|
}
|
|
else
|
|
{ return 0; }
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub make_dependents
|
|
{
|
|
local($file,$dep,$base_name,$ch,$toext,$fromext,$proptoext,$must,$func_name,$return);
|
|
|
|
foreach $file (split(' ',$_[0]))
|
|
{
|
|
$ch = '';
|
|
$toext = '';
|
|
$base_name = $file;
|
|
while (( $ch ne '.' ) && ( $ch ne '/' ) && ( $base_name ne '' ))
|
|
{
|
|
$toext = $ch . $toext;
|
|
$ch = chop $base_name;
|
|
}
|
|
if (( $ch eq '.' ) && ( $base_name ne '' ))
|
|
{
|
|
#Extracted proper extention.
|
|
foreach $dep ( @cus_dep_list )
|
|
{
|
|
($fromext,$proptoext,$must,$func_name) = split(' ',$dep);
|
|
if ( $toext eq $proptoext )
|
|
{
|
|
# Found match
|
|
if ( -e "$base_name.$fromext" )
|
|
{
|
|
# From file exists, now check if it is newer
|
|
if (( ! (-e "$base_name.$toext" ))
|
|
|| ( &get_mtime("$base_name.$toext")
|
|
< &get_mtime("$base_name.$fromext") ))
|
|
{
|
|
warn "------------\nRunning $func_name [$base_name]\n------------\n";
|
|
$return = &$func_name($base_name);
|
|
$updated = 1;
|
|
if ( !$force_mode && $return )
|
|
{
|
|
&exit_msg("$func_name encountered an error");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !$force_mode && ( $must != 0 ))
|
|
{
|
|
&exit_msg("File '$base_name.$fromext' does not exist to build '$base_name.$toext'\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub make_printout
|
|
{
|
|
my $ext = '';
|
|
if ( length($ps_filter) == 0 )
|
|
{
|
|
$ext = '.ps';
|
|
}
|
|
else
|
|
{
|
|
$ext = '.psF';
|
|
}
|
|
warn "------------\nPrinting using $lpr [$root_filename]\n------------\n";
|
|
&Run("$lpr $root_filename$ext");
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub make_postscript
|
|
{
|
|
my $tmpfile;
|
|
my $header;
|
|
my $dvi_file;
|
|
|
|
# Figure out the dvi file name
|
|
if ( length($dvi_filter) == 0 )
|
|
{
|
|
$dvi_file = "$root_filename.dvi";
|
|
}
|
|
else
|
|
{
|
|
$dvi_file = "$root_filename.dviF";
|
|
}
|
|
|
|
# Do banner stuff
|
|
if ( $banner )
|
|
{
|
|
## Make temp banner file
|
|
# local(*INFILE,*OUTFILE,$count);
|
|
local(*OUTFILE,$count);
|
|
|
|
$tmpfile = "$tmpdir/latexmk.$$";
|
|
$count = 0;
|
|
while ( -e $tmpfile )
|
|
{
|
|
$count = $count + 1;
|
|
$tmpfile = "$tmpdir/latexmk.$$.$count";
|
|
}
|
|
if ( ! open(OUTFILE, ">$tmpfile") ) {
|
|
die "Latexmk: Could not open temporary file [$tmpfile]\n"; }
|
|
print OUTFILE "userdict begin /bop-hook{gsave 200 30 translate\n";
|
|
print OUTFILE "65 rotate /Times-Roman findfont $banner_scale scalefont setfont\n";
|
|
print OUTFILE "0 0 moveto $banner_intensity setgray ($banner_message) show grestore}def end\n";
|
|
close(OUTFILE);
|
|
$header = "-h $tmpfile";
|
|
}
|
|
else
|
|
{
|
|
$header = '';
|
|
}
|
|
|
|
my $ps_mtime = &get_mtime("$root_filename.ps");
|
|
my $dvi_mtime = &get_mtime("$dvi_file");
|
|
if ((! -e "$root_filename.ps")
|
|
||( $ps_mtime < $dvi_mtime )
|
|
|| $banner
|
|
)
|
|
{
|
|
warn "------------\nRunning $dvips [$root_filename]\n------------\n";
|
|
&Run("$dvips $header $dvi_file -o $root_filename.ps");
|
|
$updated = 1;
|
|
}
|
|
|
|
if ( $banner )
|
|
{
|
|
unlink("$tmpfile");
|
|
}
|
|
|
|
## Do we have postscript filtering?
|
|
if ( length($ps_filter) != 0 )
|
|
{
|
|
warn "------------\nRunning $ps_filter [$root_filename]\n------------\n";
|
|
&Run("$ps_filter < $root_filename.ps > $root_filename.psF");
|
|
$updated = 1;
|
|
}
|
|
}
|
|
|
|
#************************************************************
|
|
# run appropriate previewer.
|
|
|
|
sub make_preview
|
|
{
|
|
my $ext;
|
|
my $viewer;
|
|
if ( $view eq 'dvi' )
|
|
{
|
|
$viewer = $dvi_previewer;
|
|
$ext = '.dvi';
|
|
if ( length($dvi_filter) != 0 )
|
|
{
|
|
$ext = '.dviF';
|
|
}
|
|
}
|
|
elsif ( $view eq 'ps' )
|
|
{
|
|
$viewer = $ps_previewer;
|
|
$ext = '.ps';
|
|
if ( length($ps_filter) != 0 )
|
|
{
|
|
$ext = '.psF';
|
|
}
|
|
}
|
|
elsif ( $view eq 'pdf' )
|
|
{
|
|
$viewer = $pdf_previewer;
|
|
$ext = '.pdf';
|
|
}
|
|
else
|
|
{
|
|
die "Latexmk: BUG: No preview method defined\n";
|
|
}
|
|
|
|
my $view_file = "$root_filename$ext";
|
|
|
|
warn "------------\nStarting previewer: $viewer $view_file\n------------\n";
|
|
$return = &Run ("$viewer $view_file");
|
|
if ($return){
|
|
warn "Latexmk: Could not start previewer [$viewer $view_file]";
|
|
}
|
|
exit;
|
|
}
|
|
|
|
#************************************************************
|
|
#************************************************************
|
|
|
|
sub find_process_id {
|
|
# find_process_id(string) finds id of process containing string and
|
|
# being run by the present user. Typically the string will be the
|
|
# name of the process or part of its command line.
|
|
# On success, this subroutine returns the process ID.
|
|
# On failure, it returns 0.
|
|
# This subroutine only works on UNIX systems at the moment.
|
|
|
|
if ( $pid_position < 0 ) {
|
|
# I cannot do a ps on this system
|
|
return (0);
|
|
}
|
|
|
|
my $looking_for = $_[0];
|
|
my @ps_output = `$pscmd`;
|
|
|
|
shift(@ps_output); # Discard the header line from ps
|
|
foreach (@ps_output) {
|
|
next unless ( /$looking_for/ ) ;
|
|
my @ps_line = split (' ');
|
|
return($ps_line[$pid_position]);
|
|
}
|
|
|
|
# No luck in finding the specified process.
|
|
return(0);
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub make_preview_continous
|
|
{
|
|
|
|
# How do we persuade viewer to update. Default is to do nothing.
|
|
my $viewer_update_method = 0;
|
|
|
|
if ( $view eq 'dvi' )
|
|
{
|
|
$viewer = $dvi_previewer;
|
|
$viewer_update_method = $dvi_update_method;
|
|
$ext = '.dvi';
|
|
if ( length($dvi_filter) != 0 )
|
|
{
|
|
$ext = '.dviF';
|
|
}
|
|
}
|
|
elsif ( $view eq 'ps' )
|
|
{
|
|
$viewer = $ps_previewer;
|
|
$viewer_update_method = $ps_update_method;
|
|
$ext = '.ps';
|
|
if ( length($ps_filter) != 0 )
|
|
{
|
|
$ext = '.psF';
|
|
}
|
|
}
|
|
elsif ( $view eq 'pdf' )
|
|
{
|
|
$viewer_update_method = $ps_update_method;
|
|
$viewer = $pdf_previewer;
|
|
$ext = '.pdf';
|
|
}
|
|
else
|
|
{
|
|
die "Latexmk: BUG: No preview method defined\n";
|
|
}
|
|
|
|
# note, we only launch a previewer if one isn't already running...
|
|
# But I only know how to do this under UNIX
|
|
|
|
my $view_file = "$root_filename$ext";
|
|
|
|
my $viewer_process = 0; # default: no viewer processknown
|
|
|
|
$viewer_process = &find_process_id ($view_file);
|
|
if ( $viewer_process ) {
|
|
print "Previewer is already running\n";
|
|
} else {
|
|
print "I have not found a previewer that is already running. ",
|
|
"So I will start it\n";
|
|
Run ("start $viewer $root_filename$ext");
|
|
$viewer_process = &find_process_id ($view_file);
|
|
}
|
|
|
|
|
|
# Loop forever, rebuilding .dvi and .ps as necessary.
|
|
while ( 1 ) {
|
|
$updated = 0;
|
|
sleep($sleep_time);
|
|
&make_files;
|
|
if ( ($viewer_process != 0) && $updated && ($viewer_update_method == 2) ) {
|
|
if ( $diagnostics ) {
|
|
print "I am signalling viewer, process ID $viewer_process\n";
|
|
}
|
|
kill 'USR1', $viewer_process;
|
|
}
|
|
}
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub get_mtime
|
|
{
|
|
my $mtime = (stat($_[0]))[9];
|
|
return $mtime;
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
# check for citation which bibtex didnt find.
|
|
|
|
sub check_for_bibtex_errors
|
|
{
|
|
local($log_file) = "$root_filename.blg";
|
|
open(log_file) || die "Latexmk: Could not open bibtex log file error check\n";
|
|
while (<log_file>)
|
|
{
|
|
# if (/Warning--/) { return 1; }
|
|
if (/error message/) { return 1; }
|
|
}
|
|
0;
|
|
}
|
|
|
|
#************************************************************
|
|
# check for bibtex warnings
|
|
|
|
sub check_for_bibtex_warnings
|
|
{
|
|
local($log_file) = "$root_filename.blg";
|
|
open(log_file) || die "Latexmk: Could not open bibtex log file error check\n";
|
|
my $have_warning = 0;
|
|
while (<log_file>)
|
|
{
|
|
if (/Warning--/) { print "Bibtex warning: $_"; $have_warning = 1}
|
|
if (/error message/) { print "Bibtex error: $_"; $have_warning = 1}
|
|
}
|
|
return $have_warning;
|
|
}
|
|
|
|
#************************************************************
|
|
# cleanup_basic
|
|
# - erases basic set of generated files, exits w/ no other processing.
|
|
# (all but aux, dep, dvi, pdf, and ps),
|
|
# and also texput.log, and files with extensions in $clean_ext
|
|
|
|
sub cleanup_basic
|
|
{
|
|
# Basic set:
|
|
unlink("$root_filename.aux.bak");
|
|
unlink("$root_filename.bbl");
|
|
unlink("$root_filename.blg");
|
|
unlink("$root_filename.log");
|
|
unlink("$root_filename.ind");
|
|
unlink("$root_filename.idx");
|
|
unlink("$root_filename.idx.bak");
|
|
unlink("$root_filename.ilg");
|
|
unlink("$root_filename.toc");
|
|
unlink("$root_filename.toc.bak");
|
|
unlink("$root_filename.lof");
|
|
unlink("$root_filename.lot");
|
|
unlink("texput.log");
|
|
|
|
# Do any other file extensions specified
|
|
foreach $ext (split(' ',$clean_ext))
|
|
{
|
|
unlink("$root_filename.$ext");
|
|
}
|
|
}
|
|
|
|
|
|
#************************************************************
|
|
# cleanup_dvi_ps_pdf
|
|
# - erases generated dvi, ps, and pdf files (and others specified in
|
|
# $cleanup_full_ext),
|
|
# and also texput.dvi, and files with extensions in $clean_full_ext
|
|
|
|
sub cleanup_dvi_ps_pdf
|
|
{
|
|
unlink("$root_filename.dvi");
|
|
unlink("$root_filename.pdf");
|
|
unlink("$root_filename.ps");
|
|
unlink("$root_filename.dviF");
|
|
unlink("$root_filename.psF");
|
|
unlink("texput.dvi");
|
|
# Do any other file extensions specified
|
|
foreach $ext (split(' ',$clean_full_ext))
|
|
{
|
|
unlink("$root_filename.$ext");
|
|
}
|
|
}
|
|
|
|
|
|
#************************************************************
|
|
# cleanup_aux_dep
|
|
# - erases generated aux and dep files, and also texput.aux
|
|
|
|
sub cleanup_aux_dep
|
|
{
|
|
unlink("$root_filename.aux");
|
|
unlink("$root_filename.dep");
|
|
unlink("texput.aux");
|
|
# .aux files are also made for \include'd files
|
|
if ($include) {
|
|
foreach $include (split(' ',$includes)) {
|
|
$include =~ s/\.[^\.]*$/.aux/;
|
|
unlink($include);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#************************************************************
|
|
sub print_help
|
|
{
|
|
print
|
|
"Latexmk $version_num: Automatic LaTeX document generation routine\n\n",
|
|
"Usage: latexmk [latexmk_options] [filename ...]\n\n",
|
|
" Latexmk_options:\n",
|
|
" -bm <message> - Print message across the page when converting to postscript\n",
|
|
" -bi <intensity> - Set contrast or intensity of banner\n",
|
|
" -bs <scale> - Set scale for banner\n",
|
|
" --commands - list commands used by latexmk for processing files\n",
|
|
" -c - clean up (remove) all nonessential files, except\n",
|
|
" dvi, ps and pdf files\n",
|
|
" -C - clean up (remove) all nonessential files\n",
|
|
" including aux, dep, dvi, postscript and pdf files\n",
|
|
" -c1 - clean up (remove) all nonessential files,\n",
|
|
" including dvi, pdf and ps files, but excluding aux and dep files \n",
|
|
" -d - Print `DRAFT' across the page when converting to postscript\n",
|
|
" -dF <filter> - Filter to apply to dvi file\n",
|
|
" -dvi - generate dvi\n",
|
|
" -dvi- - turn off required dvi\n",
|
|
" -f - force continued processing past errors\n",
|
|
" -F - Ignore non-existent files when making dependencies\n",
|
|
" -g - process regardless of file timestamps\n",
|
|
" -h - print help\n",
|
|
" --help - print help\n",
|
|
" -i - rescan for includes if dependency file older than tex file\n",
|
|
" -il - make list of included files by parsing log file\n",
|
|
" -it - make list of included files by parsing tex file\n",
|
|
" -I - force rescan for includes\n",
|
|
" -l - force landscape mode\n",
|
|
" -pdf - generate pdf\n",
|
|
" -pdf- - turn off required pdf\n",
|
|
" -ps - generate postscript\n",
|
|
" -ps- - turn off required postscript\n",
|
|
" -pF <filter> - Filter to apply to postscript file\n",
|
|
" -p - print document after generating postscript\n",
|
|
" -pv - preview document\n",
|
|
" -pvc - preview document and continuously update\n",
|
|
" -r <file> - Read custom RC file\n",
|
|
" --silent - silence progress messages from called programs\n",
|
|
" -v - display program version\n",
|
|
" --verbose - display usual progress messages from called programs\n",
|
|
" --version - display program version\n",
|
|
" --view=default - viewer is default (dvi, ps, pdf)\n",
|
|
" --view=dvi - viewer is for dvi\n",
|
|
" --view=ps - viewer is for ps\n",
|
|
" --view=pdf - viewer is for pdf\n",
|
|
" filename = the root filename of LaTeX document\n",
|
|
"\n",
|
|
"-p, -pv and -pvc are mutually exclusive\n",
|
|
"-h, -c and -C overides all other options.\n",
|
|
"-pv and -pvc require one and only one filename specified\n",
|
|
"Contents of RC file specified by -r overrides options specified\n",
|
|
" before the -r option on the command line\n";
|
|
|
|
exit;
|
|
}
|
|
|
|
#************************************************************
|
|
sub print_commands
|
|
{
|
|
warn "Commands used by latexmk:\n",
|
|
" To run latex, I use \"$latex\"\n",
|
|
" To run pdflatex, I use \"$pdflatex\"\n",
|
|
" To run bibtex, I use \"$bibtex\"\n",
|
|
" To run makeindex, I use \"$makeindex\"\n",
|
|
" To make a ps file from a dvi file, I use \"$dvips\"\n",
|
|
" To make a ps file from a dvi file with landscape format, ",
|
|
"I use \"$dvips_landscape\"\n",
|
|
" To view a pdf file, I use \"$pdf_previewer\"\n",
|
|
" To view a ps file, I use \"$ps_previewer\"\n",
|
|
" To view a ps file in landscape format, ",
|
|
"I use \"$ps_previewer_landscape\"\n",
|
|
" To view a dvi file, I use \"$dvi_previewer\"\n",
|
|
" To view a dvi file in landscape format, ",
|
|
"I use \"$dvi_previewer_landscape\"\n",
|
|
" To print a ps file, I use \"$lpr\"\n",
|
|
" To find running processes, I use \"$pscmd\", ",
|
|
"and the process number is at position $pid_position\n";
|
|
warn "Notes:\n",
|
|
" Command starting with \"start\" is run detached\n",
|
|
" Command that is just \"start\" without any other command, is\n",
|
|
" used under MS-Windows to run the command the operating system\n",
|
|
" has associated with the relevant file.\n",
|
|
" Command starting with \"NONE\" is not used at all\n";
|
|
}
|
|
|
|
#************************************************************
|
|
# - stats all files listed in first arg, returns most recent modify time of all.
|
|
|
|
sub get_latest_mtime
|
|
{
|
|
local($return_mtime) = 0;
|
|
if (! $_[0] ) {return $return_mtime; }
|
|
foreach $include (split(' ',$_[0]))
|
|
{
|
|
$include_mtime = &get_mtime($include);
|
|
# The file $include may not exist. If so ignore it, otherwise
|
|
# we'll get an undefined variable warning.
|
|
if ( ($include_mtime) && ($include_mtime > $return_mtime) )
|
|
{
|
|
$return_mtime = $include_mtime;
|
|
}
|
|
}
|
|
$return_mtime;
|
|
}
|
|
|
|
#************************************************************
|
|
# - looks recursively for included & inputted and psfig'd files and puts
|
|
# them into $includes.
|
|
# - note only primitive comment removal: cannot deal with escaped %s, but then,
|
|
# when would they occur in any line important to latexmk??
|
|
|
|
sub scan_for_includes
|
|
{
|
|
warn "------------\nGenerating Dependency File [$root_filename]\n------------\n";
|
|
&scan_for_includes_($_[0]);
|
|
}
|
|
|
|
sub scan_for_includes_
|
|
{
|
|
local(*FILE,$orig_filename);
|
|
##JCC
|
|
local($ignoremode,$line);
|
|
$ignoremode = 0;
|
|
$line = 0;
|
|
if (!open(FILE,$_[0]))
|
|
{
|
|
warn "Latexmk: could not open input file [$_[0]]\n";
|
|
return;
|
|
}
|
|
LINE:
|
|
while(<FILE>)
|
|
{
|
|
$line = $line + 1;
|
|
|
|
if ( /^\s*(%#.*)\s*$/ )
|
|
{
|
|
$_ = $1;
|
|
##warn "======Metacommand \"$_\"\n";
|
|
if ( /%#{}end.raw/ || /%#{latexmk}end.ignore/ )
|
|
{
|
|
$ignoremode = 0;
|
|
warn " Ignore mode off, at line $line in file $_[0].\n";
|
|
}
|
|
elsif ( $ignoremode == 1 )
|
|
{
|
|
# In ignore mode only end.raw, etc metacommands are recognized.
|
|
next LINE;
|
|
}
|
|
elsif ( /%#{}raw/ || /%#{}begin.raw/ ||
|
|
/%#{latexmk}ignore/ || /%#{latexmk}begin.ignore/ )
|
|
{
|
|
$ignoremode = 1;
|
|
warn " Ignore mode on, at line $line in file $_[0].\n";
|
|
}
|
|
elsif ( /%#{latexmk}include.file[\040\011]+([^\040\011\n]*)/ )
|
|
{
|
|
$includes .= "$1 ";
|
|
warn " Adding include file \"$1\" at line $line in file $_[0].\n";
|
|
}
|
|
else
|
|
{
|
|
# Unrecognized metacommands are, by specification, to be ignored.
|
|
warn "Unrec. \"$_\"\n";
|
|
}
|
|
next LINE;
|
|
}
|
|
if ( $ignoremode == 1 )
|
|
{
|
|
##warn "Skipping a line:\n $_";
|
|
next LINE;
|
|
}
|
|
|
|
($_) = split('%',$_); # primitive comment removal
|
|
|
|
if (/\\def/ || /\\newcommand/ || /\\renewcommand/ || /\\providecommand/)
|
|
{
|
|
##JCC Ignore definitions:
|
|
warn "Ignoring definition:\n $_";
|
|
}
|
|
elsif (/\\include[{\s]+([^\001\040\011}]*)[\s}]/)
|
|
{
|
|
$full_filename = $1;
|
|
$orig_filename = $full_filename;
|
|
$full_filename = &find_file_ext($full_filename, 'tex', \@TEXINPUTS);
|
|
if ($full_filename)
|
|
{
|
|
$includes .= "$full_filename ";
|
|
if ( -e $full_filename )
|
|
{
|
|
warn " Found include for file [$full_filename]\n";
|
|
&scan_for_includes_($full_filename);
|
|
}
|
|
else
|
|
{
|
|
if ( $orig_filename =~ /^\// )
|
|
{
|
|
warn "Latexmk: In \\include, ",
|
|
"could not find file [$orig_filename]\n";
|
|
}
|
|
else
|
|
{
|
|
warn "Latexmk: In \\include, ",
|
|
"could not find file [$orig_filename] in path [@TEXINPUTS]\n";
|
|
warn " assuming in current directory ($full_filename)\n";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ! $force_include_mode )
|
|
{
|
|
if ( $orig_filename =~ /^\// )
|
|
{
|
|
die "Latexmk: In \\include, ",
|
|
"could not find file [$orig_filename]\n";
|
|
}
|
|
else
|
|
{
|
|
die "Latexmk: In \\include, ",
|
|
"could not find file [$orig_filename] in path [@TEXINPUTS]\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
elsif (/\\input[{\s]+([^\001\040\011}]*)[\s}]/)
|
|
{
|
|
$full_filename = $1;
|
|
$orig_filename = $full_filename;
|
|
$full_filename = &find_file_ext($full_filename, 'tex', \@TEXINPUTS);
|
|
if ($full_filename)
|
|
{
|
|
$includes .= "$full_filename ";
|
|
warn "added '$full_filename'\n";
|
|
if ( -e $full_filename )
|
|
{
|
|
warn " Found input for file [$full_filename]\n";
|
|
&scan_for_includes_($full_filename);
|
|
}
|
|
else
|
|
{
|
|
if ( $orig_filename =~ /^\// )
|
|
{
|
|
warn "Latexmk: In \\input, could not find file [$orig_filename]\n";
|
|
}
|
|
else
|
|
{
|
|
warn "Latexmk: In \\input, ",
|
|
"could not find file [$orig_filename] in path [@TEXINPUTS]\n";
|
|
warn " assuming in current directory ($full_filename)\n";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ! $force_include_mode )
|
|
{
|
|
if ( $orig_filename =~ /^\// )
|
|
{
|
|
die "Latexmk: In \\input, could not find file [$orig_filename]\n";
|
|
}
|
|
else
|
|
{
|
|
die "Latexmk: In \\input, ",
|
|
"could not find file [$orig_filename] in path [@TEXINPUTS]\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
elsif (/\\blackandwhite{([^\001\040\011}]*)}/ || /\\colorslides{([^\001}]*)}/)
|
|
{
|
|
############ $slide_mode = 1;
|
|
$full_filename = &find_file_ext($1, 'tex', \@TEXINPUTS);
|
|
if ($full_filename)
|
|
{
|
|
$includes .= "$full_filename ";
|
|
if ( -e $full_filename )
|
|
{
|
|
warn " Found slide input for file [$full_filename]\n";
|
|
&scan_for_includes_($full_filename);
|
|
}
|
|
}
|
|
}
|
|
elsif (/\\psfig{file=([^,}]+)/ || /\\psfig{figure=([^,}]+)/)
|
|
{
|
|
$orig_filename = $1;
|
|
$full_filename = &find_file($1, \@psfigsearchpath);
|
|
if ($full_filename)
|
|
{
|
|
$includes .= "$full_filename ";
|
|
if ( -e $full_filename )
|
|
{
|
|
warn " Found psfig for file [$full_filename]\n";
|
|
}
|
|
}
|
|
}
|
|
elsif ( /\\epsfbox{([^}]+)}/ || /\\epsfbox\[[^\]]*\]{([^}]+)}/ ||
|
|
/\\epsffile{([^}]+)}/ || /\\epsffile\[[^\]]*\]{([^}]+)}/ ||
|
|
/\\epsfig{file=([^,}]+)/ || /\\epsfig{figure=([^,}]+)/ )
|
|
{
|
|
$orig_filename = $1;
|
|
$full_filename = &find_file($1, \@psfigsearchpath);
|
|
if ($full_filename)
|
|
{
|
|
$includes .= "$full_filename ";
|
|
if ( -e $full_filename )
|
|
{
|
|
warn " Found epsf for file [$full_filename]\n";
|
|
}
|
|
}
|
|
}
|
|
elsif (
|
|
/\\includegraphics{([^}]+)}/ || /\\includegraphics\[[^\]]*\]{([^}]+)}/
|
|
)
|
|
{
|
|
$orig_filename = $1;
|
|
$full_filename = &find_file_ext($1,'eps', \@psfigsearchpath);
|
|
if ($full_filename)
|
|
{
|
|
$includes .= "$full_filename ";
|
|
if ( -e $full_filename )
|
|
{
|
|
warn " Found epsf for file [$full_filename]\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
warn "Latexmk: For \\includegraphics, ",
|
|
"could not find file [$orig_filename]\n",
|
|
" in path [@psfigsearchpath]\n";
|
|
if ( ! $force_include_mode ) {die "\n";}
|
|
}
|
|
}
|
|
elsif (/\\documentstyle[^\000]+landscape/)
|
|
{
|
|
warn " Detected landscape mode\n";
|
|
$landscape_mode = 1;
|
|
}
|
|
elsif (/\\bibliography{([^}]+)}/)
|
|
{
|
|
$bib_files = $1;
|
|
$bib_files =~ tr/,/ /;
|
|
$bib_files = &find_file_list($bib_files, '.bib', \@BIBINPUTS);
|
|
warn " Found bibliography files [$bib_files]\n";
|
|
$bibtex_mode = 1;
|
|
}
|
|
elsif (/\\psfigsearchpath{([^}]+)}/)
|
|
{
|
|
@psfigsearchpath = &split_search_path(':', '', $1);
|
|
}
|
|
elsif (/\\graphicspath{([^}]+)}/)
|
|
{
|
|
@psfigsearchpath = &split_search_path(':', '', $1);
|
|
}
|
|
elsif (/\\makeindex/)
|
|
{
|
|
$index_mode = 1;
|
|
warn " Detected index mode\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
#**************************************************
|
|
# Find file with default extension
|
|
# Usage: find_file_ext( name, default_ext, ref_to_array_search_path)
|
|
sub find_file_ext
|
|
{
|
|
my $full_filename = shift;
|
|
my $ext = shift;
|
|
my $ref_search_path = shift;
|
|
my $full_filename1 = &find_file($full_filename, $ref_search_path, '1');
|
|
#print "Finding \"$full_filename\" with ext \"$ext\" ... ";
|
|
if (( $full_filename1 eq '' ) || ( ! -e $full_filename1 ))
|
|
{
|
|
my $full_filename2 =
|
|
&find_file("$full_filename.$ext",$ref_search_path,'1');
|
|
if (( $full_filename2 ne '' ) && ( -e $full_filename2 ))
|
|
{
|
|
$full_filename = $full_filename2;
|
|
}
|
|
else
|
|
{
|
|
$full_filename = $full_filename1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$full_filename = $full_filename1;
|
|
}
|
|
#print "Found \"$full_filename\".\n";
|
|
return $full_filename;
|
|
}
|
|
|
|
#************************************************************
|
|
# given filename and path, return full name of file, or die if none found.
|
|
# when force_include_mode=1, only warn if an include file was not
|
|
# found, and return 0 (PvdS).
|
|
# Usage: find_file(name, ref_to_array_search_path, param)
|
|
sub find_file
|
|
{
|
|
my $name = $_[0];
|
|
my $ref_path = $_[1];
|
|
my $dir;
|
|
if ( $name =~ /^\// )
|
|
{
|
|
if ($force_include_mode)
|
|
{
|
|
if ( $_[2] eq '' )
|
|
{
|
|
warn "Latexmk: Could not find file [$name]\n";
|
|
}
|
|
return("$name");
|
|
}
|
|
else
|
|
{
|
|
if (-e $name)
|
|
{
|
|
return("$name");
|
|
}
|
|
die "Latexmk: Could not find file [$name]\n";
|
|
}
|
|
}
|
|
foreach $dir ( @{$ref_path} )
|
|
{
|
|
#warn "\"$dir\", \"$name\"\n";
|
|
if (-e "$dir/$name")
|
|
{
|
|
return("$dir/$name");
|
|
}
|
|
}
|
|
if ($force_include_mode)
|
|
{
|
|
if ( $_[2] eq '' )
|
|
{
|
|
warn "Latexmk: Could not find file [$name] in path [@{$ref_path}]\n";
|
|
warn " assuming in current directory (./$name)\n";
|
|
}
|
|
return("./$name");
|
|
}
|
|
else
|
|
{
|
|
if ( $_[2] ne '' )
|
|
{
|
|
return('');
|
|
}
|
|
# warn "\"$name\", \"$ref_path\", \"$dir\"\n";
|
|
die "Latexmk: Could not find file [$name] in path [@{$ref_path}]\n";
|
|
}
|
|
}
|
|
|
|
#************************************************************
|
|
# given space sep list of filenames, a file suffix, and a path, return list of
|
|
# full names of files, or die w/ warning if not found.
|
|
# When $force_include_mode=1, don't die and don't append the file names (PvdS).
|
|
# Usage: find_file_list(file_list, suffix, ref_to_array_search_path)
|
|
sub find_file_list
|
|
{
|
|
local($tmp_file,$return_list) = '';
|
|
foreach $file (split(' ',$_[0]))
|
|
{
|
|
$tmp_file = &find_file("$file$_[1]", $_[2], '');
|
|
if ($tmp_file)
|
|
{
|
|
$return_list .= $tmp_file . " ";
|
|
}
|
|
}
|
|
$return_list;
|
|
}
|
|
|
|
#************************************************************
|
|
sub exit_msg
|
|
{
|
|
warn "\n------------\n";
|
|
warn "Latexmk: $_[0].\n";
|
|
warn "-- Use the -f option to force complete processing.\n";
|
|
if ($_[1])
|
|
{
|
|
warn "Latexmk: restoring last $root_filename.aux file\n";
|
|
©_file ("$root_filename.aux.bak", "$root_filename.aux");
|
|
}
|
|
exit;
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub parse_log
|
|
{
|
|
# Scan log file for: include files, bibtex mode,
|
|
# reference_changed, bad_reference, bad_citation
|
|
# In bibtex mode, scan aux file for bib files
|
|
# Return value: 1 if success, 0 if no log file.
|
|
# Set global variables:
|
|
# $includes_in_log to list of included files.
|
|
# $reference_changed, $bad_reference, and $bad_citation suitably.
|
|
|
|
local($log_file) = "$root_filename.log";
|
|
@aux_files1 = ();
|
|
if ( ! open(log_file) )
|
|
{
|
|
$includes_in_log = "";
|
|
return 0;
|
|
}
|
|
my $line_number = 0;
|
|
my $graphic_line = 0;
|
|
my @non_existent = ();
|
|
my @bbl_files = ();
|
|
my @existent = ();
|
|
my @include_list = ();
|
|
|
|
$reference_changed = 0;
|
|
$bad_reference = 0;
|
|
$bad_citation = 0;
|
|
|
|
LINE:
|
|
while(<log_file>) {
|
|
$line_number++;
|
|
if ( $line_number == 1 ){
|
|
if ( /^This is / ) {
|
|
# First line OK\n";
|
|
next LINE;
|
|
} else {
|
|
die "Error on first line of \"$log_file\". This is not a TeX log file.\n$_";
|
|
}
|
|
}
|
|
# Handle wrapped lines:
|
|
my $len = length($_);
|
|
while ($len == $log_wrap)
|
|
{
|
|
s/\n//;
|
|
my $extra = <log_file>;
|
|
$line_number++;
|
|
$len = length($extra);
|
|
$_ .= $extra;
|
|
}
|
|
# Check for changed references, bad references and bad citations:
|
|
if (/Rerun to get/) {
|
|
warn "\n=== References changed.\n";
|
|
$reference_changed = 1;
|
|
}
|
|
if (/LaTeX Warning: (Reference[^\001]*undefined)./) {
|
|
warn "\n=== $1 \n";
|
|
$bad_reference = 1;
|
|
}
|
|
if (/LaTeX Warning: (Citation[^\001]*undefined)./) {
|
|
warn "\n=== $1 \n";
|
|
$bad_citation = 1;
|
|
}
|
|
if ( /^Document Class: / ) {
|
|
# Latex message
|
|
next LINE;
|
|
}
|
|
if ( /^Output written on / ) {
|
|
# Latex message
|
|
next LINE;
|
|
}
|
|
if ( /^Underfull / ) {
|
|
# Latex error/warning
|
|
next LINE;
|
|
}
|
|
if ( /^Overfull / ) {
|
|
# Latex error/warning
|
|
next LINE;
|
|
}
|
|
if ( /^\(Font\)/ ) {
|
|
# Font info line
|
|
next LINE;
|
|
}
|
|
if ( /^Package: / ) {
|
|
# Package sign-on line
|
|
next LINE;
|
|
}
|
|
if ( /^Writing index file / ) {
|
|
$index_mode =1;
|
|
warn "Index file written, so turn on index_mode\n";
|
|
next LINE;
|
|
}
|
|
if ( /^No file .*?\.bbl./ ) {
|
|
warn "Non-existent bbl file, so turn on bibtex_mode\n $_"
|
|
unless $bibtex_mode == 1;
|
|
$bibtex_mode = 1;
|
|
next LINE;
|
|
}
|
|
if ( /^File: ([^\s\[]*) Graphic file \(type / ) {
|
|
# First line of message from includegraphics/x
|
|
push @include_list, $1;
|
|
next LINE;
|
|
}
|
|
if ( /^File: / ) {
|
|
# Package sign-on line. Includegraphics/x also produces a line
|
|
# with this signature, but I've already handled it.
|
|
next LINE;
|
|
}
|
|
INCLUDE_NAME:
|
|
while ( /\(([^\)\s\[\{]*)/ ) {
|
|
$_ = $';
|
|
$include_name = $1;
|
|
if ( "$include_name" eq "[]" ) {
|
|
# Part of overfull hbox message
|
|
} elsif ( $include_name =~ /\.bbl$/ ) {
|
|
warn "Included bbl file \"$include_name\", so turn on bibtex_mode\n"
|
|
unless $bibtex_mode == 1;
|
|
$bibtex_mode = 1;
|
|
push @bbl_files, $include_name;
|
|
} elsif ( "$include_name" =~ /\.aux$/ ) {
|
|
push @aux_files1, $include_name;
|
|
} else {
|
|
push @include_list, $include_name;
|
|
}
|
|
}
|
|
}
|
|
close(log_file);
|
|
@aux_files1 = &uniq( sort(@aux_files1) );
|
|
|
|
if ( $bibtex_mode )
|
|
{
|
|
&parse_aux;
|
|
foreach (split(' ', $bib_files)){
|
|
push @include_list, $_;
|
|
}
|
|
}
|
|
|
|
@include_list = &uniq(sort @include_list);
|
|
foreach (@include_list) {
|
|
if ( -e $_ ) {
|
|
push @existent, $_;
|
|
} else {
|
|
push @non_existent, $_;
|
|
}
|
|
}
|
|
|
|
$includes_in_log = '';
|
|
foreach (@existent) {
|
|
$includes_in_log .= " $_ ";
|
|
}
|
|
|
|
if ( $diagnostics )
|
|
{
|
|
my $inc = $#include_list + 1;
|
|
my $exist = $#existent + 1;
|
|
my $non_exist = $#non_existent + 1;
|
|
my $bbl = $#bbl_files + 1;
|
|
print "$inc included files, of which ";
|
|
print "$exist exist, and $non_exist do not exist.\n";
|
|
print "Included files that exist:\n";
|
|
foreach (@existent) { print " $_\n";}
|
|
|
|
if ( $#bbl_files >= 0 ) {
|
|
print "Included bbl files:\n";
|
|
foreach (@bbl_files) { print " $_\n"; }
|
|
}
|
|
if ( $#non_existent >= 0 ) {
|
|
print "Included files that appear NOT to exist:\n";
|
|
foreach (@non_existent) { print " $_\n"; }
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub parse_aux
|
|
# Parse aux_file for bib files.
|
|
# Return 1 with $bib_files set if aux_file exists
|
|
# Return 0 and leave $bib_files unchanged in aux_file does not exist (or
|
|
# cannot be opened)
|
|
{
|
|
local($aux_file) = "$root_filename.aux";
|
|
if (! open(aux_file) )
|
|
{ return 0; }
|
|
$bib_files = "";
|
|
AUX_LINE:
|
|
while (<aux_file>)
|
|
{
|
|
if ( /^\\bibdata\{(.*)\}/ )
|
|
{
|
|
if ( $bib_files) { $bib_files .= ",$1"; }
|
|
else { $bib_files = $1; }
|
|
next AUX_LINE;
|
|
}
|
|
}
|
|
close(aux_file);
|
|
$bib_files =~ tr/,/ /;
|
|
$bib_files = &find_file_list($bib_files, '.bib', \@BIBINPUTS);
|
|
warn "Found bibliography files [$bib_files]\n";
|
|
return 1;
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub update_depend_file
|
|
{
|
|
warn "Writing dependency file [$root_filename.dep]\n";
|
|
$rc_file = ">$root_filename.dep";
|
|
open(rc_file) || die "Latexmk: Unable to open dependency file [$rc_file] for updating\n";
|
|
print rc_file '$includes = \'' . "$includes';\n";
|
|
print rc_file '$bib_files = \'' . "$bib_files';\n";
|
|
if ($bibtex_mode)
|
|
{
|
|
print rc_file '$bibtex_mode = 1;' . "\n";
|
|
}
|
|
if ($dvi_mode)
|
|
{
|
|
print rc_file '$dvi_mode = 1; ' . "\n";
|
|
}
|
|
if ($index_mode)
|
|
{
|
|
print rc_file '$index_mode = 1;' . "\n";
|
|
}
|
|
if ($pdf_mode)
|
|
{
|
|
print rc_file '$pdf_mode = 1; ' . "\n";
|
|
}
|
|
if ($postscript_mode)
|
|
{
|
|
print rc_file '$postscript_mode = 1; ' . "\n";
|
|
}
|
|
close rc_file;
|
|
}
|
|
|
|
#************************************************************
|
|
#
|
|
# UTILITIES
|
|
|
|
|
|
|
|
#************************************************************
|
|
|
|
sub uniq
|
|
# Read arguments, delete neighboring items that are identical,
|
|
# return array of results
|
|
{
|
|
my @sort = ();
|
|
my ($current, $prev);
|
|
my $first = 1;
|
|
while (@_)
|
|
{
|
|
$current = shift;
|
|
if ($first || ($current ne $prev) )
|
|
{
|
|
push @sort, $current;
|
|
$prev = $current;
|
|
$first = 0;
|
|
}
|
|
}
|
|
return @sort;
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub copy_file {
|
|
# Copy file1 to file2, preserving time
|
|
my $source = shift;
|
|
my $dest = shift;
|
|
my $retcode = copy ($source, $dest)
|
|
and do {
|
|
my $mtime = get_mtime($source);
|
|
utime $mtime, $mtime, $dest;
|
|
};
|
|
return $retcode;
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub diff {
|
|
# diff(filename1, filename2):
|
|
# Return 2 if either or both files cannot be opened.
|
|
# 1 if the files are different
|
|
# 0 if the files are the same
|
|
my $file1 = new FileHandle;
|
|
my $file2 = new FileHandle;
|
|
# Note automatic close of files when they go out of scope.
|
|
open ($file1, $_[0]) or return 2;
|
|
open ($file2, $_[1]) or return 2;
|
|
my $retcode = 0;
|
|
while ( ( not eof($file1)) || ( not eof($file2) ) ){
|
|
if ( <$file1> ne <$file2> ) {
|
|
$retcode = 1;
|
|
last;
|
|
}
|
|
}
|
|
return $retcode;
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub diff_OLDVERSION {
|
|
# diff(filename1, filename2):
|
|
# Return 2 if either or both files cannot be opened.
|
|
# 1 if the files are different
|
|
# 0 if the files are the same
|
|
local (*file1, *file2);
|
|
unless( open (file1, $_[0]) ) {
|
|
return 2;
|
|
}
|
|
unless ( open (file2, $_[1])) {
|
|
close (file1);
|
|
return 2;
|
|
}
|
|
my $retcode = 0;
|
|
while ( ( not eof(file1)) && ( not eof(file2) ) ){
|
|
if ( <file1> ne <file2> ) {
|
|
$retcode = 1;
|
|
last;
|
|
}
|
|
}
|
|
close (file1);
|
|
close (file2);
|
|
return $retcode;
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub split_search_path
|
|
{
|
|
# Usage: &split_search_path( separator, default, string )
|
|
# Splits string by separator and returns array of the elements
|
|
# Allow empty last component.
|
|
# Replace empty terms by the default.
|
|
my $separator = $_[0];
|
|
my $default = $_[1];
|
|
my $search_path = $_[2];
|
|
my @list = split( /$separator/, $search_path);
|
|
if ( $search_path =~ /$separator$/ ) {
|
|
push @list, "";
|
|
}
|
|
# Replace each blank argument (default) by current directory:
|
|
for ($i = 0; $i <= $#list ; $i++ ) {
|
|
if ($list[$i] eq "") {$list[$i] = $default;}
|
|
}
|
|
return @list;
|
|
}
|
|
|
|
#************************************************************
|
|
|
|
sub Run {
|
|
# Usage: Run ("program arguments ");
|
|
# or Run ("start program arguments");
|
|
# or Run ("NONE program arguments");
|
|
# First form is just a call to system, and the routine returns after the
|
|
# program has finished executing.
|
|
# Second form (with 'start') runs the program detached, as appropriate for
|
|
# the operating system: It runs "program arguments &" on UNIX, and
|
|
# "start program arguments" on WIN95 and WINNT. If multiple start
|
|
# words are at the beginning of the command, the extra ones are removed.
|
|
# Third form (with 'NONE') does not run anything, but prints an error
|
|
# message. This is provided to allow program names defined in the
|
|
# configuration to flag themselves as unimplemented.
|
|
|
|
# One word per element:
|
|
my @cmdline = split (/ /, $_[0]);
|
|
if (! @cmdline ) {
|
|
warn "Latexmk::Run: Attempt to run a null program.";
|
|
return 1;
|
|
}
|
|
if ( "$cmdline[0]" eq "start" ) {
|
|
# Run detached. How to do this depends on the OS
|
|
# But first remove extra starts (which may have been inserted
|
|
# to force a command to be run detached, when the command
|
|
# already contained a "start").
|
|
while ($cmdline[0] eq "start") {shift (@cmdline);}
|
|
if ( "$^O" eq "MSWin32" ){
|
|
# Win95, WinNT, etc: Prepend start to the command
|
|
unshift @cmdline, "start";
|
|
} else {
|
|
# UNIX:
|
|
push @cmdline, "&";
|
|
}
|
|
} elsif ( "$cmdline[0]" eq "NONE" ) {
|
|
warn "Latexmk::Run: ",
|
|
"Program not implemented for this version. Command line:\n";
|
|
warn " \"@cmdline\"\n";
|
|
return 1;
|
|
}
|
|
|
|
# The command is given to system as a single argument, to force shell
|
|
# metacharacters to be interpreted:
|
|
return system join( ' ', @cmdline);
|
|
}
|
|
|
|
#************************************************************
|