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