From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- support/latexmk/latexmk.pl | 9968 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 9968 insertions(+) create mode 100755 support/latexmk/latexmk.pl (limited to 'support/latexmk/latexmk.pl') diff --git a/support/latexmk/latexmk.pl b/support/latexmk/latexmk.pl new file mode 100755 index 0000000000..7dd5dc35e3 --- /dev/null +++ b/support/latexmk/latexmk.pl @@ -0,0 +1,9968 @@ +#!/usr/bin/env perl + +#!!!!!!!!!!!!!!!!!!!????????? CLEAN UP INITIALIZATION +#!!! See all FIX items. + +# Perhaps add subroutine rdb_change_active( (rules to deactivate), (rules to activate)) + +# ?? Still need to fix bcf error issue. +# Don't keep looping after error +# pvc: Only re-run on USER FILE CHANGE. +# See # ??????? BCF + + +#!!!!!!!!??? Check @pwd_log + + +# !!!!!!!!!! Don't forget to document $silence_logfile_warnings.!!! + +# N.B. !!!!!!!!!!! See 17 July 2012 comments !!!!!!!!!!!!!!!!!! + +# On a UNIX-like system, the above enables latexmk to run independently +# of the location of the perl executable. This line relies on the +# existence of the program /usr/bin/env +# If there is a problem for any reason, you can replace the first line of +# this file by: + +#!/usr/bin/perl -w + +# with the path of the perl executable adjusted for your system. + +use warnings; + +# Delete #??!! when working + +# See ?? <=============================== + +## ?? Issues with clean-up +## List of aux files deleted is those read, not those generated. +## Other files are generated by (pdf)latex; should they be deleted? +## (I have hooks for this). + + + +#======================================= + +#?? Force mode doesn't appear to do force (if error in latex file) +#??? Get banner back in. +#?? CORRECT DIAGNOSTICS ON CHANGED FILES IF THEY DIDN'T EXIST BEFORE +#?? Further corrections to deal with disappeared source files for custom dependencies. +# Message repeatedly appears about remake when source file of cusdep doesn't exist. +#?? logfile w/o fdb file: don't set changed file, perhaps for generated exts. +# Reconsider +#?? Do proper run-stuff for bibtex, makeindex, cus-deps. OK I think +# Parse and correctly find ist files + + +# ATTEMPT TO ALLOW FILENAMES WITH SPACES: +# (as of 1 Apr 2006, and then 14 Sep. 2007) + +# Problems: +# A. Quoting filenames will not always work. +# a. Under UNIX, quotes are legal in filenames, so when PERL +# directly runs a binary, a quoted filename will be treated as +# as a filename containing a quote character. But when it calls +# a shell, the quotes are handled by the shell as quotes. +# b. Under MSWin32, quotes are illegal filename characters, and tend +# to be handled correctly. +# c. But under cygwin, results are not so clear (there are many +# combinations: native v. cygwin perl, native v cygwin programs +# NT v. unix scripts, which shell is called. +# B. TeX doesn't always handle filenames with spaces gracefully. +# a. UNIX/LINUX: The version on gluon2 Mar 31, 2006 to Sep. 2007) +# doesn't handle them at all. (TeX treats space as separator.) +# b. At least some later versions actually do (Brad Miller e-mail, +# Sep. 2007). +# c. fptex [[e-TeXk, Version 3.141592-2.1 (Web2c 7.5.2)] does, on +# my MSWin at home. In \input the filename must be in quotes. +# d. Bibtex [BibTeX (Web2c 7.5.2) 0.99c on my MSWin system at home, +# Sep. 2007] does not allow names of bibfiles to have spaces. +# C. =====> Using the shell for command lines is not safe, since special +# characters can cause lots of mayhem. +# It will therefore be a good idea to sanitize filenames. +# +# I've sanitized all calls out: +# a. system and exec use a single argument, which forces +# use of shell, under all circumstances +# Thus I can safely use quotes on filenames: They will be handled by +# the shell under UNIX, and simply passed on to the program under MSWin32. +# b. I reorganized Run, Run_Detached to use single command line +# c. All calls to Run and Run_Detached have quoted filenames. +# d. So if a space-free filename with wildcards is given on latexmk's +# command line, and it globs to space-containing filename(s), that +# works (fptex on home computer, native NT tex) +# e. ====> But globbing fails: the glob function takes space as filename +# separator. ==================== + +#================= TO DO ================ +# +# 1. See ?? ESPECIALLY $MSWin_fudge_break +# 2. Check fudged conditions in looping and make_files +# 3. Should not completely abort after a run that ends in failure from latex +# Missing input files (including via custom dependency) should be checked for +# a change in status +# If sources for missing files from custom dependency +# are available, then do a rerun +# If sources of any kind become available rerun (esp. for pvc) +# rerun +# Must parse log_file after unsuccessful run of latex: it may give +# information about missing files. +# 4. Check file of bug reports and requests +# 5. Rationalize bibtex warnings and errors. Two almost identical routines. +# Should 1. Use single routine +# 2. Convert errors to failure only in calling routine +# 3. Save first warning/error. + +# ?? Use of generated_exts arrays and hashes needs rationalization + +# To do: +# Rationalize again handling of include files. +# Now I use kpsewhich to do searches, if file not found +# (How do I avoid getting slowed down too much?) +# Document the assumptions at each stage of processing algorithm. +# 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 + +## Copyright John Collins 1998-2019 +## (username jcc8 at node psu.edu) +## (and thanks to David Coppit (username david at node 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 +## +## +## +## NEW FEATURES, since v. 2.0: +## 1. Correct algorithm for deciding how many times to run latex: +## based on whether source file(s) change 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. +## +## Modification log from 9 Dec 2011 onwards in detail +## +## 12 Jan 2012 STILL NEED TO DOCUMENT some items below +## +## 28 Jun 2019 John Collins Try to deal with log file parsing problems +## V. 4.65 +## 21 May 2019 John Collins Fix incorrect listings by -rules and by -deps +## 21 May 2019 John Collins V. 4.64a. +## 20,21 May 2019 John Collins Fix problem with not always running dvipdf, +## dvips, xdvpdf because of missing information +## on source files. Do this by adding a +## source_rule hash to each rule and adding a +## pass-based criterion for out-of-dateness +## 20 May 2019 John Collins V. 4.64. +## 17 Mar 2019 John Collins V. 4.63c. +## 18 Mar 2019 John Collins Update copyright date +## 17 Mar 2019 John Collins Further test for problems when linking rules +## 17 Mar 2019 John Collins V. 4.63b. +## 17 Mar 2019 John Collins Fix problem revealed by bibtopic package +## 15 Mar 2019 John Collins Corrections +## 14 Mar 2019 John Collins Version to 4.63a +## 12-14 Mar 2019 John Collins Jobname has placeholder +## 8-11 Mar 2019 John Collins Correct aux-dir bugs +## 8 Mar 2019 John Collins Version to 4.63 +## 1 Jan 2019 John Collins Correct bug in output switching code +## 31 Dec 2018 John Collins Correct bug that with $cleanup_includes_generated +## -c mode deletes final output files (e.g., .dvi, .pdf). +## 13 Dec 2018 John Collins Fixes, cleanup +## 12 Dec 2018 John Collins Fix rdb_read +## 11 Dec 2018 John Collins For output-switch: Reorganize initialization +## Remove possibility of more than one primary. +## 1 Dec 2018 John Collins Clean up some code. +## 30 Nov 2018 John Collins Allow any characters in directory part of tex +## filename when cd mode on. (Still standard +## set of disallowed characters applies basename.) +## 21 Nov 2018 John Collins Infrastructure finished, I think, for active flag +## Start on output switch +## 16 Nov 2018 John Collins Remove in non-diagnostics mode a warning about +## rule not in use in this session that is given +## when reading an fdb_latexmk file. +## 2 Nov 2018 John Collins Start implementing active flag for rules. +## 1 Nov 2018 John Collins Fix finding of missing files that are relative to aux_dir +## 29-31 Oct 2018 John Collins Some cleanup. +## 27,28 Oct 2018 John Collins Fix bug that in -pvc mode, after an error in +## certain rules, new rounds of compilation +## are triggered because of changes in generated +## files, instead of only by later user-generated +## changes. +## Improve linking of rules. +## 25 Oct 2018 John Collins V. 4.62 +## Clean up can remove (empty) directories +## 25 Oct 2018 John Collins Fix definition of clean up substitution for %R +## so that something with intermediate %R works, +## as in 'pythontex-files-%R/*'. +## +## 1998-2018, John Collins. Many improvements and fixes. +## See CHANGE-log.txt for full list, and CHANGES for summary +## +## Modified by Evan McLean (no longer available for support) +## Original script (RCS version 2.3) called "go" written by David J. Musliner +## +##----------------------------------------------------------------------- + + +## Explicit exit codes: +## 10 = bad command line arguments +## 11 = file specified on command line not found +## or other file not found +## 12 = failure in some part of making files +## 13 = error in initialization file +## 20 = probable bug +## or retcode from called program. + +$my_name = 'latexmk'; +$My_name = 'Latexmk'; +$version_num = '4.65'; +$version_details = "$My_name, John Collins, 18 June 2019"; + +use Config; +use File::Basename; +use File::Copy; +use File::Spec; + +# If possible, use better glob, which does not use space as item separator. +# It's either File::Glob::bsd_glob or File::Glob::glob +# The first does not exist in old versions of Perl, while the second +# is deprecated in more recent versions and will be removed +$have_bsd_glob = 0; +sub my_glob { + if ($have_bsd_glob) { return bsd_glob( $_[0] ); } + else { return glob( $_[0] ); } +} +use File::Glob; +if ( eval{ File::Glob->import('bsd_glob'); 1; } ) { + # Success in importing bsd_glob + $have_bsd_glob = 1; +} +elsif ( eval{ File::Glob->import('glob'); 1; } ) { + warn "$My_name: I could not import File::Glob:bsd_glob, probably because your\n", + " Perl is too old. I have arranged to use the deprecated File::Glob:glob\n", + " instead.\n", + " WARNING: It may malfunction on clean up operation on filenames containing\n", + " spaces.\n"; + $have_bsd_glob = 0; +} +else { + die "Could not import 'File::Glob:bsd_glob' or 'File::Glob:glob'\n"; +} + +use File::Path 2.08 qw( make_path ); +use FileHandle; +use File::Find; +use List::Util qw( max ); +use Cwd; # To be able to change cwd +use Cwd "chdir"; # Ensure $ENV{PWD} tracks cwd +use Digest::MD5; + +#use strict; + +# The following variables are assigned once and then used in symbolic +# references, so we need to avoid warnings 'name used only once': +use vars qw( $dvi_update_command $ps_update_command $pdf_update_command ); + +# Translation of signal names to numbers and vv: +%signo = (); +@signame = (); +if ( defined $Config{sig_name} ) { + $i = 0; + foreach $name (split('\s+', $Config{sig_name})) { + $signo{$name} = $i; + $signame[$i] = $name; + $i++; + } +} +else { + warn "Something wrong with the perl configuration: No signals?\n"; +} + + +# Line length in log file that indicates wrapping. +# This number EXCLUDES line-end characters, and is one-based. +# It is the parameter max_print_line in the TeX program. (tex.web) +$log_wrap = 79; + +######################################################################### +## Default parsing and file-handling settings + +## Array of reg-exps for patterns in log-file for file-not-found +## Each item is the string in a regexp, without the enclosing slashes. +## First parenthesized part is the filename. +## Note the need to quote slashes and single right quotes to make them +## appear in the regexp. +## Add items by push, e.g., +## push @file_not_found, '^No data file found `([^\\\']*)\\\''; +## will give match to line starting "No data file found `filename'" +@file_not_found = ( + '^No file\\s*(.*)\\.$', + '^\\! LaTeX Error: File `([^\\\']*)\\\' not found\\.', + '.*?:\\d*: LaTeX Error: File `([^\\\']*)\\\' not found\\.', + '^LaTeX Warning: File `([^\\\']*)\\\' not found', + '^Package .* [fF]ile `([^\\\']*)\\\' not found', + '^Package .* No file `([^\\\']*)\\\'', + 'Error: pdflatex \(file ([^\)]*)\): cannot find image file', + ': File (.*) not found:\s*$', + '! Unable to load picture or PDF file \\\'([^\\\']+)\\\'.', +); + +# Characters that we won't allow in the name of a TeX file. +# Notes: Some are disallowed by TeX itself. +# '\' results in TeX macro expansion +# '$' results in possible variable substitution by kpsewhich called from tex. +# '"' gets special treatment. +# See subroutine test_fix_texnames and its call for their use. +$illegal_in_texname = "\x00\t\f\n\r\$%\\~\x7F"; + + +## Hash mapping file extension (w/o period, e.g., 'eps') to a single regexp, +# whose matching by a line in a file with that extension indicates that the +# line is to be ignored in the calculation of the hash number (md5 checksum) +# for the file. Typically used for ignoring datestamps in testing whether +# a file has changed. +# Add items e.g., by +# $hash_calc_ignore_pattern{'eps'} = '^%%CreationDate: '; +# This makes the hash calculation for an eps file ignore lines starting with +# '%%CreationDate: ' +# ?? Note that a file will be considered changed if +# (a) its size changes +# or (b) its hash changes +# So it is useful to ignore lines in the hash calculation only if they +# are of a fixed size (as with a date/time stamp). +%hash_calc_ignore_pattern =(); + + +# Specification of templates for extra rules. +# See subroutine rdb_initialize_rules for examples of rule templates, and +# how they get used to construct rules. +# (Documentation obviously needs to be improved!) +%extra_rule_spec = (); + + +# Hooks for customized extra processing on aux files. The following +# variable is an array of references to function. Each function is +# invoked in turn when a line of an aux file is processed (if none +# of the built-in actions have been done). On entry to the function, +# the following variables are set: +# $_ = current line of aux file +# $rule = name of rule during the invocation of which, the aux file +# was supposed to have been generated. +@aux_hooks = (); + +######################################################################### +## Default document processing programs, and related settings, +## These are mostly the same on all systems. +## Most of these variables represents the external command needed to +## perform a certain action. Some represent switches. + + +## Which TeX distribution is being used +## E.g., "MiKTeX 2.9", "TeX Live 2018" +## "" means not determined. Obtain from first line of .log file. +$tex_distribution = ''; + +&std_tex_cmds; + +# Possible code to execute by *latex before inputting source file. +# Not used by default. +$pre_tex_code = ''; + +## Default switches: +$latex_default_switches = ''; +$pdflatex_default_switches = ''; +$lualatex_default_switches = ''; + # Note that xelatex is used to give xdv file, not pdf file, hence + # we need the -no-pdf option. +$xelatex_default_switches = '-no-pdf'; + +## Switch(es) to make them silent: +$latex_silent_switch = '-interaction=batchmode'; +$pdflatex_silent_switch = '-interaction=batchmode'; +$lualatex_silent_switch = '-interaction=batchmode'; +$xelatex_silent_switch = '-interaction=batchmode'; + +%input_extensions = (); +# %input_extensions maps primary_rule_name to pointer to hash of file extensions +# used for extensionless files specified in the source file by constructs +# like \input{file} \includegraphics{file} +set_input_ext( 'latex', 'tex', 'eps' ); +set_input_ext( 'pdflatex', 'tex', 'jpg', 'pdf', 'png' ); +$input_extensions{lualatex} = $input_extensions{pdflatex}; +$input_extensions{xelatex} = $input_extensions{pdflatex}; +# Save these values as standards to be used when switching output, +# i.e., when actual primary rule differs from standard. +%standard_input_extensions = %input_extensions; + +%allowed_output_ext = ( ".dvi" => 1, ".xdv" => 1, ".pdf" => 1 ); +# Extensions of files preserved when clean up is by -c rather than -C: +%small_cleanup_preserved_exts = (); +foreach ( 'dvi', 'dviF', 'ps', 'psF', 'pdf', 'synctex.gz', 'xdv' ) { + $small_cleanup_preserved_exts{$_} = 1; +} + + +# Information about options to latex and pdflatex that latexmk will simply +# pass through to (pdf)latex +# Option without arg. maps to itself. +# Option with arg. maps the option part to the full specification +# e.g., -kpathsea-debug => -kpathsea-debug=NUMBER +%allowed_latex_options = (); +%allowed_latex_options_with_arg = (); +foreach ( + ##### + # TeXLive options + "-draftmode switch on draft mode (generates no output PDF)", + "-enc enable encTeX extensions such as \\mubyte", + "-etex enable e-TeX extensions", + "-file-line-error enable file:line:error style messages", + "-no-file-line-error disable file:line:error style messages", + "-fmt=FMTNAME use FMTNAME instead of program name or a %& line", + "-halt-on-error stop processing at the first error", + "-interaction=STRING set interaction mode (STRING=batchmode/nonstopmode/\n". + " scrollmode/errorstopmode)", + "-ipc send DVI output to a socket as well as the usual\n". + " output file", + "-ipc-start as -ipc, and also start the server at the other end", + "-kpathsea-debug=NUMBER set path searching debugging flags according to\n". + " the bits of NUMBER", + "-mktex=FMT enable mktexFMT generation (FMT=tex/tfm/pk)", + "-no-mktex=FMT disable mktexFMT generation (FMT=tex/tfm/pk)", + "-mltex enable MLTeX extensions such as \charsubdef", + "-output-comment=STRING use STRING for DVI file comment instead of date\n". + " (no effect for PDF)", + "-output-format=FORMAT use FORMAT for job output; FORMAT is `dvi\" or `pdf\"", + "-parse-first-line enable parsing of first line of input file", + "-no-parse-first-line disable parsing of first line of input file", + "-progname=STRING set program (and fmt) name to STRING", + "-shell-escape enable \\write18{SHELL COMMAND}", + "-no-shell-escape disable \\write18{SHELL COMMAND}", + "-shell-restricted enable restricted \\write18", + "-src-specials insert source specials into the DVI file", + "-src-specials=WHERE insert source specials in certain places of\n". + " the DVI file. WHERE is a comma-separated value\n". + " list: cr display hbox math par parend vbox", + "-synctex=NUMBER generate SyncTeX data for previewers if nonzero", + "-translate-file=TCXNAME use the TCX file TCXNAME", + "-8bit make all characters printable by default", + + ##### + # MikTeX options not in TeXLive + "-alias=app pretend to be app", + "-buf-size=n maximum number of characters simultaneously present\n". + " in current lines", + "-c-style-errors C-style error messages", + "-disable-installer disable automatic installation of missing packages", + "-disable-pipes disable input (output) from (to) child processes", + "-disable-write18 disable the \\write18{command} construct", + "-dont-parse-first-line disable checking whether the first line of the main\n". + " input file starts with %&", + "-enable-enctex enable encTeX extensions such as \\mubyte", + "-enable-installer enable automatic installation of missing packages", + "-enable-mltex enable MLTeX extensions such as \charsubdef", + "-enable-pipes enable input (output) from (to) child processes", + "-enable-write18 fully enable the \\write18{command} construct", + "-error-line=n set the width of context lines on terminal error\n". + " messages", + "-extra-mem-bot=n set the extra size (in memory words) for large data\n". + " structures", + "-extra-mem-top=n set the extra size (in memory words) for chars,\n". + " tokens, et al", + "-font-max=n set the maximum internal font number", + "-font-mem-size=n set the size, in TeX memory words, of the font memory", + "-half-error-line=n set the width of first lines of contexts in terminal\n". + " error messages", + "-hash-extra=n set the extra space for the hash table of control\n". + " sequences", + "-job-time=file set the time-stamp of all output files equal to\n". + " file's time-stamp", + "-main-memory=n change the total size (in memory words) of the main\n". + " memory array", + "-max-in-open=n set the maximum number of input files and error\n". + " insertions that can be going on simultaneously", + "-max-print-line=n set the width of longest text lines output", + "-max-strings=n set the maximum number of strings", + "-nest-size=n set the maximum number of semantic levels\n". + " simultaneously active", + "-no-c-style-errors standard error messages", + "-param-size=n set the the maximum number of simultaneous macro\n". + " parameters", + "-pool-size=n set the maximum number of characters in strings", + "-record-package-usages=file record all package usages and write them into\n". + " file", + "-restrict-write18 partially enable the \\write18{command} construct", + "-save-size=n set the the amount of space for saving values\n". + " outside of current group", + "-stack-size=n set the maximum number of simultaneous input sources", + "-string-vacancies=n set the minimum number of characters that should be\n". + " available for the user's control sequences and font\n". + " names", + "-tcx=name process the TCX table name", + "-time-statistics show processing time statistics", + "-trace enable trace messages", + "-trace=tracestreams enable trace messages. The tracestreams argument is\n". + " a comma-separated list of trace stream names", + "-trie-size=n set the amount of space for hyphenation patterns", + "-undump=name use name as the name of the format to be used,\n". + " instead of the name by which the program was\n". + " called or a %& line.", + + ##### + # Options passed to (pdf)latex that have special processing by latexmk, + # so they are commented out here. + #-jobname=STRING set the job name to STRING + #-aux-directory=dir Set the directory dir to which auxiliary files are written + #-output-directory=DIR use existing DIR as the directory to write files in + #-quiet + #-recorder enable filename recorder + # + # Options with different processing by latexmk than (pdf)latex + #-help + #-version + # + # Options NOT used by latexmk + #-includedirectory=dir prefix dir to the search path + #-initialize become the INI variant of the compiler + #-ini be pdfinitex, for dumping formats; this is implicitly + # true if the program name is `pdfinitex' +) { + if ( /^([^\s=]+)=/ ) { + $allowed_latex_options_with_arg{$1} = $_; + } + elsif ( /^([^\s=]+)\s/ ) { + $allowed_latex_options{$1} = $_; + } + else { + $allowed_latex_options{$_} = $_; + } +} + +# Arrays of options that will be added to latex and pdflatex. +# These need to be stored until after the command line parsing is finished, +# in case the values of $latex and/or $pdflatex change after an option +# is added. +@extra_latex_options = (); +@extra_pdflatex_options = (); +@extra_lualatex_options = (); +@extra_xelatex_options = (); + + +## Command to invoke biber & bibtex +$biber = 'biber %O %B'; +$bibtex = 'bibtex %O %B'; +# Switch(es) to make biber & bibtex silent: +$bibtex_fudge = 1; # Use hack to get bibtex working in old versions that + # don't handle output-directory. +$biber_silent_switch = '--onlylog'; +$bibtex_silent_switch = '-terse'; +$bibtex_use = 1; # Whether to actually run bibtex to update bbl files. + # This variable is also used in deciding whether to + # delete bbl files in clean up operations. + # 0: Never run bibtex. + # Do NOT delete bbl files on clean up. + # 1: Run bibtex only if the bibfiles exists + # according to kpsewhich, and the bbl files + # appear to be out-of-date. + # Do NOT delete bbl files on clean up. + # 1.5: Run bibtex only if the bibfiles exists + # according to kpsewhich, and the bbl files + # appear to be out-of-date. + # Only delete bbl files on clean up if bibfiles exist. + # 2: Run bibtex when the bbl files are out-of-date + # Delete bbl files on clean up. + # + # In any event bibtex is only run if the log file + # indicates that the document uses bbl files. + +## Command to invoke makeindex +$makeindex = 'makeindex %O -o %D %S'; +# Switch(es) to make makeinex silent: +$makeindex_silent_switch = '-q'; + +## Command to convert dvi file to pdf file directly: +$dvipdf = 'dvipdf %O %S %D'; +# N.B. Standard dvipdf runs dvips and gs with their silent switch, so for +# standard dvipdf $dvipdf_silent_switch is unneeded, but innocuous. +# But dvipdfmx can be used instead, and it has a silent switch (-q). +# So implementing $dvipdf_silent_switch is useful. + +$dvipdf_silent_switch = '-q'; + +## Command to convert dvi file to ps file: +$dvips = 'dvips %O -o %D %S'; +## Command to convert dvi file to ps file in landscape format: +$dvips_landscape = 'dvips -tlandscape %O -o %D %S'; +# Switch(es) to get dvips to make ps file suitable for conversion to good pdf: +# (If this is not used, ps file and hence pdf file contains bitmap fonts +# (type 3), which look horrible under acroread. An appropriate switch +# ensures type 1 fonts are generated. You can put this switch in the +# dvips command if you prefer.) +$dvips_pdf_switch = '-P pdf'; +# Switch(es) to make dvips silent: +$dvips_silent_switch = '-q'; + +## Command to convert ps file to pdf file: +$ps2pdf = 'ps2pdf %O %S %D'; + +## Command to convert xdv file to pdf file +$xdvipdfmx = 'xdvipdfmx -o %D %O %S'; +$xdvipdfmx_silent_switch = '-q'; + + +## Command to search for tex-related files +$kpsewhich = 'kpsewhich %S'; + +## Command to run make: +$make = 'make'; + +##Printing: +$print_type = 'auto'; # When printing, print the postscript file. + # Possible values: 'dvi', 'ps', 'pdf', 'auto', 'none' + # 'auto' ==> set print type according to the printable + # file(s) being made: priority 'ps', 'pdf', 'dvi' + +## 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'; + +# Viewers. These are system dependent, so default to none: +$pdf_previewer = $ps_previewer = $ps_previewer_landscape = $dvi_previewer = $dvi_previewer_landscape = "NONE"; + +$dvi_update_signal = undef; +$ps_update_signal = undef; +$pdf_update_signal = undef; + +$dvi_update_command = undef; +$ps_update_command = undef; +$pdf_update_command = undef; + +$allow_subdir_creation = 1; + +$new_viewer_always = 0; # If 1, always open a new viewer in pvc mode. + # If 0, only open a new viewer if no previous + # viewer for the same file is detected. + +# Commands for use in pvc mode for compiling, success, warnings, and failure; +# they default to empty, i.e., not to use: +$compiling_cmd = $success_cmd = $warning_cmd = $failure_cmd = ""; + +# Commands for printing are highly system dependent, so default to NONE: +$lpr = 'NONE $lpr variable is not configured to allow printing of ps files'; +$lpr_dvi = 'NONE $lpr_dvi variable is not configured to allow printing of dvi files'; +$lpr_pdf = 'NONE $lpr_pdf variable is not configured to allow printing of pdf files'; + + +# The $pscmd below holds a **system-dependent** 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 variable is not configured to detect running processes'; +$pid_position = -1; # offset of PID in output of pscmd. + # Negative means I cannot use ps + + +$quote_filenames = 1; # Quote filenames in external commands + +$del_dir = ''; # Directory into which cleaned up files are to be put. + # If $del_dir is '', just delete the files + +@rc_system_files = (); + +######################################################################### + +################################################################ +## Special variables for system-dependent fudges, etc. +$log_file_binary = 0; # Whether to treat log file as binary + # Normally not, since the log file SHOULD be pure text. + # But Miktex 2.7 sometimes puts binary characters + # in it. (Typically in construct \OML ... after + # overfull box with mathmode.) + # Sometimes there is ctrl/Z, which is not only non-text, + # but is end-of-file marker for MS-Win in text mode. + +$MSWin_fudge_break = 1; # Give special treatment to ctrl/C and ctrl/break + # in -pvc mode under MSWin + # Under MSWin32 (at least with perl 5.8 and WinXP) + # when latexmk is running another program, and the + # user gives ctrl/C or ctrl/break, to stop the + # daughter program, not only does it reach + # the daughter, but also latexmk/perl, so + # latexmk is stopped also. In -pvc mode, + # this is not normally desired. So when the + # $MSWin_fudge_break variable is set, + # latexmk arranges to ignore ctrl/C and + # ctrl/break during processing of files; + # only the daughter programs receive them. + # This fudge is not applied in other + # situations, since then having latexmk also + # stopping because of the ctrl/C or + # ctrl/break signal is desirable. + # The fudge is not needed under UNIX (at least + # with Perl 5.005 on Solaris 8). Only the + # daughter programs receive the signal. In + # fact the inverse would be useful: In + # normal processing, as opposed to -pvc, if + # force mode (-f) is set, a ctrl/C is + # received by a daughter program does not + # also stop latexmk. Under tcsh, we get + # back to a command prompt, while latexmk + # keeps running in the background! + +## Substitute backslashes in file and directory names for +## MSWin command line +$MSWin_back_slash = 1; + +## Separator of elements in search_path. Default is unix value +$search_path_separator = ':'; + + +# Directory for temporary files. Default to current directory. +$tmpdir = "."; + + +# When the aux_dir is on a network share (or the like), its system +# time may differ from the system time on which latexmk is running. +# This complicates the tests of whether particular files have been +# made in a current run of a program or are left over from a previous +# run. One test, which is needed under some situations, is that a +# file was made on a previous run when the files modification time is +# less than the system time when the program is started. (See +# subroutine test_gen_file; this is only needed in a couple of +# situations.) The comparison between file and system times must be +# corrected if there is an offset between system times on the computer +# running latexmk and the computer hosting the file system containing +# aux_dir. The offset is measured in subroutine get_filetime_offset +# by writing a temporary file; the test only needs to be done once. +# +# The following variables are used. Since the system-independent +# values of system and file time are only accurate to a second (or 2 +# seconds for FAT file systems), the offset is also accurate only to a +# second or two. So thresholds are needed below which differences +# are insignificant. +# +# Note that the making or not making of a file is controlled by the +# state of the document being compiled and by latexmk's configuration. +# So a file that is left over from a previous run and not overwritten +# on the current run will have a file time at least many seconds less +# than the current time, corresponding to the time scale for a human +# run-edit-run cycle. +# +$filetime_offset_measured = 0; # Measurement not yet done. +$filetime_offset = 0; # Filetime relative to system time. +$filetime_causality_threshold = 5; # Threshold for detection of left-over file. + # Should be non-negative always, and should + # be bigger than 2 secs if a remote + # filesystem or network share is used. +$filetime_offset_report_threshold = 30; # Threshold beyond which filetime offsets + # are reported; large offsets indicate + # incorrect system time on at least one system. + + +################################################################ + + +# System-dependent overrides: +# Currently, the cases I have tests for are: MSWin32, cygwin, linux and +# darwin, msys, with the main complications being for MSWin32 and cygwin. +# Further special treatment may also be useful for MSYS (for which $^O reports +# "msys"). This is another *nix-emulation/system for MSWindows. At +# present it is treated as unix-like, but the environment variables +# are those of Windows. (The test for USERNAME as well as USER was +# to make latexmk work under MSYS's perl.) +# +if ( $^O eq "MSWin32" ) { +# Pure MSWindows configuration + ## Configuration parameters: + + ## Use first existing case for $tmpdir: + $tmpdir = $ENV{TMPDIR} || $ENV{TEMP} || '.'; + $log_file_binary = 1; # Protect against ctrl/Z in log file from + # Miktex 2.7. + + ## List of possibilities for the system-wide initialization file. + ## The first one found (if any) is used. + @rc_system_files = ( "C:/latexmk/LatexMk", "C:/latexmk/latexmkrc" ); + + $search_path_separator = ';'; # Separator of elements in search_path + + # For a pdf-file, "start x.pdf" starts the pdf viewer associated with + # pdf files, so no program name is needed: + $pdf_previewer = 'start %O %S'; + $ps_previewer = 'start %O %S'; + $ps_previewer_landscape = $ps_previewer; + $dvi_previewer = 'start %O %S'; + $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 signal. Number of signal in $dvi_update_signal, + # $ps_update_signal, $pdf_update_signal + # 3 => viewer can't update, because it locks the file and the file + # cannot be updated. (acroread under MSWIN) + # 4 => run a command to force the update. The commands are + # specified by the variables $dvi_update_command, + # $ps_update_command, $pdf_update_command + $dvi_update_method = 1; + $ps_update_method = 1; + $pdf_update_method = 3; # acroread locks the pdf file +} +elsif ( $^O eq "cygwin" ) { + # The problem is a mixed MSWin32 and UNIX environment. + # Perl decides the OS is cygwin in two situations: + # 1. When latexmk is run from a cygwin shell under a cygwin + # environment. Perl behaves in a UNIX way. This is OK, since + # the user is presumably expecting UNIXy behavior. + # 2. When CYGWIN exectuables are in the path, but latexmk is run + # from a native NT shell. Presumably the user is expecting NT + # behavior. But perl behaves more UNIXy. This causes some + # clashes. + # The issues to handle are: + # 1. Perl sees both MSWin32 and cygwin filenames. This is + # normally only an advantage. + # 2. Perl uses a UNIX shell in the system command + # This is a nasty problem: under native NT, there is a + # start command that knows about NT file associations, so that + # we can do, e.g., (under native NT) system("start file.pdf"); + # But this won't work when perl has decided the OS is cygwin, + # even if it is invoked from a native NT command line. An + # NT command processor must be used to deal with this. + # 3. External executables can be native NT (which only know + # NT-style file names) or cygwin executables (which normally + # know both cygwin UNIX-style file names and NT file names, + # but not always; some do not know about drive names, for + # example). + # Cygwin executables for tex and latex may only know cygwin + # filenames. + # 4. The BIBINPUTS environment variables may be + # UNIX-style or MSWin-style depending on whether native NT or + # cygwin executables are used. They are therefore parsed + # differently. Here is the clash: + # a. If a user is running under an NT shell, is using a + # native NT installation of tex (e.g., fptex or miktex), + # but has the cygwin executables in the path, then perl + # detects the OS as cygwin, but the user needs NT + # behavior from latexmk. + # b. If a user is running under an UNIX shell in a cygwin + # environment, and is using the cygwin installation of + # tex, then perl detects the OS as cygwin, and the user + # needs UNIX behavior from latexmk. + # Latexmk has no way of detecting the difference. The two + # situations may even arise for the same user on the same + # computer simply by changing the order of directories in the + # path environment variable + + + ## Configuration parameters: We'll assume native NT executables. + ## The user should override if they are not. + + # This may fail: perl converts MSWin temp directory name to cygwin + # format. Names containing this string cannot be handled by native + # NT executables. + $tmpdir = $ENV{TMPDIR} || $ENV{TEMP} || '.'; + + ## List of possibilities for the system-wide initialization file. + ## The first one found (if any) is used. + ## We could stay with MSWin files here, since cygwin perl understands them + ## @rc_system_files = ( 'C:/latexmk/LatexMk', 'C:/latexmk/latexmkrc' ); + ## But they are deprecated in v. 1.7. So use the UNIX version, prefixed + ## with a cygwin equivalent of the MSWin location + ## In addition, we need to add the same set of possible locations as with + ## unix, so that the user use a unix-style setup. + @rc_system_files = (); + foreach ( 'LatexMk', 'latexmkrc' ) { + push @rc_system_files, + ( "/cygdrive/c/latexmk/$_", + "/opt/local/share/latexmk/$_", + "/usr/local/share/latexmk/$_", + "/usr/local/lib/latexmk/$_" ); + } + $search_path_separator = ';'; # Separator of elements in search_path + # This is tricky. The search_path_separator depends on the kind + # of executable: native NT v. cygwin. + # So the user will have to override this. + + # We will assume that files can be viewed by native NT programs. + # Then we must fix the start command/directive, so that the + # NT-native start command of a cmd.exe is used. + # For a pdf-file, "start x.pdf" starts the pdf viewer associated with + # pdf files, so no program name is needed: + $start_NT = "cmd /c start \"\""; + $pdf_previewer = "$start_NT %O %S"; + $ps_previewer = "$start_NT %O %S"; + $ps_previewer_landscape = $ps_previewer; + $dvi_previewer = "$start_NT %O %S"; + $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 signal. Number of signal in $dvi_update_signal, + # $ps_update_signal, $pdf_update_signal + # 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 +} +elsif ( $^O eq "msys" ) { + $search_path_separator = ';'; # Separator of elements in search_path + # I think MS-Win value is OK, since + # msys is running under MS-Win + $pdf_previewer = q[sh -c 'start %S']; + $ps_previewer = q[sh -c 'start %S']; + $dvi_previewer = q[sh -c 'start %S']; + $ps_previewer_landscape = $ps_previewer; + $dvi_previewer_landscape = "$dvi_previewer"; +} +else { + # Assume anything else is UNIX or clone + # Do special cases (e.g., linux, darwin (i.e., OS-X)) inside this block. + + ## Use first existing case for $tmpdir: + $tmpdir = $ENV{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. + ## But /usr/local/lib/latexmk is put in the list for + ## compatibility with older versions of latexmk. + @rc_system_files = (); + foreach ( 'LatexMk', 'latexmkrc' ) { + push @rc_system_files, + ( "/opt/local/share/latexmk/$_", + "/usr/local/share/latexmk/$_", + "/usr/local/lib/latexmk/$_" ); + } + $search_path_separator = ':'; # Separator of elements in search_path + + $dvi_update_signal = $signo{USR1} + if ( defined $signo{USR1} ); # Suitable for xdvi + $ps_update_signal = $signo{HUP} + if ( defined $signo{HUP} ); # Suitable for gv + $pdf_update_signal = $signo{HUP} + if ( defined $signo{HUP} ); # Suitable for gv + ## default document processing programs. + # 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 signal. Number of signal in $dvi_update_signal, + # $ps_update_signal, $pdf_update_signal + # 3 => viewer can't update, because it locks the file and the file + # cannot be updated. (acroread under MSWIN) + # 4 => Run command to update. Command in $dvi_update_command, + # $ps_update_command, $pdf_update_command. + $dvi_previewer = 'start xdvi %O %S'; + $dvi_previewer_landscape = 'start xdvi -paper usr %O %S'; + if ( defined $dvi_update_signal ) { + $dvi_update_method = 2; # xdvi responds to signal to update + } else { + $dvi_update_method = 1; + } +# if ( defined $ps_update_signal ) { +# $ps_update_method = 2; # gv responds to signal to update +# $ps_previewer = 'start gv -nowatch'; +# $ps_previewer_landscape = 'start gv -swap -nowatch'; +# } else { +# $ps_update_method = 0; # gv -watch watches the ps file +# $ps_previewer = 'start gv -watch'; +# $ps_previewer_landscape = 'start gv -swap -watch'; +# } + # Turn off the fancy options for gv. Regular gv likes -watch etc + # GNU gv likes --watch etc. User must configure + $ps_update_method = 0; # gv -watch watches the ps file + $ps_previewer = 'start gv %O %S'; + $ps_previewer_landscape = 'start gv -swap %O %S'; + $pdf_previewer = 'start acroread %O %S'; + $pdf_update_method = 1; # acroread under unix needs manual update + $lpr = 'lpr %O %S'; # Assume lpr command prints postscript files correctly + $lpr_dvi = + 'NONE $lpr_dvi variable is not configured to allow printing of dvi files'; + $lpr_pdf = + 'NONE $lpr_pdf variable is not configured to allow printing of pdf files'; + # 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{USER} to get all processes started by current user (not just + # those associated with current terminal), but none of other users' + # processes. + # However, the USER environment variable may not exist. Windows uses + # USERNAME instead. (And this propagates to a situation of + # unix-emulation software running under Windows.) + if ( exists $ENV{USER} ) { + $pscmd = "ps -f -u $ENV{USER}"; + } + elsif ( exists $ENV{USERNAME} ) { + $pscmd = "ps -f -u $ENV{USERNAME}"; + } + else { + $pscmd = "ps -f"; + } + $pid_position = 1; # offset of PID in output of pscmd; first item is 0. + if ( $^O eq "linux" ) { + # Ps on Redhat (at least v. 7.2) appears to truncate its output + # at 80 cols, so that a long command string is truncated. + # Fix this with the --width option. This option works under + # other versions of linux even if not necessary (at least + # for SUSE 7.2). + # However the option is not available under other UNIX-type + # systems, e.g., Solaris 8. + # But (19 Aug 2010), the truncation doesn't happen on RHEL4 and 5, + # unless the output is written to a terminal. So the --width + # option is now unnecessary + # $pscmd = "ps --width 200 -f -u $ENV{USER}"; + } + elsif ( $^O eq "darwin" ) { + # OS-X on Macintosh + # open starts command associated with a file. + # For pdf, this is set by default to OS-X's preview, which is suitable. + # Manual update is simply by clicking on window etc, which is OK. + # For ps, this is set also to preview. This works, but since it + # converts the file to pdf and views the pdf file, it doesn't + # see updates, and a refresh cannot be done. This is far from + # optimal. + # For a full installation of MacTeX, which is probably the most common + # on OS-X, an association is created between dvi files and TeXShop. + # This also converts the file to pdf, so again while it works, it + # does not deal with changed dvi files, as far as I can see. + $pdf_previewer = 'open %S'; + $pdf_update_method = 1; # manual + $dvi_previewer = $dvi_previewer_landscape = 'NONE'; + $ps_previewer = $ps_previewer_landscape = 'NONE'; + # Others + $lpr_pdf = 'lpr %O %S'; + $pscmd = "ps -ww -u $ENV{USER}"; + } +} + +## default parameters +$auto_rc_use = 1; # Whether to read rc files automatically +$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. + # At least one document class (JHEP.cls) works + # in such a way that a 4th run is needed. + # We allow an extra run for safety for a + # maximum of 5. Needing further runs is + # usually an indication of a problem; further + # runs may not resolve the problem, and + # instead could cause an infinite loop. +$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 +@default_files = ( '*.tex' ); # Array of LaTeX files to process when + # no files are specified on the command line. + # Wildcards allowed + # Best used for project specific files. +@default_excluded_files = ( ); + # Array of LaTeX files to exclude when using + # @default_files, i.e., when no files are specified + # on the command line. + # Wildcards allowed + # Best used for project specific files. +$texfile_search = ""; # Specification for extra files to search for + # when no files are specified on the command line + # and the @default_files variable is empty. + # Space separated, and wildcards allowed. + # These files are IN ADDITION to *.tex in current + # directory. + # This variable is obsolete, and only in here for + # backward compatibility. + +$fdb_ext = 'fdb_latexmk'; # Extension for the file for latexmk's + # file-database + # Make it long to avoid possible collisions. +$fdb_ver = 3; # Version number for kind of fdb_file. + +$jobname = ''; # Jobname: as with current tex, etc indicates + # basename of generated files. Defined so + # that --jobname=STRING on latexmk's command + # line has same effect as with current tex, + # etc, with the exception listed below. (If + # $jobname is non-empty, then the + # --jobname=... option is used on tex.) + # Extension: $jobname is allowed to contain + # placeholder(s) (currently only %A), + # which allows construction of jobnames + # dependent on name of main TeX file; this is + # useful when a jobname is used and latexmk is + # invoked on multiple files. +$out_dir = ''; # Directory for output files. + # Cf. --output-directory of current (pdf)latex +$aux_dir = ''; # Directory for aux files (log, aux, etc). + # Cf. --aux-directory of current (pdf)latex in MiKTeX. + + +## default flag settings. +$recorder = 1; # Whether to use recorder option on latex/pdflatex +$silent = 0; # Silence latex's messages? +$warnings_as_errors = 0;# Treat warnings as errors and exit with non-zero exit code +$silence_logfile_warnings = 0; # Do list warnings in log file +$kpsewhich_show = 0; # Show calls to and results from kpsewhich +$landscape_mode = 0; # default to portrait mode +$analyze_input_log_always = 1; # Always analyze .log for input files in the + # <...> and (...) constructions. Otherwise, only + # do the analysis when fls file doesn't exist or is + # out of date. + # Under normal circumstances, the data in the fls file + # is reliable, and the test of the log file gets lots + # of false positives; usually $analyze_input_log_always + # is best set to zero. But the test of the log file + # is needed at least in the following situation: + # When a user needs to persuade latexmk that a certain + # file is a source file, and latexmk doesn't otherwise + # find it. User code causes line with (...) to be + # written to log file. One important case is for + # lualatex, which doesn't always generate lines in the + # .fls file for input lua files. (The situation with + # lualatex is HIGHLY version dependent, e.g., between + # 2016 and 2017.) + # To keep backward compatibility with older versions + # of latexmk, the default is to set + # $analyze_input_log_always to 1. + +# The following two arrays contain lists of extensions (without +# period) for files that are read in during a (pdf)LaTeX run but that +# are generated automatically from the previous run, as opposed to +# being user generated files (directly or indirectly from a custom +# dependency). These files get two kinds of special treatment: +# 1. In clean up, where depending on the kind of clean up, some +# or all of these generated files are deleted. +# (Note that special treatment is given to aux files.) +# 2. In analyzing the results of a run of (pdf)LaTeX, to +# determine if another run is needed. With an error free run, +# a rerun should be provoked by a change in any source file, +# whether a user file or a generated file. But with a run +# that ends in an error, only a change in a user file during +# the run (which might correct the error) should provoke a +# rerun, but a change in a generated file should not. +# These arrays can be user-configured. + +@generated_exts = ( 'aux', 'bcf', 'fls', 'idx', 'ind', 'lof', 'lot', + 'out', 'toc' ); + # N.B. 'out' is generated by hyperref package + +# 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 + # Possible values: + # 0 don't create pdf file + # 1 to create pdf file by pdflatex + # 2 to create pdf file by ps2pdf + # 3 to create pdf file by dvipdf + # 4 to create pdf file by lualatex + # 5 to create pdf file by xelatex + xdvipdfmx +$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 +$do_cd = 0; # Do not do cd to directory of source file. + # Thus behave like latex. +$dependents_list = 0; # Whether to display list(s) of dependencies +$dependents_phony = 0; # Whether list(s) of dependencies includes phony targets + # (as with 'gcc -MP'). +$deps_file = '-'; # File for dependency list output. Default stdout. +$rules_list = 0; # Whether to display list(s) of dependencies +@dir_stack = (); # Stack of pushed directories, each of form of + # pointer to array [ cwd, good_cwd ], where + # good_cwd differs from cwd by being converted + # to native MSWin path when cygwin is used. +$cleanup_mode = 0; # No cleanup of nonessential LaTex-related files. + # $cleanup_mode = 0: no cleanup + # $cleanup_mode = 1: full cleanup + # $cleanup_mode = 2: cleanup except for dvi, + # dviF, pdf, ps, psF & xdv +$cleanup_fdb = 0; # No removal of file for latexmk's file-database +$cleanup_only = 0; # When doing cleanup, do not go on to making files +$cleanup_includes_generated = 0; + # Determines whether cleanup deletes files generated by + # (pdf)latex (found from \openout lines in log file). + # It's more than that. BUG +$cleanup_includes_cusdep_generated = 0; + # Determines whether cleanup deletes files generated by + # custom dependencies +$diagnostics = 0; +$dvi_filter = ''; # DVI filter command +$ps_filter = ''; # Postscript filter command + +$force_mode = 0; # =1 to force processing past errors +$go_mode = 0; # =1 to force processing regardless of time-stamps + # =2 full clean-up first +$preview_mode = 0; +$preview_continuous_mode = 0; +$printout_mode = 0; # Don't print the file + +## Control pvc inactivity timeout: +$pvc_timeout = 0; +$pvc_timeout_mins = 30; + +$show_time = 0; +@timings = (); +$processing_time1 = processing_time(); + +$use_make_for_missing_files = 0; # Whether to use make to try to make missing files. + +# Do we make view file in temporary then move to final destination? +# (To avoid premature updating by viewer). +$always_view_file_via_temporary = 0; # Set to 1 if viewed file is always + # made through a temporary. +$pvc_view_file_via_temporary = 1; # Set to 1 if only in -pvc mode is viewed + # file made through a temporary. + +# State variables initialized here: + +$updated = 0; # Flags when something has been remade + # Used to allow convenient user message in -pvc mode +$waiting = 0; # Flags whether we are in loop waiting for an event + # Used to avoid unnecessary repeated o/p in wait loop + +# The following are used for some results of parsing log file +# Global variables, so results can be reported in main program. +$reference_changed = 0; +$mult_defined = 0; +$bad_reference = 0; +$bad_character = 0; +$bad_citation = 0; +@primary_warning_summary = (); + +# Cache of expensive-to-compute state variables, e.g., cwd in form +# fixed to deal with cygwin issues. +%cache = (); +&cache_good_cwd; + +# Set search paths for includes. +# Set them early so that they can be overridden +$BIBINPUTS = $ENV{'BIBINPUTS'}; +if (!$BIBINPUTS) { $BIBINPUTS = '.'; } + +# Convert search paths to arrays: +# If any of the paths end in '//' then recursively search the +# directory. After these operations, @BIBINPUTS should +# have all the directories that need to be searched + +@BIBINPUTS = find_dirs1( $BIBINPUTS ); + + +###################################################################### +###################################################################### +# +# ??? UPDATE THE FOLLOWING!! +# +# We will need to determine whether source files for runs of various +# programs are out of date. In a normal situation, this is done by +# asking whether the times of the source files are later than the +# destination files. But this won't work for us, since a common +# situation is that a file is written on one run of latex, for +# example, and read back in on the next run (e.g., an .aux file). +# Some situations of this kind are standard in latex generally; others +# occur with particular macro packages or with particular +# postprocessors. +# +# The correct criterion for whether a source is out-of-date is +# therefore NOT that its modification time is later than the +# destination file, but whether the contents of the source file have +# changed since the last successful run. This also handles the case +# that the user undoes some changes to a source file by replacing the +# source file by reverting to an earlier version, which may well have +# an older time stamp. Since a direct comparison of old and new files +# would involve storage and access of a large number of backup files, +# we instead use the md5 signature of the files. (Previous versions +# of latexmk used the backup file method, but restricted to the case +# of .aux and .idx files, sufficient for most, but not all, +# situations.) +# +# We will have a database of (time, size, md5) for the relevant +# files. If the time and size of a file haven't changed, then the file +# is assumed not to have changed; this saves us from having to +# determine its md5 signature, which would involve reading the whole +# file, which is naturally time-consuming, especially if network file +# access to a server is needed, and many files are involved, when most +# of them don't change. It is of course possible to change a file +# without changing its size, but then to adjust its timestamp +# to what it was previously; this requires a certain amount of +# perversity. We can safely assume that if the user edits a file or +# changes its contents, then the file's timestamp changes. The +# interesting case is that the timestamp does change, because the file +# has actually been written to, but that the contents do not change; +# it is for this that we use the md5 signature. However, since +# computing the md5 signature involves reading the whole file, which +# may be large, we should avoid computing it more than necessary. +# +# So we get the following structure: +# +# 1. For each relevant run (latex, pdflatex, each instance of a +# custom dependency) we have a database of the state of the +# source files that were last used by the run. +# 2. On an initial startup, the database for a primary tex file +# is read that was created by a previous run of latex or +# pdflatex, if this exists. +# 3. If the file doesn't exist, then the criterion for +# out-of-dateness for an initial run is that it goes by file +# timestamps, as in previous versions of latexmk, with due +# (dis)regard to those files that are known to be generated by +# latex and re-read on the next run. +# 4. Immediately before a run, the database is updated to +# represent the current conditions of the run's source files. +# 5. After the run, it is determined whether any of the source +# files have changed. This covers both files written by the +# run, which are therefore in a dependency loop, and files that +# the user may have updated during the run. (The last often +# happens when latex takes a long time, for a big document, +# and the user makes edits before latex has finished. This is +# particularly prevalent when latexmk is used with +# preview-continuous mode.) +# 6. In the case of latex or pdflatex, the custom dependencies +# must also be checked and redone if out-of-date. +# 7. If any source files have changed, the run is redone, +# starting at step 1. +# 8. There is naturally a limit on the number of reruns, to avoid +# infinite loops from bugs and from pathological or unforeseen +# conditions. +# 9. After the run is done, the run's file database is updated. +# (By hypothesis, the sizes and md5s are correct, if the run +# is successful.) +# 10. To allow reuse of data from previous runs, the file database +# is written to a file after every complete set of passes +# through latex or pdflatex. (Note that there is separate +# information for latex and pdflatex; the necessary +# information won't coincide: Out-of-dateness for the files +# for each program concerns the properties of the files when +# the other program was run, and the set of source files could +# be different, e.g., for graphics files.) +# +# We therefore maintain the following data structures.: +# +# a. For each run (latex, pdflatex, each custom dependency) a +# database is maintained. This is a hash from filenames to a +# reference to an array: [time, size, md5]. The semantics of +# the database is that it represents the state of the source +# files used in the run. During a run it represents the state +# immediately before the run; after a run, with all reruns, it +# represents the state of the files used, modified by having +# the latest timestamps for generated files. +# b. There is a global database for all files, which represents +# the current state. This saves having to recompute the md5 +# signatures of a changed file used in more than one run +# (e.g., latex and pdflatex). +# c. Each of latex and pdflatex has a list of the relevant custom +# dependencies. +# +# In all the following a fdb-hash is a hash of the form: +# filename -> [time, size, md5] +# If a file is found to disappear, its entry is removed from the hash. +# In returns from fdb access routines, a size entry of -1 indicates a +# non-existent file. + + +# List of known rules. Rule types: primary, +# external (calls program), internal (calls routine), cusdep. + +%possible_primaries = ( 'latex' => 'primary', 'pdflatex' => 'primary', + 'lualatex' => 'primary', 'xelatex' => 'primary' ); + +# Hashes, whose keys give names of particular kinds of rule, and targets. +# We use hashes for ease of lookup. +%possible_one_time = ( 'view' => 1, 'print' => 1, 'update_view' => 1, ); +%target_files = (); # Hash for target files. + # The keys are the filenames and the value is + # currently irrelevant. +%target_rules = (); # Hash for target rules beyond those corresponding to files. + # The keys are the rule names and the value is + # currently irrelevant. +# The target **files** can only be set inside the FILE loop. +$current_primary = 'latex'; # Rule to compile .tex file. + # Subject to document-dependent override if .tex document + # uses metcommands andobeying them is enabled. +$pdf_method = ''; # How to make pdf file. '' if not requested, + # else 'ps2pdf', 'dvipdf', 'pdflatex', 'lualatex' or 'xelatex' + # Subject to document-dependent override if .tex document + #uses \pdfoutput or c. +%requested_filetypes = (); # Hash of requested file types (dvi, dviF, etc) +%one_time = (); # Hash for requested one-time-only rules, currently + # possible values 'print' and 'view'. + +%actives = (); # Hash of active rules + +$allow_switch = 1; # Allow switch of rule structure to accommodate + # changed output file name of primary. Even if + # this flag is set on, the switch may be + # prohibited by other issues. + +%rule_db = (); # Database of all rules: + # Hash: rulename -> [array of rule data] + # Rule data: + # 0: [ cmd_type, ext_cmd, int_cmd, test_kind, + # source, dest, base, + # out_of_date, out_of_date_user, + # time_of_last_run, time_of_last_file_check, + # changed + # last_result, last_message, + # default_extra_generated, + # ] + # where + # cmd_type is 'primary', 'external', or 'cusdep' + # ext_cmd is string for associated external command + # with substitutions (%D for destination, %S + # for source, %B for base of current rule, + # %R for base of primary tex file, %T for + # texfile name, %O for options, + # %Y for $aux_dir1, and %Z for $out_dir1 + # int_cmd specifies any internal command to be + # used to implement the application of the + # rule. If this is present, it overrides + # the external command, and it is the + # responsibility of the perl subroutine + # specified in intcmd to execute the + # external command if this is appropriate. + # This variable intcmd is a reference to an array, + # $$intcmd[0] = internal routine + # $$intcmd[1...] = its arguments (if any) + # test_kind specifies method of determining + # whether a file is out-of-date: + # 0 for never + # 1 for usual: whether there is a source + # file change + # 2 for dest earlier than source + # 3 for method 2 at first run, 1 thereafter + # (used when don't have file data from + # previous run). + # source = name of primary source file, if any + # dest = name of primary destination file, + # if any + # base = base name, if any, of files for + # this rule + # out_of_date = 1 if it has been detected that + # this rule needs to be run + # (typically because a source + # file has changed). + # Other values may be used for special cases. + # 0 otherwise + # out_of_date_user is like out_of_date, except + # that the detection of out-of-dateness + # has been made from a change of a + # putative user file, i.e., one that is + # not a generated file (e.g., aux). This + # kind of out-of-dateness should provoke a + # rerun whether or not there was an error + # during a run of (pdf)LaTeX. Normally, + # if there is an error, one should wait + # for the user to correct the error. But + # it is possible the error condition is + # already corrected during the run, e.g., + # by the user changing a source file in + # response to an error message. + # time_of_last_run = time that this rule was + # last applied. (In standard units + # from perl, to be directly compared + # with file modification times.) + # time_of_last_file_check = last time that a check + # was made for changes in source files. + # changed flags whether special changes have been made + # that require file-existence status to be ignored + # last_result is + # -1 if no run has been made, + # 0 if the last run was successful + # 1 if last run was successful, but + # failed to create an output file + # 2 if last run failed + # 200 if last run gave a warning that is + # important enough to be reported with + # the error summary. The warning + # message is stored in last_message. + # last_message is error message for last run + # default_extra_generated is a reference to an array + # of specifications of extra generated files (beyond + # the main dest file. Standard place holders are used. + # 1: {Hash sourcefile -> [source-file data] } + # Source-file data array: + # 0: time + # 1: size + # 2: md5 + # 3: name of rule to make this file + # 4: whether the file is of the kind made by epstopdf.sty + # during a primary run. It will have been read during + # the run, so that even though the file changes during + # a primary run, there is no need to trigger another + # run because of this. + # Size and md5 correspond to the values at the last run. + # But time may be updated to correspond to the time + # for the file, if the file is otherwise unchanged. + # This saves excessive md5 calculations, which would + # otherwise be done everytime the file is checked, + # in the following situation: + # When the file has been rewritten after a run + # has started (commonly aux, bbl files etc), + # but the actual file contents haven't + # changed. Then because the filetime has + # changed, on every file-change check latexmk + # would normally redo the md5 calculation to + # test for actual changes. Once one such + # check is done, and the contents are + # unchanged, later checks are superfluous, and + # can be avoided by changing the file's time + # in the source-file list. + # 2: {Hash generated_file -> 1 } + # This lists all generated files; the values + # are currently unused, only the keys + # 3: {Hash source_rule -> last_pass } + # This lists rules that are to be considered source + # rules for the current rule, separately from the + # from_rules of the source files. It maps the name + # of each of these rules to the pass number of the + # current rule when it was last run. The current rule + # is out-of-date if the last_pass for a source rule + # is less than the pass number for the rule. + # The purpose of this is when the source file list + # is expected to be inaccurate, because the source + # files are hard to determine. Typical needs are + # for rules applied to dvi and xdv files, when + # graphics files are involved. Their names are coded + # inside the dvi/xdv file, but not the contents. + # It would need parsing of the contents of the file + # to determine the actual source files. + # An implication of using a source_rule is that this + # rule passes files to the current rule and that the + # current rule can be considered out-of-date whenever + # the source_rule has been run. Effectively these + # files are unconditionallyconsidered changed when + # the source_rule runs. + +%fdb_current = (); # Hash of information for all files used. + # It maps filename to a reference to an array + # (time, size, md5_checksum). +@nofile = (0,-1,0); # What we use for initializing a new entry in fdb + # or flagging non-existent file. + +# The following provide information about the structure of the network of rules +# and files. They are set by the routine rdb_set_rule_net +%from_rules = (); # Used to optimize test for whether a file is generated. + # This maps files to rules that generate them. (Files + # anywhere in %$PHdest.) +%from_rules_main = (); # Used to optimize test for whether a file is generated. + # This maps files to rules that generate them as the + # MAIN output. (I.e., file $$Pdest only.) +# Classification of rules, for determining order of application +%current_primaries = (); # Keys are primary rules (latex, etc) that are currently in use. +@pre_primary = (); # Array of rules that are thought of as pre-primary +@post_primary = (); # Array of rules that are thought of as post-primary +@unusual_one_time = (); # Array of rules that are special cases of one-time rules. + # Currently not used. + + +# User's home directory +$HOME = ''; +if (exists $ENV{'HOME'} ) { + $HOME = $ENV{'HOME'}; +} +elsif (exists $ENV{'USERPROFILE'} ) { + $HOME = $ENV{'USERPROFILE'}; +} +# XDG configuration home +$XDG_CONFIG_HOME = ''; +if (exists $ENV{'XDG_CONFIG_HOME'} ) { + $XDG_CONFIG_HOME = $ENV{'XDG_CONFIG_HOME'}; +} +elsif ($HOME ne '') { + if ( -d "$HOME/.config") { + $XDG_CONFIG_HOME = "$HOME/.config"; + } +} + + +#================================================== + +# Options that are to be obeyed before rc files are read: + +foreach $_ ( @ARGV ) +{ + if (/^-{1,2}norc$/ ) { + $auto_rc_use = 0; + } +} + +#================================================== +## Read rc files with this subroutine + +sub read_first_rc_file_in_list { + foreach my $rc_file ( @_ ) { + #print "===Testing for rc file \"$rc_file\" ...\n"; + if ( -d $rc_file ) { + warn "$My_name: I have found a DIRECTORY named \"$rc_file\".\n", + " Have you perhaps misunderstood latexmk's documentation?\n", + " This name is normally used for a latexmk configuration (rc) file,\n", + " and in that case it should be a regular text file, not a directory.\n"; + } + elsif ( -e $rc_file ) { + #print "===Reading rc file \"$rc_file\" ...\n"; + process_rc_file( $rc_file ); + return; + } + } +} + +# Note that each rc file may unset $auto_rc_use to +# prevent lower-level rc files from being read. +# So test on $auto_rc_use in each case. +if ( $auto_rc_use ) { + # System rc file: + if (exists $ENV{LATEXMKRCSYS} ) { + push @rc_system_files, $ENV{LATEXMKRCSYS}; + if ( !-e $ENV{LATEXMKRCSYS} ) { + warn "$My_name: you've specified a system rc file `$ENV{LATEXMKRCSYS}`\n", + " in environment variable LATEXMKRCSYS, but the file doesn't exist.\n", + " I won't read any system rc file.\n"; + } + else { + process_rc_file( $ENV{LATEXMKRCSYS} ); + } + } + else { + read_first_rc_file_in_list( @rc_system_files ); + } +} +if ( $auto_rc_use && ($HOME ne "" ) ) { + # User rc file: + @user_rc = (); + if ( $XDG_CONFIG_HOME ) { + push @user_rc, "$XDG_CONFIG_HOME/latexmk/latexmkrc"; + } + # N.B. $HOME equals "" if latexmk couldn't determine a home directory. + # In that case, we shouldn't look for an rc file there. + if ( $HOME ) { + push @user_rc, "$HOME/.latexmkrc"; + } + read_first_rc_file_in_list( @user_rc ); +} +if ( $auto_rc_use ) { + # Rc file in current directory: + read_first_rc_file_in_list( "latexmkrc", ".latexmkrc" ); +} + +## Process command line args. +@command_line_file_list = (); +$bad_options = 0; + +while ($_ = $ARGV[0]) +{ + # Make -- and - equivalent at beginning of option, + # but save original for possible use in (pdf)latex command line + $original = $_; + s/^--/-/; + shift; + if ( /^-aux-directory=(.*)$/ || /^-auxdir=(.*)$/ ) { + $aux_dir = $1; + } + elsif (/^-bibtex$/) { $bibtex_use = 2; } + elsif (/^-bibtex-$/) { $bibtex_use = 0; } + elsif (/^-nobibtex$/) { $bibtex_use = 0; } + elsif (/^-bibtex-cond$/) { $bibtex_use = 1; } + elsif (/^-bibtex-cond1$/) { $bibtex_use = 1.5; } + elsif (/^-c$/) { $cleanup_mode = 2; $cleanup_fdb = 1; $cleanup_only = 1; } + elsif (/^-C$/ || /^-CA$/ ) { $cleanup_mode = 1; $cleanup_fdb = 1; $cleanup_only = 1; } + elsif (/^-CF$/) { $cleanup_fdb = 1; } + elsif (/^-cd$/) { $do_cd = 1; } + elsif (/^-cd-$/) { $do_cd = 0; } + elsif (/^-commands$/) { &print_commands; exit; } + elsif (/^-d$/) { $banner = 1; } + elsif (/^-dependents$/ || /^-deps$/ || /^-M$/ ) { $dependents_list = 1; } + elsif (/^-nodependents$/ || /^-dependents-$/ || /^-deps-$/) { $dependents_list = 0; } + elsif (/^-deps-out=(.*)$/) { + $deps_file = $1; + $dependents_list = 1; + } + elsif (/^-diagnostics/) { $diagnostics = 1; } + elsif (/^-dvi$/) { $dvi_mode = 1; } + elsif (/^-dvi-$/) { $dvi_mode = 0; } + elsif (/^-f$/) { $force_mode = 1; } + elsif (/^-f-$/) { $force_mode = 0; } + elsif (/^-g$/) { $go_mode = 1; } + elsif (/^-g-$/) { $go_mode = 0; } + elsif (/^-gg$/) { + $go_mode = 2; $cleanup_mode = 1; $cleanup_fdb = 1; $cleanup_only = 0; + } + elsif ( /^-h$/ || /^-help$/ ) { &print_help; exit;} + elsif (/^-jobname=(.*)$/) { + $jobname = $1; + } + elsif (/^-l$/) { $landscape_mode = 1; } + elsif (/^-l-$/) { $landscape_mode = 0; } + elsif (/^-latex=(.*)$/) { + $latex = $1; + } + elsif (/^-latexoption=(.*)$/) { + push @extra_latex_options, $1; + push @extra_pdflatex_options, $1; + push @extra_lualatex_options, $1; + push @extra_xelatex_options, $1; + } + elsif ( /^-logfilewarninglist$/ || /^-logfilewarnings$/ ) + { $silence_logfile_warnings = 0; } + elsif ( /^-logfilewarninglist-$/ || /^-logfilewarnings-$/ ) + { $silence_logfile_warnings = 1; } +# See above for -M + elsif (/^-MF$/) { + if ( $ARGV[0] eq '' ) { + &exit_help( "No file name specified after -MF switch"); + } + $deps_file = $ARGV[0]; + shift; + } + elsif ( /^-MP$/ ) { $dependents_phony = 1; } + elsif (/^-new-viewer$/) { + $new_viewer_always = 1; + } + elsif (/^-new-viewer-$/) { + $new_viewer_always = 0; + } + elsif (/^-norc$/ ) { + $auto_rc_use = 0; + # N.B. This has already been obeyed. + } + elsif ( /^-output-directory=(.*)$/ ||/^-outdir=(.*)$/ ) { + $out_dir = $1; + } + elsif (/^-p$/) { $printout_mode = 1; + $preview_continuous_mode = 0; # to avoid conflicts + $preview_mode = 0; + } + elsif (/^-p-$/) { $printout_mode = 0; } + elsif (/^-pdf$/) { $pdf_mode = 1; } + elsif (/^-pdf-$/) { $pdf_mode = 0; } + elsif (/^-pdfdvi$/){ $pdf_mode = 3; } + elsif (/^-pdflua$/){ $pdf_mode = 4; } + elsif (/^-pdfps$/) { $pdf_mode = 2; } + elsif (/^-pdfxe$/) { $pdf_mode = 5; } +# elsif (/^-pdflatex$/) { +# $pdflatex = "pdflatex %O %S"; +# $pdf_mode = 1; +# $dvi_mode = $postscript_mode = 0; +# } + elsif (/^-pdflatex=(.*)$/) { + $pdflatex = $1; + } + elsif (/^-pdflualatex=(.*)$/) { + $lualatex = $1; + } + elsif (/^-pdfxelatex=(.*)$/) { + $xelatex = $1; + } + elsif (/^-pretex=(.*)$/) { + $pre_tex_code = $1; + } + elsif (/^-print=(.*)$/) { + $value = $1; + if ( $value =~ /^dvi$|^ps$|^pdf$|^auto$/ ) { + $print_type = $value; + $printout_mode = 1; + } + else { + &exit_help("$My_name: unknown print type '$value' in option '$_'"); + } + } + elsif (/^-ps$/) { $postscript_mode = 1; } + elsif (/^-ps-$/) { $postscript_mode = 0; } + elsif (/^-pv$/) { $preview_mode = 1; + $preview_continuous_mode = 0; # to avoid conflicts + $printout_mode = 0; + } + elsif (/^-pv-$/) { $preview_mode = 0; } + elsif (/^-pvc$/) { $preview_continuous_mode = 1; + $force_mode = 0; # So that errors do not cause loops + $preview_mode = 0; # to avoid conflicts + $printout_mode = 0; + } + elsif (/^-pvc-$/) { $preview_continuous_mode = 0; } + elsif (/^-pvctimeout$/) { $pvc_timeout = 1; } + elsif (/^-pvctimeout-$/) { $pvc_timeout = 0; } + elsif (/^-pvctimeoutmins=(.*)$/) { $pvc_timeout_mins = $1; } + elsif (/^-recorder$/ ){ $recorder = 1; } + elsif (/^-recorder-$/ ){ $recorder = 0; } + elsif (/^-rules$/ ) { $rules_list = 1; } + elsif (/^-norules$/ || /^-rules-$/ ) { $rules_list = 0; } + elsif (/^-showextraoptions$/) { + print "List of extra latex and pdflatex options recognized by $my_name.\n", + "These are passed as is to (pdf)latex. They may not be recognized by\n", + "particular versions of (pdf)latex. This list is a combination of those\n", + "for TeXLive and MikTeX.\n", + "\n", + "Note that in addition to the options in this list, there are several\n", + "options known to the (pdf)latex programs that are also recognized by\n", + "latexmk and trigger special behavior by latexmk. Since these options\n", + "appear in the main list given by running 'latexmk --help', they do not\n", + "appear in the following list\n", + "NOTE ALSO: Not all of these options are supported by all versions of (pdf)latex.\n", + "\n"; + foreach $option ( sort( keys %allowed_latex_options, keys %allowed_latex_options_with_arg ) ) { + if (exists $allowed_latex_options{$option} ) { print " $allowed_latex_options{$option}\n"; } + if (exists $allowed_latex_options_with_arg{$option} ) { print " $allowed_latex_options_with_arg{$option}\n"; } + } + exit; + } + elsif (/^-silent$/ || /^-quiet$/ ){ $silent = 1; } + elsif (/^-stdtexcmds$/) { &std_tex_cmds; } + elsif (/^-time$/) { $show_time = 1;} + elsif (/^-time-$/) { $show_time = 0;} + elsif (/^-use-make$/) { $use_make_for_missing_files = 1; } + elsif (/^-use-make-$/) { $use_make_for_missing_files = 0; } + elsif (/^-usepretex$/) { &alt_tex_cmds; } + elsif (/^-usepretex=(.*)$/) { + &alt_tex_cmds; + $pre_tex_code = $1; + } + elsif (/^-v$/ || /^-version$/) { + print "\n$version_details. Version $version_num\n"; + exit; + } + elsif (/^-verbose$/) { $silent = 0; } + elsif (/^-view=default$/) { $view = "default";} + elsif (/^-view=dvi$/) { $view = "dvi";} + elsif (/^-view=none$/) { $view = "none";} + elsif (/^-view=ps$/) { $view = "ps";} + elsif (/^-view=pdf$/) { $view = "pdf"; } + elsif (/^-Werror$/){ $warnings_as_errors = 1; } + elsif (/^-lualatex$/) { + $pdf_mode = 4; + $dvi_mode = $postscript_mode = 0; + } + elsif (/^-xelatex$/) { + $pdf_mode = 5; + $dvi_mode = $postscript_mode = 0; + } + elsif (/^-e$/) { + if ( $#ARGV < 0 ) { + &exit_help( "No code to execute specified after -e switch"); + } + execute_code_string( $ARGV[0] ); + shift; + } + elsif (/^-r$/) { + if ( $ARGV[0] eq '' ) { + &exit_help( "No RC file specified after -r switch"); + } + if ( -e $ARGV[0] ) { + process_rc_file( $ARGV[0] ); + } + else { + die "$My_name: RC file [$ARGV[0]] does not exist\n"; + } + shift; + } + elsif (/^-bm$/) { + if ( $ARGV[0] eq '' ) { + &exit_help( "No message specified after -bm switch"); + } + $banner = 1; $banner_message = $ARGV[0]; + shift; + } + elsif (/^-bi$/) { + if ( $ARGV[0] eq '' ) { + &exit_help( "No intensity specified after -bi switch"); + } + $banner_intensity = $ARGV[0]; + shift; + } + elsif (/^-bs$/) { + if ( $ARGV[0] eq '' ) { + &exit_help( "No scale specified after -bs switch"); + } + $banner_scale = $ARGV[0]; + shift; + } + elsif (/^-dF$/) { + if ( $ARGV[0] eq '' ) { + &exit_help( "No dvi filter specified after -dF switch"); + } + $dvi_filter = $ARGV[0]; + shift; + } + elsif (/^-pF$/) { + if ( $ARGV[0] eq '' ) { + &exit_help( "No ps filter specified after -pF switch"); + } + $ps_filter = $ARGV[0]; + shift; + } + elsif ( ( exists( $allowed_latex_options{$_} ) ) + || ( /^(-.+)=/ && exists( $allowed_latex_options_with_arg{$1} ) ) + ) + { + push @extra_latex_options, $original; + push @extra_pdflatex_options, $original; + push @extra_lualatex_options, $original; + push @extra_xelatex_options, $original; + } + elsif (/^-/) { + warn "$My_name: $_ bad option\n"; + $bad_options++; + } + else { + push @command_line_file_list, $_ ; + } +} + +if ( $bad_options > 0 ) { + &exit_help( "Bad options specified" ); +} + +warn "$My_name: This is $version_details, version: $version_num.\n", + unless $silent; + + +if ( ($out_dir ne '') && ($aux_dir eq '') ){ + $aux_dir = $out_dir; +} + +# Save original values for use in diagnositics. +# We may change $aux_dir and $out_dir after a detection +# of results of misconfiguration. +$aux_dir_requested = $aux_dir; +$out_dir_requested = $out_dir; +# The following reports results of diagnostics on location of .log file +# after the first run of a latex engine, when actually used aux_dir +# may not be the expected one, due to a configuration error. +# Values: -1 uninitialized (before first run) +# 0 log file not found; +# 1 log file in aux_dir; +# 2 log file **not** in aux_dir but in out_dir; +# 3 log file **not** in aux_dir or out_dir, but in cwd. +$where_log = -1; + +&set_dirs_etc; + +if ($bibtex_use > 1) { + push @generated_exts, 'bbl'; +} + +# For backward compatibility, convert $texfile_search to @default_files +# Since $texfile_search is initialized to "", a nonzero value indicates +# that an initialization file has set it. +if ( $texfile_search ne "" ) { + @default_files = split /\s+/, "*.tex $texfile_search"; +} + +#Glob the filenames command line if the script was not invoked under a +# UNIX-like environment. +# Cases: (1) MS/MSwin native Glob +# (OS detected as MSWin32) +# (2) MS/MSwin cygwin Glob [because we do not know whether +# the cmd interpreter is UNIXy (and does glob) or is +# native MS-Win (and does not glob).] +# (OS detected as cygwin) +# (3) UNIX Don't glob (cmd interpreter does it) +# (Currently, I assume this is everything else) +if ( ($^O eq "MSWin32") || ($^O eq "cygwin") ) { + # Preserve ordering of files + @file_list = glob_list1(@command_line_file_list); +#print "A1:File list:\n"; +#for ($i = 0; $i <= $#file_list; $i++ ) { print "$i: '$file_list[$i]'\n"; } +} +else { + @file_list = @command_line_file_list; +} +@file_list = uniq1( @file_list ); + + +# Check we haven't selected mutually exclusive modes. +# Note that -c overrides 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 )) +{ + # Each of the options -p, -pv, -pvc turns the other off. + # So the only reason to arrive here is an incorrect inititalization + # file, or a bug. + &exit_help( "Conflicting options (print, preview, preview_continuous) selected"); +} + +if ( @command_line_file_list ) { + # At least one file specified on command line (before possible globbing). + if ( !@file_list ) { + &exit_help( "Wildcards in file names didn't match any files"); + } +} +else { + # No files specified on command line, try and find some + # Evaluate in order specified. The user may have some special + # for wanting processing in a particular order, especially + # if there are no wild cards. + # Preserve ordering of files + my @file_list1 = uniq1( glob_list1(@default_files) ); + my @excluded_file_list = uniq1( glob_list1(@default_excluded_files) ); + # Make hash of excluded files, for easy checking: + my %excl = (); + foreach my $file (@excluded_file_list) { + $excl{$file} = ''; + } + foreach my $file (@file_list1) { + push( @file_list, $file) unless ( exists $excl{$file} ); + } + if ( !@file_list ) { + &exit_help( "No file name specified, and I couldn't find any"); + } +} + +$num_files = $#file_list + 1; +$num_specified = $#command_line_file_list + 1; + +#print "Command line file list:\n"; +#for ($i = 0; $i <= $#command_line_file_list; $i++ ) { print "$i: '$command_line_file_list[$i]'\n"; } +#print "File list:\n"; +#for ($i = 0; $i <= $#file_list; $i++ ) { print "$i: '$file_list[$i]'\n"; } + + +# If selected a preview-continuous mode, make sure exactly one filename was specified +if ($preview_continuous_mode && ($num_files != 1) ) { + if ($num_specified > 1) { + &exit_help( + "Need to specify exactly one filename for ". + "preview-continuous mode\n". + " but $num_specified were specified" + ); + } + elsif ($num_specified == 1) { + &exit_help( + "Need to specify exactly one filename for ". + "preview-continuous mode\n". + " but wildcarding produced $num_files files" + ); + } + else { + &exit_help( + "Need to specify exactly one filename for ". + "preview-continuous mode.\n". + " Since none were specified on the command line, I looked for \n". + " files in '@default_files'.\n". + " But I found $num_files files, not 1." + ); + } +} + +# If selected jobname, can only apply that to one file: +if ( ($jobname ne '') && ($jobname !~ /%A/) && ($num_files > 1) ) { + &exit_help( + "Need to specify at most one filename if ". + "jobname specified without a %A, \n". + " but $num_files were found (after defaults and wildcarding)." + ); +} +if ( $jobname =~ /%[^A]/ ) { + &exit_help( + "Jobname '$jobname' contains placeholder other than %A." + ); +} + +# Normalize the commands, to have place-holders for source, dest etc: +&fix_cmds; + +# Add common options +add_option( $latex_default_switches, \$latex ); +add_option( $pdflatex_default_switches, \$pdflatex ); +add_option( $lualatex_default_switches, \$lualatex ); +add_option( $xelatex_default_switches, \$xelatex ); + +foreach (@extra_latex_options) { add_option( $_, \$latex ); } +foreach (@extra_pdflatex_options) { add_option( $_, \$pdflatex ); } +foreach (@extra_lualatex_options) { add_option( $_, \$lualatex ); } +foreach (@extra_xelatex_options) { add_option( $_, \$xelatex ); } + + +# If landscape mode, change dvips processor, and the previewers: +if ( $landscape_mode ) +{ + $dvips = $dvips_landscape; + $dvi_previewer = $dvi_previewer_landscape; + $ps_previewer = $ps_previewer_landscape; +} + +if ( $silent ) { + add_option( "$latex_silent_switch", \$latex ); + add_option( "$pdflatex_silent_switch", \$pdflatex ); + add_option( "$lualatex_silent_switch", \$lualatex ); + add_option( "$xelatex_silent_switch", \$xelatex ); + add_option( "$biber_silent_switch", \$biber ); + add_option( "$bibtex_silent_switch", \$bibtex ); + add_option( "$makeindex_silent_switch", \$makeindex ); + add_option( "$dvipdf_silent_switch", \$dvipdf ); + add_option( "$dvips_silent_switch", \$dvips ); + add_option( "$xdvipdfmx_silent_switch", \$xdvipdfmx ); +} + +if ( $recorder ) { + add_option( "-recorder", \$latex, \$pdflatex, \$lualatex, \$xelatex ); +} + +# If the output and/or aux directories are specified, fix the (pdf)latex +# commands to use them. +# N.B. We'll ensure that the directories actually exist only after a +# possible cd to the document directory, since the directories can be +# relative to the document. + +if ( $out_dir ) { + add_option( "-output-directory=\"$out_dir\"", + \$latex, \$pdflatex, \$lualatex, \$xelatex ); +} +if ( $aux_dir && ($aux_dir ne $out_dir) ) { + # N.B. If $aux_dir and $out_dir are the same, then the -output-directory + # option is sufficient, especially because the -aux-directory exists + # only in MiKTeX, not in TeXLive. + add_option( "-aux-directory=\"$aux_dir\"", + \$latex, \$pdflatex, \$lualatex, \$xelatex ); +} + +if ( $jobname ne '' ) { + # Since $jobname may include placeholder(s), put %R placeholder + # in option, and let %R be substituted by actual jobname at runtime. + add_option( "--jobname=%R", \$latex, \$lualatex, \$pdflatex, \$xelatex ); +} + +# Which kind of file do we preview? +if ( $view eq "default" ) { + # If default viewer requested, use "highest" of dvi, ps and pdf + # that was requested by user. + # No explicit request means view dvi. + $view = "dvi"; + if ( $postscript_mode ) { $view = "ps"; } + if ( $pdf_mode ) { $view = "pdf"; } +} + +# Make sure we make the kind of file we want to view: +if ($view eq 'dvi') { $dvi_mode = 1; } +if ($view eq 'ps') { $postscript_mode = 1; } +if ( ($view eq 'pdf') && ($pdf_mode == 0) ) { + $pdf_mode = 1; +} + +# Make sure that we make something if all requests are turned off +if ( ! ( $dvi_mode || $pdf_mode || $postscript_mode || $printout_mode) ) { + print "No specific requests made, so default to dvi by latex\n"; + $dvi_mode = 1; +} + +# Determine requests. +if ( $banner ) { $postscript_mode = 1; } +if ( $dvi_mode ) { + $current_primary = 'latex'; + $requested_filetypes{'dvi'} = 1; + if ( length($dvi_filter) != 0 ) { $requested_filetypes{'dviF'} = 1; } +} +if ( $postscript_mode ) { + $current_primary = 'latex'; + $requested_filetypes{'ps'} = 1; + if ( length($ps_filter) != 0 ) { $requested_filetypes{'psF'} = 1; } +} + +if ($pdf_mode > 5) { + warn "$My_name: Non-allowed value of \$pdf_mode = $pdf_mode,", + " replaced by 1.\n"; + $pdf_mode = 1; +} +if ( ($dvi_mode || $postscript_mode) && $pdf_mode ) { + my %disallowed = (); + foreach (1,4,5) { $disallowed{$_} = 1; } + if ($disallowed{$pdf_mode}) { + warn "$My_name: \$pdf_mode = $pdf_mode is incompatible with dvi and postscript modes\n", + " which are required by other requests.\n"; + if ($postscript_mode) {$pdf_mode = 2;} + else { $pdf_mode = 3; } + warn " I replaced it by $pdf_mode.\n"; + } +} +if ( $pdf_mode == 0 ) { + $pdf_method = ''; +} +elsif ( $pdf_mode == 1 ) { + $requested_filetypes{'pdf'} = 1; + $pdf_method = 'pdflatex'; +} +elsif ( $pdf_mode == 2 ) { + $requested_filetypes{'pdf'} = 1; + $pdf_method = 'ps2pdf'; +} +elsif ( $pdf_mode == 3 ) { + $requested_filetypes{'pdf'} = 1; + $pdf_method = 'dvipdf'; +} +elsif ( $pdf_mode == 4 ) { + $requested_filetypes{'pdf'} = 1; + $pdf_method = 'lualatex'; +} +elsif ( $pdf_mode == 5 ) { + $requested_filetypes{'pdf'} = 1; + $pdf_method = 'xelatex'; +} + +if ($print_type eq 'auto') { + if ( $postscript_mode ) { $print_type = 'ps'; } + elsif ( $pdf_mode ) { $print_type = 'pdf'; } + elsif ( $dvi_mode ) { $print_type = 'dvi'; } + else { $print_type = 'none'; } +} +if ( $printout_mode ) { + $one_time{'print'} = 1; + if ($print_type eq 'none'){ + warn "$My_name: You have requested printout, but \$print_type is set to 'none'\n"; + } +} +if ( $preview_continuous_mode || $preview_mode ) { $one_time{'view'} = 1; } + +$can_switch = $allow_switch; +if ( $dvi_mode || $postscript_mode + || ( $printout_mode && ($print_type eq 'ps') || ($print_type eq 'dvi') ) + || ( ($preview_mode || $preview_continuous_mode) && ( ($view eq 'ps') || ($view eq 'dvi') ) ) + ) { + # Automatic switching (e.g., pdf<->dvi o/p) requires pdf files to be + # the only destinations. So if ps or dvi files needed, we cannot + # allow switching. (There will then be an error condition if a TeX + # engine fails to produce the correct type of output file.) + warn "$My_name: Disallowing switch of output file as incompatible\n", + " with file requests.\n"; + $can_switch = 0; +} + + +if ( $pdf_mode == 2 ) { + # We generate pdf from ps. Make sure we have the correct kind of ps. + add_option( "$dvips_pdf_switch", \$dvips ); +} + +# Restrict variables to allowed values: + +if ($filetime_causality_threshold < 0) { + warn "$My_name: Correcting negative value of \$filetime_causality_threshold to zero.\n"; + $filetime_causality_threshold = 0; +} + +# Note sleep has granularity of 1 second. +# Sleep periods 0 < $sleep_time < 1 give zero delay, +# which is probably not what the user intended. +# Sleep periods less than zero give infinite delay +if ( $sleep_time < 0 ) { + warn "$My_name: Correcting negative sleep_time to 1 sec.\n"; + $sleep_time = 1; +} +elsif ( ($sleep_time < 1) && ( $sleep_time != 0 ) ) { + warn "$My_name: Correcting nonzero sleep_time of less than 1 sec to 1 sec.\n"; + $sleep_time = 1; +} +elsif ( $sleep_time == 0 ) { + warn "$My_name: sleep_time was configured to zero.\n", + " Do you really want to do this? It will give 100% CPU usage.\n"; +} + +# Make convenient forms for lookup. +# Extensions always have period. + +# Convert @generated_exts to a hash for ease of look up and deletion +# Keep extension without period! +%generated_exts_all = (); +foreach (@generated_exts ) { + $generated_exts_all{$_} = 1; +} + +$quell_uptodate_msgs = $silent; + # Whether to quell informational messages when files are uptodate + # Will turn off in -pvc mode + +$failure_count = 0; +@failed_primaries = (); + +if ($deps_file eq '' ) { + # Standardize name used for stdout + $deps_file = '-'; +} + +# Since deps_file is global (common to all processed files), we must +# delete it here when doing a clean up, and not in the FILE loop, where +# per-file processing (including clean-up) is done +if ( ($cleanup_mode > 0) && $dependents_list && ( $deps_file ne '-' ) ) { + unlink_or_move( $deps_file ); +} + +# In non-pvc mode, the dependency list is global to all processed TeX files, +# so we open a single file here, and add items to it after processing +# each file. But in -pvc mode, the dependency list should be written +# after round of processing the single TeX file (as if each round were +# a separate run of latexmk). +# If we are cleaning up ($cleanup_mode != 0) AND NOT continuing to +# make files (--gg option and $go_mode == 2), deps_file should not be +# created. +# I will use definedness of $deps_handle as flag for global deps file having +# been opened and therefore being available to be written to after +# compiling a file. +$deps_handle = undef; +if ( $dependents_list + && ! $preview_continuous_mode + && ( ($cleanup_mode == 0) || ($go_mode == 2) ) + ) { + $deps_handle = new FileHandle "> $deps_file"; + if (! $deps_handle ) { + die "Cannot open '$deps_file' for output of dependency information\n"; + } +} + +# Remove leading and trailing space in the following space-separated lists, +# and collapse multiple spaces to one, +# to avoid getting incorrect blank items when they are split. +foreach ($clean_ext, $clean_full_ext) { s/^\s+//; s/\s+$//; s/\s+/ /g; } + +# Deal with illegal and problematic characters in filename: +test_fix_texnames( @file_list ); + +FILE: +foreach $filename ( @file_list ) +{ + # Global variables for making of current file: + $updated = 0; + $failure = 0; # Set nonzero to indicate failure at some point of + # a make. Use value as exit code if I exit. + $failure_msg = ''; # Indicate reason for failure + + if ( $do_cd ) { + ($filename, $path) = fileparse( $filename ); + warn "$My_name: Changing directory to '$path'\n" + if !$silent; + pushd( $path ); + } + else { + $path = ''; + } + + # Ensure the output/auxiliary directories exist, if need be + if ( $out_dir ) { + if ( ! -e $out_dir ) { + warn "$My_name: making output directory '$out_dir'\n" + if ! $silent; + make_path $out_dir; + } + elsif ( ! -d $out_dir ) { + warn "$My_name: you requested output directory '$out_dir',\n", + " but an ordinary file of the same name exists, which will\n", + " probably give an error later\n"; + } + } + + if ( $aux_dir && ($aux_dir ne $out_dir) ) { + # N.B. If $aux_dir and $out_dir are the same, then the -output-directory + # option is sufficient, especially because the -aux-directory exists + # only in MiKTeX, not in TeXLive. + if ( ! -e $aux_dir ) { + warn "$My_name: making auxiliary directory '$aux_dir'\n" + if ! $silent; + make_path $aux_dir; + } + elsif ( ! -d $aux_dir ) { + warn "$My_name: you requested aux directory '$aux_dir',\n", + " but an ordinary file of the same name exists, which will\n", + " probably give an error later\n"; + } + } + + &set_names; + # For use under error conditions: + @default_includes = ($texfile_name, $aux_main); + # N.B. Do **not** apply local %rule_db here. It might appear appropriate, + # but %rule_db is needed in the continue block, which is not in the + # scope of a local declaration here. + &rdb_initialize_rules; + + if ( $cleanup_mode > 0 ) { +# ?? MAY NEED TO FIX THE FOLLOWING IF $aux_dir or $out_dir IS SET. + my %other_generated = (); + my @index_bibtex_generated = (); + my @aux_files = (); + my @missing_bib_files = (); + my $bibs_all_exist = 0; + my %final_output_files = (); + foreach (keys %small_cleanup_preserved_exts) { + $final_output_files{"$out_dir1$root_filename.$_"} = 1; + } + $have_fdb = 0; + if ( -e $fdb_name ) { + print "$My_name: Examining fdb file '$fdb_name' for rules ...\n" + if $diagnostics; + $have_fdb = ( 0 == rdb_read( $fdb_name ) ); + } + if ( $have_fdb ) { + rdb_for_actives( + sub { # Find generated files at rule level + my ($base, $path, $ext) = fileparseA( $$Psource ); + $base = $path.$base; + if ( $rule =~ /^makeindex/ ) { + push @index_bibtex_generated, $$Psource, $$Pdest, "$base.ilg"; + } + elsif ( $rule =~ /^(bibtex|biber)/ ) { + push @index_bibtex_generated, $$Pdest, "$base.blg"; + push @aux_files, $$Psource; + if ( $bibtex_use == 1.5) { + foreach ( keys %$PHsource ) { + if ( ( /\.bib$/ ) && (! -e $_) ) { + push @missing_bib_files, $_; + } + } + } + } + elsif ( exists $other_generated{$$Psource} ) { +# print "=========== CHECKING: source file of rule '$rule', '$$Psource'\n", +# " is a generated file.\n"; + ## OLD with apparent bug: + #$other_generated{$$Pdest}; + } + foreach my $key (keys %$PHdest) { + $other_generated{$key} = 1; + } + }, + sub { # Find generated files at source file level + if ( $file =~ /\.aux$/ ) { push @aux_files, $file; } + } + ); + if ($#missing_bib_files == -1) { $bibs_all_exist = 1; } + } + elsif ( -e $log_name ) { + # No fdb file, but log file exists, so do inferior job by parse_log + print "$My_name: Examining log file '$log_name' for generated files...\n" + if $diagnostics; + # Variables set by parse_log. Can I remove them? + local %generated_log = (); + local %dependents = (); # Maps files to status. Not used here. + local @bbl_files = (); # Not used here. + local %idx_files = (); # Maps idx_file to (ind_file, base). Not used here. + local %conversions = (); # (pdf)latex-performed conversions. Not used here. + # Maps output file created and read by (pdf)latex + # to source file of conversion. + local $primary_out = ''; # Actual output file (dvi or pdf). Not used here. + local $fls_file_analyzed = 0; + &parse_log; + %other_generated = %generated_log; + } + else { + print "$My_name: No fdb or log file, so clean up default set of files ...\n" + if $diagnostics; + } + + if ( ($go_mode == 2) && !$silent ) { + warn "$My_name: Removing all generated files\n" unless $silent; + } + my $keep_bbl = 1; + if ( ($bibtex_use > 1.6) + || + ( ($bibtex_use == 1.5) && ($bibs_all_exist) ) + ) { + $keep_bbl = 0; + } + if ($keep_bbl) { + delete $generated_exts_all{'bbl'}; + } + # Convert two arrays to hashes: + my %index_bibtex_generated = (); + my %aux_files = (); + my %aux_files_to_save = (); + foreach (@index_bibtex_generated) { + $index_bibtex_generated{$_} = 1 + unless ( /\.bbl$/ && ($keep_bbl) ); + delete( $other_generated{$_} ); + } + foreach (@aux_files) { + if (exists $other_generated{$_} ) { + $aux_files{$_} = 1; + } + else { + $aux_files_to_save{$_} = 1; + } + } + + foreach (keys %final_output_files) { delete $other_generated{$_}; } + + if ($diagnostics) { + show_array( "For deletion, the following were determined from fdb file or log file:\n" + ." Generated (from makeindex and bibtex):", + keys %index_bibtex_generated ); + show_array( " Aux files:", keys %aux_files ); + show_array( " Other generated files:\n" + ." (only deleted if \$cleanup_includes_generated is set): ", + keys %other_generated ); + show_array( " Yet other generated files are specified by patterns:\n". + " Explicit pattern with %R or root-filename.extension:", + keys %generated_exts_all ); + show_array( " Aux files to SAVE and not delete:", keys %aux_files_to_save ); + } + + my @clean_args = ( 'blg', 'ilg', 'log', 'aux.bak', 'idx.bak', + split('\s+',$clean_ext), keys %generated_exts_all ); + cleanup1( $aux_dir1, @clean_args ); + if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @clean_args ); } + if ( $cleanup_mode == 1 ) { + my @clean_args = ( keys %small_cleanup_preserved_exts, split('\s+', $clean_full_ext) ); + cleanup1( $aux_dir1, @clean_args ); + if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @clean_args ); } + } + unlink_or_move( 'texput.log', "texput.aux", "missfont.log", + keys %index_bibtex_generated, + keys %aux_files ); + if ($cleanup_includes_generated) { + unlink_or_move( keys %other_generated ); + } + if ( $cleanup_includes_cusdep_generated) { + &cleanup_cusdep_generated; + } + } + if ($cleanup_fdb) { + unlink_or_move( $fdb_name ); + # If the fdb file exists, it will have been read, and therefore changed + # rule database. But deleting the fdb file implies we also want + # a virgin rule database, so we must reset it: + &rdb_initialize_rules; + } + if ($cleanup_only) { next FILE; } + + if ( $diagnostics ) { + print "$My_name: Rules after start up for '$texfile_name'\n"; + rdb_show(); + } + + $have_fdb = 0; + if (! -e $aux_main ) { + # No aux file => set up trivial aux file + # and corresponding fdb_file. Arrange them to provoke one run + # as minimum, but no more if actual aux file is trivial. + # (Useful on big files without cross references.) + # If aux file doesn't exist, then any fdb file is surely + # wrong. + # Previously, I had condition for this as being both aux and + # fdb files failing to exist. But it's not obvious what to + # do if aux exists and fdb doesn't. So I won't do anything. + &set_trivial_aux_fdb; + } + + if ( -e $fdb_name ) { + $rdb_errors = rdb_read( $fdb_name ); + $have_fdb = ($rdb_errors == 0); + } + if (!$have_fdb) { + # We didn't get a valid set of data on files used in + # previous run. So use filetime criterion for make + # instead of change from previous run, until we have + # done our own make. + rdb_recurse( [keys %possible_primaries], + sub{ if ( $$Ptest_kind == 1 ) { $$Ptest_kind = 3;} } + ); + if ( -e $log_name ) { + rdb_for_some( [keys %possible_primaries], \&rdb_set_latex_deps ); + } + } + foreach $rule ( &rdb_accessible ) { + # For all source files of all accessible rules, + # if the file data are not already set (e.g., from fdb_latexmk + # file, set them from disk. + rdb_one_rule ($rule, undef, + sub{ if ( $$Ptime == 0) { &rdb_update1; } } + ); + } + + if ($go_mode) { + # Force everything to be remade. + rdb_recurse( [ &rdb_target_array], sub{$$Pout_of_date=1;} ); + } + + + if ( $diagnostics ) { + print "$My_name: Rules after initialization\n"; + rdb_show(); + } + + #************************************************************ + + if ( $preview_continuous_mode ) { + &make_preview_continuous; + next FILE; + } + + +## Handling of failures: +## Variable $failure is set to indicate a failure, with information +## put in $failure_msg. +## These variables should be set to 0 and '' at any point at which it +## should be assumed that no failures have occurred. +## When after a routine is called it is found that $failure is set, then +## processing should normally be aborted, e.g., by return. +## Then there is a cascade of returns back to the outermost level whose +## responsibility is to handle the error. +## Exception: An outer level routine may reset $failure and $failure_msg +## after initial processing, when the error condition may get +## ameliorated later. + #Initialize failure flags now. + $failure = 0; + $failure_msg = ''; + $failure = &rdb_make; + if ( ( $failure <= 0 ) || $force_mode ) { + rdb_for_some( [keys %one_time], \&rdb_run1 ); + } + if ($#primary_warning_summary > -1) { + # N.B. $mult_defined, $bad_reference, $bad_character, $bad_citation also available here. + if ($warnings_as_errors) { + $failure = 1; + $failure_msg = "Warning(s) from latex (or c.) for '$filename'; treated as error"; + } + } + if ($failure > 0) { next FILE; } +} # end FILE +continue { + if ($deps_handle) { deps_list($deps_handle); } + # If requested, print the list of rules. But don't do this in -pvc + # mode, since the rules list has already been printed. + if ($rules_list && ! $preview_continuous_mode) { rdb_list(); } + # Handle any errors + $error_message_count = rdb_show_rule_errors(); + if ( ($error_message_count == 0) || ($failure > 0) ) { + if ( $failure_msg ) { + #Remove trailing space + $failure_msg =~ s/\s*$//; + warn "----------------------\n"; + warn "This message may duplicate earlier message.\n"; + warn "$My_name: Failure in processing file '$filename':\n", + " $failure_msg\n"; + warn "----------------------\n"; + $failure = 1; + } + } + if ( ($failure > 0) || ($error_message_count > 0) ) { + $failure_count ++; + push @failed_primaries, $filename; + } + &ifcd_popd; +} +close($deps_handle) if ( $deps_handle ); + +if ($show_time) { show_timing();} + +sub show_timing { + my $processing_time = processing_time() - $processing_time1; + print @timings, "Accumulated processing time = $processing_time\n"; + @timings = (); + $processing_time1 = processing_time(); +} + +# If we get here without going through the continue section: +if ( $do_cd && ($#dir_stack > -1) ) { + # Just in case we did an abnormal exit from the loop + warn "$My_name: Potential bug: dir_stack not yet unwound, undoing all directory changes now\n"; + &finish_dir_stack; +} + +if ($failure_count > 0) { + if ( $#file_list > 0 ) { + # Error occured, but multiple files were processed, so + # user may not have seen all the error messages + warn "\n------------\n"; + show_array( + "$My_name: Some operations failed, for the following tex file(s)", + @failed_primaries); + } + if ( !$force_mode ) { + warn "$My_name: Use the -f option to force complete processing,\n", + " unless error was exceeding maximum runs, or warnings treated as errors.\n"; + } + exit 12; +} + +if ( $where_log == 2 ) { + warn "$My_name: You requested aux_dir '$aux_dir_requested',\n". + " but '$aux_dir' was used by the (pdf)latex engine.\n". + " That indicates a configuration error.\n"; + if ( ($tex_distribution !~ /^MiKTeX/i) && ($aux_dir_requested ne $out_dir_requested) ) { + warn " Probably you set different aux and out directories,\n". + " but that is not supported by your TeX distribution.\n". + " The only current distribution supporting this is MiKTeX.\n"; + } +} + + + +# end MAIN PROGRAM +############################################################# +############################################################# + +sub set_tex_cmds { + # Usage, e.g., set_tex_cmds( '%O %S' ) + my $args = $_[0]; + foreach my $cmd ('latex', 'lualatex', 'pdflatex', 'xelatex' ) { + ${$cmd} = "$cmd $args"; + } + # N.B. See setting of $latex_default_switches, ..., + # $xelatex_default_switches, etc, for any special options needed. +} + +sub std_tex_cmds { set_tex_cmds( '%O %S' ); } + +sub alt_tex_cmds { set_tex_cmds( '%O %P' ); } + +#======================== + +sub test_fix_texnames { + my $illegal_char = 0; + my $unbalanced_quote = 0; + my $balanced_quote = 0; + foreach (@_) { + if ( $^O eq "MSWin32" ) { + # On MS-Win, change directory separator '\' to '/', as needed + # by the TeX engines, for which '\' introduces a macro name. + # Remember that '/' is a valid directory separator in MS-Win. + s[\\][/]g; + } + if ($do_cd) { + my ($filename, $path) = fileparse( $_ ); + if ($filename =~ /[\Q$illegal_in_texname\E]/ ) { + $illegal_char++; + warn "$My_name: Filename '$filename' contains character not allowed for TeX file.\n"; + } + if ($filename =~ /^&/) { + $illegal_char++; + warn "$My_name: Filename '$filename' contains initial '&', which is\n", + " not allowed for TeX file.\n"; + } + } + else { + if ( /[\Q$illegal_in_texname\E]/ ) { + $illegal_char++; + warn "$My_name: Filename '$_' contains character not allowed for TeX file.\n"; + } + if (/^&/ ) { + $illegal_char++; + warn "$My_name: Filename '$_' contains initial '&', which is not allowed\n", + " for TeX file.\n"; + } + } + my $count_q = ($_ =~ tr/\"//); + if ( ($count_q % 2) != 0 ) { + warn "$My_name: Filename '$_' contains unbalanced quotes, not allowed.\n"; + $unbalanced_quote++; + } + elsif ( $count_q > 0 ) { + warn "$My_name: Removed (balanced quotes) from filename '$_',\n"; + s/\"//g; + warn " and obtained '$_'.\n"; + $balanced_quote++; + } + } + if ($illegal_char || $unbalanced_quote) { + die "$My_name: Stopping because of bad filename(s).\n"; + } +} + +############################################################# + +sub ensure_path { + # Usage: ensure_path( $var, values ...) + # $ENV{$var} is an environment variable (e.g. $ENV{TEXINPUTS}. + # Ensure the values are in it, prepending them if not, and + # creating the environment variable if it doesn't already exist. + my $var = shift; + my %cmpts = (); + if ( exists $ENV{$var} ) { + foreach ( split $search_path_separator, $ENV{$var} ) { + if ($_ ne '') { $cmpts{$_} = 1; } + } + } + foreach (@_) { + next if ( ($_ eq '') || (exists $cmpts{$_}) ); + if (exists $ENV{$var}) { + $ENV{$var} = $_ . $search_path_separator . $ENV{$var}; + } + else { + $ENV{$var} = $_ . $search_path_separator; + } + } +} + +############################################################# + +sub set_dirs_etc { + # Normalize versions terminating in directory/path separator + # and versions referring to current directory + # These actions in a subroutine so they can be used elsewhere. + $out_dir1 = $out_dir; + $aux_dir1 = $aux_dir; + foreach ( $aux_dir1, $out_dir1 ) { + if ( ($_ ne '') && ! m([\\/\:]$) ) { + $_ .= '/'; + } + while ( s[^\.\/][] ) {} + } + if ($aux_dir) { + # Ensure $aux_dir is in BIBINPUTS and TEXINPUTS search paths. + # TEXINPUTS is used by dvips for files generated by mpost. + # For BIBINPUTS, + # at least one widely package (revtex4-1) generates a bib file + # (which is used in revtex4-1 for putting footnotes in the reference + # list), and bibtex must be run to use it. But latexmk needs to + # determine the existence of the bib file by use of kpsewhich, otherwise + # there is an error. So cope with this situation (and any analogous + # cases by adding the aux_dir to the relevant path search environment + # variables. BIBINPUTS seems to be the only one currently affected. + foreach ( 'BIBINPUTS', 'TEXINPUTS' ) { + ensure_path( $_, $aux_dir ); + } + } +} + +############################################################# + +sub fix_cmds { + # If commands do not have placeholders for %S etc, put them in + foreach ($latex, $lualatex, $pdflatex, $xelatex, $lpr, $lpr_dvi, $lpr_pdf, + $pdf_previewer, $ps_previewer, $ps_previewer_landscape, + $dvi_previewer, $dvi_previewer_landscape, + $kpsewhich + ) { + # Source only + if ( $_ && ! /%/ ) { $_ .= " %O %S"; } + } + foreach ($pdf_previewer, $ps_previewer, $ps_previewer_landscape, + $dvi_previewer, $dvi_previewer_landscape, + ) { + # Run previewers detached + if ( $_ && ! /^(nostart|NONE|internal) / ) { + $_ = "start $_"; + } + } + foreach ($biber, $bibtex) { + # Base only + if ( $_ && ! /%/ ) { $_ .= " %O %B"; } + } + foreach ($dvipdf, $ps2pdf) { + # Source and dest without flag for destination + if ( $_ && ! /%/ ) { $_ .= " %O %S %D"; } + } + foreach ($dvips, $makeindex) { + # Source and dest with -o dest before source + if ( $_ && ! /%/ ) { $_ .= " %O -o %D %S"; } + } + foreach ($dvi_filter, $ps_filter) { + # Source and dest, but as filters + if ( $_ && ! /%/ ) { $_ .= " %O <%S >%D"; } + } +} #END fix_cmds + +############################################################# + +sub add_option { + # Call add_option( $opt, \$cmd ... ) + # Add option to one or more commands + my $option = shift; + while (@_) { + if ( ${$_[0]} !~ /%/ ) { &fix_cmds; } + ${$_[0]} =~ s/%O/$option %O/; + shift; + } +} #END add_option + +############################################################# + +sub rdb_initialize_rules { + # Initialize rule database. + # (The rule database may get overridden/extended after the fdb_latexmk + # file is read, and after running commands to adjust to dependencies + # determined from document. + %rule_db = (); + %target_rules = (); + %target_files = (); + + local %rule_list = (); + &rdb_set_rule_templates; + + my %rule_template = %rule_list; + while ( my ($key, $value) = each %extra_rule_spec ) { + $rule_template{$key} = $value; + } + foreach my $rule ( keys %rule_template ) { + my ( $cmd_type, $ext_cmd, $int_cmd, $source, $dest, $base, $test_kind, $PA_extra_gen ) = @{$rule_template{$rule}}; + if ( ! $PA_extra_gen ) { $PA_extra_gen = []; } + my $needs_making = 0; + # Substitute in the filename variables, since we will use + # those for determining filenames. But delay expanding $cmd + # until run time, in case of changes. + foreach ($base, $source, $dest, @$PA_extra_gen ) { + s/%R/$root_filename/g; + s/%Y/$aux_dir1/; + s/%Z/$out_dir1/; + } + foreach ($source, $dest ) { + s/%B/$base/; + s/%T/$texfile_name/; + } + rdb_create_rule( $rule, $cmd_type, $ext_cmd, $int_cmd, $test_kind, + $source, $dest, $base, + $needs_making, undef, undef, 1, $PA_extra_gen ); + } # End rule iteration + + # Ensure we only have one way to make pdf file, and that it is appropriate. Remove other incompatibilities + if ($pdf_mode == 1) { rdb_deactivate( 'dvipdf', 'ps2pdf', 'latex', 'lualatex', 'xdvipdfmx', 'xelatex' ); } + elsif ($pdf_mode == 2) { rdb_deactivate( 'dvipdf', 'pdflatex', 'lualatex', 'xdvipdfmx', 'xelatex' ); } + elsif ($pdf_mode == 3) { rdb_deactivate( 'pdflatex', 'ps2pdf', 'lualatex', 'xdvipdfmx', 'xelatex' ); } + elsif ($pdf_mode == 4) { rdb_deactivate( 'pdflatex', 'ps2pdf', 'dvipdf', 'xdvipdfmx', 'xelatex' ); } + elsif ($pdf_mode == 5) { rdb_deactivate( 'pdflatex', 'ps2pdf', 'dvipdf', 'lualatex' ); } + else { rdb_deactivate( 'dvipdf', 'pdflatex', 'ps2pdf', 'lualatex', 'xdvipdfmx', 'xelatex' ); } + + if ($dvi_mode == 1) { + rdb_activate( 'latex' ); + $target_files{$dvi_final} = 1; + } + if ($postscript_mode == 1) { + rdb_activate( 'latex' ); + $target_files{$ps_final} = 1; + } + if ($pdf_mode) { $target_files{$pdf_final} = 1; } + &rdb_set_rule_net; +} # END rdb_initialize_rules + +#************************************************************ + +sub rdb_set_rule_templates { +# Set up specifications for standard rules, adjusted to current conditions +# Substitutions: %S = source, %D = dest, %B = this rule's base +# %T = texfile, %R = root = base for latex. +# %Y for $aux_dir1, %Z for $out_dir1 + + + my $print_file = ''; + my $print_cmd = 'NONE'; + if ( $print_type eq 'dvi' ) { + $print_file = $dvi_final; + $print_cmd = $lpr_dvi; + } + elsif ( $print_type eq 'pdf' ) { + $print_file = $pdf_final; + $print_cmd = $lpr_pdf; + } + elsif ( $print_type eq 'ps' ) { + $print_file = $ps_final; + $print_cmd = $lpr; + } + elsif ( $print_type eq 'none' ) { + $print_cmd = 'NONE echo NO PRINTING CONFIGURED'; + } + + my $view_file = ''; + my $viewer = ''; + my $viewer_update_method = 0; + my $viewer_update_signal = undef; + my $viewer_update_command = undef; + + if ( ($view eq 'dvi') || ($view eq 'pdf') || ($view eq 'ps') ) { + $view_file = ${$view.'_final'}; + $viewer = ${$view.'_previewer'}; + $viewer_update_method = ${$view.'_update_method'}; + $viewer_update_signal = ${$view.'_update_signal'}; + if (defined ${$view.'_update_command'}) { + $viewer_update_command = ${$view.'_update_command'}; + } + } + # Specification of internal command for viewer update: + my $PA_update = ['do_update_view', $viewer_update_method, $viewer_update_signal, 0, 1]; + +# For test_kind: Use file contents for latex and friends, but file time for the others. +# This is because, especially for dvi file, the contents of the file may contain +# a pointer to a file to be included, not the contents of the file! + %rule_list = ( + 'latex' => [ 'primary', "$latex", '', "%T", $dvi_name, "%R", 1, [$log_name] ], + 'pdflatex' => [ 'primary', "$pdflatex", '', "%T", $pdf_name, "%R", 1, [$log_name] ], + 'lualatex' => [ 'primary', "$lualatex", '', "%T", $pdf_name, "%R", 1, [$log_name] ], + 'xelatex' => [ 'primary', "$xelatex", '', "%T", $xdv_name, "%R", 1, [$log_name] ], + 'dvipdf' => [ 'external', "$dvipdf", 'do_viewfile', $dvi_final, $pdf_name, "%Z%R", 2 ], + 'xdvipdfmx' => [ 'external', "$xdvipdfmx", 'do_viewfile', $xdv_final, $pdf_name, "%Z%R", 2 ], + 'dvips' => [ 'external', "$dvips", 'do_viewfile', $dvi_final, $ps_name, "%Z%R", 2 ], + 'dvifilter' => [ 'external', $dvi_filter, 'do_viewfile', $dvi_name, $dviF_name, "%Z%R", 2 ], + 'ps2pdf' => [ 'external', "$ps2pdf", 'do_viewfile', $ps_final, $pdf_name, "%Z%R", 2 ], + 'psfilter' => [ 'external', $ps_filter, 'do_viewfile', $ps_name, $psF_name, "%Z%R", 2 ], + 'print' => [ 'external', "$print_cmd", 'if_source', $print_file, "", "", 2 ], + 'update_view' => [ 'external', $viewer_update_command, $PA_update, + $view_file, "", "", 2 ], + 'view' => [ 'external', "$viewer", 'if_source', $view_file, "", "", 2 ], + ); +} # END rdb_set_rule_templates + +#************************************************************ + +sub rdb_set_rule_net { + # Set network of rules, including links + &rdb_make_links; + &rdb_classify_rules; +} + +#************************************************************ + +sub rdb_make_links { +# ?? Problem if there are multiple rules for getting a file. Notably pdf. +# Which one to choose? +# ?? Problem: what if a rule is inactive, +# e.g., bibtex because biber is in use, +# or xelatex when pdflatex is in use +# or bibtex when $bibtex_use is 0. +# What if both latex and pdflatex are being used? +# That has been allowed. But .aux file (also +# .log file) are made by both. + +# Other case: package (like bibtopic) creates bbl or other file when +# it doesn't exist. Later a rule is created by latexmk to make that +# file. Then the rule's main destination file should have priority +# over non-main generated files from other rules. + local %from_rules_old = %from_rules; + &rdb_cache_generated; + rdb_for_actives( + 0, + sub{ + if ( exists $from_rules_main{$file} ) { + $$Pfrom_rule = $from_rules_main{$file}; + } + elsif ( exists $from_rules{$file} ) { + $$Pfrom_rule = $from_rules{$file}; + } + if ( $$Pfrom_rule && (! rdb_rule_exists( $$Pfrom_rule ) ) ) { + $$Pfrom_rule = ''; + } + } + ); + rdb_for_actives( \&rdb_set_source_rules ); +# &rdb_show; +} # END rdb_make_links + +#************************************************************ + +sub rdb_set_source_rules { + # This applies to rules whose source file is a dvi or xdv file + # Uses rule context + my ($base, $path, $ext) = fileparseA( $$Psource ); + if ( ($ext eq '.dvi') || ($ext eq '.dviF') || ($ext eq '.xdv') ) { + my $old_rule = $from_rules_old{$$Psource}; + my $new_rule = $from_rules{$$Psource}; + if ( defined $old_rule + && defined $new_rule + && ($old_rule eq $new_rule) + && defined $$PHsource_rules{$new_rule} + ) + { # Nothing to do: source rule is correct. + } + else { + if ( defined $old_rule ) { delete $$PHsource_rules{$old_rule}; } + if ( defined $new_rule ) { $$PHsource_rules{$new_rule} = 0; } + } + } +} + +#************************************************************ + +sub rdb_cache_generated { + # Update %from_rules + %from_rules = (); + %from_rules_main = (); + rdb_for_actives( \&one_from_main_rule_cache ); + rdb_for_actives( \&one_from_rule_cache ); +} # END rdb_cache_generated + +#------------ + +sub one_from_main_rule_cache { + # Rule context assumed. + # Set from_rules_main items for one rule + if (! $$Pdest) { return; } +# Error message trigger: if ( $$Pdest =~ /pdf$/) { $from_rules_main{$$Pdest} = 'pdflatexA'; } + if ( exists $from_rules_main{$$Pdest} ) { + my $old_rule = $from_rules_main{$$Pdest}; + if ( $old_rule eq $rule ) { + # OK + } + else { + warn "$My_name: Possible bug:\n", + " In linking rules I already set from_rules_main{$$Pdest} to '$old_rule'\n", + " But now I want to set it to '$rule'\n"; +#???? traceback(); + } + } + $from_rules_main{$$Pdest} = $rule; +} # END one_from_main_rule_cache + +#------------ + +sub one_from_rule_cache { + # Rule context assumed. + # Set from_rules items for one rule + foreach ( @$PA_extra_gen, keys %$PHdest ) { + # Error message trigger: if ( $_ =~ /aux$/) { $from_rules{$_} = 'pdflatexA'; } + if ( exists $from_rules{$_} ) { + my $old_rule = $from_rules{$_}; + if ( $old_rule eq $rule ) { + # OK + } + elsif ( exists $from_rules_main{$_} && ( $from_rules_main{$_} ne $rule ) ) { + warn "$My_name: Possible problem:\n", + " In linking rules, I already set from_rules_main{$_}\n". + " to '$from_rules_main{$_}'\n", + " But now I also have a different rule '$rule' that also made the file.\n"; + } + elsif ( exists($possible_primaries{$old_rule}) && exists($possible_primaries{$rule}) ) { + # This could be problematic. But we'll let it go, + # because it is a common case for .aux and .log files + # (etc), and these cases do not appear to mess up + # anything (by experience). + # Once we allow an active flag for rules and only + # examine active rules, the only case of this that + # will appear (in the absence of other problems) will + # be where two primary rules are active, notably a + # latex rule to make dvi and a pdflatex (or other + # rule) to make pdf. + } + else { + warn "$My_name: Possible bug:\n", + " In linking rules I already set from_rules{$_} to '$old_rule'\n", + " But now I want to set it to '$rule'\n"; +#???? traceback(); + } + } + $from_rules{$_} = $rule; + } +} #END from_rule_cache + +#************************************************************ + +sub set_trivial_aux_fdb { + # 1. Write aux file EXACTLY as would be written if the tex file + # had no cross references, etc. I.e., a minimal .aux file. + # 2. Write a corresponding fdb file + # 3. Provoke a run of (pdf)latex (actually of all primaries). + + local *aux_file; + open( aux_file, '>', $aux_main ) + or die "Cannot write file '$aux_main'\n"; + print aux_file "\\relax \n"; + close(aux_file); + + foreach my $rule (keys %possible_primaries ) { + rdb_ensure_file( $rule, $texfile_name ); + rdb_ensure_file( $rule, $aux_main ); + rdb_one_rule( $rule, + sub{ $$Pout_of_date = 1; } + ); + } + &rdb_write( $fdb_name ); +} #END set_trivial_aux_fdb + +#************************************************************ +#### Particular actions +#************************************************************ +#************************************************************ + +sub do_cusdep { + # Unconditional application of custom-dependency + # except that rule is not applied if the source file source + # does not exist, and an error is returned if the dest is not made. + # + # Assumes rule context for the custom-dependency, and that my first + # argument is the name of the subroutine to apply + my $func_name = $_[0]; + my $return = 0; + if ( !-e $$Psource ) { + # Source does not exist. Users of this rule will need to turn + # it off when custom dependencies are reset + if ( !$silent ) { +## ??? Was commented out. 1 Sep. 2008 restored, for cusdep no-file-exists issue + warn "$My_name: In trying to apply custom-dependency rule\n", + " to make '$$Pdest' from '$$Psource'\n", + " the source file has disappeared since the last run\n"; + } + # Treat as successful + } + elsif ( !$func_name ) { + warn "$My_name: Possible misconfiguration or bug:\n", + " In trying to apply custom-dependency rule\n", + " to make '$$Pdest' from '$$Psource'\n", + " the function name is blank.\n"; + } + elsif ( ! defined &$func_name ) { + warn "$My_name: Misconfiguration or bug,", + " in trying to apply custom-dependency rule\n", + " to make '$$Pdest' from '$$Psource'\n", + " function name '$func_name' does not exists.\n"; + } + else { + my $cusdep_ret = &$func_name( $$Pbase ); + if ( defined $cusdep_ret && ($cusdep_ret != 0) ) { + $return = $cusdep_ret; + if ($return) { + warn "Rule '$rule', function '$func_name'\n", + " failed with return code = $return\n"; + } + } + elsif ( !-e $$Pdest ) { + # Destination non-existent, but routine failed to give an error + warn "$My_name: In running custom-dependency rule\n", + " to make '$$Pdest' from '$$Psource'\n", + " function '$func_name' did not make the destination.\n"; + $return = -1; + } + } + return $return; +} # END do_cusdep + +#************************************************************ + +sub do_viewfile { + # Unconditionally make file for viewing, going through temporary file if + # Assumes rule context + + my $return = 0; + my ($base, $path, $ext) = fileparseA( $$Pdest ); + if ( &view_file_via_temporary ) { + if ( $$Pext_cmd =~ /%D/ ) { + my $tmpfile = tempfile1( "${root_filename}_tmp", $ext ); + warn "$My_name: Making '$$Pdest' via temporary '$tmpfile'...\n"; + $return = &Run_subst( undef, undef, undef, undef, $tmpfile ); + move( $tmpfile, $$Pdest ); + } + else { + warn "$My_name is configured to make '$$Pdest' via a temporary file\n", + " but the command template '$$Pext_cmd' does not have a slot\n", + " to set the destination file, so I won't use a temporary file\n"; + $return = &Run_subst(); + } + } + else { + $return = &Run_subst(); + } + return $return; +} #END do_viewfile + +#************************************************************ + +sub do_update_view { + # Update viewer + # Assumes rule context + # Arguments: (method, signal, viewer_process) + + my $return = 0; + + # Although the process is passed as an argument, we'll need to update it. + # So (FUDGE??) bypass the standard interface for the process. + # We might as well do this for all the arguments. + my $viewer_update_method = ${$PAint_cmd}[1]; + my $viewer_update_signal = ${$PAint_cmd}[2]; + my $Pviewer_process = \${$PAint_cmd}[3]; + my $Pneed_to_get_viewer_process = \${$PAint_cmd}[4]; + + if ($viewer_update_method == 2) { + if ($$Pneed_to_get_viewer_process) { + $$Pviewer_process = &find_process_id( $$Psource ); + if ($$Pviewer_process != 0) { + $$Pneed_to_get_viewer_process = 0; + } + } + if ($$Pviewer_process == 0) { + print "$My_name: need to signal viewer for file '$$Psource', but didn't get \n", + " process ID for some reason, e.g., no viewer, bad configuration, bug\n" + if $diagnostics ; + } + elsif ( defined $viewer_update_signal) { + print "$My_name: signalling viewer, process ID $$Pviewer_process ", + "with signal $viewer_update_signal\n" + if $diagnostics ; + kill $viewer_update_signal, $$Pviewer_process; + } + else { + warn "$My_name: viewer is supposed to be sent a signal\n", + " but no signal is defined. Misconfiguration or bug?\n"; + $return = 1; + } + } + elsif ($viewer_update_method == 4) { + if (defined $$Pext_cmd) { + $return = &Run_subst(); + } + else { + warn "$My_name: viewer is supposed to be updated by running a command,\n", + " but no command is defined. Misconfiguration or bug?\n"; + } + } + return $return; +} #END do_update_view + +#************************************************************ + +sub if_source { + # Unconditionally apply rule if source file exists. + # Assumes rule context + if ( -e $$Psource ) { + return &Run_subst(); + } + else { + warn "Needed source file '$$Psource' does not exist.\n"; + return -1; + } +} #END if_source + +#************************************************************ +#### Subroutines +#************************************************************ +#************************************************************ + +sub find_basename { + # 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. + + # !!!!!!!! I still need to implement use of kpsewhich to match behavior + # of (pdf)latex correctly. + + 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 TeXLive 2016) => + # A. Finding of tex file: + # 1. If filename.tex exists, use it, + # 2. else if kpsewhich finds filename.tex, use it + # 3. else if filename exists, use it, + # 4. else if kpsewhich finds filename, use it. + # (Probably can unify the above by + # 1'. If kpsewhich finds filename.tex, use result. + # 2'. else if kpsewhich finds filename, use result. + # 3'. else report file not found. + # B. 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.) + # C. 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". + # But there are also modifications of this when a file can be + # found by kpsewhich. + + if ( -f "$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 "$My_name: 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; +} #END find_basename + +#************************************************************ + +sub make_preview_continuous { + local @changed = (); + local %changed_rules = (); + local @changed_user = (); + local @disappeared = (); + local @no_dest = (); # Non-existent destination files + local @rules_never_run = (); + local @rules_to_apply = (); + + local $failure = 0; + local %rules_applied = (); + local $updated = 0; + + print "======= Need to update make_preview_continuous for target files\n"; + + $quell_uptodate_msgs = 1; + + local $view_file = ''; + rdb_one_rule( 'view', sub{ $view_file = $$Psource; } ); + + if ( ($view eq 'dvi') || ($view eq 'pdf') || ($view eq 'ps') ) { + warn "Viewing $view\n"; + } + elsif ( $view eq 'none' ) { + warn "Not using a previewer\n"; + $view_file = ''; + } + else { + warn "$My_name: BUG: Invalid preview method '$view'\n"; + exit 20; + } + + my $viewer_running = 0; # No viewer known to be running yet + # Get information from update_view rule + local $viewer_update_method = 0; + # Pointers so we can update the following: + local $Pviewer_process = undef; + local $Pneed_to_get_viewer_process = undef; + rdb_one_rule( 'update_view', + sub{ $viewer_update_method = $$PAint_cmd[1]; + $Pviewer_process = \$$PAint_cmd[3]; + $Pneed_to_get_viewer_process = \$$PAint_cmd[4]; + } + ); + # Note that we don't get the previewer process number from the program + # that starts it; that might only be a script to get things set up and the + # actual previewer could be (and sometimes IS) another process. + + if ( ($view_file ne '') && (-e $view_file) && !$new_viewer_always ) { + # Is a viewer already running? + # (We'll save starting up another viewer.) + $$Pviewer_process = &find_process_id( $view_file ); + if ( $$Pviewer_process ) { + warn "$My_name: Previewer is already running\n" + if !$silent; + $viewer_running = 1; + $$Pneed_to_get_viewer_process = 0; + } + } + + # Loop forever, rebuilding .dvi and .ps as necessary. + # Set $first_time to flag first run (to save unnecessary diagnostics) + my $last_action_time = time(); + my $timed_out = 0; +CHANGE: + for (my $first_time = 1; 1; $first_time = 0 ) { + + my %rules_to_watch = array_to_hash( &rdb_accessible ); + + $updated = 0; + $failure = 0; + $failure_msg = ''; + if ( $MSWin_fudge_break && ($^O eq "MSWin32") ) { + # Fudge under MSWin32 ONLY, to stop perl/latexmk from + # catching ctrl/C and ctrl/break, and let it only reach + # downstream programs. See comments at first definition of + # $MSWin_fudge_break. + $SIG{BREAK} = $SIG{INT} = 'IGNORE'; + } + if ($compiling_cmd) { + Run_subst( $compiling_cmd ); + } + $failure = &rdb_make; + +## warn "=========Viewer PID = $$Pviewer_process; updated=$updated\n"; + + if ( $MSWin_fudge_break && ($^O eq "MSWin32") ) { + $SIG{BREAK} = $SIG{INT} = 'DEFAULT'; + } + # Start viewer if needed. + if ( ($failure > 0) && (! $force_mode) ) { + # No viewer yet + } + elsif ( ($view_file ne '') && (-e $view_file) && $updated && $viewer_running ) { + # A viewer is running. Explicitly get it to update screen if we have to do it: + rdb_one_rule( 'update_view', \&rdb_run1 ); + } + elsif ( ($view_file ne '') && (-e $view_file) && !$viewer_running ) { + # Start the viewer + if ( !$silent ) { + if ($new_viewer_always) { + warn "$My_name: starting previewer for '$view_file'\n", + "------------\n"; + } + else { + warn "$My_name: I have not found a previewer that ", + "is already running. \n", + " So I will start it for '$view_file'\n", + "------------\n"; + } + } + local $retcode = 0; + rdb_one_rule( 'view', sub { $retcode = &rdb_run1;} ); + if ( $retcode != 0 ) { + if ($force_mode) { + warn "$My_name: I could not run previewer\n"; + } + else { + &exit_msg1( "I could not run previewer", $retcode); + } + } + else { + $viewer_running = 1; + $$Pneed_to_get_viewer_process = 1; + } # end analyze result of trying to run viewer + } # end start viewer + if ( $failure > 0 ) { + if ( !$failure_msg ) { + $failure_msg = 'Failure to make the files correctly'; + } + &rdb_set_rule_net; + %rules_to_watch = array_to_hash( &rdb_accessible ); + + # There will be files changed during the run that are irrelevant. + # We need to wait for the user to change the files. + + # So set the GENERATED files from (pdf)latex as up-to-date: + rdb_for_some( [keys %current_primaries], \&rdb_update_gen_files ); + + # And don't watch for changes for post_primary rules (ps and pdf + # from dvi, etc haven't been run after an error in (pdf)latex, so + # are out-of-date by filetime criterion, but they should not be run + # until after another (pdf)latex run: + foreach (@post_primary) { delete $rules_to_watch{$_}; } + + $failure_msg =~ s/\s*$//; #Remove trailing space + warn "$My_name: $failure_msg\n", + " ==> You will need to change a source file before I do another run <==\n"; + if ($failure_cmd) { + Run_subst( $failure_cmd ); + } + } + else { + if ( ($#primary_warning_summary > -1) && $warning_cmd ) { + Run_subst( $warning_cmd ); + } + elsif ( ($#primary_warning_summary > -1) && $warnings_as_errors && $failure_cmd ) { + Run_subst( $failure_cmd ); + } + elsif ($success_cmd) { + Run_subst( $success_cmd ); + } + } + rdb_show_rule_errors(); + if ($rules_list) { rdb_list(); } + if ($show_time && ! $first_time) { show_timing(); } + if ( $dependents_list && ($updated || $failure) ) { + my $deps_handle = new FileHandle "> $deps_file"; + if ( defined $deps_handle ) { + deps_list($deps_handle); + close($deps_handle); + } + else { + warn "Cannot open '$deps_file' for output of dependency information\n"; + } + } + + # Now wait for a file to change... + &rdb_cache_generated; + # During waiting for file changes, handle ctrl/C and ctrl/break here, + # rather than letting system handle them by terminating script (and + # code in the following command line to work: any script that calls + # it). This allows, for example, the command cleanup in the following + # command line to work: + # latexmk -pvc foo; cleanup; + &catch_break; + $have_break = 0; + $last_action_time = time(); + $waiting = 1; + print "\n=== Watching for updated files. Use ctrl/C to stop ...\n"; + WAIT: while (1) { + sleep( $sleep_time ); + if ($have_break) { last WAIT; } + if ( rdb_user_changes(keys %rules_to_watch) ) { + if (!$silent) { + warn "$My_name: Need to remake files.\n"; + &rdb_diagnose_changes( ' ' ); + } + last WAIT; + } + # Don't count waiting time in processing: + $processing_time1 = processing_time(); + # Does this do this job???? + local $new_files = 0; + rdb_for_some( [keys %current_primaries], sub{ $new_files += &rdb_find_new_files } ); + if ($new_files > 0) { + warn "$My_name: New file(s) found.\n"; + last WAIT; + } + if ($have_break) { last WAIT; } + if ($pvc_timeout && ( time() > $last_action_time+60*$pvc_timeout_mins ) ) { + $timed_out = 1; + last WAIT; + } + } # end WAIT: + &default_break; + if ($have_break) { + print "$My_name: User typed ctrl/C or ctrl/break. I'll finish.\n"; + return; + } + if ($timed_out) { + print "$My_name: More than $pvc_timeout_mins mins of inactivity. I'll finish.\n"; + return; + } + $waiting = 0; if ($diagnostics) { warn "NOT WAITING\n"; } + } #end infinite_loop CHANGE: +} #END sub make_preview_continuous + +#************************************************************ + +sub process_rc_file { + # Usage process_rc_file( filename ) + # NEW VERSION + # Run rc_file whose name is given in first argument + # Exit with code 0 on success + # Exit with code 1 if file cannot be read or does not exist. + # Stop if there is a syntax error or other problem. + # PREVIOUSLY: + # Exit with code 2 if is a syntax error or other problem. + my $rc_file = $_[0]; + my $ret_code = 0; + warn "$My_name: Executing Perl code in file '$rc_file'...\n" + if $diagnostics; + # I could use the do command of perl, but the preceeding -r test + # to get good diagnostics gets the wrong result under cygwin + # (e.g., on /cygdrive/c/latexmk/LatexMk) + my $RCH = new FileHandle; + if ( !-e $rc_file ) { + warn "$My_name: The rc-file '$rc_file' does not exist\n"; + return 1; + } + elsif ( -d $rc_file ) { + warn "$My_name: The supposed rc-file '$rc_file' is a directory; but it\n", + " should be a normal text file\n"; + return 1; + } + elsif ( open $RCH, "<$rc_file" ) { + { local $/; eval <$RCH>; } + close $RCH; + } + else { + warn "$My_name: I cannot read the rc-file '$rc_file'\n"; + return 1; + } + # PREVIOUS VERSION +# if ( ! -r $rc_file ) { +# warn "$My_name: I cannot read the rc-file '$rc_file'\n", +# " or at least that's what Perl (for $^O) reports\n"; +# return 1; +# } +# do( $rc_file ); + if ( $@ ) { + # Indent each line of possibly multiline message: + my $message = prefix( $@, " " ); + warn "$My_name: Initialization file '$rc_file' gave an error:\n", + "$message\n"; + die "$My_name: Stopping because of problem with rc file\n"; + # Use the following if want non-fatal error. + return 2; + } + return 0; +} #END process_rc_file + +#************************************************************ + +sub execute_code_string { + # Usage execute_code_string( string_of_code ) + # Run the perl code contained in first argument + # Halt if there is a syntax error or other problem. + # ???Should I leave the exiting to the caller (perhaps as an option)? + # But I can always catch it with an eval if necessary. + # That confuses ctrl/C and ctrl/break handling. + my $code = $_[0]; + warn "$My_name: Executing initialization code specified by -e:\n", + " '$code'...\n" + if $diagnostics; + eval $code; + # The return value from the eval is not useful, since it is the value of + # the last expression evaluated, which could be anything. + # The correct test of errors is on the value of $@. + + if ( $@ ) { + # Indent each line of possibly multiline message: + my $message = prefix( $@, " " ); + die "$My_name: ", + "Stopping because executing following code from command line\n", + " $code\n", + "gave an error:\n", + "$message\n"; + } +} #END execute_code_string + +#************************************************************ + +sub cleanup1 { + # Usage: cleanup1( directory, exts_without_period, ... ) + # + # The directory and the root file name are fixed names, so I must escape + # any glob metacharacters in them: + my $dir = fix_pattern( shift ); + my $root_fixed = fix_pattern( $root_filename ); + foreach (@_) { + my $name = /%R/ ? $_ : "%R.$_"; + $name =~ s/%R/${root_fixed}/; + $name = $dir.$name; + unlink_or_move( my_glob( "$name" ) ); + } +} #END cleanup1 + +#************************************************************ + +sub cleanup_cusdep_generated { + # Remove files generated by custom dependencies + rdb_for_actives( \&cleanup_one_cusdep_generated ); +} #END cleanup_cusdep_generated + +#************************************************************ + +sub cleanup_one_cusdep_generated { + # Remove destination file generated by one custom dependency + # Assume rule context, but not that the rule is a custom dependency. + # Only delete destination file if source file exists (so destination + # file can be recreated) + if ( $$Pcmd_type ne 'cusdep' ) { + # NOT cusdep + return; + } + if ( ! -e $$Psource ) { + warn "$My_name: For custom dependency '$rule',\n", + " I won't delete destination file '$$Pdest'\n", + " and any other generated files,\n", + " because the source file '$$Psource' doesn't exist,\n", + " so the destination file may not be able to be recreated\n"; + return; + } + unlink_or_move( $$Pdest, keys %$PHdest ); +} #END cleanup_one_cusdep_generated + +#************************************************************ +#************************************************************ +#************************************************************ + +# Error handling routines, warning routines, help + +#************************************************************ + +sub die_trace { + # Call: die_trace( message ); + &traceback; # argument(s) passed unchanged + die "\n"; +} #END die_trace + +#************************************************************ + +sub traceback { + # Call: &traceback + # or traceback( message, ) + my $msg = shift; + if ($msg) { warn "$msg\n"; } + warn "Traceback:\n"; + my $i=0; # Start with immediate caller + while ( my ($pack, $file, $line, $func) = caller($i++) ) { + if ($func eq 'die_trace') { next; } + warn " $func called from line $line\n"; + } +} #END traceback + +#************************************************************ + +sub exit_msg1 +{ + # exit_msg1( error_message, retcode [, action]) + # 1. display error message + # 2. if action set, then restore aux file + # 3. exit with retcode + warn "\n------------\n"; + warn "$My_name: $_[0].\n"; + warn "-- Use the -f option to force complete processing.\n"; + + my $retcode = $_[1]; + if ($retcode >= 256) { + # Retcode is the kind returned by system from an external command + # which is 256 * command's_retcode + $retcode /= 256; + } + exit $retcode; +} #END exit_msg1 + +#************************************************************ + +sub warn_running { + # Message about running program: + if ( $silent ) { + warn "$My_name: @_\n"; + } + else { + warn "------------\n@_\n------------\n"; + } +} #END warn_running + +#************************************************************ + +sub exit_help +# Exit giving diagnostic from arguments and how to get help. +{ + warn "\n$My_name: @_\n", + "Use\n", + " $my_name -help\nto get usage information\n"; + exit 10; +} #END exit_help + + +#************************************************************ + +sub print_help +{ + print + "$My_name $version_num: Automatic LaTeX document generation routine\n\n", + "Usage: $my_name [latexmk_options] [filename ...]\n\n", + " Latexmk_options:\n", + " -aux-directory=dir or -auxdir=dir \n", + " - set name of directory for auxiliary files (aux, log)\n", + " - Currently this only works with MiKTeX\n", + " -bibtex - use bibtex when needed (default)\n", + " -bibtex- - never use bibtex\n", + " -bibtex-cond - use bibtex when needed, but only if the bib file exists\n", + " -bibtex-cond1 - use bibtex when needed, but only if the bib file exists;\n", + " on cleanup delete bbl file only if bib file exists\n", + " -bm - Print message across the page when converting to postscript\n", + " -bi - Set contrast or intensity of banner\n", + " -bs - Set scale for banner\n", + " -commands - list commands used by $my_name for processing files\n", + " -c - clean up (remove) all nonessential files, except\n", + " dvi, ps and pdf files.\n", + " This and the other clean-ups are instead of a regular make.\n", + " -C - clean up (remove) all nonessential files\n", + " including aux, dep, dvi, postscript and pdf files\n", + " and file of database of file information\n", + " -CA - clean up (remove) all nonessential files.\n", + " Equivalent to -C option.\n", + " -CF - Remove file of database of file information before doing \n", + " other actions\n", + " -cd - Change to directory of source file when processing it\n", + " -cd- - Do NOT change to directory of source file when processing it\n", + " -dependents or -deps - Show list of dependent files after processing\n", + " -dependents- or -deps- - Do not show list of dependent files\n", + " -deps-out=file - Set name of output file for dependency list,\n", + " and turn on showing of dependency list\n", + " -dF - Filter to apply to dvi file\n", + " -dvi - generate dvi\n", + " -dvi- - turn off required dvi\n", + " -e - Execute specified Perl code (as part of latexmk start-up\n", + " code)\n", + " -f - force continued processing past errors\n", + " -f- - turn off forced continuing processing past errors\n", + " -gg - Super go mode: clean out generated files (-CA), and then\n", + " process files regardless of file timestamps\n", + " -g - process regardless of file timestamps\n", + " -g- - Turn off -g\n", + " -h - print help\n", + " -help - print help\n", + " -jobname=STRING - set basename of output file(s) to STRING.\n", + " (Like --jobname=STRING on command line for many current\n", + " implementations of latex/pdflatex.)\n", + " -l - force landscape mode\n", + " -l- - turn off -l\n", + " -latex= - set program used for latex.\n", + " (replace '' by the program name)\n", + " -latexoption=