texlive[62768] branches/branch2021.final: latexmk (17mar22) (branch)

commits+karl at tug.org commits+karl at tug.org
Thu Mar 17 21:30:35 CET 2022


Revision: 62768
          http://tug.org/svn/texlive?view=revision&revision=62768
Author:   karl
Date:     2022-03-17 21:30:35 +0100 (Thu, 17 Mar 2022)
Log Message:
-----------
latexmk (17mar22) (branch)

Modified Paths:
--------------
    branches/branch2021.final/Build/source/texk/texlive/linked_scripts/latexmk/latexmk.pl
    branches/branch2021.final/Master/texmf-dist/doc/man/man1/latexmk.1
    branches/branch2021.final/Master/texmf-dist/doc/man/man1/latexmk.man1.pdf
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/CHANGES
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/INSTALL
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/README
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/asymptote_latexmkrc
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/chapterbib-latexmkrc
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/clean_pattern_latexmkrc
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/exceltex_latexmkrc
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/fix-aux.latexmkrc
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/pythontex-latexmkrc
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.pdf
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.txt
    branches/branch2021.final/Master/texmf-dist/scripts/latexmk/latexmk.pl

Added Paths:
-----------
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/dot2tex-latexmkrc
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/glossaries_latexmkrc
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/minted_latexmkrc
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.cmd

Removed Paths:
-------------
    branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/glossary_latexmkrc

Modified: branches/branch2021.final/Build/source/texk/texlive/linked_scripts/latexmk/latexmk.pl
===================================================================
--- branches/branch2021.final/Build/source/texk/texlive/linked_scripts/latexmk/latexmk.pl	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Build/source/texk/texlive/linked_scripts/latexmk/latexmk.pl	2022-03-17 20:30:35 UTC (rev 62768)
@@ -2,7 +2,7 @@
 
 use warnings;
 
-## Copyright John Collins 1998-2021
+## Copyright John Collins 1998-2022
 ##           (username jcc8 at node psu.edu)
 ##      (and thanks to David Coppit (username david at node coppit.org) 
 ##           for suggestions) 
@@ -25,73 +25,8 @@
 ##    along with this program; if not, write to the Free Software
 ##    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 ##
+## See file CHANGES for list of main version-to-version changes.
 ##
-##
-##   Modification log from 14 Apr 2021 onwards in detail
-##
-## 20 Nov 2021 John Collins  Add /etc to list of locations for system rc files
-##  4 Nov 2021 John Collins  Improve diagnostics when there's a mismatch of 
-##                             destination file of rule between .fdb_latexmk
-##                             file and expectation.
-##  2 Nov 2021 John Collins  Sort generated-file section by filename; it's
-##                             already done in file data secton.
-##                           Only write fdb_latexmk file if nothing has been
-##                             done.  (Addition of $runs_total variable.)
-##                           V. 4.76.
-## 23 Sep 2021 John Collins  Option -time: times for all rules reported now
-## 18 Sep 2021 John Collins  For biber: parse blg file for config file use
-##                           V. 4.75.
-## 27 Aug 2021 John Collins  Modified "missing file" message (when parsing
-#                              log file). 
-## 29 May 2021 John Collins  When emulating aux_dir, put .synctex.gz .synctex
-##                             files in out_dir (as done by MiKTeX, and needed
-##                             for their use).
-##                           Turn emulate aux_dir off by default, to match older
-##                             behavior.  (BACKWARDS INCOMPATIBLE with 4.73 and
-##                             4.74.)
-##                           Add end-of-all-runs warning if emulate aux_dir needed
-##                             to be turned on, when it was initially off.
-##                           Add .synctex to list of extensions to clear by default.
-## 20 May 2021 John Collins  Turn back on default to report rc files read.
-##                           Add options -rc-report, -rc-report-, 
-##                             -dir_report, -dir_report-.
-## 16 May 2021 John Collins  Deal with some variable used only once warnings
-##                           Remove by default informational messages on rc
-##                           files read, and aux_dir and out_dir setting.
-##  5-6 May 2021 John Collins  Correct normalization of aux and out dirs.
-##                           Version 4.74
-##  3 May 2021 John Collins  Minor corrections.  Submit to CTAN.
-## 30 Apr 2021 John Collins  Revert the change of 14-15 Apr, by removing the
-##                           of cwd().  That gave sometimes obnoxiously slow
-##                           parsing of big log files, because of the slowness
-##                           of large number of calls to cwd() caused by calls
-##                           to sub normalize_filename. I think I am mistaken
-##                           that cwd() could possibly give a different result
-##                           than getcwd(), whose cached result is used by
-##                           my goodcwd(). That idea was my motivation on 14 Apr.
-## 22 Apr 2021 John Collins  Clean up aux and out_dir code.
-## 21 Apr 2021 John Collins  Clean up some comments
-##                           Add in emulation of -aux-directory.  On by
-##                           default.
-## 20 Apr 2021 John Collins  Add -dALLOWPSTRANSPARENCY option to ps2pdf and
-##                           dvi2pdf. That avoids problems with recent
-##                           ghostscript versions when, e.g., pstricks is used.
-## 16 Apr 2021 John Collins  Better normalization of aux_dir and out_dir, so
-##                that TEXMFOUTPUT, and the source and dest names for bibtex
-##                and makeindex allow them to work always when the aux_dir
-##                is **not** below cwd, at least under TeX Live. With MiKTeX
-##                bibtex works even without special precautions for aux_dir
-##                not below cwd.  But makeindex doesn't work in this case,
-##                even if TEXMFOUTPUT is set correctly.
-## 14-15 Apr 2021 John Collins  In normalize_filename, try both good_cwd() and
-##                           cwd() for removing directory component.
-##                           That improves clean up.  At least it could.
-##                V. 4.73.
-##
-##
-## 1998-2021, John Collins:  Many improvements and fixes.
-##   See CHANGE-log.txt for full list, and CHANGES for summaries
-##
 ## Modified by Evan McLean (no longer available for support)
 ## Original script (RCS version 2.3) called "go" written by David J. Musliner
 ##
@@ -108,8 +43,8 @@
 
 $my_name = 'latexmk';
 $My_name = 'Latexmk';
-$version_num = '4.76';
-$version_details = "$My_name, John Collins, 20 November 2021";
+$version_num = '4.77';
+$version_details = "$My_name, John Collins, 17 Mar. 2022. Version $version_num";
 
 use Config;
 use File::Basename;
@@ -127,21 +62,16 @@
     $have_bsd_glob = 1;
 }
 elsif ( eval{ File::Glob->import('glob'); 1; } ) {
-    warn "$My_name: I could not import File::Glob:bsd_glob, probably because your\n",
-         "  Perl is too old.  I have arranged to use the deprecated File::Glob:glob\n",
-         "  instead.\n",
-         "  WARNING: It may malfunction on clean up operation on filenames containing\n",
-         "           spaces.\n";
+    warn( "$My_name: I could not import File::Glob:bsd_glob, probably because your\n",
+             "  Perl is too old.  I have arranged to use the deprecated File::Glob:glob\n",
+             "  instead.\n",
+             "  WARNING: It may malfunction on clean up operation on filenames containing\n",
+             "           spaces.\n" );
     $have_bsd_glob = 0;
 }
 else {
     die "Could not import 'File::Glob:bsd_glob' or 'File::Glob:glob'\n";
 }
-# How I use the result of loading glob routines:
-sub my_glob {
-    if ($have_bsd_glob) { return bsd_glob( $_[0] ); }
-    else { return glob( $_[0] ); }
-}
 
 use File::Path 2.08 qw( make_path );
 use FileHandle;
@@ -152,11 +82,200 @@
 use Cwd "chdir";    # Ensure $ENV{PWD}  tracks cwd.
 use Digest::MD5;
 
-#use strict;
+#################################################
+#
+#  Unicode set up to be used in latexmk
+#
+use Encode qw( decode encode );
+use Unicode::Normalize;
+use utf8;  # For UTF-8 strings in **this** script
+use feature 'unicode_strings';
+use feature 'say';
+use bytes;  # To avoid messes when we use string operations on byte-coded/encoded
+            # filename strings.
 
+# Coding:
+# 1. $CS_system = CS for file names in file system calls, and for CL.
+#    It's to be UTF-8 on all except: MSWin when the MSWin system code page is
+#    not 65001.
+# 2. Internally use CS_system generally, and especially for filenames.
+#    Note with "use bytes;", even **de**coded strings have length and contents
+#    in terms of bytes with UTF-8 coding.
+#    Then standard file system calls, print to terminal don't need encoding,
+#    and things in rc files work unchanged from earlier versions of latexmk,
+#    when I didn't treat non-ASCII coding issues explicitly.
+# 3. But must set console codepage to system codepage on MSWin, otherwise
+#    display on terminal is garbled.
+# 4. fdb_latexmk: write and read UTF-8, convert to and from CS_system for
+#    strings.
+# 5. .fls, .log, .aux are all UTF-8, so if necessary convert to CS_system.
+# 6. However, with TeXLive on MSWin with system CP not equal to 65001,
+#    the PWD is in CS_system on all but most recent *latex (that's a bug).
+#    Convert file/path names to CS_system.
+# 7. Don't support non-UTF-8 on *nix.
+# 8. Do NOT do any conversion to a NF for Unicode: File systems are **either**
+#    normalization-sensitive (NTFS, ext4) and we need to preserve
+#    normalization, **or** they are normalization-insensitve (hfs+, apfs),
+#    in which case we can access a file with any normalization for its name.
+#
+# N.B.  I18N::Langinfo often doesn't give useful enough information.
+
+
+
+# My default CSs: UTF-8
+our $CS_system;
+$CS_system = 'UTF-8';
+# Quick short cut for tests of whether conversions needed:
+our $utf8_used = 1;
+
+# Win32 specific CP **numbers**.  Initialize to 65001 (utf-8), and change
+# by results of system calls.
+# Corresponding CS name: Prefix by 'CP'.
+# Preserve intial values for console/terminal to allow restore on exit.
+our ($CP_Win_system, $CP_init_Win_console_in, $CP_init_Win_console_out);
+$CP_Win_system = $CP_init_Win_console_in = $CP_init_Win_console_out = '65001';
+
+# Whether to revert Windows console CPs on exit:
+our $Win_revert_settings = 0;
+
+if ($^O eq "MSWin32") {
+    eval {  require Win32;
+            $CP_Win_system = Win32::GetACP();
+            $CS_system = 'CP' . $CP_Win_system;
+            $CP_init_Win_console_in = Win32::GetConsoleCP();
+            $CP_init_Win_console_out = Win32::GetConsoleOutputCP();
+            if ( Win32::SetConsoleOutputCP($CP_Win_system)
+                 && Win32::SetConsoleCP($CP_Win_system) ) {
+            } else {
+                warn "Cannot set Windows Console Output CP to $CP_Win_system.\n";
+            }
+    };
+    if ($@) { warn "Trouble finding and setting code pages used by Windows:\n",
+              "  $@",
+              "  ILL CONTINUE WITH UTF-8.\n"; 
+    }
+    else {
+        $Win_revert_settings =
+              ($CP_init_Win_console_in ne $CP_Win_system)
+              || ($CP_init_Win_console_out ne $CP_Win_system);
+    }
+    print "Win CP console initial and current in/out Win: ",
+        "($CP_init_Win_console_in, $CP_init_Win_console_out), ",
+        "($CP_Win_system, $CP_Win_system)\n";
+}
+$utf8_used = ($CS_system eq 'UTF-8') || ($CS_system eq 'CP65001');
+
+# Ensure that on ctrl/C interruption, etc, Windows console CPs are restored:
+use sigtrap qw(die untrapped normal-signals);
+END {
+    if ($Win_revert_settings ) {
+        warn "Reverting Windows console CPs to ",
+             "(in,out) = ($CP_init_Win_console_in,$CP_init_Win_console_out)\n";
+        Win32::SetConsoleCP($CP_init_Win_console_in);
+        Win32::SetConsoleOutputCP($CP_init_Win_console_out);
+    }
+}
+
+print "Coding system for system and terminal: '$CS_system'\n---\n"
+    unless $utf8_used;
+
+########################################################
+
+#************************************************************
+#************************************************************
+#            Unicode manipuation and normalization
+
+
+#-------------------------------------
+
+sub analyze_string {
+    # Useful for debugging encoding issues.
+    my ($m,$s) = @_;
+    say "=== $m '$s':";
+    say(
+        'Perl flag = ',
+        (utf8::is_utf8($s) ? 'utf8' : 'NOT utf8'),
+          ", len = ", length($s)
+        );
+    my @code = unpack( 'U*', $s );
+    @code = map { sprintf('%4X', $_) }  @code;
+    say join( ' ', @code );
+}
+
+#==================
+
+sub utf8_to_mine {
+    # Given string encoded in UTF-8, return encoded string in my current CS.
+    if  ($utf8_used) { return $_[0]; }
+    else { return  encode( $CS_system, decode('UTF-8', $_[0])); }  
+}
+
+#-------------------------------------
+
+sub mine_to_utf8 {
+    # Given string encoded in my current CS, return utf-8 encoded string.
+    if  ($utf8_used) { return $_[0]; }
+    else { return  encode( 'UTF-8', decode($CS_system, $_[0])); }
+}
+
+#-------------------------------------
+
+sub is_valid_utf8 {
+   eval { decode( 'UTF-8', $_[0], (Encode::FB_CROAK | Encode::LEAVE_SRC ) ); };
+   if ($@) { return 0; }
+   else { return 1; }
+}
+
+#-------------------------------------
+
+sub fprint8 {
+    # Usage: fprint8( handle, data array)
+    # Write to file converting from my CS to UTF-8
+    my $fh = shift;
+    print $fh mine_to_utf8( join( '', @_ ) );
+}
+
+#-------------------------------------
+
+################################################################
+
+
+
+
+################################################################
+################################################################
+#============ Deal with how I'm invoked: name and CL args:
+
+# Name that I'm invoked with indicates default behavior (latexmk
+# v. pdflatexmk, etc):
+(our $invoked_name) = fileparseA($0);
+
+our $invoked_kind = $invoked_name;
+print "$My_name: Invoked as '$invoked_name'\n"
+    if ($invoked_name ne 'latexmk');
+
+# Map my invoked name to pointer to array of default values for $dvi_mode,
+# $postscript_mode, $pdf_mode.  These are used if after processing rc files
+# and CL args, no values are set for any of these variables.
+# Thus default compilation for latexmk is by latex,
+#                          for pdflatexmk is by pdflatex, etc.
+%compilation_defaults =
+    ( 'latexmk' => [1,0,0],
+      'lualatexmk' => [0,0,4],
+      'pdflatexmk' => [0,0,1],
+      'xelatexmk' => [0,0,5],
+    );
+# If name isn't in canonical set, change it to a good default:
+unless (exists $compilation_defaults{$invoked_name}) { $invoked_name = 'latexmk'; }
+
+#==================
+
+################################################################
+################################################################
 # The following variables are assigned once and then used in symbolic 
 #     references, so we need to avoid warnings 'name used only once':
-use vars qw( $dvi_update_command $ps_update_command $pdf_update_command $out_dir_requested );
+use vars qw( $dvi_update_command $ps_update_command $pdf_update_command
+             $aux_dir_requested $out_dir_requested );
 
 # Translation of signal names to numbers and vv:
 %signo = ();
@@ -239,6 +358,9 @@
 %extra_rule_spec = ();
 
 
+#??????? !!!!!!!!! If @aux_hooks and @latex_file_hooks are still needed,
+# should I incorporate them into the general hook hash???
+#
 # Hooks for customized extra processing on aux files.  The following
 # variable is an array of references to functions.  Each function is
 # invoked in turn when a line of an aux file is processed (if none
@@ -247,7 +369,8 @@
 #    $_ = current line of aux file
 #    $rule = name of rule during the invocation of which, the aux file
 #            was supposed to have been generated.
- at aux_hooks = ();
+our @aux_hooks = ();
+#
 # Hooks for customized processing on lists of source and missing files.
 # The following variable is an array of references to functions.  Each 
 # function is invoked in turn after a run of latex (or pdflatex etc) and
@@ -256,7 +379,15 @@
 #    $rule = name of *latex rule
 #    %dependents: maps source files and possible source files to a status.
 #                 See begining of sub parse_log for possible values.
- at latex_file_hooks = ();
+our @latex_file_hooks = ();
+#
+# Single hash for various stacks of hooks:
+our %hooks = ();
+for ( 'before_xlatex', 'after_xlatex', 'after_xlatex_analysis' ) {
+    $hooks{$_} = [];
+}
+$hooks{aux_hooks} = \@aux_hooks;
+$hooks{latex_file_hooks} = \@latex_file_hooks;
 
 #########################################################################
 ## Default document processing programs, and related settings,
@@ -296,10 +427,14 @@
 # Whether emulate_aux had to be switched on during a run:
 $emulate_aux_switched = 0;
 
-%input_extensions = ();
+#--------------------
+# Specification of extensions/files that need special treatment,
+# e.g., in cleanup or in analyzing missing dependent files. 
+#
 # %input_extensions maps primary_rule_name to pointer to hash of file extensions
 #    used for extensionless files specified in the source file by constructs
 #    like \input{file}  \includegraphics{file}
+%input_extensions = ();
 set_input_ext( 'latex', 'tex', 'eps' );
 set_input_ext( 'pdflatex', 'tex', 'jpg', 'pdf', 'png' );
 $input_extensions{lualatex} = $input_extensions{pdflatex};
@@ -308,14 +443,64 @@
 # i.e., when actual primary rule differs from standard.
 %standard_input_extensions = %input_extensions;
 
+# Possible extensions for main output file of *latex:
 %allowed_output_ext = ( ".dvi" => 1, ".xdv" => 1, ".pdf" => 1 );
-# Extensions of files preserved when clean up is by -c rather than -C:
-%small_cleanup_preserved_exts = ();
-foreach ( 'dvi', 'dviF', 'ps', 'psF', 'pdf', 'synctex', 'synctex.gz', 'xdv' ) {
-    $small_cleanup_preserved_exts{$_} = 1;
-}
 
+# Variables relevant to specifying cleanup.
+# The first set of variables is intended to be user configurable.
+#
+# The @generated_exts array contains list of extensions (without
+# period) for files that are generated by rules run by latexmk.
+#
+# Instead of an extension, an item in the array can be a string containing
+# the placeholder %R for the root of the filenames.  This is used for more
+# general patterns.  Such a pattern may contain wildcards (bsd_glob
+# definitions).
+#
+# By default, it excludes "final output files" that
+# are normally only deleted on a full cleanup, not a small cleanup.
+# These files get two kinds of special treatment:
+#     1.  In clean up, where depending on the kind of clean up, some
+#         or all of these generated files are deleted.
+#         (Note that special treatment is given to aux files.)
+#     2.  In analyzing the results of a run of *LaTeX, to
+#         determine if another run is needed.  With an error free run,
+#         a rerun should be provoked by a change in any source file,
+#         whether a user file or a generated file.  But with a run
+#         that ends in an error, only a change in a user file during
+#         the run (which might correct the error) should provoke a
+#         rerun, but a change in a generated file should not.
+#         Also at the start of a round of processing, only user-file
+#         changes are relevant.
+# Special cases for extensions aux and bbl
+#   aux files beyond the standard one are found by a special analysis
+#   bbl files get special treatment because their deletion is conditional
+#       and because of the possibility of extra bibtex/biber rules with
+#       non-standard basename.
+ at generated_exts = ( 'aux', 'bcf', 'fls', 'idx', 'ind', 'lof', 'lot', 
+                    'out', 'toc',
+                    'blg', 'ilg', 'log',
+                    'xdv'
+                  );
+                  # N.B. 'out' is generated by hyperref package
+$clean_ext = "";        # For backward compatibility: Space separated 
+                        # extensions to be added to @generated_exts after
+                        # startup (and rc file reading).
+# Extensions of files to be deleted by -C, but aren't normally included
+# in the small clean up by -c.  Analogous to @generated_exts and $clean_ext,
+# except that pattern rules (with %R) aren't applied.
+ at final_output_exts = ( 'dvi', 'dviF', 'ps', 'psF', 'pdf',
+                        'synctex', 'synctex.gz' );
+$clean_full_ext = "";
 
+
+# Set of extra specific files to be deleted in small cleanup. These are
+#  ones that get generated under some kinds of error conditions.  All cases:
+#   Relative to current directory, and relative to aux and out directories.
+ at std_small_cleanup_files = ( 'texput.log', "texput.aux", "missfont.log" );
+
+#-------------------------
+
 # Information about options to latex and pdflatex that latexmk will simply
 #   pass through to *latex
 # Option without arg. maps to itself.
@@ -446,9 +631,6 @@
     elsif ( /^([^\s=]+)\s/ ) {
         $allowed_latex_options{$1} = $_;
     }
-    else {
-        $allowed_latex_options{$_} = $_;
-    }
 }
 
 # Arrays of options that will be added to latex and pdflatex.
@@ -589,7 +771,7 @@
 $quote_filenames = 1;       # Quote filenames in external commands
 
 $del_dir = '';        # Directory into which cleaned up files are to be put.
-                      # If $del_dir is '', just delete the files
+                      # If $del_dir is '', just delete the files in a clean up.
 
 @rc_system_files = ();
 
@@ -597,6 +779,7 @@
 
 ################################################################
 ##  Special variables for system-dependent fudges, etc.
+#    ???????? !!!!!!!!!!
 $log_file_binary = 0;   # Whether to treat log file as binary
                         # Normally not, since the log file SHOULD be pure text.
                         # But Miktex 2.7 sometimes puts binary characters
@@ -635,7 +818,7 @@
 
 ## Substitute backslashes in file and directory names for
 ##  MSWin command line
-$MSWin_back_slash = 1;
+$MSWin_back_slash = 0;
 
 ## Separator of elements in search_path.  Default is unix value
 $search_path_separator = ':'; 
@@ -645,44 +828,6 @@
 $tmpdir = ".";
 
 
-# When the aux_dir is on a network share (or the like), its system
-# time may differ from the system time on which latexmk is running.
-# This complicates the tests of whether particular files have been
-# made in a current run of a program or are left over from a previous
-# run.  One test, which is needed under some situations, is that a
-# file was made on a previous run when the files modification time is
-# less than the system time when the program is started.  (See
-# subroutine test_gen_file; this is only needed in a couple of
-# situations.)  The comparison between file and system times must be
-# corrected if there is an offset between system times on the computer
-# running latexmk and the computer hosting the file system containing
-# aux_dir.  The offset is measured in subroutine get_filetime_offset
-# by writing a temporary file; the test only needs to be done once.
-#
-# The following variables are used.  Since the system-independent
-# values of system and file time are only accurate to a second (or 2
-# seconds for FAT file systems), the offset is also accurate only to a
-# second or two.  So thresholds are needed below which differences
-# are insignificant.
-#
-# Note that the making or not making of a file is controlled by the
-# state of the document being compiled and by latexmk's configuration.
-# So a file that is left over from a previous run and not overwritten
-# on the current run will have a file time at least many seconds less
-# than the current time, corresponding to the time scale for a human
-# run-edit-run cycle.
-#
-$filetime_offset_measured = 0;       # Measurement not yet done.
-$filetime_offset = 0;                # Filetime relative to system time.
-$filetime_causality_threshold = 5;   # Threshold for detection of left-over file.
-                                     # Should be non-negative always, and should
-                                     # be bigger than 2 secs if a remote
-                                     # filesystem or network share is used.
-$filetime_offset_report_threshold = 30; # Threshold beyond which filetime offsets
-                                     # are reported; large offsets indicate
-                                     # incorrect system time on at least one system.
-
-
 ################################################################
 
 
@@ -696,7 +841,8 @@
 #   to make latexmk work under MSYS's perl.)
 #
 if ( $^O eq "MSWin32" ) {
-# Pure MSWindows configuration
+    # Pure MSWindows configuration
+
     ## Configuration parameters:
 
     ## Use first existing case for $tmpdir:
@@ -990,12 +1136,6 @@
                         # usually an indication of a problem; further
                         # runs may not resolve the problem, and
                         # instead could cause an infinite loop.
-$clean_ext = "";        # space separated extensions of files that are
-                        # to be deleted when doing cleanup, beyond
-                        # standard set
-$clean_full_ext = "";   # space separated extensions of files that are
-                        # to be deleted when doing cleanup_full, beyond
-                        # standard set and those in $clean_ext
 @cus_dep_list = ();     # Custom dependency list
 @default_files = ( '*.tex' );   # Array of LaTeX files to process when 
                         # no files are specified on the command line.
@@ -1048,6 +1188,9 @@
 $silent = 0;            # Whether fo silence latex's messages (and others)
 $warnings_as_errors = 0;# Treat warnings as errors and exit with non-zero exit code
 $silence_logfile_warnings = 0; # Do list warnings in log file
+                        # The warnings reported are those about undefined refs
+                        # and citations, and the like.
+$max_logfile_warnings = 7; # Max. # number of log file warnings to report
 $rc_report = 1;         # Whether to report on rc files read
 $aux_out_dir_report = 0; # Whether to report on aux_dir & out_dir after
                          # initialization and normalization
@@ -1075,26 +1218,7 @@
                         # of latexmk, the default is to set
                         # $analyze_input_log_always to 1.
 
-# The following two arrays contain lists of extensions (without
-# period) for files that are read in during a *LaTeX run but that
-# are generated automatically from the previous run, as opposed to
-# being user generated files (directly or indirectly from a custom
-# dependency).  These files get two kinds of special treatment:
-#     1.  In clean up, where depending on the kind of clean up, some
-#         or all of these generated files are deleted.
-#         (Note that special treatment is given to aux files.)
-#     2.  In analyzing the results of a run of *LaTeX, to
-#         determine if another run is needed.  With an error free run,
-#         a rerun should be provoked by a change in any source file,
-#         whether a user file or a generated file.  But with a run
-#         that ends in an error, only a change in a user file during
-#         the run (which might correct the error) should provoke a
-#         rerun, but a change in a generated file should not.
-# These arrays can be user-configured.
 
- at generated_exts = ( 'aux', 'bcf', 'fls', 'idx', 'ind', 'lof', 'lot', 
-                    'out', 'toc' );
-     # N.B. 'out' is generated by hyperref package
 
 # Which kinds of file do I have requests to make?
 # If no requests at all are made, then I will make dvi file
@@ -1101,7 +1225,7 @@
 # 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
+$postscript_mode = 0;   # No postscript file requested
 $pdf_mode = 0;          # No pdf file requested to be made by pdflatex
                         # Possible values: 
                         #     0 don't create pdf file
@@ -1132,7 +1256,7 @@
                         # $cleanup_mode = 1: full cleanup 
                         # $cleanup_mode = 2: cleanup except for dvi,
                         #                    dviF, pdf, ps, psF & xdv
-$cleanup_fdb  = 0;      # No removal of file for latexmk's file-database
+$cleanup_fdb  = 0;      # On normal run, 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
@@ -1171,8 +1295,8 @@
 
 # State variables initialized here:
 
-$updated = 0;           # Flags when something has been remade
-                        # Used to allow convenient user message in -pvc mode
+$updated = 0;           # Flags whether something has been remade in this round
+                        # of compilation. 
 $waiting = 0;           # Flags whether we are in loop waiting for an event
                         # Used to avoid unnecessary repeated o/p in wait loop
 
@@ -1435,33 +1559,34 @@
                     #       of specifications of extra generated files (beyond
                     #       the main dest file.  Standard place holders are used.
                     #   1: {Hash sourcefile -> [source-file data] }
-                    # Source-file data array: 
-                    #   0: time
-                    #   1: size
-                    #   2: md5
-                    #   3: name of rule to make this file
-                    #   4: whether the file is of the kind made by epstopdf.sty 
-                    #      during a primary run.  It will have been read during
-                    #      the run, so that even though the file changes during
-                    #      a primary run, there is no need to trigger another 
-                    #      run because of this.
-                    #  Size and md5 correspond to the values at the last run.
-                    #  But time may be updated to correspond to the time
-                    #  for the file, if the file is otherwise unchanged.
-                    #  This saves excessive md5 calculations, which would
-                    #  otherwise be done everytime the file is checked, 
-                    #  in the following situation:
-                    #     When the file has been rewritten after a run
-                    #     has started (commonly aux, bbl files etc),
-                    #     but the actual file contents haven't
-                    #     changed.  Then because the filetime has
-                    #     changed, on every file-change check latexmk
-                    #     would normally redo the md5 calculation to
-                    #     test for actual changes.  Once one such
-                    #     check is done, and the contents are
-                    #     unchanged, later checks are superfluous, and
-                    #     can be avoided by changing the file's time
-                    #     in the source-file list.
+                    #      Source-file data array: 
+                    #        0: time
+                    #        1: size
+                    #        2: md5
+                    #        3: DUMMY.  Not used any more. ?? Lots of code depends
+                    #               on array structure, Let's not change things now.
+                    #        4: whether the file is of the kind made by epstopdf.sty 
+                    #           during a primary run.  It will have been read during
+                    #           the run, so that even though the file changes during
+                    #           a primary run, there is no need to trigger another 
+                    #           run because of this.
+                    #       Size and md5 correspond to the values at the last run.
+                    #       But time may be updated to correspond to the time
+                    #       for the file, if the file is otherwise unchanged.
+                    #       This saves excessive md5 calculations, which would
+                    #       otherwise be done everytime the file is checked, 
+                    #       in the following situation:
+                    #          When the file has been rewritten after a run
+                    #          has started (commonly aux, bbl files etc),
+                    #          but the actual file contents haven't
+                    #          changed.  Then because the filetime has
+                    #          changed, on every file-change check latexmk
+                    #          would normally redo the md5 calculation to
+                    #          test for actual changes.  Once one such
+                    #          check is done, and the contents are
+                    #          unchanged, later checks are superfluous, and
+                    #          can be avoided by changing the file's time
+                    #          in the source-file list.
                     #   2: {Hash generated_file -> 1 }
                     #      This lists all generated files; the values
                     #          are currently unused, only the keys
@@ -1468,25 +1593,35 @@
                     #   3: {Hash source_rule -> last_pass }
                     #      This lists rules that are to be considered source
                     #      rules for the current rule, separately from the 
-                    #      from_rules of the source files. It maps the name
-                    #      of each of these rules to the pass number of the
-                    #      current rule when it was last run. The current rule
-                    #      is out-of-date if the last_pass for a source rule
-                    #      is less than the pass number for the rule.
-                    #      The purpose of this is when the source file list
-                    #      is expected to be inaccurate, because the source
-                    #      files are hard to determine.  Typical needs are
-                    #      for rules applied to dvi and xdv files, when
-                    #      graphics files are involved.  Their names are coded
-                    #      inside the dvi/xdv file, but not the contents.
-                    #      It would need parsing of the contents of the file
-                    #      to determine the actual source files.
-                    #      An implication of using a source_rule is that this
-                    #      rule passes files to the current rule and that the
-                    #      current rule can be considered out-of-date whenever
-                    #      the source_rule has been run.  Effectively these 
-                    #      files are unconditionallyconsidered changed when
-                    #      the source_rule runs.
+                    #      source_rules of the source files. Its main use
+                    #      (the only one at present) is when the list of
+                    #      known source files, at item 1, is/may be
+                    #      incomplete. This is notably the case for rules
+                    #      applied to dvi and xdv files when graphics files
+                    #      are involved. Their names are coded inside the
+                    #      dvi/xdv file, but not the contents. It would
+                    #      need parsing of the contents of the file to
+                    #      determine the actual source files. In the case
+                    #      of rules that process dvi and xdv files, the
+                    #      source_rule is the *latex rule that generates
+                    #      the dvi or xdv file.
+                    #
+                    #      In determining whether a rerun of the current
+                    #      rule is needed at some stage in a round of
+                    #      compilation, the following is added to the
+                    #      basic source-file-change criterion.
+                    #        The value that a source rule in this hash maps
+                    #        to is its pass number when the current rule was
+                    #        last run. The current rule is flagged
+                    #        out-of-date if the saved last_pass for a source
+                    #        rule is less than the current pass number for
+                    #        that source rule (as known to the compilation
+                    #        process). 
+                    #      An implication of using a source_rule in this
+                    #      way is that the source_rule passes files (or
+                    #      other information) to the current rule, and that
+                    #      the current rule is to be rerun whenever the
+                    #      source_rule has been run. 
 
 %fdb_current = ();  # Hash of information for all files used.
                     # It maps filename to a reference to an array
@@ -1494,19 +1629,28 @@
 @nofile = (0,-1,0); # What we use for initializing a new entry in fdb
                     # or flagging non-existent file.
 
-# The following provide information about the structure of the network of rules
-# and files.  They are set by the routine rdb_set_rule_net
-%from_rules = ();        # Used to optimize test for whether a file is generated.
-                         # This maps files to rules that generate them.  (Files
-                         # anywhere in %$PHdest.)
-%from_rules_main = ();   # Used to optimize test for whether a file is generated.
-                         # This maps files to rules that generate them as the 
-                         # MAIN output.  (I.e., file $$Pdest only.)
+# The following are variables which are set by the routine rdb_set_rule_net.
+# They are **derived** from information in %rule_db, and provide information
+# about the structure of the network of rules and files.   This derived
+# information is in a form useful for using the network of rules.
+
+# For recursing backwards through the network of rules:
+%from_rules = ();        # This maps file names to rule names.
+                         # $from_rules{'File'} is the name of the rule that
+                         # generates file 'File'.  If there is no rule to
+                         # generate the file, then $from_rules{'File'} is
+                         # not defined (or possibly the null string '').
+
 # Classification of rules, for determining order of application
-%current_primaries = ();   # Keys are primary rules (latex, etc) that are currently in use.
- at pre_primary = ();         # Array of rules that are thought of as pre-primary
- at post_primary = ();        # Array of rules that are thought of as post-primary
- at unusual_one_time = ();    # Array of rules that are special cases of one-time rules.
+%current_primaries = ();   # Keys are primary rules (latex, etc) that are
+                           # currently in use.
+ at pre_primary = ();         # Array of rules that are thought of as pre-primary,
+                           # Should be in an appropriate order for invoking
+                           # them, to optimize making.
+ at post_primary = ();        # Array of rules that are thought of as post-primary.
+                           # In suitable order for invocation
+ at unusual_one_time = ();    # Array of rules that are special cases of
+                           # one-time rules.
                            # Currently not used.
 
 
@@ -1533,7 +1677,8 @@
 #==================================================
 
 # Which rc files did I read?
- at rc_files_read = ();
+ at rc_files_read = ();  # In order of reading
+%rc_files_read2 = (); # Map **abs** filename to 1; used to check duplicate reads.
 
 # Options that are to be obeyed before rc files are read:
 foreach $_ ( @ARGV )
@@ -1621,8 +1766,8 @@
   elsif (/^-nobibtex$/) { $bibtex_use = 0; }
   elsif (/^-bibtex-cond$/) { $bibtex_use = 1; }
   elsif (/^-bibtex-cond1$/) { $bibtex_use = 1.5; }
-  elsif (/^-c$/)        { $cleanup_mode = 2; $cleanup_fdb = 1; $cleanup_only = 1; }
-  elsif (/^-C$/ || /^-CA$/ ) { $cleanup_mode = 1; $cleanup_fdb = 1; $cleanup_only = 1; }
+  elsif (/^-c$/)        { $cleanup_mode = 2; $cleanup_only = 1; }
+  elsif (/^-C$/ || /^-CA$/ ) { $cleanup_mode = 1; $cleanup_only = 1; }
   elsif (/^-CF$/)    { $cleanup_fdb = 1; }
   elsif (/^-cd$/)    { $do_cd = 1; }
   elsif (/^-cd-$/)   { $do_cd = 0; }
@@ -1646,7 +1791,7 @@
   elsif (/^-g$/)     { $go_mode = 1; }
   elsif (/^-g-$/)    { $go_mode = 0; }
   elsif (/^-gg$/)    { 
-     $go_mode = 2; $cleanup_mode = 1; $cleanup_fdb = 1; $cleanup_only = 0; 
+     $go_mode = 2; $cleanup_mode = 1; $cleanup_only = 0; 
   }
   elsif ( /^-h$/ || /^-help$/ )   { &print_help; exit;}
   elsif (/^-jobname=(.*)$/) {
@@ -1812,7 +1957,7 @@
       $pre_tex_code = $1;
   }
   elsif (/^-v$/ || /^-version$/)   { 
-      print "\n$version_details. Version $version_num\n";
+      print "$version_details\n";
       exit;
   }
   elsif (/^-verbose$/)  { $silent = 0; }
@@ -1839,7 +1984,9 @@
         &exit_help( "No RC file specified after -r switch"); 
      }
      if ( -e $ARGV[0] ) {
-        process_rc_file( $ARGV[0] );
+         # Give process_rc_file a non-zero argument so that there is a warning
+         # if $ARGV[0] has already been processed as an rc file:
+         process_rc_file( $ARGV[0], 1 );
      } 
      else {
         die "$My_name: RC file [$ARGV[0]] does not exist\n"; 
@@ -1907,7 +2054,7 @@
     &exit_help( "Bad options specified" );
 }
 
-warn "$My_name: This is $version_details, version: $version_num.\n",
+print "$My_name: This is $version_details, version: $version_num.\n",
    unless $silent;
 
 if ($out_dir eq '' ){
@@ -1925,17 +2072,6 @@
 $aux_dir_requested = $aux_dir;
 $out_dir_requested = $out_dir;
 
-
-# The following reports results of diagnostics on location of .log file
-#   after the first run of a latex engine, when actually used aux_dir
-#   may not be the expected one, due to a configuration error.
-# Values: -1 uninitialized (before first run)
-#          0 log file not found;
-#          1 log file in aux_dir;
-#          2 log file **not** in aux_dir but in out_dir;
-#          3 log file **not** in aux_dir or out_dir, but in cwd.
-$where_log = -1;  
-
 if ($bibtex_use > 1) {
     push @generated_exts, 'bbl';
 }
@@ -2110,6 +2246,21 @@
     add_option( "--jobname=%R", \$latex, \$lualatex, \$pdflatex, \$xelatex );
 }
 
+# Make sure we make the kind of file we want to view:
+if ($view eq 'dvi') { $dvi_mode = 1; }
+if ($view eq 'ps') { $postscript_mode = 1; }
+if ( ($view eq 'pdf') && ($pdf_mode == 0) ) { 
+    $pdf_mode = 1; 
+}
+
+# Make sure that we make something if all requests are turned off
+unless ( $dvi_mode || $pdf_mode || $postscript_mode || $printout_mode )  {
+    print "No specific requests made, so using default for $invoked_name.\n";
+    ($dvi_mode, $postscript_mode, $pdf_mode)
+        = @{$compilation_defaults{$invoked_name}};    
+}
+
+
 # Which kind of file do we preview?
 if ( $view eq "default" ) {
     # If default viewer requested, use "highest" of dvi, ps and pdf
@@ -2120,19 +2271,6 @@
     if ( $pdf_mode ) { $view = "pdf"; }
 }
 
-# Make sure we make the kind of file we want to view:
-if ($view eq 'dvi') { $dvi_mode = 1; }
-if ($view eq 'ps') { $postscript_mode = 1; }
-if ( ($view eq 'pdf') && ($pdf_mode == 0) ) { 
-    $pdf_mode = 1; 
-}
-
-# Make sure that we make something if all requests are turned off
-if ( ! ( $dvi_mode || $pdf_mode || $postscript_mode || $printout_mode) ) {
-    print "No specific requests made, so default to dvi by latex\n";
-    $dvi_mode = 1;
-}
-
 # Determine requests.
 if ( $banner ) { $postscript_mode = 1; }
 if ( $dvi_mode ) {
@@ -2222,39 +2360,34 @@
     add_option( "$dvips_pdf_switch", \$dvips );
 }
 
-# Restrict variables to allowed values:
-
-if ($filetime_causality_threshold < 0) {
-    warn "$My_name: Correcting negative value of \$filetime_causality_threshold to zero.\n";
-    $filetime_causality_threshold = 0;
-}
-
 # Note sleep has granularity of 1 second.
 # Sleep periods 0 < $sleep_time < 1 give zero delay,
 #    which is probably not what the user intended.
 # Sleep periods less than zero give infinite delay
-if ( $sleep_time < 0 ) {
-     warn "$My_name: Correcting negative sleep_time to 1 sec.\n";
-     $sleep_time = 1;
+if ( $sleep_time == 0 ) {
+     warn "$My_name: sleep_time was configured to zero.\n",
+    "    Do you really want to do this?  It can give 100% CPU usage.\n";
 }
-elsif ( ($sleep_time < 1) && ( $sleep_time != 0 ) ) {
+elsif ( $sleep_time < 1 ) {
      warn "$My_name: Correcting nonzero sleep_time of less than 1 sec to 1 sec.\n";
      $sleep_time = 1;
 }
-elsif ( $sleep_time == 0 ) {
-     warn "$My_name: sleep_time was configured to zero.\n",
-    "    Do you really want to do this?  It will give 100% CPU usage.\n";
-}
 
-# Make convenient forms for lookup.
-# Extensions always have period.
 
-# Convert @generated_exts to a hash for ease of look up and deletion
+# Standardize specifications for generated file extensions:
+#
+# Remove leading and trailing space in the following space-separated lists,
+# and collapse multiple spaces to one,
+# to avoid getting incorrect blank items when they are split.
+foreach ($clean_ext, $clean_full_ext) { s/^\s+//; s/\s+$//; s/\s+/ /g; }
+# Put everything in the arrays:
+push @generated_exts,  split('\s+',$clean_ext);
+push @final_output_exts,  split('\s+',$clean_full_ext);
+
+# Convert the arrays to hashes, for ease of deletion:
 # Keep extension without period!
-%generated_exts_all = ();
-foreach (@generated_exts ) {
-    $generated_exts_all{$_} = 1;
-}
+%generated_exts = ();
+foreach (@generated_exts ) { $generated_exts{$_} = 1; }
 
 $quell_uptodate_msgs = $silent; 
    # Whether to quell informational messages when files are uptodate
@@ -2286,22 +2419,18 @@
 # I will use definedness of $deps_handle as flag for global deps file having
 #   been opened and therefore being available to be written to after
 #   compiling a file.
+
 $deps_handle = undef;
 if ( $dependents_list
      && ! $preview_continuous_mode
      && ( ($cleanup_mode == 0) || ($go_mode == 2) )
    ) {
-    $deps_handle = new FileHandle "> $deps_file";
+    open( $deps_handle, ">$deps_file" );
     if (! $deps_handle ) {
         die "Cannot open '$deps_file' for output of dependency information\n";
     }
 }
 
-# Remove leading and trailing space in the following space-separated lists,
-#   and collapse multiple spaces to one,
-#   to avoid getting incorrect blank items when they are split.
-foreach ($clean_ext, $clean_full_ext) { s/^\s+//; s/\s+$//; s/\s+/ /g; }
-
 # Deal with illegal and problematic characters in filename:
 test_fix_texnames( @file_list );
 
@@ -2318,7 +2447,7 @@
 
     if ( $do_cd ) {
        ($filename, $path) = fileparse( $filename );
-       warn "$My_name: Changing directory to '$path'\n"
+       print "$My_name: Changing directory to '$path'\n"
            if !$silent;
        pushd( dirname_no_tail( $path ) );
     }
@@ -2325,7 +2454,11 @@
     else {
         $path = '';
     }
-    
+
+    # Localize the following, because they may get changed because of
+    # conditions specific to the current tex file, notably:
+    #   Change of emulation state of aux_dir
+    #   Use of $do_cd, which can affect how $aux_dir and $out_dir get normalized.
     local $aux_dir = $aux_dir;
     local $out_dir = $out_dir;
     local $latex = $latex;
@@ -2334,175 +2467,70 @@
     local $xelatex = $xelatex;
 
     &normalize_aux_out_ETC;
-    # Set -output-directory and -aux-directory options for *latex
+    # Set -output-directory and -aux-directory options for *latex here,
+    # since at least: Their method of use depends on the dynamically
+    # set $emulate_aux, and the exact strings for the directory names are
+    # not known until after the call to normalize_aux_out_ETC:
     &set_aux_out_options;
-
-    &set_names;
+    &set_names;   # Names of standard files
     
     # For use under error conditions:
     @default_includes = ($texfile_name, $aux_main);
-    # N.B. Do **not** apply local %rule_db here.  It might appear appropriate,
-    #      but %rule_db is needed in the continue block, which is not in the
-    #      scope of a local declaration here.
+    # Set rules here for current conditions
     &rdb_initialize_rules;
     $view_file = '';
     rdb_one_rule( 'view', sub{ $view_file = $$Psource; } );
 
-    if ( $cleanup_mode > 0 ) {
-        my %other_generated = ();
-        my @index_bibtex_generated = ();
-        my @aux_files = ();
-        my @missing_bib_files = ();
-        my $bibs_all_exist = 0;
-        my %final_output_files = ();
-        foreach (keys %small_cleanup_preserved_exts) {
-            $final_output_files{"$out_dir1$root_filename.$_"} = 1;
-        }
-        $have_fdb = 0;
-        if ( -e $fdb_name ) {
-            print "$My_name: Examining fdb file '$fdb_name' for rules ...\n"
-              if $diagnostics;
-            $have_fdb = ( 0 == rdb_read( $fdb_name ) );
-        }
-        if ( $have_fdb ) {
-            rdb_for_actives(
-                sub {  # Find generated files at rule level
-                    my ($base, $path, $ext) = fileparseA( $$Psource );
-                    $base = $path.$base;
-                    if ( $rule =~ /^makeindex/ ) {
-                        push @index_bibtex_generated, $$Psource, $$Pdest, "$base.ilg";
-                    }
-                    elsif ( $rule =~ /^(bibtex|biber)/ ) {
-                        push @index_bibtex_generated, $$Pdest, "$base.blg";
-                        push @aux_files, $$Psource;
-                        if ( $bibtex_use == 1.5) {
-                            foreach ( keys %$PHsource ) {
-                                if ( ( /\.bib$/ ) && (! -e $_) ) {
-                                    push @missing_bib_files, $_;
-                                }
-                            }
-                        }
-                    }
-                    elsif ( exists $other_generated{$$Psource} ) {
-#                       print "=========== CHECKING: source file of rule '$rule', '$$Psource'\n",
-#                              "  is a generated file.\n";
-                        ## OLD with apparent bug:
-                        #$other_generated{$$Pdest};
-                    }
-                    foreach my $key (keys %$PHdest) {
-                        $other_generated{$key} = 1;
-                    }
-                },
-                sub {  # Find generated files at source file level
-                    if ( $file =~ /\.aux$/ ) { push @aux_files, $file; }
-                }
-            );
-            if ($#missing_bib_files == -1) { $bibs_all_exist = 1; }
-        }
-        elsif ( -e $log_name ) {
-            # No fdb file, but log file exists, so do inferior job by parse_log
-            print "$My_name: Examining log file '$log_name' for generated files...\n"
-              if $diagnostics;
-            # Variables set by parse_log. Can I remove them?
-            local %generated_log = ();
-            local %dependents = ();    # Maps files to status.  Not used here.
-            local @bbl_files = ();     # Not used here.
-            local %idx_files = ();     # Maps idx_file to (ind_file, base). Not used here.
-            local %conversions = ();   # *latex-performed conversions.  Not used here.
-                         # Maps output file created and read by *latex
-                         #    to source file of conversion.
-            local $primary_out = '';   # Actual output file (dvi or pdf). Not used here.
-            local $fls_file_analyzed = 0;
-            &parse_log;
-            %other_generated = %generated_log;
-        }
-        else {
-            print "$My_name: No fdb or log file, so clean up default set of files ...\n"
-              if $diagnostics;
-        }
-        
-        if ( ($go_mode == 2) && !$silent ) {
-            warn "$My_name: Removing all generated files\n" unless $silent;
-        }
-        my $keep_bbl = 1;
-        if ( ($bibtex_use > 1.6)
-             ||
-             (  ($bibtex_use == 1.5) && ($bibs_all_exist) )
-           ) {
-               $keep_bbl = 0;
-        }
-        if ($keep_bbl) {
-            delete $generated_exts_all{'bbl'}; 
-        }
-        # Convert two arrays to hashes:
-        my %index_bibtex_generated = ();
-        my %aux_files = ();
-        my %aux_files_to_save = ();
-        foreach (@index_bibtex_generated) {
-            $index_bibtex_generated{$_} = 1
-               unless ( /\.bbl$/ && ($keep_bbl) );
-            delete( $other_generated{$_} );
-        }
-        foreach (@aux_files) {
-            if (exists $other_generated{$_} ) {
-                $aux_files{$_} = 1;
-            }
-            else {
-                $aux_files_to_save{$_} = 1;
-            }
-        }
+    if ( $diagnostics ) {
+       print "$My_name: Rules after start up for '$texfile_name'\n";
+       rdb_show();
+    }
 
-        foreach (keys %final_output_files) { delete $other_generated{$_}; }
-        
-        if ($diagnostics) {
-            show_array( "For deletion, the following were determined from fdb file or log file:\n"
-                       ." Generated (from makeindex and bibtex):", 
-                        keys %index_bibtex_generated );
-            show_array( " Aux files:", keys %aux_files );
-            show_array( " Other generated files:\n"
-                       ." (only deleted if \$cleanup_includes_generated is set): ",
-                        keys %other_generated );
-            show_array( " Yet other generated files are specified by patterns:\n".
-                        " Explicit pattern with %R or root-filename.extension:",
-                        keys %generated_exts_all );
-            show_array( " Aux files to SAVE and not delete:", keys %aux_files_to_save );
-        }
+    if ($cleanup_fdb) {
+        print "$My_name: Deleting '$fdb_name' (file of cached information)\n";
+        unlink_or_move( $fdb_name );
+    }
 
-        my @clean_args = ( 'blg', 'ilg', 'log', 'aux.bak', 'idx.bak',
-                   split('\s+',$clean_ext), keys %generated_exts_all );
-        cleanup1( $aux_dir1, @clean_args );
-        if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @clean_args ); }
-        if ( $cleanup_mode == 1 ) {
-            my @clean_args = ( keys %small_cleanup_preserved_exts, split('\s+', $clean_full_ext) );
-            cleanup1( $aux_dir1, @clean_args );
-            if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @clean_args ); }
+    # Set rules from fdb_latexmk file, if possible.
+    # Allow adaptation of output extension for primary rule to cached
+    # value, but not if we are doing a cleanup (since then the rules
+    # will all be reset after the cleanup).
+    if ( -e $fdb_name ) {
+        if (0 != rdb_read( $fdb_name, $cleanup_mode ) ) {
+            # There were some problems with the file of cached rules, so
+            # the  resulting set of rules may be problematic: file status
+            # data may be incorrect.
+            # So use filetime criterion for make instead of file change from
+            # previous run, until we have done our own make.
+            rdb_recurse( [keys %possible_primaries],
+                      sub{ if ( $$Ptest_kind == 1 ) { $$Ptest_kind = 3;} }
+            );
         }
-        unlink_or_move( 'texput.log', "texput.aux", "missfont.log",
-                keys %index_bibtex_generated, 
-                        keys %aux_files );
-        if ($cleanup_includes_generated) {
-            unlink_or_move( keys %other_generated );
-        }
-        if ( $cleanup_includes_cusdep_generated) {
-            &cleanup_cusdep_generated;
-        }
     }
-    if ($cleanup_fdb) {
-       unlink_or_move( $fdb_name );
-       # If the fdb file exists, it will have been read, and therefore changed
-       #   rule database.  But deleting the fdb file implies we also want
-       #   a virgin rule database, so we must reset it:
-       &rdb_initialize_rules;
+    elsif ( -e $log_name ) {
+        # At least we can use dependency information from previous run of
+        # *latex, which may not have been under latexmk control, otherwise
+        # the fdb_latexmk file would have been made.
+        rdb_for_some( [keys %current_primaries],
+                      sub{ rdb_set_latex_deps($cleanup_mode) }
+                    );
+        &rdb_set_rule_net;
     }
+    # At this point, the file and rule databases are correctly initialized
+    # either from the fdb_latexmk database (corresponding to the state at
+    # the end of the previous run of latexmk), or from default initialization,
+    # assisted by dependency information from log files about previous
+    # run, if the log file exists.
+    # PERHAPS if fdb_latexmk doesn't exist but appropriate output files exist,
+    #   we could assume there was a previous run that completed.  Then new
+    #   run of *latex etc isn't needed until files are changed; then we
+    #   should set the file data from the on-disk state.
+
+    if ( $cleanup_mode ) { &do_small_cleanup; }
+    if ( $cleanup_mode == 1 ) { &do_extra_cleanup; }
     if ($cleanup_only) { next FILE; }
 
-    if ( $diagnostics ) {
-       print "$My_name: Rules after start up for '$texfile_name'\n";
-       rdb_show();
-    }
-
-    $have_fdb = 0;
-    if (! -e $aux_main ) {
+    if ( ! -e $aux_main ) {
         # No aux file => set up trivial aux file 
         #    and corresponding fdb_file.  Arrange them to provoke one run 
         #    as minimum, but no more if actual aux file is trivial.
@@ -2515,29 +2543,8 @@
         &set_trivial_aux_fdb;
     }
 
-    if ( -e $fdb_name ) {
-        $rdb_errors = rdb_read( $fdb_name );
-        $have_fdb = ($rdb_errors == 0);
-    }
-    if (!$have_fdb) { 
-        # We didn't get a valid set of data on files used in
-        # previous run.  So use filetime criterion for make
-        # instead of change from previous run, until we have
-        # done our own make.
-        rdb_recurse( [keys %possible_primaries],
-                      sub{ if ( $$Ptest_kind == 1 ) { $$Ptest_kind = 3;} }
-        );
-        if ( -e $log_name ) {
-            rdb_for_some( [keys %current_primaries], \&rdb_set_latex_deps );
-        }
-    }
-    # At this point, we assume that the file database was correctly
-    # initialized from fdb_latexmk database (corresponding to the state at
-    # the end of the previous run of latexmk, if the fdb_latexmk file exists.
-    # PERHAPS if fdb_latexmk doesn't exist we ought to assume there was
-    # a previous run that completed, if the appropriate output files exist,
-    # so a new run of *latex etc isn't needed; then we should set the file
-    # data from the on-disk state.
+
+
     if ($go_mode) {
         # Force everything to be remade.
         rdb_recurse( [ &rdb_target_array], sub{$$Pout_of_date=1;}  );
@@ -2621,14 +2628,6 @@
 
 if ($show_time) { show_timing();}
 
-sub show_timing {
-    my $processing_time = processing_time() - $processing_time1;
-    print @timings, "Accumulated processing time = $processing_time\n";
-    print "Number of rules run = ", 1+$#timings, "\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
@@ -2641,34 +2640,41 @@
         # Error occured, but multiple files were processed, so
         #     user may not have seen all the error messages
         warn "\n------------\n";
-        show_array( 
+        warn_array( 
            "$My_name: Some operations failed, for the following tex file(s)", 
            @failed_primaries);
     }
     if ( !$force_mode ) {
-      warn "$My_name: Use the -f option to force complete processing,\n",
-           " unless error was exceeding maximum runs, or warnings treated as errors.\n";
+        warn
+            "$My_name: If appropriate, the -f option can be used to get latexmk\n",
+            "  to try to force complete processing.\n";
     }
     exit 12;
 }
 
-if ( $where_log == 2 ) {
-    warn "$My_name: You requested aux_dir '$aux_dir_requested',\n",
-         "  but '$out_dir' was used for the .log file etc, and I couldn't\n",
-         "  correct the problem, even by setting emulation of aux_dir on.\n",
-         "  There is a strong suspicion of a bug in $my_name or a configuration error.\n";
-}
 if ( $emulate_aux_switched ) {
-    warn "$My_name: I had to switch -aux-directory on after it was initially off,\n",
-         "  because your *latex program appeared not to support it. You probably\n",
-         "  should either use the option -emulate-aux-dir, or in a latexmkrc file\n",
-         "  set \$emulate_aux = 1;\n";
+    warn "$My_name: I had to switch emulate-aux-dir on after it was initially off,\n",
+         "  because your *latex program appeared not to support -aux-directory. You\n",
+         "  probably should either use the option -emulate-aux-dir, or in a\n",
+         "  latexmkrc file set \$emulate_aux = 1;\n";
 }
 
 # end MAIN PROGRAM
+
 #############################################################
 #############################################################
 
+sub show_timing {
+    my $processing_time = processing_time() - $processing_time1;
+    print @timings, "Accumulated processing time = ",
+          sprintf('%.2f', $processing_time), "\n";
+    print "Number of rules run = ", 1+$#timings, "\n";
+    @timings = (); 
+    $processing_time1 = processing_time();
+}
+
+#############################################################
+
 sub set_tex_cmds {
     # Usage, e.g., set_tex_cmds( '%O %S' )
     my $args = $_[0];
@@ -2725,9 +2731,9 @@
             $unbalanced_quote++;
         }
         elsif ( $count_q > 0 ) {
-            warn "$My_name: Removed (balanced quotes) from filename '$_',\n";
+            print "$My_name: Removed (balanced quotes) from filename '$_',\n";
             s/\"//g;
-            warn "   and obtained '$_'.\n";
+            print "   and obtained '$_'.\n";
             $balanced_quote++;
         }
     }
@@ -2777,7 +2783,7 @@
     # 4. Set some TeX-related environment variables.
     # 5. Ensure the aux and out directories exist
 
-    # Ensure the output/auxiliary directories exist, if need be
+    # Ensure the output/auxiliary directories exist, if need be, **with error checking**.
     my $ret1 = 0;
     my $ret2 = 0;
     eval {
@@ -2847,9 +2853,9 @@
     }
     
     if ($diagnostics || $aux_out_dir_report ) {
-        warn "$My_name: Cwd: '", good_cwd(), "'\n";
-        warn "$My_name: Normalized aux dir and out dir: '$aux_dir', '$out_dir'\n";
-        warn "$My_name: and combining forms: '$aux_dir1', '$out_dir1'\n";
+        print "$My_name: Cwd: '", good_cwd(), "'\n";
+        print "$My_name: Normalized aux dir and out dir: '$aux_dir', '$out_dir'\n";
+        print "$My_name: and combining forms: '$aux_dir1', '$out_dir1'\n";
     }
 
 }  #END normalize_aux_out_ETC
@@ -3070,56 +3076,86 @@
 #************************************************************
 
 sub rdb_set_rule_net {
-    # Set network of rules, including links
-    &rdb_make_links;
+    # Set network of rules, including links and classifications.
+    #
+    # ?? Problem if there are multiple rules for getting a file.  Notably pdf.
+    #    Which one to choose?
+    # ?? Problem: what if a rule is inactive,
+    #    e.g., bibtex because biber is in use,
+    #          or xelatex when pdflatex is in use
+    #          or bibtex when $bibtex_use is 0.
+    #    What if both latex and pdflatex are being used?
+    #      That has been allowed.  But .aux file (also
+    #      .log file) are made by both.
+
+    #  Other case: package (like bibtopic) creates bbl or other file when
+    #  it doesn't exist.  Later a rule is created by latexmk to make that
+    #  file.  Then the rule's main destination file should have priority
+    #  over non-main generated files from other rules.
+    local %from_rules_old = %from_rules;
+    %from_rules = ();     # File to rule.
+    rdb_for_actives( \&set_file_links_for_rule );
+    rdb_for_actives( \&rdb_set_source_rules );
     &rdb_classify_rules;
+    #    print "=========In rdb_make_links: rules\n"; &rdb_show;
 }
 
-#************************************************************
+#------------
 
-sub rdb_make_links {
-# ?? Problem if there are multiple rules for getting a file.  Notably pdf.
-#    Which one to choose?
-# ?? Problem: what if a rule is inactive,
-#    e.g., bibtex because biber is in use,
-#          or xelatex when pdflatex is in use
-#          or bibtex when $bibtex_use is 0.
-#    What if both latex and pdflatex are being used?
-#      That has been allowed.  But .aux file (also
-#      .log file) are made by both.
-
-#  Other case: package (like bibtopic) creates bbl or other file when
-#  it doesn't exist.  Later a rule is created by latexmk to make that
-#  file.  Then the rule's main destination file should have priority
-#  over non-main generated files from other rules.
-    local %from_rules_old = %from_rules;
-    &rdb_cache_generated;
-    
-    rdb_for_actives( 
-        0,
-        sub{ 
-            if ( exists $from_rules_main{$file} ) {
-                $$Pfrom_rule = $from_rules_main{$file};
+sub set_file_links_for_rule {
+    foreach my $dest ( @$PA_extra_gen, keys %$PHdest ) {
+        if ( exists $from_rules{$dest} ) {
+            my $old_rule = $from_rules{$dest};
+            if ( $old_rule eq $rule ) {
+                # OK
             }
-            elsif ( exists $from_rules{$file} ) {
-                $$Pfrom_rule = $from_rules{$file};
+            elsif ( exists($possible_primaries{$old_rule})
+                    && exists($possible_primaries{$rule}) ) {
+                # This could be problematic.  But we'll let it go,
+                # because it is a common case for .aux and .log files
+                # (etc), and these cases do not appear to mess up
+                # anything (by experience).
+                # Once we allow an active flag for rules and only
+                # examine active rules, the only case of this that
+                # will appear (in the absence of other problems) will
+                # be where two primary rules are active, notably a
+                # latex rule to make dvi and a pdflatex (or other
+                # rule) to make pdf.
             }
-            if ( $$Pfrom_rule && (! rdb_rule_exists( $$Pfrom_rule ) ) ) {
-                $$Pfrom_rule = '';
+            else {
+                warn "$My_name: Possible bug:\n",
+                 "  In linking rules I already set source_rules{$dest} to '$old_rule'\n",
+                 "  But now I want to set it to '$rule'\n";
             }
         }
-        );
-    rdb_for_actives( \&rdb_set_source_rules );
-#    print "=========In rdb_make_links: rules\n"; &rdb_show;
-} # END rdb_make_links
+        $from_rules{$dest} = $rule;
+    }
+} # END set_file_links_for_rule
+   
+#------------
 
-#************************************************************
-
 sub rdb_set_source_rules {
-    # This applies to rules whose source file is a dvi or xdv file
-    # Uses rule context
+    # This assumes rule context, and sets explicit source rules in the hash
+    # %$PHsource_rules.  These are to be rules on which the current rule
+    # depends, but that aren't determined by using the known set of source
+    # files of the current rule together with the known sets of destination
+    # files for other rules.
+    #
+    # The standard case, and the only one used at the moment is for rules
+    # whose **main** source file is a dvi or xdv file.  These programs used
+    # by these rules (dvips etc) do not provide easily accessible
+    # information on the set of graphics files that they read in.
+    # So such rules are given a source rule that is the *latex that
+    # generates them.
+    #
+    # These cases need special treatment coded here and in the algorithms
+    # in rdb_make etc.
+    #
     my ($base, $path, $ext) = fileparseA( $$Psource );
     if ( ($ext eq '.dvi') || ($ext eq '.dviF') || ($ext eq '.xdv') ) {
+        # Rules that use .dvi, .dviF, .xdv don't get all dependencies,
+        # notably about included graphics files.
+        # So use a pass criterion instead.
         my $old_rule = $from_rules_old{$$Psource};
         my $new_rule = $from_rules{$$Psource};
         if ( defined $old_rule
@@ -3134,81 +3170,104 @@
             if ( defined $new_rule ) { $$PHsource_rules{$new_rule} = 0; }
         }
     }
-}
+} # END rdb_set_source_rules
 
-#************************************************************
+#------------
 
-sub rdb_cache_generated {
-    # Update %from_rules
-    %from_rules = ();
-    %from_rules_main = ();
-    rdb_for_actives( \&one_from_main_rule_cache );
-    rdb_for_actives( \&one_from_rule_cache );
-} # END rdb_cache_generated
+sub rdb_classify_rules {
+    # Usage: &rdb_classify_rules
+    # Assume the following variables are available (global or local):
+    # Input:
+    #    %target_rules    # Set to target rules
+    #    %target_files    # Set to target files
+    #    %possible_primaries
+    
+    # Output:
+    #    %current_primaries    # Keys are actual primaries
+    #    @pre_primary          # Array of rules
+    #    @post_primary         # Array of rules
+    #    @unusual_one_time     # Array of rules
+    # @pre_primary and @post_primary are in natural order of application.
 
-#------------
+    local @requested_targets = &rdb_target_array;
+    local $state = 0;       # Post-primary
+    local @classify_stack = ();
 
-sub one_from_main_rule_cache {
-    # Rule context assumed.
-    # Set from_rules_main items for one rule
-    if (! $$Pdest) { return; }
-# Error message trigger:    if ( $$Pdest =~ /pdf$/) { $from_rules_main{$$Pdest} = 'pdflatexA'; }
-    if ( exists $from_rules_main{$$Pdest} ) {
-        my $old_rule = $from_rules_main{$$Pdest};
-        if ( $old_rule eq $rule ) {
-            # OK
-        }
-        else {
-            warn "$My_name: Possible bug:\n",
-                 "  In linking rules I already set from_rules_main{$$Pdest} to '$old_rule'\n",
-                 "  But now I want to set it to '$rule'\n";
-#            traceback( "================================\nFrom one_from_main_rule_cache" );
-        }
+    %current_primaries = ();
+    @pre_primary = ();
+    @post_primary = ();
+    @unusual_one_time = ();
+
+    rdb_recurse( \@requested_targets, \&rdb_classify1, 0,0, \&rdb_classify2 );
+
+    # Reverse, as tendency is to find last rules first.
+    @pre_primary = reverse @pre_primary;
+    @post_primary = reverse @post_primary;
+
+    my @current_primaries = keys %current_primaries;
+    if ($#current_primaries < 0) {
+        die "$My_name: No active primary rules found.  I have to stop.\n";
     }
-    $from_rules_main{$$Pdest} = $rule;
-} # END one_from_main_rule_cache
+    elsif ($#current_primaries > 0) {
+        die "$My_name: More than one active primary rule found.  I have to stop.\n",
+            "  Primary rules: @current_primaries\n";
+    }
+    $current_primary = $current_primaries[0];
 
-#------------
+    if ($diagnostics) {
+        print "Rule classification: \n";
+        show_array( "  Requested rules:",  @requested_targets );
+        show_array( "  Pre-primaries:", @pre_primary );
+        show_array( "  Primaries:", keys %current_primaries );
+        show_array( "  Post-primaries:", @post_primary );
+        show_array( "  Inner-level one_time rules:", @unusual_one_time );
+        show_array( "  Outer-level one_time rules:", keys %one_time );
+    } #end diagnostics
 
-sub one_from_rule_cache {
-    # Rule context assumed.
-    # Set from_rules items for one rule
-    foreach (  @$PA_extra_gen, keys %$PHdest ) {
-        # Error message trigger:  if ( $_ =~ /aux$/) { $from_rules{$_} = 'pdflatexA'; }
-        if ( exists $from_rules{$_} ) {
-            my $old_rule = $from_rules{$_};
-            if ( $old_rule eq $rule ) {
-                # OK
-            }
-            elsif ( exists $from_rules_main{$_} && ( $from_rules_main{$_} ne $rule ) ) {
-                warn "$My_name: Possible bug:\n",
-                     "  In linking rules, I already set from_rules_main{$_}\n".
-                     "  to '$from_rules_main{$_}'\n",
-                     "  But now I also have a different rule '$rule' that also made the file.\n";
-            }
-            elsif ( exists($possible_primaries{$old_rule}) && exists($possible_primaries{$rule}) ) {
-                # This could be problematic.  But we'll let it go,
-                # because it is a common case for .aux and .log files
-                # (etc), and these cases do not appear to mess up
-                # anything (by experience).
-                # Once we allow an active flag for rules and only
-                # examine active rules, the only case of this that
-                # will appear (in the absence of other problems) will
-                # be where two primary rules are active, notably a
-                # latex rule to make dvi and a pdflatex (or other
-                # rule) to make pdf.
-            }
-            else {
-                warn "$My_name: Possible bug:\n",
-                     "  In linking rules I already set from_rules{$_} to '$old_rule'\n",
-                     "  But now I want to set it to '$rule'\n";
-#            traceback( "================================\nFrom one_from__rule_cache" );
-            }
+} #END rdb_classify_rules
+
+#-------------------
+
+sub rdb_classify1 {
+    # Helper routine for rdb_classify_rules
+    # Applied as rule_act1 in recursion over rules
+    # Assumes rule context, and local variables from rdb_classify_rules
+    push @classify_stack, [$state];
+    if ( exists $possible_one_time{$rule} ) {
+        # Normally, we will have already extracted the one_time rules,
+        # and they will never be accessed here.  But just in case of
+        # problems or generalizations, we will cover all possibilities:
+        if ($depth > 1) {
+           warn "ONE TIME rule not at outer level '$rule'\n";
         }
-        $from_rules{$_} = $rule;
+        push @unusual_one_time, $rule;
     }
-} #END from_rule_cache
+    elsif ($state == 0) {
+       if ( exists $possible_primaries{$rule} ) {
+           $state = 1;   # In primary rule
+           $current_primaries{ $rule } = 1;
+       }
+       else {
+           push @post_primary, $rule;
+       }
+    }
+    else {
+        $state = 2;     # in post-primary rule
+        push @pre_primary, $rule;
+    }
+} #END rdb_classify1
 
+#-------------------
+
+sub rdb_classify2 {
+    # Helper routine for rdb_classify_rules
+    # Applied as rule_act2 in recursion over rules
+    # Assumes rule context
+    ($state) = @{ pop @classify_stack };
+} #END rdb_classify2
+
+#================================
+
 #************************************************************
 
 sub set_trivial_aux_fdb {
@@ -3222,14 +3281,13 @@
     # 2. Write a corresponding fdb file
     # 3. Provoke a run of *latex (actually of all primaries). 
 
-    local *aux_file;
-    open( aux_file, '>', $aux_main )
+    open( my $aux_file, '>', $aux_main )
         or die "Cannot write file '$aux_main'\n";
-    print aux_file "\\relax \n";
+    fprint8 $aux_file, "\\relax \n";
     # The following is added by recent versions of latex for a
     # one page document
-    print aux_file "\\gdef \\\@abspage\@last{1}\n";
-    close(aux_file);
+    fprint8 $aux_file, "\\gdef \\\@abspage\@last{1}\n";
+    close($aux_file);
 
     foreach my $rule (keys %possible_primaries ) { 
         rdb_ensure_file( $rule, $texfile_name );
@@ -3246,6 +3304,148 @@
 #************************************************************
 #************************************************************
 
+sub do_extra_cleanup {
+    print "$My_name: Doing extra clean up (of final output files) for '$texfile_name'\n"
+        if ! $silent;
+    cleanup1( $aux_dir1, @final_output_exts );
+    if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @final_output_exts ); }
+}  # END do_extra_cleanup
+
+#************************************************************
+
+sub do_small_cleanup {
+    # Assume dependency information from previous run has been obtained. 
+    my %other_generated = ();
+    my %cusdep_generated = ();
+    my @index_bibtex_generated = ();
+    my @aux_files = ();
+    my @missing_bib_files = ();
+    my $bibs_all_exist = 0;
+    my %final_output_files = ();
+    print "$My_name: Doing main (small) clean up for '$texfile_name'\n"
+        if ! $silent;
+
+    foreach (@final_output_exts) {
+        $final_output_files{"$out_dir1$root_filename.$_"} = 1;
+    }
+    rdb_for_actives(
+        sub {  # Find generated files at rule level
+               my ($base, $path, $ext) = fileparseA( $$Psource );
+               $base = $path.$base;
+               if ( $rule =~ /^makeindex/ ) {
+                   push @index_bibtex_generated, $$Psource, $$Pdest, "$base.ilg";
+               }
+               elsif ( $rule =~ /^(bibtex|biber)/ ) {
+                   push @index_bibtex_generated, $$Pdest, "$base.blg";
+                   push @aux_files, $$Psource;
+                   if ( $bibtex_use == 1.5) {
+                       foreach ( keys %$PHsource ) {
+                           if ( ( /\.bib$/ ) && (! -e $_) ) {
+                               push @missing_bib_files, $_;
+                           }
+                       }
+                   }
+               }
+               elsif ( $rule =~ /^(latex|lualtex|pdflatex|xelatex)/ ) {
+                   foreach my $key (keys %$PHdest) {
+                       $other_generated{$key} = 1;
+                   }
+               }
+               elsif ( ($rule =~ /^cusdep/) && (-e $$Psource) ) {
+                   # N.B. Deleting cusdep generated files is wrong if source file doesn't exist.
+                   #  But that will be taken care of in the rule-network setup.
+                   #  So just have a test for safety in the elsif line, without diagnostics.
+                   foreach my $key (keys %$PHdest) {
+                       $cusdep_generated{$key} = 1;
+                   }
+               }
+            },
+            sub {  # Find generated files at source file level
+               if ( $file =~ /\.aux$/ ) { push @aux_files, $file; }
+            }
+    );
+    if ($#missing_bib_files == -1) { $bibs_all_exist = 1; }
+    
+    my $keep_bbl = 1;
+    if ( ($bibtex_use > 1.6)
+         ||
+         (  ($bibtex_use == 1.5) && ($bibs_all_exist) )
+       ) {
+           $keep_bbl = 0;
+    }
+    if ($keep_bbl) {
+        delete $generated_exts{'bbl'}; 
+    }
+    # Convert some arrays to hashes, since deletions are easier to handle:
+    my %index_bibtex_generated = ();
+    my %aux_files = ();
+    my %aux_files_to_save = ();
+    foreach (@index_bibtex_generated) {
+        $index_bibtex_generated{$_} = 1
+           unless ( /\.bbl$/ && ($keep_bbl) );
+        delete( $other_generated{$_} );
+    }
+    foreach (@aux_files) {
+        if (exists $other_generated{$_} ) {
+            $aux_files{$_} = 1;
+        }
+        else {
+            $aux_files_to_save{$_} = 1;
+        }
+    }
+
+    foreach (keys %final_output_files) { delete $other_generated{$_}; }
+
+    if ($diagnostics) {
+        print "For deletion, files are as follows. Lists are non-exclusive.\n";
+        show_array( " Files specified by patterns\n"
+                    ." (explicit pattern with %R or root-filename.extension):",
+                    sort keys %generated_exts );
+        show_array( " Files determined from fdb file or log file that were generated by makeindex\n"
+                    ." or bibtex:", 
+                    sort keys %index_bibtex_generated );
+        show_array( " Aux files (from analysis of rules):", keys %aux_files );
+        show_array( " Aux files to SAVE and not delete:", keys %aux_files_to_save );
+        show_array( " Other non-cusdep generated files from *latex:\n"
+                    ." (only deleted if \$cleanup_includes_generated is set and file\n"
+                    ." doesn't appear in another list):",
+                    sort keys %other_generated );
+        show_array( " Cusdep generated files:\n"
+                   ." (only deleted if \$cleanup_includes_cusdep_generated is set and file\n"
+                    ." doesn't appear in another list):",
+                    sort keys %cusdep_generated );
+    }
+
+    my @clean_args = keys %generated_exts;
+    cleanup1( $aux_dir1, @clean_args );
+    if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @clean_args ); }
+
+    my @specific_deletions = @std_small_cleanup_files;
+    foreach my $file (@std_small_cleanup_files) {
+        foreach my $dir ($aux_dir1, $out_dir1 ) {
+            if ($dir) { push @specific_deletions, "$dir$file"; }
+        }
+    }
+    unlink_or_move( @specific_deletions,
+                    keys %index_bibtex_generated, 
+                    keys %aux_files );
+
+    if ($cleanup_includes_generated) {
+        unlink_or_move( keys %other_generated );
+    }
+    if ( $cleanup_includes_cusdep_generated) {
+        unlink_or_move( keys %cusdep_generated );
+    }
+    unlink_or_move( $fdb_name );
+    # If the fdb file (or log, fls and/or aux files), it/they will have been
+    #   used to make a changed rule database.  But a cleanup implies that we
+    #   need a virgin rule database, corresponding to current state of files,
+    #   so we reset the rule database and net:
+    &rdb_initialize_rules;
+}  # END do_small_cleanup
+
+#************************************************************
+
 sub do_cusdep {
     # Unconditional application of custom-dependency
     # except that rule is not applied if the source file source 
@@ -3259,7 +3459,7 @@
         # Source does not exist.  Users of this rule will need to turn
         # it off when custom dependencies are reset
         if ( !$silent ) {
-            warn "$My_name: In trying to apply custom-dependency rule\n",
+            print "$My_name: In trying to apply custom-dependency rule\n",
             "  to make '$$Pdest' from '$$Psource'\n",
             "  the source file has disappeared since the last run\n";
         }
@@ -3308,7 +3508,7 @@
     if ( &view_file_via_temporary ) {
         if ( $$Pext_cmd =~ /%D/ ) {
             my $tmpfile = tempfile1( "${root_filename}_tmp", $ext );
-            warn "$My_name: Making '$$Pdest' via temporary '$tmpfile'...\n";
+            print "$My_name: Making '$$Pdest' via temporary '$tmpfile'...\n";
             $return = &Run_subst( undef, undef, undef, undef, $tmpfile );
             move( $tmpfile, $$Pdest );
         }
@@ -3352,12 +3552,12 @@
         if ($$Pviewer_process == 0) {
             print "$My_name: need to signal viewer for file '$$Psource', but didn't get \n",
                   "   process ID for some reason, e.g., no viewer, bad configuration, bug\n"
-                if $diagnostics ;             
+                if $diagnostics;             
         }
         elsif ( defined $viewer_update_signal) {
             print "$My_name: signalling viewer, process ID $$Pviewer_process ",
                   "with signal $viewer_update_signal\n"
-                if $diagnostics ;
+                if $diagnostics;
             kill $viewer_update_signal, $$Pviewer_process;
         }
         else {
@@ -3415,9 +3615,9 @@
     # Treatment of extensions (in TeXLive 2019), with omission of path search:
     # Exists: always means exists as a file, i.e., not as a directory.
     #  A. Finding of tex file:
-    #   1. If extension is .tex and given_name.tex exists, use it.
+    #   1. If extension is .tex and given_name exists, use it.
     #   2. Else if given_name.tex exists, use it.
-    #   3. Else if givne_name exists, use it.
+    #   3. Else if given_name exists, use it.
     # B. The base filename is obtained by deleting the path
     #    component and the extension.
     # C. The names of generated files (log, aux) are obtained by appending
@@ -3448,7 +3648,7 @@
     elsif ( ($ext eq '.tex') && find_cus_dep( $given_name, $source_name ) ) {
        $tex_name = $given_name;
     }
-    elsif ( find_cus_dep( "$given_name.tex", \$source_name ) ) {
+    elsif ( find_cus_dep( "$given_name.tex", $source_name ) ) {
        $tex_name = "$given_name.tex";
        $base_name .= $ext;
     }
@@ -3470,7 +3670,9 @@
     $_[2] = $tex_name;
 
     if ($diagnostics) {
-       print "Given='$given_name', tex='$tex_name', base='$base_name', ext= $ext, source='$source_name'\n";
+        print "Given='$given_name', tex='$tex_name', base='$base_name', ext= $ext";
+        if ($source_name) { print ",  source='$source_name'"; }
+        print "\n";
     }
     return $fail;
 
@@ -3496,10 +3698,10 @@
     $quell_uptodate_msgs = 1;
 
     if ( ($view eq 'dvi') || ($view eq 'pdf') || ($view eq 'ps') ) { 
-        warn "Viewing $view\n";
+        print "Viewing $view\n";
     }
     elsif ( $view eq 'none' ) {
-        warn "Not using a previewer\n";
+        print "Not using a previewer\n";
         $view_file = '';
     }
     else {
@@ -3528,7 +3730,7 @@
         #    (We'll save starting up another viewer.)
         $$Pviewer_process = &find_process_id( $view_file );
         if ( $$Pviewer_process ) {
-            warn "$My_name: Previewer is already running\n" 
+            print "$My_name: Previewer is already running\n" 
               if !$silent;
             $viewer_running = 1;
             $$Pneed_to_get_viewer_process = 0;
@@ -3574,11 +3776,11 @@
             # Start the viewer
             if ( !$silent ) {
                 if ($new_viewer_always) {
-                    warn "$My_name: starting previewer for '$view_file'\n",
+                    print "$My_name: starting previewer for '$view_file'\n",
                          "------------\n";
                 }
                 else {
-                    warn "$My_name: I have not found a previewer that ",
+                    print "$My_name: I have not found a previewer that ",
                          "is already running. \n",
                          "   So I will start it for '$view_file'\n",
                          "------------\n";
@@ -3611,7 +3813,6 @@
 
             # So set the GENERATED files from *latex as up-to-date:
             rdb_for_some( [keys %current_primaries], \&rdb_update_gen_files );
-
             # And don't watch for changes for post_primary rules (ps and pdf 
             # from dvi, etc haven't been run after an error in *latex, so
             # are out-of-date by filetime criterion, but they should not be run
@@ -3640,8 +3841,7 @@
         if ($rules_list) { rdb_list(); }
         if ($show_time && ! $first_time) { show_timing(); }
         if ( $dependents_list && ($updated || $failure) ) {
-           my $deps_handle = new FileHandle "> $deps_file";
-           if ( defined $deps_handle ) {
+            if ( open( my $deps_handle, ">$deps_file" ) ) {
                deps_list($deps_handle);
                close($deps_handle);
            }
@@ -3651,7 +3851,8 @@
          }
 
         # Now wait for a file to change...
-        &rdb_cache_generated;
+        #        &rdb_cache_generated;
+        &rdb_set_rule_net;
         # During waiting for file changes, handle ctrl/C and ctrl/break here,
         #   rather than letting system handle them by terminating script (and
         #   code in the following command line to work: any script that calls
@@ -3668,7 +3869,7 @@
            if ($have_break) { last WAIT; }
            if ( rdb_user_changes(keys %rules_to_watch) ) { 
                if (!$silent) {
-                   warn "$My_name: Need to remake files.\n";
+                   print "$My_name: Need to remake files.\n";
                    &rdb_diagnose_changes( '  ' );
                }
                last WAIT;
@@ -3679,7 +3880,7 @@
            local $new_files = 0;
            rdb_for_some( [keys %current_primaries], sub{ $new_files += &rdb_find_new_files } );
            if ($new_files > 0) {
-               warn "$My_name: New file(s) found.\n";
+               print "$My_name: New file(s) found.\n";
                last WAIT; 
            }
            if ($have_break) { last WAIT; }
@@ -3697,7 +3898,7 @@
          print "$My_name: More than $pvc_timeout_mins mins of inactivity.  I'll finish.\n";
          return;
      }
-     $waiting = 0; if ($diagnostics) { warn "NOT       WAITING\n"; }
+     $waiting = 0; if ($diagnostics) { print "NOT       WAITING\n"; }
   } #end infinite_loop CHANGE:
 } #END sub make_preview_continuous
 
@@ -3704,8 +3905,16 @@
 #************************************************************
 
 sub process_rc_file {
-    # Usage process_rc_file( filename )
-    # NEW VERSION
+    # Usage process_rc_file( rc_file, [repeat_reaction] )
+    #   2nd argument controls action if the the file rc_file has already been
+    #   processed:
+    #      Omitted, undef, or 0: Silently ignore.  Used for processing
+    #                            standard rc files (system, user, current
+    #                            directory) since this situation legitimately
+    #                            occurs when cwd is one of the directories
+    #                            for the previously processed file.
+    #                     other: Give a warning, and don't process the file
+    #
     # Run rc_file whose name is given in first argument
     #    Exit with code 0 on success
     #    Exit with code 1 if file cannot be read or does not exist.
@@ -3712,14 +3921,27 @@
     #    Stop if there is a syntax error or other problem.
     # PREVIOUSLY: 
     #    Exit with code 2 if is a syntax error or other problem.
-    my $rc_file = $_[0];
+    my ($rc_file, $repeat_reaction) = @_;
+    my $abs_rc = abs_path($rc_file);
     my $ret_code = 0;
+    if ( exists $rc_files_read2{$abs_rc} ) {
+        if ( $repeat_reaction ) { 
+            warn
+                "$My_name: A user -r option asked me to process an rc file an extra time.\n",
+                "   Name of file = '$rc_file'\n",
+                ( ($rc_file ne $abs_rc) ? "   Abs. path = '$abs_rc'\n": ""),
+                "  I'll not process it\n";
+        }
+        return 0;
+    }
+    else {
+        $rc_files_read2{$abs_rc} = 1;
+    }
     push @rc_files_read, $rc_file;
 
     # I could use the do command of perl, but the preceeding -r test
     # to get good diagnostics gets the wrong result under cygwin
     # (e.g., on /cygdrive/c/latexmk/LatexMk)
-    my $RCH = new FileHandle;
     if ( !-e $rc_file ) {
         warn "$My_name: The rc-file '$rc_file' does not exist\n";
         return 1;
@@ -3729,9 +3951,10 @@
              "          should be a normal text file\n";
         return 1;
     }
-    elsif ( open $RCH, "<$rc_file" ) {
+    elsif ( open( my $RCH, "<", $rc_file ) ) {
         my $code = '';
-        { local $/; $code = <$RCH>;}
+        # Read all contents of file into $code:
+        { local $/ = undef; $code = <$RCH>;}
         close $RCH;
         eval $code;
     }
@@ -3739,13 +3962,6 @@
         warn "$My_name: I cannot read the rc-file '$rc_file'\n";
         return 1;
     }
-    # PREVIOUS VERSION
-#    if ( ! -r $rc_file ) {
-#        warn "$My_name: I cannot read the rc-file '$rc_file'\n",
-#            "          or at least that's what Perl (for $^O) reports\n";
-#        return 1;
-#    }
-#    do( $rc_file );
     if ( $@ ) {
         # Indent each line of possibly multiline message:
         my $message = prefix( $@, "     " );
@@ -3768,7 +3984,7 @@
     #     But I can always catch it with an eval if necessary.
     #     That confuses ctrl/C and ctrl/break handling.
     my $code = $_[0];
-    warn "$My_name: Executing initialization code specified by -e:\n",
+    print "$My_name: Executing initialization code specified by -e:\n",
          "   '$code'...\n" 
         if  $diagnostics;
     eval $code;
@@ -3823,7 +4039,7 @@
        return;
     }
     if ( ! -e $$Psource ) {
-        warn "$My_name: For custom dependency '$rule',\n",
+        print "$My_name: For custom dependency '$rule',\n",
              "    I won't delete destination file '$$Pdest'\n",
              "    and any other generated files,\n",
              "    because the source file '$$Psource' doesn't exist,\n",
@@ -3888,10 +4104,10 @@
 sub warn_running {
    # Message about running program:
     if ( $silent ) {
-        warn "$My_name: @_\n";
+        print "$My_name: @_\n";
     }
     else {
-        warn "------------\n at _\n------------\n";
+        print "------------\n at _\n------------\n";
     }
 } #END warn_running
 
@@ -3900,7 +4116,7 @@
 sub exit_help
 # Exit giving diagnostic from arguments and how to get help.
 {
-    warn "\n$My_name: @_\n",
+    print "\n$My_name: @_\n",
          "Use\n",
          "   $my_name -help\nto get usage information\n";
     exit 10;
@@ -4084,7 +4300,7 @@
 #************************************************************
 
 sub print_commands {
-  warn "Commands used by $my_name:\n",
+  print "Commands used by $my_name:\n",
        "   To run latex, I use \"$latex\"\n",
        "   To run pdflatex, I use \"$pdflatex\"\n",
        "   To run lualatex, I use \"$lualatex\"\n",
@@ -4110,7 +4326,7 @@
        "   To print a pdf file, I use \"$lpr_pdf\"\n",
        "   To find running processes, I use \"$pscmd\", \n",
        "      and the process number is at position $pid_position\n";
-   warn "Notes:\n",
+   print "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",
@@ -4146,8 +4362,7 @@
     my $base = $_[0];
     my $Pbiber_source = $_[1];
     my $blg_name = "$base.blg";
-    my $blg_file = new FileHandle;
-    open( $blg_file, "<$blg_name" )
+    open( my $blg_file, "<", $blg_name )
       or return 3;
     my $have_warning = 0;
     my $have_error = 0;
@@ -4163,6 +4378,7 @@
     my $control_file_malformed = 0;
     my %remote = ();                # List of extensions of remote files
     while (<$blg_file>) {
+        $_ = utf8_to_mine($_);
         if (/> WARN /) { 
             print "Biber warning: $_"; 
             $have_warning = 1;
@@ -4239,13 +4455,13 @@
     @$Pbiber_source = uniqs( @$Pbiber_source );
 
     if ( ($#not_found < 0) && ($#$Pbiber_source >= 0) ) {
-        warn "$My_name: Found biber source file(s) [@$Pbiber_source]\n"
+        print "$My_name: Found biber source file(s) [@$Pbiber_source]\n"
         unless $silent;
     }
     elsif ( ($#not_found == 0) && ($not_found[0] =~ /\.bib$/) ) {
         # Special treatment if sole missing file is bib file
         # I don't want to treat that as an error
-        warn "$My_name: Biber did't find bib file [$not_found[0]]\n";
+        print "$My_name: Biber did't find bib file [$not_found[0]]\n";
         return 5;
     }
     else {
@@ -4347,7 +4563,7 @@
         $return = &Run_subst( undef, undef, '', $source_base, $dest_base, $base );
         popd();
         if (!$silent) {
-            print "$My_name: Change directory back to '", cwd(), "'\n";
+            print "$My_name: Change directory back to '$cwd'\n";
         }
     }
     else {
@@ -4370,8 +4586,7 @@
 
     my $base = $_[0];
     my $blg_name = "$base.blg";
-    my $blg_file = new FileHandle;
-    open( $blg_file, "<$blg_name" )
+    open( my $blg_file, "<", $blg_name )
       or return 3;
     my $have_warning = 0;
     my $have_error = 0;
@@ -4379,6 +4594,7 @@
     my @missing_aux = ();
     my $error_count = 0;
     while (<$blg_file>) {
+        $_ = utf8_to_mine($_);
         if (/^Warning--/) { 
             #print "Bibtex warning: $_"; 
             $have_warning = 1;
@@ -4399,7 +4615,7 @@
     my $missing = $missing_citations + $#missing_aux + 1;
     if ( $#missing_aux > -1 ) {
         # Need to make the missing files.
-        warn "$My_name: One or more aux files is missing for bibtex. I'll try\n",
+        print "$My_name: One or more aux files is missing for bibtex. I'll try\n",
              "          to get *latex to remake them.\n";
         rdb_for_some( [keys %current_primaries], sub{ $$Pout_of_date = 1; } );
     }
@@ -4467,7 +4683,6 @@
     #       .fls file in out_dir, not aux_dir, which seems
     #       not natural.
     $fls_name = "%Z%R.fls";
-
     $dvi_name  = "%Z%R.dvi";
     $dviF_name = "%Z%R.dviF";
     $ps_name   = "%Z%R.ps";
@@ -4511,7 +4726,7 @@
         my $from =  "$aux_dir1$root_filename.$ext";
         my $to = "$out_dir1$root_filename.$ext" ;
         if ( test_gen_file( $from ) ) {
-            if (! $silent) { warn "$My_name: Moving '$from' to '$to'\n"; }
+            if (! $silent) { print "$My_name: Moving '$from' to '$to'\n"; }
             my $ret = move( $from, $to );
             if ( ! $ret ) { die "  That failed, with message '$!'\n";}
         }
@@ -4521,9 +4736,13 @@
 #***************************************************
 
 sub parse_log {
-# Scan log file for: dependent files
-#    reference_changed, bad_reference, bad_citation
-# Return value: 1 if success, 0 if no log file.
+# Use: parse_log( log_file_name,
+#                 ref to array containing lines,
+#                 ref to hash containing diagnostic etc information )
+# Given lines from already read log file, scan them for: dependent files
+#    reference_changed, bad_reference, bad_citation.
+# Assume in the lines array, lines are already wrapped, and converted to my CS.   
+# Return value: 1 if success, 0 if problems.
 # Put results in UPDATES of global variables (which are normally declared
 # local in calling routine, to be suitably scoped):
 #   %dependents: maps definite dependents to code:
@@ -4571,8 +4790,9 @@
 #
 # Input globals: $primary_out, $fls_file_analyzed
 #
+
+my ($log_name, $PAlines, $PHinfo) = @_;
    
-   
 # Give a quick way of looking up custom-dependency extensions
     my %cusdep_from = ();
     my %cusdep_to = ();
@@ -4581,11 +4801,7 @@
         $cusdep_from{$fromext} = $cusdep_from{".$fromext"} = $_;
         $cusdep_to{$toext} = $cusdep_to{".$toext"} = $_;
     }
-#    print "==== Cusdep from-exts:"; foreach (keys %cusdep_from) {print " '$_'";} print "\n";
-#    print "==== Cusdep to-exts:"; foreach (keys %cusdep_to) {print " '$_'";} print "\n";
 
-
-
     # $primary_out is actual output file (dvi or pdf)
     # It is initialized before the call to this routine, to ensure
     # a sensible default in case of misparsing
@@ -4596,71 +4812,14 @@
     $bad_character = 0;
     $bad_citation = 0;
 
-    my $log_file = new FileHandle;
-    if ( ! open( $log_file, "<$log_name" ) ) {
-        return 0;
-    }
     print "$My_name: Examining '$log_name'\n"
         if not $silent;
-    if ($log_file_binary) { binmode $log_file; }
-# Collect lines of log file
-    my @lines = ();
-    my $line = 0;
-    my $engine = 'pdfTeX';  # Simple default in case of problems
-    while(<$log_file>) {
-        $line++;
-        # Could use chomp here, but that fails if there is a mismatch
-        #    between the end-of-line sequence used by latex and that
-        #    used by perl.  (Notably a problem with MSWin latex and
-        #    cygwin perl!)
-        s/[\n\r]*$//;
-        # Handle wrapped lines:
-        # They are lines brutally broken at exactly $log_wrap chars 
-        #    excluding line-end.  Sometimes a line $log_wrap chars 
-        #    long is an ordinary line, sometimes it is part of a line
-        #    that was wrapped.  To handle all cases, I keep both
-        #    options open by putting the line into @lines before
-        #    and after appending the next line:  
-        my $len = length($_);
-        if ($line == 1) {
-            if ( /^This is ([^,]+), / ) {
-                $engine = $1;
-                print "=== TeX engine is '$engine'\n"
-                    if (!$silent);
-                if ( /^This is ([^,]+), [^\(]*\(([^\)]+)\)/ ) {
-                    $tex_distribution = $2;
-                    print "=== TeX distribution is '$tex_distribution'\n"
-                        if ($diagnostics);
-                }
-            }
-            else {
-                warn "$My_name: First line of .log file '$log_name' is not in standard format.\n";
-            }
-        }
-        else {
-            # Xetex and luatex sometimes wrap at longer line lengths:
-            # LuaTeX sometimes at 80. Xetex 80 or longer with non-ascii characters.
-            while ( ( ($len == $log_wrap)
-                      || ( ($engine eq 'LuaTeX') && ($len == $log_wrap+1) )
-                      || ( ($engine eq 'LuaHBTeX') && ($len == $log_wrap+1) )
-                      || ( ($engine eq 'XeTeX') &&  ($len >= $log_wrap+1) )
-                    )
-                    && !eof($log_file) ) {
-                push @lines, $_;
-                my $extra = <$log_file>;
-                $extra =~ s/[\n\r]*$//;
-                $len = length($extra);
-                $_ .= $extra;
-            }
-        }
-        push @lines, $_;
-    }
-    close $log_file;
 
-    push @lines, "";   # Blank line to terminate.  So multiline blocks 
-              # are always terminated by non-block line, rather than eof.
-    
-    $line = 0;
+    my $engine = $$PHinfo{engine};
+    my $tex_distribution = $$PHinfo{distribution};
+
+    # Now analyze the result:
+    $line_num = 0;
     my $state = 0;   # 0 => before ** line,
                      # 1 => after **filename line, before next line (first file-reading line)
                      # 2 => pwd_log determined.
@@ -4675,18 +4834,12 @@
     my $delegated_output = "";   #    and output file.  (Don't put in
                                  #    data structure until block is ended.)
     my %new_conversions = ();
-    my @retries = ();
     my $log_silent = ($silent ||  $silence_logfile_warnings);
-    my @warning_list = ();
+    @warning_list = ();
+
 LINE:
-    while( ($line <= $#lines) || ($#retries > -1) ) { 
-        if ($#retries > -1) {
-            $_ = pop @retries;
-        }
-        else {
-            $_ = $lines[$line];
-            $line ++;
-        }
+    for (@$PAlines) {
+        $line_num++;
         if ( /^! pdfTeX warning/ || /^pdfTeX warning/ ) {
             # This kind of warning is produced by some versions of pdftex
             # or produced by my reparse of warnings from other
@@ -4693,24 +4846,14 @@
             # versions.
             next;
         }
-        elsif ( /^(.+)(pdfTeX warning.*)$/ ) {
-            # Line contains a pdfTeX warnings that may have been
-            # inserted directly after other material without an
-            # intervening new line.  I think pdfTeX always inserts a
-            # newline after the warning.  (From examination of source
-            # code.) 
-            push @retries, $1;
-            # But continue parsing the original line, in case it was a
-            # misparse, e.g., of a filename ending in 'pdfTeX';
-        }
-        if ( $line == 1 ){
+        if ( $line_num == 1 ){
             if ( /^This is / ) {
                 # First line OK
                 next LINE;
             } else {
                 warn "$My_name: Error on first line of '$log_name'.\n".
-                    "This is apparently not a TeX log file.  ",
-                    "The first line is:\n$_\n";
+                     "  This is apparently not a TeX log file.  ",
+                     "  The first line is:\n$_\n";
                 $failure = 1;
                 $failure_msg = "Log file '$log_name' appears to have wrong format.";
                 return 0;
@@ -4769,7 +4912,7 @@
 
         # Check for changed references, bad references and bad citations:
         if (/Rerun to get/) { 
-            warn "$My_name: References changed.\n" if ! $log_silent;
+            print "$My_name: References changed.\n" if ! $log_silent;
             $reference_changed = 1;
         } 
         if (/^LaTeX Warning: (Reference[^\001]*undefined on input line .*)\./) {
@@ -4804,12 +4947,12 @@
         }
         elsif (/^No pages of output\./) {
             $primary_out = ''; 
-            warn "$My_name: Log file says no output from latex\n";
+            print "$My_name: Log file says no output from latex\n";
             next LINE;
         }
         elsif ( /^Output written on\s+(.*)\s+\(\d+\s+page/ ) {
             $primary_out = normalize_clean_filename($1, @pwd_log);
-            warn "$My_name: Log file says output to '$primary_out'\n"
+            print "$My_name: Log file says output to '$primary_out'\n"
                unless $silent;
             next LINE;
         }
@@ -4885,14 +5028,14 @@
             $idx_base = $idx_path.$idx_base;
             $idx_file = $idx_base.$idx_ext;
             if ( $idx_ext eq '.idx' ) {
-                warn "$My_name: Index file '$idx_file' was written\n"
+                print "$My_name: Index file '$idx_file' was written\n"
                   unless $silent;
                 $idx_files{$idx_file} = [ "$idx_base.ind", $idx_base ];
             }
             elsif ( exists $cusdep_from{$idx_ext} ) {
                 if ( !$silent ) {
-                    warn "$My_name: Index file '$idx_file' was written\n";
-                    warn "   Cusdep '$cusdep_from{$idx_ext}' should be used\n";
+                    print "$My_name: Index file '$idx_file' was written\n";
+                    print "   Cusdep '$cusdep_from{$idx_ext}' should be used\n";
                 }
                 # No action needed here
             }
@@ -5134,7 +5277,7 @@
                 $dependents{$include_name} = 3;
             }
             if ( $ext eq '.bbl' ) {
-                warn "$My_name: Found input bbl file '$include_name'\n"
+                print "$My_name: Found input bbl file '$include_name'\n"
                    unless $silent;
                 push @bbl_files, $include_name;
             }
@@ -5144,9 +5287,6 @@
     # Default includes are always definitive:
     foreach (@default_includes) { $dependents{$_} = 4; }
 
-    ###print "New parse: \n";
-    ###foreach (sort keys %dependents) { print "  '$_': $dependents{$_}\n"; }
-
     my @misparsed = ();
     my @missing = ();
     my @not_found = ();
@@ -5267,12 +5407,6 @@
             }
         }
     }
-
-    if ( ($#warning_list >= 0) && !$log_silent ) {
-        @warning_list = uniqs( @warning_list );
-        show_array( "$My_name: List of undefined refs and citations:",
-                    @warning_list );
-    }
     
     if ( $diagnostics ) {
         @misparse = uniqs( @misparse );
@@ -5298,21 +5432,17 @@
             print "\n";
         }
         if ($not_found > 0) {
-            print "Not found:\n";
-            foreach (@not_found) { print "   $_\n"; }
+            show_array( "Not found:", @not_found );
         }
         if ($missing > 0) {
-            print "Not existent:\n";
-            foreach (@missing) { print "   $_\n"; }
+            show_array( "Not existent:", @missing );
         }
         if ( $bbl > 0 ) {
-            print "Input bbl files:\n";
-            foreach (@bbl_files) { print "   $_\n"; }
+            show_array( "Input bbl files:", @bbl_files );
         }
 
         if ( $misparse > 0 ) {
-            print "Possible input files, perhaps from misunderstood lines in .log file:\n";
-            foreach ( @misparse ) { print "   $_\n"; }
+            show_array( "Possible input files, perhaps from misunderstood lines in .log file:",  @misparse );
         }
     }
     return 1;
@@ -5320,61 +5450,157 @@
 
 #************************************************************
 
+sub get_log_file {
+    # Use: get_log_file( log_file_name,
+    #                    ref to array to receive lines,
+    #                    ref to hash to receive diagnostic etc informaion )
+    # 3rd argument is optional
+    # Lines are unwrapped and converted to CS_system.
+    
+    my ($file, $PAlines, $PHinfo) = @_;
+
+    # Essential to use byte semantics, since (pdf)latex & lualatex
+    # wrap by bytes, not characters
+    use bytes;
+
+    # Where lines are wrapped at.  We'll sometimes override.
+    local $log_wrap = $log_wrap;
+
+    my $engine = '';
+    my $tex_distribution = '';
+    my ($line_num, $cont, $max_len) = ( 0, 0, 0 );
+    my $lua_mode = 0;  # Whether to use luatex-specific wrapping method.
+    my $byte_wrapping = 1;  # *latex does byte wrapping.  Modify if we find
+                            # log file is generated by a tex program that
+                            # wrapping by Unicode code points.
+
+    # File encoding: pdftex: UTF-8 but with wrapping at $log_wrap BYTES.
+    #                        (So individual wrapped lines can be malformed
+    #                        UTF-8, but we get valid UTF-8 after unwrapping.)
+    #                luatex: UTF-8 but with wrapping at APPROXIMATELY
+    #                        $log_wrap bytes. Rest as pdftex
+    #                xetex:  UTF-8 with wrapping at $log_wrap codepoints.
+    # So start reading file as bytes; first line gives which program,
+    # and for xetex we switch to reading file as UTF-8.
+    print "$My_name: Getting log file '$file'\n";
+    open( my $fh, '<', $file )
+        or return 0;
+  LINE:
+    while (<$fh> ) {
+        $line_num++;
+        s/\r?\n$//;
+        if ($line_num == 1) {
+            if ( /^This is ([^,]+), [^\(]*\(([^\)]+)\)/ ) {
+                $engine = $1;
+                $tex_distribution = $2;
+            }
+            else {
+                warn "$My_name: First line of .log file '$file' is not in standard format.\n";
+            }
+            if ( $engine =~ /XeTeX/i ) {
+                $byte_wrapping = 0;
+            }
+            $lua_mode = ( $engine =~ /lua.*tex/i );
+            # TeXLive's *tex take log wrap value from environment variable max_print_line, if it exists:
+            if ( ($tex_distribution =~ /TeX\s*Live/) && $ENV{max_print_line} ) {
+                $log_wrap = $ENV{max_print_line};
+                print "$My_name: changed column for log file wrapping from standard to $log_wrap\n".
+                      "  from env. var. max_print_line, which is obeyed by your TeXLive programs\n"
+                   if $diagnostics;
+            }
+            # First (signon) line of log file doesn't get wrapped
+            push @$PAlines, $_;
+            next LINE;
+        }
+        my $len = 0;
+        if ($byte_wrapping) { $len = length($_); }
+        else {
+            no bytes;
+            $len = length( decode('UTF-8', $_) );
+        }
+        if ($len > $max_len) { $max_len = $len }
+
+        # Is this line continuation of previous line?
+        if ($cont) { $$PAlines[$#$PAlines] .= $_; }
+        else { push @$PAlines, $_ }
+
+        # Is this line wrapped? I.e., is next line to be appended to it?
+        # Allow for fact that luatex doesn't reliably wrap at std place, e.g., 79.
+        $cont = ($len == $log_wrap)
+            || ( $lua_mode && ($len >= $log_wrap-2) && ($len <= $log_wrap+1) );
+        if ($cont && $diagnostics ) {
+            print "====Continuing line $line_num of length $len\n$_\n";
+        }
+    }
+    close($fh);
+    foreach (@$PAlines) { $_ = utf8_to_mine($_); }
+    push @$PAlines, "";  # Blank line to terminate.  So multiline blocks 
+              # are always terminated by non-block line, rather than eof.
+    $$PHinfo{max_len} = $max_len;
+    $$PHinfo{num_lines} = $line_num;
+    $$PHinfo{num_after} = 1 + $#$PAlines;
+    $$PHinfo{engine} = $engine;
+    $$PHinfo{distribution} = $tex_distribution;
+    return 1;
+} #END get_log_file
+
+#=====================================
+
 sub find_set_log {
-    # Locate the log file, if possible.  This allows for possible configuration
-    # errors, e.g., because the command for (*)latex was such that it did not 
-    # do the setting of -output-directory or -aux-directory that the user intended,
-    # or because the version used did not support one or other of these options.
-    # Put result in $where_log (see its initial declaration/definition for details).
-    # Change $aux_dir and/or $out_dir as appropriate, and make consequent changes.
+    # Locate the log file, generated on this run.
+    # It should be in aux_dir. But:
+    #  1. With a sufficiently severe error in *latex, no log file was generated.
+    #  2. With aux_dir ne out_dir and emulate_aux off and a (TeXLive) *latex
+    #     that doesn't support aux_dir, the log file is in out_dir.
+    #  3. If the specified command has no %O or if *latex doesn't support
+    #     out_dir (hence not TeXLive and not MiKTeX), the log file would
+    #     be in cwd.
     #
-    # Probably further attention to location of output file (.dvi, .pdf, or .xdv)
-    # could be done, to get $out_dir and $$Pdest more accurately set.
+    #  3 is fatal error.
+    #  2 is handled by turning emulate_aux on, after which next run of *latex
+    #    handles problem.
+    #  1 is like any other error.
+    #  4 is treated like 1 (log file not found).
     #
-    # Typical configuration errors that lead to the need for this subroutine:
-    #        %O not used in command definition, so directory options don't getpassed
-    #           to (*)latex.
-    #        Use of $aux_dir different to $out_dir, when (*)latex doesn't support
-    #           the -aux-directory option (notably with TeXLive distribution).
-    if ($where_log == 1) {
-        # .log file was found in correct place on previous run.
-        # So there's no need to repeat search, since if the location were to
-        # change from run to run, we'd have other serious difficulties that are
-        # to hard to deal with.
-        return;
-    }
+    # Returns 
+    #    0 log file not found;
+    #    1 log file in aux_dir i.e., correct place;
+    #    2 log file **not** in aux_dir but in out_dir,
+    #      emulate_aux turned on, commands fixed,
+    #      and log file copied to aux_dir
+    # If the log file is found in cwd, report it and give fatal error.
+    
+    my $where_log = -1; # Nothing analyzed yet
+
     if ( test_gen_file( "$aux_dir1$root_filename.log" ) ) {
         # .log file is in expected place.
         $where_log = 1;
     }
-    elsif ( test_gen_file( "$out_dir1$root_filename.log" ) ) {
-        # .log file is in out_dir not in aux_dir.
-        # Presumably there is a configuration error
-        # that prevents aux_dir from being used by latex.
-        warn "$My_name: .log file in '$out_dir' instead of expected '$aux_dir'\n";
-        if ($emulate_aux) {
-            warn "    But emulate_aux is on, so that should not happen\n",
-                 "    I'll switch aux_dir to equal out_dir\n";
-            $where_log = 2;
-            $aux_dir = $out_dir;
+    elsif ( (! $emulate_aux) && test_gen_file( "$out_dir1$root_filename.log" ) ) {
+        warn "$My_name: .log file in '$out_dir' instead of expected '$aux_dir'\n",
+             "   But emulate_aux is off.  So I'll turn it on.\n",
+             "   I'll copy the log file to the correct place.\n",
+             "   The next run of *latex **SHOULD** not have this problem.\n";
+        copy( "$out_dir1$root_filename.log", "$aux_dir1$root_filename.log" );
+        $where_log = 2;
+        $emulate_aux = 1;
+        $emulate_aux_switched = 1;
+        # Fix up commands to have fudged use of directories for
+        # use with non-aux-dir-supported *latex engines.
+        foreach ( $$Pext_cmd ) {
+            s/ -output-directory=[^ ]*(?= )//g;
+            s/ -aux(-directory=[^ ]*)(?= )/ -output$1/g;
         }
-        else {
-            warn "    But emulate_aux is off.  So I'll turn it on.\n";
-            $emulate_aux = 1;
-            $emulate_aux_switched = 1;
-            foreach ( $$Pext_cmd ) {
-                s/ -output-directory=[^ ]*(?= )//g;
-                s/ -aux(-directory=[^ ]*)(?= )/ -output$1/g;
-            }
-        }
     }
     elsif ( test_gen_file( "$root_filename.log" ) ) {
         # .log file is not in out_dir nor in aux_dir, but is in cwd.
         # Presumably there is a configuration error
         # that prevents the directories from being used by latex.
-        # So change $aux_dir to the actually used value.
-        $where_log = 3;
-        $aux_dir = "";
+        die "$My_name: The log file found was '$root_filename.log' instead of\n",
+            "  '$aux_dir1$root_filename.log'.  Probably a configuration error\n",
+            "  prevented the use of the -aux-directory and/or the -output-directory\n",
+            "  options with the *latex command.\n",
+            "  I'll stop.\n";
     }
     else {
         # No .log file found
@@ -5384,18 +5610,7 @@
         $failure_msg 
             = "*LaTeX didn't generate the expected log file '$log_name'\n";
     }
-    if ($where_log > 1) {
-        warn "$My_name: Changed aux_dir from '$aux_dir_requested' to '$aux_dir'\n".
-             "          to allow for probable configuration error\n";
-        # Allow for the changes associated with change of $aux_dir:
-        &normalize_aux_out_ETC;
-        &set_names;
-        warn "$My_name: Actual .log file is\n",
-             "     '$log_name'\n",
-             "  instead of the value\n",
-             "     '$aux_dir_requested/$root_filename.log'\n",
-             "   that seemed to be intended.\n";
-    }
+    return $where_log;
 } #END find_set_log
 
 #************************************************************
@@ -5404,7 +5619,7 @@
     my $start_time = processing_time();  
     my ($fls_name, $Pinputs, $Poutputs, $Pfirst_read_after_write, $Ppwd_latex ) = @_;
     %$Pinputs = %$Poutputs = %$Pfirst_read_after_write = ();
-    my $fls_file = new FileHandle;
+    my $fls_file;
     # Make a note of current working directory
     # I'll update it from the fls file later
     # Currently I don't use this, but it would be useful to use
@@ -5421,23 +5636,39 @@
     # be definitive in the fls file.
 
     my $cwd = good_cwd();
-    if ( ! open ($fls_file, "<$fls_name") ) {
+    if ( ! open($fls_file, "<", $fls_name) ) {
+#    if ( ! open($fls_file, "<:encoding(UTF-8)", $fls_name) ) {
         return 1;
     }
 
+    print "$My_name: Examining '$fls_name'\n"
+        if not $silent;
+
     my $pdf_base = basename($pdf_name);
     my $log_base = basename($log_name);
     my $out_base = basename($$Pdest);
-
-    foreach $_ ( <$fls_file> ) {
+    my $pwd_subst = undef; # Initial string for pwd that is to be removed to
+                           # make relative paths, when possible.  It must end
+                           # in '/', if defined.
+    for ( <$fls_file> ) {
         # Remove trailing CR and LF. Thus we get correct behavior when an fls file
         #  is produced by MS-Windows program (e.g., in MiKTeX) with CRLF line ends,
         #  but is read by Unix Perl (which treats LF as line end, and preserves CRLF
         #  in read-in lines):
-        $_ =~ s/[\n\r]*$//;
+        # And convert '\'
+        s/\r?\n$//;
+        s[\\][/]g;
+        if (($^O eq 'MSWin32') && /PWD/ && is_valid_utf8($_) ) {
+            # TeXLive produces PWD in CS_system not UTF-8.
+            # ???? Later get tex_distribution before analyzing fls file, so do better test.
+            print "PWD line not in UTF-8\n";
+            # Assume in CS_system, no change needed.
+        }
+        else { $_ = utf8_to_mine($_); }
         if (/^\s*PWD\s+(.*)$/) {
             my $cwd_fls = $1;
-            $$Ppwd_latex = $cwd_fls;
+            $pwd_subst = $$Ppwd_latex = $cwd_fls;
+            if ($pwd_subst !~ m[/$] ) { $pwd_subst .= '/'; }
             if ( $cwd_fls =~ /\"/ ) {
                 warn "$My_name: The working directory has a '\"' character in its name:\n",
                      "  '$cwd'\n  This can cause me trouble. Beware!\n";
@@ -5454,8 +5685,8 @@
             #   us from coding issues if the PWD contains non-ASCII characters.  What
             #   coding scheme (UTF-8, code page, etc) is used depends on OS, TeX
             #   implementation, ...
-            if ( defined $$Ppwd_latex ) { 
-                $file =~ s(^\Q$$Ppwd_latex\E[\\/])();
+            if ( defined $pwd_subst ) { 
+                $file =~ s(^\Q$pwd_subst\E)();
             }
             $file = normalize_filename( $file );
             if ( (exists $$Poutputs{$file}) && (! exists $$Pinputs{$file}) ) {
@@ -5546,48 +5777,52 @@
 # ------------------------------
 
 sub normalize_filename {
-   # Usage: normalize_filename( filename [, extra forms of name of cwd] )
-   # Returns filename with removal of various forms for cwd, and
-   # with conversion of directory separator to '/' only.
-   # Also when filename is name of a directory, with a trailing '/',
-   #   the trailing '/' is removed.
-   #
-   my ( $file, @dirs ) = @_;
-   my $file1 = $file;   # Saved original value
-   my $cwd = good_cwd();
-   # Normalize files to use / to separate directory components:
-   # (Note both / and \ are allowed under MSWin.)
-   foreach ($cwd, $file,  @dirs) {
-       s(\\)(/)g;
-       # If this is directory name of form :.../", remove unnecessary
-       # trailing directory separators:
-       $_ = dirname_no_tail( $_ );
-   }
-   
-   # Remove initial component equal to current working directory.
-   # Use \Q and \E round directory name in regex to avoid interpretation
-   #   of metacharacters in directory name:
-   foreach my $dir ( @dirs, '.', $cwd ) {
-       if ( $dir =~ /^\s*$/ ) {
-           # All spaces, nothing to do.
-           next;
-       }
-       if ($file eq $dir) {
-           # Filename equals cwd, so it is . relative to cwd:
-           $file = '.';
-           last;
-       }
-       if ( $file =~ s(^\Q$dir\E/)() ) {
-           last;
-     }
-   }
-   if ($file eq '' ) {
-       # This only occurs for $file equal to a directory that
-       # is the cwd. Our convention is always to set it to '.'
-       # 
-       $file = '.';
-   }
-   return $file;
+    # Usage: normalize_filename( filename [, extra forms of name of cwd] )
+    # Returns filename with removal of various forms for cwd, and
+    # with conversion of directory separator to '/' only,
+    # and with use of my current choice of Unicode normalization.
+    # Also when filename is name of a directory, with a trailing '/',
+    #   the trailing '/' is removed.
+    # ????In presence of accented characters in directory names, intended
+    # functioning is when all cwd strings are in my chosen NF.
+    #
+    my ( $file, @dirs ) = @_;
+    my $cwd = good_cwd();
+    # Normalize files to use / to separate directory components:
+    # (Note both / and \ are allowed under MSWin.)
+    foreach ($cwd, $file,  @dirs) {
+        s(\\)(/)g;
+        # If this is directory name of form :.../", remove unnecessary
+        # trailing directory separators:
+        $_ = dirname_no_tail( $_ );
+    }
+
+    # Remove initial component equal to current working directory.
+    # Use \Q and \E round directory name in regex to avoid interpretation
+    #   of metacharacters in directory name:
+    foreach my $dir ( @dirs, '.', $cwd ) {
+        if ( $dir =~ /^\s*$/ ) {
+            # All spaces, nothing to do.
+            next;
+        }
+        if ($file eq $dir) {
+            # Filename equals cwd, so it is . relative to cwd:
+            $file = '.';
+            last;
+        }
+        my $subst = $dir;
+        if ($subst !~ m[/$]) { $subst .= '/'; }
+        if ( $file =~ s(^\Q$subst\E)() ) {
+            last;
+      }
+    }
+    if ($file eq '' ) {
+        # This only occurs for $file equal to a directory that
+        # is the cwd. Our convention is always to set it to '.'
+        # 
+        $file = '.';
+    }
+    return $file;
 } #END normalize_filename
 
 # ------------------------------
@@ -5652,7 +5887,7 @@
     @$Pbst_files = uniqs( @$Pbst_files );
 
     if ( $#{$Pbib_files} == -1 ) {
-        warn "$My_name: No .bib files listed in .aux file '$aux_file' \n",
+        print "$My_name: No .bib files listed in .aux file '$aux_file' \n",
         return 2;
     }
     my @not_found = &find_file_list1( $Pbib_files, $Pbib_files,
@@ -5671,7 +5906,7 @@
             return 3;
     }
     if ( $#not_found < 0) {
-        warn "$My_name: Found bibliography file(s) [@$Pbib_files]\n"
+        print "$My_name: Found bibliography file(s) [@$Pbib_files]\n"
         unless $silent;
     }
     else {
@@ -5699,7 +5934,7 @@
 #   Return 0 if fail to open it
 {
    my $aux_file = $_[0];
-   my $aux_fh = new FileHandle;
+   my $aux_fh;
    if (! open($aux_fh, $aux_file) ) { 
        warn "$My_name: Couldn't find aux file '$aux_file'\n";
        return 0; 
@@ -5707,6 +5942,7 @@
    push @$Paux_files, $aux_file;
 AUX_LINE:
    while (<$aux_fh>) {
+      $_ = utf8_to_mine($_);
       if ( /^\\bibdata\{(.*)\}/ ) { 
           # \\bibdata{comma_separated_list_of_bib_file_names}
           # These are normally without the '.bib' extension.
@@ -5722,9 +5958,7 @@
           &parse_aux1( $aux_dir1.$1 );
       }
       else {
-          foreach my $Psub (@aux_hooks) {
-              &$Psub;
-          }
+          run_hooks( 'aux_hooks' );
       }
    }
    close($aux_fh);
@@ -5838,9 +6072,16 @@
 #************************************************************
 
 sub rdb_read {
-    # Call: rdb_read( $in_name  )
+    # Call: rdb_read( $in_name, inhibit_output_switch  )
     # Sets rule database from saved file, in format written by rdb_write.
-    # Returns -1 if file could not be read else number of errors.
+    # The second argument controls behavior when there's a mismatch between
+    # output extensions for primary rule in the cache and current settings.
+    # If the second argument is true, omit a switch of output extension,
+    # otherwise let the cached setting be obeyed (if possible).
+    #
+    # Returns: -2 if file doesn't exist,
+    #          -1 if file existed but couldn't be read
+    #          else number of errors.
     # Thus return value on success is 0
     # Requires: Rule database initialized with standard rules, with
     #             conditions corresponding to requests determined by
@@ -5865,14 +6106,30 @@
     #       may/should be in the future.)
     #   (e) Something else, e.g., copying/editing of fdb_latexmk file.
     #
-    local $in_name = $_[0];
-    my $in_handle = new FileHandle;
-    $in_handle->open( $in_name, '<' )
-        or return ();
+    local ($in_name, $inhibit_output_switch) = @_;
+
+    # We'll have conversions between encodings, and pattern,
+    # so byte semantics will be safest.
+    use bytes;
+    
+    my $in_handle;
+    if ( ! -e $in_name ) {
+        # Note: This is NOT an error condition, since the fdb_latexmk file
+        #       can legitimately not exist.
+        return -2;   
+    }
+    if ( ! open( $in_handle, '<', $in_name ) ) {
+        warn "$My_name: Couldn't read '$fdb_name' even though it exists\n";
+        return -1;
+    }
+    print "$My_name: Examining fdb file '$fdb_name' for cached rules ...\n"
+      if $diagnostics;
     my $errors = 0;
-    my $state = -1;   # Values: -1: before start; 0: outside rule;
-                      # 1: in source section;
-                      # 2: in generated file section;
+    my $state = -1;   # Values:
+                      # -1: before start;
+                      #  0: outside rule;
+                      #  1: in source section;
+                      #  2: in generated file section;
                       # 10: ignored rule.
     my $rule = '';
     local $run_time = 0;
@@ -5883,17 +6140,19 @@
     local %new_sources = ();  # Hash: rule => { file=>[ time, size, md5, fromrule ] }
     my $new_source = undef;   # Reference to hash of sources for current rule
 LINE:
-    while ( <$in_handle> ) {
+    while ( <$in_handle> ) {        
         # Remove leading and trailing white space.
         s/^\s*//;
         s/\s*$//;
+        $_ = utf8_to_mine($_);
+        
         if ($state == -1) {
             if ( ! /^# Fdb version ([\d]+)$/ ) {
                 warn "$My_name: File-database '$in_name' is not of correct format\n";
                 return 1;
             }
-            if ( $1 > $fdb_ver) {
-                warn "$My_name: File-database '$in_name' is of too new version, $1 > $fdb_ver\n";
+            if ( $1 ne $fdb_ver) {
+                warn "$My_name: File-database '$in_name' is of incompatible version, $1 v. $fdb_ver\n";
                 return 1;
             }
             $state = 0;
@@ -5908,32 +6167,33 @@
             $run_time = $check_time = 0;
             $source = $dest = $base = '';
             $old_actives{$rule} = 1;
-            if ( $tail =~ /^\s*(\S+)\s*$/ ) {
+            if ( $tail =~ /^\s*(\S+)\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s+(\S+)\s*$/ ) {
                 $run_time = $1;
-            }
-            elsif ( $tail =~ /^\s*(\S+)\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s*$/ ) {
-                $run_time = $1;
                 $source = $2;
                 $dest = $3;
                 $base = $4;
-            }
-            elsif ( $tail =~ /^\s*(\S+)\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s+(\S+)\s*$/ ) {
-                $run_time = $1;
-                $source = $2;
-                $dest = $3;
-                $base = $4;
                 $check_time = $5;
             }
+            else {
+                # Line is not in correct format
+                warn "$My_name: In '$in_name' there's a rule line not in correct format:\n",
+                     "    $_\n",
+                     "Perhaps the file has been edited, or there's a bug.\n";                    
+                $errors ++;
+                $state = 10;
+                next LINE;
+            }
             if ( rdb_rule_exists( $rule ) ) {
                 rdb_one_rule( $rule, \&rdb_read_set_rule );
             }
             elsif ($rule =~ /^cusdep\s+(\S+)\s+(\S+)\s+(.+)$/ ) {
-                # Create custom dependency
+                # create custom dependency
                 my $fromext = $1;
                 my $toext = $2;
                 my $base = $3;
-                $source = "$base.$fromext";
-#                $dest =   "$base.$toext";
+                # don't set $source and $dest here, but use the already-set values
+                #  from the rule definition line: under some situations the rule
+                #  may have these changed from normal.
                 my $func_name = '';
                 foreach my $dep ( @cus_dep_list ) {
                     my ($tryfromext,$trytoext,$must,$try_func_name) = split('\s+',$dep);
@@ -5984,11 +6244,11 @@
                 if ($rule =~ /^(bibtex|biber)/) { $PA_extra_gen = [ "$base.blg" ]; }
                 if ($rule =~ /^bibtex/) { $int_cmd = "run_bibtex"; }
                 if ($rule =~ /^makeindex/) { $int_cmd = "run_makeindex"; }
-                warn "$My_name: File-database '$in_name': setting rule '$rule'\n"
+                print "$My_name: File-database '$in_name': setting rule '$rule'\n"
                    if $diagnostics;
                 my $cmd_type = 'external';
                 my $ext_cmd = ${$rule_generic};
-                warn "  Rule kind = '$rule_generic'; ext_cmd = '$ext_cmd';\n",
+                print "  Rule kind = '$rule_generic'; ext_cmd = '$ext_cmd';\n",
                      "  int_cmd = '$int_cmd';\n",
                      "  source = '$source'; dest = '$dest'; base = '$base';\n"
                    if $diagnostics;
@@ -6000,7 +6260,7 @@
             }
             else {
                 if ($diagnostics) {
-                    warn "$My_name: In file-database '$in_name' rule '$rule'\n",
+                    print "$My_name: In file-database '$in_name' rule '$rule'\n",
                         "   is not in use in this session\n";
                 }
                 $new_source = undef;
@@ -6051,8 +6311,8 @@
             next LINE;
         }
     }
-    undef $in_handle;
-    # Set cus dependencies.
+    close $in_handle;
+    # Get state of dependencies, including creating cus deps if needed
     &rdb_set_dependents( keys %rule_db );
     &rdb_set_rule_net;
 
@@ -6092,15 +6352,20 @@
          && $possible_primaries{$rule}
          && exists( $allowed_output_ext{$oldext} )
          && ( $oldpath.$oldbase eq $newpath.$newbase )
+         && ( ! $inhibit_output_switch )
         )
     {
         # Change only in extension: A common cause: use of \pdfoutput in tex
         # file, with conflict with requested compilation type.  The old
         # extension wins.
-        warn "$My_name: change in extension of output file from '$oldext' on previous run\n",
-             "  to '$newext' for this run.\n",
-             "  So I'll CHANGE the output type from '$newext' to '$oldext',\n",
-             "  and make any necessary fixups.\n";
+        warn "$My_name: In reading the fdb_latexmk file for the previous run of latexmk, I\n",
+            "    found that the output extension for '$rule' was '$oldext', but requests for\n",
+            "    this run of latexmk give '$newext'.  Probably that was due to a specific\n",
+            "    request by the .tex document for output to '$oldext'.\n",
+            "    So (if possible) I'll reset the output extension back to '$oldext', which\n",
+            "    will be correct on the assumption that the old extension still reflects the\n",
+            "    situation with the .tex document. If the assumption is wrong, I'll correct\n",
+            "    that after the next run of '$rule'.\n";
         my $switch_error =  switch_output( $rule, $oldext, $newext );
         if ($switch_error) {
             warn "   I could not accommodate the changed output extension.\n",
@@ -6113,13 +6378,6 @@
         return;
     }
     # All special cases now dealt with. 
-    warn "$My_name: In reading file '$in_name' for state of files and rules on\n",
-         "  previous run, I found that rule '$rule' had a destination file\n",
-         "    $dest\n",
-         "  that differs from the current destination file\n",
-         "    $$Pdest\n",
-         "  I'll use the current destination, and flag the rule as out of date.\n";
-    $$Pout_of_date = 10;
 }  #END rdb_read_set_rule
 
 #************************************************************
@@ -6130,19 +6388,23 @@
     #   for all rules needed to make final output
     # Returns 1 on success, 0 if file couldn't be opened.
     local $out_name = $_[0];
-    local $out_handle = new FileHandle;
+
+    use bytes;
+    
+    local $out_handle;
     if ( ($out_name eq "") || ($out_name eq "-") ) {
         # Open STDOUT
-        $out_handle->open( '>-' );
+        open( $out_handle, '>-' );
     }
     else {
-       $out_handle->open( $out_name, '>' );
+       open( $out_handle, '>', $out_name );
     }
     if (!$out_handle) { return 0; }
 
+    #  ??? For safety?
     &rdb_set_rule_net;
 
-    print $out_handle "# Fdb version $fdb_ver\n";
+    fprint8( $out_handle, "# Fdb version $fdb_ver\n" );
     my @rules = sort &rdb_accessible;
     rdb_for_some(
        \@rules,
@@ -6155,17 +6417,19 @@
            { 
                return;
            }
-           print $out_handle "[\"$rule\"] $$Prun_time \"$$Psource\" \"$$Pdest\" \"$$Pbase\" $$Pcheck_time\n";
+           fprint8( $out_handle, "[\"$rule\"] $$Prun_time \"$$Psource\" \"$$Pdest\" \"$$Pbase\" $$Pcheck_time\n" );
            rdb_do_files(
-             sub { print $out_handle "  \"$file\" $$Ptime $$Psize $$Pmd5 \"$$Pfrom_rule\"\n"; }
+               sub { my $from_rule = $from_rules{$file} || '';
+                     fprint8( $out_handle, "  \"$file\" $$Ptime $$Psize $$Pmd5 \"$from_rule\"\n" );
+               }
            );
-           print $out_handle "  (generated)\n";
+           fprint8( $out_handle, "  (generated)\n" );
            foreach (sort keys %$PHdest) {
-               print $out_handle "  \"$_\"\n";
+               fprint8( $out_handle, "  \"$_\"\n" );
            }
        }
     );
-    undef $out_handle;
+    close $out_handle;
     return 1;
 } #END rdb_write
 
@@ -6172,6 +6436,7 @@
 #************************************************************
 
 sub rdb_set_latex_deps {
+    # Call: rdb_set_latex_deps( [inhibit_output_switch] )
     # Assume primary rule context.  
     # This is intended to be applied only for a primary (LaTeX-like) rule.
     # Set its dependents etc, using information from log, aux, and fls files.
@@ -6276,6 +6541,7 @@
     #     see pythontex-latexmk) for subroutine called to process a .tex to add items to
     #     %PHdest. So initializing here is too late.
 
+    local ($inhibit_output_switch) = @_;
     # Rules should only be primary
     if ( $$Pcmd_type ne 'primary' ) {
         warn "\n$My_name: ==========$My_name: Probable BUG======= \n   ",
@@ -6312,7 +6578,7 @@
                                   #  missing file during *latex compliation
                                   #  instead of just allowing to be made later
                                   #  by another rule. 
-    
+
     # The following are also returned by parsing routines, but are global,
     # to be used by caller:
     # $reference_changed, $bad_reference, $bad_character, $bad_citation, $mult_defined
@@ -6323,6 +6589,27 @@
         if ( /^eps pdf / ) { $epspdf_cusdep = 1; last; }
     }
 
+
+    # Settings to be found by reading log file:
+    our $engine = ''; # Which tex program?  (Use of $latex v.  ... no good, since
+                      # can be set to use another program.)
+    our $tex_distribution = '';
+    local %log_info = (); # Info. returned by get_log_file
+    local @log_lines = ();  # Lines in log file after unwrapping and converting
+                            # to use my internal CS.
+    # Get lines from log file now, with side effect of setting $engine and
+    #  $tex_distribution, so parse_fls can adjust its behavior if necessary).
+    my $read_log_file = get_log_file( $log_name, \@log_lines, \%log_info );
+    if (! $read_log_file ) {
+        warn "$My_name: Couldn't read log file '$log_name':\n  $!\n";
+    }
+    else {
+        $engine = $log_info{engine};
+        $tex_distribution = $log_info{distribution};
+    }
+
+
+    
     # Analyze fls file first.  It tells us the working directory as seen by *latex
     # But we'll use the results later, so that they take priority over the findings
     # from the log file.
@@ -6335,7 +6622,7 @@
         }
     }
  
-    &parse_log;
+    if ($read_log_file) { parse_log( $log_name, \@log_lines, \%log_info ); }
 
     my $missing_dirs = 'none';      # Status of missing directories
     if (@missing_subdirs) {
@@ -6354,7 +6641,7 @@
                 }
                 else {
                     if (mkdir $dir) {
-                        warn "$My_name: Directory '$dir' created\n";
+                        print "$My_name: Directory '$dir' created\n";
                     }
                     else {
                         $missing_dirs = 'failure';
@@ -6366,11 +6653,9 @@
         }
         else {
             $missing_dirs = 'not allowed';
-            warn "$My_name: There are missing subdirectories, but their creation\n",
-                 "    is not allowed.  The subdirectories are:\n";
-            foreach my $dir ( uniqs( @missing_subdirs ) ) {
-                warn "   '$dir'\n";
-            }
+            warn_array( "$My_name: There are missing subdirectories, but their creation\n".
+                        "    is not allowed.  The subdirectories are:",
+                        uniqs(@missing_subdirs) );
        }
     }
     # Use results from fls file.  (N.B. The hashes will be empty if the fls file
@@ -6441,13 +6726,13 @@
     #         package or class) sets \pdfoutput. 
     $missing_dvi_pdf = '';
     if ($primary_out eq '')  {
-        warn "$My_name: For rule '$rule', no output was made\n";
+        print "$My_name: For rule '$rule', no output was made\n";
         $missing_dvi_pdf = $$Pdest;
     }
     elsif ($primary_out ne normalize_filename($$Pdest) ) {
         my ($actual_base, $actual_path, $actual_ext) = fileparseA( $primary_out );
         my ($intended_base, $intended_path, $intended_ext) = fileparseA( $$Pdest );
-        if ( $actual_ext ne $intended_ext ) {
+        if ( ($actual_ext ne $intended_ext) && (!$inhibit_output_switch) ) {
             warn "$My_name: ===For rule '$rule', the extensions differ between the\n",
                  "   actual output file '$primary_out',\n",
                  "   and the expected output '$$Pdest'.\n";
@@ -6465,7 +6750,7 @@
                     $failure_msg = 'Could not handle change of output extension';
                 }
                 else {
-                    warn "   Rule structure will be changed suitably.\n";
+                    print "   Rule structure will be changed suitably.\n";
                 }
             }
         }
@@ -6587,11 +6872,11 @@
             if ($diagnostics);
         if ( exists $first_read_after_write{$new_source} ) {
             if ( dep_at_start($new_source) ) {
-                #warn "--- READ ONLY AFTER WRITE OF '$new_source'\n";
+                #print "--- READ ONLY AFTER WRITE OF '$new_source'\n";
                 $dependents{$new_source} = 7;
             }
             else {
-                #warn "--- READ ONLY AFTER CREATE OF '$new_source'\n";
+                #print "--- READ ONLY AFTER CREATE OF '$new_source'\n";
                 $dependents{$new_source} = 6;
             }
         }
@@ -6637,9 +6922,7 @@
         }
     }
 
-    foreach my $Psub (@latex_file_hooks) {
-         &$Psub;
-    }
+    run_hooks( 'latex_file_hooks' );
 
     # Some packages (e.g., bibtopic) generate a dummy error-message-providing
     #   bbl file when a bbl file does not exist.  Then the fls and log files
@@ -6663,8 +6946,7 @@
     }
     if ($diagnostics) {
         if ($num_new > 0 ) {
-            print "$num_new new source files for rule '$rule':\n";
-            foreach (@more_sources) { print "   '$_'\n"; }
+            show_array( "$num_new new source files for rule '$rule':", @more_sources );k { print "   '$_'\n"; }
         }
         else {
             print "No new source files for rule '$rule':\n";
@@ -6671,11 +6953,8 @@
         }
         my @first_read_after_write = sort keys %first_read_after_write;
         if ($#first_read_after_write >= 0) {
-            print "The following files were only read after being written:\n";
-            foreach (@first_read_after_write) {
-                print "   '$_'\n";
-            }
-          }
+            show_array( "The following files were only read after being written:", @first_read_after_write );
+        }
     }
     my @files_not_needed = ();
     foreach (keys %$PHsource) { 
@@ -6731,7 +7010,11 @@
     if ( ($actual_ext eq '.xdv') && ($out_dir ne $aux_dir) ){ $new_dest =~ s/^$out_dir1/$aux_dir1/; }
     if ( ($intended_ext eq '.xdv') && ($out_dir ne $aux_dir) ){ $new_dest =~ s/^$aux_dir1/$out_dir1/; }
 
-    rdb_change_dest( $new_dest );
+    rdb_remove_generated( $old_dest );
+    rdb_add_generated( $new_dest );
+    $$Pdest = $new_dest;
+
+    &rdb_set_rule_net;
         
     # Some fixes to avoid spurious error conditions:
     $switched_primary_output = 1;
@@ -6751,19 +7034,15 @@
     # Tests whether the file was generated during a run of *latex.
     # Assumes context for primary rule.
     # Two kinds of test are used:
-    # a. From %generated_log, which works after the log file has been parsed,
-    #    but only for certain files and for those TeX engines (not MiKTeX)
-    #    that put \openout lines in log file.
+    # a. From %generated_log and %generated_fls, which works after the fls and
+    #    log files hav been parsed, but in the log file only for certain files
+    #    and for those TeX engines (not MiKTeX) that put \openout lines in log
+    #    file.
     # b. By the file existing and being at least as new as the system
-    #    time at the start of the run. But we allow for a measured
-    #    offset between filetime and system time, which could be
-    #    nonzero if the file is on a different, remote system than the
-    #    one running latexmk. We must also allow a threshold in the
-    #    comparisons of filetimes to allow for the inaccuracy of the
-    #    offset measurement.
+    #    time at the start of the run. 
     my $file = shift;
-    return exists $generated_log{$file}
-           || ( -e $file && ( get_mtime( $file ) >= $$Prun_time + $filetime_offset - $filetime_causality_threshold));
+    return exists $generated_log{$file} || $generated_fls{$file}
+           || ( -e $file && ( get_mtime( $file ) >= $$Prun_time));
 }
 
 #************************************************************
@@ -6867,10 +7146,7 @@
     }
 
     if ( $diagnostics && ( $found > 0 ) ) {
-        warn "$My_name: Detected previously missing files:\n";
-        foreach ( sort keys %new_includes ) {
-            warn "   '$_'\n";
-        }
+        show_array( "$My_name: Detected previously missing files:", sort keys %new_includes );
     }
     return $found;
 } # END rdb_find_new_files
@@ -6879,18 +7155,15 @@
 
 sub rdb_set_dependents {
     # Call rdb_set_dependents( rules ...)
-    # Returns array (sorted), of new source files.
+    # Returns array (sorted), of new source files for the given rules.
     local @new_sources = ();
     local @deletions = ();
 
-# Shouldn't recurse.  The definite rules to be examined are given.
     rdb_for_some( [@_],  0, \&rdb_one_dep );
-# OLD    rdb_recurse( [@_],  0, \&rdb_one_dep );
     foreach (@deletions) {
         my ($rule, $file) = @$_;
         rdb_remove_files( $rule, $file );
     }
-    &rdb_make_links;
     return uniqs( @new_sources );
 } #END rdb_set_dependents
 
@@ -6926,7 +7199,6 @@
     if ( (! exists $possible_primaries{$rule}) && ($rule !~ /^cusdep/) ) {
         return;
     }
-#print "=============ONE_DEP: '$rule' '$file'\n";
     local $new_dest = $file;
     my ($base_name, $path, $toext) = fileparseA( $new_dest );
     $base_name = $path.$base_name;
@@ -6940,10 +7212,10 @@
             my $source = "$base_name.$fromext";
             # Found match of rule
             if ($diagnostics) {
-                print "Found cusdep:  $source to make $rule:$new_dest ====\n";
+                print "Found cusdep: $source to make $rule:$new_dest ====\n";
             }
             if ( -e $source ) {
-                $$Pfrom_rule = "cusdep $fromext $toext $base_name";
+                my $from_rule = "cusdep $fromext $toext $base_name";
                 my $new_new_dest = "$base_name.$toext";
                 if ($new_new_dest ne $new_dest) {
                     rdb_ensure_file( $rule, $new_new_dest );
@@ -6953,9 +7225,9 @@
                 if ( !-e $new_dest ) {
                     push @new_sources, $new_dest;
                 }
-                if (! rdb_rule_exists( $$Pfrom_rule ) ) {
-                    print "$My_name: === Creating rule '$$Pfrom_rule'\n" if $diagnostics;
-                    rdb_create_rule( $$Pfrom_rule, 'cusdep', '', \@PAnew_cmd, 3, 
+                if (! rdb_rule_exists( $from_rule ) ) {
+                    print "$My_name: === Creating rule '$from_rule'\n" if $diagnostics;
+                    rdb_create_rule( $from_rule, 'cusdep', '', \@PAnew_cmd, 3, 
                                      $source, $new_dest, $base_name, 0 );
                 }
                 return;
@@ -6969,10 +7241,10 @@
                                    "to build '$base_name.$toext'";
                     return;
                 }
-                elsif ( $$Pfrom_rule =~ /^cusdep $fromext $toext / )  {
+                elsif ( $from_rules{$file} && ($from_rules{$file} =~ /^cusdep $fromext $toext / ) )  {
                     # Source file does not exist, destination has the rule set.
                     # So turn the from_rule off
-                    $$Pfrom_rule = '';
+                    delete $from_rules{$file};
                 }
                 else {
                 }
@@ -6993,11 +7265,11 @@
                 $new_dest = "$base_name.$proptoext";
                 my $from_rule = "cusdep $fromext $proptoext $base_name";
                 push @new_sources, $new_dest;
-                print "Ensuring rule for '$from_rule', to make '$new_dest'\n"
+                print "$My_name: Ensuring rule for '$from_rule', to make '$new_dest'\n"
                     if $diagnostics > -1;
                 local @PAnew_cmd = ( 'do_cusdep', $func_name );
                 if (! rdb_rule_exists( $from_rule ) ) {
-                    print "$My_name: === Creating rule '$$Pfrom_rule'\n" if $diagnostics;
+                    print "$My_name: === Creating rule '$from_rule'\n" if $diagnostics;
                     rdb_create_rule( $from_rule, 'cusdep', '', \@PAnew_cmd, 3, 
                                      $source, $new_dest, $base_name, 0 );
                 }
@@ -7075,7 +7347,7 @@
     # Call: deps_list(fh)
     # List dependent files to file open on fh
     my $fh = $_[0];
-    print $fh "#===Dependents, and related info, for $filename:\n";
+    fprint8 $fh, "#===Dependents, and related info, for $filename:\n";
     my @dest_exts = ();
     if ($pdf_mode) {push @dest_exts, '.pdf';}
     if ($dvi_mode) {push @dest_exts, '.dvi';}
@@ -7088,7 +7360,7 @@
         sub{ push @generated, keys %$PHdest; },
         sub{ $source{$file} = 1; }
     );
-    foreach (keys %generated_exts_all) {
+    foreach (keys %generated_exts) {
         (my $name = /%R/ ? $_ : "%R.$_") =~ s/%R/${aux_dir1}${root_filename}/;
         push @generated, $name;
     }
@@ -7110,19 +7382,19 @@
          # deps file out-of-date are the same as those that make the real
          # target file (e.g., .pdf) out-of-date. So the GNU method seems
          # completely unnecessary.
-       print $fh "${out_dir1}${root_filename}${ext} :";
+       fprint8 $fh, "${out_dir1}${root_filename}${ext} :";
        foreach (sort keys %source) {
-           print $fh "\\\n    $_";
+           fprint8 $fh, "\\\n    $_";
        }
-       print $fh "\n";
+       fprint8 $fh, "\n";
     }
-    print $fh "#===End dependents for $filename:\n";
+    fprint8 $fh, "#===End dependents for $filename:\n";
     if ($dependents_phony) {
-        print $fh "\n#===Phony rules for $filename:\n\n";
+        fprint8 $fh, "\n#===Phony rules for $filename:\n\n";
         foreach (sort keys %source) {
-            print $fh "$_ :\n\n";
+            fprint8 $fh, "$_ :\n\n";
         }
-        print $fh "#===End phony rules for $filename:\n";
+        fprint8 $fh, "#===End phony rules for $filename:\n";
     }
 } #END deps_list
 
@@ -7142,7 +7414,7 @@
              }
              print "  [$rule]: '$$Pcmd_type' '$$Pext_cmd' '@int_cmd' $$Ptest_kind ",
                    "'$$Psource' '$$Pdest' '$$Pbase' $$Pout_of_date $$Pout_of_date_user\n"; },
-        sub{ print "    '$file': $$Ptime $$Psize $$Pmd5 '$$Pfrom_rule'\n"; }
+        sub{ print "    '$file': $$Ptime $$Psize $$Pmd5 '", ($from_rules{$file} || ''), "'\n"; }
     );
     if ($count_rules <= 0) {
         print "   ---No rules defined\n";
@@ -7165,6 +7437,8 @@
     foreach (keys %target_files) {
         if (exists $from_rules{$_}) { $rules{$from_rules{$_}} = 1; }
     }
+#    show_array( 'target_hash', sort keys %rules );
+#    &traceback;
     return %rules;
 } # End rdb_target_hash
 
@@ -7322,7 +7596,7 @@
     #           source files.  
     #    
 
-
+    # ??? Overkill?
     &rdb_set_rule_net;
 
     local %pass = ();
@@ -7333,6 +7607,7 @@
     local $too_many_passes = 0;
     local %rules_applied = ();
     local $switched_primary_output = 0;
+    local @warning_list = ();  # Undef refs etc reported in last primary run
     my $retry_msg = 0;         # Did I earlier say I was going to attempt 
                                # another pass after a failure?
     rdb_for_some ( [keys %rule_db],
@@ -7360,12 +7635,12 @@
         if ($diagnostics) {
             print "Make: doing pre_primary and primary...\n";
         }
-        # Do the primary run if it is needed. On return $runs == 0
-        #       signals that nothing was run (and hence no output
-        #       files changed), either because no input files
-        #       changed and no run was needed, or because the
-        #       number of passes through the rule exceeded the
-        #       limit.  In the second case $too_many_runs is set.
+        # Do the primary run preceeded by pre_primary runs, all only if needed.
+        #      On return, $runs == 0 signals that nothing was run (and hence
+        #      no output files changed), either because no input files
+        #      changed and no run was needed, or because the
+        #      number of passes through the rule exceeded the
+        #      limit.  In the second case $too_many_runs is set.
         rdb_for_some( [@pre_primary, $current_primary], \&rdb_make1 );
         if ($switched_primary_output) {
             print "=========SWITCH OF OUTPUT WAS DONE.\n";
@@ -7420,7 +7695,7 @@
     rdb_for_some( [@unusual_one_time], \&rdb_make1 );
 
     if ($runs_total > 0) { rdb_write( $fdb_name ); }
-    else { print "Nothing to do\n"; }
+    else { print "$My_name: Nothing to do for '$texfile_name'.\n"; }
 
     if ($#primary_warning_summary > -1) {
         # N.B. $mult_defined, $bad_reference, $bad_character, $bad_citation also available here.
@@ -7427,6 +7702,17 @@
         show_array( "$My_name: Summary of warnings from last run of *latex:", 
                     @primary_warning_summary );
     }
+    if ( ($#warning_list >= 0) && !$silence_logfile_warnings ) {
+        warn "$My_name: ====List of undefined refs and citations:\n";
+        for (my $i = 0; $i <= $#warning_list; $i++) {
+            if ($i >= $max_logfile_warnings ) {
+                warn " And ", $#warning_list + 1 - $i, " more --- see log file.\n";    
+                last;
+            }
+            warn "  $warning_list[$i]\n";
+        }
+    }
+
     if (! $silent) {
         if ($failure && $force_mode) {
             print "$My_name: Errors, in force_mode: so I tried finishing targets\n";
@@ -7479,16 +7765,10 @@
                }
               );
     if ($#warnings > -1) { 
-        warn "Collected warning summary (may duplicate other messages):\n";
-        foreach (@warnings){
-            warn "  $_\n";
-        }
+        show_array( "Collected warning summary (may duplicate other messages):". @warnings );
     }
     if ($#errors > -1) { 
-        warn "Collected error summary (may duplicate other messages):\n";
-        foreach (@errors){
-            warn "  $_\n";
-        }
+        show_array( "Collected error summary (may duplicate other messages):", @errors );
     }
     return $#errors+1;
 }
@@ -7502,7 +7782,7 @@
     # Assumes contexts for recursion, make, and rule, and
     # assumes that source files for the rule are to be considered
     # up-to-date.
-    if ($diagnostics) { print "  Make1 $rule\n"; }
+    if ($diagnostics) { print "  Make for rule '$rule'\n"; }
     if ($failure & ! $force_mode) {return;}
     if ( ! defined $pass{$rule} ) {$pass{$rule} = 0; } 
 
@@ -7556,7 +7836,7 @@
             #      Any error will arise at the *latex level due to a 
             #      missing source file at that level.
             if ( $$Psource && (! -e $$Psource)
-                 && ( ( $$Pcmd_type ne 'primary') )
+                 && ( $$Pcmd_type ne 'primary' )
                ) {
                 # Main source file doesn't exist, and rule is NOT primary.
                 # No action, since a run is pointless.  Primary is different:
@@ -7626,10 +7906,7 @@
     }
     else {
         warn_running( "Run number $pass{$rule} of rule '$rule'" );
-        if ($$Pcmd_type eq 'primary' ) { 
-            $return = &rdb_primary_run;
-        }
-        else { $return = &rdb_run1; }
+        $return = &rdb_run1;
     }
     if ($$Pchanged) {
         $newrule_nofile = 1;
@@ -7689,133 +7966,6 @@
 
 #************************************************************
 
-sub rdb_classify_rules {
-    # Usage: &rdb_classify_rules
-    # Assume the following variables are available (global or local):
-    # Input:
-    #    %target_rules    # Set to target rules
-    #    %target_files    # Set to target files
-    #    %possible_primaries
-    
-    # Output:
-    #    %current_primaries    # Keys are actual primaries
-    #    @pre_primary          # Array of rules
-    #    @post_primary         # Array of rules
-    #    @unusual_one_time     # Array of rules
-    # @pre_primary and @post_primary are in natural order of application.
-
-    local @requested_targets = &rdb_target_array;
-    local $state = 0;       # Post-primary
-    local @classify_stack = ();
-
-    %current_primaries = ();
-    @pre_primary = ();
-    @post_primary = ();
-    @unusual_one_time = ();
-
-    rdb_recurse( \@requested_targets, \&rdb_classify1, 0,0, \&rdb_classify2 );
-
-    # Reverse, as tendency is to find last rules first.
-    @pre_primary = reverse @pre_primary;
-    @post_primary = reverse @post_primary;
-
-    my @current_primaries = keys %current_primaries;
-    if ($#current_primaries < 0) {
-        die "$My_name: No active primary rules found.  I have to stop.\n";
-    }
-    elsif ($#current_primaries > 0) {
-        die "$My_name: More than one active primary rule found.  I have to stop.\n",
-            "  Primary rules: @current_primaries\n";
-    }
-    $current_primary = $current_primaries[0];
-
-    if ($diagnostics) {
-        print "Rule classification: \n";
-        if ($#requested_targets < 0) {
-            print "  No requested rules\n";
-        }
-        else {
-            print "  Requested rules:\n";
-            foreach ( @requested_targets ) { print "    $_\n"; }
-        }
-        if ($#pre_primary < 0) {
-            print "  No pre-primaries\n";
-        }
-        else {
-            print "  Pre-primaries:\n";
-            foreach (@pre_primary) { print "    $_\n"; }
-        }
-        print "  Primaries:\n";
-        foreach (keys %current_primaries) { print "    $_\n"; }
-        if ($#post_primary < 0) {
-            print "  No post-primaries\n";
-        }
-        else {
-            print "  Post-primaries:\n";
-            foreach (@post_primary) { print "    $_\n"; }
-        }
-        if ($#unusual_one_time < 0) {
-            print "  No inner-level one_time rules, as expected\n";
-        }
-        else {
-            print "  Inner-level one_time rules:\n";
-            foreach ( @unusual_one_time ) { print "    $_\n"; }
-        }
-        my @normal_one_time = keys %one_time;
-        if ($#normal_one_time < 0) {
-            print "  No outer-level one_time rules\n";
-        }
-        else {
-            print "  Outer-level one_time rules:\n";
-            foreach ( @normal_one_time ) { print "    $_\n"; }
-        }
-    } #end diagnostics
-
-} #END rdb_classify_rules
-
-#-------------------
-
-sub rdb_classify1 {
-    # Helper routine for rdb_classify_rules
-    # Applied as rule_act1 in recursion over rules
-    # Assumes rule context, and local variables from rdb_classify_rules
-    push @classify_stack, [$state];
-    if ( exists $possible_one_time{$rule} ) {
-        # Normally, we will have already extracted the one_time rules,
-        # and they will never be accessed here.  But just in case of
-        # problems or generalizations, we will cover all possibilities:
-        if ($depth > 1) {
-           warn "ONE TIME rule not at outer level '$rule'\n";
-        }
-        push @unusual_one_time, $rule;
-    }
-    elsif ($state == 0) {
-       if ( exists $possible_primaries{$rule} ) {
-           $state = 1;   # In primary rule
-           $current_primaries{ $rule } = 1;
-       }
-       else {
-           push @post_primary, $rule;
-       }
-    }
-    else {
-        $state = 2;     # in post-primary rule
-        push @pre_primary, $rule;
-    }
-} #END rdb_classify1
-
-#-------------------
-
-sub rdb_classify2 {
-    # Helper routine for rdb_classify_rules
-    # Applied as rule_act2 in recursion over rules
-    # Assumes rule context
-    ($state) = @{ pop @classify_stack };
-} #END rdb_classify2
-
-#************************************************************
-
-
 sub rdb_run1 {
     # Assumes context for: rule.
     # Unconditionally apply the rule
@@ -7824,20 +7974,38 @@
     #            -1 on error, 
     #            -2 when missing dest_file is to be ignored
 
-    # Source file data, by definition, correspond to the file state just
-    # before the latest run, and the run_time to the time just before the run:
-    &rdb_update_files;
+    # Defaults for summary of results of run.
     $$Prun_time = time();
+    
     $$Pchanged = 0;       # No special changes in files
     $$Plast_result = 0;
     $$Plast_message = '';
+    my $latex_like = ($$Pcmd_type eq 'primary'); 
 
-    # Return values for external command:
+    # Return value for external command:
     my $return = 0;
 
+# Source file data, by definition, correspond to the file state just
+# before the latest run, and the run_time to the time just before the run:
+    if ($latex_like) {
+        # For *latex, we will generate the list of generated files from the
+        # analysis of the results of the run.  So before the run we must
+        # reset the list of generated files saved in the rule data. Otherwise
+        # it can continue to contain out-of-date items left from the previous
+        # run.  (Think bibtopic, which writes bbl files!)
+        #
+        # This reset is not used/needed for other rules, since normally no
+        # analysis of a log file (or similar) is made to find generated
+        # files.  The set of extra generated files beyond the main
+        # destination file  is hard wired into the rule definition.
+        # 
+        &rdb_initialize_generated;
+    }
+    # Now set the current state of the files
+    &rdb_update_files;
+
     # Find any internal command
     my @int_args = @$PAint_cmd;
-    
     my $int_cmd = shift @int_args;
     my @int_args_for_printing = @int_args;
     foreach (@int_args_for_printing) {
@@ -7844,8 +8012,15 @@
         if ( ! defined $_ ) { $_ = 'undef'; }
     }
 
-    # The actual execution of the command:
+# ==========  Now the actual run of the command or ... for the rule ==========
+# But first save current total processing time for the process, so that after
+# the run of the command for the rule we can measure the processing time of
+# the rule (without overhead from other work latexmk does):
+
+    if ($latex_like) { run_hooks( 'before_xlatex' ); }
+
     my $time = processing_time();
+   
     if ($int_cmd) {
         print "For rule '$rule', use internal command '\&$int_cmd( @int_args_for_printing )' ...\n"
             if $diagnostics;
@@ -7863,9 +8038,27 @@
         $$Plast_message = "Bug or configuration error; incorrect command type";
     }
     $time = processing_time() - $time;
-    push @timings, "'$_[0]': time = $time\n";            
+    push @timings, "'$_[0]': time = " . sprintf('%.2f',$time) . "\n";
 
-    if ( $rule =~ /^biber/ ) {
+#============================================================================
+
+
+    # Analyze the results of the run, the first step of which is highly rule
+    # dependent, and may reassess the return code in $return.
+    # ????? Probably it would be best at a later revision to have analysis
+    # subroutines for each special case instead of in-line code here; there
+    # could possibly a user-configurable per-rulehook.
+    #
+    $$Pout_of_date = $$Pout_of_date_user = 0;
+    if ($latex_like) {
+        if ( $emulate_aux && ($aux_dir ne $out_dir) ) {
+            &move_out_files_from_aux;
+        }
+        run_hooks( 'after_xlatex' );
+        $return = analyze_latex_run( $return );
+        run_hooks( 'after_xlatex_analysis' );
+    }
+    elsif ( $rule =~ /^biber/ ) {
         my @biber_source = ( );
         my $retcode = check_biber_log( $$Pbase, \@biber_source );
         foreach my $source ( @biber_source ) {
@@ -7885,7 +8078,7 @@
         elsif ($retcode == 6) {
            # Missing control file.  Need to remake it (if possible)
            # Don't treat missing bbl file as error.
-           warn "$My_name: bibtex control file missing.  Since that can\n",
+           print "$My_name: bibtex control file missing.  Since that can\n",
                 "   be recreated, I'll try to do so.\n";
            $return = -2;
            rdb_for_some( [keys %current_primaries], sub{ $$Pout_of_date = 1; } );
@@ -7915,7 +8108,7 @@
         elsif ($retcode == 11) {
             push @warnings, "Biber: malformed bcf file for '$$Pbase'.  IGNORE";
             if (!$silent) {
-               warn "$My_name: biber found malformed bcf file for '$$Pbase'.\n",
+               print "$My_name: biber found malformed bcf file for '$$Pbase'.\n",
                     "  I'll ignore error, and delete any bbl file.\n";
             }
             # Malformed bcf file is a downstream consequence, normally,
@@ -7940,7 +8133,7 @@
             
         }
     }
-    if ( $rule =~ /^bibtex/ ) {
+    elsif ( $rule =~ /^bibtex/ ) {
         my $retcode = check_bibtex_log($$Pbase);
         if ( ! -e $$Psource ) {
             $retcode = 10;
@@ -7963,7 +8156,7 @@
             push @warnings, "Bibtex found no citations for '$$Pbase',\n",
                             "    or bibtex found a missing aux file\n";
             if (! -e $$Pdest ) {
-                warn "$My_name: Bibtex did not produce '$$Pdest'.  But that\n",
+                print "$My_name: Bibtex did not produce '$$Pdest'.  But that\n",
                      "     was because of missing files, so I will continue.\n";
                 $return = -2;
             }
@@ -7972,10 +8165,11 @@
             }
         }
     }
+    else {
+        # No special analysis for other rules
+    }
 
-    if ( ($$Pcmd_type eq 'primary') && ( $aux_dir ne $out_dir ) ) {
-        &move_out_files_from_aux;
-    }
+    # General
     $updated = 1;
     if ($$Ptest_kind == 3) { 
         # We are time-criterion first time only.  Now switch to
@@ -7982,7 +8176,6 @@
         # file-change criterion
         $$Ptest_kind = 1; 
     }
-    $$Pout_of_date = $$Pout_of_date_user = 0;
 
     if ( ($$Plast_result == 0) && ($return != 0) && ($return != -2) ) {
         $$Plast_result = 2;
@@ -7989,7 +8182,13 @@
         if ($$Plast_message eq '') {
             $$Plast_message = "Command for '$rule' gave return code $return";
             if ($rule =~ /^(pdf|lua|xe|)latex/) {
-                $$Plast_message .= "\n      Refer to '$log_name' for details";
+                if ( test_gen_file($log_name) ) {
+                    $$Plast_message .= "\n      Refer to '$log_name' for details";
+                }
+                else {
+                    $$Plast_message .=
+                    "\n     Serious error that appeared not to generate a log file.";
+                }
             }
             elsif ($rule =~ /^makeindex/) {
                 $$Plast_message .= "\n      Refer to '${aux_dir1}${root_filename}.ilg' for details";
@@ -8100,7 +8299,6 @@
         if (exists($subst{$_})) { $_ = $subst{$_}; }
     }
     $ext_cmd = join '', @tokens;
-
     my ($pid, $return) = 
           ( ($msg == 0) || ( ($msg == 1) && $silent ) )
              ? &Run($ext_cmd)
@@ -8110,33 +8308,26 @@
 
 #-----------------
 
-sub rdb_primary_run {
-    # Call: rdb_primary_run
+sub analyze_latex_run {
+    # Call: analyze_latex_run(old_ret_code)
+    # Analyze results of run of *latex (or whatever was run instead) from
+    # fls, log and aux files, and certain other information.
+    # It also deals with (a) Change of main output file from one allowed
+    # extension to another (e.g., dvi -> pdf). (b) Failure of *latex to
+    # handle -aux-directory option, as with TeXLive.
+    #
+    # The argument is the return code as obtained from the run of *latex
+    # and the returned value is either the original return code or an adjusted
+    # value depending on the conditions found (e.g., missing file(s) that
+    # latexmk know how to create).
+    #
     # Assumes contexts for: recursion, make, & rule.
     # Assumes (a) the rule is a primary, 
     #         (b) a run has to be made,
-    #         (c) source files have been made.
-    # This routine carries out the run of the rule unconditionally,
-    # and then parses log file etc.
-    my $return = 0;
 
-    if ( ! $filetime_offset_measured ) {
-        $filetime_offset = get_filetime_offset( $aux_dir1."tmp" );
-        if ( (abs($filetime_offset) > $filetime_offset_report_threshold)
-             && ($diagnostics || ! $silent) )
-        {
-            warn "$My_name: I am working around an offset relative to my system time by\n",
-                 "   $filetime_offset secs for file times in directory '$aux_dir1'.\n";
-        }
-        $filetime_offset_measured = 1;
-    }
+    my $return_latex = shift;
+    my $return = $return_latex;
 
-    # Need to reset the list of generated files.  If we don't it can contain
-    # out-of-date items from previous run.  (Think bibtopic, which writes
-    # bbl files!)
-    &rdb_initialize_generated;
-    my $return_latex = &rdb_run1;
-
     # Need to worry about changed directory, changed output extension
     # Where else is $missing_dvi_pdf set?  Was it initialized?
     if (-e $$Pdest) { $missing_dvi_pdf = '';}
@@ -8150,6 +8341,7 @@
         #    of name latex.fls or pdflatex.fls instead of $root_filename.fls.
         # Also that setting of -output-directory -aux-directory is not 
         #    respected by *latex, at least in some versions.
+
         my $std_fls_file = $fls_name;
         my @other_fls_names = ( );
         if ( $rule =~ /^pdflatex/ ) {
@@ -8202,15 +8394,6 @@
         rdb_show();
     }
 
-    $return = $return_latex;
-
-# ???? Is the following needed?
-    if ($return_latex && $$Pout_of_date_user) {
-       print "Error in *LaTeX, but change of user file(s), ",
-             "so ignore error & provoke rerun\n"
-          if (! $silent);
-       $return = 0;
-    }
     if ($return_latex && ($missing_dirs ne 'none') ) {
        print "Error in *LaTeX, but needed subdirectories in output directory\n",
              "   were missing and successfully created, so try again.\n"
@@ -8239,9 +8422,11 @@
     if ( $diagnostics && ($#primary_warning_summary > -1) ) {
        show_array( "$My_name: Summary of warnings:", @primary_warning_summary );
     }
+
     return $return;
-} #END rdb_primary_run
 
+} #END analyze_latex_run
+
 #************************************************************
 
 sub rdb_clear_change_record {
@@ -8274,6 +8459,11 @@
     $dest_mtime = get_mtime($$Pdest) if ($$Pdest);
     rdb_do_files( \&rdb_file_change1);
     while ( my ($s_rule, $l_pass) = each %$PHsource_rules ) {
+        # %$PHsource_rules is about rules on which the current rule
+        #   depends, but for which this dependence is not determined by
+        #   the source rules of the set of known source files.
+        # Use pass-count criterion to determine out-of-dateness for these.
+        # 
         if ( defined $pass{$s_rule}
              && ($pass{$s_rule} > $l_pass)
             )
@@ -8355,7 +8545,7 @@
 sub rdb_user_changes {
     # Argument(s): a set of top level rules.
     # Aim: Find any changed user files for those rules and all ancestors.
-    # Assumption: List of from_rules for files is up-to-date.
+    # Assumption: List of source_rules for files is up-to-date.
     &rdb_clear_change_record;
     rdb_recurse( [@_], sub{ &rdb_flag_changes_here(1); } );
     if ($#changed_user >=0) { show_array( 'User changed files', @changed_user ); }
@@ -8371,37 +8561,28 @@
     my $heading = defined($_[0]) ?   $_[0]  :  "$My_name: "; 
 
     if ($#rules_never_run >= 0) {
-        warn "${heading}Rules & subrules not known to be previously run:\n";
-        foreach (@rules_never_run) { warn "   $_\n"; }
+        show_array( "${heading}Rules & subrules not known to be previously run:", @rules_never_run );
     }
     if ( ($#changed >= 0) || (keys %changed_rules > 0) || ($#disappeared >= 0) || ($#no_dest >= 0) ) {
-        warn "${heading}File changes, etc:\n";
+        print "${heading}File changes, etc:\n";
         if ( $#changed >= 0 ) {
-            warn "   Changed files, or newly in use since previous run(s):\n";
-            foreach (uniqs(@changed)) { warn "      '$_'\n"; }
+            show_array( "   Changed files, or newly in use since previous run(s):", uniqs(@changed) );
         }
         if ( $#disappeared >= 0 ) {
-            warn "   No-longer-existing files:\n";
-            foreach (uniqs(@disappeared)) { warn "      '$_'\n"; }
+            show_array( "   No-longer-existing files:", uniqs(@disappeared) );
         }
         if ( $#no_dest >= 0 ) {
-            warn "   Non-existent destination files:\n";
-            foreach (uniqs(@no_dest)) { warn "      '$_'\n"; }
+            show_array( "   Non-existent destination files:", uniqs(@no_dest) );
         }
         if ( keys %changed_rules > 0 ) {
-            warn "   Rule(s) that have been run and require run of dependent rule:\n";
+            print "   Rule(s) that have been run and require run of dependent rule:\n";
             while (my ($s_rule, $d_rule) = each %changed_rules) {
-                warn "      '$s_rule' which requires run of '$d_rule'\n";
+                print "      '$s_rule' which requires run of '$d_rule'\n";
             }
         }
     }
-    elsif ($#rules_to_apply >=0) {
-         warn "${heading}The following rules & subrules became out-of-date:\n";
-         foreach (@rules_to_apply) { warn "      '$_'\n"; }
-    }
-    else {
-        warn "${heading}No file changes\n";
-    }
+    show_array( "${heading}The following rules & subrules became out-of-date:",
+                @rules_to_apply);
 }     #END rdb_diagnose_changes
 
 
@@ -8564,6 +8745,7 @@
 #************************************************************
 
 sub rdb_for_one_file {
+    # Use : rdb_for_one_file( rule, file, ref to action subroutine )
     my $rule = shift;
     # Avoid name collisions with general recursion and iteraction routines:
     local $file1 = shift;
@@ -8581,7 +8763,7 @@
 sub rdb_recurse_rule {
     # Call: rdb_recurse_rule($rule, \&rule_act1, \&file_act1, \&file_act2, 
     #                    \&rule_act2 )
-    # to do the work for one rule, recurisvely called from_rules for
+    # to do the work for one rule, recurisvely called source_rules for
     # the sources of the rules.
     # Assumes recursion context, i.e. that %visited, @heads, $depth.
     # We are overriding actions:
@@ -8612,9 +8794,10 @@
     # passed as a reference in calls in higher-level subroutine.
     # Assumes contexts set for: Recursion, rule, and file
     &$file_act1 if $file_act1;
-    rdb_recurse_rule( $$Pfrom_rule, $rule_act1, $file_act1, $file_act2,
+    my $from_rule = $from_rules{$file} || '';
+    rdb_recurse_rule( $from_rule, $rule_act1, $file_act1, $file_act2,
                       $rule_act2 )
-        if $$Pfrom_rule;
+        if $from_rule;
     &$file_act2 if $file_act2;
 } #END rdb_recurse_file
 
@@ -8721,12 +8904,10 @@
     local ($file, $file_act) = @_;
     if ( (!$file) ||(!exists ${$PHsource}{$file}) ) { return; }
     local $PAfile_data = ${$PHsource}{$file};
-    local ($Ptime, $Psize, $Pmd5, $Pfrom_rule, $Pcorrect_after_primary ) 
+    our $DUMMY;  # Fudge until fix rule_db
+    local ($Ptime, $Psize, $Pmd5, $DUMMY, $Pcorrect_after_primary ) 
           = Parray( $PAfile_data );
     &$file_act() if $file_act;
-    if ( ! rdb_rule_exists( $$Pfrom_rule ) ) {
-        $$Pfrom_rule = '';
-    }
 } #END rdb_one_file
 
 #************************************************************
@@ -8886,7 +9067,7 @@
                   }
     );
     if (defined $new_from_rule ) {
-        rdb_for_one_file( $rule, $new_file, sub{ $$Pfrom_rule = $new_from_rule; });
+        $from_rules{$new_file} = $new_from_rule;
     }
 } #END rdb_ensure_file 
 
@@ -8936,36 +9117,6 @@
 
 #************************************************************
 
-sub rdb_change_dest {
-   # Assumes rule context.
-   # Usage change_dest( new_dest [, flag] )
-   # Changes destination for this rule. Fixes from_rule links.
-   # If flag set, make the new_dest a source file in any rule
-   # for which the old destination is already set.
-   # No action if there's no change of destination.
-   local ($new_dest, $flag) = @_;
-   local $old_dest = $$Pdest;
-   if ($old_dest eq $new_dest) { return; }
-#   if ( $new_dest =~ /\"/ ) { return; }
-   rdb_remove_generated( $old_dest );
-   rdb_add_generated( $new_dest );
-   if ($flag) {
-      print "rdb_change_dest: fixing dependencies\n";
-      rdb_for_actives( sub{ if ( rdb_file_exists( $rule, $old_dest ) ) {
-                            rdb_ensure_file( $rule, $new_dest );
-                            rdb_remove_files( $rule, $old_dest );
-                        }
-                      }
-                 );
-   }
-   $$Pdest = $new_dest;
-   # ??? Do I need to fix from_rule setting?
-   #&rdb_make_links;
-   return;
-} #END rdb_change_dest
-
-#************************************************************
-
 sub rdb_rule_exists { 
     # Call rdb_rule_exists($rule): Returns whether rule exists.
     my $rule = shift;
@@ -8992,7 +9143,7 @@
     # Assumes rule context.  Update source files of rule to current state.
     rdb_do_files( 
         sub{
-            if ( exists $generated_exts_all{ ext_no_period($file) }
+            if ( exists $generated_exts{ ext_no_period($file) }
                  || exists $$PHdest{$file}
                 ) {
                 &rdb_update1;
@@ -9099,6 +9250,39 @@
 
 sub show_array {
 # For use in diagnostics and debugging. 
+#  On stdout, print line with $_[0] = label.  
+#  Then print rest of @_, one item per line preceeded by some space
+    print "$_[0]\n";
+    shift;
+    if ($#_ >= 0) {
+        foreach (@_){
+           if (defined $_ ) { print "  $_\n"; }
+           else { print "  UNDEF\n"; }
+        }
+    }
+    else { print "  NONE\n"; }
+}
+
+#************************************************************
+
+sub show_hash {
+    my ($msg, $PH ) = @_;
+    print "$msg\n";
+    if (! %$PH ) {
+        print "     NONE\n";
+    }
+    else {
+        while ( my ($key, $value) = each %$PH ) {
+            if (defined $value) { print "  '$key' => '$value'\n"; }
+            else { print "  '$key' => UNDEF\n"; }
+        }
+    }
+}
+
+#************************************************************
+
+sub warn_array {
+#  For use in error messages etc.
 #  On stderr, print line with $_[0] = label.  
 #  Then print rest of @_, one item per line preceeded by some space
     warn "$_[0]\n";
@@ -9253,76 +9437,27 @@
 
 #************************************************************
 
-sub get_mtime_raw
-{ 
-  my $mtime = (stat($_[0]))[9];
-  return $mtime;
+sub get_mtime {
+    # Return mtime of file if it exists, otherwise 0.
+    # 
+    # stat returns an empty array for a non-existent file, and then
+    # accessing an element of the array gives undef.  Use || 0 to replace it
+    # by the desired 0.
+    return ( stat($_[0]) )[9] || 0;
 }
 
 #************************************************************
 
-sub get_mtime { 
-    return get_mtime0($_[0]);
-}
-
-#************************************************************
-
-sub get_mtime0 {
-   # Return time of file named in argument
-   # If file does not exist, return 0;
-   if ( -e $_[0] ) {
-       return get_mtime_raw($_[0]);
-   }
-   else {
-       return 0;
-   }
-}
-
-#************************************************************
-
-sub get_size {
-   # Return time of file named in argument
-   # If file does not exist, return 0;
-   if ( -e $_[0] ) {
-       return get_size_raw($_[0]);
-   }
-   else {
-       return 0;
-   }
-}
-
-#************************************************************
-
-sub get_size_raw
-{ 
-  my $size = (stat($_[0]))[7];
-  return $size;
-}
-
-#************************************************************
-
 sub get_time_size {
-   # Return time and size of file named in argument
-   # If file does not exist, return (0,-1);
-   if ( -e $_[0] ) {
-       return get_time_size_raw($_[0]);
-   }
-   else {
-       return (0,-1);
-   }
+    # Return time and size of file named in argument
+    # If file does not exist, return (0,-1);
+    # Argument _ to stat: use values from previous call, to save disk access..
+    return (   ( ( stat($_[0]) )[9] || 0 ),
+               ( ( stat(_) )[7] || -1 )   );
 }
 
 #************************************************************
 
-sub get_time_size_raw
-{ 
-  my $mtime = (stat($_[0]))[9];
-  my $size = (stat($_[0]))[7];
-  return ($mtime, $size);
-}
-
-#************************************************************
-
 sub processing_time
 {  my ($user, $system, $cuser, $csystem) = times();
    return $user + $system + $cuser + $csystem;
@@ -9332,11 +9467,11 @@
 
 sub get_checksum_md5 {
     my $source = shift;
-    my $input = new FileHandle;
+    my $input;
     my $md5 = Digest::MD5->new;
     my $ignore_pattern = undef;
 
-#warn "======= GETTING MD5: $source\n";
+#print "======= GETTING MD5: $source\n";
     if ( -d $source ) {
         # We won't use checksum for directory
         return 0;
@@ -9369,7 +9504,7 @@
 
 sub create_empty_file {
     my $name = shift;
-    my $h = new FileHandle ">$name"
+    open( my $h, ">", $name )
         or return 1;
     close ($h);
     return 0;
@@ -9491,6 +9626,7 @@
 #************************************************************
 
 sub make_path_mod {
+    # Ensures directory given in $_[0] exists, with error checking
     my $dir = $_[0];
     my $title = $_[1];
     my $ret = 0;
@@ -9498,7 +9634,7 @@
     elsif ( (! -e $dir) && (! -l $dir) ) {
         # N.B. A link pointing to a non-existing target
         # returns false for -e, so we must also check -l
-        warn "$My_name: making $title directory '$dir'\n"
+        print "$My_name: making $title directory '$dir'\n"
             if ! $silent;
         # Error handling from File::Path documentation:
         make_path( $dir, {error => \my $err} );
@@ -9555,7 +9691,7 @@
     open $fh, "$cmd|"
         or die "Cannot open pipe for \"$cmd\"\n";
     while ( <$fh> ) {
-        s/[\r\n]*$//;
+        s/\r?\n$//;
         push @found, $_;
     }
     close $fh;
@@ -9624,36 +9760,82 @@
 ####################################################
 ####################################################
 
-sub add_aux_hook {
-    # Usage: add_aux_hook( sub_name )
-    # Add the name subroutine to the array of hooks for
-    # processing lines of aux files.
-    # The argument is either a string naming the subroutine, e.g.
-    #     add_aux_hook( 'subname' );
-    # or a Perl reference to the subroutine, e.g.,
-    #     add_aux_hook( \&subname );
-    # It is also possible to use an anonymous subroutine, e.g.,
-    #     add_aux_hook( sub{  code of subroutine... } );
-    my ($sub_name) = @_;
-    push @aux_hooks, $sub_name;
+sub add_hook {
+    # Usage: add_book( name of stack, name of orpointer to subroutine )
+    # Return 1 for success, 0 for failure.
+    our %hooks;
+    my ($stack, $routine ) = @_;
+    unless ( exists $hooks{$stack} ) {
+        warn "In add_hook, request to add hook to non-existent stack '$stack'.\n";
+        return 0;
+    }
+
+    my $ref;
+    if ( ref $routine ) {
+        $ref = $routine
+    }
+    elsif ( defined &$routine ) {
+        $ref = \&$routine;
+    }
+    else {
+        warn "In add_hook, no subroutine '$routine' to add to stack '$stack'.\n";
+            return 0;
+    }
+    push @{$hooks{$stack}}, $ref;
+    return 1;
 }
 
-####################################################
+#****************************************************
 
-sub add_latex_file_hook {
-    # Usage: add_latex_file_hook( sub_name )
-    # Add the name subroutine to the array of hooks for
-    # processing list of possible dependency files after a run of *latex.
-    # The argument is either a string naming the subroutine, e.g.
-    #     add_latex_file_hook( 'subname' );
-    # or a Perl reference to the subroutine, e.g.,
-    #     add_latex_file_hook( \&subname );
-    # It is also possible to use an anonymous subroutine, e.g.,
-    #     add_latex_file_hook( sub{  code of subroutine... } );
-    my ($sub_name) = @_;
-    push @latex_file_hooks, $sub_name;
+sub run_hooks {
+    # Usage: run_hooks( stackname, ... )
+    # Call the subroutines whose references on on the named stack.
+    # They are given arguments as follows
+    #   a. If arguments follow the stackname in the call to run_hooks, these
+    #      are given to the called subroutines.
+    #   b. Otherwise a hash of information is given to the called subroutines.
+    # Return 1 for success, 0 for failure.        
+    my $name = shift;
+    my $Pstack = $hooks{$name};
+    my @args = @_;
+    if (!@args) { @args = &info_make; }
+    else { print "Have args\n"; }
+    if (defined $Pstack) {
+        # Do NOT use default $_, as in "for (...) {...}":
+        # The called subroutine may change $_, which is a global variable
+        # (although localized to the for loop and called subroutines).
+        for my $Psub ( @$Pstack) { &$Psub(@args); }
+        return 1;
+    }
+    else {
+        warn "run_hooks: No stack named '$name'\n";
+        return 0;
+    }
 }
 
+#-------------------------------------
+
+sub info_make {
+    my %info_make = (
+        'aux_main'  => $aux_main,
+        'fls_file'  => $fls_name,
+        'log_file'  => $log_name,
+        'root_name' => $root_filename,
+        'tex_file'  => $texfile_name,   
+
+        'aux_dir'   => $aux_dir,
+        'aux_dir1'  => $aux_dir1,
+        'out_dir'   => $out_dir,
+        'out_dir1'  => $out_dir1,
+        );
+    # Rule data, if in rule context:
+    if ($rule)    { $info_make{rule} = $rule; }
+    if ($Pbase)   { $info_make{base} = $$Pbase; }
+    if ($Psource) { $info_make{source} = $$Psource; }
+    if ($Pdest)   { $info_make{dest} = $$Pdest; }
+    return %info_make;
+}
+
 ####################################################
 
 sub set_input_ext {
@@ -9666,9 +9848,7 @@
     # custom dependencies to make the missing file, it will assume that
     # the file has one of the specified extensions.
     my $rule = shift;
-    $input_extensions{$rule} = {};
-    my $Prule = $input_extensions{$rule};
-    foreach (@_) { $$Prule{$_} = 1; }
+    $input_extensions{$rule} = { map { $_ => 1 } @_ };
 }
 
 ####################################################
@@ -9728,6 +9908,16 @@
 
 #************************************************************
 
+# How I use the result of loading glob routines:
+sub my_glob {
+    my @results = ();
+    if ($have_bsd_glob) { @results = bsd_glob( $_[0] ); }
+    else { @results =  glob( $_[0] ); }
+    return @results;
+}
+
+#************************************************************
+
 sub uniq 
 # Read arguments, delete neighboring items that are identical,
 # return array of results
@@ -9847,36 +10037,6 @@
 
 #################################
 
-sub get_filetime_offset {
-    # Usage: get_filetime_offset( prefix, [suffix] )
-    # Measures offset between filetime in a directory and system time
-    # Makes a temporary file of a unique name, and deletes in.
-    # Filename is of form concatenation of prefix, an integer, suffix.
-    # Prefix is normally of form dir/ or dir/tmp.
-    # Default default suffix ".tmp".
-    my $prefix = $_[0];
-    my $suffix = $_[1] || '.tmp';
-    my $tmp_file_count = 0;
-    while (1==1) {
-        # Find a new temporary file, and make it.
-        $tmp_file_count++;
-        my $tmp_file = "${prefix}${tmp_file_count}${suffix}";
-        if ( ! -e $tmp_file ) {
-            open( TMP, ">$tmp_file" ) 
-                or die "$My_name.get_filetime_offset: In measuring filetime offset, couldn't write to\n",
-                       "    temporary file '$tmp_file'\n";
-            my $time = time();
-            close(TMP);
-            my $offset = get_mtime($tmp_file) - $time;
-            unlink $tmp_file;
-            return $offset;
-         }
-     }
-     die "$My_name.get_filetime_offset: BUG TO ARRIVE HERE\n";
-}
-
-#################################
-
 sub tempfile1 {
     # Makes a temporary file of a unique name.  I could use file::temp,
     # but it is not present in all versions of perl.
@@ -9889,9 +10049,9 @@
         $tmp_file_count++;
         my $tmp_file = "${tmpdir}/${prefix}${tmp_file_count}${suffix}";
         if ( ! -e $tmp_file ) {
-            open( TMP, ">$tmp_file" ) 
+            open( my $tmp, ">$tmp_file" ) 
                or next;
-            close(TMP);
+            close($tmp);
             return $tmp_file;
          }
      }
@@ -9912,17 +10072,6 @@
 
 #==================
 
-sub Run_time {
-    # This is wrapper around Run to capture timing information
-    my $time1 = processing_time();
-    my ($pid, $return) = Run($_[0]);
-    my $time = processing_time() - $time1;
-    push @timings, "'$_[0]': time = $time\n"; 
-    return ($pid, $return);
-} #END Run_time
-
-#==================
-
 sub Run {
 # Usage: Run_no_time ("command string");
 #    or  Run_no_time ("one-or-more keywords command string");
@@ -9999,13 +10148,13 @@
     if ( $cmd_line =~ /^internal\s+([a-zA-Z_]\w*)\s+(.*)$/ ) {
         my $routine = $1;
         my @args = parse_quotes( $2 );
-        warn "$My_name: calling $routine( $2 )\n"
+        print "$My_name: calling $routine( $2 )\n"
             if (! $silent);
         return ( 0, &$routine( @args ) );
     }
     elsif ( $cmd_line =~ /^internal\s+([a-zA-Z_]\w*)\s*$/ ) {
         my $routine = $1;
-        warn "$My_name: calling $routine()\n"
+        print "$My_name: calling $routine()\n"
             if (! $silent);
         return ( 0, &$routine() );
     }
@@ -10045,7 +10194,7 @@
 
     my $cmd_line = $_[0];
 
-##    warn "Running '$cmd_line' detached...\n";
+##    print "Running '$cmd_line' detached...\n";
     if ( $cmd_line =~ /^NONE / ) {
         warn "$My_name: ",
              "Program not implemented for this version.  Command line:\n";
@@ -10061,17 +10210,17 @@
     } else {
         # Assume anything else is UNIX or clone
         # For this purpose cygwin behaves like UNIX.
-        ## warn "Run_Detached.UNIX: A\n";
+        ## print "Run_Detached.UNIX: A\n";
         my $pid = fork();
-        ## warn "Run_Detached.UNIX: B pid=$pid\n";
+        ## print "Run_Detached.UNIX: B pid=$pid\n";
         if ( ! defined $pid ) {
-            ## warn "Run_Detached.UNIX: C\n";
+            ## print "Run_Detached.UNIX: C\n";
             warn "$My_name: Could not fork to run the following command:\n";
             warn "   '$cmd_line'\n";
             return (0, 1);
         }
         elsif( $pid == 0 ){
-           ## warn "Run_Detached.UNIX: D\n";
+           ## print "Run_Detached.UNIX: D\n";
            # Forked child process arrives here
            # Insulate child process from interruption by ctrl/C to kill parent:
            #     setpgrp(0,0);
@@ -10083,12 +10232,12 @@
            die "$My_name forked process: could not run the command\n",
                "  '$cmd_line'\n";
         }
-        ##warn "Run_Detached.UNIX: E\n";
+        ##print "Run_Detached.UNIX: E\n";
         # Original process arrives here
         return ($pid, 0);
     }
     # NEVER GET HERE.
-    ##warn "Run_Detached.UNIX: F\n";
+    ##print "Run_Detached.UNIX: F\n";
 } #END Run_Detached
 
 #************************************************************
@@ -10232,7 +10381,7 @@
 
 sub ifcd_popd {
     if ( $do_cd ) {
-        warn "$My_name: Undoing directory change\n"
+        print "$My_name: Undoing directory change\n"
           if !$silent;
         &popd;
     }

Modified: branches/branch2021.final/Master/texmf-dist/doc/man/man1/latexmk.1
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/man/man1/latexmk.1	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/man/man1/latexmk.1	2022-03-17 20:30:35 UTC (rev 62768)
@@ -1,4 +1,4 @@
-.TH LATEXMK 1 "20 November 2021" ""
+.TH LATEXMK 1 "17 March 2022" ""
 .SH NAME
 latexmk \- generate LaTeX document
 .SH SYNOPSIS
@@ -2136,9 +2136,9 @@
 information. Therefore this variable is turned off by default, and
 then files to be deleted are restricted to those explicitly specified
 by patterns configured in the variables \fIclean_ext\fR,
-\fIclean_full_ext\fR, and \fI at generated_exts\fR, together with those
-very standard cases that are hardwired into \fIlatexmk\fR (e.g., .log
-files). 
+\fIclean_full_ext\fR, and \fI at generated_exts\fR.  Standard cases (e.g., .log
+files) appear in \fIlatexmk\fR's initial value for the array
+\fI at generated_exts\fR. 
 .TP
 .B $cleanup_mode [0]
 If nonzero, specifies cleanup mode: 1 for full cleanup, 2 for cleanup
@@ -2169,13 +2169,21 @@
 pythontex-files-FOO/*, where FOO stands for the basename of the file
 being processed (as in FOO.tex).
 
-The files to be deleted are relative to the directory specified by
-\fI$aux_dir\fR.  (Note that if \fI$out_dir\fR but not \fI$aux_dir\fR
-is set, then in its initialization, \fIlatexmk\fR sets \fI$aux_dir\fR
-equal to \fI$out_dir\fR.  A normal situation is therefore that \fI$aux_dir\fR
-equals \fI$out_dir\fR, which is the only case supported by
-TeXLive, unlike MiKTeX.)
+Most of the files to be deleted are relative to the directory specified by
+\fI$aux_dir\fR.  Note that if \fI$out_dir\fR but not \fI$aux_dir\fR is
+set, then in its initialization, \fIlatexmk\fR sets \fI$aux_dir\fR equal to
+\fI$out_dir\fR.  A normal situation is therefore that \fI$aux_dir\fR equals
+\fI$out_dir\fR, which is the only case directly supported by TeXLive,
+unlike MiKTeX.  Note that even with TeXLive latexmk does now support
+different values for the directories -- see the explanation of the
+\fI$emulate_aux variable.
 
+If \fI$out_dir\fR and \fI$aux_dir\fR different, latexmk actually deletes
+any files of the specified names in both \fI$aux_dir\fR and \fI$out_dir\fR;
+this is because under certain error conditions, the files may be put in
+\fI$out_dir\fR instead of \fI$aux_dir\fR.  This also handles the case of
+deleting any fls file, since that file is in \fI$out_dir\fR.
+
 The filenames specified for a clean-up operation can refer not only to
 regular files but also to directories.  Directories are only deleted
 if they are empty.  An example of an application is to pythontex, which
@@ -2184,7 +2192,11 @@
 
     $clean_ext = "pythontex-files-%R pythontex-files-%R";
 
-See also the variable \fI at generated_exts\fR.
+See also the (array) variable \fI at generated_exts\fR.  In the past, this
+variable had certain uses beyond that of \fI$clean_ext\fR.  But now, they
+accomplish the same things.  In fact, after initialization including the
+processing of command line options, \fIlatexmk\fR simply appends the list
+of extensions in \fI$clean_ext\fR to the array \fI at generated_exts\fR.
 .TP
 .B $clean_full_ext [""]
 Extra extensions of files for \fIlatexmk\fR to remove when the \fB-C\fR
@@ -2522,29 +2534,38 @@
 If nonzero, continue processing past minor \fIlatex\fR errors 
 including unrecognized cross references.  Equivalent to specifying the
 \fB-f\fR option.
+
 .TP
-.B @generated_exts [( "aux", "bbl", "idx", "ind", "lof", "lot", "out", "toc", $fdb_ext )]
+.B @generated_exts [( 'aux', 'bcf', 'fls', 'idx', 'ind', 'lof', 'lot', 'out', 'toc', 'blg', 'ilg', 'log', 'xdv' )]
+
 This contains a list of extensions for files that are generated during
-a LaTeX run and that are read in by LaTeX in later runs, either
-directly or indirectly. 
+processing, and that should be deleted during a main clean up operation, as
+invoked by the command line option \fB-c\fR.  (The use of \fB-C\fR or
+\fB-gg\fR gives this clean up and more.)  
 
-This list specifies files known to be generated by \fI*latex\fR.
-It is used in two ways:
-(a) The specified files are deleted in a cleanup operation (with the
-\fB-c\fR, \fB-C\fR, \fB-CA\fR, \fB-g\fR and \fB-gg\fR options), and
-(b) It affects the determination of whether a rerun of *latex is
-needed after a run that gives an error. 
+The default values are extensions for standard files generated by 
+*latex, bibtex, and the like.  (Note that the clean up also deletes the
+fdb_latexmk file, but that's separately coded into latexmk, currently.)
 
-(Concerning item (b): Normally, a change of a source file during a run
-should provoke a rerun.  This includes a file generated by LaTeX,
-e.g., an aux file, that is read in on subsequent runs.  But after a
-run that results in an error, a new run should not occur until the
-user has made a change in the files.  But the user may have corrected
-an error in a source .tex file during the run.  So \fIlatexmk\fR needs
-to distinguish user-generated and automatically generated files; it
-determines the automatically generated files as those with extensions
-in the list in @generated_exts.)
+After initialization of latexmk and the processing of its command line, the
+items in \fIclean_ext\fR are appended to \fI at generated_exts\fR.  So these
+two variables have the same meaning (contrary to older versions of
+latexmk).
 
+The items in \fI at generated_exts\fR are normally extensions of files, whose
+base name is the same as the main tex file.  But it is also possible to
+specify patterns including that basename --- see the explanation of the
+variable \fI$clean_ext\fR.   
+
+In addition to specifying files to be deleted in a clean up, latexmk uses
+the same specification to assist its examination of changes in source
+files: Under some situations it needs to find those changes in files (since
+a previous run) that are expected to be due to the user editing a file.
+This contrasts with the cases of files that are generated by some program
+run by latexmk and that differ from the results of the previous run.  This
+use of \fI at generated_exts\fR is normally unimportant, given the usual
+accuracy of latexmk's other ways of determining these generated files.
+
 A convenient way to add an extra extension to the list, without losing
 the already defined ones is to use a push command in the line in an
 RC file.  E.g.,
@@ -2553,7 +2574,8 @@
 
 adds the extension "end" to the list of predefined generated
 extensions.  (This extension is used by the RevTeX package, for
-example.) 
+example.)
+
 .TP
 .B $go_mode [0]
 If nonzero, process files regardless of timestamps, and is then
@@ -3825,7 +3847,7 @@
   set_tex_cmds( CMD_SPEC );
 
 Here CMD_SPEC is the command line without the program name. This
-results in \fI$latex = 'CMD_SPEC'\fR, and similarly for
+results in \fI$latex = 'latex CMD_SPEC'\fR, and similarly for
 \fI$pdflatex\fR, \fI$lualatex\fR, and \fI$xelatex\fR. An example would
 be 
 
@@ -3996,7 +4018,7 @@
 harvested too easily.)
 .SH AUTHOR
 Current version, by John Collins 
-(Version 4.76).
+(Version 4.77).
 Report bugs etc to his e-mail (jcc8 at psu.edu).
 
 Released version can be obtained from CTAN:

Modified: branches/branch2021.final/Master/texmf-dist/doc/man/man1/latexmk.man1.pdf
===================================================================
(Binary files differ)

Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/CHANGES
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/CHANGES	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/CHANGES	2022-03-17 20:30:35 UTC (rev 62768)
@@ -789,3 +789,18 @@
   Improve some diagnostics.
   Add /etc to list of locations for system rc files (with Unix-like OSs).
 
+From v. 4.76 to 4.77
+  Clean up and improvements in warnings etc
+  Ensured systematic use of STDOUT and STDERR, to more or less match that
+    of  *tex: STDOUT for progress messages, and, normally, errors and
+    warnings caused by the compilation of a document.  STDERR is for
+    within-latexmk errors etc: incorrect command line, configuration errors
+    etc.  
+  Internal improvements and bug fixes.
+  Correctly handle non-ASCII filenames, UTF-8 coding of log files etc,
+    including on MS Wndows, and including correct parsing of wrapped
+    lines in log files.  Adjust method of unwrapping of wrapped lines in
+    log file according to whether latex/pdflatex, lualatex or xelatex is
+    used, thereby reducing misparses of information in log file.
+  Reinstate Windows batch file for running latexmk, now called latexmk.cmd.
+

Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/INSTALL
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/INSTALL	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/INSTALL	2022-03-17 20:30:35 UTC (rev 62768)
@@ -1,6 +1,6 @@
             INSTALLING latexmk
             ==================
-      (Version 4.76, 20 Nov. 2021)
+      (Version 4.77, 17 Mar. 2022)
 
             John Collins
             Physics Department
@@ -43,40 +43,36 @@
     documents to be compiled and processed.
 
 
-!!!!  IMPORTANT NOTE:  !!!!
-===========================
+!!!!  IMPORTANT NOTES:  !!!!
+============================
 
-If you have installed a modern distribution of TeX and friends, you
-may find that latexmk is already installed on your computer.  This is
-true for full installations of TeXLive 2009 or later on the operating
-systems it supports.  (Note that MacTeX on OS-X incorporates TeXLive,
-so anything said about TeXLive also applies to MacTeX.)  If you have
-only installed a subset of packages, e.g., because you installed
-BasicTeX, then the subset may not include latexmk; in that case you
-should be able to use your distribution's package manager to install
-latexmk.  This is generally the recommended method; only use the
-manual installation method below if you have a special need for it.
-However, you should still examine the information on configuration
-here and in the main documentation to get latexmk working exactly as
-you want it.
+1. If you have installed a distribution of TeX and friends, you will
+probably find that latexmk is already installed on your computer.  This
+applies to both the TeXLive and the MiKTeX distributions (Note that MacTeX
+on OS-X incorporates TeXLive, so anything said about TeXLive also applies
+to MacTeX.)  If you have only installed a subset of packages, e.g., because
+you installed BasicTeX, then the subset may or may not include latexmk; in
+that case you should be able to use your distribution's package manager to
+install latexmk.  Having latexmk installed by a TeX distribution is
+normally the recommended way to be able to use latexmk.
 
-You can test whether latexmk is already properly installed by trying
-the command "latexmk -v" from the command line.  If this succeeds,
-then latexmk is already installed.  Otherwise, if you are using
-TeXLive or MacTeX, then you can simply use its package manager to get
-latexmk installed, the same as for any other missing package.
+2. The only extra requirement beyond having latexmk installed is to have an
+installation of Perl. See above.
 
-If you are on MS-Windows and you are using TeXLive (2009, or later),
-this distribution also includes a distribution of Perl sufficient to
-run latexmk.pl, so you don't need to install Perl separately.  It also
-includes an executable file latexmk.exe that runs latexmk.
+3. You will normally need to use the manual installation method below if
+you have a special need for it.  However, you should still examine the
+information on configuration below and in the main documentation to get
+latexmk working exactly as you want it.
 
-In the case of MiKTeX, the other standard distribution for MS-Windows,
-the main difference from TeXLive as regards latexmk is that you may
-need to install a distribution of Perl. A standard default
-installation of Perl should enable latexmk to work.
+4. You can test whether latexmk is already properly installed by trying the
+command "latexmk -v" from the command line.  If this succeeds, then latexmk
+is already installed and will report its version number.  Otherwise, if you
+are using TeXLive or MacTeX, then you can simply use its package manager to
+get latexmk installed, the same as for any other missing package.
 
-BUT, you may need to configure latexmk to
+BUT, you may need to configure latexmk to adjust its behavior to suit your
+needs. See item 6 below, as well as the full documentation, for further
+information.
 
 
 **Manual** installation on UNIX/LINUX/OS-X
@@ -84,12 +80,13 @@
 
 (Power users can modify these as appropriate, of course.)
 
-NOTE: If you are using TeXLive 2009 or later, you can install latexmk
-simply by using the TeXLive package manager (that includes users of
-MacTeX).  In fact, depending on how much of TeXLive you have already
-installed, latexmk may already have been installed.  In that case you don't
-normally need to bother with the manual installation explained below.
-Still you may need to examine the configuration instructions see item 6.
+NOTE: If you are using TeXLive 2009 or later, or a moderately recent
+version of MiKTeX, you can install latexmk simply by using the TeXLive
+package manager (that includes users of MacTeX).  In fact, depending on how
+much of TeXLive or MiKTeX you have already installed, latexmk may already
+have been installed.  In that case you don't normally need to bother with
+the manual installation explained below.  Still you may need to examine the
+configuration instructions see item 6.
 
 1.  Make sure you have working installations of Perl and TeX/LaTeX.
 
@@ -98,8 +95,11 @@
     /usr/local/bin.  But if you are an ordinary user, you can put the
     file somewhere where you have access, and ensure that the PATH
     environment variable includes the directory where latexmk is
-    installed.  
+    installed.
 
+    If you are using MS-Windows, go to the corresponding items in the
+    instructions for Windows.
+
 3.  Rename this file to latexmk.
 
 4.  Make sure latexmk is executable, e.g., by using chmod suitably.
@@ -141,13 +141,15 @@
     If latexmk does not get one of more of these commands correct, put an
     override in a startup file:
 
-    a.  For a system-wide installation, the correction should be in the
+    a.  For a system-wide installation, the correction can be in the
         system startup file, which on a UNIX-like operating system is any
         one of
         
+           /etc/LatexMk,
            /opt/local/share/latexmk/LatexMk,
            /usr/local/share/latexmk/LatexMk,
            /usr/local/lib/latexmk/LatexMk,
+           /etc/latexmkrc,
            /opt/local/share/latexmk/latexmkrc,
            /usr/local/share/latexmk/latexmkrc,
            /usr/local/lib/latexmk/latexmkrc.
@@ -161,9 +163,8 @@
         Cygwin, latexmk combines both the MS-Windows and the Unix
         possibilities.)
 
-    b.  If you are installing latexmk as an ordinary user, the startup
-        file is the user startup file, which is the file .latexmkrc in
-        your home directory.
+    b.  You can also/instead put the configuration lines in the user
+        startup file, which is the file .latexmkrc in your home directory.
 
         (Under normal circumstances, latexmk's definition of home
         directory under Unix-like operating systems is the usual one,
@@ -232,35 +233,49 @@
 MiKTeX's package manager.  But to allow latexmk to work, you will also
 need to install a distribution of Perl if you haven't done so already.
 
+In either of these cases you don't normally need to bother with the manual
+installation explained below.  Still you may need to examine the
+configuration instructions see item 6.
+
+
 1.  Make sure you have working installations of Perl and TeX/LaTeX,
     complete with viewers for dvi, postscript and/or pdf files.  You will
-    also need whatever packages your document needs.
+    also need whatever packages your document needs.  
 
 2.  If necessary, unpack the latexmk distribution.  
 
 3.  **Difference compared with UNIX-type systems**: Copy the file
-    latexmk.pl to a suitable directory (your choice), and arrange for it to
-    be invoked as a command.  (If you don't know how to do this, find out
-    about "executable extension for perl on windows", by a web search.)
+    latexmk.pl to a suitable directory and arrange for it to be invoked as
+    a command.  See the following sentences for what "suitable directory"
+    means. One way to ensure that you can invoke the latexmk command is to
+    also put the file latexmk.cmd in the same directory, and then follow
+    the next instructions:
 
-4.  If the directory in the previous step is NOT already in the search
-    path for executable files, arrange for this, by adjusting the
-    environment variable PATH suitably.
+    If the directory in the previous step is NOT already in the search path
+    for executable files, arrange for this, by adjusting the environment
+    variable PATH suitably.  In Windows, there is a Control Panel setting
+    for this.  (It should be under Advanced system settings->Environment
+    variables.)  Log out and back in to make sure the changed setting gets
+    used.
 
-    In Windows, there is a Control Panel setting for this.  (Should be
-    under Advanced system settings->Environment variables.)
+    Note: Each of TeXLive and MiKTeX make a suitable change to the PATH
+    environment variable, so that all the programs they install are
+    usable, including latexmk.
 
-5.  (Optional) Copy documentation file(s) to a suitable directory.  The
-    only requirement on the directory is your convenience: some convenient
-    place to look up documentation. The relevant files are latexmk.txt
-    which is a pure ASCII text file, and latexmk.pdf which is a postscript
-    file.  
-
-6.  You may need to reboot, or at least logoff and log back in, if you made
+4.  You may need to reboot, or at least logoff and log back in, if you made
     any changes to PATH.
 
-7.  Test out the installation at the command-line prompt:
+5.  Concerning invocation of latexmk:  See later items.
 
+6.  (Optional) Copy documentation file(s) to a suitable directory.  The
+    only requirement on the directory is your convenience: i.e., some
+    convenient place to look up documentation. The relevant files are
+    latexmk.txt which is a pure ASCII text file, and latexmk.pdf which is a
+    postscript file.
+
+7.  Test out the installation at the command-line prompt (cmd.exe or Power
+    Shell): 
+
     a. First do
 
             latexmk --version
@@ -292,20 +307,22 @@
        Also LOOK AT THE SECTION NAMED "TRICKY POINTS" below to see some
        hints. 
 
-
 8.  If the commands used by latexmk are incorrect, see the UNIX
     installation instructions for what to do.  The only changes needed
     from the UNIX instructions are: 
 
-    a.  The system initialization file is C:\latexmk\LatexMk.  (If
-        this is not suitable for some reason, you'll need to change
-        the latexmk.pl file where this filename appears.)
+    a.  The system initialization file is either C:\latexmk\LatexMk or
+        C:\latexmk\latexmkrc.  (If these is not suitable for some reason,
+        you'll need to change the latexmk.pl file where this filename
+        appears.  But normally it's easier to change the user latexmkrc
+        file --- see the next item.)
 
     b.  The user initialization file is .latexmkrc in the directory
-        specified by the environment variable HOME.  If there is no HOME
-        variable, then the file is in the directory specified by the
-        environment variable USERPROFILE, which should have been set
-        by the MS-Windows operating system at login.
+        specified by the environment variable HOME, if that happens to be
+        defined, which it normally isn't.  If there is no HOME variable,
+        then the file is in the directory specified by the environment
+        variable USERPROFILE, which should have been set by the MS-Windows
+        operating system at login.
 
 
        
@@ -320,35 +337,40 @@
 
 Tricky points
 =============
+(These aren't so much issues about installation as about use of latexmk.)
 
-1.  BEWARE of filenames with double extensions, for example,
-    two.part.tex.  The behavior of TeX-related software is not
-    consistent in this situation.  You may, for example, find a log
-    file named two.log or two.part.log, depending on which version of
-    which implementation of TeX/LaTeX you use.  Naturally, there is a
-    possibility in this situation that latexmk will get confused, and
-    not recognize, for example, that a dvi file has been generated.
-    Latexmk has configuration variables to deal with some of the
-    possibilities, so you could try playing with them --- see the
-    code.  But it general, it is best to avoid such double extensions:
-    they make your files non-portable.  Do something like two-part.tex
-    or two_part.tex instead.
+1.  BEWARE of filenames with double extensions, for example, two.part.tex.
+    The behavior of TeX-related software is not consistent in this
+    situation.  You may, for example, find a log file named two.log or
+    two.part.log, depending on which version of which implementation of
+    TeX/LaTeX you use.  Naturally, there is a possibility in this situation
+    that latexmk will get confused, and not recognize, for example, that a
+    dvi or other file has been generated.  Latexmk has configuration
+    variables to deal with some of the possibilities, so you could try
+    playing with them --- see the code.  But it general, it is best to
+    avoid such double extensions: they make your files non-portable.  Do
+    something like two-part.tex or two_part.tex instead.
 
-2.  The same goes for filenames and directory names with spaces in
-    them.  Much software tends to interpret spaces as separators
-    between different filenames or between filenames and other text.
-    This can cause problems in some of the programs called by latexmk.
-    It can also cause problems when latexmk parses a .log file to
-    determine dependency information.  Latexmk does try to correctly
-    treat filenames with spaces, as do current implementations of the
-    TeX program.
+2.  Filenames and directory names with spaces in them can potentially cause
+    problems.  Much software tends to interpret spaces as separators
+    between different filenames or between filenames and other text.  This
+    coul cause problems in some of the programs called by latexmk.
 
-3.  Beware also of files and directories whose names contain non-ASCII
-    characters.  There are some tricky problems because of mismatches
-    between character codings as used by different software and
-    operating systems.  Latexmk tries to do its best, but problems can
-    arise.  Often things work without trouble.
+    Even so, file and directory names containing spaces generally cause no
+    problems in both latexmk and the programs it calls.
 
+3.  Non-ASCII characters in file and directory names: In the current
+    version of latexmk and current TeXLive and MiKTeX, these are generally
+    handled correctly, particular on linux and macOS systems.
+
+    But it is worth being aware there is a potential for problems: (a) Default
+    installations of MS-Windows do not make all Unicode characters in
+    filenames available to Perl and hence latexmk.  (b) Some annoying
+    issues may arise if you transfer files from a macOS HFS+ volume to a
+    volume used by another operating system for use with that OS.  These
+    problems concern different ways of normalizing filenames containing
+    accented characters, and may entail renaming the transferred files.
+
 4.  If you need to remake documentation files, e.g., latexmk.pdf or
     latexmk.txt, from the man page file latexmk.1, the following
     commands work (on my linux and OS-X systems at least):
@@ -378,7 +400,7 @@
 
 The current version is by John Collins (username jcc8 at node
 psu.edu) -- other contact details at the top.  It is copyright
-1998-2019 by John Collins, and the previous authors; see the copyright
+1998-2022 by John Collins, and the previous authors; see the copyright
 notice in the latexmk.pl file, which gives permission to use, copy,
 modify, and distribute this software and its documentation under the
 terms of the GNU Public License v. 2.

Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/README
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/README	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/README	2022-03-17 20:30:35 UTC (rev 62768)
@@ -1,5 +1,5 @@
-Latexmk, version 4.76, 20 Nov 2021
----------------------------------
+Latexmk, version 4.77, 17 Mar 2022
+----------------------------------
 
 Latexmk completely automates the process of generating a LaTeX
 document.  Essentially, it is a highly specialized cousin of the
@@ -10,19 +10,18 @@
 be set to run continuously with a previewer; the latex program, etc,
 are rerun whenever one of the source files is modified.
 
-Latexmk automatically determines file dependencies from the LaTeX .log
-file.  It features: a fully reliable algorithm for deciding how many
-times to run latex and related programs, automatic detection of
-dependent files, the ability to generate pdf files using pdflatex or
-via dvi or postscript files, and the continuous-preview mode.  For
-bibliographies, the current version now supports biber as well as the
+Latexmk automatically determines file dependencies from the LaTeX .fls,
+.log, and .aux files.  It features: a fully reliable algorithm for deciding
+how many times to run latex and related programs, automatic detection of
+dependent files, the ability to generate pdf files using pdflatex or via
+dvi or postscript files, and the continuous-preview mode.  For
+bibliographies, the current version supports biber as well as the
 traditional bibtex.  Which of bibtex or biber to use is determined
-automatically.
+automatically. 
 
-Please read the man page (or the corresponding text or postscript file) for
-details of what latexmk does and what all the features are.  A copy of the
-fast help that can be seen by running "latexmk -h" is at the end of this
-file.
+Please read the man page (or the corresponding text or pdf file) for
+details of what latexmk does and what all the features are.  A list of
+available command-line options is available by running 'latexmk --help'.
 
 Latexmk is a perl script.  It is licensed under the GNU General Public
 License v. 2.
@@ -40,8 +39,7 @@
             http://www.personal.psu.edu/jcc8/
             username jcc8 at node psu.edu
 
-The start of the script file has copyright notices and disclaimers.  It
-also has a modification history for those who are interested.
+The start of the script file has copyright notices and disclaimers.  
 
 NOTES:-
 
@@ -63,172 +61,3 @@
    under development.
 
 John Collins
----------------------------- "latexmk -h" ----------------------------
-Latexmk 4.76: Automatic LaTeX document generation routine
-
-Usage: latexmk [latexmk_options] [filename ...]
-
-  Latexmk_options:
-   -aux-directory=dir or -auxdir=dir 
-                 - set name of directory for auxiliary files (aux, log)
-                 - Currently this only works with MiKTeX
-   -bibtex       - use bibtex when needed (default)
-   -bibtex-      - never use bibtex
-   -bibtex-cond  - use bibtex when needed, but only if the bib file exists
-   -bibtex-cond1 - use bibtex when needed, but only if the bib file exists;
-                   on cleanup delete bbl file only if bib file exists
-   -bibfudge or -bibtexfudge - change directory to output directory when running bibtex
-   -bibfudge- or -bibtexfudge- - don't change directory when running bibtex
-   -bm <message> - Print message across the page when converting to postscript
-   -bi <intensity> - Set contrast or intensity of banner
-   -bs <scale> - Set scale for banner
-   -commands  - list commands used by latexmk for processing files
-   -c     - clean up (remove) all nonessential files, except
-            dvi, ps and pdf files.
-            This and the other clean-ups are instead of a regular make.
-   -C     - clean up (remove) all nonessential files
-            including aux, dep, dvi, postscript and pdf files
-            and file of database of file information
-   -CA     - clean up (remove) all nonessential files.
-            Equivalent to -C option.
-   -CF     - Remove file of database of file information before doing 
-            other actions
-   -cd    - Change to directory of source file when processing it
-   -cd-   - Do NOT change to directory of source file when processing it
-   -dependents or -deps - Show list of dependent files after processing
-   -dependents- or -deps- - Do not show list of dependent files
-   -deps-out=file - Set name of output file for dependency list,
-                    and turn on showing of dependency list
-   -dF <filter> - Filter to apply to dvi file
-   -dir-report  - Before processing a tex file, report aux and out dir settings
-   -dir-report- - Before processing a tex file, do not report aux and out dir settings
-   -dvi   - generate dvi
-   -dvi-  - turn off required dvi
-   -e <code> - Execute specified Perl code (as part of latexmk start-up
-               code)
-   -emulate-aux-dir  - emulate -aux-directory option for *latex
-   -emulate-aux-dir- - use -aux-directory option with *latex
-   -f     - force continued processing past errors
-   -f-    - turn off forced continuing processing past errors
-   -gg    - Super go mode: clean out generated files (-CA), and then
-            process files regardless of file timestamps
-   -g     - process at least one run of all rules
-   -g-    - Turn off -g and -gg
-   -h     - print help
-   -help - print help
-   -indexfudge or -makeindexfudge - change directory to output directory when running makeindex
-   -indexfudge- or -makeindexfudge- - don't change directory when running makeindex
-   -jobname=STRING - set basename of output file(s) to STRING.
-            (Like --jobname=STRING on command line for many current
-            implementations of latex/pdflatex.)
-   -l     - force landscape mode
-   -l-    - turn off -l
-   -latex=<program> - set program used for latex.
-                      (replace '<program>' by the program name)
-   -latexoption=<option> - add the given option to the *latex command
-   -logfilewarninglist or -logfilewarnings 
-               give list of warnings after run of *latex
-   -logfilewarninglist- or -logfilewarnings- 
-               do not give list of warnings after run of *latex
-   -lualatex     - use lualatex for processing files to pdf
-                   and turn dvi/ps modes off
-   -M     - Show list of dependent files after processing
-   -MF file - Specifies name of file to receives list dependent files
-   -MP    - List of dependent files includes phony target for each source file.
-   -makeindexfudge - change directory to output directory when running makeindex
-   -makeindexfudge-- don't change directory to output directory when running makeindex
-   -MSWinBackSlash  under MSWin use backslash (\) for directory separators
-                    for filenames given to called programs
-   -MSWinBackSlash-  under MSWin use forward slash (/) for directory separators
-                     for filenames given to called programs
-   -new-viewer    - in -pvc mode, always start a new viewer
-   -new-viewer-   - in -pvc mode, start a new viewer only if needed
-   -nobibtex      - never use bibtex
-   -nobibfudge or -nobibtexfudge - don't change directory when running bibtex
-   -nodependents  - Do not show list of dependent files after processing
-   -noemulate-aux-dir - use -aux-directory option with *latex
-   -noindexfudge or -nomakeindexfudge - don't change directory when running makeindex
-   -norc          - omit automatic reading of system, user and project rc files
-   -output-directory=dir or -outdir=dir
-                  - set name of directory for output files
-   -output-format=FORMAT
-                  - if FORMAT is dvi, turn on dvi output, turn off others
-                  - if FORMAT is pdf, turn on pdf output, turn off others
-                  - otherwise error
-   -pdf   - generate pdf by pdflatex
-   -pdfdvi - generate pdf by dvipdf
-   -pdflatex=<program> - set program used for pdflatex.
-                      (replace '<program>' by the program name)
-   -pdflualatex=<program> - set program used for lualatex.
-                      (replace '<program>' by the program name)
-   -pdfps - generate pdf by ps2pdf
-   -pdflua - generate pdf by lualatex
-   -pdfxe - generate pdf by xelatex
-   -pdfxelatex=<program> - set program used for xelatex.
-                      (replace '<program>' by the program name)
-   -pdf-  - turn off pdf
-   -ps    - generate postscript
-   -ps-   - turn off postscript
-   -pF <filter> - Filter to apply to postscript file
-   -p     - print document after generating postscript.
-            (Can also .dvi or .pdf files -- see documentation)
-   -pretex=<TeX code> - Sets TeX code to be executed before inputting source
-                    file, if commands suitable configured
-   -print=dvi     - when file is to be printed, print the dvi file
-   -print=ps      - when file is to be printed, print the ps file (default)
-   -print=pdf     - when file is to be printed, print the pdf file
-   -pv    - preview document.  (Side effect turn off continuous preview)
-   -pv-   - turn off preview mode
-   -pvc   - preview document and continuously update.  (This also turns
-                on force mode, so errors do not cause latexmk to stop.)
-            (Side effect: turn off ordinary preview mode.)
-   -pvc-  - turn off -pvc
-   -pvctimeout    - timeout in pvc mode after period of inactivity
-   -pvctimeout-   - don't timeout in pvc mode after inactivity
-   -pvctimeoutmins=<time> - set period of inactivity (minutes) for pvc timeout
-   -quiet    - silence progress messages from called programs
-   -r <file> - Read custom RC file
-               (N.B. This file could override options specified earlier
-               on the command line.)
-   -rc-report  - After initialization, report names of rc files read
-   -rc-report- - After initialization, do not report names of rc files read
-   -recorder - Use -recorder option for *latex
-               (to give list of input and output files)
-   -recorder- - Do not use -recorder option for *latex
-   -rules    - Show list of rules after processing
-   -rules-   - Do not show list of rules after processing
-   -showextraoptions  - Show other allowed options that are simply passed
-               as is to latex and pdflatex
-   -silent   - silence progress messages from called programs
-   -stdtexcmds - Sets standard commands for *latex
-   -time     - show CPU time used
-   -time-    - don't show CPU time used
-   -use-make - use the make program to try to make missing files
-   -use-make- - don't use the make program to try to make missing files
-   -usepretex - Sets commands for *latex to use extra code before inputting
-                source file
-   -usepretex=<TeX code> - Equivalent to -pretex=<TeX code> -usepretex
-   -v        - display program version
-   -verbose  - display usual progress messages from called programs
-   -version      - display program version
-   -view=default - viewer is default (dvi, ps, pdf)
-   -view=dvi     - viewer is for dvi
-   -view=none    - no viewer is used
-   -view=ps      - viewer is for ps
-   -view=pdf     - viewer is for pdf
-   -Werror   - treat warnings from called programs as errors
-   -xelatex      - use xelatex for processing files to pdf
-                   and turn dvi/ps modes off
-
-   filename = the root filename of LaTeX document
-
--p, -pv and -pvc are mutually exclusive
--h, -c and -C override all other options.
--pv and -pvc require one and only one filename specified
-All options can be introduced by '-' or '--'.  (E.g., --help or -help.)
- 
-In addition, latexmk recognizes many other options that are passed to
-latex and/or pdflatex without interpretation by latexmk.  Run latexmk
-with the option -showextraoptions to see a list of these
-
-Report bugs etc to John Collins <jcc8 at psu.edu>.

Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/asymptote_latexmkrc
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/asymptote_latexmkrc	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/asymptote_latexmkrc	2022-03-17 20:30:35 UTC (rev 62768)
@@ -48,8 +48,7 @@
 
 sub asy2x   {
    my $ret = system("asy -vv -f '$_[1]' '$_[0]' >& '$_[0].log'");
-   my $FH = new FileHandle;
-   open $FH, "$_[0].log";
+   open( my $FH, "<", "$_[0].log" );
    %imp = ();
 
    while (<$FH>) {

Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/chapterbib-latexmkrc
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/chapterbib-latexmkrc	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/chapterbib-latexmkrc	2022-03-17 20:30:35 UTC (rev 62768)
@@ -26,11 +26,17 @@
     if ( $base_bare eq $root ) {
         print "--- Will run bibtex on modified '$root.aux' file\n";
         my $aux_mod_base = $base."-mod";
-        local $out_fh = new FileHandle "> $aux_mod_base$ext";
+
+        # Open output (modified aux file) here rather than in fix_aux, and
+        # make the relevant variables local.  This is instead opening both
+        # files in fix_aux itself.  The reason: fix_aux calls itself
+        # recursively, but must always write to the same file.
+        open( local $out_fh, ">", $aux_mod_base$ext );
         if (!$out_fh) { die "Cannot write to '$aux_mod_base$ext'\n"; }
         local $level = 0;
         fix_aux( $source );
         close $out_fh;
+
         # Override source, dest, and basenames, since they are to have the path given
         # in the arguments to this subroutine, instead of the path given in the
         # corresponding names in the rule.  Latexmk may change directory before
@@ -51,7 +57,7 @@
    # removing \bibdata and \bibstyle lines that were in included .aux files.
    my $aux_file = $_[0];
    print "Processing '$aux_file'\n";
-   my $aux_fh = new FileHandle $aux_file;
+   open( my $aux_fh, "<", $aux_file );
    if (!$aux_fh) { die "$My_name: Couldn't read aux file '$aux_file'\n"; }
    $level++;
    while (<$aux_fh>) {

Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/clean_pattern_latexmkrc
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/clean_pattern_latexmkrc	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/clean_pattern_latexmkrc	2022-03-17 20:30:35 UTC (rev 62768)
@@ -2,7 +2,7 @@
 # extension or something containing %R.
 # This is done by overriding latexmk's cleanup1 subroutine.
 
-# Here is an example of a usefule application:
+# Here is an example of a useful application:
 $clean_ext = "*-eps-converted-to.pdf";
 
 sub cleanup1 {

Added: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/dot2tex-latexmkrc
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/dot2tex-latexmkrc	                        (rev 0)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/dot2tex-latexmkrc	2022-03-17 20:30:35 UTC (rev 62768)
@@ -0,0 +1,175 @@
+# ================ Customization for dot2tex: ================================
+
+push @generated_exts, '%R-dot2tex-fig*.tex', '%R-dot2tex-fig*.dot',
+                      '%R-dot2tex-fig*.dot2texopts';
+add_cus_dep( 'dot', 'tex', 0, 'dot2tex' );
+
+# Fancy: prefix string for each *latex by "internal" mylatex and basename of tex file
+#foreach my $name ( 'latex', 'pdflatex', 'lualatex', 'xelatex' ) {
+#   ${$name} = "internal mylatex %B ". ${$name};
+#}
+
+$latex    = 'internal mylatex %B latex %O %S';
+$lualatex = 'internal mylatex %B lualatex %O %S';
+$pdflatex = 'internal mylatex %B pdflatex %O %S';
+$xelatex  = 'internal mylatex %B xelatex %O %S';
+
+
+#---------------------------------
+
+sub dot2tex {
+    # Context for a dot2tex custom dependency assumed.
+
+    # Default options:
+    my $opts = '--figonly -fpgf -tmath';
+
+    # File that contains the option string. (Written after analysis of the
+    # log file for the previous *latex run.)  
+    my $opt_file = "$_[0].dot2texopts";
+
+    # Ensure that it is known as a source file of this rule, since some
+    # changes in the main .tex could affect the options only, but not the
+    # contents of the .dot file
+    rdb_ensure_file( $rule, $opt_file );
+
+    if ( -e $opt_file && open( my $fh, '<', $opt_file ) ) {
+        $opts = <$fh>;
+        close $opt_file;
+    }
+    else { warn "dot2tex: Cannot open '$opt_file'\n"; }
+    
+    my @cmd = ( 'dot2tex', split(/\s+/, $opts), '-o', $$Pdest, $$Psource );
+    print "dot2tex command line to execute:\n ", join( ' ', @cmd), "\n";
+    return system @cmd;
+}
+
+#---------------------------------
+
+sub mylatex {
+    # Context for a *latex rule assumed.
+    # Run *latex as specified in my arguments, and then process the log file
+    # to deal with dot2tex conversions needed by the dot2texi package.
+
+    my ($base, @cmd) = @_;
+    my $log_name = "$aux_dir1$base.log";
+
+    my $return = system @cmd;
+    &examine_log_for_dot2tex( $log_name );
+    return $return;
+}
+
+#---------------------------------
+
+sub examine_log_for_dot2tex {
+   # Context for a *latex rule assumed.
+   # From the log file given in the argument to this subroutine,
+   # find places where dot2tex would be invoked if *latex were used with
+   # the -shell-escape option.  This invocation is on .dot files created
+   # by the dot2texi package.
+   # Find the basename of the .dot and .tex files (all assumed to be
+   # relative to the aux dir).  (Basename includes a possible path
+   # component.) 
+   # Ensure that for each .dot file the .tex file is in the source file of
+   # the current rule, so that latexmk will know to make a corresponding
+   # custom dependency.
+   # Put the option string in a file where the custom dependency for the
+   # dot-to-tex conversion can find it.
+
+   my $log_name = $_[0];
+
+   # Map of basenames_with_relative_path of dot/tex file to option string
+   my %found = ();
+
+   open( my $log_fh, '<', $log_name )
+      or ( warn( "examine_log_for_dot2tex: Can't read '$log_name'\n" ),
+           return
+         );
+LINE:
+   while (my $line = <$log_fh> ) {
+       # Aim: find lines of form runsystem\(dot2tex followed by options
+       #      followed by "-o file.tex file.dot)", for some value of file.
+       #      Allow for continuation lines.
+       # Often use /.../x with x option to regex, to get space in pattern
+       # ignored, for readability
+
+       # Ignore lines with wrong start:
+       if ( $line !~ /^runsystem\(dot2tex \s+ (.*)$/x ) { next; }
+
+       # Rest of command line (after dot2tex) is in $1.
+       my $args = $1;
+
+       # Only keep going if arguments begin with options and have -o (for
+       # output file):
+       if ( $args !~ /(-.*) \s+ -o \s+ (.*) $/x ) {
+          next LINE;
+       }
+
+       # Putative options for command, then source and dest file:
+       my ($opts, $file_part) = ($1, $2);
+       # Remove superfluous space:
+       $opts =~ s/\s+/ /g;
+       $opts =~ s/\s*$//;
+       if ( $opts !~ /^(-\S+\s*)*$/x ) {
+          warn "Putative options for dot2tex in '$opts' aren't options\n";
+          next LINE;
+       }
+       my $attempts = 0;
+
+CONT_LINE:
+       while ($attempts < 2) {
+           $attempts++;
+           if ($file_part =~ /^(.+) \.tex \s+ \1 \.dot\)/x ) {
+               ($found{$1} = $opts) =~ s/\s+/ /g;
+               last CONT_LINE;
+           }
+           if (length($line) >= 80) {
+              if (eof($log_fh)) { last LINE; }
+              $file_part .= <$log_fh>;
+              # Remove trailing new line characters:
+              $file_part =~ s/[\n\r]$//;
+           }
+           else { last CONT_LINE; }
+       }
+   }
+   close $log_fh;
+
+   my @missing_files = ();
+   while (my ($base, $opts) = each %found) {
+       my $dot = "$aux_dir1$base.dot";
+       my $tex = "$aux_dir1$base.tex";
+       # File to save options for dot2tex command, so cusdep can read them:
+       my $opt_file = "$aux_dir1$base.dot2texopts";
+
+       write_to_file( $opt_file, "$opts\n" );
+       if (! -e $tex) { push @missing_files, $tex; }
+   }
+   if (@missing_files) {
+       # No-file lines for missing .tex files will tell latexmk to try
+       # to find a cusdep to make them:
+       append_to_file( $log_name, map("No file $_.\n", @missing_files) );
+   }
+}
+
+#---------------------------------
+
+sub write_to_file {
+  # Usage: write_to_file( name, items to write )
+  my $file = shift;
+  open( my $fh, ">", $file )
+    or (warn "Cannot write to '$file'\n", return 0 );
+  print $fh @_;
+  close( $fh );
+}
+
+#---------------------------------
+
+sub append_to_file {
+  # Usage: append_to_file( name, items to write )
+  my $file = shift;
+  open( my $fh, ">>", $file )
+    or (warn "Cannot append to '$file'\n", return 0 );
+  print $fh @_;
+  close( $fh );
+}
+
+#---------------------------------

Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/exceltex_latexmkrc
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/exceltex_latexmkrc	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/exceltex_latexmkrc	2022-03-17 20:30:35 UTC (rev 62768)
@@ -44,7 +44,7 @@
     # changes, and to do this before running latex/pdflatex again.
 
     # First find dependency/ies on .xls files, by parsing the .excltx file,
-    my $Hsource = new FileHandle;
+    my $Hsource;
     my %xls = ();
     my $source = "$_[0].excltx";
     if (! open $Hsource, "<$source") {

Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/fix-aux.latexmkrc
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/fix-aux.latexmkrc	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/fix-aux.latexmkrc	2022-03-17 20:30:35 UTC (rev 62768)
@@ -3,7 +3,11 @@
 # option.  (Of the standard distributions, MiKTeX supports -aux-directory,
 # but TeXLive does not.)
 
+# !!!IMPORTANT: THIS CONFIGURATION IS NO LONGER NECESSARY. From V. 4.74b onwards,
+#    latexmk can handle the aux_dir isssue itself --- see the documentation on the
+#    $emulate_aux variable.
 
+
 foreach my $cmd ('latex', 'lualatex', 'pdflatex', 'xelatex' ) {
     ${$cmd} = "internal latex_fix_aux $cmd %O %S";
 }

Added: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/glossaries_latexmkrc
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/glossaries_latexmkrc	                        (rev 0)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/glossaries_latexmkrc	2022-03-17 20:30:35 UTC (rev 62768)
@@ -0,0 +1,39 @@
+# This shows how to use the glossaries package
+# (http://www.ctan.org/pkg/glossaries) and the glossaries-extra package
+# (http://www.ctan.org/pkg/glossaries-extra) with latexmk.
+
+# N.B. There is also the OBSOLETE glossary package
+# (http://www.ctan.org/pkg/glossary), which has some differences.  See item 2.
+
+# 1. If you use the glossaries or the glossaries-extra package, then you can use:
+
+   add_cus_dep( 'acn', 'acr', 0, 'makeglossaries' );
+   add_cus_dep( 'glo', 'gls', 0, 'makeglossaries' );
+   $clean_ext .= " acr acn alg glo gls glg";
+
+   sub makeglossaries {
+        my ($base_name, $path) = fileparse( $_[0] );
+        my @args = ( "-q", "-d", $path, $base_name );
+        if ($silent) { unshift @args, "-q"; }
+        return system "makeglossaries", "-d", $path, $base_name; 
+    }
+
+# 2. The above will tend to run makeglossaries more often than needed, since
+#    each out of date file will trigger the use of makeglossaries, even
+#    though makeglossaries makes all the glossaries.  The following solution
+#    solves this, but at the expense of not having the convenience that
+#    makeglossaries can change how it makes the glossaries depending on the
+#    settings of the glossaries package.
+#    A better solution will need more advanced work.
+#
+#   add_cus_dep( 'acn', 'acr', 0, 'makeglossaries' );
+#   add_cus_dep( 'glo', 'gls', 0, 'makeglossaries' );
+#   $clean_ext .= " acr acn alg glo gls glg";
+#
+#   sub makeglossaries {
+#       my @args = ( "-s", "$_[0].ist", "-t", "$$Psource.ilg",
+#                    "-o", $$Pdest, $$Psource );
+#       if ($silent) { unshift @args, "-q"; }
+#       return system "makeindex", @args;
+#   }
+

Deleted: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/glossary_latexmkrc
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/glossary_latexmkrc	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/glossary_latexmkrc	2022-03-17 20:30:35 UTC (rev 62768)
@@ -1,44 +0,0 @@
-# This shows how to use the glossaries package
-# (http://www.ctan.org/pkg/glossaries) and the glossaries-extra package
-# (http://www.ctan.org/pkg/glossaries-extra) with latexmk.
-
-# N.B. There is also the OBSOLETE glossary package
-# (http://www.ctan.org/pkg/glossary), which has some differences.  See item 2.
-
-# 1. If you use the glossaries or the glossaries-extra package, then you use:
-
-   add_cus_dep( 'acn', 'acr', 0, 'makeglossaries' );
-   add_cus_dep( 'glo', 'gls', 0, 'makeglossaries' );
-   $clean_ext .= " acr acn alg glo gls glg";
-   sub makeglossaries {
-      my ($base_name, $path) = fileparse( $_[0] );
-      pushd $path;
-      my $return = system "makeglossaries", $base_name;
-      popd;
-      return $return;
-   }
-
-
-# 2. If you use the OBSOLETE glossary package, then you can do the following:
-#    (Note that the code lines are commented out to avoid trouble when this
-#    file is simply copied into a latexmkrc or this file is arranged to be
-#    read by latexmk, and one of the modern packages glossaries and
-#    glossaries-extra is used.)
-
-   ## For the main glossary:
-   #add_cus_dep( 'glo', 'gls', 0, 'makeglo2gls' );
-   #sub makeglo2gls {
-   #    system("makeindex -s \"$_[0].ist\" -t \"$_[0].glg\" -o \"$_[0].gls\" \"$_[0].glo\"" );
-   #}
-
-   ## For acronyms:
-   ## 
-   ## ===> WARNING: The code below is ONLY FOR PACKAGE glossary, NOT FOR
-   ##      glossaries and glossaries-extra. In the current glossaries and
-   ##      glossaries-extra packages the roles of the .acr and .acn files are
-   ##      exchanged compared with the old glossary package.  Hence the the
-   ##      code below will fail with the more modern packages.
-   #add_cus_dep( 'acr', 'acn', 0, 'makeacr2acn' );
-   #sub makeacr2acn {
-   #    system( "makeindex -s \"$_[0].ist\" -t \"$_[0].alg\" -o \"$_[0].acn\" \"$_[0].acr\"" );
-   #}

Added: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/minted_latexmkrc
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/minted_latexmkrc	                        (rev 0)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/minted_latexmkrc	2022-03-17 20:30:35 UTC (rev 62768)
@@ -0,0 +1,38 @@
+# For the minted package (which does nice formatting of source code):
+#
+# 1. Need to use -shell-escape on *latex command.
+# 2. Need to arrange passing of the output dir (actually aux dir if it
+#    differs from out dir) to minted.  Then this directory information does
+#    not have to be specified  in the .tex file itself.
+# 3. In some cases, latexmk does an extra run of *latex than is
+#    needed.  This is solved by getting latexmk to ignore certain lines in
+#    the aux file when latexmk looks for changes.  These lines are written
+#    by minted and are irrelevant to the output file from *latex.
+#
+#    The reason for the extra run of *latex that may happen is because
+#    after minted runs pygmentize to make the nicely formatted source code,
+#    minted saves cached information about the run(s) of pygmentize. This
+#    information is  put in the aux file. So latexmk sees the changed aux
+#    file, and knows that may affect the output of *latex, which it
+#    therefore reruns. However the minted-written lines do not affect the
+#    output of *latex.
+#
+# The method works if the aux dir's name contains a string of MORE than one 
+# space That's a problem in minted's calls to pygmentize.
+# Single spaces in the name are OK.
+# Generally it helps to  use only aux_dir and out_dir names  without spaces,
+# to avoid trouble. 
+
+&set_tex_cmds( '-shell-escape %O '
+        . '\'\PassOptionsToPackage{outputdir={%Y}}{minted}\input{%S}\''
+        );
+# (Here the outer level of single quotes is for Perl.  The dot is for
+# Perl's string concatenation. The \' tell Perl to put actual single
+# quotes in the string (given to the shell).  In Unix, the shell is sh (or
+# equivalent), so the string inside the single quotes is a single argument
+# to the command is not changed at all.) 
+#
+$hash_calc_ignore_pattern{aux} = '^\\\\gdef\\\\minted at oldcachelist\{,'.
+                                 '|^\s*default\.pygstyle,'.
+                                 '|^\s*[[:xdigit:]]+\.pygtex';
+

Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/pythontex-latexmkrc
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/pythontex-latexmkrc	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/example_rcfiles/pythontex-latexmkrc	2022-03-17 20:30:35 UTC (rev 62768)
@@ -21,7 +21,7 @@
    my $result_dir = $aux_dir1."pythontex-files-$$Pbase";
    my $ret = Run_subst( $pythontex, 2 );
    rdb_add_generated( glob "$result_dir/*" );
-   my $fh = new FileHandle $$Pdest, "r";
+   open( my $fh, "<", $$Pdest );
    if ($fh) {
       while (<$fh>) {
          if ( /^%PythonTeX dependency:\s+'([^']+)';/ ) {

Added: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.cmd
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.cmd	                        (rev 0)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.cmd	2022-03-17 20:30:35 UTC (rev 62768)
@@ -0,0 +1,24 @@
+Rem This batch file is only of interest to a small subset of **Windows** users.
+
+Rem Under modern TeX distributions, MiKTeX and TeXLive, you do **NOT**
+Rem need this batch file.  Both distributions have a latexmk executable
+Rem that correctly runs the latexmk Perl script itself.  This file
+Rem is only useful if you need to bypass that for some reason, e.g.,
+Rem if you have not upgraded to a current year's TeXLive, but want to
+Rem run the latest version of latexmk.
+Rem You may have to modify you copy of this file for your needs.
+
+Rem ==============================
+
+Rem This batch file executes perl so as to run latexmk.pl.  As written it
+Rem assumes that latexmk.pl is in a directory in the
+Rem environment variable PATH.  Of course this file latexmk.cmd should
+Rem itself also have been copied to a directory in PATH.
+Rem
+Rem In addition, this file assumes that perl.exe is in a directory in PATH.
+Rem If not, you should replace 'perl' by the full pathname of the perl
+Rem executable, e.g., 'C:\perl\bin\perl.exe' or
+Rem 'C:\Strawberry\perl\bin\perl.exe.  (Current distributions of Perl
+Rem for Windows do set PATH appropriately when installed in the default way.
+
+perl -S latexmk.pl %*


Property changes on: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.cmd
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.pdf
===================================================================
(Binary files differ)

Modified: branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.txt
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.txt	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/doc/support/latexmk/latexmk.txt	2022-03-17 20:30:35 UTC (rev 62768)
@@ -61,7 +61,7 @@
 
 
 
-                               20 November 2021                              1
+                                 17 March 2022                               1
 
 
 
@@ -127,7 +127,7 @@
 
 
 
-                               20 November 2021                              2
+                                 17 March 2022                               2
 
 
 
@@ -193,7 +193,7 @@
 
 
 
-                               20 November 2021                              3
+                                 17 March 2022                               3
 
 
 
@@ -259,7 +259,7 @@
 
 
 
-                               20 November 2021                              4
+                                 17 March 2022                               4
 
 
 
@@ -325,7 +325,7 @@
 
 
 
-                               20 November 2021                              5
+                                 17 March 2022                               5
 
 
 
@@ -391,7 +391,7 @@
 
 
 
-                               20 November 2021                              6
+                                 17 March 2022                               6
 
 
 
@@ -457,7 +457,7 @@
 
 
 
-                               20 November 2021                              7
+                                 17 March 2022                               7
 
 
 
@@ -523,7 +523,7 @@
 
 
 
-                               20 November 2021                              8
+                                 17 March 2022                               8
 
 
 
@@ -589,7 +589,7 @@
 
 
 
-                               20 November 2021                              9
+                                 17 March 2022                               9
 
 
 
@@ -655,7 +655,7 @@
 
 
 
-                               20 November 2021                             10
+                                 17 March 2022                              10
 
 
 
@@ -721,7 +721,7 @@
 
 
 
-                               20 November 2021                             11
+                                 17 March 2022                              11
 
 
 
@@ -787,7 +787,7 @@
 
 
 
-                               20 November 2021                             12
+                                 17 March 2022                              12
 
 
 
@@ -853,7 +853,7 @@
 
 
 
-                               20 November 2021                             13
+                                 17 March 2022                              13
 
 
 
@@ -919,7 +919,7 @@
 
 
 
-                               20 November 2021                             14
+                                 17 March 2022                              14
 
 
 
@@ -985,7 +985,7 @@
 
 
 
-                               20 November 2021                             15
+                                 17 March 2022                              15
 
 
 
@@ -1051,7 +1051,7 @@
 
 
 
-                               20 November 2021                             16
+                                 17 March 2022                              16
 
 
 
@@ -1117,7 +1117,7 @@
 
 
 
-                               20 November 2021                             17
+                                 17 March 2022                              17
 
 
 
@@ -1183,7 +1183,7 @@
 
 
 
-                               20 November 2021                             18
+                                 17 March 2022                              18
 
 
 
@@ -1249,7 +1249,7 @@
 
 
 
-                               20 November 2021                             19
+                                 17 March 2022                              19
 
 
 
@@ -1315,7 +1315,7 @@
 
 
 
-                               20 November 2021                             20
+                                 17 March 2022                              20
 
 
 
@@ -1381,7 +1381,7 @@
 
 
 
-                               20 November 2021                             21
+                                 17 March 2022                              21
 
 
 
@@ -1447,7 +1447,7 @@
 
 
 
-                               20 November 2021                             22
+                                 17 March 2022                              22
 
 
 
@@ -1513,7 +1513,7 @@
 
 
 
-                               20 November 2021                             23
+                                 17 March 2022                              23
 
 
 
@@ -1579,7 +1579,7 @@
 
 
 
-                               20 November 2021                             24
+                                 17 March 2022                              24
 
 
 
@@ -1645,7 +1645,7 @@
 
 
 
-                               20 November 2021                             25
+                                 17 March 2022                              25
 
 
 
@@ -1711,7 +1711,7 @@
 
 
 
-                               20 November 2021                             26
+                                 17 March 2022                              26
 
 
 
@@ -1777,7 +1777,7 @@
 
 
 
-                               20 November 2021                             27
+                                 17 March 2022                              27
 
 
 
@@ -1843,7 +1843,7 @@
 
 
 
-                               20 November 2021                             28
+                                 17 March 2022                              28
 
 
 
@@ -1909,7 +1909,7 @@
 
 
 
-                               20 November 2021                             29
+                                 17 March 2022                              29
 
 
 
@@ -1975,7 +1975,7 @@
 
 
 
-                               20 November 2021                             30
+                                 17 March 2022                              30
 
 
 
@@ -2041,7 +2041,7 @@
 
 
 
-                               20 November 2021                             31
+                                 17 March 2022                              31
 
 
 
@@ -2107,7 +2107,7 @@
 
 
 
-                               20 November 2021                             32
+                                 17 March 2022                              32
 
 
 
@@ -2173,7 +2173,7 @@
 
 
 
-                               20 November 2021                             33
+                                 17 March 2022                              33
 
 
 
@@ -2239,7 +2239,7 @@
 
 
 
-                               20 November 2021                             34
+                                 17 March 2022                              34
 
 
 
@@ -2305,7 +2305,7 @@
 
 
 
-                               20 November 2021                             35
+                                 17 March 2022                              35
 
 
 
@@ -2371,7 +2371,7 @@
 
 
 
-                               20 November 2021                             36
+                                 17 March 2022                              36
 
 
 
@@ -2437,7 +2437,7 @@
 
 
 
-                               20 November 2021                             37
+                                 17 March 2022                              37
 
 
 
@@ -2503,7 +2503,7 @@
 
 
 
-                               20 November 2021                             38
+                                 17 March 2022                              38
 
 
 
@@ -2514,9 +2514,9 @@
 
               files to be deleted are restricted to those explicitly specified
               by    patterns    configured   in   the   variables   clean_ext,
-              clean_full_ext, and @generated_exts, together  with  those  very
-              standard  cases  that  are  hardwired  into  latexmk (e.g., .log
-              files).
+              clean_full_ext, and @generated_exts.  Standard cases (e.g., .log
+              files)  appear  in latexmk's initial value for the array @gener-
+              ated_exts.
 
        $cleanup_mode [0]
               If nonzero, specifies cleanup mode: 1 for full  cleanup,  2  for
@@ -2548,44 +2548,57 @@
               figures*.log,  and  pythontex-files-FOO/*,  where FOO stands for
               the basename of the file being processed (as in FOO.tex).
 
-              The files to be deleted are relative to the directory  specified
-              by  $aux_dir.   (Note  that if $out_dir but not $aux_dir is set,
-              then in its  initialization,  latexmk  sets  $aux_dir  equal  to
-              $out_dir.   A normal situation is therefore that $aux_dir equals
-              $out_dir, which is the only case supported  by  TeXLive,  unlike
-              MiKTeX.)
+              Most of the files to be deleted are relative  to  the  directory
+              specified  by  $aux_dir.  Note that if $out_dir but not $aux_dir
+              is set, then in its initialization, latexmk sets $aux_dir  equal
+              to  $out_dir.   A  normal  situation  is therefore that $aux_dir
+              equals $out_dir, which is the only case  directly  supported  by
+              TeXLive,  unlike  MiKTeX.   Note  that even with TeXLive latexmk
+              does now support different values for the directories -- see the
+              explanation of the $emulate_aux variable.
 
+              If $out_dir and $aux_dir different, latexmk actually deletes any
+              files of the specified names in both $aux_dir and $out_dir; this
+              is  because under certain error conditions, the files may be put
+              in $out_dir instead of $aux_dir.  This also handles the case  of
+              deleting any fls file, since that file is in $out_dir.
+
               The  filenames  specified for a clean-up operation can refer not
               only to regular files but also to directories.  Directories  are
               only deleted if they are empty.  An example of an application is
-              to pythontex, which creates files  in  a  particular  directory.
-              You  can  arrange  to remove both the files and the directory by
-              setting
 
-                  $clean_ext = "pythontex-files-%R pythontex-files-%R";
 
-              See also the variable @generated_exts.
 
+                                 17 March 2022                              39
 
 
 
-                               20 November 2021                             39
 
 
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
 
 
+              to pythontex, which creates files  in  a  particular  directory.
+              You  can  arrange  to remove both the files and the directory by
+              setting
 
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+                  $clean_ext = "pythontex-files-%R pythontex-files-%R";
 
+              See also the (array) variable  @generated_exts.   In  the  past,
+              this  variable  had certain uses beyond that of $clean_ext.  But
+              now, they accomplish the same things.  In fact,  after  initial-
+              ization  including  the  processing of command line options, la-
+              texmk simply appends the list of extensions in $clean_ext to the
+              array @generated_exts.
 
        $clean_full_ext [""]
-              Extra extensions of files for latexmk to remove when the -C  op-
-              tion  is  selected, i.e., extensions of files to remove when the
+              Extra  extensions of files for latexmk to remove when the -C op-
+              tion is selected, i.e., extensions of files to remove  when  the
               .dvi, etc files are to be cleaned-up.
 
               More general patterns are allowed, as for $clean_ext.
 
-              The files specified by $clean_full_ext to be deleted  are  rela-
+              The  files  specified by $clean_full_ext to be deleted are rela-
               tive to the directory specified by $out_dir.
 
 
@@ -2592,75 +2605,75 @@
        $compiling_cmd [""], $failure_cmd [""], $warning_cmd [""], $success_cmd
        [""]
 
-              These variables specify commands that are  executed  at  certain
-              points  of  compilations.  One motivation for their existence is
-              to allow very useful convenient visual indications  of  compila-
-              tion  status even when the window receiving the screen output of
-              the compilation is hidden.  This is particularly useful in  pre-
+              These  variables  specify  commands that are executed at certain
+              points of compilations.  One motivation for their  existence  is
+              to  allow  very useful convenient visual indications of compila-
+              tion status even when the window receiving the screen output  of
+              the  compilation is hidden.  This is particularly useful in pre-
               view-continuous mode.
 
-              The  commands  are  executed  at  the following points: $compil-
-              ing_cmd at the start of compilation, $success_cmd at the end  of
-              a  completely successful compilation, $failure_cmd at the end of
+              The commands are executed  at  the  following  points:  $compil-
+              ing_cmd  at the start of compilation, $success_cmd at the end of
+              a completely successful compilation, $failure_cmd at the end  of
               an unsuccessful compilation, $warning_cmd at the of an otherwise
               successful compilation that gives warnings about undefined cita-
               tions or references or about multiply defined references. If any
-              of  above  variables  is  undefined or blank (the default situa-
+              of above variables is undefined or  blank  (the  default  situa-
               tion), then the corresponding command is not executed.
 
-              However, when $warning_cmd is not set, then in  the  case  of  a
-              compilation  with  warnings  about  references or citations, but
-              with no other error, one or  other  of  $success_cmd  or  $fail-
-              ure_cmd  is  used  (if  it  is  set) according to the setting of
+              However,  when  $warning_cmd  is  not set, then in the case of a
+              compilation with warnings about  references  or  citations,  but
+              with  no  other  error,  one  or other of $success_cmd or $fail-
+              ure_cmd is used (if it is  set)  according  to  the  setting  of
               $warnings_as_errors.
 
               An example of a simple setting of these variables is as follows
 
-                  $compiling_cmd = "xdotool search  --name  \"%D\"  set_window
+                  $compiling_cmd  =  "xdotool  search --name \"%D\" set_window
               --name \"%D compiling\"";
-                  $success_cmd    =  "xdotool  search --name \"%D\" set_window
-              --name \"%D OK\"";
-                  $warning_cmd   = "xdotool search --name \"%D\" ".
-                                   "set_window --name \"%D CITE/REF ISSUE\"";
-                  $failure_cmd   = "xdotool search  --name  \"%D\"  set_window
-              --name \"%D FAILURE\"";
+                  $success_cmd   = "xdotool search  --name  \"%D\"  set_window
 
-              These  assume  that  the  program xdotool is installed, that the
-              previewer is using an X-Window system for display, and that  the
-              title  of the window contains the name of the displayed file, as
-              it normally does.  When the commands are  executed,  the  place-
-              holder  string  %D  is  replaced  by the name of the destination
-              file, which is the previewed file.  The above commands result in
-              an  appropriate  string  being  appended  to the filename in the
 
 
+                                 17 March 2022                              40
 
-                               20 November 2021                             40
 
 
 
 
-
 LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
 
 
-              window title: " compiling", " OK", or " FAILURE".
+              --name \"%D OK\"";
+                  $warning_cmd   = "xdotool search --name \"%D\" ".
+                                   "set_window --name \"%D CITE/REF ISSUE\"";
+                  $failure_cmd    =  "xdotool  search --name \"%D\" set_window
+              --name \"%D FAILURE\"";
 
-              Other placeholders that can be used are %S, %T, and %R, with  %S
-              and  %T normally being identical. These can be useful for a com-
-              mand changing the title of the edit window. The  visual  indica-
-              tion  in a window title can useful, since the user does not have
-              to keep shifting attention to the (possibly hidden)  compilation
+              These assume that the program xdotool  is  installed,  that  the
+              previewer  is using an X-Window system for display, and that the
+              title of the window contains the name of the displayed file,  as
+              it  normally  does.   When the commands are executed, the place-
+              holder string %D is replaced by  the  name  of  the  destination
+              file, which is the previewed file.  The above commands result in
+              an appropriate string being appended to the filename in the win-
+              dow title: " compiling", " OK", or " FAILURE".
+
+              Other  placeholders that can be used are %S, %T, and %R, with %S
+              and %T normally being identical. These can be useful for a  com-
+              mand  changing  the title of the edit window. The visual indica-
+              tion in a window title can useful, since the user does not  have
+              to  keep shifting attention to the (possibly hidden) compilation
               window to know the status of the compilation.
 
-              More  complicated  situations  can best be handled by defining a
-              Perl subroutine to invoke the necessary commands, and using  the
-              "internal"  keyword  in the definitions to get the subroutine to
+              More complicated situations can best be handled  by  defining  a
+              Perl  subroutine to invoke the necessary commands, and using the
+              "internal" keyword in the definitions to get the  subroutine  to
               be invoked.  (See the section "Format of Command Specifications"
               for how to do this.)
 
-              Naturally,  the  above  settings that invoke the xdotool program
-              are only applicable when the X-Window system  is  used  for  the
+              Naturally, the above settings that invoke  the  xdotool  program
+              are  only  applicable  when  the X-Window system is used for the
               relevant window(s).  For other cases, you will have to find what
               software solutions are available.
 
@@ -2669,15 +2682,15 @@
               Custom dependency list -- see section on "Custom Dependencies".
 
        @default_excluded_files [()]
-              When latexmk is invoked with no files specified on  the  command
+              When  latexmk  is invoked with no files specified on the command
               line, then, by default, it will process all files in the current
               directory with the extension .tex.  (In general, it will process
               the files specified in the @default_files variable.)
 
               But sometimes you want to exclude particular files from this de-
-              fault list.  In that case you can specify the excluded files  in
+              fault  list.  In that case you can specify the excluded files in
               the array @default_excluded_files.  For example if you wanted to
-              process all .tex files with the exception of  common.tex,  which
+              process  all  .tex files with the exception of common.tex, which
               is a not a standard alone LaTeX file but a file input by some or
               all of the others, you could do
 
@@ -2685,40 +2698,40 @@
 
                    @default_excluded_files = ("common.tex");
 
-              If you have a variable or large number of files to be processed,
-              this method saves you from having to list them in detail in @de-
-              fault_files and having to update the list every time you  change
-              the set of files to be processed.
 
-              Notes:  1.  This variable has no effect except when no files are
-              specified on the latexmk command line.  2. Wildcards are allowed
-              in @default_excluded_files.
 
-       @default_files [("*.tex")]
-              Default list of files to be processed.
 
-              If  no  filenames  are  specified  on  the command line, latexmk
+                                 17 March 2022                              41
 
 
 
-                               20 November 2021                             41
 
 
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
 
 
+              If you have a variable or large number of files to be processed,
+              this method saves you from having to list them in detail in @de-
+              fault_files  and having to update the list every time you change
+              the set of files to be processed.
 
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+              Notes: 1. This variable has no effect except when no  files  are
+              specified on the latexmk command line.  2. Wildcards are allowed
+              in @default_excluded_files.
 
+       @default_files [("*.tex")]
+              Default list of files to be processed.
 
-              processes all tex files specified in  the  @default_files  vari-
-              able,  which by default is set to all tex files ("*.tex") in the
-              current directory.  This is a convenience: just run latexmk  and
-              it  will process an appropriate set of files.  But sometimes you
+              If no filenames are specified on the command line, latexmk  pro-
+              cesses  all  tex files specified in the @default_files variable,
+              which by default is set to all tex files ("*.tex") in  the  cur-
+              rent  directory.  This is a convenience: just run latexmk and it
+              will process an appropriate set of  files.   But  sometimes  you
               want only some of these files to be processed.  In this case you
-              can  list the files to be processed by setting @default_files in
-              an initialization file (e.g., the file "latexmkrc" in  the  cur-
-              rent  directory).  Then if no files are specified on the command
-              line then the files you specify by  setting  @default_files  are
+              can list the files to be processed by setting @default_files  in
+              an  initialization  file (e.g., the file "latexmkrc" in the cur-
+              rent directory).  Then if no files are specified on the  command
+              line  then  the  files you specify by setting @default_files are
               processed.
 
               Three examples:
@@ -2729,55 +2742,54 @@
 
                    @default_files = ("*.tex", "*.dtx");
 
-              Note  that more than file may be given, and that the default ex-
+              Note that more than file may be given, and that the default  ex-
               tension is ".tex".  Wild cards are allowed.  The parentheses are
               because @default_files is an array variable, i.e., a sequence of
               filename specifications is possible.
 
-              If you want latexmk to process all .tex files with a few  excep-
+              If  you want latexmk to process all .tex files with a few excep-
               tions, see the @default_excluded_files array variable.
 
        $dependents_phony [0]
-              If  a  list  of dependencies is output, this variable determines
-              whether to include a phony target for each source file.  If  you
-              use  the  dependents  list  in  a Makefile, the dummy rules work
-              around errors make gives if you remove header files without  up-
+              If a list of dependencies is output,  this  variable  determines
+              whether  to include a phony target for each source file.  If you
+              use the dependents list in a  Makefile,  the  dummy  rules  work
+              around  errors make gives if you remove header files without up-
               dating the Makefile to match.
 
        $dependents_list [0]
-              Whether  to  display  a  list(s) of dependencies at the end of a
+              Whether to display a list(s) of dependencies at  the  end  of  a
               run.
 
        $deps_file ["-"]
-              Name of file to receive list(s) of dependencies at the end of  a
-              run,  to be used if $dependesnt_list is set.  If the filename is
-              "-", then the dependency list is set to stdout  (i.e.,  normally
-              the screen).
+              Name  of file to receive list(s) of dependencies at the end of a
+              run, to be used if $dependesnt_list is set.  If the filename  is
 
 
-       $do_cd [0]
-              Whether  to  change working directory to the directory specified
-              for the main source file before processing it.  The default  be-
-              havior  is  not to do this, which is the same as the behavior of
-              *latex programs.  This variable is set by the -cd and  -cd-  op-
-              tions on latexmk's command line.
 
-       $dvi_filter [empty]
-              The  dvi  file  filter  to be run on the newly produced dvi file
+                                 17 March 2022                              42
 
 
 
-                               20 November 2021                             42
 
 
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
 
 
+              "-",  then  the dependency list is set to stdout (i.e., normally
+              the screen).
 
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
 
+       $do_cd [0]
+              Whether to change working directory to the  directory  specified
+              for  the main source file before processing it.  The default be-
+              havior is not to do this, which is the same as the  behavior  of
+              *latex  programs.   This variable is set by the -cd and -cd- op-
+              tions on latexmk's command line.
 
-              before other processing.  Equivalent to specifying the  -dF  op-
-              tion.
+       $dvi_filter [empty]
+              The dvi file filter to be run on the newly produced dvi file be-
+              fore other processing.  Equivalent to specifying the -dF option.
 
        $dvi_mode [See below for default]
               If  nonzero, generate a dvi version of the document.  Equivalent
@@ -2818,6 +2830,18 @@
 
                    $dvipdf = "dvipdfm %O -o %D %S";
 
+
+
+
+                                 17 March 2022                              43
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               WARNING: The default dvipdf  script  generates  pdf  files  with
               bitmapped fonts, which do not look good when viewed by acroread.
               That script should be modified to give  dvips  the  options  "-P
@@ -2830,18 +2854,6 @@
               silent switch has no effect, but is actually innocuous.  But  if
               an  alternative program is used, e.g., dvipdfmx, then the silent
               switch has an  effect.   The  default  setting  is  correct  for
-
-
-
-                               20 November 2021                             43
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               dvipdfm and dvipdfmx.
 
        $dvips ["dvips %O -o %D %S"]
@@ -2883,31 +2895,31 @@
                   4 => run a command to do the update.  The command is  speci-
               fied by the variable $dvi_update_command.
 
-              See  information on the variable $pdf_update_method for an exam-
-              ple of updating by command.
+              See  information  on  the  variable  $pdf_update_method  for  an
 
-       $dvi_update_signal [Under UNIX: SIGUSR1, which  is  a  system-dependent
-       value]
-              The  number of the signal that is sent to the dvi viewer when it
-              is updated by sending a signal -- see  the  information  on  the
-              variable  $dvi_update_method.   The default value is the one ap-
-              propriate for xdvi on a UNIX system.
 
-       $emulate_aux [0]
-              Whether to emulate the use of aux_dir when $aux_dir and $out_dir
-              are  different,  rather than using the -aux-directory option for
 
+                                 17 March 2022                              44
 
 
-                               20 November 2021                             44
 
 
 
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
 
 
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+              example of updating by command.
 
+       $dvi_update_signal [Under UNIX: SIGUSR1, which  is  a  system-dependent
+       value]
+              The  number of the signal that is sent to the dvi viewer when it
+              is updated by sending a signal -- see  the  information  on  the
+              variable  $dvi_update_method.   The default value is the one ap-
+              propriate for xdvi on a UNIX system.
 
+       $emulate_aux [0]
+              Whether to emulate the use of aux_dir when $aux_dir and $out_dir
+              are  different,  rather than using the -aux-directory option for
               the  *latex  programs.   (MiKTeX  supports  -aux-directory,  but
               TeXLive doesn't.)
 
@@ -2950,6 +2962,18 @@
               the program was started. If the  modification  time  is  earlier
               than  when the program was started, the file is a leftover file,
               which latexmk treats as if it were not created.  If the filetime
+
+
+
+                                 17 March 2022                              45
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               is  at least the program start time, then it can be assumed that
               the file was created in the current run.
 
@@ -2962,18 +2986,6 @@
               (a second or so, or a few seconds).  But even a small difference
               can mess up latexmk's test.
 
-
-
-
-                               20 November 2021                             45
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               Latexmk measures the time difference between the time on the two
               systems and compensates for this.  But  the  measurement  (in  a
               system-independent way) is only accurate to a second or two.  So
@@ -3003,35 +3015,23 @@
               ing unrecognized cross references.  Equivalent to specifying the
               -f option.
 
-       @generated_exts [( aux , bbl , idx , ind , lof , lot  ,  out  ,  toc  ,
-       $fdb_ext )]
-              This  contains a list of extensions for files that are generated
-              during a LaTeX run and that are read in by LaTeX in later  runs,
-              either directly or indirectly.
 
-              This  list  specifies files known to be generated by *latex.  It
-              is used in two ways: (a) The specified files are  deleted  in  a
-              cleanup  operation  (with  the -c, -C, -CA, -g and -gg options),
-              and (b) It affects the determination of whether a rerun of  *la-
-              tex is needed after a run that gives an error.
+       @generated_exts [( 'aux', 'bcf', 'fls',  'idx',  'ind',  'lof',  'lot',
+       'out', 'toc', 'blg', 'ilg', 'log', 'xdv' )]
 
-              (Concerning item (b): Normally, a change of a source file during
-              a run should provoke a rerun.  This includes a file generated by
-              LaTeX,  e.g.,  an  aux file, that is read in on subsequent runs.
-              But after a run that results in an error, a new run  should  not
-              occur  until  the  user has made a change in the files.  But the
-              user may have corrected an error in a source  .tex  file  during
-              the run.  So latexmk needs to distinguish user-generated and au-
-              tomatically generated files;  it  determines  the  automatically
-              generated  files as those with extensions in the list in @gener-
-              ated_exts.)
+              This  contains a list of extensions for files that are generated
+              during processing, and that should  be  deleted  during  a  main
+              clean  up  operation,  as invoked by the command line option -c.
+              (The use of -C or -gg gives this clean up and more.)
 
-              A convenient way to add an extra extension to the list,  without
-              losing  the already defined ones is to use a push command in the
+              The default values are extensions for standard  files  generated
+              by  *latex,  bibtex, and the like.  (Note that the clean up also
+              deletes the fdb_latexmk file, but that's separately  coded  into
+              latexmk, currently.)
 
 
 
-                               20 November 2021                             46
+                                 17 March 2022                              46
 
 
 
@@ -3040,6 +3040,29 @@
 LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
 
 
+              After  initialization  of latexmk and the processing of its com-
+              mand line, the  items  in  clean_ext  are  appended  to  @gener-
+              ated_exts.   So  these two variables have the same meaning (con-
+              trary to older versions of latexmk).
+
+              The items in @generated_exts are normally extensions  of  files,
+              whose  base  name  is  the same as the main tex file.  But it is
+              also possible to specify patterns including  that  basename  ---
+              see the explanation of the variable $clean_ext.
+
+              In addition to specifying files to be deleted in a clean up, la-
+              texmk uses the same specification to assist its  examination  of
+              changes  in source files: Under some situations it needs to find
+              those changes in files (since a previous run) that are  expected
+              to  be  due to the user editing a file.  This contrasts with the
+              cases of files that are generated by some program run by latexmk
+              and  that differ from the results of the previous run.  This use
+              of @generated_exts is normally unimportant, given the usual  ac-
+              curacy  of  latexmk's  other ways of determining these generated
+              files.
+
+              A convenient way to add an extra extension to the list,  without
+              losing  the already defined ones is to use a push command in the
               line in an RC file.  E.g.,
 
                               push @generated_exts, "end";
@@ -3048,6 +3071,7 @@
               tensions.   (This  extension  is used by the RevTeX package, for
               example.)
 
+
        $go_mode [0]
               If nonzero, process files regardless of timestamps, and is  then
               equivalent to the -g option.
@@ -3071,6 +3095,17 @@
 
                  $hash_calc_ignore_pattern{'eps'} = '^%%CreationDate: ';
 
+
+
+                                 17 March 2022                              47
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               This creates a rule for files with extension .eps about lines to
               ignore.  The left-hand side is a Perl idiom for setting an  item
               in  a hash.  Note that the file extension is specified without a
@@ -3094,18 +3129,6 @@
               causes lines starting with either "^%%CreationDate: " or "^%%Ti-
               tle: " to be ignored.
 
-
-
-
-                               20 November 2021                             47
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               It may happen that a pattern to be ignored is specified in,  for
               example,  in  a system or user initialization file, and you wish
               to remove this in a file that is read later.  To  do  this,  you
@@ -3138,6 +3161,17 @@
               Suppose you had .tex files test1.tex and test2.tex.   Then  when
               you run
 
+
+
+                                 17 March 2022                              48
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
                  latexmk -pdf *.tex
 
               both  files  will  be  compiled.  The .aux, .log, and .pdf files
@@ -3160,18 +3194,6 @@
               sibilities listed in the FORMAT OF COMMAND SPECIFICATIONS do not
               apply.   The  internal  and  start keywords are not available. A
               simple command specification with possible options and then "%S"
-
-
-
-                               20 November 2021                             48
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               is  all  that  is  guaranteed to work.  Note that for other com-
               mands, "%S" is substituted by a single source file. In contrast,
               for $kpsewhich, "%S" may be substituted by a long list of space-
@@ -3204,6 +3226,18 @@
 
                                   $latex = "latex --src-specials %O %S";
 
+
+
+
+                                 17 March 2022                              49
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               To do a coordinated setting of all of $latex, $pdflatex, $luala-
               tex, and $xelatex, see the section "Advanced Configuration".
 
@@ -3225,21 +3259,9 @@
               are the extensions.  The values are  irrelevant.)   Two  subrou-
               tines  are  provided for manipulating this and the related vari-
               able %pdflatex_input_extensions,  add_input_ext  and  remove_in-
-              put_ext.   They  are  used  as  in  the  following  examples are
+              put_ext.   They are used as in the following examples are possi-
+              ble lines in an initialization file:
 
-
-
-                               20 November 2021                             49
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
-              possible lines in an initialization file:
-
                   remove_input_ext( 'latex', 'tex' );
 
               removes the extension 'tex' from latex_input_extensions
@@ -3270,6 +3292,18 @@
 
               Under  MS-Windows (unlike UNIX/Linux), there is no standard pro-
               gram for printing files.  But there are ways you can do it.  For
+
+
+
+                                 17 March 2022                              50
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               example, if you have gsview installed, you could use it with the
               option "/p":
 
@@ -3293,17 +3327,6 @@
               Under  MS-Windows you could set this to use gsview, if it is in-
               stalled, e.g.,
 
-
-
-                               20 November 2021                             50
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
                   $lpr = '"c:/Program Files/Ghostgum/gsview/gsview32.exe" /p';
 
               If gsview is installed in a different directory, you  will  need
@@ -3335,6 +3358,18 @@
               fault extensions are 'tex', 'pdf', 'jpg, and 'png'.
 
               See details of the %latex_input_extensions for other information
+
+
+
+                                 17 March 2022                              51
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               that equally applies to %lualatex_input_extensions.
 
        $lualatex_silent_switch ["-interaction=batchmode"]
@@ -3357,19 +3392,6 @@
               will refuse to write its output and log files, for security rea-
               sons.
 
-
-
-
-
-                               20 November 2021                             51
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        $makeindex_silent_switch ["-q"]
               Switch(es) for the index processing program when silent mode  is
               on.
@@ -3401,10 +3423,22 @@
               stitution from "/" to "\", by default.
 
               However  there  are also programs on MS-Windows for which a back
-              slash "\" is interpreted differently than as a directory separa-
-              tor;  for these the directory separator should be "/".  Programs
-              with this behavior  include  all  the  *latex  programs  in  the
-              TeXLive  implementation  (but  not  the  MiKTeX implementation).
+              slash  "\"  is  interpreted  differently  than  as  a  directory
+
+
+
+                                 17 March 2022                              52
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
+              separator;  for  these  the  directory  separator should be "/".
+              Programs with this behavior include all the *latex  programs  in
+              the  TeXLive implementation (but not the MiKTeX implementation).
               Hence if you use TeXLive on MS-Windows,  then  $MSWin_back_slash
               should be set to zero.
 
@@ -3424,18 +3458,6 @@
 
               The effect of this variable (when non-blank) is achieved by  us-
               ing  the -output-directory option of *latex.  This exists in the
-
-
-
-                               20 November 2021                             52
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               usual current (Dec. 2011  and  later)  implementations  of  TeX,
               i.e.,  MiKTeX  and  TeXLive.  But it may not be present in other
               versions.
@@ -3468,6 +3490,18 @@
               equal to 1, generate a pdf version of the document using  pdfla-
               tex,  using the command specified by the $pdflatex variable.  If
               equal to 2, generate a pdf version of the document from  the  ps
+
+
+
+                                 17 March 2022                              53
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               file,  by  using  the command specified by the $ps2pdf variable.
               If equal to 3, generate a pdf version of the document  from  the
               dvi  file,  by  using the command specified by the $dvipdf vari-
@@ -3490,18 +3524,6 @@
 
                    $pdflatex = "pdflatex --shell-escape %O %S";
 
-
-
-
-                               20 November 2021                             53
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               (In some earlier versions of latexmk, you needed to use  an  as-
               signment  to  $pdflatex  to allow the use of lualatex or xelatex
               instead of pdflatex.  There are now separate configuration vari-
@@ -3534,6 +3556,18 @@
               See  details  of  the $latex_silent_switch for other information
               that equally applies to $pdflatex_silent_switch.
 
+
+
+
+                                 17 March 2022                              54
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
        $pdf_previewer ["start acroread %O %S"]
               The command to invoke a pdf-previewer.
 
@@ -3556,18 +3590,6 @@
               ample, SumatraPDF or gsview is used to view pdf files.
 
               Important note: Normally you will want to have a  previewer  run
-
-
-
-                               20 November 2021                             54
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               detached, so that latexmk doesn't wait for the previewer to ter-
               minate before continuing its work.  So normally you should  pre-
               fix  the  command  by  "start  ", which flags to latexmk that it
@@ -3601,6 +3623,17 @@
                   $pdf_update_method = 4;
                   $pdf_update_command = "xpdf -remote %R -reload";
 
+
+
+                                 17 March 2022                              55
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               The first setting arranges for the xpdf program to  be  used  in
               its  "remote server mode", with the server name specified as the
               rootname of the TeX file.  The second setting arranges  for  up-
@@ -3622,18 +3655,6 @@
               with their default settings of $pscmd.
 
               Setting the variable to -1 is used to indicate  that  $pscmd  is
-
-
-
-                               20 November 2021                             55
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               not to be used.
 
        $postscript_mode [0]
@@ -3667,6 +3688,18 @@
               option.   Which  previewer is run depends on the other settings,
               see the command line options -view=, and the variable $view.
 
+
+
+
+                                 17 March 2022                              56
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
        $preview_mode [0]
               If nonzero, run a previewer to preview the document.  Equivalent
               to  the -pv option.  Which previewer is run depends on the other
@@ -3688,18 +3721,6 @@
               The  -pvc  option  uses  the  command  specified by the variable
               $pscmd to determine if there is an  already  running  previewer,
               and  to  find  the process ID (needed if latexmk needs to signal
-
-
-
-                               20 November 2021                             56
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               the previewer about file changes).
 
               Each line of the output of this command is assumed to correspond
@@ -3733,6 +3754,18 @@
 
               WARNING: Linux systems may have installed one (or more) versions
               of  gv  under  different  names, e.g., ggv, kghostview, etc, but
+
+
+
+                                 17 March 2022                              57
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               perhaps not one actually called gv.
 
               Important note: Normally you will want to have a  previewer  run
@@ -3755,17 +3788,6 @@
               command, this is the command that is run.  See  the  information
               for the variable $ps_update_method.
 
-
-
-                               20 November 2021                             57
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        $ps_update_method [0 under UNIX, 1 under MS-Windows]
               How  the postscript viewer updates its display when the .ps file
               has changed.  See  the  information  on  the  variable  $dvi_up-
@@ -3797,6 +3819,19 @@
               The same as $always_view_file_via_temporary, except that it only
               applies in preview-continuous mode (-pvc option).
 
+
+
+
+
+                                 17 March 2022                              58
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
        $quote_filenames [1]
               This specifies whether substitutions for placeholders in command
               specifications  (as  in  $pdflatex)  are  surrounded  by  double
@@ -3820,18 +3855,6 @@
               Whether to use the -recorder option to (latex Use of this option
               results in a file of extension .fls containing  a  list  of  the
               files  that  these programs have read and written.  Latexmk will
-
-
-
-                               20 November 2021                             58
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               then use this file to improve its detection of source files  and
               generated files after a run of *latex.
 
@@ -3863,6 +3886,18 @@
               output or aux directories.]
 
               The  default  under  MSWin and Cygwin is ';' and under UNIX-like
+
+
+
+                                 17 March 2022                              59
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               operating systems (including Linux and OS-X) is  ':'.   Normally
               the  defaults give correct behavior.  But there can be difficul-
               ties if your operating system is of one kind, but some  of  your
@@ -3887,17 +3922,6 @@
               lence_logfile_warning_list   and  -silence_logfile_warning_list-
               also set this variable.
 
-
-
-                               20 November 2021                             59
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
               Note that multiple occurrences for the same undefined object  on
               the same page and same line will be compressed to a single warn-
               ing.
@@ -3927,6 +3951,19 @@
        $success_cmd [undefined]
               See the documentation for $compiling_cmd.
 
+
+
+
+
+                                 17 March 2022                              60
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
        $tmpdir [See below for default]
               Directory  to  store  temporary  files that latexmk may generate
               while running.
@@ -3953,17 +3990,6 @@
               do this.  The intent of calling make from latexmk is  merely  to
               detect dependencies.
 
-
-
-                               20 November 2021                             60
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        $view ["default"]
               Which  kind  of  file is to be previewed if a previewer is used.
               The possible values are  "default",  "dvi",  "ps",  "pdf".   The
@@ -3992,6 +4018,18 @@
 
               The default behavior is normally satisfactory in the usual edit-
               compile-edit  cycle.  But, for example, latexmk can also be used
+
+
+
+                                 17 March 2022                              61
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               as part of a build process for some bigger  project,  e.g.,  for
               creating  documentation  in the build of a software application.
               Then it is often sensible to treat citation and reference  warn-
@@ -4018,18 +4056,6 @@
               The program to make a pdf file from an xdv file  (used  in  con-
               junction with xelatex when $pdf_mode=5).
 
-
-
-
-                               20 November 2021                             61
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        $xdvipdfmx_silent_switch ["-q"]
               Switch(es) for the xdvipdfmx program when silent mode is on.
 
@@ -4058,6 +4084,18 @@
               not been found, and the file  is  given  without  an  extension.
               This  typically  happens  when  LaTeX  commands of the form \in-
               put{file} or \includegraphics{figure}, when the relevant  source
+
+
+
+                                 17 March 2022                              62
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               file does not exist.
 
               In  this  situation, latexmk searches for custom dependencies to
@@ -4085,17 +4123,6 @@
        in the .tex file.
 
 
-
-
-                               20 November 2021                             62
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
    Defining a custom dependency:
        The old method of configuring latexmk to use a custom dependency was to
        directly  manipulate  the @cus_dep_list array that contains information
@@ -4123,6 +4150,18 @@
        must:  If  non-zero,  the file from which we are converting must exist,
               if it doesn't exist latexmk will give an error message and  exit
               unless the -f option is specified.  If must is zero and the file
+
+
+
+                                 17 March 2022                              63
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
               we are converting from doesn't exist, then no action  is  taken.
               Generally, the appropriate value of must is zero.
 
@@ -4150,18 +4189,6 @@
        tects that a run of *latex needs to read a file, like a graphics  file,
        whose  extension  is the to-extension of a custom dependency.  Then la-
        texmk examines whether a file exists with the same name, but  with  the
-
-
-
-                               20 November 2021                             63
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        corresponding  from-extension,  as  specified in the custom-dependency.
        If it does, then a corresponding instance of the custom  dependency  is
        created,  after which the rule is invoked whenever the destination file
@@ -4189,6 +4216,18 @@
        Note  for  advanced  usage: The operating system's environment variable
        TEXINPUTS can be used to specify a search path for finding files by la-
        tex  etc.   Correspondingly,  when  a missing file is reported, latexmk
+
+
+
+                                 17 March 2022                              64
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
        looks in the directories specified in TEXINPUTS as well as in the  cur-
        rent  directory, to find a source file from which an instance of a cus-
        tom dependency can be used to make the missing file.
@@ -4216,18 +4255,6 @@
        initialization  file),  the latexmk will delete this rule before making
        the new one.
 
-
-
-
-                               20 November 2021                             64
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        Suppose latexmk is using this rule to convert a  file  "figure.fig"  to
        "figure.eps".   Then  it  will invoke the fig2eps subroutine defined in
        the above code with a single argument "figure", which is  the  basename
@@ -4255,6 +4282,18 @@
            }
 
        Note  1: In the command lines given in the system commands in the above
+
+
+
+                                 17 March 2022                              65
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
        examples, double quotes have been inserted around the file  names  (im-
        plemented  by '\"' in the Perl language).  They immunize the running of
        the program against special characters in filenames.  Very often  these
@@ -4281,19 +4320,6 @@
        need it.
 
 
-
-
-
-
-                               20 November 2021                             65
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
    Removing custom dependencies, and when you might need to do this:
        If  you  have some general custom dependencies defined in the system or
        user initialization file, you may find that for  a  particular  project
@@ -4321,14 +4347,26 @@
        file.  This method has been available since very old  versions  of  la-
        texmk, and many examples can be found, e.g., on the web.
 
-       However  in later versions of latexmk the internal structure of the im-
-       plementation of its "rules" for the steps of processing, including cus-
-       tom dependencies, became much more powerful.  The function implementing
-       a custom dependency is executed within a special context where a number
-       of  extra  variables  and subroutines are defined.  Publicly documented
-       ones, intended to be long-term stable,  are  listed  below,  under  the
-       heading "Variables and subroutines for processing a rule".
+       However  in  later  versions  of  latexmk the internal structure of the
 
+
+
+                                 17 March 2022                              66
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
+       implementation of its "rules" for the steps  of  processing,  including
+       custom  dependencies,  became  much more powerful.  The function imple-
+       menting a custom dependency is executed within a special context  where
+       a number of extra variables and subroutines are defined.  Publicly doc-
+       umented ones, intended to be long-term stable, are listed below,  under
+       the heading "Variables and subroutines for processing a rule".
+
        Examples  of  their  use is given in the following examples, concerning
        multiple index files and glossaries.
 
@@ -4349,17 +4387,6 @@
            }
            push @generated_exts, 'ndx', 'nnd';
 
-
-
-                               20 November 2021                             66
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        Notice  the  added line compared with earlier examples.  The extra line
        gets the extensions "ndx" and "nnd" added to the list of extensions for
        generated files; then the extra index files will be deleted by clean-up
@@ -4387,6 +4414,18 @@
            push @generated_exts, 'ndx', 'nnd', 'adx', 'and';
 
        This  last example uses the command specification in $makeindex, and so
+
+
+
+                                 17 March 2022                              67
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
        any customization you have made for the standard index also applies  to
        your extra indexes.
 
@@ -4415,17 +4454,6 @@
        item,  and the name of the subroutine for the custom dependency.  These
        were all defined above.
 
-
-
-                               20 November 2021                             67
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        An example of the old method of defining custom dependencies is as fol-
        lows.  It  is  the code in an RC file to ensure automatic conversion of
        .fig files to .eps files:
@@ -4451,10 +4479,22 @@
 
        See  also the section DEALING WITH ERRORS, PROBLEMS, ETC.  See also the
        examples in the directory example_rcfiles in the latexmk distributions.
-       Even if none of the examples apply to your case, they may give you use-
-       ful ideas
+       Even  if  none  of  the  examples apply to your case, they may give you
 
 
+
+                                 17 March 2022                              68
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
+       useful ideas
+
+
    Utility subroutines
        ensure_path( var, values ...)
 
@@ -4481,17 +4521,6 @@
               invoked programs.
 
 
-
-
-                               20 November 2021                             68
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
    Variables and subroutines for processing a rule
        A step in the processing is called a rule. One possibility to implement
        the  processing  of a rule is by a Perl subroutine.  This is always the
@@ -4516,6 +4545,19 @@
               This gives the name of the primary source file.  Note the double
               dollar signs.
 
+
+
+
+
+                                 17 March 2022                              69
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
        $$Pdest
               This gives the name of the main output file if  any.   Note  the
               double dollar signs.
@@ -4546,18 +4588,6 @@
 
        rdb_set_source( $rule, file, ... )
 
-
-
-
-                               20 November 2021                             69
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        rdb_set_source( $rule, @files )
               This subroutine sets the dependency list for the given  rule  to
               be the specified files.  Files that are already in the list have
@@ -4582,6 +4612,18 @@
        pattern,  you  can  use one of the following subroutines, std_tex_cmds,
        alt_tex_cmds, and set_tex_cmds.
 
+
+
+
+                                 17 March 2022                              70
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
        They work as follows
 
           &std_tex_cmds;
@@ -4599,8 +4641,8 @@
          set_tex_cmds( CMD_SPEC );
 
        Here CMD_SPEC is the command line without the program  name.  This  re-
-       sults  in  $latex = 'CMD_SPEC', and similarly for $pdflatex, $lualatex,
-       and $xelatex. An example would be
+       sults  in  $latex = 'latex CMD_SPEC', and similarly for $pdflatex, $lu-
+       alatex, and $xelatex. An example would be
 
          set_tex_cmds( '--interaction=batchmode %O %S' );
 
@@ -4612,18 +4654,6 @@
 
        Now the basic task of latexmk is to run  the  appropriate  programs  to
        make  a  viewable version of a LaTeX document.  However, the usual make
-
-
-
-                               20 November 2021                             70
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        program is not suited to this purpose for at least two reasons.   First
        is that the use of LaTeX involves circular dependencies (e.g., via .aux
        files), and these cannot be handled by the standard make program.  Sec-
@@ -4647,9 +4677,21 @@
        could be quite complicated, for example if some of the source files for
        a LaTeX document are generated by the project's software.
 
-       In this section, I give a couple of examples of how latexmk can be use-
-       fully invoked from a Makefile.  The examples use specific  features  of
-       current  versions  of  GNU make, which is the default on both linux and
+       In  this  section,  I  give  a couple of examples of how latexmk can be
+
+
+
+                                 17 March 2022                              71
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
+       usefully invoked from a Makefile.  The examples use  specific  features
+       of current versions of GNU make, which is the default on both linux and
        OS-X systems.  They may need modifications for other versions of make.
 
        The simplest method is simply to delegate all the relevant tasks to la-
@@ -4677,26 +4719,14 @@
        try.tex, but these aren't specified in the Makefile, so changes in them
        will not by themselves cause latexmk to be invoked.  Instead, the  pat-
        tern  rule is equipped with a "phony" prerequisite FORCE_MAKE; this has
-       the effect of causing the  rule  to  be  always  out-of-date,  so  that
+       the effect of causing the rule to be always out-of-date,  so  that  la-
+       texmk  is always run.  It is latexmk that decides whether any action is
+       needed, e.g., a rerun of pdflatex.  Effectively the Makefile  delegates
+       all  decisions  to  latexmk, while make has no knowledge of the list of
+       source files except for primary LaTeX file for the  document.  If there
+       are, for example, graphics files to be made, these must be made by cus-
+       tom dependencies configured in latexmk.
 
-
-
-                               20 November 2021                             71
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
-       latexmk  is  always run.  It is latexmk that decides whether any action
-       is needed, e.g., a rerun of pdflatex.  Effectively the  Makefile  dele-
-       gates all decisions to latexmk, while make has no knowledge of the list
-       of source files except for primary LaTeX file for  the   document.   If
-       there  are,  for example, graphics files to be made, these must be made
-       by custom dependencies configured in latexmk.
-
        But something better is needed in more complicated situations, for  ex-
        ample, when the making of graphics files needs to be specified by rules
        in the Makefile.  To do this, one can use a Makefile like  the  follow-
@@ -4714,6 +4744,18 @@
                    mkdir $@
             %.pdf : %.tex
                    if [ ! -e $(DEPS_DIR) ]; then mkdir $(DEPS_DIR); fi
+
+
+
+                                 17 March 2022                              72
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
                    $(LATEXMK) -pdf -dvi- -ps- -deps-out=$(DEPS_DIR)/$@P $<
             %.pdf : %.fig
                    fig2dev -Lpdf $< $@
@@ -4744,18 +4786,6 @@
        and an xfig file "graph.fig" exists.  On a first run, pdflatex  reports
        a  missing  file, named "graph". Latexmk succeeds in making "graph.pdf"
        by calling "make graph.pdf", and after completion of its work, it lists
-
-
-
-                               20 November 2021                             72
-
-
-
-
-
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
-
-
        "fig.pdf" among the dependents of the file latexmk is making.  Then let
        "fig.fig" be updated, and then let make be  run.   Make  first  remakes
        "fig.pdf", and only then reruns latexmk.
@@ -4780,6 +4810,18 @@
        manual  update (reopen); it views postscript and pdf.  Gsview under MS-
        Windows works for both postscript and pdf, but only reads  the  updated
        file  when  its  screen  is refreshed.  Acroread under UNIX/Linux views
+
+
+
+                                 17 March 2022                              73
+
+
+
+
+
+LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
+
+
        pdf, but the file needs to be closed and reopened to  view  an  updated
        version.   Under  MS-Windows,  acroread locks its input file and so the
        pdf file cannot be updated.  (Remedy: configure latexmk  to  use  suma-
@@ -4793,7 +4835,7 @@
        dard form to avoid being harvested too easily.)
 
 AUTHOR
-       Current  version,  by  John Collins (Version 4.76).  Report bugs etc to
+       Current  version,  by  John Collins (Version 4.77).  Report bugs etc to
        his e-mail (jcc8 at psu.edu).
 
        Released     version     can      be      obtained      from      CTAN:
@@ -4813,13 +4855,11 @@
 
 
 
-                               20 November 2021                             73
 
 
 
 
 
-LATEXMK(1)                  General Commands Manual                 LATEXMK(1)
 
 
 
@@ -4839,46 +4879,6 @@
 
 
 
+                                 17 March 2022                              74
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-                               20 November 2021                             74
-
-

Modified: branches/branch2021.final/Master/texmf-dist/scripts/latexmk/latexmk.pl
===================================================================
--- branches/branch2021.final/Master/texmf-dist/scripts/latexmk/latexmk.pl	2022-03-17 20:30:20 UTC (rev 62767)
+++ branches/branch2021.final/Master/texmf-dist/scripts/latexmk/latexmk.pl	2022-03-17 20:30:35 UTC (rev 62768)
@@ -2,7 +2,7 @@
 
 use warnings;
 
-## Copyright John Collins 1998-2021
+## Copyright John Collins 1998-2022
 ##           (username jcc8 at node psu.edu)
 ##      (and thanks to David Coppit (username david at node coppit.org) 
 ##           for suggestions) 
@@ -25,73 +25,8 @@
 ##    along with this program; if not, write to the Free Software
 ##    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 ##
+## See file CHANGES for list of main version-to-version changes.
 ##
-##
-##   Modification log from 14 Apr 2021 onwards in detail
-##
-## 20 Nov 2021 John Collins  Add /etc to list of locations for system rc files
-##  4 Nov 2021 John Collins  Improve diagnostics when there's a mismatch of 
-##                             destination file of rule between .fdb_latexmk
-##                             file and expectation.
-##  2 Nov 2021 John Collins  Sort generated-file section by filename; it's
-##                             already done in file data secton.
-##                           Only write fdb_latexmk file if nothing has been
-##                             done.  (Addition of $runs_total variable.)
-##                           V. 4.76.
-## 23 Sep 2021 John Collins  Option -time: times for all rules reported now
-## 18 Sep 2021 John Collins  For biber: parse blg file for config file use
-##                           V. 4.75.
-## 27 Aug 2021 John Collins  Modified "missing file" message (when parsing
-#                              log file). 
-## 29 May 2021 John Collins  When emulating aux_dir, put .synctex.gz .synctex
-##                             files in out_dir (as done by MiKTeX, and needed
-##                             for their use).
-##                           Turn emulate aux_dir off by default, to match older
-##                             behavior.  (BACKWARDS INCOMPATIBLE with 4.73 and
-##                             4.74.)
-##                           Add end-of-all-runs warning if emulate aux_dir needed
-##                             to be turned on, when it was initially off.
-##                           Add .synctex to list of extensions to clear by default.
-## 20 May 2021 John Collins  Turn back on default to report rc files read.
-##                           Add options -rc-report, -rc-report-, 
-##                             -dir_report, -dir_report-.
-## 16 May 2021 John Collins  Deal with some variable used only once warnings
-##                           Remove by default informational messages on rc
-##                           files read, and aux_dir and out_dir setting.
-##  5-6 May 2021 John Collins  Correct normalization of aux and out dirs.
-##                           Version 4.74
-##  3 May 2021 John Collins  Minor corrections.  Submit to CTAN.
-## 30 Apr 2021 John Collins  Revert the change of 14-15 Apr, by removing the
-##                           of cwd().  That gave sometimes obnoxiously slow
-##                           parsing of big log files, because of the slowness
-##                           of large number of calls to cwd() caused by calls
-##                           to sub normalize_filename. I think I am mistaken
-##                           that cwd() could possibly give a different result
-##                           than getcwd(), whose cached result is used by
-##                           my goodcwd(). That idea was my motivation on 14 Apr.
-## 22 Apr 2021 John Collins  Clean up aux and out_dir code.
-## 21 Apr 2021 John Collins  Clean up some comments
-##                           Add in emulation of -aux-directory.  On by
-##                           default.
-## 20 Apr 2021 John Collins  Add -dALLOWPSTRANSPARENCY option to ps2pdf and
-##                           dvi2pdf. That avoids problems with recent
-##                           ghostscript versions when, e.g., pstricks is used.
-## 16 Apr 2021 John Collins  Better normalization of aux_dir and out_dir, so
-##                that TEXMFOUTPUT, and the source and dest names for bibtex
-##                and makeindex allow them to work always when the aux_dir
-##                is **not** below cwd, at least under TeX Live. With MiKTeX
-##                bibtex works even without special precautions for aux_dir
-##                not below cwd.  But makeindex doesn't work in this case,
-##                even if TEXMFOUTPUT is set correctly.
-## 14-15 Apr 2021 John Collins  In normalize_filename, try both good_cwd() and
-##                           cwd() for removing directory component.
-##                           That improves clean up.  At least it could.
-##                V. 4.73.
-##
-##
-## 1998-2021, John Collins:  Many improvements and fixes.
-##   See CHANGE-log.txt for full list, and CHANGES for summaries
-##
 ## Modified by Evan McLean (no longer available for support)
 ## Original script (RCS version 2.3) called "go" written by David J. Musliner
 ##
@@ -108,8 +43,8 @@
 
 $my_name = 'latexmk';
 $My_name = 'Latexmk';
-$version_num = '4.76';
-$version_details = "$My_name, John Collins, 20 November 2021";
+$version_num = '4.77';
+$version_details = "$My_name, John Collins, 17 Mar. 2022. Version $version_num";
 
 use Config;
 use File::Basename;
@@ -127,21 +62,16 @@
     $have_bsd_glob = 1;
 }
 elsif ( eval{ File::Glob->import('glob'); 1; } ) {
-    warn "$My_name: I could not import File::Glob:bsd_glob, probably because your\n",
-         "  Perl is too old.  I have arranged to use the deprecated File::Glob:glob\n",
-         "  instead.\n",
-         "  WARNING: It may malfunction on clean up operation on filenames containing\n",
-         "           spaces.\n";
+    warn( "$My_name: I could not import File::Glob:bsd_glob, probably because your\n",
+             "  Perl is too old.  I have arranged to use the deprecated File::Glob:glob\n",
+             "  instead.\n",
+             "  WARNING: It may malfunction on clean up operation on filenames containing\n",
+             "           spaces.\n" );
     $have_bsd_glob = 0;
 }
 else {
     die "Could not import 'File::Glob:bsd_glob' or 'File::Glob:glob'\n";
 }
-# How I use the result of loading glob routines:
-sub my_glob {
-    if ($have_bsd_glob) { return bsd_glob( $_[0] ); }
-    else { return glob( $_[0] ); }
-}
 
 use File::Path 2.08 qw( make_path );
 use FileHandle;
@@ -152,11 +82,200 @@
 use Cwd "chdir";    # Ensure $ENV{PWD}  tracks cwd.
 use Digest::MD5;
 
-#use strict;
+#################################################
+#
+#  Unicode set up to be used in latexmk
+#
+use Encode qw( decode encode );
+use Unicode::Normalize;
+use utf8;  # For UTF-8 strings in **this** script
+use feature 'unicode_strings';
+use feature 'say';
+use bytes;  # To avoid messes when we use string operations on byte-coded/encoded
+            # filename strings.
 
+# Coding:
+# 1. $CS_system = CS for file names in file system calls, and for CL.
+#    It's to be UTF-8 on all except: MSWin when the MSWin system code page is
+#    not 65001.
+# 2. Internally use CS_system generally, and especially for filenames.
+#    Note with "use bytes;", even **de**coded strings have length and contents
+#    in terms of bytes with UTF-8 coding.
+#    Then standard file system calls, print to terminal don't need encoding,
+#    and things in rc files work unchanged from earlier versions of latexmk,
+#    when I didn't treat non-ASCII coding issues explicitly.
+# 3. But must set console codepage to system codepage on MSWin, otherwise
+#    display on terminal is garbled.
+# 4. fdb_latexmk: write and read UTF-8, convert to and from CS_system for
+#    strings.
+# 5. .fls, .log, .aux are all UTF-8, so if necessary convert to CS_system.
+# 6. However, with TeXLive on MSWin with system CP not equal to 65001,
+#    the PWD is in CS_system on all but most recent *latex (that's a bug).
+#    Convert file/path names to CS_system.
+# 7. Don't support non-UTF-8 on *nix.
+# 8. Do NOT do any conversion to a NF for Unicode: File systems are **either**
+#    normalization-sensitive (NTFS, ext4) and we need to preserve
+#    normalization, **or** they are normalization-insensitve (hfs+, apfs),
+#    in which case we can access a file with any normalization for its name.
+#
+# N.B.  I18N::Langinfo often doesn't give useful enough information.
+
+
+
+# My default CSs: UTF-8
+our $CS_system;
+$CS_system = 'UTF-8';
+# Quick short cut for tests of whether conversions needed:
+our $utf8_used = 1;
+
+# Win32 specific CP **numbers**.  Initialize to 65001 (utf-8), and change
+# by results of system calls.
+# Corresponding CS name: Prefix by 'CP'.
+# Preserve intial values for console/terminal to allow restore on exit.
+our ($CP_Win_system, $CP_init_Win_console_in, $CP_init_Win_console_out);
+$CP_Win_system = $CP_init_Win_console_in = $CP_init_Win_console_out = '65001';
+
+# Whether to revert Windows console CPs on exit:
+our $Win_revert_settings = 0;
+
+if ($^O eq "MSWin32") {
+    eval {  require Win32;
+            $CP_Win_system = Win32::GetACP();
+            $CS_system = 'CP' . $CP_Win_system;
+            $CP_init_Win_console_in = Win32::GetConsoleCP();
+            $CP_init_Win_console_out = Win32::GetConsoleOutputCP();
+            if ( Win32::SetConsoleOutputCP($CP_Win_system)
+                 && Win32::SetConsoleCP($CP_Win_system) ) {
+            } else {
+                warn "Cannot set Windows Console Output CP to $CP_Win_system.\n";
+            }
+    };
+    if ($@) { warn "Trouble finding and setting code pages used by Windows:\n",
+              "  $@",
+              "  ILL CONTINUE WITH UTF-8.\n"; 
+    }
+    else {
+        $Win_revert_settings =
+              ($CP_init_Win_console_in ne $CP_Win_system)
+              || ($CP_init_Win_console_out ne $CP_Win_system);
+    }
+    print "Win CP console initial and current in/out Win: ",
+        "($CP_init_Win_console_in, $CP_init_Win_console_out), ",
+        "($CP_Win_system, $CP_Win_system)\n";
+}
+$utf8_used = ($CS_system eq 'UTF-8') || ($CS_system eq 'CP65001');
+
+# Ensure that on ctrl/C interruption, etc, Windows console CPs are restored:
+use sigtrap qw(die untrapped normal-signals);
+END {
+    if ($Win_revert_settings ) {
+        warn "Reverting Windows console CPs to ",
+             "(in,out) = ($CP_init_Win_console_in,$CP_init_Win_console_out)\n";
+        Win32::SetConsoleCP($CP_init_Win_console_in);
+        Win32::SetConsoleOutputCP($CP_init_Win_console_out);
+    }
+}
+
+print "Coding system for system and terminal: '$CS_system'\n---\n"
+    unless $utf8_used;
+
+########################################################
+
+#************************************************************
+#************************************************************
+#            Unicode manipuation and normalization
+
+
+#-------------------------------------
+
+sub analyze_string {
+    # Useful for debugging encoding issues.
+    my ($m,$s) = @_;
+    say "=== $m '$s':";
+    say(
+        'Perl flag = ',
+        (utf8::is_utf8($s) ? 'utf8' : 'NOT utf8'),
+          ", len = ", length($s)
+        );
+    my @code = unpack( 'U*', $s );
+    @code = map { sprintf('%4X', $_) }  @code;
+    say join( ' ', @code );
+}
+
+#==================
+
+sub utf8_to_mine {
+    # Given string encoded in UTF-8, return encoded string in my current CS.
+    if  ($utf8_used) { return $_[0]; }
+    else { return  encode( $CS_system, decode('UTF-8', $_[0])); }  
+}
+
+#-------------------------------------
+
+sub mine_to_utf8 {
+    # Given string encoded in my current CS, return utf-8 encoded string.
+    if  ($utf8_used) { return $_[0]; }
+    else { return  encode( 'UTF-8', decode($CS_system, $_[0])); }
+}
+
+#-------------------------------------
+
+sub is_valid_utf8 {
+   eval { decode( 'UTF-8', $_[0], (Encode::FB_CROAK | Encode::LEAVE_SRC ) ); };
+   if ($@) { return 0; }
+   else { return 1; }
+}
+
+#-------------------------------------
+
+sub fprint8 {
+    # Usage: fprint8( handle, data array)
+    # Write to file converting from my CS to UTF-8
+    my $fh = shift;
+    print $fh mine_to_utf8( join( '', @_ ) );
+}
+
+#-------------------------------------
+
+################################################################
+
+
+
+
+################################################################
+################################################################
+#============ Deal with how I'm invoked: name and CL args:
+
+# Name that I'm invoked with indicates default behavior (latexmk
+# v. pdflatexmk, etc):
+(our $invoked_name) = fileparseA($0);
+
+our $invoked_kind = $invoked_name;
+print "$My_name: Invoked as '$invoked_name'\n"
+    if ($invoked_name ne 'latexmk');
+
+# Map my invoked name to pointer to array of default values for $dvi_mode,
+# $postscript_mode, $pdf_mode.  These are used if after processing rc files
+# and CL args, no values are set for any of these variables.
+# Thus default compilation for latexmk is by latex,
+#                          for pdflatexmk is by pdflatex, etc.
+%compilation_defaults =
+    ( 'latexmk' => [1,0,0],
+      'lualatexmk' => [0,0,4],
+      'pdflatexmk' => [0,0,1],
+      'xelatexmk' => [0,0,5],
+    );
+# If name isn't in canonical set, change it to a good default:
+unless (exists $compilation_defaults{$invoked_name}) { $invoked_name = 'latexmk'; }
+
+#==================
+
+################################################################
+################################################################
 # The following variables are assigned once and then used in symbolic 
 #     references, so we need to avoid warnings 'name used only once':
-use vars qw( $dvi_update_command $ps_update_command $pdf_update_command $out_dir_requested );
+use vars qw( $dvi_update_command $ps_update_command $pdf_update_command
+             $aux_dir_requested $out_dir_requested );
 
 # Translation of signal names to numbers and vv:
 %signo = ();
@@ -239,6 +358,9 @@
 %extra_rule_spec = ();
 
 
+#??????? !!!!!!!!! If @aux_hooks and @latex_file_hooks are still needed,
+# should I incorporate them into the general hook hash???
+#
 # Hooks for customized extra processing on aux files.  The following
 # variable is an array of references to functions.  Each function is
 # invoked in turn when a line of an aux file is processed (if none
@@ -247,7 +369,8 @@
 #    $_ = current line of aux file
 #    $rule = name of rule during the invocation of which, the aux file
 #            was supposed to have been generated.
- at aux_hooks = ();
+our @aux_hooks = ();
+#
 # Hooks for customized processing on lists of source and missing files.
 # The following variable is an array of references to functions.  Each 
 # function is invoked in turn after a run of latex (or pdflatex etc) and
@@ -256,7 +379,15 @@
 #    $rule = name of *latex rule
 #    %dependents: maps source files and possible source files to a status.
 #                 See begining of sub parse_log for possible values.
- at latex_file_hooks = ();
+our @latex_file_hooks = ();
+#
+# Single hash for various stacks of hooks:
+our %hooks = ();
+for ( 'before_xlatex', 'after_xlatex', 'after_xlatex_analysis' ) {
+    $hooks{$_} = [];
+}
+$hooks{aux_hooks} = \@aux_hooks;
+$hooks{latex_file_hooks} = \@latex_file_hooks;
 
 #########################################################################
 ## Default document processing programs, and related settings,
@@ -296,10 +427,14 @@
 # Whether emulate_aux had to be switched on during a run:
 $emulate_aux_switched = 0;
 
-%input_extensions = ();
+#--------------------
+# Specification of extensions/files that need special treatment,
+# e.g., in cleanup or in analyzing missing dependent files. 
+#
 # %input_extensions maps primary_rule_name to pointer to hash of file extensions
 #    used for extensionless files specified in the source file by constructs
 #    like \input{file}  \includegraphics{file}
+%input_extensions = ();
 set_input_ext( 'latex', 'tex', 'eps' );
 set_input_ext( 'pdflatex', 'tex', 'jpg', 'pdf', 'png' );
 $input_extensions{lualatex} = $input_extensions{pdflatex};
@@ -308,14 +443,64 @@
 # i.e., when actual primary rule differs from standard.
 %standard_input_extensions = %input_extensions;
 
+# Possible extensions for main output file of *latex:
 %allowed_output_ext = ( ".dvi" => 1, ".xdv" => 1, ".pdf" => 1 );
-# Extensions of files preserved when clean up is by -c rather than -C:
-%small_cleanup_preserved_exts = ();
-foreach ( 'dvi', 'dviF', 'ps', 'psF', 'pdf', 'synctex', 'synctex.gz', 'xdv' ) {
-    $small_cleanup_preserved_exts{$_} = 1;
-}
 
+# Variables relevant to specifying cleanup.
+# The first set of variables is intended to be user configurable.
+#
+# The @generated_exts array contains list of extensions (without
+# period) for files that are generated by rules run by latexmk.
+#
+# Instead of an extension, an item in the array can be a string containing
+# the placeholder %R for the root of the filenames.  This is used for more
+# general patterns.  Such a pattern may contain wildcards (bsd_glob
+# definitions).
+#
+# By default, it excludes "final output files" that
+# are normally only deleted on a full cleanup, not a small cleanup.
+# These files get two kinds of special treatment:
+#     1.  In clean up, where depending on the kind of clean up, some
+#         or all of these generated files are deleted.
+#         (Note that special treatment is given to aux files.)
+#     2.  In analyzing the results of a run of *LaTeX, to
+#         determine if another run is needed.  With an error free run,
+#         a rerun should be provoked by a change in any source file,
+#         whether a user file or a generated file.  But with a run
+#         that ends in an error, only a change in a user file during
+#         the run (which might correct the error) should provoke a
+#         rerun, but a change in a generated file should not.
+#         Also at the start of a round of processing, only user-file
+#         changes are relevant.
+# Special cases for extensions aux and bbl
+#   aux files beyond the standard one are found by a special analysis
+#   bbl files get special treatment because their deletion is conditional
+#       and because of the possibility of extra bibtex/biber rules with
+#       non-standard basename.
+ at generated_exts = ( 'aux', 'bcf', 'fls', 'idx', 'ind', 'lof', 'lot', 
+                    'out', 'toc',
+                    'blg', 'ilg', 'log',
+                    'xdv'
+                  );
+                  # N.B. 'out' is generated by hyperref package
+$clean_ext = "";        # For backward compatibility: Space separated 
+                        # extensions to be added to @generated_exts after
+                        # startup (and rc file reading).
+# Extensions of files to be deleted by -C, but aren't normally included
+# in the small clean up by -c.  Analogous to @generated_exts and $clean_ext,
+# except that pattern rules (with %R) aren't applied.
+ at final_output_exts = ( 'dvi', 'dviF', 'ps', 'psF', 'pdf',
+                        'synctex', 'synctex.gz' );
+$clean_full_ext = "";
 
+
+# Set of extra specific files to be deleted in small cleanup. These are
+#  ones that get generated under some kinds of error conditions.  All cases:
+#   Relative to current directory, and relative to aux and out directories.
+ at std_small_cleanup_files = ( 'texput.log', "texput.aux", "missfont.log" );
+
+#-------------------------
+
 # Information about options to latex and pdflatex that latexmk will simply
 #   pass through to *latex
 # Option without arg. maps to itself.
@@ -446,9 +631,6 @@
     elsif ( /^([^\s=]+)\s/ ) {
         $allowed_latex_options{$1} = $_;
     }
-    else {
-        $allowed_latex_options{$_} = $_;
-    }
 }
 
 # Arrays of options that will be added to latex and pdflatex.
@@ -589,7 +771,7 @@
 $quote_filenames = 1;       # Quote filenames in external commands
 
 $del_dir = '';        # Directory into which cleaned up files are to be put.
-                      # If $del_dir is '', just delete the files
+                      # If $del_dir is '', just delete the files in a clean up.
 
 @rc_system_files = ();
 
@@ -597,6 +779,7 @@
 
 ################################################################
 ##  Special variables for system-dependent fudges, etc.
+#    ???????? !!!!!!!!!!
 $log_file_binary = 0;   # Whether to treat log file as binary
                         # Normally not, since the log file SHOULD be pure text.
                         # But Miktex 2.7 sometimes puts binary characters
@@ -635,7 +818,7 @@
 
 ## Substitute backslashes in file and directory names for
 ##  MSWin command line
-$MSWin_back_slash = 1;
+$MSWin_back_slash = 0;
 
 ## Separator of elements in search_path.  Default is unix value
 $search_path_separator = ':'; 
@@ -645,44 +828,6 @@
 $tmpdir = ".";
 
 
-# When the aux_dir is on a network share (or the like), its system
-# time may differ from the system time on which latexmk is running.
-# This complicates the tests of whether particular files have been
-# made in a current run of a program or are left over from a previous
-# run.  One test, which is needed under some situations, is that a
-# file was made on a previous run when the files modification time is
-# less than the system time when the program is started.  (See
-# subroutine test_gen_file; this is only needed in a couple of
-# situations.)  The comparison between file and system times must be
-# corrected if there is an offset between system times on the computer
-# running latexmk and the computer hosting the file system containing
-# aux_dir.  The offset is measured in subroutine get_filetime_offset
-# by writing a temporary file; the test only needs to be done once.
-#
-# The following variables are used.  Since the system-independent
-# values of system and file time are only accurate to a second (or 2
-# seconds for FAT file systems), the offset is also accurate only to a
-# second or two.  So thresholds are needed below which differences
-# are insignificant.
-#
-# Note that the making or not making of a file is controlled by the
-# state of the document being compiled and by latexmk's configuration.
-# So a file that is left over from a previous run and not overwritten
-# on the current run will have a file time at least many seconds less
-# than the current time, corresponding to the time scale for a human
-# run-edit-run cycle.
-#
-$filetime_offset_measured = 0;       # Measurement not yet done.
-$filetime_offset = 0;                # Filetime relative to system time.
-$filetime_causality_threshold = 5;   # Threshold for detection of left-over file.
-                                     # Should be non-negative always, and should
-                                     # be bigger than 2 secs if a remote
-                                     # filesystem or network share is used.
-$filetime_offset_report_threshold = 30; # Threshold beyond which filetime offsets
-                                     # are reported; large offsets indicate
-                                     # incorrect system time on at least one system.
-
-
 ################################################################
 
 
@@ -696,7 +841,8 @@
 #   to make latexmk work under MSYS's perl.)
 #
 if ( $^O eq "MSWin32" ) {
-# Pure MSWindows configuration
+    # Pure MSWindows configuration
+
     ## Configuration parameters:
 
     ## Use first existing case for $tmpdir:
@@ -990,12 +1136,6 @@
                         # usually an indication of a problem; further
                         # runs may not resolve the problem, and
                         # instead could cause an infinite loop.
-$clean_ext = "";        # space separated extensions of files that are
-                        # to be deleted when doing cleanup, beyond
-                        # standard set
-$clean_full_ext = "";   # space separated extensions of files that are
-                        # to be deleted when doing cleanup_full, beyond
-                        # standard set and those in $clean_ext
 @cus_dep_list = ();     # Custom dependency list
 @default_files = ( '*.tex' );   # Array of LaTeX files to process when 
                         # no files are specified on the command line.
@@ -1048,6 +1188,9 @@
 $silent = 0;            # Whether fo silence latex's messages (and others)
 $warnings_as_errors = 0;# Treat warnings as errors and exit with non-zero exit code
 $silence_logfile_warnings = 0; # Do list warnings in log file
+                        # The warnings reported are those about undefined refs
+                        # and citations, and the like.
+$max_logfile_warnings = 7; # Max. # number of log file warnings to report
 $rc_report = 1;         # Whether to report on rc files read
 $aux_out_dir_report = 0; # Whether to report on aux_dir & out_dir after
                          # initialization and normalization
@@ -1075,26 +1218,7 @@
                         # of latexmk, the default is to set
                         # $analyze_input_log_always to 1.
 
-# The following two arrays contain lists of extensions (without
-# period) for files that are read in during a *LaTeX run but that
-# are generated automatically from the previous run, as opposed to
-# being user generated files (directly or indirectly from a custom
-# dependency).  These files get two kinds of special treatment:
-#     1.  In clean up, where depending on the kind of clean up, some
-#         or all of these generated files are deleted.
-#         (Note that special treatment is given to aux files.)
-#     2.  In analyzing the results of a run of *LaTeX, to
-#         determine if another run is needed.  With an error free run,
-#         a rerun should be provoked by a change in any source file,
-#         whether a user file or a generated file.  But with a run
-#         that ends in an error, only a change in a user file during
-#         the run (which might correct the error) should provoke a
-#         rerun, but a change in a generated file should not.
-# These arrays can be user-configured.
 
- at generated_exts = ( 'aux', 'bcf', 'fls', 'idx', 'ind', 'lof', 'lot', 
-                    'out', 'toc' );
-     # N.B. 'out' is generated by hyperref package
 
 # Which kinds of file do I have requests to make?
 # If no requests at all are made, then I will make dvi file
@@ -1101,7 +1225,7 @@
 # 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
+$postscript_mode = 0;   # No postscript file requested
 $pdf_mode = 0;          # No pdf file requested to be made by pdflatex
                         # Possible values: 
                         #     0 don't create pdf file
@@ -1132,7 +1256,7 @@
                         # $cleanup_mode = 1: full cleanup 
                         # $cleanup_mode = 2: cleanup except for dvi,
                         #                    dviF, pdf, ps, psF & xdv
-$cleanup_fdb  = 0;      # No removal of file for latexmk's file-database
+$cleanup_fdb  = 0;      # On normal run, 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
@@ -1171,8 +1295,8 @@
 
 # State variables initialized here:
 
-$updated = 0;           # Flags when something has been remade
-                        # Used to allow convenient user message in -pvc mode
+$updated = 0;           # Flags whether something has been remade in this round
+                        # of compilation. 
 $waiting = 0;           # Flags whether we are in loop waiting for an event
                         # Used to avoid unnecessary repeated o/p in wait loop
 
@@ -1435,33 +1559,34 @@
                     #       of specifications of extra generated files (beyond
                     #       the main dest file.  Standard place holders are used.
                     #   1: {Hash sourcefile -> [source-file data] }
-                    # Source-file data array: 
-                    #   0: time
-                    #   1: size
-                    #   2: md5
-                    #   3: name of rule to make this file
-                    #   4: whether the file is of the kind made by epstopdf.sty 
-                    #      during a primary run.  It will have been read during
-                    #      the run, so that even though the file changes during
-                    #      a primary run, there is no need to trigger another 
-                    #      run because of this.
-                    #  Size and md5 correspond to the values at the last run.
-                    #  But time may be updated to correspond to the time
-                    #  for the file, if the file is otherwise unchanged.
-                    #  This saves excessive md5 calculations, which would
-                    #  otherwise be done everytime the file is checked, 
-                    #  in the following situation:
-                    #     When the file has been rewritten after a run
-                    #     has started (commonly aux, bbl files etc),
-                    #     but the actual file contents haven't
-                    #     changed.  Then because the filetime has
-                    #     changed, on every file-change check latexmk
-                    #     would normally redo the md5 calculation to
-                    #     test for actual changes.  Once one such
-                    #     check is done, and the contents are
-                    #     unchanged, later checks are superfluous, and
-                    #     can be avoided by changing the file's time
-                    #     in the source-file list.
+                    #      Source-file data array: 
+                    #        0: time
+                    #        1: size
+                    #        2: md5
+                    #        3: DUMMY.  Not used any more. ?? Lots of code depends
+                    #               on array structure, Let's not change things now.
+                    #        4: whether the file is of the kind made by epstopdf.sty 
+                    #           during a primary run.  It will have been read during
+                    #           the run, so that even though the file changes during
+                    #           a primary run, there is no need to trigger another 
+                    #           run because of this.
+                    #       Size and md5 correspond to the values at the last run.
+                    #       But time may be updated to correspond to the time
+                    #       for the file, if the file is otherwise unchanged.
+                    #       This saves excessive md5 calculations, which would
+                    #       otherwise be done everytime the file is checked, 
+                    #       in the following situation:
+                    #          When the file has been rewritten after a run
+                    #          has started (commonly aux, bbl files etc),
+                    #          but the actual file contents haven't
+                    #          changed.  Then because the filetime has
+                    #          changed, on every file-change check latexmk
+                    #          would normally redo the md5 calculation to
+                    #          test for actual changes.  Once one such
+                    #          check is done, and the contents are
+                    #          unchanged, later checks are superfluous, and
+                    #          can be avoided by changing the file's time
+                    #          in the source-file list.
                     #   2: {Hash generated_file -> 1 }
                     #      This lists all generated files; the values
                     #          are currently unused, only the keys
@@ -1468,25 +1593,35 @@
                     #   3: {Hash source_rule -> last_pass }
                     #      This lists rules that are to be considered source
                     #      rules for the current rule, separately from the 
-                    #      from_rules of the source files. It maps the name
-                    #      of each of these rules to the pass number of the
-                    #      current rule when it was last run. The current rule
-                    #      is out-of-date if the last_pass for a source rule
-                    #      is less than the pass number for the rule.
-                    #      The purpose of this is when the source file list
-                    #      is expected to be inaccurate, because the source
-                    #      files are hard to determine.  Typical needs are
-                    #      for rules applied to dvi and xdv files, when
-                    #      graphics files are involved.  Their names are coded
-                    #      inside the dvi/xdv file, but not the contents.
-                    #      It would need parsing of the contents of the file
-                    #      to determine the actual source files.
-                    #      An implication of using a source_rule is that this
-                    #      rule passes files to the current rule and that the
-                    #      current rule can be considered out-of-date whenever
-                    #      the source_rule has been run.  Effectively these 
-                    #      files are unconditionallyconsidered changed when
-                    #      the source_rule runs.
+                    #      source_rules of the source files. Its main use
+                    #      (the only one at present) is when the list of
+                    #      known source files, at item 1, is/may be
+                    #      incomplete. This is notably the case for rules
+                    #      applied to dvi and xdv files when graphics files
+                    #      are involved. Their names are coded inside the
+                    #      dvi/xdv file, but not the contents. It would
+                    #      need parsing of the contents of the file to
+                    #      determine the actual source files. In the case
+                    #      of rules that process dvi and xdv files, the
+                    #      source_rule is the *latex rule that generates
+                    #      the dvi or xdv file.
+                    #
+                    #      In determining whether a rerun of the current
+                    #      rule is needed at some stage in a round of
+                    #      compilation, the following is added to the
+                    #      basic source-file-change criterion.
+                    #        The value that a source rule in this hash maps
+                    #        to is its pass number when the current rule was
+                    #        last run. The current rule is flagged
+                    #        out-of-date if the saved last_pass for a source
+                    #        rule is less than the current pass number for
+                    #        that source rule (as known to the compilation
+                    #        process). 
+                    #      An implication of using a source_rule in this
+                    #      way is that the source_rule passes files (or
+                    #      other information) to the current rule, and that
+                    #      the current rule is to be rerun whenever the
+                    #      source_rule has been run. 
 
 %fdb_current = ();  # Hash of information for all files used.
                     # It maps filename to a reference to an array
@@ -1494,19 +1629,28 @@
 @nofile = (0,-1,0); # What we use for initializing a new entry in fdb
                     # or flagging non-existent file.
 
-# The following provide information about the structure of the network of rules
-# and files.  They are set by the routine rdb_set_rule_net
-%from_rules = ();        # Used to optimize test for whether a file is generated.
-                         # This maps files to rules that generate them.  (Files
-                         # anywhere in %$PHdest.)
-%from_rules_main = ();   # Used to optimize test for whether a file is generated.
-                         # This maps files to rules that generate them as the 
-                         # MAIN output.  (I.e., file $$Pdest only.)
+# The following are variables which are set by the routine rdb_set_rule_net.
+# They are **derived** from information in %rule_db, and provide information
+# about the structure of the network of rules and files.   This derived
+# information is in a form useful for using the network of rules.
+
+# For recursing backwards through the network of rules:
+%from_rules = ();        # This maps file names to rule names.
+                         # $from_rules{'File'} is the name of the rule that
+                         # generates file 'File'.  If there is no rule to
+                         # generate the file, then $from_rules{'File'} is
+                         # not defined (or possibly the null string '').
+
 # Classification of rules, for determining order of application
-%current_primaries = ();   # Keys are primary rules (latex, etc) that are currently in use.
- at pre_primary = ();         # Array of rules that are thought of as pre-primary
- at post_primary = ();        # Array of rules that are thought of as post-primary
- at unusual_one_time = ();    # Array of rules that are special cases of one-time rules.
+%current_primaries = ();   # Keys are primary rules (latex, etc) that are
+                           # currently in use.
+ at pre_primary = ();         # Array of rules that are thought of as pre-primary,
+                           # Should be in an appropriate order for invoking
+                           # them, to optimize making.
+ at post_primary = ();        # Array of rules that are thought of as post-primary.
+                           # In suitable order for invocation
+ at unusual_one_time = ();    # Array of rules that are special cases of
+                           # one-time rules.
                            # Currently not used.
 
 
@@ -1533,7 +1677,8 @@
 #==================================================
 
 # Which rc files did I read?
- at rc_files_read = ();
+ at rc_files_read = ();  # In order of reading
+%rc_files_read2 = (); # Map **abs** filename to 1; used to check duplicate reads.
 
 # Options that are to be obeyed before rc files are read:
 foreach $_ ( @ARGV )
@@ -1621,8 +1766,8 @@
   elsif (/^-nobibtex$/) { $bibtex_use = 0; }
   elsif (/^-bibtex-cond$/) { $bibtex_use = 1; }
   elsif (/^-bibtex-cond1$/) { $bibtex_use = 1.5; }
-  elsif (/^-c$/)        { $cleanup_mode = 2; $cleanup_fdb = 1; $cleanup_only = 1; }
-  elsif (/^-C$/ || /^-CA$/ ) { $cleanup_mode = 1; $cleanup_fdb = 1; $cleanup_only = 1; }
+  elsif (/^-c$/)        { $cleanup_mode = 2; $cleanup_only = 1; }
+  elsif (/^-C$/ || /^-CA$/ ) { $cleanup_mode = 1; $cleanup_only = 1; }
   elsif (/^-CF$/)    { $cleanup_fdb = 1; }
   elsif (/^-cd$/)    { $do_cd = 1; }
   elsif (/^-cd-$/)   { $do_cd = 0; }
@@ -1646,7 +1791,7 @@
   elsif (/^-g$/)     { $go_mode = 1; }
   elsif (/^-g-$/)    { $go_mode = 0; }
   elsif (/^-gg$/)    { 
-     $go_mode = 2; $cleanup_mode = 1; $cleanup_fdb = 1; $cleanup_only = 0; 
+     $go_mode = 2; $cleanup_mode = 1; $cleanup_only = 0; 
   }
   elsif ( /^-h$/ || /^-help$/ )   { &print_help; exit;}
   elsif (/^-jobname=(.*)$/) {
@@ -1812,7 +1957,7 @@
       $pre_tex_code = $1;
   }
   elsif (/^-v$/ || /^-version$/)   { 
-      print "\n$version_details. Version $version_num\n";
+      print "$version_details\n";
       exit;
   }
   elsif (/^-verbose$/)  { $silent = 0; }
@@ -1839,7 +1984,9 @@
         &exit_help( "No RC file specified after -r switch"); 
      }
      if ( -e $ARGV[0] ) {
-        process_rc_file( $ARGV[0] );
+         # Give process_rc_file a non-zero argument so that there is a warning
+         # if $ARGV[0] has already been processed as an rc file:
+         process_rc_file( $ARGV[0], 1 );
      } 
      else {
         die "$My_name: RC file [$ARGV[0]] does not exist\n"; 
@@ -1907,7 +2054,7 @@
     &exit_help( "Bad options specified" );
 }
 
-warn "$My_name: This is $version_details, version: $version_num.\n",
+print "$My_name: This is $version_details, version: $version_num.\n",
    unless $silent;
 
 if ($out_dir eq '' ){
@@ -1925,17 +2072,6 @@
 $aux_dir_requested = $aux_dir;
 $out_dir_requested = $out_dir;
 
-
-# The following reports results of diagnostics on location of .log file
-#   after the first run of a latex engine, when actually used aux_dir
-#   may not be the expected one, due to a configuration error.
-# Values: -1 uninitialized (before first run)
-#          0 log file not found;
-#          1 log file in aux_dir;
-#          2 log file **not** in aux_dir but in out_dir;
-#          3 log file **not** in aux_dir or out_dir, but in cwd.
-$where_log = -1;  
-
 if ($bibtex_use > 1) {
     push @generated_exts, 'bbl';
 }
@@ -2110,6 +2246,21 @@
     add_option( "--jobname=%R", \$latex, \$lualatex, \$pdflatex, \$xelatex );
 }
 
+# Make sure we make the kind of file we want to view:
+if ($view eq 'dvi') { $dvi_mode = 1; }
+if ($view eq 'ps') { $postscript_mode = 1; }
+if ( ($view eq 'pdf') && ($pdf_mode == 0) ) { 
+    $pdf_mode = 1; 
+}
+
+# Make sure that we make something if all requests are turned off
+unless ( $dvi_mode || $pdf_mode || $postscript_mode || $printout_mode )  {
+    print "No specific requests made, so using default for $invoked_name.\n";
+    ($dvi_mode, $postscript_mode, $pdf_mode)
+        = @{$compilation_defaults{$invoked_name}};    
+}
+
+
 # Which kind of file do we preview?
 if ( $view eq "default" ) {
     # If default viewer requested, use "highest" of dvi, ps and pdf
@@ -2120,19 +2271,6 @@
     if ( $pdf_mode ) { $view = "pdf"; }
 }
 
-# Make sure we make the kind of file we want to view:
-if ($view eq 'dvi') { $dvi_mode = 1; }
-if ($view eq 'ps') { $postscript_mode = 1; }
-if ( ($view eq 'pdf') && ($pdf_mode == 0) ) { 
-    $pdf_mode = 1; 
-}
-
-# Make sure that we make something if all requests are turned off
-if ( ! ( $dvi_mode || $pdf_mode || $postscript_mode || $printout_mode) ) {
-    print "No specific requests made, so default to dvi by latex\n";
-    $dvi_mode = 1;
-}
-
 # Determine requests.
 if ( $banner ) { $postscript_mode = 1; }
 if ( $dvi_mode ) {
@@ -2222,39 +2360,34 @@
     add_option( "$dvips_pdf_switch", \$dvips );
 }
 
-# Restrict variables to allowed values:
-
-if ($filetime_causality_threshold < 0) {
-    warn "$My_name: Correcting negative value of \$filetime_causality_threshold to zero.\n";
-    $filetime_causality_threshold = 0;
-}
-
 # Note sleep has granularity of 1 second.
 # Sleep periods 0 < $sleep_time < 1 give zero delay,
 #    which is probably not what the user intended.
 # Sleep periods less than zero give infinite delay
-if ( $sleep_time < 0 ) {
-     warn "$My_name: Correcting negative sleep_time to 1 sec.\n";
-     $sleep_time = 1;
+if ( $sleep_time == 0 ) {
+     warn "$My_name: sleep_time was configured to zero.\n",
+    "    Do you really want to do this?  It can give 100% CPU usage.\n";
 }
-elsif ( ($sleep_time < 1) && ( $sleep_time != 0 ) ) {
+elsif ( $sleep_time < 1 ) {
      warn "$My_name: Correcting nonzero sleep_time of less than 1 sec to 1 sec.\n";
      $sleep_time = 1;
 }
-elsif ( $sleep_time == 0 ) {
-     warn "$My_name: sleep_time was configured to zero.\n",
-    "    Do you really want to do this?  It will give 100% CPU usage.\n";
-}
 
-# Make convenient forms for lookup.
-# Extensions always have period.
 
-# Convert @generated_exts to a hash for ease of look up and deletion
+# Standardize specifications for generated file extensions:
+#
+# Remove leading and trailing space in the following space-separated lists,
+# and collapse multiple spaces to one,
+# to avoid getting incorrect blank items when they are split.
+foreach ($clean_ext, $clean_full_ext) { s/^\s+//; s/\s+$//; s/\s+/ /g; }
+# Put everything in the arrays:
+push @generated_exts,  split('\s+',$clean_ext);
+push @final_output_exts,  split('\s+',$clean_full_ext);
+
+# Convert the arrays to hashes, for ease of deletion:
 # Keep extension without period!
-%generated_exts_all = ();
-foreach (@generated_exts ) {
-    $generated_exts_all{$_} = 1;
-}
+%generated_exts = ();
+foreach (@generated_exts ) { $generated_exts{$_} = 1; }
 
 $quell_uptodate_msgs = $silent; 
    # Whether to quell informational messages when files are uptodate
@@ -2286,22 +2419,18 @@
 # I will use definedness of $deps_handle as flag for global deps file having
 #   been opened and therefore being available to be written to after
 #   compiling a file.
+
 $deps_handle = undef;
 if ( $dependents_list
      && ! $preview_continuous_mode
      && ( ($cleanup_mode == 0) || ($go_mode == 2) )
    ) {
-    $deps_handle = new FileHandle "> $deps_file";
+    open( $deps_handle, ">$deps_file" );
     if (! $deps_handle ) {
         die "Cannot open '$deps_file' for output of dependency information\n";
     }
 }
 
-# Remove leading and trailing space in the following space-separated lists,
-#   and collapse multiple spaces to one,
-#   to avoid getting incorrect blank items when they are split.
-foreach ($clean_ext, $clean_full_ext) { s/^\s+//; s/\s+$//; s/\s+/ /g; }
-
 # Deal with illegal and problematic characters in filename:
 test_fix_texnames( @file_list );
 
@@ -2318,7 +2447,7 @@
 
     if ( $do_cd ) {
        ($filename, $path) = fileparse( $filename );
-       warn "$My_name: Changing directory to '$path'\n"
+       print "$My_name: Changing directory to '$path'\n"
            if !$silent;
        pushd( dirname_no_tail( $path ) );
     }
@@ -2325,7 +2454,11 @@
     else {
         $path = '';
     }
-    
+
+    # Localize the following, because they may get changed because of
+    # conditions specific to the current tex file, notably:
+    #   Change of emulation state of aux_dir
+    #   Use of $do_cd, which can affect how $aux_dir and $out_dir get normalized.
     local $aux_dir = $aux_dir;
     local $out_dir = $out_dir;
     local $latex = $latex;
@@ -2334,175 +2467,70 @@
     local $xelatex = $xelatex;
 
     &normalize_aux_out_ETC;
-    # Set -output-directory and -aux-directory options for *latex
+    # Set -output-directory and -aux-directory options for *latex here,
+    # since at least: Their method of use depends on the dynamically
+    # set $emulate_aux, and the exact strings for the directory names are
+    # not known until after the call to normalize_aux_out_ETC:
     &set_aux_out_options;
-
-    &set_names;
+    &set_names;   # Names of standard files
     
     # For use under error conditions:
     @default_includes = ($texfile_name, $aux_main);
-    # N.B. Do **not** apply local %rule_db here.  It might appear appropriate,
-    #      but %rule_db is needed in the continue block, which is not in the
-    #      scope of a local declaration here.
+    # Set rules here for current conditions
     &rdb_initialize_rules;
     $view_file = '';
     rdb_one_rule( 'view', sub{ $view_file = $$Psource; } );
 
-    if ( $cleanup_mode > 0 ) {
-        my %other_generated = ();
-        my @index_bibtex_generated = ();
-        my @aux_files = ();
-        my @missing_bib_files = ();
-        my $bibs_all_exist = 0;
-        my %final_output_files = ();
-        foreach (keys %small_cleanup_preserved_exts) {
-            $final_output_files{"$out_dir1$root_filename.$_"} = 1;
-        }
-        $have_fdb = 0;
-        if ( -e $fdb_name ) {
-            print "$My_name: Examining fdb file '$fdb_name' for rules ...\n"
-              if $diagnostics;
-            $have_fdb = ( 0 == rdb_read( $fdb_name ) );
-        }
-        if ( $have_fdb ) {
-            rdb_for_actives(
-                sub {  # Find generated files at rule level
-                    my ($base, $path, $ext) = fileparseA( $$Psource );
-                    $base = $path.$base;
-                    if ( $rule =~ /^makeindex/ ) {
-                        push @index_bibtex_generated, $$Psource, $$Pdest, "$base.ilg";
-                    }
-                    elsif ( $rule =~ /^(bibtex|biber)/ ) {
-                        push @index_bibtex_generated, $$Pdest, "$base.blg";
-                        push @aux_files, $$Psource;
-                        if ( $bibtex_use == 1.5) {
-                            foreach ( keys %$PHsource ) {
-                                if ( ( /\.bib$/ ) && (! -e $_) ) {
-                                    push @missing_bib_files, $_;
-                                }
-                            }
-                        }
-                    }
-                    elsif ( exists $other_generated{$$Psource} ) {
-#                       print "=========== CHECKING: source file of rule '$rule', '$$Psource'\n",
-#                              "  is a generated file.\n";
-                        ## OLD with apparent bug:
-                        #$other_generated{$$Pdest};
-                    }
-                    foreach my $key (keys %$PHdest) {
-                        $other_generated{$key} = 1;
-                    }
-                },
-                sub {  # Find generated files at source file level
-                    if ( $file =~ /\.aux$/ ) { push @aux_files, $file; }
-                }
-            );
-            if ($#missing_bib_files == -1) { $bibs_all_exist = 1; }
-        }
-        elsif ( -e $log_name ) {
-            # No fdb file, but log file exists, so do inferior job by parse_log
-            print "$My_name: Examining log file '$log_name' for generated files...\n"
-              if $diagnostics;
-            # Variables set by parse_log. Can I remove them?
-            local %generated_log = ();
-            local %dependents = ();    # Maps files to status.  Not used here.
-            local @bbl_files = ();     # Not used here.
-            local %idx_files = ();     # Maps idx_file to (ind_file, base). Not used here.
-            local %conversions = ();   # *latex-performed conversions.  Not used here.
-                         # Maps output file created and read by *latex
-                         #    to source file of conversion.
-            local $primary_out = '';   # Actual output file (dvi or pdf). Not used here.
-            local $fls_file_analyzed = 0;
-            &parse_log;
-            %other_generated = %generated_log;
-        }
-        else {
-            print "$My_name: No fdb or log file, so clean up default set of files ...\n"
-              if $diagnostics;
-        }
-        
-        if ( ($go_mode == 2) && !$silent ) {
-            warn "$My_name: Removing all generated files\n" unless $silent;
-        }
-        my $keep_bbl = 1;
-        if ( ($bibtex_use > 1.6)
-             ||
-             (  ($bibtex_use == 1.5) && ($bibs_all_exist) )
-           ) {
-               $keep_bbl = 0;
-        }
-        if ($keep_bbl) {
-            delete $generated_exts_all{'bbl'}; 
-        }
-        # Convert two arrays to hashes:
-        my %index_bibtex_generated = ();
-        my %aux_files = ();
-        my %aux_files_to_save = ();
-        foreach (@index_bibtex_generated) {
-            $index_bibtex_generated{$_} = 1
-               unless ( /\.bbl$/ && ($keep_bbl) );
-            delete( $other_generated{$_} );
-        }
-        foreach (@aux_files) {
-            if (exists $other_generated{$_} ) {
-                $aux_files{$_} = 1;
-            }
-            else {
-                $aux_files_to_save{$_} = 1;
-            }
-        }
+    if ( $diagnostics ) {
+       print "$My_name: Rules after start up for '$texfile_name'\n";
+       rdb_show();
+    }
 
-        foreach (keys %final_output_files) { delete $other_generated{$_}; }
-        
-        if ($diagnostics) {
-            show_array( "For deletion, the following were determined from fdb file or log file:\n"
-                       ." Generated (from makeindex and bibtex):", 
-                        keys %index_bibtex_generated );
-            show_array( " Aux files:", keys %aux_files );
-            show_array( " Other generated files:\n"
-                       ." (only deleted if \$cleanup_includes_generated is set): ",
-                        keys %other_generated );
-            show_array( " Yet other generated files are specified by patterns:\n".
-                        " Explicit pattern with %R or root-filename.extension:",
-                        keys %generated_exts_all );
-            show_array( " Aux files to SAVE and not delete:", keys %aux_files_to_save );
-        }
+    if ($cleanup_fdb) {
+        print "$My_name: Deleting '$fdb_name' (file of cached information)\n";
+        unlink_or_move( $fdb_name );
+    }
 
-        my @clean_args = ( 'blg', 'ilg', 'log', 'aux.bak', 'idx.bak',
-                   split('\s+',$clean_ext), keys %generated_exts_all );
-        cleanup1( $aux_dir1, @clean_args );
-        if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @clean_args ); }
-        if ( $cleanup_mode == 1 ) {
-            my @clean_args = ( keys %small_cleanup_preserved_exts, split('\s+', $clean_full_ext) );
-            cleanup1( $aux_dir1, @clean_args );
-            if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @clean_args ); }
+    # Set rules from fdb_latexmk file, if possible.
+    # Allow adaptation of output extension for primary rule to cached
+    # value, but not if we are doing a cleanup (since then the rules
+    # will all be reset after the cleanup).
+    if ( -e $fdb_name ) {
+        if (0 != rdb_read( $fdb_name, $cleanup_mode ) ) {
+            # There were some problems with the file of cached rules, so
+            # the  resulting set of rules may be problematic: file status
+            # data may be incorrect.
+            # So use filetime criterion for make instead of file change from
+            # previous run, until we have done our own make.
+            rdb_recurse( [keys %possible_primaries],
+                      sub{ if ( $$Ptest_kind == 1 ) { $$Ptest_kind = 3;} }
+            );
         }
-        unlink_or_move( 'texput.log', "texput.aux", "missfont.log",
-                keys %index_bibtex_generated, 
-                        keys %aux_files );
-        if ($cleanup_includes_generated) {
-            unlink_or_move( keys %other_generated );
-        }
-        if ( $cleanup_includes_cusdep_generated) {
-            &cleanup_cusdep_generated;
-        }
     }
-    if ($cleanup_fdb) {
-       unlink_or_move( $fdb_name );
-       # If the fdb file exists, it will have been read, and therefore changed
-       #   rule database.  But deleting the fdb file implies we also want
-       #   a virgin rule database, so we must reset it:
-       &rdb_initialize_rules;
+    elsif ( -e $log_name ) {
+        # At least we can use dependency information from previous run of
+        # *latex, which may not have been under latexmk control, otherwise
+        # the fdb_latexmk file would have been made.
+        rdb_for_some( [keys %current_primaries],
+                      sub{ rdb_set_latex_deps($cleanup_mode) }
+                    );
+        &rdb_set_rule_net;
     }
+    # At this point, the file and rule databases are correctly initialized
+    # either from the fdb_latexmk database (corresponding to the state at
+    # the end of the previous run of latexmk), or from default initialization,
+    # assisted by dependency information from log files about previous
+    # run, if the log file exists.
+    # PERHAPS if fdb_latexmk doesn't exist but appropriate output files exist,
+    #   we could assume there was a previous run that completed.  Then new
+    #   run of *latex etc isn't needed until files are changed; then we
+    #   should set the file data from the on-disk state.
+
+    if ( $cleanup_mode ) { &do_small_cleanup; }
+    if ( $cleanup_mode == 1 ) { &do_extra_cleanup; }
     if ($cleanup_only) { next FILE; }
 
-    if ( $diagnostics ) {
-       print "$My_name: Rules after start up for '$texfile_name'\n";
-       rdb_show();
-    }
-
-    $have_fdb = 0;
-    if (! -e $aux_main ) {
+    if ( ! -e $aux_main ) {
         # No aux file => set up trivial aux file 
         #    and corresponding fdb_file.  Arrange them to provoke one run 
         #    as minimum, but no more if actual aux file is trivial.
@@ -2515,29 +2543,8 @@
         &set_trivial_aux_fdb;
     }
 
-    if ( -e $fdb_name ) {
-        $rdb_errors = rdb_read( $fdb_name );
-        $have_fdb = ($rdb_errors == 0);
-    }
-    if (!$have_fdb) { 
-        # We didn't get a valid set of data on files used in
-        # previous run.  So use filetime criterion for make
-        # instead of change from previous run, until we have
-        # done our own make.
-        rdb_recurse( [keys %possible_primaries],
-                      sub{ if ( $$Ptest_kind == 1 ) { $$Ptest_kind = 3;} }
-        );
-        if ( -e $log_name ) {
-            rdb_for_some( [keys %current_primaries], \&rdb_set_latex_deps );
-        }
-    }
-    # At this point, we assume that the file database was correctly
-    # initialized from fdb_latexmk database (corresponding to the state at
-    # the end of the previous run of latexmk, if the fdb_latexmk file exists.
-    # PERHAPS if fdb_latexmk doesn't exist we ought to assume there was
-    # a previous run that completed, if the appropriate output files exist,
-    # so a new run of *latex etc isn't needed; then we should set the file
-    # data from the on-disk state.
+
+
     if ($go_mode) {
         # Force everything to be remade.
         rdb_recurse( [ &rdb_target_array], sub{$$Pout_of_date=1;}  );
@@ -2621,14 +2628,6 @@
 
 if ($show_time) { show_timing();}
 
-sub show_timing {
-    my $processing_time = processing_time() - $processing_time1;
-    print @timings, "Accumulated processing time = $processing_time\n";
-    print "Number of rules run = ", 1+$#timings, "\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
@@ -2641,34 +2640,41 @@
         # Error occured, but multiple files were processed, so
         #     user may not have seen all the error messages
         warn "\n------------\n";
-        show_array( 
+        warn_array( 
            "$My_name: Some operations failed, for the following tex file(s)", 
            @failed_primaries);
     }
     if ( !$force_mode ) {
-      warn "$My_name: Use the -f option to force complete processing,\n",
-           " unless error was exceeding maximum runs, or warnings treated as errors.\n";
+        warn
+            "$My_name: If appropriate, the -f option can be used to get latexmk\n",
+            "  to try to force complete processing.\n";
     }
     exit 12;
 }
 
-if ( $where_log == 2 ) {
-    warn "$My_name: You requested aux_dir '$aux_dir_requested',\n",
-         "  but '$out_dir' was used for the .log file etc, and I couldn't\n",
-         "  correct the problem, even by setting emulation of aux_dir on.\n",
-         "  There is a strong suspicion of a bug in $my_name or a configuration error.\n";
-}
 if ( $emulate_aux_switched ) {
-    warn "$My_name: I had to switch -aux-directory on after it was initially off,\n",
-         "  because your *latex program appeared not to support it. You probably\n",
-         "  should either use the option -emulate-aux-dir, or in a latexmkrc file\n",
-         "  set \$emulate_aux = 1;\n";
+    warn "$My_name: I had to switch emulate-aux-dir on after it was initially off,\n",
+         "  because your *latex program appeared not to support -aux-directory. You\n",
+         "  probably should either use the option -emulate-aux-dir, or in a\n",
+         "  latexmkrc file set \$emulate_aux = 1;\n";
 }
 
 # end MAIN PROGRAM
+
 #############################################################
 #############################################################
 
+sub show_timing {
+    my $processing_time = processing_time() - $processing_time1;
+    print @timings, "Accumulated processing time = ",
+          sprintf('%.2f', $processing_time), "\n";
+    print "Number of rules run = ", 1+$#timings, "\n";
+    @timings = (); 
+    $processing_time1 = processing_time();
+}
+
+#############################################################
+
 sub set_tex_cmds {
     # Usage, e.g., set_tex_cmds( '%O %S' )
     my $args = $_[0];
@@ -2725,9 +2731,9 @@
             $unbalanced_quote++;
         }
         elsif ( $count_q > 0 ) {
-            warn "$My_name: Removed (balanced quotes) from filename '$_',\n";
+            print "$My_name: Removed (balanced quotes) from filename '$_',\n";
             s/\"//g;
-            warn "   and obtained '$_'.\n";
+            print "   and obtained '$_'.\n";
             $balanced_quote++;
         }
     }
@@ -2777,7 +2783,7 @@
     # 4. Set some TeX-related environment variables.
     # 5. Ensure the aux and out directories exist
 
-    # Ensure the output/auxiliary directories exist, if need be
+    # Ensure the output/auxiliary directories exist, if need be, **with error checking**.
     my $ret1 = 0;
     my $ret2 = 0;
     eval {
@@ -2847,9 +2853,9 @@
     }
     
     if ($diagnostics || $aux_out_dir_report ) {
-        warn "$My_name: Cwd: '", good_cwd(), "'\n";
-        warn "$My_name: Normalized aux dir and out dir: '$aux_dir', '$out_dir'\n";
-        warn "$My_name: and combining forms: '$aux_dir1', '$out_dir1'\n";
+        print "$My_name: Cwd: '", good_cwd(), "'\n";
+        print "$My_name: Normalized aux dir and out dir: '$aux_dir', '$out_dir'\n";
+        print "$My_name: and combining forms: '$aux_dir1', '$out_dir1'\n";
     }
 
 }  #END normalize_aux_out_ETC
@@ -3070,56 +3076,86 @@
 #************************************************************
 
 sub rdb_set_rule_net {
-    # Set network of rules, including links
-    &rdb_make_links;
+    # Set network of rules, including links and classifications.
+    #
+    # ?? Problem if there are multiple rules for getting a file.  Notably pdf.
+    #    Which one to choose?
+    # ?? Problem: what if a rule is inactive,
+    #    e.g., bibtex because biber is in use,
+    #          or xelatex when pdflatex is in use
+    #          or bibtex when $bibtex_use is 0.
+    #    What if both latex and pdflatex are being used?
+    #      That has been allowed.  But .aux file (also
+    #      .log file) are made by both.
+
+    #  Other case: package (like bibtopic) creates bbl or other file when
+    #  it doesn't exist.  Later a rule is created by latexmk to make that
+    #  file.  Then the rule's main destination file should have priority
+    #  over non-main generated files from other rules.
+    local %from_rules_old = %from_rules;
+    %from_rules = ();     # File to rule.
+    rdb_for_actives( \&set_file_links_for_rule );
+    rdb_for_actives( \&rdb_set_source_rules );
     &rdb_classify_rules;
+    #    print "=========In rdb_make_links: rules\n"; &rdb_show;
 }
 
-#************************************************************
+#------------
 
-sub rdb_make_links {
-# ?? Problem if there are multiple rules for getting a file.  Notably pdf.
-#    Which one to choose?
-# ?? Problem: what if a rule is inactive,
-#    e.g., bibtex because biber is in use,
-#          or xelatex when pdflatex is in use
-#          or bibtex when $bibtex_use is 0.
-#    What if both latex and pdflatex are being used?
-#      That has been allowed.  But .aux file (also
-#      .log file) are made by both.
-
-#  Other case: package (like bibtopic) creates bbl or other file when
-#  it doesn't exist.  Later a rule is created by latexmk to make that
-#  file.  Then the rule's main destination file should have priority
-#  over non-main generated files from other rules.
-    local %from_rules_old = %from_rules;
-    &rdb_cache_generated;
-    
-    rdb_for_actives( 
-        0,
-        sub{ 
-            if ( exists $from_rules_main{$file} ) {
-                $$Pfrom_rule = $from_rules_main{$file};
+sub set_file_links_for_rule {
+    foreach my $dest ( @$PA_extra_gen, keys %$PHdest ) {
+        if ( exists $from_rules{$dest} ) {
+            my $old_rule = $from_rules{$dest};
+            if ( $old_rule eq $rule ) {
+                # OK
             }
-            elsif ( exists $from_rules{$file} ) {
-                $$Pfrom_rule = $from_rules{$file};
+            elsif ( exists($possible_primaries{$old_rule})
+                    && exists($possible_primaries{$rule}) ) {
+                # This could be problematic.  But we'll let it go,
+                # because it is a common case for .aux and .log files
+                # (etc), and these cases do not appear to mess up
+                # anything (by experience).
+                # Once we allow an active flag for rules and only
+                # examine active rules, the only case of this that
+                # will appear (in the absence of other problems) will
+                # be where two primary rules are active, notably a
+                # latex rule to make dvi and a pdflatex (or other
+                # rule) to make pdf.
             }
-            if ( $$Pfrom_rule && (! rdb_rule_exists( $$Pfrom_rule ) ) ) {
-                $$Pfrom_rule = '';
+            else {
+                warn "$My_name: Possible bug:\n",
+                 "  In linking rules I already set source_rules{$dest} to '$old_rule'\n",
+                 "  But now I want to set it to '$rule'\n";
             }
         }
-        );
-    rdb_for_actives( \&rdb_set_source_rules );
-#    print "=========In rdb_make_links: rules\n"; &rdb_show;
-} # END rdb_make_links
+        $from_rules{$dest} = $rule;
+    }
+} # END set_file_links_for_rule
+   
+#------------
 
-#************************************************************
-
 sub rdb_set_source_rules {
-    # This applies to rules whose source file is a dvi or xdv file
-    # Uses rule context
+    # This assumes rule context, and sets explicit source rules in the hash
+    # %$PHsource_rules.  These are to be rules on which the current rule
+    # depends, but that aren't determined by using the known set of source
+    # files of the current rule together with the known sets of destination
+    # files for other rules.
+    #
+    # The standard case, and the only one used at the moment is for rules
+    # whose **main** source file is a dvi or xdv file.  These programs used
+    # by these rules (dvips etc) do not provide easily accessible
+    # information on the set of graphics files that they read in.
+    # So such rules are given a source rule that is the *latex that
+    # generates them.
+    #
+    # These cases need special treatment coded here and in the algorithms
+    # in rdb_make etc.
+    #
     my ($base, $path, $ext) = fileparseA( $$Psource );
     if ( ($ext eq '.dvi') || ($ext eq '.dviF') || ($ext eq '.xdv') ) {
+        # Rules that use .dvi, .dviF, .xdv don't get all dependencies,
+        # notably about included graphics files.
+        # So use a pass criterion instead.
         my $old_rule = $from_rules_old{$$Psource};
         my $new_rule = $from_rules{$$Psource};
         if ( defined $old_rule
@@ -3134,81 +3170,104 @@
             if ( defined $new_rule ) { $$PHsource_rules{$new_rule} = 0; }
         }
     }
-}
+} # END rdb_set_source_rules
 
-#************************************************************
+#------------
 
-sub rdb_cache_generated {
-    # Update %from_rules
-    %from_rules = ();
-    %from_rules_main = ();
-    rdb_for_actives( \&one_from_main_rule_cache );
-    rdb_for_actives( \&one_from_rule_cache );
-} # END rdb_cache_generated
+sub rdb_classify_rules {
+    # Usage: &rdb_classify_rules
+    # Assume the following variables are available (global or local):
+    # Input:
+    #    %target_rules    # Set to target rules
+    #    %target_files    # Set to target files
+    #    %possible_primaries
+    
+    # Output:
+    #    %current_primaries    # Keys are actual primaries
+    #    @pre_primary          # Array of rules
+    #    @post_primary         # Array of rules
+    #    @unusual_one_time     # Array of rules
+    # @pre_primary and @post_primary are in natural order of application.
 
-#------------
+    local @requested_targets = &rdb_target_array;
+    local $state = 0;       # Post-primary
+    local @classify_stack = ();
 
-sub one_from_main_rule_cache {
-    # Rule context assumed.
-    # Set from_rules_main items for one rule
-    if (! $$Pdest) { return; }
-# Error message trigger:    if ( $$Pdest =~ /pdf$/) { $from_rules_main{$$Pdest} = 'pdflatexA'; }
-    if ( exists $from_rules_main{$$Pdest} ) {
-        my $old_rule = $from_rules_main{$$Pdest};
-        if ( $old_rule eq $rule ) {
-            # OK
-        }
-        else {
-            warn "$My_name: Possible bug:\n",
-                 "  In linking rules I already set from_rules_main{$$Pdest} to '$old_rule'\n",
-                 "  But now I want to set it to '$rule'\n";
-#            traceback( "================================\nFrom one_from_main_rule_cache" );
-        }
+    %current_primaries = ();
+    @pre_primary = ();
+    @post_primary = ();
+    @unusual_one_time = ();
+
+    rdb_recurse( \@requested_targets, \&rdb_classify1, 0,0, \&rdb_classify2 );
+
+    # Reverse, as tendency is to find last rules first.
+    @pre_primary = reverse @pre_primary;
+    @post_primary = reverse @post_primary;
+
+    my @current_primaries = keys %current_primaries;
+    if ($#current_primaries < 0) {
+        die "$My_name: No active primary rules found.  I have to stop.\n";
     }
-    $from_rules_main{$$Pdest} = $rule;
-} # END one_from_main_rule_cache
+    elsif ($#current_primaries > 0) {
+        die "$My_name: More than one active primary rule found.  I have to stop.\n",
+            "  Primary rules: @current_primaries\n";
+    }
+    $current_primary = $current_primaries[0];
 
-#------------
+    if ($diagnostics) {
+        print "Rule classification: \n";
+        show_array( "  Requested rules:",  @requested_targets );
+        show_array( "  Pre-primaries:", @pre_primary );
+        show_array( "  Primaries:", keys %current_primaries );
+        show_array( "  Post-primaries:", @post_primary );
+        show_array( "  Inner-level one_time rules:", @unusual_one_time );
+        show_array( "  Outer-level one_time rules:", keys %one_time );
+    } #end diagnostics
 
-sub one_from_rule_cache {
-    # Rule context assumed.
-    # Set from_rules items for one rule
-    foreach (  @$PA_extra_gen, keys %$PHdest ) {
-        # Error message trigger:  if ( $_ =~ /aux$/) { $from_rules{$_} = 'pdflatexA'; }
-        if ( exists $from_rules{$_} ) {
-            my $old_rule = $from_rules{$_};
-            if ( $old_rule eq $rule ) {
-                # OK
-            }
-            elsif ( exists $from_rules_main{$_} && ( $from_rules_main{$_} ne $rule ) ) {
-                warn "$My_name: Possible bug:\n",
-                     "  In linking rules, I already set from_rules_main{$_}\n".
-                     "  to '$from_rules_main{$_}'\n",
-                     "  But now I also have a different rule '$rule' that also made the file.\n";
-            }
-            elsif ( exists($possible_primaries{$old_rule}) && exists($possible_primaries{$rule}) ) {
-                # This could be problematic.  But we'll let it go,
-                # because it is a common case for .aux and .log files
-                # (etc), and these cases do not appear to mess up
-                # anything (by experience).
-                # Once we allow an active flag for rules and only
-                # examine active rules, the only case of this that
-                # will appear (in the absence of other problems) will
-                # be where two primary rules are active, notably a
-                # latex rule to make dvi and a pdflatex (or other
-                # rule) to make pdf.
-            }
-            else {
-                warn "$My_name: Possible bug:\n",
-                     "  In linking rules I already set from_rules{$_} to '$old_rule'\n",
-                     "  But now I want to set it to '$rule'\n";
-#            traceback( "================================\nFrom one_from__rule_cache" );
-            }
+} #END rdb_classify_rules
+
+#-------------------
+
+sub rdb_classify1 {
+    # Helper routine for rdb_classify_rules
+    # Applied as rule_act1 in recursion over rules
+    # Assumes rule context, and local variables from rdb_classify_rules
+    push @classify_stack, [$state];
+    if ( exists $possible_one_time{$rule} ) {
+        # Normally, we will have already extracted the one_time rules,
+        # and they will never be accessed here.  But just in case of
+        # problems or generalizations, we will cover all possibilities:
+        if ($depth > 1) {
+           warn "ONE TIME rule not at outer level '$rule'\n";
         }
-        $from_rules{$_} = $rule;
+        push @unusual_one_time, $rule;
     }
-} #END from_rule_cache
+    elsif ($state == 0) {
+       if ( exists $possible_primaries{$rule} ) {
+           $state = 1;   # In primary rule
+           $current_primaries{ $rule } = 1;
+       }
+       else {
+           push @post_primary, $rule;
+       }
+    }
+    else {
+        $state = 2;     # in post-primary rule
+        push @pre_primary, $rule;
+    }
+} #END rdb_classify1
 
+#-------------------
+
+sub rdb_classify2 {
+    # Helper routine for rdb_classify_rules
+    # Applied as rule_act2 in recursion over rules
+    # Assumes rule context
+    ($state) = @{ pop @classify_stack };
+} #END rdb_classify2
+
+#================================
+
 #************************************************************
 
 sub set_trivial_aux_fdb {
@@ -3222,14 +3281,13 @@
     # 2. Write a corresponding fdb file
     # 3. Provoke a run of *latex (actually of all primaries). 
 
-    local *aux_file;
-    open( aux_file, '>', $aux_main )
+    open( my $aux_file, '>', $aux_main )
         or die "Cannot write file '$aux_main'\n";
-    print aux_file "\\relax \n";
+    fprint8 $aux_file, "\\relax \n";
     # The following is added by recent versions of latex for a
     # one page document
-    print aux_file "\\gdef \\\@abspage\@last{1}\n";
-    close(aux_file);
+    fprint8 $aux_file, "\\gdef \\\@abspage\@last{1}\n";
+    close($aux_file);
 
     foreach my $rule (keys %possible_primaries ) { 
         rdb_ensure_file( $rule, $texfile_name );
@@ -3246,6 +3304,148 @@
 #************************************************************
 #************************************************************
 
+sub do_extra_cleanup {
+    print "$My_name: Doing extra clean up (of final output files) for '$texfile_name'\n"
+        if ! $silent;
+    cleanup1( $aux_dir1, @final_output_exts );
+    if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @final_output_exts ); }
+}  # END do_extra_cleanup
+
+#************************************************************
+
+sub do_small_cleanup {
+    # Assume dependency information from previous run has been obtained. 
+    my %other_generated = ();
+    my %cusdep_generated = ();
+    my @index_bibtex_generated = ();
+    my @aux_files = ();
+    my @missing_bib_files = ();
+    my $bibs_all_exist = 0;
+    my %final_output_files = ();
+    print "$My_name: Doing main (small) clean up for '$texfile_name'\n"
+        if ! $silent;
+
+    foreach (@final_output_exts) {
+        $final_output_files{"$out_dir1$root_filename.$_"} = 1;
+    }
+    rdb_for_actives(
+        sub {  # Find generated files at rule level
+               my ($base, $path, $ext) = fileparseA( $$Psource );
+               $base = $path.$base;
+               if ( $rule =~ /^makeindex/ ) {
+                   push @index_bibtex_generated, $$Psource, $$Pdest, "$base.ilg";
+               }
+               elsif ( $rule =~ /^(bibtex|biber)/ ) {
+                   push @index_bibtex_generated, $$Pdest, "$base.blg";
+                   push @aux_files, $$Psource;
+                   if ( $bibtex_use == 1.5) {
+                       foreach ( keys %$PHsource ) {
+                           if ( ( /\.bib$/ ) && (! -e $_) ) {
+                               push @missing_bib_files, $_;
+                           }
+                       }
+                   }
+               }
+               elsif ( $rule =~ /^(latex|lualtex|pdflatex|xelatex)/ ) {
+                   foreach my $key (keys %$PHdest) {
+                       $other_generated{$key} = 1;
+                   }
+               }
+               elsif ( ($rule =~ /^cusdep/) && (-e $$Psource) ) {
+                   # N.B. Deleting cusdep generated files is wrong if source file doesn't exist.
+                   #  But that will be taken care of in the rule-network setup.
+                   #  So just have a test for safety in the elsif line, without diagnostics.
+                   foreach my $key (keys %$PHdest) {
+                       $cusdep_generated{$key} = 1;
+                   }
+               }
+            },
+            sub {  # Find generated files at source file level
+               if ( $file =~ /\.aux$/ ) { push @aux_files, $file; }
+            }
+    );
+    if ($#missing_bib_files == -1) { $bibs_all_exist = 1; }
+    
+    my $keep_bbl = 1;
+    if ( ($bibtex_use > 1.6)
+         ||
+         (  ($bibtex_use == 1.5) && ($bibs_all_exist) )
+       ) {
+           $keep_bbl = 0;
+    }
+    if ($keep_bbl) {
+        delete $generated_exts{'bbl'}; 
+    }
+    # Convert some arrays to hashes, since deletions are easier to handle:
+    my %index_bibtex_generated = ();
+    my %aux_files = ();
+    my %aux_files_to_save = ();
+    foreach (@index_bibtex_generated) {
+        $index_bibtex_generated{$_} = 1
+           unless ( /\.bbl$/ && ($keep_bbl) );
+        delete( $other_generated{$_} );
+    }
+    foreach (@aux_files) {
+        if (exists $other_generated{$_} ) {
+            $aux_files{$_} = 1;
+        }
+        else {
+            $aux_files_to_save{$_} = 1;
+        }
+    }
+
+    foreach (keys %final_output_files) { delete $other_generated{$_}; }
+
+    if ($diagnostics) {
+        print "For deletion, files are as follows. Lists are non-exclusive.\n";
+        show_array( " Files specified by patterns\n"
+                    ." (explicit pattern with %R or root-filename.extension):",
+                    sort keys %generated_exts );
+        show_array( " Files determined from fdb file or log file that were generated by makeindex\n"
+                    ." or bibtex:", 
+                    sort keys %index_bibtex_generated );
+        show_array( " Aux files (from analysis of rules):", keys %aux_files );
+        show_array( " Aux files to SAVE and not delete:", keys %aux_files_to_save );
+        show_array( " Other non-cusdep generated files from *latex:\n"
+                    ." (only deleted if \$cleanup_includes_generated is set and file\n"
+                    ." doesn't appear in another list):",
+                    sort keys %other_generated );
+        show_array( " Cusdep generated files:\n"
+                   ." (only deleted if \$cleanup_includes_cusdep_generated is set and file\n"
+                    ." doesn't appear in another list):",
+                    sort keys %cusdep_generated );
+    }
+
+    my @clean_args = keys %generated_exts;
+    cleanup1( $aux_dir1, @clean_args );
+    if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @clean_args ); }
+
+    my @specific_deletions = @std_small_cleanup_files;
+    foreach my $file (@std_small_cleanup_files) {
+        foreach my $dir ($aux_dir1, $out_dir1 ) {
+            if ($dir) { push @specific_deletions, "$dir$file"; }
+        }
+    }
+    unlink_or_move( @specific_deletions,
+                    keys %index_bibtex_generated, 
+                    keys %aux_files );
+
+    if ($cleanup_includes_generated) {
+        unlink_or_move( keys %other_generated );
+    }
+    if ( $cleanup_includes_cusdep_generated) {
+        unlink_or_move( keys %cusdep_generated );
+    }
+    unlink_or_move( $fdb_name );
+    # If the fdb file (or log, fls and/or aux files), it/they will have been
+    #   used to make a changed rule database.  But a cleanup implies that we
+    #   need a virgin rule database, corresponding to current state of files,
+    #   so we reset the rule database and net:
+    &rdb_initialize_rules;
+}  # END do_small_cleanup
+
+#************************************************************
+
 sub do_cusdep {
     # Unconditional application of custom-dependency
     # except that rule is not applied if the source file source 
@@ -3259,7 +3459,7 @@
         # Source does not exist.  Users of this rule will need to turn
         # it off when custom dependencies are reset
         if ( !$silent ) {
-            warn "$My_name: In trying to apply custom-dependency rule\n",
+            print "$My_name: In trying to apply custom-dependency rule\n",
             "  to make '$$Pdest' from '$$Psource'\n",
             "  the source file has disappeared since the last run\n";
         }
@@ -3308,7 +3508,7 @@
     if ( &view_file_via_temporary ) {
         if ( $$Pext_cmd =~ /%D/ ) {
             my $tmpfile = tempfile1( "${root_filename}_tmp", $ext );
-            warn "$My_name: Making '$$Pdest' via temporary '$tmpfile'...\n";
+            print "$My_name: Making '$$Pdest' via temporary '$tmpfile'...\n";
             $return = &Run_subst( undef, undef, undef, undef, $tmpfile );
             move( $tmpfile, $$Pdest );
         }
@@ -3352,12 +3552,12 @@
         if ($$Pviewer_process == 0) {
             print "$My_name: need to signal viewer for file '$$Psource', but didn't get \n",
                   "   process ID for some reason, e.g., no viewer, bad configuration, bug\n"
-                if $diagnostics ;             
+                if $diagnostics;             
         }
         elsif ( defined $viewer_update_signal) {
             print "$My_name: signalling viewer, process ID $$Pviewer_process ",
                   "with signal $viewer_update_signal\n"
-                if $diagnostics ;
+                if $diagnostics;
             kill $viewer_update_signal, $$Pviewer_process;
         }
         else {
@@ -3415,9 +3615,9 @@
     # Treatment of extensions (in TeXLive 2019), with omission of path search:
     # Exists: always means exists as a file, i.e., not as a directory.
     #  A. Finding of tex file:
-    #   1. If extension is .tex and given_name.tex exists, use it.
+    #   1. If extension is .tex and given_name exists, use it.
     #   2. Else if given_name.tex exists, use it.
-    #   3. Else if givne_name exists, use it.
+    #   3. Else if given_name exists, use it.
     # B. The base filename is obtained by deleting the path
     #    component and the extension.
     # C. The names of generated files (log, aux) are obtained by appending
@@ -3448,7 +3648,7 @@
     elsif ( ($ext eq '.tex') && find_cus_dep( $given_name, $source_name ) ) {
        $tex_name = $given_name;
     }
-    elsif ( find_cus_dep( "$given_name.tex", \$source_name ) ) {
+    elsif ( find_cus_dep( "$given_name.tex", $source_name ) ) {
        $tex_name = "$given_name.tex";
        $base_name .= $ext;
     }
@@ -3470,7 +3670,9 @@
     $_[2] = $tex_name;
 
     if ($diagnostics) {
-       print "Given='$given_name', tex='$tex_name', base='$base_name', ext= $ext, source='$source_name'\n";
+        print "Given='$given_name', tex='$tex_name', base='$base_name', ext= $ext";
+        if ($source_name) { print ",  source='$source_name'"; }
+        print "\n";
     }
     return $fail;
 
@@ -3496,10 +3698,10 @@
     $quell_uptodate_msgs = 1;
 
     if ( ($view eq 'dvi') || ($view eq 'pdf') || ($view eq 'ps') ) { 
-        warn "Viewing $view\n";
+        print "Viewing $view\n";
     }
     elsif ( $view eq 'none' ) {
-        warn "Not using a previewer\n";
+        print "Not using a previewer\n";
         $view_file = '';
     }
     else {
@@ -3528,7 +3730,7 @@
         #    (We'll save starting up another viewer.)
         $$Pviewer_process = &find_process_id( $view_file );
         if ( $$Pviewer_process ) {
-            warn "$My_name: Previewer is already running\n" 
+            print "$My_name: Previewer is already running\n" 
               if !$silent;
             $viewer_running = 1;
             $$Pneed_to_get_viewer_process = 0;
@@ -3574,11 +3776,11 @@
             # Start the viewer
             if ( !$silent ) {
                 if ($new_viewer_always) {
-                    warn "$My_name: starting previewer for '$view_file'\n",
+                    print "$My_name: starting previewer for '$view_file'\n",
                          "------------\n";
                 }
                 else {
-                    warn "$My_name: I have not found a previewer that ",
+                    print "$My_name: I have not found a previewer that ",
                          "is already running. \n",
                          "   So I will start it for '$view_file'\n",
                          "------------\n";
@@ -3611,7 +3813,6 @@
 
             # So set the GENERATED files from *latex as up-to-date:
             rdb_for_some( [keys %current_primaries], \&rdb_update_gen_files );
-
             # And don't watch for changes for post_primary rules (ps and pdf 
             # from dvi, etc haven't been run after an error in *latex, so
             # are out-of-date by filetime criterion, but they should not be run
@@ -3640,8 +3841,7 @@
         if ($rules_list) { rdb_list(); }
         if ($show_time && ! $first_time) { show_timing(); }
         if ( $dependents_list && ($updated || $failure) ) {
-           my $deps_handle = new FileHandle "> $deps_file";
-           if ( defined $deps_handle ) {
+            if ( open( my $deps_handle, ">$deps_file" ) ) {
                deps_list($deps_handle);
                close($deps_handle);
            }
@@ -3651,7 +3851,8 @@
          }
 
         # Now wait for a file to change...
-        &rdb_cache_generated;
+        #        &rdb_cache_generated;
+        &rdb_set_rule_net;
         # During waiting for file changes, handle ctrl/C and ctrl/break here,
         #   rather than letting system handle them by terminating script (and
         #   code in the following command line to work: any script that calls
@@ -3668,7 +3869,7 @@
            if ($have_break) { last WAIT; }
            if ( rdb_user_changes(keys %rules_to_watch) ) { 
                if (!$silent) {
-                   warn "$My_name: Need to remake files.\n";
+                   print "$My_name: Need to remake files.\n";
                    &rdb_diagnose_changes( '  ' );
                }
                last WAIT;
@@ -3679,7 +3880,7 @@
            local $new_files = 0;
            rdb_for_some( [keys %current_primaries], sub{ $new_files += &rdb_find_new_files } );
            if ($new_files > 0) {
-               warn "$My_name: New file(s) found.\n";
+               print "$My_name: New file(s) found.\n";
                last WAIT; 
            }
            if ($have_break) { last WAIT; }
@@ -3697,7 +3898,7 @@
          print "$My_name: More than $pvc_timeout_mins mins of inactivity.  I'll finish.\n";
          return;
      }
-     $waiting = 0; if ($diagnostics) { warn "NOT       WAITING\n"; }
+     $waiting = 0; if ($diagnostics) { print "NOT       WAITING\n"; }
   } #end infinite_loop CHANGE:
 } #END sub make_preview_continuous
 
@@ -3704,8 +3905,16 @@
 #************************************************************
 
 sub process_rc_file {
-    # Usage process_rc_file( filename )
-    # NEW VERSION
+    # Usage process_rc_file( rc_file, [repeat_reaction] )
+    #   2nd argument controls action if the the file rc_file has already been
+    #   processed:
+    #      Omitted, undef, or 0: Silently ignore.  Used for processing
+    #                            standard rc files (system, user, current
+    #                            directory) since this situation legitimately
+    #                            occurs when cwd is one of the directories
+    #                            for the previously processed file.
+    #                     other: Give a warning, and don't process the file
+    #
     # Run rc_file whose name is given in first argument
     #    Exit with code 0 on success
     #    Exit with code 1 if file cannot be read or does not exist.
@@ -3712,14 +3921,27 @@
     #    Stop if there is a syntax error or other problem.
     # PREVIOUSLY: 
     #    Exit with code 2 if is a syntax error or other problem.
-    my $rc_file = $_[0];
+    my ($rc_file, $repeat_reaction) = @_;
+    my $abs_rc = abs_path($rc_file);
     my $ret_code = 0;
+    if ( exists $rc_files_read2{$abs_rc} ) {
+        if ( $repeat_reaction ) { 
+            warn
+                "$My_name: A user -r option asked me to process an rc file an extra time.\n",
+                "   Name of file = '$rc_file'\n",
+                ( ($rc_file ne $abs_rc) ? "   Abs. path = '$abs_rc'\n": ""),
+                "  I'll not process it\n";
+        }
+        return 0;
+    }
+    else {
+        $rc_files_read2{$abs_rc} = 1;
+    }
     push @rc_files_read, $rc_file;
 
     # I could use the do command of perl, but the preceeding -r test
     # to get good diagnostics gets the wrong result under cygwin
     # (e.g., on /cygdrive/c/latexmk/LatexMk)
-    my $RCH = new FileHandle;
     if ( !-e $rc_file ) {
         warn "$My_name: The rc-file '$rc_file' does not exist\n";
         return 1;
@@ -3729,9 +3951,10 @@
              "          should be a normal text file\n";
         return 1;
     }
-    elsif ( open $RCH, "<$rc_file" ) {
+    elsif ( open( my $RCH, "<", $rc_file ) ) {
         my $code = '';
-        { local $/; $code = <$RCH>;}
+        # Read all contents of file into $code:
+        { local $/ = undef; $code = <$RCH>;}
         close $RCH;
         eval $code;
     }
@@ -3739,13 +3962,6 @@
         warn "$My_name: I cannot read the rc-file '$rc_file'\n";
         return 1;
     }
-    # PREVIOUS VERSION
-#    if ( ! -r $rc_file ) {
-#        warn "$My_name: I cannot read the rc-file '$rc_file'\n",
-#            "          or at least that's what Perl (for $^O) reports\n";
-#        return 1;
-#    }
-#    do( $rc_file );
     if ( $@ ) {
         # Indent each line of possibly multiline message:
         my $message = prefix( $@, "     " );
@@ -3768,7 +3984,7 @@
     #     But I can always catch it with an eval if necessary.
     #     That confuses ctrl/C and ctrl/break handling.
     my $code = $_[0];
-    warn "$My_name: Executing initialization code specified by -e:\n",
+    print "$My_name: Executing initialization code specified by -e:\n",
          "   '$code'...\n" 
         if  $diagnostics;
     eval $code;
@@ -3823,7 +4039,7 @@
        return;
     }
     if ( ! -e $$Psource ) {
-        warn "$My_name: For custom dependency '$rule',\n",
+        print "$My_name: For custom dependency '$rule',\n",
              "    I won't delete destination file '$$Pdest'\n",
              "    and any other generated files,\n",
              "    because the source file '$$Psource' doesn't exist,\n",
@@ -3888,10 +4104,10 @@
 sub warn_running {
    # Message about running program:
     if ( $silent ) {
-        warn "$My_name: @_\n";
+        print "$My_name: @_\n";
     }
     else {
-        warn "------------\n at _\n------------\n";
+        print "------------\n at _\n------------\n";
     }
 } #END warn_running
 
@@ -3900,7 +4116,7 @@
 sub exit_help
 # Exit giving diagnostic from arguments and how to get help.
 {
-    warn "\n$My_name: @_\n",
+    print "\n$My_name: @_\n",
          "Use\n",
          "   $my_name -help\nto get usage information\n";
     exit 10;
@@ -4084,7 +4300,7 @@
 #************************************************************
 
 sub print_commands {
-  warn "Commands used by $my_name:\n",
+  print "Commands used by $my_name:\n",
        "   To run latex, I use \"$latex\"\n",
        "   To run pdflatex, I use \"$pdflatex\"\n",
        "   To run lualatex, I use \"$lualatex\"\n",
@@ -4110,7 +4326,7 @@
        "   To print a pdf file, I use \"$lpr_pdf\"\n",
        "   To find running processes, I use \"$pscmd\", \n",
        "      and the process number is at position $pid_position\n";
-   warn "Notes:\n",
+   print "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",
@@ -4146,8 +4362,7 @@
     my $base = $_[0];
     my $Pbiber_source = $_[1];
     my $blg_name = "$base.blg";
-    my $blg_file = new FileHandle;
-    open( $blg_file, "<$blg_name" )
+    open( my $blg_file, "<", $blg_name )
       or return 3;
     my $have_warning = 0;
     my $have_error = 0;
@@ -4163,6 +4378,7 @@
     my $control_file_malformed = 0;
     my %remote = ();                # List of extensions of remote files
     while (<$blg_file>) {
+        $_ = utf8_to_mine($_);
         if (/> WARN /) { 
             print "Biber warning: $_"; 
             $have_warning = 1;
@@ -4239,13 +4455,13 @@
     @$Pbiber_source = uniqs( @$Pbiber_source );
 
     if ( ($#not_found < 0) && ($#$Pbiber_source >= 0) ) {
-        warn "$My_name: Found biber source file(s) [@$Pbiber_source]\n"
+        print "$My_name: Found biber source file(s) [@$Pbiber_source]\n"
         unless $silent;
     }
     elsif ( ($#not_found == 0) && ($not_found[0] =~ /\.bib$/) ) {
         # Special treatment if sole missing file is bib file
         # I don't want to treat that as an error
-        warn "$My_name: Biber did't find bib file [$not_found[0]]\n";
+        print "$My_name: Biber did't find bib file [$not_found[0]]\n";
         return 5;
     }
     else {
@@ -4347,7 +4563,7 @@
         $return = &Run_subst( undef, undef, '', $source_base, $dest_base, $base );
         popd();
         if (!$silent) {
-            print "$My_name: Change directory back to '", cwd(), "'\n";
+            print "$My_name: Change directory back to '$cwd'\n";
         }
     }
     else {
@@ -4370,8 +4586,7 @@
 
     my $base = $_[0];
     my $blg_name = "$base.blg";
-    my $blg_file = new FileHandle;
-    open( $blg_file, "<$blg_name" )
+    open( my $blg_file, "<", $blg_name )
       or return 3;
     my $have_warning = 0;
     my $have_error = 0;
@@ -4379,6 +4594,7 @@
     my @missing_aux = ();
     my $error_count = 0;
     while (<$blg_file>) {
+        $_ = utf8_to_mine($_);
         if (/^Warning--/) { 
             #print "Bibtex warning: $_"; 
             $have_warning = 1;
@@ -4399,7 +4615,7 @@
     my $missing = $missing_citations + $#missing_aux + 1;
     if ( $#missing_aux > -1 ) {
         # Need to make the missing files.
-        warn "$My_name: One or more aux files is missing for bibtex. I'll try\n",
+        print "$My_name: One or more aux files is missing for bibtex. I'll try\n",
              "          to get *latex to remake them.\n";
         rdb_for_some( [keys %current_primaries], sub{ $$Pout_of_date = 1; } );
     }
@@ -4467,7 +4683,6 @@
     #       .fls file in out_dir, not aux_dir, which seems
     #       not natural.
     $fls_name = "%Z%R.fls";
-
     $dvi_name  = "%Z%R.dvi";
     $dviF_name = "%Z%R.dviF";
     $ps_name   = "%Z%R.ps";
@@ -4511,7 +4726,7 @@
         my $from =  "$aux_dir1$root_filename.$ext";
         my $to = "$out_dir1$root_filename.$ext" ;
         if ( test_gen_file( $from ) ) {
-            if (! $silent) { warn "$My_name: Moving '$from' to '$to'\n"; }
+            if (! $silent) { print "$My_name: Moving '$from' to '$to'\n"; }
             my $ret = move( $from, $to );
             if ( ! $ret ) { die "  That failed, with message '$!'\n";}
         }
@@ -4521,9 +4736,13 @@
 #***************************************************
 
 sub parse_log {
-# Scan log file for: dependent files
-#    reference_changed, bad_reference, bad_citation
-# Return value: 1 if success, 0 if no log file.
+# Use: parse_log( log_file_name,
+#                 ref to array containing lines,
+#                 ref to hash containing diagnostic etc information )
+# Given lines from already read log file, scan them for: dependent files
+#    reference_changed, bad_reference, bad_citation.
+# Assume in the lines array, lines are already wrapped, and converted to my CS.   
+# Return value: 1 if success, 0 if problems.
 # Put results in UPDATES of global variables (which are normally declared
 # local in calling routine, to be suitably scoped):
 #   %dependents: maps definite dependents to code:
@@ -4571,8 +4790,9 @@
 #
 # Input globals: $primary_out, $fls_file_analyzed
 #
+
+my ($log_name, $PAlines, $PHinfo) = @_;
    
-   
 # Give a quick way of looking up custom-dependency extensions
     my %cusdep_from = ();
     my %cusdep_to = ();
@@ -4581,11 +4801,7 @@
         $cusdep_from{$fromext} = $cusdep_from{".$fromext"} = $_;
         $cusdep_to{$toext} = $cusdep_to{".$toext"} = $_;
     }
-#    print "==== Cusdep from-exts:"; foreach (keys %cusdep_from) {print " '$_'";} print "\n";
-#    print "==== Cusdep to-exts:"; foreach (keys %cusdep_to) {print " '$_'";} print "\n";
 
-
-
     # $primary_out is actual output file (dvi or pdf)
     # It is initialized before the call to this routine, to ensure
     # a sensible default in case of misparsing
@@ -4596,71 +4812,14 @@
     $bad_character = 0;
     $bad_citation = 0;
 
-    my $log_file = new FileHandle;
-    if ( ! open( $log_file, "<$log_name" ) ) {
-        return 0;
-    }
     print "$My_name: Examining '$log_name'\n"
         if not $silent;
-    if ($log_file_binary) { binmode $log_file; }
-# Collect lines of log file
-    my @lines = ();
-    my $line = 0;
-    my $engine = 'pdfTeX';  # Simple default in case of problems
-    while(<$log_file>) {
-        $line++;
-        # Could use chomp here, but that fails if there is a mismatch
-        #    between the end-of-line sequence used by latex and that
-        #    used by perl.  (Notably a problem with MSWin latex and
-        #    cygwin perl!)
-        s/[\n\r]*$//;
-        # Handle wrapped lines:
-        # They are lines brutally broken at exactly $log_wrap chars 
-        #    excluding line-end.  Sometimes a line $log_wrap chars 
-        #    long is an ordinary line, sometimes it is part of a line
-        #    that was wrapped.  To handle all cases, I keep both
-        #    options open by putting the line into @lines before
-        #    and after appending the next line:  
-        my $len = length($_);
-        if ($line == 1) {
-            if ( /^This is ([^,]+), / ) {
-                $engine = $1;
-                print "=== TeX engine is '$engine'\n"
-                    if (!$silent);
-                if ( /^This is ([^,]+), [^\(]*\(([^\)]+)\)/ ) {
-                    $tex_distribution = $2;
-                    print "=== TeX distribution is '$tex_distribution'\n"
-                        if ($diagnostics);
-                }
-            }
-            else {
-                warn "$My_name: First line of .log file '$log_name' is not in standard format.\n";
-            }
-        }
-        else {
-            # Xetex and luatex sometimes wrap at longer line lengths:
-            # LuaTeX sometimes at 80. Xetex 80 or longer with non-ascii characters.
-            while ( ( ($len == $log_wrap)
-                      || ( ($engine eq 'LuaTeX') && ($len == $log_wrap+1) )
-                      || ( ($engine eq 'LuaHBTeX') && ($len == $log_wrap+1) )
-                      || ( ($engine eq 'XeTeX') &&  ($len >= $log_wrap+1) )
-                    )
-                    && !eof($log_file) ) {
-                push @lines, $_;
-                my $extra = <$log_file>;
-                $extra =~ s/[\n\r]*$//;
-                $len = length($extra);
-                $_ .= $extra;
-            }
-        }
-        push @lines, $_;
-    }
-    close $log_file;
 
-    push @lines, "";   # Blank line to terminate.  So multiline blocks 
-              # are always terminated by non-block line, rather than eof.
-    
-    $line = 0;
+    my $engine = $$PHinfo{engine};
+    my $tex_distribution = $$PHinfo{distribution};
+
+    # Now analyze the result:
+    $line_num = 0;
     my $state = 0;   # 0 => before ** line,
                      # 1 => after **filename line, before next line (first file-reading line)
                      # 2 => pwd_log determined.
@@ -4675,18 +4834,12 @@
     my $delegated_output = "";   #    and output file.  (Don't put in
                                  #    data structure until block is ended.)
     my %new_conversions = ();
-    my @retries = ();
     my $log_silent = ($silent ||  $silence_logfile_warnings);
-    my @warning_list = ();
+    @warning_list = ();
+
 LINE:
-    while( ($line <= $#lines) || ($#retries > -1) ) { 
-        if ($#retries > -1) {
-            $_ = pop @retries;
-        }
-        else {
-            $_ = $lines[$line];
-            $line ++;
-        }
+    for (@$PAlines) {
+        $line_num++;
         if ( /^! pdfTeX warning/ || /^pdfTeX warning/ ) {
             # This kind of warning is produced by some versions of pdftex
             # or produced by my reparse of warnings from other
@@ -4693,24 +4846,14 @@
             # versions.
             next;
         }
-        elsif ( /^(.+)(pdfTeX warning.*)$/ ) {
-            # Line contains a pdfTeX warnings that may have been
-            # inserted directly after other material without an
-            # intervening new line.  I think pdfTeX always inserts a
-            # newline after the warning.  (From examination of source
-            # code.) 
-            push @retries, $1;
-            # But continue parsing the original line, in case it was a
-            # misparse, e.g., of a filename ending in 'pdfTeX';
-        }
-        if ( $line == 1 ){
+        if ( $line_num == 1 ){
             if ( /^This is / ) {
                 # First line OK
                 next LINE;
             } else {
                 warn "$My_name: Error on first line of '$log_name'.\n".
-                    "This is apparently not a TeX log file.  ",
-                    "The first line is:\n$_\n";
+                     "  This is apparently not a TeX log file.  ",
+                     "  The first line is:\n$_\n";
                 $failure = 1;
                 $failure_msg = "Log file '$log_name' appears to have wrong format.";
                 return 0;
@@ -4769,7 +4912,7 @@
 
         # Check for changed references, bad references and bad citations:
         if (/Rerun to get/) { 
-            warn "$My_name: References changed.\n" if ! $log_silent;
+            print "$My_name: References changed.\n" if ! $log_silent;
             $reference_changed = 1;
         } 
         if (/^LaTeX Warning: (Reference[^\001]*undefined on input line .*)\./) {
@@ -4804,12 +4947,12 @@
         }
         elsif (/^No pages of output\./) {
             $primary_out = ''; 
-            warn "$My_name: Log file says no output from latex\n";
+            print "$My_name: Log file says no output from latex\n";
             next LINE;
         }
         elsif ( /^Output written on\s+(.*)\s+\(\d+\s+page/ ) {
             $primary_out = normalize_clean_filename($1, @pwd_log);
-            warn "$My_name: Log file says output to '$primary_out'\n"
+            print "$My_name: Log file says output to '$primary_out'\n"
                unless $silent;
             next LINE;
         }
@@ -4885,14 +5028,14 @@
             $idx_base = $idx_path.$idx_base;
             $idx_file = $idx_base.$idx_ext;
             if ( $idx_ext eq '.idx' ) {
-                warn "$My_name: Index file '$idx_file' was written\n"
+                print "$My_name: Index file '$idx_file' was written\n"
                   unless $silent;
                 $idx_files{$idx_file} = [ "$idx_base.ind", $idx_base ];
             }
             elsif ( exists $cusdep_from{$idx_ext} ) {
                 if ( !$silent ) {
-                    warn "$My_name: Index file '$idx_file' was written\n";
-                    warn "   Cusdep '$cusdep_from{$idx_ext}' should be used\n";
+                    print "$My_name: Index file '$idx_file' was written\n";
+                    print "   Cusdep '$cusdep_from{$idx_ext}' should be used\n";
                 }
                 # No action needed here
             }
@@ -5134,7 +5277,7 @@
                 $dependents{$include_name} = 3;
             }
             if ( $ext eq '.bbl' ) {
-                warn "$My_name: Found input bbl file '$include_name'\n"
+                print "$My_name: Found input bbl file '$include_name'\n"
                    unless $silent;
                 push @bbl_files, $include_name;
             }
@@ -5144,9 +5287,6 @@
     # Default includes are always definitive:
     foreach (@default_includes) { $dependents{$_} = 4; }
 
-    ###print "New parse: \n";
-    ###foreach (sort keys %dependents) { print "  '$_': $dependents{$_}\n"; }
-
     my @misparsed = ();
     my @missing = ();
     my @not_found = ();
@@ -5267,12 +5407,6 @@
             }
         }
     }
-
-    if ( ($#warning_list >= 0) && !$log_silent ) {
-        @warning_list = uniqs( @warning_list );
-        show_array( "$My_name: List of undefined refs and citations:",
-                    @warning_list );
-    }
     
     if ( $diagnostics ) {
         @misparse = uniqs( @misparse );
@@ -5298,21 +5432,17 @@
             print "\n";
         }
         if ($not_found > 0) {
-            print "Not found:\n";
-            foreach (@not_found) { print "   $_\n"; }
+            show_array( "Not found:", @not_found );
         }
         if ($missing > 0) {
-            print "Not existent:\n";
-            foreach (@missing) { print "   $_\n"; }
+            show_array( "Not existent:", @missing );
         }
         if ( $bbl > 0 ) {
-            print "Input bbl files:\n";
-            foreach (@bbl_files) { print "   $_\n"; }
+            show_array( "Input bbl files:", @bbl_files );
         }
 
         if ( $misparse > 0 ) {
-            print "Possible input files, perhaps from misunderstood lines in .log file:\n";
-            foreach ( @misparse ) { print "   $_\n"; }
+            show_array( "Possible input files, perhaps from misunderstood lines in .log file:",  @misparse );
         }
     }
     return 1;
@@ -5320,61 +5450,157 @@
 
 #************************************************************
 
+sub get_log_file {
+    # Use: get_log_file( log_file_name,
+    #                    ref to array to receive lines,
+    #                    ref to hash to receive diagnostic etc informaion )
+    # 3rd argument is optional
+    # Lines are unwrapped and converted to CS_system.
+    
+    my ($file, $PAlines, $PHinfo) = @_;
+
+    # Essential to use byte semantics, since (pdf)latex & lualatex
+    # wrap by bytes, not characters
+    use bytes;
+
+    # Where lines are wrapped at.  We'll sometimes override.
+    local $log_wrap = $log_wrap;
+
+    my $engine = '';
+    my $tex_distribution = '';
+    my ($line_num, $cont, $max_len) = ( 0, 0, 0 );
+    my $lua_mode = 0;  # Whether to use luatex-specific wrapping method.
+    my $byte_wrapping = 1;  # *latex does byte wrapping.  Modify if we find
+                            # log file is generated by a tex program that
+                            # wrapping by Unicode code points.
+
+    # File encoding: pdftex: UTF-8 but with wrapping at $log_wrap BYTES.
+    #                        (So individual wrapped lines can be malformed
+    #                        UTF-8, but we get valid UTF-8 after unwrapping.)
+    #                luatex: UTF-8 but with wrapping at APPROXIMATELY
+    #                        $log_wrap bytes. Rest as pdftex
+    #                xetex:  UTF-8 with wrapping at $log_wrap codepoints.
+    # So start reading file as bytes; first line gives which program,
+    # and for xetex we switch to reading file as UTF-8.
+    print "$My_name: Getting log file '$file'\n";
+    open( my $fh, '<', $file )
+        or return 0;
+  LINE:
+    while (<$fh> ) {
+        $line_num++;
+        s/\r?\n$//;
+        if ($line_num == 1) {
+            if ( /^This is ([^,]+), [^\(]*\(([^\)]+)\)/ ) {
+                $engine = $1;
+                $tex_distribution = $2;
+            }
+            else {
+                warn "$My_name: First line of .log file '$file' is not in standard format.\n";
+            }
+            if ( $engine =~ /XeTeX/i ) {
+                $byte_wrapping = 0;
+            }
+            $lua_mode = ( $engine =~ /lua.*tex/i );
+            # TeXLive's *tex take log wrap value from environment variable max_print_line, if it exists:
+            if ( ($tex_distribution =~ /TeX\s*Live/) && $ENV{max_print_line} ) {
+                $log_wrap = $ENV{max_print_line};
+                print "$My_name: changed column for log file wrapping from standard to $log_wrap\n".
+                      "  from env. var. max_print_line, which is obeyed by your TeXLive programs\n"
+                   if $diagnostics;
+            }
+            # First (signon) line of log file doesn't get wrapped
+            push @$PAlines, $_;
+            next LINE;
+        }
+        my $len = 0;
+        if ($byte_wrapping) { $len = length($_); }
+        else {
+            no bytes;
+            $len = length( decode('UTF-8', $_) );
+        }
+        if ($len > $max_len) { $max_len = $len }
+
+        # Is this line continuation of previous line?
+        if ($cont) { $$PAlines[$#$PAlines] .= $_; }
+        else { push @$PAlines, $_ }
+
+        # Is this line wrapped? I.e., is next line to be appended to it?
+        # Allow for fact that luatex doesn't reliably wrap at std place, e.g., 79.
+        $cont = ($len == $log_wrap)
+            || ( $lua_mode && ($len >= $log_wrap-2) && ($len <= $log_wrap+1) );
+        if ($cont && $diagnostics ) {
+            print "====Continuing line $line_num of length $len\n$_\n";
+        }
+    }
+    close($fh);
+    foreach (@$PAlines) { $_ = utf8_to_mine($_); }
+    push @$PAlines, "";  # Blank line to terminate.  So multiline blocks 
+              # are always terminated by non-block line, rather than eof.
+    $$PHinfo{max_len} = $max_len;
+    $$PHinfo{num_lines} = $line_num;
+    $$PHinfo{num_after} = 1 + $#$PAlines;
+    $$PHinfo{engine} = $engine;
+    $$PHinfo{distribution} = $tex_distribution;
+    return 1;
+} #END get_log_file
+
+#=====================================
+
 sub find_set_log {
-    # Locate the log file, if possible.  This allows for possible configuration
-    # errors, e.g., because the command for (*)latex was such that it did not 
-    # do the setting of -output-directory or -aux-directory that the user intended,
-    # or because the version used did not support one or other of these options.
-    # Put result in $where_log (see its initial declaration/definition for details).
-    # Change $aux_dir and/or $out_dir as appropriate, and make consequent changes.
+    # Locate the log file, generated on this run.
+    # It should be in aux_dir. But:
+    #  1. With a sufficiently severe error in *latex, no log file was generated.
+    #  2. With aux_dir ne out_dir and emulate_aux off and a (TeXLive) *latex
+    #     that doesn't support aux_dir, the log file is in out_dir.
+    #  3. If the specified command has no %O or if *latex doesn't support
+    #     out_dir (hence not TeXLive and not MiKTeX), the log file would
+    #     be in cwd.
     #
-    # Probably further attention to location of output file (.dvi, .pdf, or .xdv)
-    # could be done, to get $out_dir and $$Pdest more accurately set.
+    #  3 is fatal error.
+    #  2 is handled by turning emulate_aux on, after which next run of *latex
+    #    handles problem.
+    #  1 is like any other error.
+    #  4 is treated like 1 (log file not found).
     #
-    # Typical configuration errors that lead to the need for this subroutine:
-    #        %O not used in command definition, so directory options don't getpassed
-    #           to (*)latex.
-    #        Use of $aux_dir different to $out_dir, when (*)latex doesn't support
-    #           the -aux-directory option (notably with TeXLive distribution).
-    if ($where_log == 1) {
-        # .log file was found in correct place on previous run.
-        # So there's no need to repeat search, since if the location were to
-        # change from run to run, we'd have other serious difficulties that are
-        # to hard to deal with.
-        return;
-    }
+    # Returns 
+    #    0 log file not found;
+    #    1 log file in aux_dir i.e., correct place;
+    #    2 log file **not** in aux_dir but in out_dir,
+    #      emulate_aux turned on, commands fixed,
+    #      and log file copied to aux_dir
+    # If the log file is found in cwd, report it and give fatal error.
+    
+    my $where_log = -1; # Nothing analyzed yet
+
     if ( test_gen_file( "$aux_dir1$root_filename.log" ) ) {
         # .log file is in expected place.
         $where_log = 1;
     }
-    elsif ( test_gen_file( "$out_dir1$root_filename.log" ) ) {
-        # .log file is in out_dir not in aux_dir.
-        # Presumably there is a configuration error
-        # that prevents aux_dir from being used by latex.
-        warn "$My_name: .log file in '$out_dir' instead of expected '$aux_dir'\n";
-        if ($emulate_aux) {
-            warn "    But emulate_aux is on, so that should not happen\n",
-                 "    I'll switch aux_dir to equal out_dir\n";
-            $where_log = 2;
-            $aux_dir = $out_dir;
+    elsif ( (! $emulate_aux) && test_gen_file( "$out_dir1$root_filename.log" ) ) {
+        warn "$My_name: .log file in '$out_dir' instead of expected '$aux_dir'\n",
+             "   But emulate_aux is off.  So I'll turn it on.\n",
+             "   I'll copy the log file to the correct place.\n",
+             "   The next run of *latex **SHOULD** not have this problem.\n";
+        copy( "$out_dir1$root_filename.log", "$aux_dir1$root_filename.log" );
+        $where_log = 2;
+        $emulate_aux = 1;
+        $emulate_aux_switched = 1;
+        # Fix up commands to have fudged use of directories for
+        # use with non-aux-dir-supported *latex engines.
+        foreach ( $$Pext_cmd ) {
+            s/ -output-directory=[^ ]*(?= )//g;
+            s/ -aux(-directory=[^ ]*)(?= )/ -output$1/g;
         }
-        else {
-            warn "    But emulate_aux is off.  So I'll turn it on.\n";
-            $emulate_aux = 1;
-            $emulate_aux_switched = 1;
-            foreach ( $$Pext_cmd ) {
-                s/ -output-directory=[^ ]*(?= )//g;
-                s/ -aux(-directory=[^ ]*)(?= )/ -output$1/g;
-            }
-        }
     }
     elsif ( test_gen_file( "$root_filename.log" ) ) {
         # .log file is not in out_dir nor in aux_dir, but is in cwd.
         # Presumably there is a configuration error
         # that prevents the directories from being used by latex.
-        # So change $aux_dir to the actually used value.
-        $where_log = 3;
-        $aux_dir = "";
+        die "$My_name: The log file found was '$root_filename.log' instead of\n",
+            "  '$aux_dir1$root_filename.log'.  Probably a configuration error\n",
+            "  prevented the use of the -aux-directory and/or the -output-directory\n",
+            "  options with the *latex command.\n",
+            "  I'll stop.\n";
     }
     else {
         # No .log file found
@@ -5384,18 +5610,7 @@
         $failure_msg 
             = "*LaTeX didn't generate the expected log file '$log_name'\n";
     }
-    if ($where_log > 1) {
-        warn "$My_name: Changed aux_dir from '$aux_dir_requested' to '$aux_dir'\n".
-             "          to allow for probable configuration error\n";
-        # Allow for the changes associated with change of $aux_dir:
-        &normalize_aux_out_ETC;
-        &set_names;
-        warn "$My_name: Actual .log file is\n",
-             "     '$log_name'\n",
-             "  instead of the value\n",
-             "     '$aux_dir_requested/$root_filename.log'\n",
-             "   that seemed to be intended.\n";
-    }
+    return $where_log;
 } #END find_set_log
 
 #************************************************************
@@ -5404,7 +5619,7 @@
     my $start_time = processing_time();  
     my ($fls_name, $Pinputs, $Poutputs, $Pfirst_read_after_write, $Ppwd_latex ) = @_;
     %$Pinputs = %$Poutputs = %$Pfirst_read_after_write = ();
-    my $fls_file = new FileHandle;
+    my $fls_file;
     # Make a note of current working directory
     # I'll update it from the fls file later
     # Currently I don't use this, but it would be useful to use
@@ -5421,23 +5636,39 @@
     # be definitive in the fls file.
 
     my $cwd = good_cwd();
-    if ( ! open ($fls_file, "<$fls_name") ) {
+    if ( ! open($fls_file, "<", $fls_name) ) {
+#    if ( ! open($fls_file, "<:encoding(UTF-8)", $fls_name) ) {
         return 1;
     }
 
+    print "$My_name: Examining '$fls_name'\n"
+        if not $silent;
+
     my $pdf_base = basename($pdf_name);
     my $log_base = basename($log_name);
     my $out_base = basename($$Pdest);
-
-    foreach $_ ( <$fls_file> ) {
+    my $pwd_subst = undef; # Initial string for pwd that is to be removed to
+                           # make relative paths, when possible.  It must end
+                           # in '/', if defined.
+    for ( <$fls_file> ) {
         # Remove trailing CR and LF. Thus we get correct behavior when an fls file
         #  is produced by MS-Windows program (e.g., in MiKTeX) with CRLF line ends,
         #  but is read by Unix Perl (which treats LF as line end, and preserves CRLF
         #  in read-in lines):
-        $_ =~ s/[\n\r]*$//;
+        # And convert '\'
+        s/\r?\n$//;
+        s[\\][/]g;
+        if (($^O eq 'MSWin32') && /PWD/ && is_valid_utf8($_) ) {
+            # TeXLive produces PWD in CS_system not UTF-8.
+            # ???? Later get tex_distribution before analyzing fls file, so do better test.
+            print "PWD line not in UTF-8\n";
+            # Assume in CS_system, no change needed.
+        }
+        else { $_ = utf8_to_mine($_); }
         if (/^\s*PWD\s+(.*)$/) {
             my $cwd_fls = $1;
-            $$Ppwd_latex = $cwd_fls;
+            $pwd_subst = $$Ppwd_latex = $cwd_fls;
+            if ($pwd_subst !~ m[/$] ) { $pwd_subst .= '/'; }
             if ( $cwd_fls =~ /\"/ ) {
                 warn "$My_name: The working directory has a '\"' character in its name:\n",
                      "  '$cwd'\n  This can cause me trouble. Beware!\n";
@@ -5454,8 +5685,8 @@
             #   us from coding issues if the PWD contains non-ASCII characters.  What
             #   coding scheme (UTF-8, code page, etc) is used depends on OS, TeX
             #   implementation, ...
-            if ( defined $$Ppwd_latex ) { 
-                $file =~ s(^\Q$$Ppwd_latex\E[\\/])();
+            if ( defined $pwd_subst ) { 
+                $file =~ s(^\Q$pwd_subst\E)();
             }
             $file = normalize_filename( $file );
             if ( (exists $$Poutputs{$file}) && (! exists $$Pinputs{$file}) ) {
@@ -5546,48 +5777,52 @@
 # ------------------------------
 
 sub normalize_filename {
-   # Usage: normalize_filename( filename [, extra forms of name of cwd] )
-   # Returns filename with removal of various forms for cwd, and
-   # with conversion of directory separator to '/' only.
-   # Also when filename is name of a directory, with a trailing '/',
-   #   the trailing '/' is removed.
-   #
-   my ( $file, @dirs ) = @_;
-   my $file1 = $file;   # Saved original value
-   my $cwd = good_cwd();
-   # Normalize files to use / to separate directory components:
-   # (Note both / and \ are allowed under MSWin.)
-   foreach ($cwd, $file,  @dirs) {
-       s(\\)(/)g;
-       # If this is directory name of form :.../", remove unnecessary
-       # trailing directory separators:
-       $_ = dirname_no_tail( $_ );
-   }
-   
-   # Remove initial component equal to current working directory.
-   # Use \Q and \E round directory name in regex to avoid interpretation
-   #   of metacharacters in directory name:
-   foreach my $dir ( @dirs, '.', $cwd ) {
-       if ( $dir =~ /^\s*$/ ) {
-           # All spaces, nothing to do.
-           next;
-       }
-       if ($file eq $dir) {
-           # Filename equals cwd, so it is . relative to cwd:
-           $file = '.';
-           last;
-       }
-       if ( $file =~ s(^\Q$dir\E/)() ) {
-           last;
-     }
-   }
-   if ($file eq '' ) {
-       # This only occurs for $file equal to a directory that
-       # is the cwd. Our convention is always to set it to '.'
-       # 
-       $file = '.';
-   }
-   return $file;
+    # Usage: normalize_filename( filename [, extra forms of name of cwd] )
+    # Returns filename with removal of various forms for cwd, and
+    # with conversion of directory separator to '/' only,
+    # and with use of my current choice of Unicode normalization.
+    # Also when filename is name of a directory, with a trailing '/',
+    #   the trailing '/' is removed.
+    # ????In presence of accented characters in directory names, intended
+    # functioning is when all cwd strings are in my chosen NF.
+    #
+    my ( $file, @dirs ) = @_;
+    my $cwd = good_cwd();
+    # Normalize files to use / to separate directory components:
+    # (Note both / and \ are allowed under MSWin.)
+    foreach ($cwd, $file,  @dirs) {
+        s(\\)(/)g;
+        # If this is directory name of form :.../", remove unnecessary
+        # trailing directory separators:
+        $_ = dirname_no_tail( $_ );
+    }
+
+    # Remove initial component equal to current working directory.
+    # Use \Q and \E round directory name in regex to avoid interpretation
+    #   of metacharacters in directory name:
+    foreach my $dir ( @dirs, '.', $cwd ) {
+        if ( $dir =~ /^\s*$/ ) {
+            # All spaces, nothing to do.
+            next;
+        }
+        if ($file eq $dir) {
+            # Filename equals cwd, so it is . relative to cwd:
+            $file = '.';
+            last;
+        }
+        my $subst = $dir;
+        if ($subst !~ m[/$]) { $subst .= '/'; }
+        if ( $file =~ s(^\Q$subst\E)() ) {
+            last;
+      }
+    }
+    if ($file eq '' ) {
+        # This only occurs for $file equal to a directory that
+        # is the cwd. Our convention is always to set it to '.'
+        # 
+        $file = '.';
+    }
+    return $file;
 } #END normalize_filename
 
 # ------------------------------
@@ -5652,7 +5887,7 @@
     @$Pbst_files = uniqs( @$Pbst_files );
 
     if ( $#{$Pbib_files} == -1 ) {
-        warn "$My_name: No .bib files listed in .aux file '$aux_file' \n",
+        print "$My_name: No .bib files listed in .aux file '$aux_file' \n",
         return 2;
     }
     my @not_found = &find_file_list1( $Pbib_files, $Pbib_files,
@@ -5671,7 +5906,7 @@
             return 3;
     }
     if ( $#not_found < 0) {
-        warn "$My_name: Found bibliography file(s) [@$Pbib_files]\n"
+        print "$My_name: Found bibliography file(s) [@$Pbib_files]\n"
         unless $silent;
     }
     else {
@@ -5699,7 +5934,7 @@
 #   Return 0 if fail to open it
 {
    my $aux_file = $_[0];
-   my $aux_fh = new FileHandle;
+   my $aux_fh;
    if (! open($aux_fh, $aux_file) ) { 
        warn "$My_name: Couldn't find aux file '$aux_file'\n";
        return 0; 
@@ -5707,6 +5942,7 @@
    push @$Paux_files, $aux_file;
 AUX_LINE:
    while (<$aux_fh>) {
+      $_ = utf8_to_mine($_);
       if ( /^\\bibdata\{(.*)\}/ ) { 
           # \\bibdata{comma_separated_list_of_bib_file_names}
           # These are normally without the '.bib' extension.
@@ -5722,9 +5958,7 @@
           &parse_aux1( $aux_dir1.$1 );
       }
       else {
-          foreach my $Psub (@aux_hooks) {
-              &$Psub;
-          }
+          run_hooks( 'aux_hooks' );
       }
    }
    close($aux_fh);
@@ -5838,9 +6072,16 @@
 #************************************************************
 
 sub rdb_read {
-    # Call: rdb_read( $in_name  )
+    # Call: rdb_read( $in_name, inhibit_output_switch  )
     # Sets rule database from saved file, in format written by rdb_write.
-    # Returns -1 if file could not be read else number of errors.
+    # The second argument controls behavior when there's a mismatch between
+    # output extensions for primary rule in the cache and current settings.
+    # If the second argument is true, omit a switch of output extension,
+    # otherwise let the cached setting be obeyed (if possible).
+    #
+    # Returns: -2 if file doesn't exist,
+    #          -1 if file existed but couldn't be read
+    #          else number of errors.
     # Thus return value on success is 0
     # Requires: Rule database initialized with standard rules, with
     #             conditions corresponding to requests determined by
@@ -5865,14 +6106,30 @@
     #       may/should be in the future.)
     #   (e) Something else, e.g., copying/editing of fdb_latexmk file.
     #
-    local $in_name = $_[0];
-    my $in_handle = new FileHandle;
-    $in_handle->open( $in_name, '<' )
-        or return ();
+    local ($in_name, $inhibit_output_switch) = @_;
+
+    # We'll have conversions between encodings, and pattern,
+    # so byte semantics will be safest.
+    use bytes;
+    
+    my $in_handle;
+    if ( ! -e $in_name ) {
+        # Note: This is NOT an error condition, since the fdb_latexmk file
+        #       can legitimately not exist.
+        return -2;   
+    }
+    if ( ! open( $in_handle, '<', $in_name ) ) {
+        warn "$My_name: Couldn't read '$fdb_name' even though it exists\n";
+        return -1;
+    }
+    print "$My_name: Examining fdb file '$fdb_name' for cached rules ...\n"
+      if $diagnostics;
     my $errors = 0;
-    my $state = -1;   # Values: -1: before start; 0: outside rule;
-                      # 1: in source section;
-                      # 2: in generated file section;
+    my $state = -1;   # Values:
+                      # -1: before start;
+                      #  0: outside rule;
+                      #  1: in source section;
+                      #  2: in generated file section;
                       # 10: ignored rule.
     my $rule = '';
     local $run_time = 0;
@@ -5883,17 +6140,19 @@
     local %new_sources = ();  # Hash: rule => { file=>[ time, size, md5, fromrule ] }
     my $new_source = undef;   # Reference to hash of sources for current rule
 LINE:
-    while ( <$in_handle> ) {
+    while ( <$in_handle> ) {        
         # Remove leading and trailing white space.
         s/^\s*//;
         s/\s*$//;
+        $_ = utf8_to_mine($_);
+        
         if ($state == -1) {
             if ( ! /^# Fdb version ([\d]+)$/ ) {
                 warn "$My_name: File-database '$in_name' is not of correct format\n";
                 return 1;
             }
-            if ( $1 > $fdb_ver) {
-                warn "$My_name: File-database '$in_name' is of too new version, $1 > $fdb_ver\n";
+            if ( $1 ne $fdb_ver) {
+                warn "$My_name: File-database '$in_name' is of incompatible version, $1 v. $fdb_ver\n";
                 return 1;
             }
             $state = 0;
@@ -5908,32 +6167,33 @@
             $run_time = $check_time = 0;
             $source = $dest = $base = '';
             $old_actives{$rule} = 1;
-            if ( $tail =~ /^\s*(\S+)\s*$/ ) {
+            if ( $tail =~ /^\s*(\S+)\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s+(\S+)\s*$/ ) {
                 $run_time = $1;
-            }
-            elsif ( $tail =~ /^\s*(\S+)\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s*$/ ) {
-                $run_time = $1;
                 $source = $2;
                 $dest = $3;
                 $base = $4;
-            }
-            elsif ( $tail =~ /^\s*(\S+)\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s+\"([^\"]*)\"\s+(\S+)\s*$/ ) {
-                $run_time = $1;
-                $source = $2;
-                $dest = $3;
-                $base = $4;
                 $check_time = $5;
             }
+            else {
+                # Line is not in correct format
+                warn "$My_name: In '$in_name' there's a rule line not in correct format:\n",
+                     "    $_\n",
+                     "Perhaps the file has been edited, or there's a bug.\n";                    
+                $errors ++;
+                $state = 10;
+                next LINE;
+            }
             if ( rdb_rule_exists( $rule ) ) {
                 rdb_one_rule( $rule, \&rdb_read_set_rule );
             }
             elsif ($rule =~ /^cusdep\s+(\S+)\s+(\S+)\s+(.+)$/ ) {
-                # Create custom dependency
+                # create custom dependency
                 my $fromext = $1;
                 my $toext = $2;
                 my $base = $3;
-                $source = "$base.$fromext";
-#                $dest =   "$base.$toext";
+                # don't set $source and $dest here, but use the already-set values
+                #  from the rule definition line: under some situations the rule
+                #  may have these changed from normal.
                 my $func_name = '';
                 foreach my $dep ( @cus_dep_list ) {
                     my ($tryfromext,$trytoext,$must,$try_func_name) = split('\s+',$dep);
@@ -5984,11 +6244,11 @@
                 if ($rule =~ /^(bibtex|biber)/) { $PA_extra_gen = [ "$base.blg" ]; }
                 if ($rule =~ /^bibtex/) { $int_cmd = "run_bibtex"; }
                 if ($rule =~ /^makeindex/) { $int_cmd = "run_makeindex"; }
-                warn "$My_name: File-database '$in_name': setting rule '$rule'\n"
+                print "$My_name: File-database '$in_name': setting rule '$rule'\n"
                    if $diagnostics;
                 my $cmd_type = 'external';
                 my $ext_cmd = ${$rule_generic};
-                warn "  Rule kind = '$rule_generic'; ext_cmd = '$ext_cmd';\n",
+                print "  Rule kind = '$rule_generic'; ext_cmd = '$ext_cmd';\n",
                      "  int_cmd = '$int_cmd';\n",
                      "  source = '$source'; dest = '$dest'; base = '$base';\n"
                    if $diagnostics;
@@ -6000,7 +6260,7 @@
             }
             else {
                 if ($diagnostics) {
-                    warn "$My_name: In file-database '$in_name' rule '$rule'\n",
+                    print "$My_name: In file-database '$in_name' rule '$rule'\n",
                         "   is not in use in this session\n";
                 }
                 $new_source = undef;
@@ -6051,8 +6311,8 @@
             next LINE;
         }
     }
-    undef $in_handle;
-    # Set cus dependencies.
+    close $in_handle;
+    # Get state of dependencies, including creating cus deps if needed
     &rdb_set_dependents( keys %rule_db );
     &rdb_set_rule_net;
 
@@ -6092,15 +6352,20 @@
          && $possible_primaries{$rule}
          && exists( $allowed_output_ext{$oldext} )
          && ( $oldpath.$oldbase eq $newpath.$newbase )
+         && ( ! $inhibit_output_switch )
         )
     {
         # Change only in extension: A common cause: use of \pdfoutput in tex
         # file, with conflict with requested compilation type.  The old
         # extension wins.
-        warn "$My_name: change in extension of output file from '$oldext' on previous run\n",
-             "  to '$newext' for this run.\n",
-             "  So I'll CHANGE the output type from '$newext' to '$oldext',\n",
-             "  and make any necessary fixups.\n";
+        warn "$My_name: In reading the fdb_latexmk file for the previous run of latexmk, I\n",
+            "    found that the output extension for '$rule' was '$oldext', but requests for\n",
+            "    this run of latexmk give '$newext'.  Probably that was due to a specific\n",
+            "    request by the .tex document for output to '$oldext'.\n",
+            "    So (if possible) I'll reset the output extension back to '$oldext', which\n",
+            "    will be correct on the assumption that the old extension still reflects the\n",
+            "    situation with the .tex document. If the assumption is wrong, I'll correct\n",
+            "    that after the next run of '$rule'.\n";
         my $switch_error =  switch_output( $rule, $oldext, $newext );
         if ($switch_error) {
             warn "   I could not accommodate the changed output extension.\n",
@@ -6113,13 +6378,6 @@
         return;
     }
     # All special cases now dealt with. 
-    warn "$My_name: In reading file '$in_name' for state of files and rules on\n",
-         "  previous run, I found that rule '$rule' had a destination file\n",
-         "    $dest\n",
-         "  that differs from the current destination file\n",
-         "    $$Pdest\n",
-         "  I'll use the current destination, and flag the rule as out of date.\n";
-    $$Pout_of_date = 10;
 }  #END rdb_read_set_rule
 
 #************************************************************
@@ -6130,19 +6388,23 @@
     #   for all rules needed to make final output
     # Returns 1 on success, 0 if file couldn't be opened.
     local $out_name = $_[0];
-    local $out_handle = new FileHandle;
+
+    use bytes;
+    
+    local $out_handle;
     if ( ($out_name eq "") || ($out_name eq "-") ) {
         # Open STDOUT
-        $out_handle->open( '>-' );
+        open( $out_handle, '>-' );
     }
     else {
-       $out_handle->open( $out_name, '>' );
+       open( $out_handle, '>', $out_name );
     }
     if (!$out_handle) { return 0; }
 
+    #  ??? For safety?
     &rdb_set_rule_net;
 
-    print $out_handle "# Fdb version $fdb_ver\n";
+    fprint8( $out_handle, "# Fdb version $fdb_ver\n" );
     my @rules = sort &rdb_accessible;
     rdb_for_some(
        \@rules,
@@ -6155,17 +6417,19 @@
            { 
                return;
            }
-           print $out_handle "[\"$rule\"] $$Prun_time \"$$Psource\" \"$$Pdest\" \"$$Pbase\" $$Pcheck_time\n";
+           fprint8( $out_handle, "[\"$rule\"] $$Prun_time \"$$Psource\" \"$$Pdest\" \"$$Pbase\" $$Pcheck_time\n" );
            rdb_do_files(
-             sub { print $out_handle "  \"$file\" $$Ptime $$Psize $$Pmd5 \"$$Pfrom_rule\"\n"; }
+               sub { my $from_rule = $from_rules{$file} || '';
+                     fprint8( $out_handle, "  \"$file\" $$Ptime $$Psize $$Pmd5 \"$from_rule\"\n" );
+               }
            );
-           print $out_handle "  (generated)\n";
+           fprint8( $out_handle, "  (generated)\n" );
            foreach (sort keys %$PHdest) {
-               print $out_handle "  \"$_\"\n";
+               fprint8( $out_handle, "  \"$_\"\n" );
            }
        }
     );
-    undef $out_handle;
+    close $out_handle;
     return 1;
 } #END rdb_write
 
@@ -6172,6 +6436,7 @@
 #************************************************************
 
 sub rdb_set_latex_deps {
+    # Call: rdb_set_latex_deps( [inhibit_output_switch] )
     # Assume primary rule context.  
     # This is intended to be applied only for a primary (LaTeX-like) rule.
     # Set its dependents etc, using information from log, aux, and fls files.
@@ -6276,6 +6541,7 @@
     #     see pythontex-latexmk) for subroutine called to process a .tex to add items to
     #     %PHdest. So initializing here is too late.
 
+    local ($inhibit_output_switch) = @_;
     # Rules should only be primary
     if ( $$Pcmd_type ne 'primary' ) {
         warn "\n$My_name: ==========$My_name: Probable BUG======= \n   ",
@@ -6312,7 +6578,7 @@
                                   #  missing file during *latex compliation
                                   #  instead of just allowing to be made later
                                   #  by another rule. 
-    
+
     # The following are also returned by parsing routines, but are global,
     # to be used by caller:
     # $reference_changed, $bad_reference, $bad_character, $bad_citation, $mult_defined
@@ -6323,6 +6589,27 @@
         if ( /^eps pdf / ) { $epspdf_cusdep = 1; last; }
     }
 
+
+    # Settings to be found by reading log file:
+    our $engine = ''; # Which tex program?  (Use of $latex v.  ... no good, since
+                      # can be set to use another program.)
+    our $tex_distribution = '';
+    local %log_info = (); # Info. returned by get_log_file
+    local @log_lines = ();  # Lines in log file after unwrapping and converting
+                            # to use my internal CS.
+    # Get lines from log file now, with side effect of setting $engine and
+    #  $tex_distribution, so parse_fls can adjust its behavior if necessary).
+    my $read_log_file = get_log_file( $log_name, \@log_lines, \%log_info );
+    if (! $read_log_file ) {
+        warn "$My_name: Couldn't read log file '$log_name':\n  $!\n";
+    }
+    else {
+        $engine = $log_info{engine};
+        $tex_distribution = $log_info{distribution};
+    }
+
+
+    
     # Analyze fls file first.  It tells us the working directory as seen by *latex
     # But we'll use the results later, so that they take priority over the findings
     # from the log file.
@@ -6335,7 +6622,7 @@
         }
     }
  
-    &parse_log;
+    if ($read_log_file) { parse_log( $log_name, \@log_lines, \%log_info ); }
 
     my $missing_dirs = 'none';      # Status of missing directories
     if (@missing_subdirs) {
@@ -6354,7 +6641,7 @@
                 }
                 else {
                     if (mkdir $dir) {
-                        warn "$My_name: Directory '$dir' created\n";
+                        print "$My_name: Directory '$dir' created\n";
                     }
                     else {
                         $missing_dirs = 'failure';
@@ -6366,11 +6653,9 @@
         }
         else {
             $missing_dirs = 'not allowed';
-            warn "$My_name: There are missing subdirectories, but their creation\n",
-                 "    is not allowed.  The subdirectories are:\n";
-            foreach my $dir ( uniqs( @missing_subdirs ) ) {
-                warn "   '$dir'\n";
-            }
+            warn_array( "$My_name: There are missing subdirectories, but their creation\n".
+                        "    is not allowed.  The subdirectories are:",
+                        uniqs(@missing_subdirs) );
        }
     }
     # Use results from fls file.  (N.B. The hashes will be empty if the fls file
@@ -6441,13 +6726,13 @@
     #         package or class) sets \pdfoutput. 
     $missing_dvi_pdf = '';
     if ($primary_out eq '')  {
-        warn "$My_name: For rule '$rule', no output was made\n";
+        print "$My_name: For rule '$rule', no output was made\n";
         $missing_dvi_pdf = $$Pdest;
     }
     elsif ($primary_out ne normalize_filename($$Pdest) ) {
         my ($actual_base, $actual_path, $actual_ext) = fileparseA( $primary_out );
         my ($intended_base, $intended_path, $intended_ext) = fileparseA( $$Pdest );
-        if ( $actual_ext ne $intended_ext ) {
+        if ( ($actual_ext ne $intended_ext) && (!$inhibit_output_switch) ) {
             warn "$My_name: ===For rule '$rule', the extensions differ between the\n",
                  "   actual output file '$primary_out',\n",
                  "   and the expected output '$$Pdest'.\n";
@@ -6465,7 +6750,7 @@
                     $failure_msg = 'Could not handle change of output extension';
                 }
                 else {
-                    warn "   Rule structure will be changed suitably.\n";
+                    print "   Rule structure will be changed suitably.\n";
                 }
             }
         }
@@ -6587,11 +6872,11 @@
             if ($diagnostics);
         if ( exists $first_read_after_write{$new_source} ) {
             if ( dep_at_start($new_source) ) {
-                #warn "--- READ ONLY AFTER WRITE OF '$new_source'\n";
+                #print "--- READ ONLY AFTER WRITE OF '$new_source'\n";
                 $dependents{$new_source} = 7;
             }
             else {
-                #warn "--- READ ONLY AFTER CREATE OF '$new_source'\n";
+                #print "--- READ ONLY AFTER CREATE OF '$new_source'\n";
                 $dependents{$new_source} = 6;
             }
         }
@@ -6637,9 +6922,7 @@
         }
     }
 
-    foreach my $Psub (@latex_file_hooks) {
-         &$Psub;
-    }
+    run_hooks( 'latex_file_hooks' );
 
     # Some packages (e.g., bibtopic) generate a dummy error-message-providing
     #   bbl file when a bbl file does not exist.  Then the fls and log files
@@ -6663,8 +6946,7 @@
     }
     if ($diagnostics) {
         if ($num_new > 0 ) {
-            print "$num_new new source files for rule '$rule':\n";
-            foreach (@more_sources) { print "   '$_'\n"; }
+            show_array( "$num_new new source files for rule '$rule':", @more_sources );k { print "   '$_'\n"; }
         }
         else {
             print "No new source files for rule '$rule':\n";
@@ -6671,11 +6953,8 @@
         }
         my @first_read_after_write = sort keys %first_read_after_write;
         if ($#first_read_after_write >= 0) {
-            print "The following files were only read after being written:\n";
-            foreach (@first_read_after_write) {
-                print "   '$_'\n";
-            }
-          }
+            show_array( "The following files were only read after being written:", @first_read_after_write );
+        }
     }
     my @files_not_needed = ();
     foreach (keys %$PHsource) { 
@@ -6731,7 +7010,11 @@
     if ( ($actual_ext eq '.xdv') && ($out_dir ne $aux_dir) ){ $new_dest =~ s/^$out_dir1/$aux_dir1/; }
     if ( ($intended_ext eq '.xdv') && ($out_dir ne $aux_dir) ){ $new_dest =~ s/^$aux_dir1/$out_dir1/; }
 
-    rdb_change_dest( $new_dest );
+    rdb_remove_generated( $old_dest );
+    rdb_add_generated( $new_dest );
+    $$Pdest = $new_dest;
+
+    &rdb_set_rule_net;
         
     # Some fixes to avoid spurious error conditions:
     $switched_primary_output = 1;
@@ -6751,19 +7034,15 @@
     # Tests whether the file was generated during a run of *latex.
     # Assumes context for primary rule.
     # Two kinds of test are used:
-    # a. From %generated_log, which works after the log file has been parsed,
-    #    but only for certain files and for those TeX engines (not MiKTeX)
-    #    that put \openout lines in log file.
+    # a. From %generated_log and %generated_fls, which works after the fls and
+    #    log files hav been parsed, but in the log file only for certain files
+    #    and for those TeX engines (not MiKTeX) that put \openout lines in log
+    #    file.
     # b. By the file existing and being at least as new as the system
-    #    time at the start of the run. But we allow for a measured
-    #    offset between filetime and system time, which could be
-    #    nonzero if the file is on a different, remote system than the
-    #    one running latexmk. We must also allow a threshold in the
-    #    comparisons of filetimes to allow for the inaccuracy of the
-    #    offset measurement.
+    #    time at the start of the run. 
     my $file = shift;
-    return exists $generated_log{$file}
-           || ( -e $file && ( get_mtime( $file ) >= $$Prun_time + $filetime_offset - $filetime_causality_threshold));
+    return exists $generated_log{$file} || $generated_fls{$file}
+           || ( -e $file && ( get_mtime( $file ) >= $$Prun_time));
 }
 
 #************************************************************
@@ -6867,10 +7146,7 @@
     }
 
     if ( $diagnostics && ( $found > 0 ) ) {
-        warn "$My_name: Detected previously missing files:\n";
-        foreach ( sort keys %new_includes ) {
-            warn "   '$_'\n";
-        }
+        show_array( "$My_name: Detected previously missing files:", sort keys %new_includes );
     }
     return $found;
 } # END rdb_find_new_files
@@ -6879,18 +7155,15 @@
 
 sub rdb_set_dependents {
     # Call rdb_set_dependents( rules ...)
-    # Returns array (sorted), of new source files.
+    # Returns array (sorted), of new source files for the given rules.
     local @new_sources = ();
     local @deletions = ();
 
-# Shouldn't recurse.  The definite rules to be examined are given.
     rdb_for_some( [@_],  0, \&rdb_one_dep );
-# OLD    rdb_recurse( [@_],  0, \&rdb_one_dep );
     foreach (@deletions) {
         my ($rule, $file) = @$_;
         rdb_remove_files( $rule, $file );
     }
-    &rdb_make_links;
     return uniqs( @new_sources );
 } #END rdb_set_dependents
 
@@ -6926,7 +7199,6 @@
     if ( (! exists $possible_primaries{$rule}) && ($rule !~ /^cusdep/) ) {
         return;
     }
-#print "=============ONE_DEP: '$rule' '$file'\n";
     local $new_dest = $file;
     my ($base_name, $path, $toext) = fileparseA( $new_dest );
     $base_name = $path.$base_name;
@@ -6940,10 +7212,10 @@
             my $source = "$base_name.$fromext";
             # Found match of rule
             if ($diagnostics) {
-                print "Found cusdep:  $source to make $rule:$new_dest ====\n";
+                print "Found cusdep: $source to make $rule:$new_dest ====\n";
             }
             if ( -e $source ) {
-                $$Pfrom_rule = "cusdep $fromext $toext $base_name";
+                my $from_rule = "cusdep $fromext $toext $base_name";
                 my $new_new_dest = "$base_name.$toext";
                 if ($new_new_dest ne $new_dest) {
                     rdb_ensure_file( $rule, $new_new_dest );
@@ -6953,9 +7225,9 @@
                 if ( !-e $new_dest ) {
                     push @new_sources, $new_dest;
                 }
-                if (! rdb_rule_exists( $$Pfrom_rule ) ) {
-                    print "$My_name: === Creating rule '$$Pfrom_rule'\n" if $diagnostics;
-                    rdb_create_rule( $$Pfrom_rule, 'cusdep', '', \@PAnew_cmd, 3, 
+                if (! rdb_rule_exists( $from_rule ) ) {
+                    print "$My_name: === Creating rule '$from_rule'\n" if $diagnostics;
+                    rdb_create_rule( $from_rule, 'cusdep', '', \@PAnew_cmd, 3, 
                                      $source, $new_dest, $base_name, 0 );
                 }
                 return;
@@ -6969,10 +7241,10 @@
                                    "to build '$base_name.$toext'";
                     return;
                 }
-                elsif ( $$Pfrom_rule =~ /^cusdep $fromext $toext / )  {
+                elsif ( $from_rules{$file} && ($from_rules{$file} =~ /^cusdep $fromext $toext / ) )  {
                     # Source file does not exist, destination has the rule set.
                     # So turn the from_rule off
-                    $$Pfrom_rule = '';
+                    delete $from_rules{$file};
                 }
                 else {
                 }
@@ -6993,11 +7265,11 @@
                 $new_dest = "$base_name.$proptoext";
                 my $from_rule = "cusdep $fromext $proptoext $base_name";
                 push @new_sources, $new_dest;
-                print "Ensuring rule for '$from_rule', to make '$new_dest'\n"
+                print "$My_name: Ensuring rule for '$from_rule', to make '$new_dest'\n"
                     if $diagnostics > -1;
                 local @PAnew_cmd = ( 'do_cusdep', $func_name );
                 if (! rdb_rule_exists( $from_rule ) ) {
-                    print "$My_name: === Creating rule '$$Pfrom_rule'\n" if $diagnostics;
+                    print "$My_name: === Creating rule '$from_rule'\n" if $diagnostics;
                     rdb_create_rule( $from_rule, 'cusdep', '', \@PAnew_cmd, 3, 
                                      $source, $new_dest, $base_name, 0 );
                 }
@@ -7075,7 +7347,7 @@
     # Call: deps_list(fh)
     # List dependent files to file open on fh
     my $fh = $_[0];
-    print $fh "#===Dependents, and related info, for $filename:\n";
+    fprint8 $fh, "#===Dependents, and related info, for $filename:\n";
     my @dest_exts = ();
     if ($pdf_mode) {push @dest_exts, '.pdf';}
     if ($dvi_mode) {push @dest_exts, '.dvi';}
@@ -7088,7 +7360,7 @@
         sub{ push @generated, keys %$PHdest; },
         sub{ $source{$file} = 1; }
     );
-    foreach (keys %generated_exts_all) {
+    foreach (keys %generated_exts) {
         (my $name = /%R/ ? $_ : "%R.$_") =~ s/%R/${aux_dir1}${root_filename}/;
         push @generated, $name;
     }
@@ -7110,19 +7382,19 @@
          # deps file out-of-date are the same as those that make the real
          # target file (e.g., .pdf) out-of-date. So the GNU method seems
          # completely unnecessary.
-       print $fh "${out_dir1}${root_filename}${ext} :";
+       fprint8 $fh, "${out_dir1}${root_filename}${ext} :";
        foreach (sort keys %source) {
-           print $fh "\\\n    $_";
+           fprint8 $fh, "\\\n    $_";
        }
-       print $fh "\n";
+       fprint8 $fh, "\n";
     }
-    print $fh "#===End dependents for $filename:\n";
+    fprint8 $fh, "#===End dependents for $filename:\n";
     if ($dependents_phony) {
-        print $fh "\n#===Phony rules for $filename:\n\n";
+        fprint8 $fh, "\n#===Phony rules for $filename:\n\n";
         foreach (sort keys %source) {
-            print $fh "$_ :\n\n";
+            fprint8 $fh, "$_ :\n\n";
         }
-        print $fh "#===End phony rules for $filename:\n";
+        fprint8 $fh, "#===End phony rules for $filename:\n";
     }
 } #END deps_list
 
@@ -7142,7 +7414,7 @@
              }
              print "  [$rule]: '$$Pcmd_type' '$$Pext_cmd' '@int_cmd' $$Ptest_kind ",
                    "'$$Psource' '$$Pdest' '$$Pbase' $$Pout_of_date $$Pout_of_date_user\n"; },
-        sub{ print "    '$file': $$Ptime $$Psize $$Pmd5 '$$Pfrom_rule'\n"; }
+        sub{ print "    '$file': $$Ptime $$Psize $$Pmd5 '", ($from_rules{$file} || ''), "'\n"; }
     );
     if ($count_rules <= 0) {
         print "   ---No rules defined\n";
@@ -7165,6 +7437,8 @@
     foreach (keys %target_files) {
         if (exists $from_rules{$_}) { $rules{$from_rules{$_}} = 1; }
     }
+#    show_array( 'target_hash', sort keys %rules );
+#    &traceback;
     return %rules;
 } # End rdb_target_hash
 
@@ -7322,7 +7596,7 @@
     #           source files.  
     #    
 
-
+    # ??? Overkill?
     &rdb_set_rule_net;
 
     local %pass = ();
@@ -7333,6 +7607,7 @@
     local $too_many_passes = 0;
     local %rules_applied = ();
     local $switched_primary_output = 0;
+    local @warning_list = ();  # Undef refs etc reported in last primary run
     my $retry_msg = 0;         # Did I earlier say I was going to attempt 
                                # another pass after a failure?
     rdb_for_some ( [keys %rule_db],
@@ -7360,12 +7635,12 @@
         if ($diagnostics) {
             print "Make: doing pre_primary and primary...\n";
         }
-        # Do the primary run if it is needed. On return $runs == 0
-        #       signals that nothing was run (and hence no output
-        #       files changed), either because no input files
-        #       changed and no run was needed, or because the
-        #       number of passes through the rule exceeded the
-        #       limit.  In the second case $too_many_runs is set.
+        # Do the primary run preceeded by pre_primary runs, all only if needed.
+        #      On return, $runs == 0 signals that nothing was run (and hence
+        #      no output files changed), either because no input files
+        #      changed and no run was needed, or because the
+        #      number of passes through the rule exceeded the
+        #      limit.  In the second case $too_many_runs is set.
         rdb_for_some( [@pre_primary, $current_primary], \&rdb_make1 );
         if ($switched_primary_output) {
             print "=========SWITCH OF OUTPUT WAS DONE.\n";
@@ -7420,7 +7695,7 @@
     rdb_for_some( [@unusual_one_time], \&rdb_make1 );
 
     if ($runs_total > 0) { rdb_write( $fdb_name ); }
-    else { print "Nothing to do\n"; }
+    else { print "$My_name: Nothing to do for '$texfile_name'.\n"; }
 
     if ($#primary_warning_summary > -1) {
         # N.B. $mult_defined, $bad_reference, $bad_character, $bad_citation also available here.
@@ -7427,6 +7702,17 @@
         show_array( "$My_name: Summary of warnings from last run of *latex:", 
                     @primary_warning_summary );
     }
+    if ( ($#warning_list >= 0) && !$silence_logfile_warnings ) {
+        warn "$My_name: ====List of undefined refs and citations:\n";
+        for (my $i = 0; $i <= $#warning_list; $i++) {
+            if ($i >= $max_logfile_warnings ) {
+                warn " And ", $#warning_list + 1 - $i, " more --- see log file.\n";    
+                last;
+            }
+            warn "  $warning_list[$i]\n";
+        }
+    }
+
     if (! $silent) {
         if ($failure && $force_mode) {
             print "$My_name: Errors, in force_mode: so I tried finishing targets\n";
@@ -7479,16 +7765,10 @@
                }
               );
     if ($#warnings > -1) { 
-        warn "Collected warning summary (may duplicate other messages):\n";
-        foreach (@warnings){
-            warn "  $_\n";
-        }
+        show_array( "Collected warning summary (may duplicate other messages):". @warnings );
     }
     if ($#errors > -1) { 
-        warn "Collected error summary (may duplicate other messages):\n";
-        foreach (@errors){
-            warn "  $_\n";
-        }
+        show_array( "Collected error summary (may duplicate other messages):", @errors );
     }
     return $#errors+1;
 }
@@ -7502,7 +7782,7 @@
     # Assumes contexts for recursion, make, and rule, and
     # assumes that source files for the rule are to be considered
     # up-to-date.
-    if ($diagnostics) { print "  Make1 $rule\n"; }
+    if ($diagnostics) { print "  Make for rule '$rule'\n"; }
     if ($failure & ! $force_mode) {return;}
     if ( ! defined $pass{$rule} ) {$pass{$rule} = 0; } 
 
@@ -7556,7 +7836,7 @@
             #      Any error will arise at the *latex level due to a 
             #      missing source file at that level.
             if ( $$Psource && (! -e $$Psource)
-                 && ( ( $$Pcmd_type ne 'primary') )
+                 && ( $$Pcmd_type ne 'primary' )
                ) {
                 # Main source file doesn't exist, and rule is NOT primary.
                 # No action, since a run is pointless.  Primary is different:
@@ -7626,10 +7906,7 @@
     }
     else {
         warn_running( "Run number $pass{$rule} of rule '$rule'" );
-        if ($$Pcmd_type eq 'primary' ) { 
-            $return = &rdb_primary_run;
-        }
-        else { $return = &rdb_run1; }
+        $return = &rdb_run1;
     }
     if ($$Pchanged) {
         $newrule_nofile = 1;
@@ -7689,133 +7966,6 @@
 
 #************************************************************
 
-sub rdb_classify_rules {
-    # Usage: &rdb_classify_rules
-    # Assume the following variables are available (global or local):
-    # Input:
-    #    %target_rules    # Set to target rules
-    #    %target_files    # Set to target files
-    #    %possible_primaries
-    
-    # Output:
-    #    %current_primaries    # Keys are actual primaries
-    #    @pre_primary          # Array of rules
-    #    @post_primary         # Array of rules
-    #    @unusual_one_time     # Array of rules
-    # @pre_primary and @post_primary are in natural order of application.
-
-    local @requested_targets = &rdb_target_array;
-    local $state = 0;       # Post-primary
-    local @classify_stack = ();
-
-    %current_primaries = ();
-    @pre_primary = ();
-    @post_primary = ();
-    @unusual_one_time = ();
-
-    rdb_recurse( \@requested_targets, \&rdb_classify1, 0,0, \&rdb_classify2 );
-
-    # Reverse, as tendency is to find last rules first.
-    @pre_primary = reverse @pre_primary;
-    @post_primary = reverse @post_primary;
-
-    my @current_primaries = keys %current_primaries;
-    if ($#current_primaries < 0) {
-        die "$My_name: No active primary rules found.  I have to stop.\n";
-    }
-    elsif ($#current_primaries > 0) {
-        die "$My_name: More than one active primary rule found.  I have to stop.\n",
-            "  Primary rules: @current_primaries\n";
-    }
-    $current_primary = $current_primaries[0];
-
-    if ($diagnostics) {
-        print "Rule classification: \n";
-        if ($#requested_targets < 0) {
-            print "  No requested rules\n";
-        }
-        else {
-            print "  Requested rules:\n";
-            foreach ( @requested_targets ) { print "    $_\n"; }
-        }
-        if ($#pre_primary < 0) {
-            print "  No pre-primaries\n";
-        }
-        else {
-            print "  Pre-primaries:\n";
-            foreach (@pre_primary) { print "    $_\n"; }
-        }
-        print "  Primaries:\n";
-        foreach (keys %current_primaries) { print "    $_\n"; }
-        if ($#post_primary < 0) {
-            print "  No post-primaries\n";
-        }
-        else {
-            print "  Post-primaries:\n";
-            foreach (@post_primary) { print "    $_\n"; }
-        }
-        if ($#unusual_one_time < 0) {
-            print "  No inner-level one_time rules, as expected\n";
-        }
-        else {
-            print "  Inner-level one_time rules:\n";
-            foreach ( @unusual_one_time ) { print "    $_\n"; }
-        }
-        my @normal_one_time = keys %one_time;
-        if ($#normal_one_time < 0) {
-            print "  No outer-level one_time rules\n";
-        }
-        else {
-            print "  Outer-level one_time rules:\n";
-            foreach ( @normal_one_time ) { print "    $_\n"; }
-        }
-    } #end diagnostics
-
-} #END rdb_classify_rules
-
-#-------------------
-
-sub rdb_classify1 {
-    # Helper routine for rdb_classify_rules
-    # Applied as rule_act1 in recursion over rules
-    # Assumes rule context, and local variables from rdb_classify_rules
-    push @classify_stack, [$state];
-    if ( exists $possible_one_time{$rule} ) {
-        # Normally, we will have already extracted the one_time rules,
-        # and they will never be accessed here.  But just in case of
-        # problems or generalizations, we will cover all possibilities:
-        if ($depth > 1) {
-           warn "ONE TIME rule not at outer level '$rule'\n";
-        }
-        push @unusual_one_time, $rule;
-    }
-    elsif ($state == 0) {
-       if ( exists $possible_primaries{$rule} ) {
-           $state = 1;   # In primary rule
-           $current_primaries{ $rule } = 1;
-       }
-       else {
-           push @post_primary, $rule;
-       }
-    }
-    else {
-        $state = 2;     # in post-primary rule
-        push @pre_primary, $rule;
-    }
-} #END rdb_classify1
-
-#-------------------
-
-sub rdb_classify2 {
-    # Helper routine for rdb_classify_rules
-    # Applied as rule_act2 in recursion over rules
-    # Assumes rule context
-    ($state) = @{ pop @classify_stack };
-} #END rdb_classify2
-
-#************************************************************
-
-
 sub rdb_run1 {
     # Assumes context for: rule.
     # Unconditionally apply the rule
@@ -7824,20 +7974,38 @@
     #            -1 on error, 
     #            -2 when missing dest_file is to be ignored
 
-    # Source file data, by definition, correspond to the file state just
-    # before the latest run, and the run_time to the time just before the run:
-    &rdb_update_files;
+    # Defaults for summary of results of run.
     $$Prun_time = time();
+    
     $$Pchanged = 0;       # No special changes in files
     $$Plast_result = 0;
     $$Plast_message = '';
+    my $latex_like = ($$Pcmd_type eq 'primary'); 
 
-    # Return values for external command:
+    # Return value for external command:
     my $return = 0;
 
+# Source file data, by definition, correspond to the file state just
+# before the latest run, and the run_time to the time just before the run:
+    if ($latex_like) {
+        # For *latex, we will generate the list of generated files from the
+        # analysis of the results of the run.  So before the run we must
+        # reset the list of generated files saved in the rule data. Otherwise
+        # it can continue to contain out-of-date items left from the previous
+        # run.  (Think bibtopic, which writes bbl files!)
+        #
+        # This reset is not used/needed for other rules, since normally no
+        # analysis of a log file (or similar) is made to find generated
+        # files.  The set of extra generated files beyond the main
+        # destination file  is hard wired into the rule definition.
+        # 
+        &rdb_initialize_generated;
+    }
+    # Now set the current state of the files
+    &rdb_update_files;
+
     # Find any internal command
     my @int_args = @$PAint_cmd;
-    
     my $int_cmd = shift @int_args;
     my @int_args_for_printing = @int_args;
     foreach (@int_args_for_printing) {
@@ -7844,8 +8012,15 @@
         if ( ! defined $_ ) { $_ = 'undef'; }
     }
 
-    # The actual execution of the command:
+# ==========  Now the actual run of the command or ... for the rule ==========
+# But first save current total processing time for the process, so that after
+# the run of the command for the rule we can measure the processing time of
+# the rule (without overhead from other work latexmk does):
+
+    if ($latex_like) { run_hooks( 'before_xlatex' ); }
+
     my $time = processing_time();
+   
     if ($int_cmd) {
         print "For rule '$rule', use internal command '\&$int_cmd( @int_args_for_printing )' ...\n"
             if $diagnostics;
@@ -7863,9 +8038,27 @@
         $$Plast_message = "Bug or configuration error; incorrect command type";
     }
     $time = processing_time() - $time;
-    push @timings, "'$_[0]': time = $time\n";            
+    push @timings, "'$_[0]': time = " . sprintf('%.2f',$time) . "\n";
 
-    if ( $rule =~ /^biber/ ) {
+#============================================================================
+
+
+    # Analyze the results of the run, the first step of which is highly rule
+    # dependent, and may reassess the return code in $return.
+    # ????? Probably it would be best at a later revision to have analysis
+    # subroutines for each special case instead of in-line code here; there
+    # could possibly a user-configurable per-rulehook.
+    #
+    $$Pout_of_date = $$Pout_of_date_user = 0;
+    if ($latex_like) {
+        if ( $emulate_aux && ($aux_dir ne $out_dir) ) {
+            &move_out_files_from_aux;
+        }
+        run_hooks( 'after_xlatex' );
+        $return = analyze_latex_run( $return );
+        run_hooks( 'after_xlatex_analysis' );
+    }
+    elsif ( $rule =~ /^biber/ ) {
         my @biber_source = ( );
         my $retcode = check_biber_log( $$Pbase, \@biber_source );
         foreach my $source ( @biber_source ) {
@@ -7885,7 +8078,7 @@
         elsif ($retcode == 6) {
            # Missing control file.  Need to remake it (if possible)
            # Don't treat missing bbl file as error.
-           warn "$My_name: bibtex control file missing.  Since that can\n",
+           print "$My_name: bibtex control file missing.  Since that can\n",
                 "   be recreated, I'll try to do so.\n";
            $return = -2;
            rdb_for_some( [keys %current_primaries], sub{ $$Pout_of_date = 1; } );
@@ -7915,7 +8108,7 @@
         elsif ($retcode == 11) {
             push @warnings, "Biber: malformed bcf file for '$$Pbase'.  IGNORE";
             if (!$silent) {
-               warn "$My_name: biber found malformed bcf file for '$$Pbase'.\n",
+               print "$My_name: biber found malformed bcf file for '$$Pbase'.\n",
                     "  I'll ignore error, and delete any bbl file.\n";
             }
             # Malformed bcf file is a downstream consequence, normally,
@@ -7940,7 +8133,7 @@
             
         }
     }
-    if ( $rule =~ /^bibtex/ ) {
+    elsif ( $rule =~ /^bibtex/ ) {
         my $retcode = check_bibtex_log($$Pbase);
         if ( ! -e $$Psource ) {
             $retcode = 10;
@@ -7963,7 +8156,7 @@
             push @warnings, "Bibtex found no citations for '$$Pbase',\n",
                             "    or bibtex found a missing aux file\n";
             if (! -e $$Pdest ) {
-                warn "$My_name: Bibtex did not produce '$$Pdest'.  But that\n",
+                print "$My_name: Bibtex did not produce '$$Pdest'.  But that\n",
                      "     was because of missing files, so I will continue.\n";
                 $return = -2;
             }
@@ -7972,10 +8165,11 @@
             }
         }
     }
+    else {
+        # No special analysis for other rules
+    }
 
-    if ( ($$Pcmd_type eq 'primary') && ( $aux_dir ne $out_dir ) ) {
-        &move_out_files_from_aux;
-    }
+    # General
     $updated = 1;
     if ($$Ptest_kind == 3) { 
         # We are time-criterion first time only.  Now switch to
@@ -7982,7 +8176,6 @@
         # file-change criterion
         $$Ptest_kind = 1; 
     }
-    $$Pout_of_date = $$Pout_of_date_user = 0;
 
     if ( ($$Plast_result == 0) && ($return != 0) && ($return != -2) ) {
         $$Plast_result = 2;
@@ -7989,7 +8182,13 @@
         if ($$Plast_message eq '') {
             $$Plast_message = "Command for '$rule' gave return code $return";
             if ($rule =~ /^(pdf|lua|xe|)latex/) {
-                $$Plast_message .= "\n      Refer to '$log_name' for details";
+                if ( test_gen_file($log_name) ) {
+                    $$Plast_message .= "\n      Refer to '$log_name' for details";
+                }
+                else {
+                    $$Plast_message .=
+                    "\n     Serious error that appeared not to generate a log file.";
+                }
             }
             elsif ($rule =~ /^makeindex/) {
                 $$Plast_message .= "\n      Refer to '${aux_dir1}${root_filename}.ilg' for details";
@@ -8100,7 +8299,6 @@
         if (exists($subst{$_})) { $_ = $subst{$_}; }
     }
     $ext_cmd = join '', @tokens;
-
     my ($pid, $return) = 
           ( ($msg == 0) || ( ($msg == 1) && $silent ) )
              ? &Run($ext_cmd)
@@ -8110,33 +8308,26 @@
 
 #-----------------
 
-sub rdb_primary_run {
-    # Call: rdb_primary_run
+sub analyze_latex_run {
+    # Call: analyze_latex_run(old_ret_code)
+    # Analyze results of run of *latex (or whatever was run instead) from
+    # fls, log and aux files, and certain other information.
+    # It also deals with (a) Change of main output file from one allowed
+    # extension to another (e.g., dvi -> pdf). (b) Failure of *latex to
+    # handle -aux-directory option, as with TeXLive.
+    #
+    # The argument is the return code as obtained from the run of *latex
+    # and the returned value is either the original return code or an adjusted
+    # value depending on the conditions found (e.g., missing file(s) that
+    # latexmk know how to create).
+    #
     # Assumes contexts for: recursion, make, & rule.
     # Assumes (a) the rule is a primary, 
     #         (b) a run has to be made,
-    #         (c) source files have been made.
-    # This routine carries out the run of the rule unconditionally,
-    # and then parses log file etc.
-    my $return = 0;
 
-    if ( ! $filetime_offset_measured ) {
-        $filetime_offset = get_filetime_offset( $aux_dir1."tmp" );
-        if ( (abs($filetime_offset) > $filetime_offset_report_threshold)
-             && ($diagnostics || ! $silent) )
-        {
-            warn "$My_name: I am working around an offset relative to my system time by\n",
-                 "   $filetime_offset secs for file times in directory '$aux_dir1'.\n";
-        }
-        $filetime_offset_measured = 1;
-    }
+    my $return_latex = shift;
+    my $return = $return_latex;
 
-    # Need to reset the list of generated files.  If we don't it can contain
-    # out-of-date items from previous run.  (Think bibtopic, which writes
-    # bbl files!)
-    &rdb_initialize_generated;
-    my $return_latex = &rdb_run1;
-
     # Need to worry about changed directory, changed output extension
     # Where else is $missing_dvi_pdf set?  Was it initialized?
     if (-e $$Pdest) { $missing_dvi_pdf = '';}
@@ -8150,6 +8341,7 @@
         #    of name latex.fls or pdflatex.fls instead of $root_filename.fls.
         # Also that setting of -output-directory -aux-directory is not 
         #    respected by *latex, at least in some versions.
+
         my $std_fls_file = $fls_name;
         my @other_fls_names = ( );
         if ( $rule =~ /^pdflatex/ ) {
@@ -8202,15 +8394,6 @@
         rdb_show();
     }
 
-    $return = $return_latex;
-
-# ???? Is the following needed?
-    if ($return_latex && $$Pout_of_date_user) {
-       print "Error in *LaTeX, but change of user file(s), ",
-             "so ignore error & provoke rerun\n"
-          if (! $silent);
-       $return = 0;
-    }
     if ($return_latex && ($missing_dirs ne 'none') ) {
        print "Error in *LaTeX, but needed subdirectories in output directory\n",
              "   were missing and successfully created, so try again.\n"
@@ -8239,9 +8422,11 @@
     if ( $diagnostics && ($#primary_warning_summary > -1) ) {
        show_array( "$My_name: Summary of warnings:", @primary_warning_summary );
     }
+
     return $return;
-} #END rdb_primary_run
 
+} #END analyze_latex_run
+
 #************************************************************
 
 sub rdb_clear_change_record {
@@ -8274,6 +8459,11 @@
     $dest_mtime = get_mtime($$Pdest) if ($$Pdest);
     rdb_do_files( \&rdb_file_change1);
     while ( my ($s_rule, $l_pass) = each %$PHsource_rules ) {
+        # %$PHsource_rules is about rules on which the current rule
+        #   depends, but for which this dependence is not determined by
+        #   the source rules of the set of known source files.
+        # Use pass-count criterion to determine out-of-dateness for these.
+        # 
         if ( defined $pass{$s_rule}
              && ($pass{$s_rule} > $l_pass)
             )
@@ -8355,7 +8545,7 @@
 sub rdb_user_changes {
     # Argument(s): a set of top level rules.
     # Aim: Find any changed user files for those rules and all ancestors.
-    # Assumption: List of from_rules for files is up-to-date.
+    # Assumption: List of source_rules for files is up-to-date.
     &rdb_clear_change_record;
     rdb_recurse( [@_], sub{ &rdb_flag_changes_here(1); } );
     if ($#changed_user >=0) { show_array( 'User changed files', @changed_user ); }
@@ -8371,37 +8561,28 @@
     my $heading = defined($_[0]) ?   $_[0]  :  "$My_name: "; 
 
     if ($#rules_never_run >= 0) {
-        warn "${heading}Rules & subrules not known to be previously run:\n";
-        foreach (@rules_never_run) { warn "   $_\n"; }
+        show_array( "${heading}Rules & subrules not known to be previously run:", @rules_never_run );
     }
     if ( ($#changed >= 0) || (keys %changed_rules > 0) || ($#disappeared >= 0) || ($#no_dest >= 0) ) {
-        warn "${heading}File changes, etc:\n";
+        print "${heading}File changes, etc:\n";
         if ( $#changed >= 0 ) {
-            warn "   Changed files, or newly in use since previous run(s):\n";
-            foreach (uniqs(@changed)) { warn "      '$_'\n"; }
+            show_array( "   Changed files, or newly in use since previous run(s):", uniqs(@changed) );
         }
         if ( $#disappeared >= 0 ) {
-            warn "   No-longer-existing files:\n";
-            foreach (uniqs(@disappeared)) { warn "      '$_'\n"; }
+            show_array( "   No-longer-existing files:", uniqs(@disappeared) );
         }
         if ( $#no_dest >= 0 ) {
-            warn "   Non-existent destination files:\n";
-            foreach (uniqs(@no_dest)) { warn "      '$_'\n"; }
+            show_array( "   Non-existent destination files:", uniqs(@no_dest) );
         }
         if ( keys %changed_rules > 0 ) {
-            warn "   Rule(s) that have been run and require run of dependent rule:\n";
+            print "   Rule(s) that have been run and require run of dependent rule:\n";
             while (my ($s_rule, $d_rule) = each %changed_rules) {
-                warn "      '$s_rule' which requires run of '$d_rule'\n";
+                print "      '$s_rule' which requires run of '$d_rule'\n";
             }
         }
     }
-    elsif ($#rules_to_apply >=0) {
-         warn "${heading}The following rules & subrules became out-of-date:\n";
-         foreach (@rules_to_apply) { warn "      '$_'\n"; }
-    }
-    else {
-        warn "${heading}No file changes\n";
-    }
+    show_array( "${heading}The following rules & subrules became out-of-date:",
+                @rules_to_apply);
 }     #END rdb_diagnose_changes
 
 
@@ -8564,6 +8745,7 @@
 #************************************************************
 
 sub rdb_for_one_file {
+    # Use : rdb_for_one_file( rule, file, ref to action subroutine )
     my $rule = shift;
     # Avoid name collisions with general recursion and iteraction routines:
     local $file1 = shift;
@@ -8581,7 +8763,7 @@
 sub rdb_recurse_rule {
     # Call: rdb_recurse_rule($rule, \&rule_act1, \&file_act1, \&file_act2, 
     #                    \&rule_act2 )
-    # to do the work for one rule, recurisvely called from_rules for
+    # to do the work for one rule, recurisvely called source_rules for
     # the sources of the rules.
     # Assumes recursion context, i.e. that %visited, @heads, $depth.
     # We are overriding actions:
@@ -8612,9 +8794,10 @@
     # passed as a reference in calls in higher-level subroutine.
     # Assumes contexts set for: Recursion, rule, and file
     &$file_act1 if $file_act1;
-    rdb_recurse_rule( $$Pfrom_rule, $rule_act1, $file_act1, $file_act2,
+    my $from_rule = $from_rules{$file} || '';
+    rdb_recurse_rule( $from_rule, $rule_act1, $file_act1, $file_act2,
                       $rule_act2 )
-        if $$Pfrom_rule;
+        if $from_rule;
     &$file_act2 if $file_act2;
 } #END rdb_recurse_file
 
@@ -8721,12 +8904,10 @@
     local ($file, $file_act) = @_;
     if ( (!$file) ||(!exists ${$PHsource}{$file}) ) { return; }
     local $PAfile_data = ${$PHsource}{$file};
-    local ($Ptime, $Psize, $Pmd5, $Pfrom_rule, $Pcorrect_after_primary ) 
+    our $DUMMY;  # Fudge until fix rule_db
+    local ($Ptime, $Psize, $Pmd5, $DUMMY, $Pcorrect_after_primary ) 
           = Parray( $PAfile_data );
     &$file_act() if $file_act;
-    if ( ! rdb_rule_exists( $$Pfrom_rule ) ) {
-        $$Pfrom_rule = '';
-    }
 } #END rdb_one_file
 
 #************************************************************
@@ -8886,7 +9067,7 @@
                   }
     );
     if (defined $new_from_rule ) {
-        rdb_for_one_file( $rule, $new_file, sub{ $$Pfrom_rule = $new_from_rule; });
+        $from_rules{$new_file} = $new_from_rule;
     }
 } #END rdb_ensure_file 
 
@@ -8936,36 +9117,6 @@
 
 #************************************************************
 
-sub rdb_change_dest {
-   # Assumes rule context.
-   # Usage change_dest( new_dest [, flag] )
-   # Changes destination for this rule. Fixes from_rule links.
-   # If flag set, make the new_dest a source file in any rule
-   # for which the old destination is already set.
-   # No action if there's no change of destination.
-   local ($new_dest, $flag) = @_;
-   local $old_dest = $$Pdest;
-   if ($old_dest eq $new_dest) { return; }
-#   if ( $new_dest =~ /\"/ ) { return; }
-   rdb_remove_generated( $old_dest );
-   rdb_add_generated( $new_dest );
-   if ($flag) {
-      print "rdb_change_dest: fixing dependencies\n";
-      rdb_for_actives( sub{ if ( rdb_file_exists( $rule, $old_dest ) ) {
-                            rdb_ensure_file( $rule, $new_dest );
-                            rdb_remove_files( $rule, $old_dest );
-                        }
-                      }
-                 );
-   }
-   $$Pdest = $new_dest;
-   # ??? Do I need to fix from_rule setting?
-   #&rdb_make_links;
-   return;
-} #END rdb_change_dest
-
-#************************************************************
-
 sub rdb_rule_exists { 
     # Call rdb_rule_exists($rule): Returns whether rule exists.
     my $rule = shift;
@@ -8992,7 +9143,7 @@
     # Assumes rule context.  Update source files of rule to current state.
     rdb_do_files( 
         sub{
-            if ( exists $generated_exts_all{ ext_no_period($file) }
+            if ( exists $generated_exts{ ext_no_period($file) }
                  || exists $$PHdest{$file}
                 ) {
                 &rdb_update1;
@@ -9099,6 +9250,39 @@
 
 sub show_array {
 # For use in diagnostics and debugging. 
+#  On stdout, print line with $_[0] = label.  
+#  Then print rest of @_, one item per line preceeded by some space
+    print "$_[0]\n";
+    shift;
+    if ($#_ >= 0) {
+        foreach (@_){
+           if (defined $_ ) { print "  $_\n"; }
+           else { print "  UNDEF\n"; }
+        }
+    }
+    else { print "  NONE\n"; }
+}
+
+#************************************************************
+
+sub show_hash {
+    my ($msg, $PH ) = @_;
+    print "$msg\n";
+    if (! %$PH ) {
+        print "     NONE\n";
+    }
+    else {
+        while ( my ($key, $value) = each %$PH ) {
+            if (defined $value) { print "  '$key' => '$value'\n"; }
+            else { print "  '$key' => UNDEF\n"; }
+        }
+    }
+}
+
+#************************************************************
+
+sub warn_array {
+#  For use in error messages etc.
 #  On stderr, print line with $_[0] = label.  
 #  Then print rest of @_, one item per line preceeded by some space
     warn "$_[0]\n";
@@ -9253,76 +9437,27 @@
 
 #************************************************************
 
-sub get_mtime_raw
-{ 
-  my $mtime = (stat($_[0]))[9];
-  return $mtime;
+sub get_mtime {
+    # Return mtime of file if it exists, otherwise 0.
+    # 
+    # stat returns an empty array for a non-existent file, and then
+    # accessing an element of the array gives undef.  Use || 0 to replace it
+    # by the desired 0.
+    return ( stat($_[0]) )[9] || 0;
 }
 
 #************************************************************
 
-sub get_mtime { 
-    return get_mtime0($_[0]);
-}
-
-#************************************************************
-
-sub get_mtime0 {
-   # Return time of file named in argument
-   # If file does not exist, return 0;
-   if ( -e $_[0] ) {
-       return get_mtime_raw($_[0]);
-   }
-   else {
-       return 0;
-   }
-}
-
-#************************************************************
-
-sub get_size {
-   # Return time of file named in argument
-   # If file does not exist, return 0;
-   if ( -e $_[0] ) {
-       return get_size_raw($_[0]);
-   }
-   else {
-       return 0;
-   }
-}
-
-#************************************************************
-
-sub get_size_raw
-{ 
-  my $size = (stat($_[0]))[7];
-  return $size;
-}
-
-#************************************************************
-
 sub get_time_size {
-   # Return time and size of file named in argument
-   # If file does not exist, return (0,-1);
-   if ( -e $_[0] ) {
-       return get_time_size_raw($_[0]);
-   }
-   else {
-       return (0,-1);
-   }
+    # Return time and size of file named in argument
+    # If file does not exist, return (0,-1);
+    # Argument _ to stat: use values from previous call, to save disk access..
+    return (   ( ( stat($_[0]) )[9] || 0 ),
+               ( ( stat(_) )[7] || -1 )   );
 }
 
 #************************************************************
 
-sub get_time_size_raw
-{ 
-  my $mtime = (stat($_[0]))[9];
-  my $size = (stat($_[0]))[7];
-  return ($mtime, $size);
-}
-
-#************************************************************
-
 sub processing_time
 {  my ($user, $system, $cuser, $csystem) = times();
    return $user + $system + $cuser + $csystem;
@@ -9332,11 +9467,11 @@
 
 sub get_checksum_md5 {
     my $source = shift;
-    my $input = new FileHandle;
+    my $input;
     my $md5 = Digest::MD5->new;
     my $ignore_pattern = undef;
 
-#warn "======= GETTING MD5: $source\n";
+#print "======= GETTING MD5: $source\n";
     if ( -d $source ) {
         # We won't use checksum for directory
         return 0;
@@ -9369,7 +9504,7 @@
 
 sub create_empty_file {
     my $name = shift;
-    my $h = new FileHandle ">$name"
+    open( my $h, ">", $name )
         or return 1;
     close ($h);
     return 0;
@@ -9491,6 +9626,7 @@
 #************************************************************
 
 sub make_path_mod {
+    # Ensures directory given in $_[0] exists, with error checking
     my $dir = $_[0];
     my $title = $_[1];
     my $ret = 0;
@@ -9498,7 +9634,7 @@
     elsif ( (! -e $dir) && (! -l $dir) ) {
         # N.B. A link pointing to a non-existing target
         # returns false for -e, so we must also check -l
-        warn "$My_name: making $title directory '$dir'\n"
+        print "$My_name: making $title directory '$dir'\n"
             if ! $silent;
         # Error handling from File::Path documentation:
         make_path( $dir, {error => \my $err} );
@@ -9555,7 +9691,7 @@
     open $fh, "$cmd|"
         or die "Cannot open pipe for \"$cmd\"\n";
     while ( <$fh> ) {
-        s/[\r\n]*$//;
+        s/\r?\n$//;
         push @found, $_;
     }
     close $fh;
@@ -9624,36 +9760,82 @@
 ####################################################
 ####################################################
 
-sub add_aux_hook {
-    # Usage: add_aux_hook( sub_name )
-    # Add the name subroutine to the array of hooks for
-    # processing lines of aux files.
-    # The argument is either a string naming the subroutine, e.g.
-    #     add_aux_hook( 'subname' );
-    # or a Perl reference to the subroutine, e.g.,
-    #     add_aux_hook( \&subname );
-    # It is also possible to use an anonymous subroutine, e.g.,
-    #     add_aux_hook( sub{  code of subroutine... } );
-    my ($sub_name) = @_;
-    push @aux_hooks, $sub_name;
+sub add_hook {
+    # Usage: add_book( name of stack, name of orpointer to subroutine )
+    # Return 1 for success, 0 for failure.
+    our %hooks;
+    my ($stack, $routine ) = @_;
+    unless ( exists $hooks{$stack} ) {
+        warn "In add_hook, request to add hook to non-existent stack '$stack'.\n";
+        return 0;
+    }
+
+    my $ref;
+    if ( ref $routine ) {
+        $ref = $routine
+    }
+    elsif ( defined &$routine ) {
+        $ref = \&$routine;
+    }
+    else {
+        warn "In add_hook, no subroutine '$routine' to add to stack '$stack'.\n";
+            return 0;
+    }
+    push @{$hooks{$stack}}, $ref;
+    return 1;
 }
 
-####################################################
+#****************************************************
 
-sub add_latex_file_hook {
-    # Usage: add_latex_file_hook( sub_name )
-    # Add the name subroutine to the array of hooks for
-    # processing list of possible dependency files after a run of *latex.
-    # The argument is either a string naming the subroutine, e.g.
-    #     add_latex_file_hook( 'subname' );
-    # or a Perl reference to the subroutine, e.g.,
-    #     add_latex_file_hook( \&subname );
-    # It is also possible to use an anonymous subroutine, e.g.,
-    #     add_latex_file_hook( sub{  code of subroutine... } );
-    my ($sub_name) = @_;
-    push @latex_file_hooks, $sub_name;
+sub run_hooks {
+    # Usage: run_hooks( stackname, ... )
+    # Call the subroutines whose references on on the named stack.
+    # They are given arguments as follows
+    #   a. If arguments follow the stackname in the call to run_hooks, these
+    #      are given to the called subroutines.
+    #   b. Otherwise a hash of information is given to the called subroutines.
+    # Return 1 for success, 0 for failure.        
+    my $name = shift;
+    my $Pstack = $hooks{$name};
+    my @args = @_;
+    if (!@args) { @args = &info_make; }
+    else { print "Have args\n"; }
+    if (defined $Pstack) {
+        # Do NOT use default $_, as in "for (...) {...}":
+        # The called subroutine may change $_, which is a global variable
+        # (although localized to the for loop and called subroutines).
+        for my $Psub ( @$Pstack) { &$Psub(@args); }
+        return 1;
+    }
+    else {
+        warn "run_hooks: No stack named '$name'\n";
+        return 0;
+    }
 }
 
+#-------------------------------------
+
+sub info_make {
+    my %info_make = (
+        'aux_main'  => $aux_main,
+        'fls_file'  => $fls_name,
+        'log_file'  => $log_name,
+        'root_name' => $root_filename,
+        'tex_file'  => $texfile_name,   
+
+        'aux_dir'   => $aux_dir,
+        'aux_dir1'  => $aux_dir1,
+        'out_dir'   => $out_dir,
+        'out_dir1'  => $out_dir1,
+        );
+    # Rule data, if in rule context:
+    if ($rule)    { $info_make{rule} = $rule; }
+    if ($Pbase)   { $info_make{base} = $$Pbase; }
+    if ($Psource) { $info_make{source} = $$Psource; }
+    if ($Pdest)   { $info_make{dest} = $$Pdest; }
+    return %info_make;
+}
+
 ####################################################
 
 sub set_input_ext {
@@ -9666,9 +9848,7 @@
     # custom dependencies to make the missing file, it will assume that
     # the file has one of the specified extensions.
     my $rule = shift;
-    $input_extensions{$rule} = {};
-    my $Prule = $input_extensions{$rule};
-    foreach (@_) { $$Prule{$_} = 1; }
+    $input_extensions{$rule} = { map { $_ => 1 } @_ };
 }
 
 ####################################################
@@ -9728,6 +9908,16 @@
 
 #************************************************************
 
+# How I use the result of loading glob routines:
+sub my_glob {
+    my @results = ();
+    if ($have_bsd_glob) { @results = bsd_glob( $_[0] ); }
+    else { @results =  glob( $_[0] ); }
+    return @results;
+}
+
+#************************************************************
+
 sub uniq 
 # Read arguments, delete neighboring items that are identical,
 # return array of results
@@ -9847,36 +10037,6 @@
 
 #################################
 
-sub get_filetime_offset {
-    # Usage: get_filetime_offset( prefix, [suffix] )
-    # Measures offset between filetime in a directory and system time
-    # Makes a temporary file of a unique name, and deletes in.
-    # Filename is of form concatenation of prefix, an integer, suffix.
-    # Prefix is normally of form dir/ or dir/tmp.
-    # Default default suffix ".tmp".
-    my $prefix = $_[0];
-    my $suffix = $_[1] || '.tmp';
-    my $tmp_file_count = 0;
-    while (1==1) {
-        # Find a new temporary file, and make it.
-        $tmp_file_count++;
-        my $tmp_file = "${prefix}${tmp_file_count}${suffix}";
-        if ( ! -e $tmp_file ) {
-            open( TMP, ">$tmp_file" ) 
-                or die "$My_name.get_filetime_offset: In measuring filetime offset, couldn't write to\n",
-                       "    temporary file '$tmp_file'\n";
-            my $time = time();
-            close(TMP);
-            my $offset = get_mtime($tmp_file) - $time;
-            unlink $tmp_file;
-            return $offset;
-         }
-     }
-     die "$My_name.get_filetime_offset: BUG TO ARRIVE HERE\n";
-}
-
-#################################
-
 sub tempfile1 {
     # Makes a temporary file of a unique name.  I could use file::temp,
     # but it is not present in all versions of perl.
@@ -9889,9 +10049,9 @@
         $tmp_file_count++;
         my $tmp_file = "${tmpdir}/${prefix}${tmp_file_count}${suffix}";
         if ( ! -e $tmp_file ) {
-            open( TMP, ">$tmp_file" ) 
+            open( my $tmp, ">$tmp_file" ) 
                or next;
-            close(TMP);
+            close($tmp);
             return $tmp_file;
          }
      }
@@ -9912,17 +10072,6 @@
 
 #==================
 
-sub Run_time {
-    # This is wrapper around Run to capture timing information
-    my $time1 = processing_time();
-    my ($pid, $return) = Run($_[0]);
-    my $time = processing_time() - $time1;
-    push @timings, "'$_[0]': time = $time\n"; 
-    return ($pid, $return);
-} #END Run_time
-
-#==================
-
 sub Run {
 # Usage: Run_no_time ("command string");
 #    or  Run_no_time ("one-or-more keywords command string");
@@ -9999,13 +10148,13 @@
     if ( $cmd_line =~ /^internal\s+([a-zA-Z_]\w*)\s+(.*)$/ ) {
         my $routine = $1;
         my @args = parse_quotes( $2 );
-        warn "$My_name: calling $routine( $2 )\n"
+        print "$My_name: calling $routine( $2 )\n"
             if (! $silent);
         return ( 0, &$routine( @args ) );
     }
     elsif ( $cmd_line =~ /^internal\s+([a-zA-Z_]\w*)\s*$/ ) {
         my $routine = $1;
-        warn "$My_name: calling $routine()\n"
+        print "$My_name: calling $routine()\n"
             if (! $silent);
         return ( 0, &$routine() );
     }
@@ -10045,7 +10194,7 @@
 
     my $cmd_line = $_[0];
 
-##    warn "Running '$cmd_line' detached...\n";
+##    print "Running '$cmd_line' detached...\n";
     if ( $cmd_line =~ /^NONE / ) {
         warn "$My_name: ",
              "Program not implemented for this version.  Command line:\n";
@@ -10061,17 +10210,17 @@
     } else {
         # Assume anything else is UNIX or clone
         # For this purpose cygwin behaves like UNIX.
-        ## warn "Run_Detached.UNIX: A\n";
+        ## print "Run_Detached.UNIX: A\n";
         my $pid = fork();
-        ## warn "Run_Detached.UNIX: B pid=$pid\n";
+        ## print "Run_Detached.UNIX: B pid=$pid\n";
         if ( ! defined $pid ) {
-            ## warn "Run_Detached.UNIX: C\n";
+            ## print "Run_Detached.UNIX: C\n";
             warn "$My_name: Could not fork to run the following command:\n";
             warn "   '$cmd_line'\n";
             return (0, 1);
         }
         elsif( $pid == 0 ){
-           ## warn "Run_Detached.UNIX: D\n";
+           ## print "Run_Detached.UNIX: D\n";
            # Forked child process arrives here
            # Insulate child process from interruption by ctrl/C to kill parent:
            #     setpgrp(0,0);
@@ -10083,12 +10232,12 @@
            die "$My_name forked process: could not run the command\n",
                "  '$cmd_line'\n";
         }
-        ##warn "Run_Detached.UNIX: E\n";
+        ##print "Run_Detached.UNIX: E\n";
         # Original process arrives here
         return ($pid, 0);
     }
     # NEVER GET HERE.
-    ##warn "Run_Detached.UNIX: F\n";
+    ##print "Run_Detached.UNIX: F\n";
 } #END Run_Detached
 
 #************************************************************
@@ -10232,7 +10381,7 @@
 
 sub ifcd_popd {
     if ( $do_cd ) {
-        warn "$My_name: Undoing directory change\n"
+        print "$My_name: Undoing directory change\n"
           if !$silent;
         &popd;
     }



More information about the tex-live-commits mailing list.