diff options
Diffstat (limited to 'Master/texmf-dist/scripts/latexmk/latexmk.pl')
-rwxr-xr-x | Master/texmf-dist/scripts/latexmk/latexmk.pl | 312 |
1 files changed, 245 insertions, 67 deletions
diff --git a/Master/texmf-dist/scripts/latexmk/latexmk.pl b/Master/texmf-dist/scripts/latexmk/latexmk.pl index b5e5fe77ff5..b03c9a58da6 100755 --- a/Master/texmf-dist/scripts/latexmk/latexmk.pl +++ b/Master/texmf-dist/scripts/latexmk/latexmk.pl @@ -24,7 +24,6 @@ use warnings; #======================================= - #?? Force mode doesn't appear to do force (if error in latex file) #??? Get banner back in. #?? CORRECT DIAGNOSTICS ON CHANGED FILES IF THEY DIDN'T EXIST BEFORE @@ -33,7 +32,7 @@ use warnings; #?? logfile w/o fdb file: don't set changed file, perhaps for generated exts. # Reconsider #?? Do proper run-stuff for bibtex, makeindex, cus-deps. OK I think -# Parse and correctly find bst and ist files +# Parse and correctly find ist files # ATTEMPT TO ALLOW FILENAMES WITH SPACES: @@ -108,8 +107,8 @@ use warnings; $my_name = 'latexmk'; $My_name = 'Latexmk'; -$version_num = '4.18'; -$version_details = "$My_name, John Collins, 27 July 2010"; +$version_num = '4.21'; +$version_details = "$My_name, John Collins, 28 December 2010"; use Config; @@ -178,6 +177,41 @@ else { ## ## Modification log from 23 Jun 2010 onwards in detail ## +## 28 Dec 2010, John Collins Version number to 4.21 +## 1. Improved handling of quotes in filenames in log file: +## a. Clean double quotes in names from messages about files. +## b. In ("..." construct, as in MiKTeX, the only character +## prohibited is ". Previously I disallowed ( and ), +## which are allowed special characters. +## 2. Reversed deletion and reinsertion in dependents list +## of name found by kpsewhich. Otherwise sometimes a name +## could be deleted in error +## 12 Nov 2010, John Collins Version number to 4.20 +## 11 Nov 2010, John Collins Fix problem that when bibtex finds no +## citations, this is treated by bibtex as an +## error, but latexmk should only treat it as +## a warning but not an error +## 8,9 Nov 2010, John Collins Get .bst file in source file list for bibtex +## 30 Oct 2010, John Collins Allow clean-up to delete destination files of +## custom-dependencies +## Configuration variable $cleanup_includes_cusdep_generated to +## whether this is done +## 20 Sep 2010, John Collins First attempt to deal with no citations warning +## Still have the problem that bibtex gives non-zero exit code +## 19 Sep 2010, John Collins Orthogonalize option and command specification +## a la Manuel Pegourie-Gonnard (email of 19 Sep 2010, +## "[latexmk] latex engine and default options".) +## Still needs documentation. +## 19 Sep 2010, John Collins More general pattern for files to clean up, +## Thanks to Manuel Pegourie-Gonnard for the code +## Must check the use of %generated_exts_all in +## sub rdb_file_change1. +## 30 Aug 2010, John Collins Remove double quotes (if any) surrounding +## output filename read from .log file. +## (Avoids wrong diagnostic message.) +## 19 Aug 2010, John Collins Remove use of --width option on $pscmd +## on linux. It's no longer needed. +## 30 Jul 2010, John Collins Timing information ## 27 Jul 2010, John Collins Clean up some comments. ## This is release version for 4.18. ## 23 Jul 2010, John Collins Only produce "Removing no-longer-needed @@ -332,6 +366,11 @@ $log_wrap = 79; ## Commands to invoke latex, pdflatex $latex = 'latex %O %S'; $pdflatex = 'pdflatex %O %S'; + +## Default switches: +$latex_default_switches = ''; +$pdflatex_default_switches = ''; + ## Switch(es) to make them silent: $latex_silent_switch = '-interaction=batchmode'; $pdflatex_silent_switch = '-interaction=batchmode'; @@ -727,7 +766,10 @@ else { # for SUSE 7.2). # However the option is not available under other UNIX-type # systems, e.g., Solaris 8. - $pscmd = "ps --width 200 -f -u $ENV{USER}"; + # But (19 Aug 2010), the truncation doesn't happen on RHEL4 and 5, + # unless the output is written to a terminal. So the --width + # option is now unnecessary + # $pscmd = "ps --width 200 -f -u $ENV{USER}"; } elsif ( $^O eq "darwin" ) { # OS-X on Macintosh @@ -849,6 +891,9 @@ $cleanup_fdb = 0; # No removal of file for latexmk's file-database $cleanup_only = 0; # When doing cleanup, do not go-on to making files $cleanup_includes_generated = 0; # Determines whether cleanup deletes files generated by + # custom dependencies +$cleanup_includes_cusdep_generated = 0; + # Determines whether cleanup deletes files generated by # (pdf)latex (found from \openout lines in log file). $diagnostics = 0; $dvi_filter = ''; # DVI filter command @@ -861,6 +906,11 @@ $preview_mode = 0; $preview_continuous_mode = 0; $printout_mode = 0; # Don't print the file +$show_time = 0; +@timings = (); +$processing_time1 = processing_time(); + + # Do we make view file in temporary then move to final destination? # (To avoid premature updating by viewer). $always_view_file_via_temporary = 0; # Set to 1 if viewed file is always @@ -1210,6 +1260,12 @@ while ($_ = $ARGV[0]) } elsif (/^-l$/) { $landscape_mode = 1; } elsif (/^-l-$/) { $landscape_mode = 0; } + elsif (/^-latex=(.*)$/) { + $latex = $1; + } + elsif (/^-pdflatex=(.*)$/) { + $pdflatex = $1; + } elsif (/^-new-viewer$/) { $new_viewer_always = 1; } @@ -1249,6 +1305,8 @@ while ($_ = $ARGV[0]) } elsif (/^-pvc-$/) { $preview_continuous_mode = 0; } elsif (/^-silent$/ || /^-quiet$/ ){ $silent = 1; } + elsif (/^-time$/) { $show_time = 1;} + elsif (/^-time-$/) { $show_time = 0;} elsif (/^-v$/ || /^-version$/) { print "\n$version_details. Version $version_num\n"; exit; @@ -1453,6 +1511,11 @@ if ( ($jobname ne '') && ($num_files > 1) ) { # Normalize the commands, to have place-holders for source, dest etc: &fix_cmds; +# Add common options +add_option( \$latex, $latex_default_switches ); +add_option( \$pdflatex, $pdflatex_default_switches ); + + # If landscape mode, change dvips processor, and the previewers: if ( $landscape_mode ) { @@ -1618,9 +1681,17 @@ foreach $filename ( @file_list ) local %conversions = (); # (pdf)latex-performed conversions. # Maps output file created and read by (pdf)latex # to source file of conversion. + print "$My_name: Examining log file for generated files...\n"; &parse_logB; + print "$My_name: Examining fdb file for rules ...\n"; + # Needed for cleanup of files generated by custom dependencies + if ( -e $fdb_file ) { + $rdb_errors = rdb_read( $fdb_file ); + $have_fdb = ($rdb_errors == 0); + } + my @index_bibtex_generated = (); my @aux_files = (); my %other_generated = %generated_log; @@ -1665,6 +1736,9 @@ foreach $filename ( @file_list ) if ($cleanup_includes_generated) { unlink( keys %other_generated ); } + if ( $cleanup_includes_cusdep_generated) { + &cleanup_cusdep_generated; + } if ( $cleanup_mode == 1 ) { &cleanup1( 'dvi', 'dviF', 'ps', 'psF', 'pdf', split(' ', $clean_full_ext) @@ -1796,6 +1870,16 @@ continue { } &ifcd_popd; } + +if ($show_time) { show_timing();} + +sub show_timing { + my $processing_time = processing_time() - $processing_time1; + print @timings, "Accumulated processing time = $processing_time\n"; + @timings = (); + $processing_time1 = processing_time(); +} + # If we get here without going through the continue section: if ( $do_cd && ($#dir_stack > -1) ) { # Just in case we did an abnormal exit from the loop @@ -2403,6 +2487,7 @@ CHANGE: " ==> You will need to change a source file before I do another run <==\n"; } rdb_show_rule_errors(); + if ($show_time && ! $first_time) { show_timing(); } if ( $first_time || $updated || $failure ) { print "\n=== Watching for updated files. Use ctrl/C to stop ...\n"; } @@ -2419,6 +2504,8 @@ CHANGE: } last WAIT; } + # Don't count waiting time in processing: + $processing_time1 = processing_time(); # Does this do this job???? local $new_files = 0; rdb_for_some( [keys %current_primaries], sub{ $new_files += &rdb_find_new_filesB } ); @@ -2521,10 +2608,42 @@ sub execute_code_string { sub cleanup1 { # Usage: cleanup1( exts_without_period, ... ) - foreach (@_) { unlink("$root_filename.$_"); } + foreach (@_) { + (my $name = /%R/ ? $_ : "%R.$_") =~ s/%R/$root_filename/; + unlink("$name"); + } } #END cleanup1 #************************************************************ + +sub cleanup_cusdep_generated { + # Remove files generated by custom dependencies + rdb_for_all( \&cleanup_one_cusdep_generated ); +} #END cleanup_cusdep_generated + +#************************************************************ + +sub cleanup_one_cusdep_generated { + # Remove destination file generated by one custom dependency + # Assume rule context, but not that the rule is a custom dependency. + # Only delete destination file if source file exists (so destination + # file can be recreated) + if ( $$Pcmd_type ne 'cusdep' ) { + # NOT cusdep + return; + } + if ( (-e $$Pdest) && (-e $$Psource) ) { + unlink $$Pdest; + } + elsif ( (-e $$Pdest) && (!-e $$Psource) ) { + warn "$My_name: For custom dependency '$rule',\n", + " I won't delete destination file '$$Pdest'\n", + " because the source file '$$Psource' doesn't exist,\n", + " so the destination file may not be able to be recreated\n"; + } +} #END cleanup_one_cusdep_generated + +#************************************************************ #************************************************************ #************************************************************ @@ -2644,12 +2763,16 @@ sub print_help " implementations of latex/pdflatex.)\n", " -l - force landscape mode\n", " -l- - turn off -l\n", + " -latex=<program> - set program used for latex.\n", + " (replace '<program>' by the program name)\n", " -new-viewer - in -pvc mode, always start a new viewer\n", " -new-viewer- - in -pvc mode, start a new viewer only if needed\n", " -nobibtex - never use bibtex\n", " -nodependents - Do not show list of dependent files after processing\n", " -pdf - generate pdf by pdflatex\n", " -pdfdvi - generate pdf by dvipdf\n", + " -pdflatex=<program> - set program used for pdflatex.\n", + " (replace '<program>' by the program name)\n", " -pdfps - generate pdf by ps2pdf\n", " -pdf- - turn off pdf\n", " -ps - generate postscript\n", @@ -2668,7 +2791,9 @@ sub print_help " -pvc- - turn off -pvc\n", " -r <file> - Read custom RC file\n", " -silent - silence progress messages from called programs\n", - " -v - display program version\n", + " -time - show CPU time used\n", + " -time- - don't show CPU time used\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", @@ -2730,12 +2855,14 @@ sub view_file_via_temporary { #************************************************************ #### Tex-related utilities +#************************************************** sub check_bibtex_log { # Check for bibtex warnings: # Usage: check_bibtex_log( base_of_bibtex_run ) # return 0: OK, 1: bibtex warnings, 2: bibtex errors, # 3: could not open .blg file. + # 10: only error is missing \citation commands. my $base = $_[0]; my $log_name = "$base.blg"; @@ -2744,17 +2871,35 @@ sub check_bibtex_log { or return 3; my $have_warning = 0; my $have_error = 0; + my $missing_citations = 0; + my $error_count = 0; while (<$log_file>) { - if (/Warning--/) { + if (/^Warning--/) { #print "Bibtex warning: $_"; $have_warning = 1; } - if (/error message/) { - #print "Bibtex error: $_"; + elsif ( /^I found no \\citation commands---while reading file/ ) { + $missing_citations++; + } + elsif (/There (were|was) (\d+) error message/) { + $error_count = $2; + #print "Bibtex error: count=$error_count $_"; $have_error = 1; } } close $log_file; + #print "Bibtex errors = $error_count, missing citations = $missing_citations\n"; + if ($have_error && ($error_count <= $missing_citations ) + && ($missing_citations > 0) ) { + # If the only error is a missing citation line, that should only + # count as a warning. + # But have to deal with the problem that bibtex gives a non-zero + # exit code. So leave things as they are so that the user gets + # a better diagnostic ?????????????????????????? +# $have_error = 0; +# $have_warning = 1; + return 10; + } if ($have_error) {return 2;} if ($have_warning) {return 1;} return 0; @@ -2762,18 +2907,23 @@ sub check_bibtex_log { #************************************************** -sub clean_file_name{ - # Convert filename found in log file to true filename. - # Used normally only by parse_logB, below - # 1. For names of form - # `"string".ext', which arises e.g., from \jobname.bbl: +sub clean_file_name { + # Convert quoted filename as found in log file to filename without quotes + # Allows arbitrarily embedded double-quoted substrings, includes the + # cases + # 1. `"string".ext', which arises e.g., from \jobname.bbl: # when the base filename contains spaces, \jobname has quotes. # and from \includegraphics with basename specified. + # Also deals with filenames written by asymptote.sty # 2. Or "string.ext" from \includegraphcs with basename and ext specified. + # and from MiKTeX logfile for input files with spaces. + # Doubled quotes (e.g., A""B) don't get converted. + # Neither do unmatched quotes. my $filename = $_[0]; - $filename =~ s/^\"([^\"]*)\"(.*)$/$1$2/; + while ( $filename =~ s/^([^\"]*)\"([^\"]+)\"(.*)$/$1$2$3/ ) {} return $filename; } + # ------------------------------ sub parse_logB { @@ -2973,8 +3123,8 @@ LINE: next LINE; } if ( /^Output written on\s+(.*)\s+\(\d+\s+page/ ) { - $primary_out = $1; - warn "$My_name: Log file says output to '$1'\n" + $primary_out = clean_file_name($1); + warn "$My_name: Log file says output to '$primary_out'\n" unless $silent; next LINE; } @@ -2987,15 +3137,15 @@ LINE: next LINE; } if ( /^\\openout\d+\s*=\s*\`([^\']+)\'\.$/ ) { - $generated_log{$1} = 1; + $generated_log{clean_file_name($1)} = 1; next LINE; } # Test for conversion produced by package: if ( /^Package (\S+) Info: Source file: <([^>]+)>/ ) { # Info. produced by epstopdf (and possibly others) # about file conversion - $current_pkg = $1; - $delegated_source = $2; + $current_pkg = clean_file_name($1); + $delegated_source = clean_file_name($2); $block_type = 'conversion'; next LINE; } @@ -3064,9 +3214,9 @@ LINE: next LINE; } } - if ( /^File: ([^\s\[]*) Graphic file \(type / ) { + if ( /^File: (.+) Graphic file \(type / ) { # First line of message from includegraphics/x - $dependents{$1} = 1; + $dependents{clean_file_name($1)} = 1; next LINE; } # Now test for generic lines to ignore, only after special cases! @@ -3140,7 +3290,7 @@ LINE: # Array of new candidate include files; sometimes more than one. my @new_includes = (); my $quoted = 0; - if ( /^\"([^\(^\)^\"]+)\"/ ) { + if ( /^\"([^\"]+)\"/ ) { # Quoted file name, as from MikTeX $quoted = 1; } @@ -3254,8 +3404,8 @@ CANDIDATE: # If the file still is not found, assume non-existent; my @kpse_result = kpsewhich( $candidate ); if ($#kpse_result > -1) { - $dependents{$kpse_result[0]} = 4; delete $dependents{$candidate}; + $dependents{$kpse_result[0]} = 4; next CANDIDATE; } else { @@ -3360,7 +3510,6 @@ CANDIDATE_PAIR: foreach (@dependents) { print " '$_' "; if ( $dependents{$_} == 6 ) { print " written by (pdf)latex";} - print "\n"; if ( $dependents{$_} == 7 ) { print " converted by (pdf)latex";} print "\n"; } @@ -3378,8 +3527,7 @@ CANDIDATE_PAIR: } if ( $misparse > 0 ) { - print "$misparse\n"; - print "Apparent input files apparently from misunderstood lines in .log file:\n"; + print "Possible input files, perhaps from misunderstood lines in .log file:\n"; foreach ( @misparse ) { print " $_\n"; } } } @@ -3389,8 +3537,8 @@ CANDIDATE_PAIR: #************************************************************ sub parse_aux { - #Usage: parse_aux( $aux_file, \@new_bib_files, \@new_aux_files ) - # Parse aux_file (recursively) for bib files. + #Usage: parse_aux( $aux_file, \@new_bib_files, \@new_aux_files, \@new_bst_files ) + # Parse aux_file (recursively) for bib files, and bst files. # If can't open aux file, then # Return 0 and leave @new_bib_files empty # Else set @new_bib_files from information in the aux files @@ -3404,8 +3552,10 @@ sub parse_aux { my $aux_file = $_[0]; local $Pbib_files = $_[1]; local $Paux_files = $_[2]; + local $Pbst_files = $_[3]; @$Pbib_files = (); + @$Pbst_files = (); @$Paux_files = (); parse_aux1( $aux_file ); @@ -3413,6 +3563,7 @@ sub parse_aux { return 0; } @$Pbib_files = uniqs( @$Pbib_files ); + @$Pbst_files = uniqs( @$Pbst_files ); if ( $#{$Pbib_files} == -1 ) { warn "$My_name: No .bib files listed in .aux file '$aux_file' \n", @@ -3421,6 +3572,8 @@ sub parse_aux { my $bibret = &find_file_list1( $Pbib_files, $Pbib_files, '.bib', \@BIBINPUTS ); @$Pbib_files = uniqs( @$Pbib_files ); + &find_file_list1( $Pbst_files, $Pbst_files, '.bst' ); + @$Pbst_files = uniqs( @$Pbst_files ); if ($bibret == 0) { warn "$My_name: Found bibliography file(s) [@$Pbib_files]\n" unless $silent; @@ -3468,6 +3621,11 @@ AUX_LINE: # (Without the '.bib' extension) push( @$Pbib_files, split /,/, $1 ); } + elsif ( /^\\bibstyle\{(.*)\}/ ) { + # \\bibstyle{bst_file_name} + # (Without the '.bst' extension) + push( @$Pbst_files, $1 ); + } elsif ( /^\\\@input\{(.*)\}/ ) { # \\@input{next_aux_file_name} &parse_aux1( $1 ); @@ -3968,9 +4126,10 @@ sub rdb_set_from_logB { foreach my $bbl_file ( uniqs( @bbl_files ) ) { my ($bbl_base, $bbl_path, $bbl_ext) = fileparseA( $bbl_file ); $bbl_base = $bbl_path.$bbl_base; - my @new_bib_files; - my @new_aux_files; - &parse_aux( "$bbl_base.aux", \@new_bib_files, \@new_aux_files ); + my @new_bib_files = (); + my @new_aux_files = (); + my @new_bst_files = (); + &parse_aux( "$bbl_base.aux", \@new_bib_files, \@new_aux_files, \@new_bst_files ); my $from_rule = "bibtex $bbl_base"; print "!!!===Dealing with rule '$from_rule'\n" if ($diagnostics); @@ -3982,7 +4141,7 @@ sub rdb_set_from_logB { } local %old_sources = (); rdb_one_rule( $from_rule, sub { %old_sources = %$PHsource; } ); - foreach my $source ( @new_bib_files, @new_aux_files ) { + foreach my $source ( @new_bib_files, @new_aux_files, @new_bst_files ) { print " === Source file '$source' for '$from_rule'\n" if ($diagnostics); rdb_ensure_file( $from_rule, $source ); @@ -4982,6 +5141,11 @@ sub rdb_run1 { elsif ($retcode == 1) { push @warnings, "Bibtex warnings for '$$Pbase'"; } + elsif ($retcode == 10) { + push @warnings, "Bibtex found no citations for '$$Pbase'"; + # But this is an innocuous error, so fix return code + $return = 0; + } } $updated = 1; @@ -5986,6 +6150,13 @@ sub get_time_size_raw #************************************************************ +sub processing_time +{ my ($user, $system, $cuser, $csystem) = times(); + return $user + $system + $cuser + $csystem; +} + +#************************************************************ + sub get_checksum_md5 { my $source = shift; my $input = new FileHandle; @@ -6040,38 +6211,41 @@ sub find_file1 { # On success: full_name = full name with path, retcode = 0 # On failure: full_name = given name, retcode = 1 - my $name = $_[0]; - # Make local copy of path, since we may rewrite it! - my @path = @{$_[1]}; - if ( $name =~ /^\// ) { - # Absolute path (if under UNIX) - # This needs fixing, in general - if (-e $name) { return( $name, 0 );} - else { return( $name, 1 );} - } - foreach my $dir ( @path ) { - #??print "-------------dir='$dir', "; - # Make $dir concatenatable, and empty for current dir: - if ( $dir eq '.' ) { - $dir = ''; - } - elsif ( $dir =~ /[\/\\:]$/ ) { - #OK if dir ends in / or \ or : - } - elsif ( $dir ne '' ) { - #Append directory separator only to non-empty dir - $dir = "$dir/"; - } - #?? print " newdir='$dir'\n"; - if (-e "$dir$name") { - return("$dir$name", 0); - } - } - my @kpse_result = kpsewhich( $name ); - if ($#kpse_result > -1) { - return( $kpse_result[0], 0); - } - return("$name" , 1); + my $name = $_[0]; + # Make local copy of path, since we may rewrite it! + my @path = (); + if ($_[1]) { + @path = @{$_[1]}; + } + if ( $name =~ /^\// ) { + # Absolute path (if under UNIX) + # This needs fixing, in general + if (-e $name) { return( $name, 0 );} + else { return( $name, 1 );} + } + foreach my $dir ( @path ) { + #??print "-------------dir='$dir', "; + # Make $dir concatenatable, and empty for current dir: + if ( $dir eq '.' ) { + $dir = ''; + } + elsif ( $dir =~ /[\/\\:]$/ ) { + #OK if dir ends in / or \ or : + } + elsif ( $dir ne '' ) { + #Append directory separator only to non-empty dir + $dir = "$dir/"; + } + #?? print " newdir='$dir'\n"; + if (-e "$dir$name") { + return("$dir$name", 0); + } + } + my @kpse_result = kpsewhich( $name ); + if ($#kpse_result > -1) { + return( $kpse_result[0], 0); + } + return("$name" , 1); } #END find_file1 #************************************************************ @@ -6419,7 +6593,11 @@ sub tempfile1 { sub Run_msg { # Same as Run, but give message about my running warn_running( "Running '$_[0]'" ); - Run($_[0]); + my $time1 = processing_time(); + my ($pid, $return) = Run($_[0]); + my $time = processing_time() - $time1; + push @timings, "'$_[0]': time = $time\n"; + return ($pid, $return); } sub Run { |