diff options
author | Karl Berry <karl@freefriends.org> | 2019-03-19 21:28:43 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2019-03-19 21:28:43 +0000 |
commit | caa11ce41041a8197fb5bef003de1a5dd0ecf277 (patch) | |
tree | eb9d8940c7147be142d65f0f8d67c4e269498d02 /Build/source | |
parent | ef1f2fe2f48a08a89cc523d65ea2f29e5b26f058 (diff) |
latexmk (19mar19)
git-svn-id: svn://tug.org/texlive/trunk@50472 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source')
5 files changed, 1465 insertions, 1000 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/latexmk/latexmk.pl b/Build/source/texk/texlive/linked_scripts/latexmk/latexmk.pl index 9a9588160c7..ed200a7c225 100755 --- a/Build/source/texk/texlive/linked_scripts/latexmk/latexmk.pl +++ b/Build/source/texk/texlive/linked_scripts/latexmk/latexmk.pl @@ -1,5 +1,10 @@ #!/usr/bin/env perl +#!!!!!!!!!!!!!!!!!!!????????? CLEAN UP INITIALIZATION +#!!! See all FIX items. + +# Perhaps add subroutine rdb_change_active( (rules to deactivate), (rules to activate)) + # ?? Still need to fix bcf error issue. # Don't keep looping after error # pvc: Only re-run on USER FILE CHANGE. @@ -119,71 +124,6 @@ use warnings; # Test for already running previewer gets wrong answer if another # process has the viewed file in its command line -$my_name = 'latexmk'; -$My_name = 'Latexmk'; -$version_num = '4.61'; -$version_details = "$My_name, John Collins, 25 October 2018"; - -use Config; -use File::Basename; -use File::Copy; -use File::Spec; - -# If possible, use better glob, which does not use space as item separator. -# It's either File::Glob::bsd_glob or File::Glob::glob -# The first does not exist in old versions of Perl, while the second -# is deprecated in more recent versions and will be removed -$have_bsd_glob = 0; -sub my_glob { - if ($have_bsd_glob) { return bsd_glob( $_[0] ); } - else { return glob( $_[0] ); } -} -use File::Glob; -if ( eval{ File::Glob->import('bsd_glob'); 1; } ) { - # Success in importing bsd_glob - $have_bsd_glob = 1; -} -elsif ( eval{ File::Glob->import('glob'); 1; } ) { - warn "$My_name: I could not import File::Glob:bsd_glob, probably because your\n", - " Perl is too old. I have arranged to use the deprecated File::Glob:glob\n", - " instead.\n", - " WARNING: It may malfunction on clean up operation on filenames containing\n", - " spaces.\n"; - $have_bsd_glob = 0; -} -else { - die "Could not import 'File::Glob:bsd_glob' or 'File::Glob:glob'\n"; -} - -use File::Path 2.08 qw( make_path ); -use FileHandle; -use File::Find; -use List::Util qw( max ); -use Cwd; # To be able to change cwd -use Cwd "chdir"; # Ensure $ENV{PWD} tracks cwd -use Digest::MD5; - -#use strict; - -# The following variables are assigned once and then used in symbolic -# references, so we need to avoid warnings 'name used only once': -use vars qw( $dvi_update_command $ps_update_command $pdf_update_command ); - -# Translation of signal names to numbers and vv: -%signo = (); -@signame = (); -if ( defined $Config{sig_name} ) { - $i = 0; - foreach $name (split('\s+', $Config{sig_name})) { - $signo{$name} = $i; - $signame[$i] = $name; - $i++; - } -} -else { - warn "Something wrong with the perl configuration: No signals?\n"; -} - ## Copyright John Collins 1998-2018 ## (username jcc8 at node psu.edu) ## (and thanks to David Coppit (username david at node coppit.org) @@ -222,64 +162,44 @@ else { ## ## 12 Jan 2012 STILL NEED TO DOCUMENT some items below ## +## 17 Mar 2019 John Collins Further test for problems when linking rules +## 17 Mar 2019 John Collins V. 4.63b. +## 17 Mar 2019 John Collins Fix problem revealed by bibtopic package +## 15 Mar 2019 John Collins Corrections +## 14 Mar 2019 John Collins Version to 4.63a +## 12-14 Mar 2019 John Collins Jobname has placeholder +## 8-11 Mar 2019 John Collins Correct aux-dir bugs +## 8 Mar 2019 John Collins Version to 4.63 +## 1 Jan 2019 John Collins Correct bug in output switching code +## 31 Dec 2018 John Collins Correct bug that with $cleanup_includes_generated +## -c mode deletes final output files (e.g., .dvi, .pdf). +## 13 Dec 2018 John Collins Fixes, cleanup +## 12 Dec 2018 John Collins Fix rdb_read +## 11 Dec 2018 John Collins For output-switch: Reorganize initialization +## Remove possibility of more than one primary. +## 1 Dec 2018 John Collins Clean up some code. +## 30 Nov 2018 John Collins Allow any characters in directory part of tex +## filename when cd mode on. (Still standard +## set of disallowed characters applies basename.) +## 21 Nov 2018 John Collins Infrastructure finished, I think, for active flag +## Start on output switch +## 16 Nov 2018 John Collins Remove in non-diagnostics mode a warning about +## rule not in use in this session that is given +## when reading an fdb_latexmk file. +## 2 Nov 2018 John Collins Start implementing active flag for rules. +## 1 Nov 2018 John Collins Fix finding of missing files that are relative to aux_dir +## 29-31 Oct 2018 John Collins Some cleanup. +## 27,28 Oct 2018 John Collins Fix bug that in -pvc mode, after an error in +## certain rules, new rounds of compilation +## are triggered because of changes in generated +## files, instead of only by later user-generated +## changes. +## Improve linking of rules. +## 25 Oct 2018 John Collins V. 4.62 +## Clean up can remove (empty) directories ## 25 Oct 2018 John Collins Fix definition of clean up substitution for %R ## so that something with intermediate %R works, ## as in 'pythontex-files-%R/*'. -## 24 Oct 2018 John Collins V. 4.61 -## 16 Oct 2018 John Collins Routines for setting all of $latex, etc. -## Variables, options, substitutable parameters -## for executing code in *latex before inputting -## source file. -## 10 Oct 2018 John Collins Fix problem that if biber gets a remote file, -## it would be deleted and latexmk would report -## it as missing, incorrectly. -## 8 Oct 2018 John Collins Report count of warnings about missing characters -## (typically unavailable Unicode characters). -## Messages about this may appear only in the .log -## file and are therefore easily missed by the user. -## V. 4.60a -## 21 Sep 2018 John Collins Fix bug that --gg with --deps-file doesn't -## create deps file. -## 3 Sep 2018 John Collins -pdfxelatex and -pdflualatex options -## 3 Sep 2018 John Collins V. 4.60 -## 7 Aug 2018 John Collins V. 4.59 Released on CTAN -## 1 Aug 2018 John Collins Correct sub rdb_find_source_file. -## 30 Jul 2018 John Collins Change handling of warnings for a difference -## between actual and expected output filenames -## for a run of a primary rule. Only give a -## warning if the extensions differ. -## In all other cases, there were significant -## numbers of false positives and no true positives. -## Improve providing of -no-pdf option to xelatex, to -## ensure it's used even after a user redefinition -## of $xelatex. Works if %O is in definition. -## 25 Jul 2018 John Collins Clean up of code. -## 24 Jul 2018 John Collins Fatal error when filename has initial '&'. This -## is not allowed for TeX file, since TeX et al -## treat the initial '&' as specifying the format. -## 20,21,23 Jul 2018 John Collins Improve quoting in file-not-found messages -## On MS-Win change \ to / on files on command line -## 18,19 Jul 2018 John Collins Complete TEXINPUTS stuff -## Fix reading of file database file when -## custom dependency no longer exists. -## 13,17 Jul 2018 John Collins Deal with double quotes in specified filename, -## and filenames not allowed by TeX. -## Illegal characters and unbalanced quotes give fatal error. -## 10 Jul 2018 John Collins Use TEXINPUTS for finding source file for cus dep. -## Version 4.58. -## 21 Jun 2018 John Collins Version 4.57. -## In get_checksum_md5, open file with mode :bytes, -## to avoid error about malformed utf8 characters -## that can happen if PERL_UNICODE is set. -## 15 Jun 2018 John Collins Configuration to be able to turn off bibtex fudge. -## 24,25 May 2018 John Collins Fix problem of .bib files not found with msys. -## Add use of environment variable LATEXMKRCSYS -## 12 May 2018 John Collins Simplify code in run_bibtex. -## 3,9 May 2018 John Collins Improved diagnostics on mismatch of output filenames -## 28,30 Apr 2018 John Collins Improve error messages for bib files not found -## 26 Apr 2018 John Collins In testing for different expected and actual -## output of primary run, normalize $$Pdest, to -## avoid spurious warnings. ## ## 1998-2018, John Collins. Many improvements and fixes. ## See CHANGE-log.txt for full list, and CHANGES for summary @@ -299,6 +219,71 @@ else { ## 20 = probable bug ## or retcode from called program. +$my_name = 'latexmk'; +$My_name = 'Latexmk'; +$version_num = '4.63b'; +$version_details = "$My_name, John Collins, 17 March 2019"; + +use Config; +use File::Basename; +use File::Copy; +use File::Spec; + +# If possible, use better glob, which does not use space as item separator. +# It's either File::Glob::bsd_glob or File::Glob::glob +# The first does not exist in old versions of Perl, while the second +# is deprecated in more recent versions and will be removed +$have_bsd_glob = 0; +sub my_glob { + if ($have_bsd_glob) { return bsd_glob( $_[0] ); } + else { return glob( $_[0] ); } +} +use File::Glob; +if ( eval{ File::Glob->import('bsd_glob'); 1; } ) { + # Success in importing bsd_glob + $have_bsd_glob = 1; +} +elsif ( eval{ File::Glob->import('glob'); 1; } ) { + warn "$My_name: I could not import File::Glob:bsd_glob, probably because your\n", + " Perl is too old. I have arranged to use the deprecated File::Glob:glob\n", + " instead.\n", + " WARNING: It may malfunction on clean up operation on filenames containing\n", + " spaces.\n"; + $have_bsd_glob = 0; +} +else { + die "Could not import 'File::Glob:bsd_glob' or 'File::Glob:glob'\n"; +} + +use File::Path 2.08 qw( make_path ); +use FileHandle; +use File::Find; +use List::Util qw( max ); +use Cwd; # To be able to change cwd +use Cwd "chdir"; # Ensure $ENV{PWD} tracks cwd +use Digest::MD5; + +#use strict; + +# The following variables are assigned once and then used in symbolic +# references, so we need to avoid warnings 'name used only once': +use vars qw( $dvi_update_command $ps_update_command $pdf_update_command ); + +# Translation of signal names to numbers and vv: +%signo = (); +@signame = (); +if ( defined $Config{sig_name} ) { + $i = 0; + foreach $name (split('\s+', $Config{sig_name})) { + $signo{$name} = $i; + $signame[$i] = $name; + $i++; + } +} +else { + warn "Something wrong with the perl configuration: No signals?\n"; +} + # Line length in log file that indicates wrapping. # This number EXCLUDES line-end characters, and is one-based. @@ -355,8 +340,8 @@ $illegal_in_texname = "\x00\t\f\n\r\$%\\~\x7F"; # Specification of templates for extra rules. -# See subroutine rdb_make_rule_list for examples of rule templates. -# See subroutine rdb_set_rules for how they get used to construct rules. +# See subroutine rdb_initialize_rules for examples of rule templates, and +# how they get used to construct rules. # (Documentation obviously needs to be improved!) %extra_rule_spec = (); @@ -403,20 +388,25 @@ $pdflatex_silent_switch = '-interaction=batchmode'; $lualatex_silent_switch = '-interaction=batchmode'; $xelatex_silent_switch = '-interaction=batchmode'; +%input_extensions = (); # %input_extensions maps primary_rule_name to pointer to hash of file extensions # used for extensionless files specified in the source file by constructs # like \input{file} \includegraphics{file} -# Could write -#%input_extensions = ( 'latex' => { 'tex' => 1, 'eps' => 1 };, -# 'pdflatex' => { 'tex' => 1, 'pdf' => 1, 'jpg' => 1, 'png' => 1 }; ); -# Instead we'll exercise the user-friendly access routines: -add_input_ext( 'latex', 'tex', 'eps' ); -add_input_ext( 'pdflatex', 'tex', 'jpg', 'pdf', 'png' ); -add_input_ext( 'lualatex', 'tex', 'jpg', 'pdf', 'png' ); -add_input_ext( 'xelatex', 'tex', 'jpg', 'pdf', 'png' ); -#show_input_ext( 'latex' ); show_input_ext( 'pdflatex' ); +set_input_ext( 'latex', 'tex', 'eps' ); +set_input_ext( 'pdflatex', 'tex', 'jpg', 'pdf', 'png' ); +$input_extensions{lualatex} = $input_extensions{pdflatex}; +$input_extensions{xelatex} = $input_extensions{pdflatex}; +# Save these values as standards to be used when switching output, +# i.e., when actual primary rule differs from standard. +%standard_input_extensions = %input_extensions; %allowed_output_ext = ( ".dvi" => 1, ".xdv" => 1, ".pdf" => 1 ); +# Extensions of files preserved when clean up is by -c rather than -C: +%small_cleanup_preserved_exts = (); +foreach ( 'dvi', 'dviF', 'ps', 'psF', 'pdf', 'synctex.gz', 'xdv' ) { + $small_cleanup_preserved_exts{$_} = 1; +} + # Information about options to latex and pdflatex that latexmk will simply # pass through to (pdf)latex @@ -1120,11 +1110,18 @@ $fdb_ext = 'fdb_latexmk'; # Extension for the file for latexmk's $fdb_ver = 3; # Version number for kind of fdb_file. $jobname = ''; # Jobname: as with current tex, etc indicates - # basename of generated files. - # Defined so that --jobname=STRING on latexmk's - # command line has same effect as with current - # tex, etc. (If $jobname is non-empty, then - # the --jobname=... option is used on tex.) + # basename of generated files. Defined so + # that --jobname=STRING on latexmk's command + # line has same effect as with current tex, + # etc, with the exception listed below. (If + # $jobname is non-empty, then the + # --jobname=... option is used on tex.) + # Extension: $jobname is allowed to contain + # placeholder(s) (currently only %A), + # which allows construction of jobnames + # dependent on name of main TeX file; this is + # useful when a jobname is used and latexmk is + # invoked on multiple files. $out_dir = ''; # Directory for output files. # Cf. --output-directory of current (pdf)latex $aux_dir = ''; # Directory for aux files (log, aux, etc). @@ -1403,21 +1400,34 @@ if (!$BIBINPUTS) { $BIBINPUTS = '.'; } %possible_primaries = ( 'latex' => 'primary', 'pdflatex' => 'primary', 'lualatex' => 'primary', 'xelatex' => 'primary' ); -%primaries = (); # Hash of rules for primary part of make. Keys are - # currently 'latex', 'pdflatex' or both; also 'lualatex' - # and 'xelatex'. Value is currently irrelevant. - # Use hash for ease of lookup - # Make remove this later, if use rdb_makeB - -# Hashes, whose keys give names of particular kinds of rule. We use -# hashes for ease of lookup. + +# Hashes, whose keys give names of particular kinds of rule, and targets. +# We use hashes for ease of lookup. %possible_one_time = ( 'view' => 1, 'print' => 1, 'update_view' => 1, ); -%requested_filerules = (); # Hash for rules corresponding to requested files. - # The keys are the rulenames and the value is +%target_files = (); # Hash for target files. + # The keys are the filenames and the value is # currently irrelevant. +%target_rules = (); # Hash for target rules beyond those corresponding to files. + # The keys are the rule names and the value is + # currently irrelevant. +# The target **files** can only be set inside the FILE loop. +$current_primary = 'latex'; # Rule to compile .tex file. + # Subject to document-dependent override if .tex document + # uses metcommands andobeying them is enabled. +$pdf_method = ''; # How to make pdf file. '' if not requested, + # else 'ps2pdf', 'dvipdf', 'pdflatex', 'lualatex' or 'xelatex' + # Subject to document-dependent override if .tex document + #uses \pdfoutput or c. +%requested_filetypes = (); # Hash of requested file types (dvi, dviF, etc) %one_time = (); # Hash for requested one-time-only rules, currently # possible values 'print' and 'view'. +%actives = (); # Hash of active rules + +$allow_switch = 1; # Allow switch of rule structure to accommodate + # changed output file name of primary. Even if + # this flag is set on, the switch may be + # prohibited by other issues. %rule_db = (); # Database of all rules: # Hash: rulename -> [array of rule data] @@ -1428,7 +1438,7 @@ if (!$BIBINPUTS) { $BIBINPUTS = '.'; } # time_of_last_run, time_of_last_file_check, # changed # last_result, last_message, - # default_extra_generated + # default_extra_generated, # ] # where # cmd_type is 'primary', 'external', or 'cusdep' @@ -1466,6 +1476,7 @@ if (!$BIBINPUTS) { $BIBINPUTS = '.'; } # this rule needs to be run # (typically because a source # file has changed). + # Other values may be used for special cases. # 0 otherwise # out_of_date_user is like out_of_date, except # that the detection of out-of-dateness @@ -1503,6 +1514,9 @@ if (!$BIBINPUTS) { $BIBINPUTS = '.'; } # default_extra_generated is a reference to an array # of specifications of extra generated files (beyond # the main dest file. Standard place holders are used. + # active (1 or 0) is whether the rule is currently active + # and hence accessed in recursion and linked to + # # Example ['%Y%R.log'] for (pdf)latex, and ['%R.blg'] # for bibtex. (There's no need for '%R.aux', here, # since such generated files are detected dynamically.) @@ -1538,7 +1552,26 @@ if (!$BIBINPUTS) { $BIBINPUTS = '.'; } # This lists all generated files; the values # are currently unused, only the keys -%fdb_current = (); # Fdb-hash for all files used. +%fdb_current = (); # Hash of information for all files used. + # It maps filename to a reference to an array + # (time, size, md5_checksum). +@nofile = (0,-1,0); # What we use for initializing a new entry in fdb + # or flagging non-existent file. + +# The following provide information about the structure of the network of rules +# and files. They are set by the routine rdb_set_rule_net +%from_rules = (); # Used to optimize test for whether a file is generated. + # This maps files to rules that generate them. (Files + # anywhere in %$PHdest.) +%from_rules_main = (); # Used to optimize test for whether a file is generated. + # This maps files to rules that generate them as the + # MAIN output. (I.e., file $$Pdest only.) +# Classification of rules, for determining order of application +%current_primaries = (); # Keys are primary rules (latex, etc) that are currently in use. +@pre_primary = (); # Array of rules that are thought of as pre-primary +@post_primary = (); # Array of rules that are thought of as post-primary +@unusual_one_time = (); # Array of rules that are special cases of one-time rules. + # Currently not used. # User's home directory @@ -1598,15 +1631,15 @@ sub read_first_rc_file_in_list { if ( $auto_rc_use ) { # System rc file: if (exists $ENV{LATEXMKRCSYS} ) { - push @rc_system_files, $ENV{LATEXMKRCSYS}; - if ( !-e $ENV{LATEXMKRCSYS} ) { - warn "$My_name: you've specified a system rc file `$ENV{LATEXMKRCSYS}`\n", - " in environment variable LATEXMKRCSYS, but the file doesn't exist.\n", - " I won't read any system rc file.\n"; - } - else { + push @rc_system_files, $ENV{LATEXMKRCSYS}; + if ( !-e $ENV{LATEXMKRCSYS} ) { + warn "$My_name: you've specified a system rc file `$ENV{LATEXMKRCSYS}`\n", + " in environment variable LATEXMKRCSYS, but the file doesn't exist.\n", + " I won't read any system rc file.\n"; + } + else { process_rc_file( $ENV{LATEXMKRCSYS} ); - } + } } else { read_first_rc_file_in_list( @rc_system_files ); @@ -1781,8 +1814,8 @@ while ($_ = $ARGV[0]) "options known to the (pdf)latex programs that are also recognized by\n", "latexmk and trigger special behavior by latexmk. Since these options\n", "appear in the main list given by running 'latexmk --help', they do not\n", - "appear in the following list\n", - "NOTE ALSO: Not all of these options are supported by all versions of (pdf)latex.\n", + "appear in the following list\n", + "NOTE ALSO: Not all of these options are supported by all versions of (pdf)latex.\n", "\n"; foreach $option ( sort( keys %allowed_latex_options, keys %allowed_latex_options_with_arg ) ) { if (exists $allowed_latex_options{$option} ) { print " $allowed_latex_options{$option}\n"; } @@ -2030,13 +2063,18 @@ if ($preview_continuous_mode && ($num_files != 1) ) { } # If selected jobname, can only apply that to one file: -if ( ($jobname ne '') && ($num_files > 1) ) { +if ( ($jobname ne '') && ($jobname !~ /%A/) && ($num_files > 1) ) { &exit_help( "Need to specify at most one filename if ". - "jobname specified, \n". + "jobname specified without a %A, \n". " but $num_files were found (after defaults and wildcarding)." ); } +if ( $jobname =~ /%[^A]/ ) { + &exit_help( + "Jobname '$jobname' contains placeholder other than %A." + ); +} # Normalize the commands, to have place-holders for source, dest etc: &fix_cmds; @@ -2096,9 +2134,10 @@ if ( $aux_dir && ($aux_dir ne $out_dir) ) { \$latex, \$pdflatex, \$lualatex, \$xelatex ); } -if ( $jobname ne '' ) { - $jobstring = "--jobname=\"$jobname\""; - add_option( "$jobstring", \$latex, \$lualatex, \$pdflatex, \$xelatex ); +if ( $jobname ne '' ) { + # Since $jobname may include placeholder(s), put %R placeholder + # in option, and let %R be substituted by actual jobname at runtime. + add_option( "--jobname=%R", \$latex, \$lualatex, \$pdflatex, \$xelatex ); } # Which kind of file do we preview? @@ -2124,29 +2163,59 @@ if ( ! ( $dvi_mode || $pdf_mode || $postscript_mode || $printout_mode) ) { $dvi_mode = 1; } -# Set new-style requested rules: -if ( $dvi_mode ) { $requested_filerules{'latex'} = 1; } -if ( $pdf_mode == 1 ) { $requested_filerules{'pdflatex'} = 1; } +# Determine requests. +if ( $banner ) { $postscript_mode = 1; } +if ( $dvi_mode ) { + $current_primary = 'latex'; + $requested_filetypes{'dvi'} = 1; + if ( length($dvi_filter) != 0 ) { $requested_filetypes{'dviF'} = 1; } +} +if ( $postscript_mode ) { + $current_primary = 'latex'; + $requested_filetypes{'ps'} = 1; + if ( length($ps_filter) != 0 ) { $requested_filetypes{'psF'} = 1; } +} + +if ($pdf_mode > 5) { + warn "$My_name: Non-allowed value of \$pdf_mode = $pdf_mode,", + " replaced by 1.\n"; + $pdf_mode = 1; +} +if ( ($dvi_mode || $postscript_mode) && $pdf_mode ) { + my %disallowed = (); + foreach (1,4,5) { $disallowed{$_} = 1; } + if ($disallowed{$pdf_mode}) { + warn "$My_name: \$pdf_mode = $pdf_mode is incompatible with dvi and postscript modes\n", + " which are required by other requests.\n"; + if ($postscript_mode) {$pdf_mode = 2;} + else { $pdf_mode = 3; } + warn " I replaced it by $pdf_mode.\n"; + } +} +if ( $pdf_mode == 0 ) { + $pdf_method = ''; +} +elsif ( $pdf_mode == 1 ) { + $requested_filetypes{'pdf'} = 1; + $pdf_method = 'pdflatex'; +} elsif ( $pdf_mode == 2 ) { - $requested_filerules{'latex'} = 1; - $requested_filerules{'dvips'} = 1; - $requested_filerules{'ps2pdf'} = 1; + $requested_filetypes{'pdf'} = 1; + $pdf_method = 'ps2pdf'; } elsif ( $pdf_mode == 3 ) { - $requested_filerules{'latex'} = 1; - $requested_filerules{'dvipdf'} = 1; + $requested_filetypes{'pdf'} = 1; + $pdf_method = 'dvipdf'; } elsif ( $pdf_mode == 4 ) { - $requested_filerules{'lualatex'} = 1; + $requested_filetypes{'pdf'} = 1; + $pdf_method = 'lualatex'; } elsif ( $pdf_mode == 5 ) { - $requested_filerules{'xelatex'} = 1; - $requested_filerules{'xdvipdfmx'} = 1; -} -if ( $postscript_mode ) { - $requested_filerules{'latex'} = 1; - $requested_filerules{'dvips'} = 1; + $requested_filetypes{'pdf'} = 1; + $pdf_method = 'xelatex'; } + if ($print_type eq 'auto') { if ( $postscript_mode ) { $print_type = 'ps'; } elsif ( $pdf_mode ) { $print_type = 'pdf'; } @@ -2160,9 +2229,20 @@ if ( $printout_mode ) { } } if ( $preview_continuous_mode || $preview_mode ) { $one_time{'view'} = 1; } -if ( length($dvi_filter) != 0 ) { $requested_filerules{'dvi_filter'} = 1; } -if ( length($ps_filter) != 0 ) { $requested_filerules{'ps_filter'} = 1; } -if ( $banner ) { $requested_filerules{'dvips'} = 1; } + +$can_switch = $allow_switch; +if ( $dvi_mode || $postscript_mode + || ( $printout_mode && ($print_type eq 'ps') || ($print_type eq 'dvi') ) + || ( ($preview_mode || $preview_continuous_mode) && ( ($view eq 'ps') || ($view eq 'dvi') ) ) + ) { + # Automatic switching (e.g., pdf<->dvi o/p) requires pdf files to be + # the only destinations. So if ps or dvi files needed, we cannot + # allow switching. (There will then be an error condition if a TeX + # engine fails to produce the correct type of output file.) + warn "$My_name: Disallowing switch of output file as incompatible\n", + " with file requests.\n"; + $can_switch = 0; +} if ( $pdf_mode == 2 ) { @@ -2264,7 +2344,8 @@ foreach $filename ( @file_list ) if ( $do_cd ) { ($filename, $path) = fileparse( $filename ); - warn "$My_name: Changing directory to '$path'\n"; + warn "$My_name: Changing directory to '$path'\n" + if !$silent; pushd( $path ); } else { @@ -2282,7 +2363,7 @@ foreach $filename ( @file_list ) warn "$My_name: you requested output directory '$out_dir',\n", " but an ordinary file of the same name exists, which will\n", " probably give an error later\n"; - } + } } if ( $aux_dir && ($aux_dir ne $out_dir) ) { @@ -2293,50 +2374,31 @@ foreach $filename ( @file_list ) warn "$My_name: making auxiliary directory '$aux_dir'\n" if ! $silent; make_path $aux_dir; - } + } elsif ( ! -d $aux_dir ) { warn "$My_name: you requested aux directory '$aux_dir',\n", " but an ordinary file of the same name exists, which will\n", " probably give an error later\n"; - } - } - - ## remove extension from filename if was given. - if ( find_basename($filename, $root_filename, $texfile_name) ) - { - if ( $force_mode ) { - warn "$My_name: Could not find file '$texfile_name'\n"; - } - else { - &ifcd_popd; - &exit_msg1( "Could not find file '$texfile_name'", - 11); } } - if ($jobname ne '' ) { - $root_filename = $jobname; - } &set_names; - - # Initialize basic dependency information: - # For use under error conditions: @default_includes = ($texfile_name, $aux_main); - - # Initialize rule database. - # ?? Should I also initialize file database? - %rule_list = (); - &rdb_make_rule_list; - &rdb_set_rules( \%rule_list, \%extra_rule_spec ); - + local %rule_db = (); + &rdb_initialize_rules; + if ( $cleanup_mode > 0 ) { # ?? MAY NEED TO FIX THE FOLLOWING IF $aux_dir or $out_dir IS SET. my %other_generated = (); my @index_bibtex_generated = (); my @aux_files = (); my @missing_bib_files = (); - my $bibs_all_exist = 0; + my $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" @@ -2344,7 +2406,7 @@ foreach $filename ( @file_list ) $have_fdb = ( 0 == rdb_read( $fdb_name ) ); } if ( $have_fdb ) { - rdb_for_all( + rdb_for_actives( sub { # Find generated files at rule level my ($base, $path, $ext) = fileparseA( $$Psource ); $base = $path.$base; @@ -2358,25 +2420,25 @@ foreach $filename ( @file_list ) foreach ( keys %$PHsource ) { if ( ( /\.bib$/ ) && (! -e $_) ) { push @missing_bib_files, $_; - } - } - } - } + } + } + } + } elsif ( exists $other_generated{$$Psource} ) { -# print "=========== CHECKING: source file of rule '$rule', '$$Psource'\n", +# print "=========== CHECKING: source file of rule '$rule', '$$Psource'\n", # " is a generated file.\n"; - ## OLD with apparent bug: + ## OLD with apparent bug: #$other_generated{$$Pdest}; } - foreach my $key (keys %$PHdest) { - $other_generated{$key} = 1; - } + 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; } + ); + 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 @@ -2391,7 +2453,7 @@ foreach $filename ( @file_list ) # Maps output file created and read by (pdf)latex # to source file of conversion. local $primary_out = ''; # Actual output file (dvi or pdf). Not used here. - local $fls_file_analyzed = 0; + local $fls_file_analyzed = 0; &parse_log; %other_generated = %generated_log; } @@ -2399,18 +2461,18 @@ foreach $filename ( @file_list ) 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) - || + my $keep_bbl = 1; + if ( ($bibtex_use > 1.6) + || ( ($bibtex_use == 1.5) && ($bibs_all_exist) ) - ) { + ) { $keep_bbl = 0; - } - if ($keep_bbl) { + } + if ($keep_bbl) { delete $generated_exts_all{'bbl'}; } # Convert two arrays to hashes: @@ -2423,14 +2485,16 @@ foreach $filename ( @file_list ) delete( $other_generated{$_} ); } foreach (@aux_files) { - if (exists $other_generated{$_} ) { - $aux_files{$_} = 1; - } - else { - $aux_files_to_save{$_} = 1; - } + if (exists $other_generated{$_} ) { + $aux_files{$_} = 1; + } + else { + $aux_files_to_save{$_} = 1; + } } + foreach (keys %final_output_files) { delete $other_generated{$_}; } + if ($diagnostics) { show_array( "For deletion, the following were determined from fdb file or log file:\n" ." Generated (from makeindex and bibtex):", @@ -2445,63 +2509,39 @@ foreach $filename ( @file_list ) show_array( " Aux files to SAVE and not delete:", keys %aux_files_to_save ); } - &cleanup1( $aux_dir1, $fdb_ext, 'blg', 'ilg', 'log', 'aux.bak', 'idx.bak', - split('\s+',$clean_ext), - keys %generated_exts_all - ); + my @clean_args = ( 'blg', 'ilg', 'log', 'aux.bak', 'idx.bak', + split('\s+',$clean_ext), keys %generated_exts_all ); + cleanup1( $aux_dir1, @clean_args ); + if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @clean_args ); } + if ( $cleanup_mode == 1 ) { + my @clean_args = ( keys %small_cleanup_preserved_exts, split('\s+', $clean_full_ext) ); + cleanup1( $aux_dir1, @clean_args ); + if ( $out_dir1 ne $aux_dir1 ) { cleanup1( $out_dir1, @clean_args ); } + } unlink_or_move( 'texput.log', "texput.aux", "missfont.log", keys %index_bibtex_generated, - keys %aux_files ); + keys %aux_files ); if ($cleanup_includes_generated) { unlink_or_move( keys %other_generated ); } if ( $cleanup_includes_cusdep_generated) { &cleanup_cusdep_generated; } - if ( $cleanup_mode == 1 ) { - &cleanup1( $out_dir1, 'dvi', 'dviF', 'ps', 'psF', 'pdf', - 'synctex.gz', 'xdv', - split('\s+', $clean_full_ext) - ); - } } 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_set_rules( \%rule_list ); + &rdb_initialize_rules; } if ($cleanup_only) { next FILE; } - -#??? The following are not needed if use rdb_make. -# ?? They may be set too early? -# Arrays and hashes for picking out accessible rules. -# Distinguish rules for making files and others - @accessible_all = sort ( &rdb_accessible( keys %requested_filerules, keys %one_time )); - %accessible_filerules = (); - foreach (@accessible_all) { - unless ( /view/ || /print/ ) { $accessible_filerules{$_} = 1; } - } - @accessible_filerules = sort keys %accessible_filerules; - -# show_array ( "=======All rules used", @accessible_all ); -# show_array ( "=======Requested file rules", sort keys %requested_filerules ); -# show_array ( "=======Rules for files", @accessible_filerules ); - if ( $diagnostics ) { print "$My_name: Rules after start up for '$texfile_name'\n"; rdb_show(); } - %primaries = (); - foreach (@accessible_all) { - if ( ($_ eq 'latex') || ($_ eq 'pdflatex') || ($_ eq 'lualatex') - || ($_ eq 'xelatex') ) - { $primaries{$_} = 1; } - } - $have_fdb = 0; if (! -e $aux_main ) { # No aux file => set up trivial aux file @@ -2509,10 +2549,10 @@ foreach $filename ( @file_list ) # as minimum, but no more if actual aux file is trivial. # (Useful on big files without cross references.) # If aux file doesn't exist, then any fdb file is surely - # wrong. - # Previously, I had condition for this as being both aux and - # fdb files failing to exist. But it's not obvious what to - # do if aux exists and fdb doesn't. So I won't do anything. + # wrong. + # Previously, I had condition for this as being both aux and + # fdb files failing to exist. But it's not obvious what to + # do if aux exists and fdb doesn't. So I won't do anything. &set_trivial_aux_fdb; } @@ -2532,7 +2572,7 @@ foreach $filename ( @file_list ) rdb_for_some( [keys %possible_primaries], \&rdb_set_latex_deps ); } } - foreach $rule ( rdb_accessible( uniq1( keys %requested_filerules ) ) ){ + foreach $rule ( &rdb_accessible ) { # For all source files of all accessible rules, # if the file data are not already set (e.g., from fdb_latexmk # file, set them from disk. @@ -2543,7 +2583,7 @@ foreach $filename ( @file_list ) if ($go_mode) { # Force everything to be remade. - rdb_recurse( [keys %requested_filerules], sub{$$Pout_of_date=1;} ); + rdb_recurse( [ &rdb_target_array], sub{$$Pout_of_date=1;} ); } @@ -2575,15 +2615,15 @@ foreach $filename ( @file_list ) #Initialize failure flags now. $failure = 0; $failure_msg = ''; - $failure = rdb_make( keys %requested_filerules ); + $failure = &rdb_make; if ( ( $failure <= 0 ) || $force_mode ) { rdb_for_some( [keys %one_time], \&rdb_run1 ); } if ($#primary_warning_summary > -1) { - # N.B. $mult_defined, $bad_reference, $bad_character, $bad_citation also available here. + # N.B. $mult_defined, $bad_reference, $bad_character, $bad_citation also available here. if ($warnings_as_errors) { $failure = 1; - $failure_msg = "Warning(s) from latex (or c.) for '$filename'; treated as error"; + $failure_msg = "Warning(s) from latex (or c.) for '$filename'; treated as error"; } } if ($failure > 0) { next FILE; } @@ -2599,11 +2639,11 @@ continue { if ( $failure_msg ) { #Remove trailing space $failure_msg =~ s/\s*$//; - warn "----------------------\n"; - warn "This message may duplicate earlier message.\n"; + warn "----------------------\n"; + warn "This message may duplicate earlier message.\n"; warn "$My_name: Failure in processing file '$filename':\n", " $failure_msg\n"; - warn "----------------------\n"; + warn "----------------------\n"; $failure = 1; } } @@ -2649,12 +2689,12 @@ if ($failure_count > 0) { if ( $where_log == 2 ) { warn "$My_name: You requested aux_dir '$aux_dir_requested',\n". - " but '$aux_dir' was used by the (pdf)latex engine.\n". - " That indicates a configuration error.\n"; + " but '$aux_dir' was used by the (pdf)latex engine.\n". + " That indicates a configuration error.\n"; if ( ($tex_distribution !~ /^MiKTeX/i) && ($aux_dir_requested ne $out_dir_requested) ) { - warn " Probably you set different aux and out directories,\n". - " but that is not supported by your TeX distribution.\n". - " The only current distribution supporting this is MiKTeX.\n"; + warn " Probably you set different aux and out directories,\n". + " but that is not supported by your TeX distribution.\n". + " The only current distribution supporting this is MiKTeX.\n"; } } @@ -2668,7 +2708,7 @@ sub set_tex_cmds { # Usage, e.g., set_tex_cmds( '%O %S' ) my $args = $_[0]; foreach my $cmd ('latex', 'lualatex', 'pdflatex', 'xelatex' ) { - ${$cmd} = "$cmd $args"; + ${$cmd} = "$cmd $args"; } # N.B. See setting of $latex_default_switches, ..., # $xelatex_default_switches, etc, for any special options needed. @@ -2687,28 +2727,37 @@ sub test_fix_texnames { foreach (@_) { if ( $^O eq "MSWin32" ) { # On MS-Win, change directory separator '\' to '/', as needed - # by the TeX engines, for which '\' introduces a macro name. - # Remember that '/' is a valid directory separator in MS-Win. + # by the TeX engines, for which '\' introduces a macro name. + # Remember that '/' is a valid directory separator in MS-Win. s[\\][/]g; } - if ( /[\Q$illegal_in_texname\E]/ ) { - $illegal_char++; - warn "$My_name: Filename '$_' contains character not allowed for TeX file.\n"; - } - my ($filename, $path) = fileparse( $_ ); - if ( $do_cd && ($filename =~ /^&/) ) { - $illegal_char++; - warn "$My_name: Filename part of '$_' contains initial '&', which is\n", - " not allowed for TeX file in my -cd mode.\n"; + if ($do_cd) { + my ($filename, $path) = fileparse( $_ ); + if ($filename =~ /[\Q$illegal_in_texname\E]/ ) { + $illegal_char++; + warn "$My_name: Filename '$filename' contains character not allowed for TeX file.\n"; + } + if ($filename =~ /^&/) { + $illegal_char++; + warn "$My_name: Filename '$filename' contains initial '&', which is\n", + " not allowed for TeX file.\n"; + } } - elsif ( /^&/ ) { - $illegal_char++; - warn "$My_name: Filename '$_' contains initial '&', which is not allowed for TeX file.\n"; + else { + if ( /[\Q$illegal_in_texname\E]/ ) { + $illegal_char++; + warn "$My_name: Filename '$_' contains character not allowed for TeX file.\n"; + } + if (/^&/ ) { + $illegal_char++; + warn "$My_name: Filename '$_' contains initial '&', which is not allowed\n", + " for TeX file.\n"; + } } my $count_q = ($_ =~ tr/\"//); if ( ($count_q % 2) != 0 ) { warn "$My_name: Filename '$_' contains unbalanced quotes, not allowed.\n"; - $unbalanced_quote++; + $unbalanced_quote++; } elsif ( $count_q > 0 ) { warn "$My_name: Removed (balanced quotes) from filename '$_',\n"; @@ -2718,7 +2767,7 @@ sub test_fix_texnames { } } if ($illegal_char || $unbalanced_quote) { - die "$My_name: Stopping because of bad filename(s).\n"; + die "$My_name: Stopping because of bad filename(s).\n"; } } @@ -2732,18 +2781,18 @@ sub ensure_path { my $var = shift; my %cmpts = (); if ( exists $ENV{$var} ) { - foreach ( split $search_path_separator, $ENV{$var} ) { - if ($_ ne '') { $cmpts{$_} = 1; } - } + foreach ( split $search_path_separator, $ENV{$var} ) { + if ($_ ne '') { $cmpts{$_} = 1; } + } } foreach (@_) { next if ( ($_ eq '') || (exists $cmpts{$_}) ); - if (exists $ENV{$var}) { - $ENV{$var} = $_ . $search_path_separator . $ENV{$var}; - } - else { - $ENV{$var} = $_ . $search_path_separator; - } + if (exists $ENV{$var}) { + $ENV{$var} = $_ . $search_path_separator . $ENV{$var}; + } + else { + $ENV{$var} = $_ . $search_path_separator; + } } } @@ -2762,19 +2811,19 @@ sub set_dirs_etc { while ( s[^\.\/][] ) {} } if ($aux_dir) { - # Ensure $aux_dir is in BIBINPUTS and TEXINPUTS search paths. - # TEXINPUTS is used by dvips for files generated by mpost. - # For BIBINPUTS, - # at least one widely package (revtex4-1) generates a bib file - # (which is used in revtex4-1 for putting footnotes in the reference - # list), and bibtex must be run to use it. But latexmk needs to - # determine the existence of the bib file by use of kpsewhich, otherwise - # there is an error. So cope with this situation (and any analogous - # cases by adding the aux_dir to the relevant path search environment - # variables. BIBINPUTS seems to be the only one currently affected. - foreach ( 'BIBINPUTS', 'TEXINPUTS' ) { - ensure_path( $_, $aux_dir ); - } + # Ensure $aux_dir is in BIBINPUTS and TEXINPUTS search paths. + # TEXINPUTS is used by dvips for files generated by mpost. + # For BIBINPUTS, + # at least one widely package (revtex4-1) generates a bib file + # (which is used in revtex4-1 for putting footnotes in the reference + # list), and bibtex must be run to use it. But latexmk needs to + # determine the existence of the bib file by use of kpsewhich, otherwise + # there is an error. So cope with this situation (and any analogous + # cases by adding the aux_dir to the relevant path search environment + # variables. BIBINPUTS seems to be the only one currently affected. + foreach ( 'BIBINPUTS', 'TEXINPUTS' ) { + ensure_path( $_, $aux_dir ); + } } } @@ -2831,24 +2880,71 @@ sub add_option { ############################################################# -sub rdb_make_rule_list { +sub rdb_initialize_rules { + # Initialize rule database. + # (The rule database may get overridden/extended after the fdb_latexmk + # file is read, and after running commands to adjust to dependencies + # determined from document. + %rule_db = (); + %target_rules = (); + %target_files = (); + + local %rule_list = (); + &rdb_set_rule_templates; + + my %rule_template = %rule_list; + while ( my ($key, $value) = each %extra_rule_spec ) { + $rule_template{$key} = $value; + } + foreach my $rule ( keys %rule_template ) { + my ( $cmd_type, $ext_cmd, $int_cmd, $source, $dest, $base, $test_kind, $PA_extra_gen ) = @{$rule_template{$rule}}; + if ( ! $PA_extra_gen ) { $PA_extra_gen = []; } + my $needs_making = 0; + # Substitute in the filename variables, since we will use + # those for determining filenames. But delay expanding $cmd + # until run time, in case of changes. + foreach ($base, $source, $dest, @$PA_extra_gen ) { + s/%R/$root_filename/g; + s/%Y/$aux_dir1/; + s/%Z/$out_dir1/; + } + foreach ($source, $dest ) { + s/%B/$base/; + s/%T/$texfile_name/; + } + rdb_create_rule( $rule, $cmd_type, $ext_cmd, $int_cmd, $test_kind, + $source, $dest, $base, + $needs_making, undef, undef, 1, $PA_extra_gen ); + } # End rule iteration + + # Ensure we only have one way to make pdf file, and that it is appropriate. Remove other incompatibilities + if ($pdf_mode == 1) { rdb_deactivate( 'dvipdf', 'ps2pdf', 'latex', 'lualatex', 'xdvipdfmx', 'xelatex' ); } + elsif ($pdf_mode == 2) { rdb_deactivate( 'dvipdf', 'pdflatex', 'lualatex', 'xdvipdfmx', 'xelatex' ); } + elsif ($pdf_mode == 3) { rdb_deactivate( 'pdflatex', 'ps2pdf', 'lualatex', 'xdvipdfmx', 'xelatex' ); } + elsif ($pdf_mode == 4) { rdb_deactivate( 'pdflatex', 'ps2pdf', 'dvipdf', 'xdvipdfmx', 'xelatex' ); } + elsif ($pdf_mode == 5) { rdb_deactivate( 'pdflatex', 'ps2pdf', 'dvipdf', 'lualatex' ); } + else { rdb_deactivate( 'dvipdf', 'pdflatex', 'ps2pdf', 'lualatex', 'xdvipdfmx', 'xelatex' ); } + + if ($dvi_mode == 1) { + rdb_activate( 'latex' ); + $target_files{$dvi_final} = 1; + } + if ($postscript_mode == 1) { + rdb_activate( 'latex' ); + $target_files{$ps_final} = 1; + } + if ($pdf_mode) { $target_files{$pdf_final} = 1; } + &rdb_set_rule_net; +} # END rdb_initialize_rules + +#************************************************************ + +sub rdb_set_rule_templates { # Set up specifications for standard rules, adjusted to current conditions # Substitutions: %S = source, %D = dest, %B = this rule's base # %T = texfile, %R = root = base for latex. # %Y for $aux_dir1, %Z for $out_dir1 - # Defaults for dvi, ps, and pdf files - # Use local, not my, so these variables can be referenced - local $dvi_final = "%Z%R.dvi"; - local $ps_final = "%Z%R.ps"; - local $pdf_final = "%Z%R.pdf"; - local $xdv_final = "%Z%R.xdv"; - if ( length($dvi_filter) > 0) { - $dvi_final = "%Z%R.dviF"; - } - if ( length($ps_filter) > 0) { - $ps_final = "%Z%R.psF"; - } my $print_file = ''; my $print_cmd = 'NONE'; @@ -2890,109 +2986,143 @@ sub rdb_make_rule_list { # This is because, especially for dvi file, the contents of the file may contain # a pointer to a file to be included, not the contents of the file! %rule_list = ( - 'latex' => [ 'primary', "$latex", '', "%T", "%Z%B.dvi", "%R", 1, ["%Y%R.log"] ], - 'pdflatex' => [ 'primary', "$pdflatex", '', "%T", "%Z%B.pdf", "%R", 1, ["%Y%R.log"] ], - 'lualatex' => [ 'primary', "$lualatex", '', "%T", "%Z%B.pdf", "%R", 1, ["%Y%R.log"] ], - 'xelatex' => [ 'primary', "$xelatex", '', "%T", "%Z%B.xdv", "%R", 1, ["%Y%R.log"] ], - 'dvipdf' => [ 'external', "$dvipdf", 'do_viewfile', $dvi_final, "%B.pdf", "%Z%R", 2 ], - 'xdvipdfmx' => [ 'external', "$xdvipdfmx", 'do_viewfile', $xdv_final, "%B.pdf", "%Z%R", 2 ], - 'dvips' => [ 'external', "$dvips", 'do_viewfile', $dvi_final, "%B.ps", "%Z%R", 2 ], - 'dvifilter'=> [ 'external', $dvi_filter, 'do_viewfile', "%B.dvi", "%B.dviF", "%Z%R", 2 ], - 'ps2pdf' => [ 'external', "$ps2pdf", 'do_viewfile', $ps_final, "%B.pdf", "%Z%R", 2 ], - 'psfilter' => [ 'external', $ps_filter, 'do_viewfile', "%B.ps", "%B.psF", "%Z%R", 2 ], - 'print' => [ 'external', "$print_cmd", 'if_source', $print_file, "", "", 2 ], + 'latex' => [ 'primary', "$latex", '', "%T", $dvi_name, "%R", 1, [$log_name] ], + 'pdflatex' => [ 'primary', "$pdflatex", '', "%T", $pdf_name, "%R", 1, [$log_name] ], + 'lualatex' => [ 'primary', "$lualatex", '', "%T", $pdf_name, "%R", 1, [$log_name] ], + 'xelatex' => [ 'primary', "$xelatex", '', "%T", $xdv_name, "%R", 1, [$log_name] ], + 'dvipdf' => [ 'external', "$dvipdf", 'do_viewfile', $dvi_final, $pdf_name, "%Z%R", 2 ], + 'xdvipdfmx' => [ 'external', "$xdvipdfmx", 'do_viewfile', $xdv_final, $pdf_name, "%Z%R", 2 ], + 'dvips' => [ 'external', "$dvips", 'do_viewfile', $dvi_final, $ps_name, "%Z%R", 2 ], + 'dvifilter' => [ 'external', $dvi_filter, 'do_viewfile', $dvi_name, $dviF_name, "%Z%R", 2 ], + 'ps2pdf' => [ 'external', "$ps2pdf", 'do_viewfile', $ps_final, $pdf_name, "%Z%R", 2 ], + 'psfilter' => [ 'external', $ps_filter, 'do_viewfile', $ps_name, $psF_name, "%Z%R", 2 ], + 'print' => [ 'external', "$print_cmd", 'if_source', $print_file, "", "", 2 ], 'update_view' => [ 'external', $viewer_update_command, $PA_update, $view_file, "", "", 2 ], 'view' => [ 'external', "$viewer", 'if_source', $view_file, "", "", 2 ], ); - -# Ensure we only have one way to make pdf file, and that it is appropriate: - if ($pdf_mode == 2) { delete $rule_list{'dvipdf'}; delete $rule_list{'pdflatex'}; delete $rule_list{'lualatex'}; delete $rule_list{'xelatex'}; } - elsif ($pdf_mode == 3) { delete $rule_list{'pdflatex'}; delete $rule_list{'ps2pdf'}; delete $rule_list{'lualatex'}; delete $rule_list{'xelatex'}; } - elsif ($pdf_mode == 4) { delete $rule_list{'pdflatex'}; delete $rule_list{'ps2pdf'}; delete $rule_list{'dvipdf'}; delete $rule_list{'xelatex'}; } - elsif ($pdf_mode == 5) { delete $rule_list{'pdflatex'}; delete $rule_list{'ps2pdf'}; delete $rule_list{'dvipdf'}; delete $rule_list{'lualatex'}; } - else { # Default is to leave pdflatex - delete $rule_list{'dvipdf'}; delete $rule_list{'ps2pdf'}; delete $rule_list{'lualatex'}; delete $rule_list{'xelatex'}; - } - -} # END rdb_make_rule_list +} # END rdb_set_rule_templates #************************************************************ -sub rdb_set_rules { - # Call rdb_set_rules( \%rule_list, ...) - # Set up rule database from definitions - - # Map of files to rules that MAKE them: - %rule_db = (); - - foreach my $Prule_list (@_) { - foreach my $rule ( keys %$Prule_list) { - my ( $cmd_type, $ext_cmd, $int_cmd, $source, $dest, $base, $test_kind, $PA_extra_gen ) = @{$$Prule_list{$rule}}; - if ( ! $PA_extra_gen ) { $PA_extra_gen = []; } - my $needs_making = 0; - # Substitute in the filename variables, since we will use - # those for determining filenames. But delay expanding $cmd - # until run time, in case of changes. - foreach ($base, $source, $dest, @$PA_extra_gen ) { - s/%R/$root_filename/; - s/%Y/$aux_dir1/; - s/%Z/$out_dir1/; - } - foreach ($source, $dest ) { - s/%B/$base/; - s/%T/$texfile_name/; - } - # print "$rule: $cmd_type, EC='$ext_cmd', IC='$int_cmd', $test_kind,\n", - # " S='$source', D='$dest', B='$base' $needs_making\n"; - rdb_create_rule( $rule, $cmd_type, $ext_cmd, $int_cmd, $test_kind, - $source, $dest, $base, - $needs_making, undef, undef, 1, $PA_extra_gen ); -# !! ?? Last line was -# $needs_making, undef, ($test_kind==1) ); - } - } # End arguments of subroutine +sub rdb_set_rule_net { + # Set network of rules, including links &rdb_make_links; -} # END rdb_set_rules + &rdb_classify_rules; +} #************************************************************ sub rdb_make_links { # ?? Problem if there are multiple rules for getting a file. Notably pdf. # Which one to choose? - # Create $from_rule if there's a suitable rule. - # Map files to rules: - local %from_rules = (); - rdb_for_all( sub{ if($$Pdest){$from_rules{$$Pdest} = $rule;} } ); -#?? foreach (sort keys %from_rules) {print "D='$_' F='$from_rules{$_}\n";} - rdb_for_all( - 0, - sub{ - # Set from_rule, but only if it isn't set or is invalid. - # Don't forget the biber v. bibtex issue - if ( exists $from_rules{$file} - && ( (!$$Pfrom_rule) || (! exists $rule_db{$$Pfrom_rule} ) ) - ) - { $$Pfrom_rule = $from_rules{$file}; - } - } - ); - rdb_for_all( +# ?? 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. + + + &rdb_cache_generated; + rdb_for_actives( 0, sub{ - if ( exists $from_rules{$file} ) { - $$Pfrom_rule = $from_rules{$file}; + if ( exists $from_rules_main{$file} ) { + $$Pfrom_rule = $from_rules_main{$file}; + } + elsif ( exists $from_rules{$file} ) { + $$Pfrom_rule = $from_rules{$file}; } if ( $$Pfrom_rule && (! rdb_rule_exists( $$Pfrom_rule ) ) ) { $$Pfrom_rule = ''; } -#?? print "$rule: $file, $$Pfrom_rule\n"; } - ); + ); +# &rdb_show; } # END rdb_make_links #************************************************************ +sub rdb_cache_generated { + # Update %from_rules + %from_rules = (); + %from_rules_main = (); + rdb_for_actives( \&one_from_main_rule_cache ); + rdb_for_actives( \&one_from_rule_cache ); +} # END rdb_cache_generated + +#------------ + +sub one_from_main_rule_cache { + # Rule context assumed. + # Set from_rules_main items for one rule + if (! $$Pdest) { return; } +# Error message trigger: if ( $$Pdest =~ /pdf$/) { $from_rules_main{$$Pdest} = 'pdflatexA'; } + if ( exists $from_rules_main{$$Pdest} ) { + my $old_rule = $from_rules_main{$$Pdest}; + if ( $old_rule eq $rule ) { + # OK + } + else { + warn "$My_name: Possible bug:\n", + " In linking rules I already set from_rules_main{$$Pdest} to '$old_rule'\n", + " But now I want to set it to '$rule'\n"; +#???? traceback(); + } + } + $from_rules_main{$$Pdest} = $rule; +} # END one_from_main_rule_cache + +#------------ + +sub one_from_rule_cache { + # Rule context assumed. + # Set from_rules items for one rule + foreach ( @$PA_extra_gen, keys %$PHdest ) { + # Error message trigger: if ( $_ =~ /aux$/) { $from_rules{$_} = 'pdflatexA'; } + if ( exists $from_rules{$_} ) { + my $old_rule = $from_rules{$_}; + if ( $old_rule eq $rule ) { + # OK + } + elsif ( exists $from_rules_main{$_} && ( $from_rules_main{$_} ne $rule ) ) { + warn "$My_name: Possible problem:\n", + " In linking rules, I already set from_rules_main{$_}\n". + " to '$from_rules_main{$_}'\n", + " But now I also have a different rule '$rule' that also made the file.\n"; + } + elsif ( exists($possible_primaries{$old_rule}) && exists($possible_primaries{$rule}) ) { + # This could be problematic. But we'll let it go, + # because it is a common case for .aux and .log files + # (etc), and these cases do not appear to mess up + # anything (by experience). + # Once we allow an active flag for rules and only + # examine active rules, the only case of this that + # will appear (in the absence of other problems) will + # be where two primary rules are active, notably a + # latex rule to make dvi and a pdflatex (or other + # rule) to make pdf. + } + else { + warn "$My_name: Possible bug:\n", + " In linking rules I already set from_rules{$_} to '$old_rule'\n", + " But now I want to set it to '$rule'\n"; +#???? traceback(); + } + } + $from_rules{$_} = $rule; + } +} #END from_rule_cache + +#************************************************************ + sub set_trivial_aux_fdb { # 1. Write aux file EXACTLY as would be written if the tex file # had no cross references, etc. I.e., a minimal .aux file. @@ -3005,7 +3135,7 @@ sub set_trivial_aux_fdb { print aux_file "\\relax \n"; close(aux_file); - foreach my $rule (keys %primaries ) { + foreach my $rule (keys %possible_primaries ) { rdb_ensure_file( $rule, $texfile_name ); rdb_ensure_file( $rule, $aux_main ); rdb_one_rule( $rule, @@ -3263,6 +3393,7 @@ sub find_basename { sub make_preview_continuous { local @changed = (); + local @changed_user = (); local @disappeared = (); local @no_dest = (); # Non-existent destination files local @rules_never_run = (); @@ -3272,9 +3403,8 @@ sub make_preview_continuous { local %rules_applied = (); local $updated = 0; - # What to make? - my @targets = keys %requested_filerules; - + print "======= Need to update make_preview_continuous for target files\n"; + $quell_uptodate_msgs = 1; local $view_file = ''; @@ -3326,7 +3456,9 @@ sub make_preview_continuous { my $timed_out = 0; CHANGE: for (my $first_time = 1; 1; $first_time = 0 ) { - my %rules_to_watch = %requested_filerules; + + my %rules_to_watch = array_to_hash( &rdb_accessible ); + $updated = 0; $failure = 0; $failure_msg = ''; @@ -3340,7 +3472,7 @@ CHANGE: if ($compiling_cmd) { Run_subst( $compiling_cmd ); } - $failure = rdb_make( @targets ); + $failure = &rdb_make; ## warn "=========Viewer PID = $$Pviewer_process; updated=$updated\n"; @@ -3388,10 +3520,9 @@ CHANGE: if ( !$failure_msg ) { $failure_msg = 'Failure to make the files correctly'; } - @pre_primary = (); # Array of rules - @post_primary = (); # Array of rules - @unusual_one_time = (); # Array of rules - &rdb_classify_rules( \%possible_primaries, keys %requested_filerules ); + &rdb_set_rule_net; + %rules_to_watch = array_to_hash( &rdb_accessible ); + # There will be files changed during the run that are irrelevant. # We need to wait for the user to change the files. @@ -3412,10 +3543,10 @@ CHANGE: } } else { - if ( ($#primary_warning_summary > -1) && $warning_cmd ) { + if ( ($#primary_warning_summary > -1) && $warning_cmd ) { Run_subst( $warning_cmd ); } - elsif ( ($#primary_warning_summary > -1) && $warnings_as_errors && $failure_cmd ) { + elsif ( ($#primary_warning_summary > -1) && $warnings_as_errors && $failure_cmd ) { Run_subst( $failure_cmd ); } elsif ($success_cmd) { @@ -3435,21 +3566,24 @@ CHANGE: warn "Cannot open '$deps_file' for output of dependency information\n"; } } - if ( $first_time || $updated || $failure ) { - print "\n=== Watching for updated files. Use ctrl/C to stop ...\n"; - } - $waiting = 1; if ($diagnostics) { warn "WAITING\n"; } -# During waiting for file changes, handle ctrl/C and ctrl/break here, rather than letting -# system handle them by terminating script (and any script that calls it). This allows, -# for example, the clean up code in the following command line to work: -# latexmk -pvc foo; cleanup; + + # Now wait for a file to change... + &rdb_cache_generated; + # During waiting for file changes, handle ctrl/C and ctrl/break here, + # rather than letting system handle them by terminating script (and + # code in the following command line to work: any script that calls + # it). This allows, for example, the command cleanup in the following + # command line to work: + # latexmk -pvc foo; cleanup; &catch_break; $have_break = 0; $last_action_time = time(); + $waiting = 1; + print "\n=== Watching for updated files. Use ctrl/C to stop ...\n"; WAIT: while (1) { sleep( $sleep_time ); if ($have_break) { last WAIT; } - if ( rdb_new_changes(keys %rules_to_watch) ) { + if ( rdb_user_changes(keys %rules_to_watch) ) { if (!$silent) { warn "$My_name: Need to remake files.\n"; &rdb_diagnose_changes( ' ' ); @@ -3467,8 +3601,8 @@ CHANGE: } if ($have_break) { last WAIT; } if ($pvc_timeout && ( time() > $last_action_time+60*$pvc_timeout_mins ) ) { - $timed_out = 1; - last WAIT; + $timed_out = 1; + last WAIT; } } # end WAIT: &default_break; @@ -3579,8 +3713,8 @@ sub cleanup1 { my $root_fixed = fix_pattern( $root_filename ); foreach (@_) { my $name = /%R/ ? $_ : "%R.$_"; - $name =~ s/%R/${root_fixed}/; - $name = $dir.$name; + $name =~ s/%R/${root_fixed}/; + $name = $dir.$name; unlink_or_move( my_glob( "$name" ) ); } } #END cleanup1 @@ -3589,7 +3723,7 @@ sub cleanup1 { sub cleanup_cusdep_generated { # Remove files generated by custom dependencies - rdb_for_all( \&cleanup_one_cusdep_generated ); + rdb_for_actives( \&cleanup_one_cusdep_generated ); } #END cleanup_cusdep_generated #************************************************************ @@ -3603,15 +3737,15 @@ sub cleanup_one_cusdep_generated { # NOT cusdep return; } - if ( (-e $$Pdest) && (-e $$Psource) ) { - unlink_or_move( $$Pdest ); - } - elsif ( (-e $$Pdest) && (!-e $$Psource) ) { + if ( ! -e $$Psource ) { warn "$My_name: For custom dependency '$rule',\n", " I won't delete destination file '$$Pdest'\n", + " and any other generated files,\n", " because the source file '$$Psource' doesn't exist,\n", " so the destination file may not be able to be recreated\n"; + return; } + unlink_or_move( $$Pdest, keys %$PHdest ); } #END cleanup_one_cusdep_generated #************************************************************ @@ -3903,9 +4037,9 @@ sub check_biber_log { # Side effect: add source files @biber_source my $base = $_[0]; my $Pbiber_source = $_[1]; - my $log_name = "$base.blg"; - my $log_file = new FileHandle; - open( $log_file, "<$log_name" ) + my $blg_name = "$base.blg"; + my $blg_file = new FileHandle; + open( $blg_file, "<$blg_name" ) or return 3; my $have_warning = 0; my $have_error = 0; @@ -3920,7 +4054,7 @@ sub check_biber_log { my $control_file_missing = 0; my $control_file_malformed = 0; my %remote = (); # List of extensions of remote files - while (<$log_file>) { + while (<$blg_file>) { if (/> WARN /) { print "Biber warning: $_"; $have_warning = 1; @@ -3939,10 +4073,10 @@ sub check_biber_log { push @$Pbiber_source, $2; } elsif ( /> ERROR - .*\.bcf is malformed/ ) { - # Special treatment: Malformed .bcf file commonly results from error - # in (pdf)latex run. This error must be ignored. - $control_file_malformed = 1; - } + # Special treatment: Malformed .bcf file commonly results from error + # in (pdf)latex run. This error must be ignored. + $control_file_malformed = 1; + } else { $have_error = 1; $error_count ++; @@ -3952,32 +4086,32 @@ sub check_biber_log { } } elsif ( /> INFO - Data source '([^']*)' is a remote BibTeX data source - fetching/ - ){ - my $spec = $1; + ){ + my $spec = $1; my ( $base, $path, $ext ) = fileparseA( $spec ); $remote{$ext} = 1; - } + } elsif ( /> INFO - Found .* '([^']+)'\s*$/ || /> INFO - Found '([^']+)'\s*$/ || /> INFO - Reading '([^']+)'\s*$/ || /> INFO - Processing .* file '([^']+)' .*$/ - ) { - my $file = $1; + ) { + my $file = $1; my ( $base, $path, $ext ) = fileparseA( $file ); - if ($remote{$ext} && ( $base =~ /^biber_remote_data_source/ ) && 1) { - # Ignore the file, which appears to be a temporary local copy - # of a remote file. Treating the file as a source file will - # be misleading, since it will normally have been deleted by - # biber itself. - } + if ($remote{$ext} && ( $base =~ /^biber_remote_data_source/ ) && 1) { + # Ignore the file, which appears to be a temporary local copy + # of a remote file. Treating the file as a source file will + # be misleading, since it will normally have been deleted by + # biber itself. + } elsif ( (defined $Pbiber_source) && (-e $file) ) { - # Note that biber log file gives full path to file. (No search is - # needed to find it.) The file must have existed when biber was - # run. If it doesn't exist now, a few moments later, it must - # have gotten deleted, probably by biber (e.g., because it is a - # copy of a remote file). - # So I have included a condition above that the file must - # exist to be included in the source-file list. + # Note that biber log file gives full path to file. (No search is + # needed to find it.) The file must have existed when biber was + # run. If it doesn't exist now, a few moments later, it must + # have gotten deleted, probably by biber (e.g., because it is a + # copy of a remote file). + # So I have included a condition above that the file must + # exist to be included in the source-file list. push @$Pbiber_source, $file; } } @@ -3988,7 +4122,7 @@ sub check_biber_log { $bibers_error_count = $1; } } - close $log_file; + close $blg_file; if ($control_file_malformed){return 11;} my @not_found = &find_file_list1( $Pbiber_source, $Pbiber_source, @@ -4038,11 +4172,11 @@ sub run_bibtex { local %ENV = %ENV; my ( $base, $path, $ext ) = fileparseA( $$Psource ); if ( $path && $bibtex_fudge ) { - # Since (e.g.,) 'bibtex output/main.aux' doesn't find subsidiary .aux + # Since (e.g.,) 'bibtex output/main.aux' doesn't find subsidiary .aux # files, as from \@include{chap.aux}, we change directory to the - # directory of the top-level .aux file to run bibtex. But we have to - # fix search paths for .bib and .bst, since they may be specified - # relative to the document directory. + # directory of the top-level .aux file to run bibtex. But we have to + # fix search paths for .bib and .bst, since they may be specified + # relative to the document directory. my $cwd = good_cwd(); foreach ( 'BIBINPUTS', 'BSTINPUTS' ) { if ( exists $ENV{$_} ) { @@ -4051,18 +4185,18 @@ sub run_bibtex { else { $ENV{$_} = $cwd.$search_path_separator; } - } + } pushd( $path ); - if (!$silent) { - print "$My_name: changed directory to '$path'\n", - "Set BIBINPUTS='$ENV{BIBINPUTS}'\n", - "Set BSTINPUTS='$ENV{BSTINPUTS}'\n"; - } + if (!$silent) { + print "$My_name: changed directory to '$path'\n", + "Set BIBINPUTS='$ENV{BIBINPUTS}'\n", + "Set BSTINPUTS='$ENV{BSTINPUTS}'\n"; + } $return = &Run_subst( undef, undef, '', $base.$ext, '', $base ); popd(); - if (!$silent) { - print "$My_name: changed directory back to '", cwd(), "'\n"; - } + if (!$silent) { + print "$My_name: changed directory back to '", cwd(), "'\n"; + } } else { $return = Run_subst(); @@ -4083,16 +4217,16 @@ sub check_bibtex_log { # (pdf)latex). my $base = $_[0]; - my $log_name = "$base.blg"; - my $log_file = new FileHandle; - open( $log_file, "<$log_name" ) + my $blg_name = "$base.blg"; + my $blg_file = new FileHandle; + open( $blg_file, "<$blg_name" ) or return 3; my $have_warning = 0; my $have_error = 0; my $missing_citations = 0; my @missing_aux = (); my $error_count = 0; - while (<$log_file>) { + while (<$blg_file>) { if (/^Warning--/) { #print "Bibtex warning: $_"; $have_warning = 1; @@ -4109,7 +4243,7 @@ sub check_bibtex_log { $have_error = 1; } } - close $log_file; + close $blg_file; my $missing = $missing_citations + $#missing_aux + 1; if ( $#missing_aux > -1 ) { @@ -4158,10 +4292,62 @@ sub normalize_force_directory { #************************************************** sub set_names { - # Set names of standard files: - $aux_main = "$aux_dir1$root_filename.aux"; - $log_name = "$aux_dir1$root_filename.log"; - $fdb_name = "$aux_dir1$root_filename.$fdb_ext"; + # Set names of standard files. These are global variables. + + ## Remove extension from filename if was given. + if ( find_basename($filename, $root_filename, $texfile_name) ) { + if ( $force_mode ) { + warn "$My_name: Could not find file '$texfile_name'\n"; + } + else { + &ifcd_popd; + &exit_msg1( "Could not find file '$texfile_name'", + 11); + } + } + $tex_basename = $root_filename; # Base name of TeX file itself + if ($jobname ne '' ) { + $root_filename = $jobname; + $root_filename =~ s/%A/$tex_basename/g; + } + + $aux_main = "%Y%R.aux"; + $log_name = "%Y%R.log"; + $fdb_name = "%Y%R.$fdb_ext"; + # Note: Only MiKTeX allows out_dir ne aux_dir. It puts + # .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"; + $psF_name = "%Z%R.psF"; + $pdf_name = "%Z%R.pdf"; + ## It would be logical for a .xdv file to be put in the out_dir, + ## just like a .dvi file. But the only program, MiKTeX, that + ## currently implements aux_dir, and hence allows aux_dir ne out_dir, + ## puts .xdv file in aux_dir. So we must use %Y not %Z: + $xdv_name = "%Y%R.xdv"; + + foreach ( $aux_main, $log_name, $fdb_name, $fls_name, + $dvi_name, $ps_name, $pdf_name, $xdv_name, $dviF_name, $psF_name ) { + s/%R/$root_filename/g; + s/%Y/$aux_dir1/; + s/%Z/$out_dir1/; + } + + $dvi_final = $dvi_name; + $ps_final = $ps_name; + $pdf_final = $pdf_name; + $xdv_final = $xdv_name; + + if ( length($dvi_filter) > 0) { + $dvi_final = $dviF_name; + } + if ( length($ps_filter) > 0) { + $ps_final = $psF_name; + } } #************************************************** @@ -4268,7 +4454,7 @@ sub parse_log { my $line = 0; my $engine = 'pdfTeX'; # Simple default in case of problems while(<$log_file>) { - $line++; + $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 @@ -4282,23 +4468,23 @@ sub parse_log { # 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 { - # LuaTeX sometimes wraps at 80 instead of 79, so work around this + 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 { + # LuaTeX sometimes wraps at 80 instead of 79, so work around this while ( ( ($len == $log_wrap) || ( ($engine eq 'LuaTeX') && ($len == $log_wrap+1) ) ) && !eof($log_file) ) { push @lines, $_; @@ -4306,7 +4492,7 @@ sub parse_log { $extra =~ s/[\n\r]*$//; $len = length($extra); $_ .= $extra; - } + } } push @lines, $_; } @@ -4388,17 +4574,17 @@ LINE: } elsif ( $state == 1 ) { $state = 2; - if (-e $source_log) { - # then the string preceeding $source_log on the line after the - # ** line is probably the PWD as it appears in filenames in the + if (-e $source_log) { + # then the string preceeding $source_log on the line after the + # ** line is probably the PWD as it appears in filenames in the # log file, except if the file appears in two locations. if ( m{^\("([^"]*)[/\\]\Q$source_log\E"} ) { unshift @pwd_log, $1; - } + } elsif ( m{^\((.*)[/\\]\Q$source_log\E} ) { unshift @pwd_log, $1; } - } + } } if ( $block_type ) { @@ -4444,9 +4630,9 @@ LINE: $bad_citation++; } elsif ( /^Missing character: There is no / - || /^! Package inputenc Error: Unicode character / - || /^! Bad character code / - ) { + || /^! Package inputenc Error: Unicode character / + || /^! Bad character code / + ) { $bad_character++; } elsif ( /^Document Class: / ) { @@ -4561,15 +4747,19 @@ LINE: $dependents{normalize_filename($file, @pwd_log)} = 0; my $file1 = $file; if ( $aux_dir ) { - # Allow for the possibility that latex generated - # a file in $aux_dir, from which the missing file can - # be created by a cusdep (or other) rule that puts - # the result in $out_dir. If the announced missing file - # has no path, then it would be effectively a missing - # file in $aux_dir, with a path. So give this alternate - # location. - my $file1 = normalize_force_directory( $aux_dir1, $file ); - $dependents{$file1} = 0; + # Allow for the possibility that latex generated + # a file in $aux_dir, from which the missing file can + # be created by a cusdep (or other) rule that puts + # the result in $out_dir. If the announced missing file + # has no path, then it would be effectively a missing + # file in $aux_dir, with a path. So give this alternate + # location. + # It is also possible to have a file that is in a directory + # relative to the aux_dir, so allow for that as well + my $file1 = normalize_force_directory( $aux_dir1, $file ); + $dependents{$file1} = 0; + $dependents{$aux_dir1.$file} = 0; + } next LINE; } @@ -4577,11 +4767,11 @@ LINE: if ( (! $fls_file_analyzed) && /^File: (.+) Graphic file \(type / ) { # First line of message from includegraphics/x - # But this does NOT include full path information - # (if exact match is not found and a non-trivial - # kpsearch was done by (pdf)latex). - # But the source-file information is in the fls file, - # if we are using it. + # But this does NOT include full path information + # (if exact match is not found and a non-trivial + # kpsearch was done by (pdf)latex). + # But the source-file information is in the fls file, + # if we are using it. $dependents{normalize_clean_filename($1, @pwd_log)} = 1; next LINE; } @@ -4617,18 +4807,18 @@ LINE: } } - if ( ($fls_file_analyzed) && (! $analyze_input_log_always) ) { - # Skip the last part, which is all about finding input - # file names which should all appear more reliably in the - # fls file. - next LINE; - } - + if ( ($fls_file_analyzed) && (! $analyze_input_log_always) ) { + # Skip the last part, which is all about finding input + # file names which should all appear more reliably in the + # fls file. + next LINE; + } + my @new_includes = (); - + GRAPHICS_INCLUDE_CANDIDATE: while ( /<([^>]+)(>|$)/g ) { - if ( -f $1 ) { push @new_includes, $1; } + if ( -f $1 ) { push @new_includes, $1; } } # GRAPHICS_INCLUDE_CANDIDATE: INCLUDE_CANDIDATE: @@ -4805,7 +4995,7 @@ CANDIDATE: # so use kpsewhich. # If the file still is not found, assume non-existent; $kpsearch_candidates{$candidate} = 1; - delete $dependents{$candidate}; + delete $dependents{$candidate}; } elsif ($code == 2) { # Candidate is from '(...' construct in log file, for input file @@ -4850,9 +5040,9 @@ CANDIDATE: my @kpsearch_candidates = keys %kpsearch_candidates; if (@kpsearch_candidates) { - foreach my $result ( kpsewhich( @kpsearch_candidates ) ) { - $dependents{$result} = 4; - } + foreach my $result ( kpsewhich( @kpsearch_candidates ) ) { + $dependents{$result} = 4; + } } CANDIDATE_PAIR: @@ -4893,7 +5083,7 @@ CANDIDATE_PAIR: } if ( ($#warning_list >= 0) && !$log_silent ) { - @warning_list = uniqs( @warning_list ); + @warning_list = uniqs( @warning_list ); show_array( "$My_name: List of undefined refs and citations:", @warning_list ); } @@ -4961,46 +5151,46 @@ sub find_set_log { # Use of $aux_dir different to $out_dir, when (*)latex doesn't support # the -aux-directory option (notably with TeXLive distribution). if ($where_log >= 0) { - # .log file was found on previous run. 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; + # .log file was found on previous run. 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; } if ( test_gen_file( "$aux_dir1$root_filename.log" ) ) { - # .log file is in expected place. - $where_log = 1; + # .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. - # So change $aux_dir to the actually used value. - $where_log = 2; - $aux_dir = $out_dir; + # .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. + # So change $aux_dir to the actually used value. + $where_log = 2; + $aux_dir = $out_dir; } 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 = ""; + # .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 = ""; } else { - # No .log file found - $failure = 1; - $$Plast_result = 2; - $where_log = 0; - $failure_msg - = "(Pdf)LaTeX didn't generate the expected log file '$log_name'\n"; + # No .log file found + $failure = 1; + $$Plast_result = 2; + $where_log = 0; + $failure_msg + = "(Pdf)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: - &set_dirs_etc; - &set_names; - warn "$My_name: Actual .log file is\n", + 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: + &set_dirs_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", @@ -5042,10 +5232,10 @@ sub parse_fls { if (/^\s*PWD\s+(.*)$/) { $cwd = $1; $$Ppwd_latex = $cwd; - if ( $cwd =~ /\"/ ) { - warn "$My_name: The working directory has a '\"' character in its name:\n", + if ( $cwd =~ /\"/ ) { + warn "$My_name: The working directory has a '\"' character in its name:\n", " '$cwd'\n This can cause me trouble. Beware!\n"; - } + } } elsif (/^\s*INPUT\s+(.*)$/) { # Take precautions against aliasing of foo, ./foo and other possibilities for cwd. @@ -5055,9 +5245,9 @@ sub parse_fls { # 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 ) { + if ( defined $$Ppwd_latex ) { $file =~ s(^\Q$$Ppwd_latex\E[\\/])(); - } + } $file = normalize_filename( $file ); if ( (exists $$Poutputs{$file}) && (! exists $$Pinputs{$file}) ) { $$Pfirst_read_after_write{$file} = 1; @@ -5184,13 +5374,13 @@ sub parse_aux { @$Pbst_files = uniqs( @$Pbst_files ); my @bad_bib = (); foreach ( @$Pbib_files ) { - if ( /\s/ ) { push @bad_bib, $_; } + if ( /\s/ ) { push @bad_bib, $_; } } if ($#bad_bib >= 0) { - warn "$My_name: White space in an argument list for \\bibliography.\n", + warn "$My_name: White space in an argument list for \\bibliography.\n", " which is not allowed by bibtex. Bad arguments:\n"; foreach (@bad_bib ) { warn " '$_'\n"; } - return 3; + return 3; } if ( $#not_found < 0) { warn "$My_name: Found bibliography file(s) [@$Pbib_files]\n" @@ -5271,7 +5461,7 @@ sub fdb_get { # that may have changed the file or the last time the file was checked # for changes --- see below. # For non-existent file, deletes its entry in fdb_current, - # and returns (0,-1,0) + # and returns (0,-1,0) (whatever is in @nofile). # As an optimization, the md5 value is taken from the cache in # fdb_current, if the time and size stamp indicate that the # file has not changed. @@ -5293,9 +5483,6 @@ sub fdb_get { my ($file, $check_time) = @_; if ( ! defined $check_time ) { $check_time = 0;} my ($new_time, $new_size) = get_time_size($file); - my @nofile = (0,-1,0); # What we use for initializing - # a new entry in fdb or flagging - # non-existent file if ( $new_size < 0 ) { delete $fdb_current{$file}; return @nofile; @@ -5328,7 +5515,6 @@ sub fdb_get { $recalculate_md5 = 1; } if ($recalculate_md5) { -#warn "--------- RECALC MD5: $rule $file: (N,O,R,C) \n = $new_time, $time, $$Prun_time, $check_time\n"; @$file_data = ( $new_time, $new_size, get_checksum_md5( $file ) ); } return @$file_data;; @@ -5341,7 +5527,7 @@ sub fdb_set { # Set data in file data cache, i.e., %fdb_current my ($file, $time, $size, $md5 ) = @_; if ( ! exists $fdb_current{$file} ) { - $fdb_current{$file} = [0, -1, 0]; + $fdb_current{$file} = [@nofile]; } @{$fdb_current{$file}} = ( $time, $size, $md5 ); } #END fdb_set @@ -5368,20 +5554,44 @@ sub rdb_read { # Sets rule database from saved file, in format written by rdb_write. # Returns -1 if file could not be read else number of errors. # Thus return value on success is 0 - my $in_name = $_[0]; + # Requires: Rule database initialized with standard rules, with + # conditions corresponding to requests determined by + # initialization and command line options. + # Asssumption: Normally the fdb_latexmk file contains state of + # rules and files corresponding to end of last + # compilation, and the rules in the file were + # active on that run. + # Complications arise when that state does not correspond to current + # rule set: + # (a) Configuration etc may have changed: e.g., different out_dir, + # different target rules and files, including different tex engine. + # (b) Output extension of primary rule may be different from current + # initialized one, because of document properties (use of + # \pdfoutput etc). + # (c) The same may arise because of misconfigured rules, a situation + # that may or may not have changed in current run. + # (d) The primary engine requested may not be the one used in + # the previous run, possibly because (i) request has + # changed, or (ii) document metacommand was obeyed to change + # engine. (The last is not currently implemented, but + # 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 (); + or return (); my $errors = 0; my $state = -1; # Values: -1: before start; 0: outside rule; # 1: in source section; # 2: in generated file section; # 10: ignored rule. my $rule = ''; - my $run_time = 0; - my $source = ''; - my $dest = ''; + local $run_time = 0; + local $source = ''; + local $dest = ''; my $base = ''; + my %old_actives = (); # Hash: keys are rules in fdb_latexmk file local %new_sources = (); # Hash: rule => { file=>[ time, size, md5, fromrule ] } my $new_source = undef; # Reference to hash of sources for current rule LINE: @@ -5409,6 +5619,7 @@ LINE: # emacs from misparsing an isolated single quote $run_time = $check_time = 0; $source = $dest = $base = ''; + $old_actives{$rule} = 1; if ( $tail =~ /^\s*(\S+)\s*$/ ) { $run_time = $1; } @@ -5426,13 +5637,7 @@ LINE: $check_time = $5; } if ( rdb_rule_exists( $rule ) ) { - rdb_one_rule( $rule, - sub{ - if ($$Ptest_kind == 3) { $$Ptest_kind = 1; } - $$Prun_time = $run_time; - $$Pcheck_time = $check_time; - } - ); + rdb_one_rule( $rule, \&rdb_read_set_rule ); } elsif ($rule =~ /^cusdep\s+(\S+)\s+(\S+)\s+(.+)$/ ) { # Create custom dependency @@ -5445,24 +5650,24 @@ LINE: foreach my $dep ( @cus_dep_list ) { my ($tryfromext,$trytoext,$must,$try_func_name) = split('\s+',$dep); if ( ($tryfromext eq $fromext) && ($trytoext eq $toext) ) { - $func_name = $try_func_name; + $func_name = $try_func_name; } } - if ($func_name) { - my $PAnew_cmd = ['do_cusdep', $func_name]; + if ($func_name) { + my $PAnew_cmd = ['do_cusdep', $func_name]; # Set source file as non-existent. # If it existed on last run, it will be in later # lines of the fdb file rdb_create_rule( $rule, 'cusdep', '', $PAnew_cmd, 1, $source, $dest, $base, 0, $run_time, $check_time, 1 ); - } - else { - warn "$My_name: In file-database '$in_name', the custom-dependency rule\n", - " '$rule' is not available in this session.\n", - " Presumably it's no longer in your configuration for latexmk.\n"; - $state = 10; - next LINE; - } + } + else { + warn "$My_name: In file-database '$in_name', the custom-dependency rule\n", + " '$rule' is not available in this session.\n", + " Presumably it's no longer in your configuration for latexmk.\n"; + $state = 10; + next LINE; + } } elsif ( $rule =~ /^(makeindex|bibtex|biber)\s*(.*)$/ ) { my $PA_extra_gen = []; @@ -5505,9 +5710,10 @@ LINE: $source, $dest, $base, 0, $run_time, $check_time, 1, $PA_extra_gen ); } else { - warn "$My_name: In file-database '$in_name' rule '$rule'\n", - " is not in use in this session\n" - if $diagnostics; + if ($diagnostics) { + warn "$My_name: In file-database '$in_name' rule '$rule'\n", + " is not in use in this session\n"; + } $new_source = undef; $state = 10; next LINE; @@ -5541,7 +5747,7 @@ LINE: rdb_ensure_file( $rule, $file, undef, 1 ); rdb_set_file1( $rule, $file, $time, $size, $md5 ); fdb_set( $file, $time, $size, $md5 ); - # Save the rest of the data, especially the from_fule until we know all + # Save the rest of the data, especially the from_rule until we know all # the rules, otherwise the from_rule may not exist. # Also we'll have a better chance of looping through files. ${$new_source}{$file} = [ $time, $size, $md5, $from_rule ]; @@ -5560,21 +5766,75 @@ LINE: undef $in_handle; # Set cus dependencies. &rdb_set_dependents( keys %rule_db ); - -#?? Check from_rules exist. + &rdb_set_rule_net; return $errors; } # END rdb_read #************************************************************ +sub rdb_read_set_rule { + # Rule context assumed. Implicit passing of $dest, $run_time, $check_time, + # $in_name used as local variables in calling routine rdb_read; + if ($$Ptest_kind == 3) { $$Ptest_kind = 1; } + $$Prun_time = $run_time; + $$Pcheck_time = $check_time; + # Deal with possibility that destination in fdb_latexmk has different name + # than the default one. The only case that concerns us is where + # the extension is changed (by \pdfoutput, e.g., in tex file). But + # it is possible out and aux directories have been chosen differently, + # and the user choice there MUST OVERRIDE the value in the fdb_latexmk file. + if ($dest ne $$Pdest) { + if (! $possible_primaries{$rule} ) { + warn "$My_name: In reading rule '$rule' in '$in_name',\n", + " name of destination file is not current one; I'll flag rule as out of date.\n"; + $$Pout_of_date = 10; + } + elsif ( ! rdb_is_active($rule) ) { + warn "$My_name: In reading rule '$rule' in '$in_name',\n", + " rule is not currently active.\n"; + # No fixup now. Causes to be analyzed: + # Change of requested files: no action needed. + # Obeying of metacommand: not implemented yet. + } + else { + # Get here if rule is active and primary and destination is different + warn "$My_name: In reading rule '$rule' in '$in_name',\n", + " destination has different name than configured...\n"; + my ($oldbase, $oldpath, $oldext) = fileparseA( $dest ); + my ($newbase, $newpath, $newext) = fileparseA( $$Pdest ); + if ($oldext ne $newext) { + if ( ! exists $allowed_output_ext{$oldext} ) { + warn " Old extension '$oldext' not allowed.\n"; + $$Pout_of_date = 10; + } + else { + warn " ===== CHANGING output type from '$newext' to '$oldext' in '$rule'\n"; + my $switch_error = switch_output( $oldext, $newext ); + if ($switch_error) { + warn " I could not accommodate the changed output extension\n", + " (either because the configuration does not allow it\n", + " or because there is a conflict with requested filetypes).\n", + "===> There may be subsequent warnings, which may or may not be ignorable.\n", + "===> If necessary, clean out generated files and try again\n"; + } + } + } + if ( ($oldbase ne $newbase) || ($oldpath ne $newpath) ) { + # There are further issues (e.g., change of out_dir). + # Need rerun to correct: + $$Pout_of_date = 10; + } + } + } +} #END rdb_read_set_rule + +#************************************************************ + sub rdb_write { # Call: rdb_write( $out_name ) # Writes to the given file name the database of file and rule data # for all rules needed to make final output - # !!?? Previously was: - # OLD Writes to the given file name the database of file and rule data - # OLD accessible from the primary rules. # Returns 1 on success, 0 if file couldn't be opened. local $out_name = $_[0]; local $out_handle = new FileHandle; @@ -5587,20 +5847,10 @@ sub rdb_write { } if (!$out_handle) { return 0; } - local %current_primaries = (); # Hash whose keys are primary rules - # needed, i.e., known latex-like rules which trigger - # circular dependencies - local @pre_primary = (); # Array of rules - local @post_primary = (); # Array of rules - local @unusual_one_time = (); # Array of rules - &rdb_classify_rules( \%possible_primaries, keys %requested_filerules ); + &rdb_set_rule_net; print $out_handle "# Fdb version $fdb_ver\n"; -# !!?? Rules or rules accessible from primary -# my @rules = rdb_accessible( uniq1( keys %possible_primaries ) ) ; - my @rules = rdb_accessible( uniq1( keys %possible_primaries, keys %requested_filerules ) ) ; - # Separate call to sort. Otherwise rdb_accessible seems to get wrong argument. - @rules = sort( @rules ); + my @rules = sort &rdb_accessible; rdb_for_some( \@rules, sub { @@ -5727,6 +5977,11 @@ sub rdb_set_latex_deps { # # I have not tried to handle the (currently rare) cases that the # OS is neither UNIX-like nor MSWin-like. + # + # Assumption: the list of generated files in %PHdest was already initialized earlier. + # In principle, I should do it here, but useful possibilities (e.g., + # see pythontex-latexmk) for subroutine called to process a .tex to add items to + # %PHdest. So initializing here is too late. # Rules should only be primary if ( $$Pcmd_type ne 'primary' ) { @@ -5739,7 +5994,7 @@ sub rdb_set_latex_deps { #?? # We'll prune this by all files determined to be needed for source files. #?? my %unneeded_source = %$PHsource; - # Parse log file to find relevant filenames + # Parse fls and log files to find relevant filenames # Result in the following variables: local %dependents = (); # Maps files to status local @bbl_files = (); @@ -5758,7 +6013,15 @@ sub rdb_set_latex_deps { local $pwd_latex = undef; # Cwd as reported in fls file by (pdf)latex - # The following are also returned, but are global, to be used by caller + local %created_rules = (); # Maps files to rules existing or created to + # make them. Use to avoid misunderstood + # dependencies when a package creates a + # 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 # Do I have my own eps-to-pdf conversion? @@ -5770,14 +6033,13 @@ sub rdb_set_latex_deps { # Analyze fls file first. It tells us the working directory as seen by (pdf)latex # But we'll use the results later, so that they take priority over the findings # from the log file. - my $fls_name = "$aux_dir1$root_filename.fls"; local $fls_file_analyzed = 0; if ($recorder && test_gen_file($fls_name) ) { - $fls_file_analyzed = - (0== parse_fls( $fls_name, \%source_fls, \%generated_fls, \%first_read_after_write, \$pwd_latex )); - if (! $fls_file_analyzed ) { - warn "$My_name: fls file '$fls_name' appears to have been made but it couldn't be opened.\n"; - } + $fls_file_analyzed = + (0== parse_fls( $fls_name, \%source_fls, \%generated_fls, \%first_read_after_write, \$pwd_latex )); + if (! $fls_file_analyzed ) { + warn "$My_name: fls file '$fls_name' appears to have been made but it couldn't be opened.\n"; + } } &parse_log; @@ -5822,24 +6084,24 @@ sub rdb_set_latex_deps { # used. foreach (keys %source_fls) { if (! -e ) { - # File is listed in .fls file as read, but doesn't exist now. - # Therefore it is not a true source file, surely. - # Sometimes this is caused by a bug (e.g., lualatex in TeXLive 2016, - # 2017) when there is an incorrect line in .fls file. (This - # would deserve a warning.) + # File is listed in .fls file as read, but doesn't exist now. + # Therefore it is not a true source file, surely. + # Sometimes this is caused by a bug (e.g., lualatex in TeXLive 2016, + # 2017) when there is an incorrect line in .fls file. (This + # would deserve a warning.) # But sometimes (e.g., with minted package), the file could be - # created during a run, read, and then deleted. + # created during a run, read, and then deleted. next; } $dependents{$_} = 4; - if ( /\.bbl$/ ) { push @bbl_files, $_; } + if ( /\.bbl$/ ) { push @bbl_files, $_; } } foreach (keys %generated_fls) { if (! -e ) { - # File is listed in .fls file as written, but doesn't exist now. - # Therefore it is not a true externally visible generated file. - # (Typically, e.g., with the minted package, it is a temporary - # file created during a run and then deleted during the run.) + # File is listed in .fls file as written, but doesn't exist now. + # Therefore it is not a true externally visible generated file. + # (Typically, e.g., with the minted package, it is a temporary + # file created during a run and then deleted during the run.) next; } rdb_add_generated( $_ ); @@ -5848,7 +6110,6 @@ sub rdb_set_latex_deps { } } - for my $conv (sort keys %conversions) { my $conv_source = $conversions{$conv}; if ( $conv =~ /^(.*)-eps-converted-to\.pdf$/ ) { @@ -5861,10 +6122,10 @@ sub rdb_set_latex_deps { rdb_remove_files( $rule, $conv ); delete $dependents{$conv}; if ($epspdf_cusdep) { - $dependents{"$base.pdf"} = ((-e "$base.pdf") ? 4 : 0 ); + $dependents{"$base.pdf"} = ((-e "$base.pdf") ? 4 : 0 ); } - } - } + } + } } @@ -5892,27 +6153,28 @@ sub rdb_set_latex_deps { 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 ) { warn "$My_name: ===For rule '$rule', the extensions differ between the\n", " actual output file '$primary_out',\n", " and the expected output '$$Pdest'.\n"; - if ( ! exists $allowed_output_ext{$actual_ext} ) { - warn " Actual output file has an extension '$actual_ext' that\n", - " is not one I know about\n"; - } - if ( (($actual_ext eq '.pdf') && ($intended_ext eq '.dvi')) - || (($actual_ext eq '.dvi') && ($intended_ext eq '.pdf')) - ) - { - warn " This could arise from use of \\pdfoutput in the source file,\n", - " or from a configuration error\n"; - } - else { - warn " This indicates a probable configuration error\n"; - } - warn " A future version of $my_name should be able to make dynamically\n", - " adjustments to deal with this problem\n"; - } + if ( ! exists $allowed_output_ext{$actual_ext} ) { + warn " Actual output file has an extension '$actual_ext' that\n", + " is not one I know about. I cannot handle this\n"; + } + else { + my $switch_error = switch_output( $actual_ext, $intended_ext ); + if ( $switch_error ) { + warn " I could not accommodate the changed output extension\n", + " (either because the configuration does not allow it\n", + " or because there is a conflict with requested filetypes).\n"; + $failure = 1; + $failure_msg = 'Could not handle change of output extension'; + } + else { + warn " Rule structure will be changed suitably.\n"; + } + } + } } IDX_FILE: @@ -5939,6 +6201,7 @@ sub rdb_set_latex_deps { # Leave failure issue to other rules. $failure = 0; } + $created_rules{$ind_file} = $from_rule; } local %processed_aux_files = (); @@ -5956,6 +6219,11 @@ sub rdb_set_latex_deps { } my $from_rule = "$bib_program $bbl_base"; print "======= Dealing with '$from_rule'\n" if ($diagnostics); + # Don't change to use activation and deactivation here, rather than + # creation and removal of rules. This is because rules are to be + # created on the fly here with details corresponding to current. So + # activating a previously inactive rule, which is out-of-date, may + # cause trouble. if ($bib_program eq 'biber') { check_biber_log( $bbl_base, \@biber_source ); # Remove OPPOSITE kind of bbl generation: @@ -5971,17 +6239,18 @@ sub rdb_set_latex_deps { if ( $bib_program eq 'biber' ) { rdb_create_rule( $from_rule, 'external', $biber, '', 1, "$bbl_base.bcf", $bbl_file, $bbl_base, 1, 0, 0, 1, [ "$bbl_base.blg" ] ); - } - else { - rdb_create_rule( $from_rule, 'external', $bibtex, 'run_bibtex', 1, + } + else { + rdb_create_rule( $from_rule, 'external', $bibtex, 'run_bibtex', 1, "$bbl_base.aux", $bbl_file, $bbl_base, 1, 0, 0, 1, [ "$bbl_base.blg" ] ); - } + } } + $created_rules{$bbl_file} = $from_rule; local %old_sources = (); rdb_one_rule( $from_rule, sub { %old_sources = %$PHsource; } ); - my @new_sources = ( @new_bib_files, @new_aux_files, @new_bst_files ); + my @new_sources = ( @new_bib_files, @new_aux_files, @new_bst_files ); if ( $bib_program eq 'biber' ) { - push @new_sources, @biber_source; + push @new_sources, @biber_source; } foreach my $source ( @new_sources ) { print " ===Source file '$source' for '$from_rule'\n" @@ -6022,19 +6291,19 @@ NEW_SOURCE: foreach my $new_source (keys %dependents) { print " ===Source file for rule '$rule': '$new_source'\n" 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"; - $dependents{$new_source} = 7; - } - else { - #warn "--- READ ONLY AFTER CREATE OF '$new_source'\n"; - $dependents{$new_source} = 6; - } + if ( exists $first_read_after_write{$new_source} ) { + if ( dep_at_start($new_source) ) { + #warn "--- READ ONLY AFTER WRITE OF '$new_source'\n"; + $dependents{$new_source} = 7; + } + else { + #warn "--- READ ONLY AFTER CREATE OF '$new_source'\n"; + $dependents{$new_source} = 6; + } } if ( ($dependents{$new_source} == 5) || ($dependents{$new_source} == 6) - ) { + ) { # (a) File was detected in "No file..." line in log file. # Typically file was searched for early in run of # latex/pdflatex, was not found, and then was written @@ -6069,11 +6338,20 @@ NEW_SOURCE: } if ( ($dependents{$new_source} == 6) || ($dependents{$new_source} == 7) - ) { + ) { rdb_add_generated($new_source); } } + # 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 + # show the bbl file as created by the primary run and hence as a + # generated file. Since we now have a rule to create a real bbl file, + # the information in the fls and log files no longer represents a + # correct dependency, so the bbl file is to be removed from the + # generated files. + foreach (keys %created_rules) { rdb_remove_generated( $_ ); } + my @more_sources = &rdb_set_dependents( $rule ); my $num_new = $#more_sources + 1; foreach (@more_sources) { @@ -6115,6 +6393,56 @@ NEW_SOURCE: #************************************************************ +sub switch_output { + # Assume rule context for primary rule + # Return 0 on success, non-zero error code on failure + + my ( $actual_ext, $intended_ext ) = @_; + if ( $actual_ext eq $intended_ext) { return 0; } + if ( ! $can_switch ) { return 1; } + + if ( $intended_ext eq '.dvi' ) { + rdb_deactivate_derequest( 'dvipdf', 'pspdf' ); + } + elsif ( $intended_ext eq '.xdv' ) { + rdb_deactivate_derequest( 'xdvipdfmx' ); + } + else { } + + if ( $actual_ext eq '.dvi' ) { + rdb_activate_request( 'dvipdf' ); + $input_extensions{$rule} = $standard_input_extensions{latex}; + } + elsif ( $actual_ext eq '.xdv' ) { + rdb_activate_request( 'xdvipdfmx' ); + $input_extensions{$rule} = $standard_input_extensions{xelatex}; + } + else { + $input_extensions{$rule} = $standard_input_extensions{pdflatex}; + } + + my $old_dest = $$Pdest; + my $new_dest = $$Pdest; + $new_dest =~ s/$intended_ext$/$actual_ext/; + # Compensate for MiKTeX's behavior: dvi and pdf are put in out_dir, but xdv is put in aux_dir: + 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 ); + + # Some fixes to avoid spurious error conditions: + $switched_primary_output = 1; + if (-e $$Pdest) { + $missing_dvi_pdf = ''; + if ($$Plast_result == 1 ) { $$Plast_result = 0; } + } + else { $missing_dvi_pdf = $$Pdest; } + + return 0; +} #END switch_output + +#************************************************************ + sub test_gen_file { # Usage: test_gen_file( filename ) # Tests whether the file was generated during a run of (pdf)latex. @@ -6223,7 +6551,7 @@ MISSING_FILE: my $found = 0; foreach my $file (keys %new_includes) { -# if ( $file =~ /\"/ ) {next; } +# if ( $file =~ /\"/ ) {next; } my $stripped = $file; $stripped =~ s{^\./}{}; if ( exists $PHsource{$file} ) { @@ -6273,13 +6601,13 @@ sub rdb_find_source_file { return $_[0]; } if ( exists $ENV{TEXINPUTS} ) { - foreach my $searchpath (split $search_path_separator, $ENV{TEXINPUTS}) { - my $file = File::Spec->catfile($searchpath,$_[0]); - my $test = "$file.$_[1]"; - if ( -e $test ) { - return $file; - } - } + foreach my $searchpath (split $search_path_separator, $ENV{TEXINPUTS}) { + my $file = File::Spec->catfile($searchpath,$_[0]); + my $test = "$file.$_[1]"; + if ( -e $test ) { + return $file; + } + } } return "$_[0]"; } @@ -6313,11 +6641,11 @@ DEP: } if ( -e $source ) { $$Pfrom_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 ); - $new_dest = $new_new_dest; - } + my $new_new_dest = "$base_name.$toext"; + if ($new_new_dest ne $new_dest) { + rdb_ensure_file( $rule, $new_new_dest ); + $new_dest = $new_new_dest; + } local @PAnew_cmd = ( 'do_cusdep', $func_name ); if ( !-e $new_dest ) { push @new_sources, $new_dest; @@ -6421,7 +6749,7 @@ sub rdb_list { # List rules and their source files print "===Rules:\n"; local $count_rules = 0; - my @accessible_all = rdb_accessible( keys %requested_filerules ); + my @accessible_all = &rdb_accessible; rdb_for_some( \@accessible_all, sub{ $count_rules++; @@ -6431,7 +6759,7 @@ sub rdb_list { sub{ print " and generates:\n"; foreach (keys %$PHdest) { print " '$_'\n"; } # print " default_extra_generated:\n"; -# foreach (@$PA_extra_generated) { print " '$_'\n"; } +# foreach (@$PA_extra_gen) { print " '$_'\n"; } }, ); if ($count_rules <= 0) { @@ -6452,13 +6780,10 @@ sub deps_list { if ($postscript_mode) {push @dest_exts, '.ps';} my %source = ( $texfile_name => 1 ); my @generated = (); - my @accessible_all = rdb_accessible( keys %requested_filerules ); + my @accessible_all = &rdb_accessible; rdb_for_some( \@accessible_all, - sub{ -# foreach (keys %$PHdest) { print "----- $_\n"; } - push @generated, keys %$PHdest; - }, + sub{ push @generated, keys %$PHdest; }, sub{ $source{$file} = 1; } ); foreach (keys %generated_exts_all) { @@ -6507,7 +6832,7 @@ sub rdb_show { # Side effect: Exercises access routines! print "===Rules:\n"; local $count_rules = 0; - rdb_for_all( + rdb_for_actives( sub{ $count_rules++; my @int_cmd = @$PAint_cmd; foreach (@int_cmd) { @@ -6524,12 +6849,31 @@ sub rdb_show { #************************************************************ +sub rdb_target_array { + # Returns array of all rules implicated by %target_rules and %target_files + my %rules = &rdb_target_hash; + return keys %rules; +} # End rdb_target_array + +#************************************************************ + +sub rdb_target_hash { + # Returns hash mapping to 1 all rules implicated by %target_rules and %target_files + my %rules = %target_rules; + foreach (keys %target_files) { + if (exists $from_rules{$_}) { $rules{$from_rules{$_}} = 1; } + } + return %rules; +} # End rdb_target_hash + +#************************************************************ + sub rdb_accessible { - # Call: rdb_accessible( rule, ...) - # Returns array of rules accessible from the given rules - local @accessible = (); - rdb_recurse( [@_], sub{ push @accessible, $rule; } ); - return @accessible; + # Call: &rdb_accessible + # Returns array of rules accessible from target rules and rules to make target files + local %accessible_rules = &rdb_target_hash; + rdb_recurse( [keys %accessible_rules], sub{ $accessible_rules{$rule} = 1; } ); + return keys %accessible_rules; } #END rdb_accessible #************************************************************ @@ -6537,7 +6881,7 @@ sub rdb_accessible { #************************************************************ sub rdb_make { - # Call: rdb_make( target, ... ) + # Call: &rdb_make # Makes the targets and prerequisites. # Leaves one-time rules to last. # Does appropriate repeated makes to resolve dependency loops @@ -6675,23 +7019,8 @@ sub rdb_make { # source files. # - local @requested_targets = @_; - local %current_primaries = (); # Hash whose keys are primary rules - # needed, i.e., known latex-like rules which trigger - # circular dependencies - local @pre_primary = (); # Array of rules - local @post_primary = (); # Array of rules - local @unusual_one_time = (); # Array of rules - - - # For diagnostics on changed files, etc: - local @changed = (); - local @disappeared = (); - local @no_dest = (); # Non-existent destination files - local @rules_never_run = (); - local @rules_to_apply = (); - &rdb_classify_rules( \%possible_primaries, @requested_targets ); + &rdb_set_rule_net; local %pass = (); local $failure = 0; # General accumulated error flag @@ -6699,87 +7028,92 @@ sub rdb_make { local $runs = 0; local $too_many_passes = 0; local %rules_applied = (); + local $switched_primary_output = 0; my $retry_msg = 0; # Did I earlier say I was going to attempt # another pass after a failure? - PRIMARY: - foreach my $primary (keys %current_primaries ) { - foreach my $rule (keys %rule_db) { - $pass{$rule} = 0; - } - PASS: - while (1==1) { - # Exit condition at end of body of loop. - $runs = 0; - my $previous_failure = $failure; - $failure = 0; - local $newrule_nofile = 0; # Flags whether rule created for + foreach my $rule (keys %rule_db) { + $pass{$rule} = 0; + } + PASS: + while (1==1) { + # Exit condition at end of body of loop. + $runs = 0; + $switched_primary_output = 0; + my $previous_failure = $failure; + $failure = 0; + local $newrule_nofile = 0; # Flags whether rule created for # making currently non-existent file, which # could become a needed source file for a run # and therefore undo an error condition - 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. - rdb_for_some( [@pre_primary, $primary], \&rdb_make1 ); - if ( ($runs > 0) && ! $too_many_passes ) { - $retry_msg = 0; - if ( $force_mode || (! $failure) ) { - next PASS; - } - # Get here on failure, without being in force_mode - if ( $newrule_nofile ) { - $retry_msg = 1; - print "$My_name: Error on run, but found possibility to ", - "make new source files\n"; - next PASS; - } - else { last PASS; } - } - if ($runs == 0) { - # $failure not set on this pass, so use value from previous pass: - $failure = $previous_failure; - if ($retry_msg) { - print "But in fact no new files made\n"; - } - if ($failure && !$force_mode ) { last PASS; } - } - if ( $missing_dvi_pdf ) { - # No output from primary, after completing circular dependence - warn "Failure to make '$missing_dvi_pdf'\n"; - $failure = 1; - last PASS; - } - if ($diagnostics) { - print "Make: doing post_primary...\n"; + foreach my $rule (keys %rule_db) { + # Update %pass in case new rules have been created + if (! exists $pass{$rule} ) { $pass{$rule} = 0; } + } + 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. + rdb_for_some( [@pre_primary, $current_primary], \&rdb_make1 ); + if ($switched_primary_output) { + print "=========SWITCH OF OUTPUT WAS DONE.\n"; + next PASS; + } + if ( ($runs > 0) && ! $too_many_passes ) { + $retry_msg = 0; + if ( $force_mode || (! $failure) || $switched_primary_output ) { + next PASS; } - rdb_for_some( [@post_primary], \&rdb_make1 ); - if ( ($runs == 0) || $too_many_passes ) { - # If $too_many_passes is set, it should also be that - # $runs == 0; but for safety, I also checked - # $too_many_passes. - last PASS; + # Get here on failure, without being in force_mode + if ( $newrule_nofile ) { + $retry_msg = 1; + print "$My_name: Error on run, but found possibility to ", + "make new source files\n"; + next PASS; } + else { last PASS; } } - continue { - # Re-evaluate rule classification and accessibility, - # but do not change primaries. - # Problem is that %current_primaries gets altered - my %old_curr_prim = %current_primaries; - &rdb_classify_rules( \%possible_primaries, @requested_targets ); - %current_primaries = %old_curr_prim; - &rdb_make_links; + if ($runs == 0) { + # $failure not set on this pass, so use value from previous pass: + $failure = $previous_failure; + if ($retry_msg) { + print "But in fact no new files made\n"; + } + if ($failure && !$force_mode ) { last PASS; } + } + if ( $missing_dvi_pdf ) { + # No output from primary, after completing circular dependence + warn "Failure to make '$missing_dvi_pdf'\n"; + $failure = 1; + last PASS; + } + if ($diagnostics) { + print "Make: doing post_primary...\n"; } - } + rdb_for_some( [@post_primary], \&rdb_make1 ); + if ( ($runs == 0) || $too_many_passes ) { + # If $too_many_passes is set, it should also be that + # $runs == 0; but for safety, I also checked + # $too_many_passes. + last PASS; + } + } + continue { + # Re-evaluate rule classification and accessibility, + # but do not change primaries. + # Problem is that %current_primaries gets altered + &rdb_set_rule_net; + } #End PASS + rdb_for_some( [@unusual_one_time], \&rdb_make1 ); rdb_write( $fdb_name ); if ($#primary_warning_summary > -1) { - # N.B. $mult_defined, $bad_reference, $bad_character, $bad_citation also available here. + # N.B. $mult_defined, $bad_reference, $bad_character, $bad_citation also available here. show_array( "$My_name: Summary of warnings from last run of (pdf)latex:", @primary_warning_summary ); } @@ -6804,7 +7138,7 @@ sub rdb_make { sub rdb_show_rule_errors { local @errors = (); local @warnings = (); - rdb_for_all( + rdb_for_actives( sub{ if ($$Plast_message ne '') { if ($$Plast_result == 200) { @@ -6852,7 +7186,6 @@ sub rdb_make1 { if ($diagnostics) { print " Make1 $rule\n"; } if ($failure & ! $force_mode) {return;} if ( ! defined $pass{$rule} ) {$pass{$rule} = 0; } - &rdb_clear_change_record; # Special fix up for bibtex: my $bibtex_not_run = -1; # Flags status as to whether this is a @@ -6904,8 +7237,6 @@ sub rdb_make1 { # Any error will arise at the (pdf)latex level due to a # missing source file at that level. if ( $$Psource && (! -e $$Psource) -# OLD && ( ( $$Pcmd_type eq 'cusdep') ) -# NEW && ( ( $$Pcmd_type ne 'primary') ) ) { # Main source file doesn't exist, and rule is NOT primary. @@ -6926,12 +7257,10 @@ sub rdb_make1 { } } + &rdb_clear_change_record; &rdb_flag_changes_here(0); if (!$$Pout_of_date) { -#?? if ( ($$Pcmd_type eq 'primary') && (! $silent) ) { -# print "Rule '$rule' up to date\n"; -# } return; } if ($diagnostics) { print " remake\n"; } @@ -7039,24 +7368,13 @@ sub rdb_make1 { #************************************************************ -#??sub rdb_submake { -#?? # Call: rdb_submake -#?? # Makes all the source files for a given rule. -#?? # Assumes contexts for recursion, for make, and rule. -#?? %visited = %visited_at_rule_start; -#?? local $failure = 0; # Error flag -#?? my @v = keys %visited; -#?? rdb_do_files( sub{ rdb_recurse_rule( $$Pfrom_rule, 0,0,0, \&rdb_make1 ) } ); -#?? return $failure; -#??} #END rdb_submake - -#************************************************************ - sub rdb_classify_rules { - # Usage: rdb_classify_rules( \%allowed_primaries, requested targets ) + # Usage: &rdb_classify_rules # Assume the following variables are available (global or local): # Input: - # @requested_targets # Set to target rules + # %target_rules # Set to target rules + # %target_files # Set to target files + # %possible_primaries # Output: # %current_primaries # Keys are actual primaries @@ -7065,8 +7383,7 @@ sub rdb_classify_rules { # @unusual_one_time # Array of rules # @pre_primary and @post_primary are in natural order of application. - local $P_allowed_primaries = shift; - local @requested_targets = @_; + local @requested_targets = &rdb_target_array; local $state = 0; # Post-primary local @classify_stack = (); @@ -7081,6 +7398,16 @@ sub rdb_classify_rules { @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) { @@ -7142,7 +7469,7 @@ sub rdb_classify1 { push @unusual_one_time, $rule; } elsif ($state == 0) { - if ( exists ${$P_allowed_primaries}{$rule} ) { + if ( exists $possible_primaries{$rule} ) { $state = 1; # In primary rule $current_primaries{ $rule } = 1; } @@ -7213,7 +7540,7 @@ sub rdb_run1 { my @biber_source = ( ); my $retcode = check_biber_log( $$Pbase, \@biber_source ); foreach my $source ( @biber_source ) { -# if ( $source =~ /\"/ ) {next; } +# if ( $source =~ /\"/ ) {next; } print " ===Source file '$source' for '$rule'\n" if ($diagnostics); rdb_ensure_file( $rule, $source ); @@ -7258,30 +7585,30 @@ sub rdb_run1 { } elsif ($retcode == 11) { push @warnings, "Biber: malformed bcf file for '$$Pbase'. IGNORE"; - if (!$silent) { + if (!$silent) { warn "$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, + " I'll ignore error, and delete any bbl file.\n"; + } + # Malformed bcf file is a downstream consequence, normally, # of an error in (pdf)latex run. So this is not an error - # condition in biber itself. - # Current version of biber deletes bbl file. - # Older versions (pre-2016) made an incorrect bbl file, which + # condition in biber itself. + # Current version of biber deletes bbl file. + # Older versions (pre-2016) made an incorrect bbl file, which # tended to cause latex errors, and give a self-perpetuating error. - # To be safe, ensure the bbl file doesn't exist. - unlink $$Pdest; - # The missing bbl file is now not an error: + # To be safe, ensure the bbl file doesn't exist. + unlink $$Pdest; + # The missing bbl file is now not an error: $return = -2; # ??????? BCF # Following is intended to work, but creates infinite loop # in malformed bcf file situation under -pvc. -# since on each check for change in ANY file, pvc finds changed file +# since on each check for change in ANY file, pvc finds changed file # Need to restrict pvc reruns to case of changed USER files -# # To give good properties for (pdf)latex rule, it is best -# # to have a valid bbl file that exists: -# create_empty_file( $$Pdest ); +# # To give good properties for (pdf)latex rule, it is best +# # to have a valid bbl file that exists: +# create_empty_file( $$Pdest ); # $return = 0; - + } } if ( $rule =~ /^bibtex/ ) { @@ -7329,12 +7656,12 @@ sub rdb_run1 { $$Plast_result = 2; 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 ($rule =~ /^(pdf|lua|xe|)latex/) { + $$Plast_message .= "\n Refer to '$log_name' for details"; + } elsif ($rule =~ /^makeindex/) { - $$Plast_message .= "\n Refer to '${aux_dir1}${root_filename}.ilg' for details"; - } + $$Plast_message .= "\n Refer to '${aux_dir1}${root_filename}.ilg' for details"; + } } } elsif ( $$Pdest && (! -e $$Pdest) && ($return != -2) ) { @@ -7409,6 +7736,7 @@ sub Run_subst { my $q = $quote_filenames ? '"' : ''; my %subst = ( + '%A' => $q.$tex_basename.$q, '%B' => $q.$base.$q, '%D' => $q.$dest.$q, '%O' => $options, @@ -7419,14 +7747,14 @@ sub Run_subst { '%Y' => $q.$aux_dir1.$q, '%Z' => $q.$out_dir1.$q, '%%' => '%' # To allow literal %B, %R, etc, by %%B. - ); + ); if ($pre_tex_code) { - $subst{'%U'} = $q.$pre_tex_code.$q; - $subst{'%P'} = "$q$pre_tex_code\\input{$source}$q"; + $subst{'%U'} = $q.$pre_tex_code.$q; + $subst{'%P'} = "$q$pre_tex_code\\input{$source}$q"; } else { - $subst{'%U'} = ''; - $subst{'%P'} = $subst{'%S'}; + $subst{'%U'} = ''; + $subst{'%P'} = $subst{'%S'}; } if ( ($^O eq "MSWin32" ) && $MSWin_back_slash ) { foreach ( '%R', '%B', '%T', '%S', '%D', '%Y', '%Z' ) { @@ -7461,16 +7789,20 @@ sub rdb_primary_run { my $return = 0; if ( ! $filetime_offset_measured ) { - $filetime_offset = get_filetime_offset( $aux_dir1."tmp" ); - if ( (abs($filetime_offset) > $filetime_offset_report_threshold) + $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", + 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; + } + $filetime_offset_measured = 1; } + # 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 @@ -7486,7 +7818,7 @@ sub rdb_primary_run { # of name latex.fls or pdflatex.fls instead of $root_filename.fls. # Also that setting of -output-directory -aux-directory is not # respected by (pdf)latex, at least in some versions. - my $std_fls_file = "$aux_dir1$root_filename.fls"; + my $std_fls_file = $fls_name; my @other_fls_names = ( ); if ( $rule =~ /^pdflatex/ ) { push @other_fls_names, "pdflatex.fls"; @@ -7495,17 +7827,24 @@ sub rdb_primary_run { push @other_fls_names, "latex.fls"; } if ( $aux_dir1 ne '' ) { - push @other_fls_names, "$root_filename.fls"; + push @other_fls_names, "$root_filename.fls"; + # MiKTeX uses out_dir for .fls. However, it seems logical to + # me for .fls to be in aux_dir. So I'll allow for this + # Possibility, although I don't know if it has been used. + push @other_fls_names, "$aux_dir1$root_filename.fls"; } # Find the first non-standard fls file and copy it to the standard # place. But only do this if the file time is compatible with being - # generated in the current run, as tested by the use of + # generated in the current run, and if the standard fls file hasn't + # been made in the current run, as tested by the use of # test_gen_file; that avoids problems with fls files leftover from # earlier runs with other versions of latex. - foreach my $cand (@other_fls_names) { - if ( test_gen_file( $cand ) ) { - copy $cand, $std_fls_file; - last; + if ( ! test_gen_file( $std_fls_file ) ) { + foreach my $cand (@other_fls_names) { + if ( test_gen_file( $cand ) ) { + copy $cand, $std_fls_file; + last; + } } } if ( ! test_gen_file( $std_fls_file ) ) { @@ -7524,17 +7863,6 @@ sub rdb_primary_run { # up-to-date: rdb_do_files( sub { if ($$Pcorrect_after_primary) {&rdb_update1;} } ); -#?? # There may be new source files, and the run may have caused -#?? # circular-dependency files to be changed. And the regular -#?? # source files may have been updated during a lengthy run of -#?? # latex. So redo the makes for sources of the current rule: -#?? my $submake_return = &rdb_submake; -#?? &rdb_clear_change_record; -#?? &rdb_flag_changes_here(0); -#?? if ($$Pout_of_date && !$silent) { -#?? &rdb_diagnose_changes( "Rule '$rule': " ); -#?? } - $updated = 1; # Flag that some dependent file has been remade #?? # Fix the state of the files as of now: this will solve the @@ -7569,8 +7897,8 @@ sub rdb_primary_run { } if ($bad_character) { push @primary_warning_summary, - "=====Latex reported missing or unavailable character(s).\n". - "=====See log file for details."; + "=====Latex reported missing or unavailable character(s).\n". + "=====See log file for details."; } if ($bad_citation) { push @primary_warning_summary, @@ -7587,6 +7915,7 @@ sub rdb_primary_run { sub rdb_clear_change_record { # Initialize diagnostics for reasons for running rule. @changed = (); + @changed_user = (); @disappeared = (); @no_dest = (); # We are not now using this @rules_never_run = (); @@ -7603,7 +7932,6 @@ sub rdb_flag_changes_here { # Usage: rdb_flag_changes_here( ignore_run_time ) # Argument: if true then fdb_get shouldn't do runtime test # for recalculation of md5 - local $ignore_run_time = $_[0]; if ( ! defined $ignore_run_time ) { $ignore_run_time = 0; } @@ -7632,6 +7960,7 @@ sub rdb_file_change1 { } my ($new_time, $new_size, $new_md5) = fdb_get($file, $check_time_argument ); my $ext_no_period = ext_no_period( $file ); + my $generated = exists $from_rules{$file}; if ( ($new_size < 0) && ($$Psize >= 0) ) { # print "Disappeared '$file' in '$rule'\n"; push @disappeared, $file; @@ -7661,10 +7990,10 @@ sub rdb_file_change1 { && ($new_size != $$Psize) ) ) { -#print "========= CHANGED: '$file' from '$$Pfrom_rule'\n"; push @changed, $file; $$Pout_of_date = 1; - if ( ! exists $generated_exts_all{$ext_no_period} ) { + if ( ! $generated ) { + push @changed_user, $file; $$Pout_of_date_user = 1; } } @@ -7672,7 +8001,7 @@ sub rdb_file_change1 { $$Ptime = $new_time; } if ( ( ($$Ptest_kind == 2) || ($$Ptest_kind == 3) ) - && (! exists $generated_exts_all{$ext_no_period} ) + && (! $generated) && ( $new_time > $dest_mtime ) ) { push @changed, $file; @@ -7682,11 +8011,15 @@ sub rdb_file_change1 { #************************************************************ -sub rdb_new_changes { +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. &rdb_clear_change_record; rdb_recurse( [@_], sub{ &rdb_flag_changes_here(1); } ); - return ($#changed >= 0) || ($#no_dest >= 0) || ($#rules_to_apply >= 0); -} #END rdb_new_changes + if ($#changed_user >=0) { show_array( 'User changed files', @changed_user ); } + return ($#changed_user >= 0); +} #END rdb_user_changes #************************************************************ @@ -7837,20 +8170,23 @@ sub rdb_recurse { local %visited = (); local $depth = 0; - foreach $rule ( @heads ) { rdb_recurse_rule( $rule, @_ ); } + foreach $rule ( @heads ) { + if ( rdb_is_active($rule) ) { rdb_recurse_rule( $rule, @_ ); } + } } #END rdb_recurse #************************************************************ -sub rdb_for_all { - # Call: rdb_for_all( \&rule_act1, \&file_act, \&rule_act2 ) +sub rdb_for_actives { + # Call: rdb_for_actives( \&rule_act1, \&file_act, \&rule_act2 ) # Loops through all rules and their source files, using the # specified set of actions, which are pointers to subroutines. # Sorts rules alphabetically. # See rdb_for_some for details. - rdb_for_some( [ sort keys %rule_db ], @_); -} #END rdb_for_all +# rdb_for_some( [ sort keys %rule_db ], @_); + rdb_for_some( [ sort &rdb_actives ], @_); +} #END rdb_for_actives #************************************************************ @@ -7911,6 +8247,7 @@ sub rdb_recurse_rule { # We are overriding actions: my ($rule, $rule_act1, $new_file_act1, $new_file_act2, $rule_act2) = @_; + if (! rdb_is_active($rule)) { return; } # and must propagate the file actions: local $file_act1 = $new_file_act1; local $file_act2 = $new_file_act2; @@ -7975,7 +8312,7 @@ sub rdb_one_rule { $Psource, $Pdest, $Pbase, $Pout_of_date, $Pout_of_date_user, $Prun_time, $Pcheck_time, $Pchanged, - $Plast_result, $Plast_message, $PA_extra_generated ) + $Plast_result, $Plast_message, $PA_extra_gen ) = Parray( $PArule_data ); &$rule_act1 if $rule_act1; @@ -7986,6 +8323,58 @@ sub rdb_one_rule { #************************************************************ +sub rdb_activate { + # Usage rdb_activate( rule_names ) + # Turns on active flag for the rules + foreach ( @_ ) { + if ( rdb_rule_exists($_) ) { $actives{$_} = 1; } + } +} + +#-------------------------------------------------- + +sub rdb_deactivate { + # Usage rdb_deactivate( rule_names ) + # Turns off active flag for the rules + foreach ( @_ ) { delete $actives{$_}; } +} + +#-------------------------------------------------- + +sub rdb_activate_request { + # Usage rdb_activate_request( rule_names ) + # Turns on active flag for the rules. + # Adds rules to target_rules list + foreach ( @_ ) { + if ( rdb_rule_exists($_) ) { $actives{$_} = 1; $target_rules{$_} = 1; } + } +} + +#-------------------------------------------------- + +sub rdb_deactivate_derequest { + # Usage rdb_deactivate_derequest( rule_names ) + # Turns off active flag for the rules + # Removes rules from target_rules list + foreach ( @_ ) { delete $actives{$_}; delete $target_rules{$_}; } +} + +#-------------------------------------------------- +sub rdb_is_active { + # Usage rdb_is_active( rule_name ) + if ( (exists $actives{$_[0]}) && rdb_rule_exists($_[0]) ) { return 1; } + else { return 0; } +} + +#-------------------------------------------------- + +sub rdb_actives { + # Returns array of active rules + return keys %actives; +} + +#************************************************************ + sub rdb_one_file { # Call: rdb_one_file($file, $file_act) # Sets context for file and carries out the action. @@ -8015,6 +8404,7 @@ sub rdb_remove_rule { # rdb_remove_rule( rule, ... ) foreach my $key (@_) { delete $rule_db{$key}; + delete $actives{$key}; } } @@ -8028,12 +8418,14 @@ sub rdb_create_rule { # int_cmd is either a string naming a perl subroutine or it is a # reference to an array containing the subroutine name and its # arguments. - # Makes rule. Error if it already exists. - # Omitted arguments: replaced by 0 or '' as needed. + # Makes rule. Update rule if it already exists. + # Omitted arguments: replaced by 0 or '' as needed. + # Rule is made active # ==== Sets rule data ==== my ( $rule, $cmd_type, $ext_cmd, $PAint_cmd, $test_kind, $source, $dest, $base, $needs_making, $run_time, $check_time, $set_file_not_exists, $extra_gen ) = @_; + my $active = 1; my $changed = 0; # Set defaults, and normalize parameters: @@ -8042,10 +8434,10 @@ sub rdb_create_rule { if (! defined $_) { $_ = ''; } } if ( ($source =~ /\"/) || ($dest =~ /\"/) || ($base =~ /\"/) ) { - die "$My_name: Error. In rdb_create_rule there is a double quote in one of\n", - " source, destination or base parameters:\n", - " '$source', '$dest', '$base'\n", - " I cannot handle this.\n"; + die "$My_name: Error. In rdb_create_rule there is a double quote in one of\n", + " source, destination or base parameters:\n", + " '$source', '$dest', '$base'\n", + " I cannot handle this.\n"; } foreach ( $needs_making, $run_time, $check_time, $test_kind ) { if (! defined $_) { $_ = 0; } @@ -8078,6 +8470,8 @@ sub rdb_create_rule { rdb_ensure_file( $rule, $source, undef, $set_file_not_exists ); } rdb_one_rule( $rule, \&rdb_initialize_generated ); + if ($active) { rdb_activate($rule); } + else { rdb_deactivate($rule); } } #END rdb_create_rule #************************************************************ @@ -8087,18 +8481,17 @@ sub rdb_initialize_generated { # Initialize hash of generated files %$PHdest = (); if ($$Pdest) { rdb_add_generated($$Pdest); } - foreach (@$PA_extra_generated) { - rdb_add_generated($_); - } + rdb_add_generated(@$PA_extra_gen); } #END rdb_initialize_generated #************************************************************ sub rdb_add_generated { # Assume rule context. -# Add arguments to hash of generated files +# Add arguments to hash of generated files, and to global cache foreach (@_) { $$PHdest{$_} = 1; + $from_rules{$_} = $rule; } } #END rdb_add_generated @@ -8107,9 +8500,7 @@ sub rdb_add_generated { sub rdb_remove_generated { # Assume rule context. # Remove arguments from hash of generated files - foreach (@_) { - delete $$PHdest{$_}; - } + foreach (@_) { delete $$PHdest{$_}; } } #END rdb_remove_generated #************************************************************ @@ -8135,17 +8526,17 @@ sub rdb_ensure_file { die_trace( "$My_name: BUG in call to rdb_ensure_file: undefined file for '$rule'" ); } if ( $new_file =~ /\"/ ) { - warn "$My_name: in rdb_ensure_file for rule '$rule', there is a double quote in\n", - " the filename: '$new_file'.\n", - " I cannot handle this, will ignore this file.\n"; - return; + warn "$My_name: in rdb_ensure_file for rule '$rule', there is a double quote in\n", + " the filename: '$new_file'.\n", + " I cannot handle this, will ignore this file.\n"; + return; } if ( ! defined $set_not_exists ) { $set_not_exists = 0; } rdb_one_rule( $rule, sub{ if (! exists ${$PHsource}{$new_file} ) { if ( $set_not_exists ) { - ${$PHsource}{$new_file} = [0, -1, 0, '', 0]; + ${$PHsource}{$new_file} = [@nofile, '', 0]; } else { ${$PHsource}{$new_file} @@ -8193,9 +8584,9 @@ sub rdb_set_source { if (!$rule) { return; } my %files = (); foreach (@_) { -# if ( /\"/ ) {next; } - rdb_ensure_file( $rule, $_ ); - $files{$_} = 1; +# if ( /\"/ ) {next; } + rdb_ensure_file( $rule, $_ ); + $files{$_} = 1; } foreach ( rdb_list_source($rule) ) { if ( ! exists $files{$_} ) { rdb_remove_files( $rule, $_ ); } @@ -8220,12 +8611,12 @@ sub rdb_change_dest { rdb_add_generated( $new_dest ); if ($flag) { print "rdb_change_dest: fixing dependencies\n"; - rdb_for_all( sub{ if ( rdb_file_exists( $rule, $old_dest ) ) { - rdb_ensure_file( $rule, $new_dest ); - rdb_remove_files( $rule, $old_dest ); + 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? @@ -8261,7 +8652,11 @@ sub rdb_update_gen_files { # Assumes rule context. Update source files of rule to current state. rdb_do_files( sub{ - if ( exists $generated_exts_all{ ext_no_period($file) } ) {&rdb_update1;} + if ( exists $generated_exts_all{ ext_no_period($file) } + || exists $$PHdest{$file} + ) { + &rdb_update1; + } } ); } #END rdb_update_gen_files @@ -8340,7 +8735,7 @@ sub cus_dep_require_primary_run { local $cus_dep_target = $$Pdest; # Loop over all rules and source files: - rdb_for_all( 0, + rdb_for_actives( 0, sub { if ($file eq $cus_dep_target) { $$Pout_of_date = 1; $$Pcorrect_after_primary = 1; @@ -8372,6 +8767,17 @@ sub show_array { else { warn " NONE\n"; } } + +#************************************************************ + +sub array_to_hash { + # Call: array_to_hash( items ) + # Returns: hash mapping items to 1 + my %hash = (); + foreach (@_) {$hash{$_} = 1; } + return %hash; +} + #************************************************************ sub Parray { @@ -8620,7 +9026,7 @@ sub get_checksum_md5 { sub create_empty_file { my $name = shift; my $h = new FileHandle ">$name" - or return 1; + or return 1; close ($h); return 0; } @@ -8724,12 +9130,24 @@ sub find_file_list1 { sub unlink_or_move { if ( $del_dir eq '' ) { - unlink @_; + foreach (@_) { + if (!-e) {next;} + if (-d) { + if (!rmdir) { + warn "$My_name: Cannot remove directory '$_'\n"; + } + } + else { + if (!unlink) { + warn "$My_name: Cannot remove file '$_'\n"; + } + } + } } else { foreach (@_) { - if (-e $_ && ! rename $_, "$del_dir/$_" ) { - warn "$My_name:Cannot move '$_' to '$del_dir/$_'\n"; + if (-e $_ && ! move $_, "$del_dir/$_" ) { + warn "$My_name: Cannot move '$_' to '$del_dir/$_'\n"; } } } @@ -8748,9 +9166,9 @@ sub kpsewhich { my $cmd = $kpsewhich; my @args = @_; if ( ($cmd eq '') || ( $cmd =~ /^NONE($| )/ ) ) { - # Kpsewhich not set up. - warn "$My_name: Kpsewhich command needed but not set up\n"; - return (); + # Kpsewhich not set up. + warn "$My_name: Kpsewhich command needed but not set up\n"; + return (); } foreach (@args) { if ( ! /^-/ ) { @@ -8772,7 +9190,7 @@ sub kpsewhich { } close $fh; if ( $kpsewhich_show || $diagnostics ) { - show_array( "$My_name.kpsewhich: '$cmd' ==>", @found ); + show_array( "$My_name.kpsewhich: '$cmd' ==>", @found ); } return @found; } @@ -8829,38 +9247,23 @@ sub add_aux_hook { #################################################### -sub add_input_ext { - # Usage: add_input_ext( rule, ext, ... ) - # Add extension(s) (specified without a leading period) to the - # list of input extensions for the given rule. The rule should be - # 'latex' or 'pdflatex'. These extensions are used when an input +sub set_input_ext { + # Usage: set_input_ext( rule, ext, ... ) + # Set list of extension(s) (specified without a leading period) + # for the given rule ('latex', 'pdflatex', etc). + # These extensions are used when an input # file without an extension is found by (pdf)latex, as in # \input{file} or \includegraphics{figure}. When latexmk searches # custom dependencies to make the missing file, it will assume that # the file has one of the specified extensions. my $rule = shift; - if ( ! exists $input_extensions{$rule} ) { - $input_extensions{$rule} = {}; - } + $input_extensions{$rule} = {}; my $Prule = $input_extensions{$rule}; foreach (@_) { $$Prule{$_} = 1; } } #################################################### -sub remove_input_ext { - # Usage: remove_input_ext( rule, ext, ... ) - # Remove extension(s) (specified without a leading period) to the - # list of input extensions for the given rule. The rule should be - # 'latex' or 'pdflatex'. See sub add_input_ext for the use. - my $rule = shift; - if ( ! exists $input_extensions{$rule} ) { return; } - my $Prule = $input_extensions{$rule}; - foreach (@_) { delete $$Prule{$_}; } -} - -#################################################### - sub show_input_ext { # Usage: show_input_ext( rule ) my $rule = shift; @@ -9051,12 +9454,12 @@ sub get_filetime_offset { 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(); + 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; + my $offset = get_mtime($tmp_file) - $time; + unlink $tmp_file; return $offset; } } @@ -9187,12 +9590,14 @@ sub Run_no_time { 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"; + warn "$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"; + warn "$My_name: calling $routine()\n" + if (! $silent); return ( 0, &$routine() ); } elsif ( $cmd_line =~ /^NONE/ ) { @@ -9306,7 +9711,7 @@ sub find_process_id { shift(@ps_output); # Discard the header line from ps foreach (@ps_output) { next unless ( /$looking_for/ ) ; - s/^\s*//; + s/^\s*//; my @ps_line = split ('\s+'); push @found, $ps_line[$pid_position]; push @ps_lines, $_; @@ -9357,7 +9762,7 @@ sub cache_good_cwd { } } elsif ( $^O eq "msys" ) { - $cwd =~ s[^/([a-z])/][\u$1:/]; + $cwd =~ s[^/([a-z])/][\u$1:/]; } $cache{cwd} = $cwd; } # END cache_good_cwd @@ -9397,7 +9802,8 @@ sub popd { sub ifcd_popd { if ( $do_cd ) { - warn "$My_name: Undoing directory change\n"; + warn "$My_name: Undoing directory change\n" + if !$silent; &popd; } } diff --git a/Build/source/texk/texlive/linked_scripts/ptex-fontmaps/kanji-config-updmap.pl b/Build/source/texk/texlive/linked_scripts/ptex-fontmaps/kanji-config-updmap.pl index 1a0f1f2530a..94cfe92dd36 100755 --- a/Build/source/texk/texlive/linked_scripts/ptex-fontmaps/kanji-config-updmap.pl +++ b/Build/source/texk/texlive/linked_scripts/ptex-fontmaps/kanji-config-updmap.pl @@ -1,12 +1,12 @@ #!/usr/bin/env perl # kanji-config-updmap: setup Japanese font embedding -# Version 20180328.0 +# Version 20190318.0 # # formerly known as updmap-setup-kanji # # Copyright 2004-2006 by KOBAYASHI R. Taizo for the shell version (updmap-otf) -# Copyright 2011-2018 by PREINING Norbert -# Copyright 2016-2018 by Japanese TeX Development Community +# Copyright 2011-2019 by PREINING Norbert +# Copyright 2016-2019 by Japanese TeX Development Community # # This file is licensed under GPL version 3 or any later version. # For copyright statements see end of file. @@ -22,7 +22,7 @@ use Getopt::Long qw(:config no_autoabbrev ignore_case_always); use strict; my $prg = "kanji-config-updmap"; -my $version = '20180328.0'; +my $version = '20190318.0'; my $updmap_real = "updmap"; my $updmap = $updmap_real; @@ -131,6 +131,7 @@ if ($opt_help) { # representatives of support font families # my %representatives; +my %ai0flags; my @databaselist = "ptex-fontmaps-data.dat"; push @databaselist, "ptex-fontmaps-macos-data.dat" if (macosx_new()); @@ -228,6 +229,7 @@ EOF sub InitDatabase { %representatives = (); + %ai0flags = (); } sub ReadDatabase { @@ -270,6 +272,30 @@ sub ReadDatabase { $representatives{'ko'}{$2}{'file'} = $3; next; } + if ($l =~ m/^JA-AI0:\s*(.*):\s*(.*)$/) { + $representatives{'ja'}{$1}{'priority'} = 9999; # lowest + $representatives{'ja'}{$1}{'file'} = $2; + $ai0flags{'ja'}{$1} = 1; + next; + } + if ($l =~ m/^SC-AI0:\s*(.*):\s*(.*)$/) { + $representatives{'sc'}{$1}{'priority'} = 9999; # lowest + $representatives{'sc'}{$1}{'file'} = $2; + $ai0flags{'sc'}{$1} = 1; + next; + } + if ($l =~ m/^TC-AI0:\s*(.*):\s*(.*)$/) { + $representatives{'tc'}{$1}{'priority'} = 9999; # lowest + $representatives{'tc'}{$1}{'file'} = $2; + $ai0flags{'tc'}{$1} = 1; + next; + } + if ($l =~ m/^KO-AI0:\s*(.*):\s*(.*)$/) { + $representatives{'ko'}{$1}{'priority'} = 9999; # lowest + $representatives{'ko'}{$1}{'file'} = $2; + $ai0flags{'ko'}{$1} = 1; + next; + } # we are still here?? die "Cannot parse \"$foo\" at line $lineno, exiting. Strange line: >>>$l<<<\n"; @@ -322,6 +348,19 @@ sub check_mapfile { } } +sub gen_mapfile { + my $opt_mode = shift; + my $map_base = shift; + # returns a representative map file name + # ptex-${map_base}.map also exists for Japanese AI0 fonts, + # but it is a stub so we use uptex-${map_base}.map instead + return ($opt_mode eq "ja" ? + ($ai0flags{$opt_mode}{$map_base} ? + "uptex-${map_base}.map" : + "ptex-${map_base}.map") : + "uptex-${opt_mode}-${map_base}.map"); +} + sub GetStatus { my $opt_mode = shift; my $val = `$updmap_real --quiet --showoption ${opt_mode}Embed`; @@ -332,19 +371,23 @@ sub GetStatus { die "Cannot find status of current ${opt_mode}Embed setting via updmap --showoption!\n"; } - my $testmap = ($opt_mode eq "ja" ? "ptex-$STATUS.map" : "uptex-${opt_mode}-$STATUS.map"); + my $testmap = gen_mapfile($opt_mode, $STATUS); if (check_mapfile($testmap)) { - print "CURRENT family for $opt_mode: $STATUS\n"; + print "CURRENT family for $opt_mode: $STATUS"; + print " (AI0)" if ($ai0flags{$opt_mode}{$STATUS}); + print "\n"; } else { print STDERR "WARNING: Currently selected map file for $opt_mode cannot be found: $testmap\n"; } for my $k (sort keys %{$representatives{$opt_mode}}) { - my $MAPFILE = ($opt_mode eq "ja" ? "ptex-$k.map" : "uptex-${opt_mode}-$k.map"); + my $MAPFILE = gen_mapfile($opt_mode, $k); next if ($MAPFILE eq $testmap); if (check_mapfile($MAPFILE)) { if ($representatives{$opt_mode}{$k}{'available'}) { - print "Standby family : $k\n"; + print "Standby family : $k"; + print " (AI0)" if ($ai0flags{$opt_mode}{$k}); + print "\n"; } } } @@ -358,14 +401,16 @@ sub GetStatus { sub SetupMapFile { my $opt_mode = shift; my $rep = shift; - my $MAPFILE = ($opt_mode eq "ja" ? "ptex-$rep.map" : "uptex-${opt_mode}-$rep.map"); + my $MAPFILE = gen_mapfile($opt_mode, $rep); if (check_mapfile($MAPFILE)) { - print "Setting up ... $MAPFILE\n"; - system("$updmap --quiet --nomkmap --nohash -setoption ${opt_mode}Embed $rep"); + print "Setting up ... $rep"; + print " (AI0)" if ($ai0flags{$opt_mode}{$rep}); + print " for $opt_mode\n"; + system("$updmap --quiet --nomkmap --nohash --setoption ${opt_mode}Embed $rep"); if ($opt_jis) { - system("$updmap --quiet --nomkmap --nohash -setoption jaVariant -04"); + system("$updmap --quiet --nomkmap --nohash --setoption jaVariant -04"); } else { - system("$updmap --quiet --nomkmap --nohash -setoption jaVariant \"\""); + system("$updmap --quiet --nomkmap --nohash --setoption jaVariant \"\""); } } else { die "NOT EXIST $MAPFILE\n"; @@ -377,21 +422,21 @@ sub SetupReplacement { my $rep = shift; if (defined($representatives{$opt_mode}{$rep})) { if ($representatives{$opt_mode}{$rep}{'available'}) { - SetupMapFile($opt_mode, $rep); + return SetupMapFile($opt_mode, $rep); } else { printf STDERR "$rep not available, falling back to auto!\n"; - SetupReplacement($opt_mode, "auto"); + return SetupReplacement($opt_mode, "auto"); } } else { if ($rep eq "nofont") { - SetupMapFile($opt_mode, "noEmbed"); + return SetupMapFile($opt_mode, "noEmbed"); } elsif ($rep eq "auto") { my $STATUS = GetStatus($opt_mode); # first check if we have a status set and the font is installed # in this case don't change anything, just make sure if (defined($representatives{$opt_mode}{$STATUS}) && $representatives{$opt_mode}{$STATUS}{'available'}) { - SetupMapFile($opt_mode, $STATUS); + return SetupMapFile($opt_mode, $STATUS); } else { if (!($STATUS eq "noEmbed" || $STATUS eq "")) { # some unknown setting is set up currently, overwrite, but warn @@ -404,15 +449,15 @@ sub SetupReplacement { $representatives{$opt_mode}{$b}{'priority'} } keys %{$representatives{$opt_mode}}) { if ($representatives{$opt_mode}{$i}{'available'}) { - SetupMapFile($opt_mode, $i); + return SetupMapFile($opt_mode, $i); } } # still here, no map file found! - SetupMapFile($opt_mode, "noEmbed"); + return SetupMapFile($opt_mode, "noEmbed"); } } else { # anything else is treated as a map file name - SetupMapFile($opt_mode, $rep); + return SetupMapFile($opt_mode, $rep); } } } diff --git a/Build/source/texk/texlive/linked_scripts/ptex-fontmaps/kanji-fontmap-creator.pl b/Build/source/texk/texlive/linked_scripts/ptex-fontmaps/kanji-fontmap-creator.pl index 4631e48c275..b1da19e74a2 100755 --- a/Build/source/texk/texlive/linked_scripts/ptex-fontmaps/kanji-fontmap-creator.pl +++ b/Build/source/texk/texlive/linked_scripts/ptex-fontmaps/kanji-fontmap-creator.pl @@ -2,7 +2,7 @@ # # kanji-fontmap-creator # (c) 2012-2014 Norbert Preining -# Version: 20180328.0 +# Version: 20190318.0 # Licenced under the GPLv2 or any higher version # # gui to create map files for (kanji-config-)updmap @@ -41,7 +41,7 @@ my $opt_help = 0; my $opt_version = 0; my $prg = "kanji-fontmap-creator"; -my $version = "20180328.0"; +my $version = "20190318.0"; # # global vars configuring operation diff --git a/Build/source/texk/texlive/linked_scripts/texlive/updmap.pl b/Build/source/texk/texlive/linked_scripts/texlive/updmap.pl index 666a15099a8..d1cfe6c5df2 100755 --- a/Build/source/texk/texlive/linked_scripts/texlive/updmap.pl +++ b/Build/source/texk/texlive/linked_scripts/texlive/updmap.pl @@ -1,9 +1,9 @@ #!/usr/bin/env perl -# $Id: updmap.pl 44331 2017-05-14 02:15:43Z preining $ +# $Id: updmap.pl 50442 2019-03-18 11:35:23Z hironobu $ # updmap - maintain map files for outline fonts. # (Maintained in TeX Live:Master/texmf-dist/scripts/texlive.) # -# Copyright 2011-2017 Norbert Preining +# Copyright 2011-2019 Norbert Preining # This file is licensed under the GNU General Public License version 2 # or any later version. # @@ -14,7 +14,7 @@ # the original versions were licensed under the following agreement: # Anyone may freely use, modify, and/or distribute this file, without -my $svnid = '$Id: updmap.pl 44331 2017-05-14 02:15:43Z preining $'; +my $svnid = '$Id: updmap.pl 50442 2019-03-18 11:35:23Z hironobu $'; my $TEXMFROOT; BEGIN { @@ -27,10 +27,10 @@ BEGIN { unshift(@INC, "$TEXMFROOT/tlpkg"); } -my $lastchdate = '$Date: 2017-05-14 04:15:43 +0200 (Sun, 14 May 2017) $'; +my $lastchdate = '$Date: 2019-03-18 12:35:23 +0100 (Mon, 18 Mar 2019) $'; $lastchdate =~ s/^\$Date:\s*//; $lastchdate =~ s/ \(.*$//; -my $svnrev = '$Revision: 44331 $'; +my $svnrev = '$Revision: 50442 $'; $svnrev =~ s/^\$Revision:\s*//; $svnrev =~ s/\s*\$$//; my $version = "r$svnrev ($lastchdate)"; @@ -845,9 +845,18 @@ sub cidx2dvips { chomp; # save the line for warnings my $l = $_; - # first check whether a PSname is given + # my $psname; + my $fbname; # + # special case for pre-defined fallback from unicode encoded font + if ($_ =~ m/%!DVIPSFB\s\s*([0-9A-Za-z-_!,][0-9A-Za-z-_!,]*)/) { + $fbname = $1; + # minimal adjustment + $fbname =~ s/^!//; + $fbname =~ s/,Bold//; + } + # first check whether a PSname is given # the matching on \w* is greedy, so will take all the word chars available # that means we do not need to test for end of word if ($_ =~ m/%!PS\s\s*([0-9A-Za-z-_][0-9A-Za-z-_]*)/) { @@ -875,7 +884,8 @@ sub cidx2dvips { # make everything single spaced s/\s\s*/ /g; # unicode encoded fonts are not supported - next if (m!^\w\w* unicode !); + # but if a fallback font is pre-defined, we can use it + next if (!defined($fbname) && (m!^[0-9A-Za-z-_][0-9A-Za-z-_]* unicode !)); # now we have the following format # <word> <word> <word> some options like -e or -s if ($_ !~ m/([^ ][^ ]*) ([^ ][^ ]*) ([^ ][^ ]*)( (.*))?$/) { @@ -911,13 +921,17 @@ sub cidx2dvips { $opts .= " \"$italicmax SlantFont\""; } # print out the result - if (defined($psname)) { - push @d, "$tfmname $psname-$cid$opts\n"; + if (defined($fbname)) { + push @d, "$tfmname $fbname\n"; } else { - if (defined($fname_psname{$fname})) { - push @d, "$tfmname $fname_psname{$fname}-$cid$opts\n"; + if (defined($psname)) { + push @d, "$tfmname $psname-$cid$opts\n"; } else { - push @d, "$tfmname $fname-$cid$opts\n"; + if (defined($fname_psname{$fname})) { + push @d, "$tfmname $fname_psname{$fname}-$cid$opts\n"; + } else { + push @d, "$tfmname $fname-$cid$opts\n"; + } } } } diff --git a/Build/source/texk/texlive/linked_scripts/tlshell/tlshell.tcl b/Build/source/texk/texlive/linked_scripts/tlshell/tlshell.tcl index 18b4de2aac0..658e5313111 100755 --- a/Build/source/texk/texlive/linked_scripts/tlshell/tlshell.tcl +++ b/Build/source/texk/texlive/linked_scripts/tlshell/tlshell.tcl @@ -2022,7 +2022,7 @@ proc populate_main {} { .mn add cascade -label [__ "Help"] -menu .mn.help -underline 0 menu .mn.help .mn.help add command -label [__ "About"] -command { - tk_messageBox -message [__ "\u00a9 2017, 2018 Siep Kroonenberg + tk_messageBox -message [__ "Copyright 2017, 2018 Siep Kroonenberg GUI interface for TeX Live Manager Implemented in Tcl/Tk |