From 139b9298a7e590dff3b79ab5be0699d2bdd2dbb0 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Thu, 18 Aug 2011 04:10:38 +0000 Subject: multi-updmap: - merging of data now working - handling of options implemented, but not all of them are implemented by now git-svn-id: svn://tug.org/texlive/trunk@23590 c570f23f-e606-0410-a88d-b1316a301751 --- Master/tlpkg/dev/multi-updmap.pl | 312 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 290 insertions(+), 22 deletions(-) diff --git a/Master/tlpkg/dev/multi-updmap.pl b/Master/tlpkg/dev/multi-updmap.pl index def1831e8aa..7680da76339 100644 --- a/Master/tlpkg/dev/multi-updmap.pl +++ b/Master/tlpkg/dev/multi-updmap.pl @@ -14,6 +14,8 @@ # limitation. # +my ($TEXMFROOT, $TEXMFMAIN, $TEXMFVAR); + BEGIN { $^W=1; $TEXMFROOT = `kpsewhich -var-value=TEXMFROOT`; @@ -21,7 +23,10 @@ BEGIN { print STDERR "updmap: Cannot find TEXMFROOT, aborting!\n"; exit 1; } - chomp($TEXMFROOT = `kpsewhich -var-value=TEXMFROOT`); + chomp($TEXMFROOT); + chomp($TEXMFMAIN =`kpsewhich --var-value=TEXMFMAIN`); + chomp($TEXMFVAR = `kpsewhich -var-value=TEXMFVAR`); + chomp($TEXMFCONFIG = `kpsewhich -var-value=TEXMFCONFIG`); unshift (@INC, "$TEXMFROOT/tlpkg"); } @@ -32,11 +37,39 @@ use TeXLive::TLUtils qw(mkdirhier mktexupd win32 log); use Getopt::Long qw(:config no_autoabbrev ignore_case_always); use Pod::Usage; -my $short_progname = "updmap"; +my $prg = TeXLive::TLUtils::basename($0); +# used for testing only use Data::Dumper; -my %opts; +my %opts = ( quiet => 0, nohash => 0, nomkmap => 0 ); +my @cmdline_options = ( + "cnffile=s@", + "copy", + "disable=s@", + "dvipdfmoutputdir=s", + "dvipsoutputdir=s", + "enable=s{1,2}", + "edit", + "force", + "listavailablemaps", + "listmaps|l", + "nohash", + "nomkmap", + "dry-run|n", + "outputdir=s", + "pdftexoutputdir=s", + "quiet|silent|q", + # the following is a correct specification of an option according + # to the manual, but it does not work! + # we will treat that option by itself in processOptions + #"setoption=s@{1,2}", + "showoptions=s@", + "syncwithtrees", + "version", + "help|h" + ); + my %settings = ( dvipsPreferOutline => [ qw/true false/ ], LW35 => [ qw/URW URWkb ADOBE ADOBEkb/ ], @@ -50,17 +83,211 @@ my %settings = ( ############### sub main { - testmain(); + processOptions(); + + help() if $opts{'help'}; + + if ($opts{'showoptions'}) { + showOptions(@{$opts{'showoptions'}}); + exit 0; + } + + # determine which config files shold be used + # replaces the former "setupCfgFile" + if ($opts{'cnffile'}) { + for my $f (@{$opts{'cnffile'}}) { + if (! -f $f) { + die "$prg: Config file \"$f\" not found."; + } + } + } else { + @{$opts{'cnffile'}} = `kpsewhich -all updmap.cfg`; + chomp(@{$opts{'cnffile'}}); + } + + if ($opts{'listmaps'}) { + listMaps(); + exit 0; + } + + if ($opts{'syncwithtrees'}) { + warning("NOT IMPLEMENTED syncwithtrees!\n"); + exit 1; + } + + # we do changes always in the used config file with the highest + # priority + my ($top_config_file) = @{$opts{'cnffile'}}; + my $bakFile = $top_config_file; + $bakFile =~ s/\.cfg$/.bak/; + ©File($top_config_file, $bakFile); + + my $cmd; + my $data = read_updmap_files(@{$opts{'cnffile'}}); + if ($opts{'edit'}) { + # it's not a good idea to edit updmap.cfg manually these days, + # but for compatibility we'll silently keep the option. + $cmd = 'edit'; + my $editor = $ENV{'VISUAL'} || $ENV{'EDITOR'}; + $editor ||= (&win32 ? "notepad" : "vi"); + system($editor, $top_config_file); + } elsif ($opts{'setoption'}) { + $cmd = 'setOption'; + warning("NOT IMPLEMENTED setoption!\n"); + exit 1; + } elsif ($opts{'enable'}) { + $cmd = 'enableMap'; + warning("NOT IMPLEMENTED enable!\n"); + exit 1; + } elsif ($opts{'disable'}) { + $cmd = 'disableMap'; + warning("NOT IMPLEMENTED disable!\n"); + exit 1; + } + + if ($cmd && !$opts{'force'} && files_are_equal($bakFile, $top_config_file)) { + print "$top_config_file unchanged. Map files not recreated.\n" + if !$opts{'quiet'}; + } else { + if (!$opts{'nomkmap'}) { + setupOutputDir("dvips"); + setupOutputDir("pdftex"); + mkMaps($data); + } + unlink ($bakFile); + } + + my $updLSR = &mktexupd(); + $updLSR->{mustexist}(0); + if (!$opts{'nohash'}) { + print "$prg: Updating ls-R files.\n" if !$opts{'quiet'}; + $updLSR->{exec}(); + } } -sub testmain { + +sub mkMaps { + warning("NOT IMPLEMENTED mkMaps ... dumping data structure for now!\n"); $Data::Dumper::Indent = 1; - my $data = read_updmap_files(); + my $data = read_updmap_files(@{$opts{'cnffile'}}); $data = read_map_files($data); + $data = merge_data($data); print Data::Dumper->Dump([$data], [qw(mapdata)]); } -##################### + +sub processOptions { + # first process the stupid setoption= s@{1,2} which is not accepted + my $oldconfig = Getopt::Long::Configure(qw(pass_through)); + my @setoptions; + GetOptions("setoption=s{1,2}" => \@setoptions) or + die "Try \"$prg --help\" for more information.\n"; + Getopt::Long::Configure($oldconfig); + + # now revamp the @setoptions that they have the proper style + my @realset; + while (@setoptions) { + my $t = shift @setoptions; + if ($t =~ m/=/) { + push @realset, $t; + } else { + my $tt = shift @setoptions; + die "Try \"$prg --help\" for more information.\n" + if !defined($tt); + push @realset, "$t=$tt"; + } + } + if (@realset) { + @{$opts{'setoption'}} = @realset; + } + + # now continue with normal option handling + + GetOptions(\%opts, @cmdline_options) or + die "Try \"$prg --help\" for more information.\n"; +} + +# determines the output dir for driver from cmd line, or if not given +# from TEXMFVAR +sub setupOutputDir { + my $driver = shift; + if (!$opts{$driver . "outputdir"}) { + if ($opts{'outputdir'}) { + $opts{$driver . "outputdir"} = $opts{'outputdir'}; + } else { + $opts{$driver . "outputdir"} = "$TEXMFVAR/fonts/map/$driver/updmap"; + } + } + my $od = $opts{$driver . "outputdir"}; + &mkdirhier($od); + if (! -w $od) { + die "$prg: Directory \"$od\" isn't writable: $!"; + } + print "$driver output dir: \"$od\"\n" if !$opts{'quiet'}; + return $od; +} + +############################################################################# +# showOptions(item) +# show Options for an item +# +sub showOptions { + foreach my $item (@_) { + if ($item eq "LW35") { + print "URWkb URW ADOBE ADOBEkb\n"; + } + elsif ($item =~ +m/(dvipsPreferOutline|(dvipdfm|pdftex)DownloadBase14|dvipsDownloadBase35)/) { + print "true false\n"; + } + else { + print "Unknown item \"$item\"; should be one of LW35, dvipsPreferOutline,\n" + . " dvipsDownloadBase35, or pdftexDownloadBase14\n"; + } + } + exit 0 +} + +# +# listMaps +# +# list all maps in the format +# Maptype Mapname 'enabled'|'disabled' 'in' updmap_cfg_filename +# +sub listMaps { + my $data = read_updmap_files(@{$opts{'cnffile'}}); + for my $m (keys %{$data->{'maps'}}) { + my $origin = $data->{'maps'}{$m}{'origin'}; + print $data->{'updmap'}{$origin}{'maps'}{$m}{'type'}, " $m ", + $data->{'updmap'}{$origin}{'maps'}{$m}{'status'}, " in $origin\n"; + } +} + +############################################################################### +# copyFile() +# copy file $src to $dst, sets $dst creation and mod time +# +sub copyFile { + my ($src, $dst) = @_; + my $dir; + ($dir=$dst)=~s/(.*)\/.*/$1/; + mkdirhier $dir; + + $src eq $dst && return "can't copy $src to itself!\n"; + + open IN, "<$src" or die "$0: can't open source file $src for copying: $!"; + open OUT, ">$dst"; + + binmode(IN); + binmode(OUT); + print OUT ; + close(OUT); + close(IN); + my @t = stat($src); + utime($t[8], $t[9], $dst); +} + +################################################################# # # reading updmap-cfg files and the actual map files # @@ -71,20 +298,23 @@ sub testmain { # initialized by read_updmap_files # $data->{'order'} = [ list of updmap in decreasing priority ] # $data->{'updmap'}{$full_path_name_of_updmap}{'setting'}{$key} = $val -# $data->{'updmap'}{$full_path_name_of_updmap}{'maps'}{$mapname} +# $data->{'updmap'}{$full_path_name_of_updmap}{'maps'}{$mapname}{'type'} # = 'Map'|'MixedMap'|'disabled' +# $data->{'updmap'}{$full_path_name_of_updmap}{'maps'}{$mapname}{'status'} +# = 'enabled'|'disabled' +# $data->{'maps'}{$m}{'origin'} = $updmap_path_name # # initialized by read_map_files -# $data->{'maps'}{$m}{$font} = $rest +# $data->{'maps'}{$m}{'fonts'}{$font} = $rest # # initialized by merge_data # $data->{'merged'}{'setting'}{$key} = $val -# $data->{'merged'}{'fonts'}{$fontdef} = $rest +# $data->{'merged'}{'allMaps'}{'fonts'}{$fontdef} = $rest +# $data->{'merged'}{'noMixedMaps'}{'fonts'}{$fontdef} = $rest # sub read_updmap_files { - my (@l) = `kpsewhich -all updmap.cfg`; - chomp(@l); + my (@l) = @_; my %data; for my $l (@l) { my $updmap = read_updmap_file($l); @@ -95,11 +325,23 @@ sub read_updmap_files { } if (defined($updmap->{'maps'})) { for my $k (keys %{$updmap->{'maps'}}) { - $data{'updmap'}{$l}{'maps'}{$k} = $updmap->{'maps'}{$k}; + $data{'updmap'}{$l}{'maps'}{$k}{'type'} = $updmap->{'maps'}{$k}{'type'}; + $data{'updmap'}{$l}{'maps'}{$k}{'status'} = $updmap->{'maps'}{$k}{'status'}; } } } $data{'order'} = \@l; + # first round determine which maps should be used and which type, as + # different updmap.cfg files might specify different types of maps + # (MixedMap or Map). + # Again, we have to do that in reverse order + for my $l (reverse @l) { + if (defined($data{'updmap'}{$l}{'maps'})) { + for my $m (keys %{$data{'updmap'}{$l}{'maps'}}) { + $data{'maps'}{$m}{'origin'} = $l; + } + } + } return \%data; } @@ -118,6 +360,8 @@ sub read_updmap_file { next if /^\s*#$/; next if /^\s*#[^!]/; next if /^#![^ ]/; + # allow for commands on the line itself + s/([^#].*)#.*$/$1/; my ($a, $b, @rest) = split ' '; if ($a eq "#!") { if ($b eq "Map" || $b eq "MixedMap") { @@ -128,7 +372,8 @@ sub read_updmap_file { if (defined($data{'maps'}{$c})) { warning("updmap: double mentioning of $c in $fn\n"); } - $data{'maps'}{$c} = 'disabled'; + $data{'maps'}{$c}{'status'} = 'disabled'; + $data{'maps'}{$c}{'type'} = $b; } } next; @@ -144,10 +389,11 @@ sub read_updmap_file { warning("updmap: unknown setting for $a: $b, ignored!\n"); } } elsif ($a eq "Map" || $a eq "MixedMap") { - if (defined($data{'maps'}{$b}) && $data{'maps'}{$b} ne $a) { + if (defined($data{'maps'}{$b}) && $data{'maps'}{$b}{'type'} ne $a) { warning("updmap: double mentioning of $b with conflicting types in $fn\n"); } else { - $data{'maps'}{$b} = $a; + $data{'maps'}{$b}{'type'} = $a; + $data{'maps'}{$b}{'status'} = 'enabled'; } } else { warning("updmap: unrecognized line $i in $fn: $_\n"); @@ -167,11 +413,11 @@ sub read_map_files { for my $m (keys %{$data->{'updmap'}{$f}{'maps'}}) { # we do not read a map file multiple times, if $data{'maps'}{$m} is # defined we expect that it was read and do skip it - next if defined($data->{'maps'}{$m}); + next if defined($data->{'maps'}{$m}{'fonts'}); my $ret = read_map_file($m); if (defined($ret)) { for my $font (keys %$ret) { - $data->{'maps'}{$m}{$font} = $ret->{$font}; + $data->{'maps'}{$m}{'fonts'}{$font} = $ret->{$font}; } } } @@ -197,10 +443,17 @@ sub read_map_file { } - +# +# merging the various font definitions +# sub merge_data { my $data = shift; my @l = @{$data->{'order'}}; + # + # for security clean out everything that was there + %{$data->{'merged'}} = (); + # + # first read in the settings # we read it in *reverse* order and simple fill up the combined data # thus if there are multiple definitions/settings, the one coming from # the first in the original list will win! @@ -212,6 +465,21 @@ sub merge_data { } } } + # + # now merge the data + # + for my $m (keys %{$data->{'maps'}}) { + my $origin = $data->{'maps'}{$m}{'origin'}; + next if ($data->{'updmap'}{$origin}{'maps'}{$m}{'status'} eq "disabled"); + for my $f (keys %{$data->{'maps'}{$m}{'fonts'}}) { + $data->{'merged'}{'allMaps'}{'fonts'}{$f} = + $data->{'maps'}{$m}{'fonts'}{$f}; + $data->{'merged'}{'noMixedMaps'}{'fonts'}{$f} = + $data->{'maps'}{$m}{'fonts'}{$f} + if ($data->{'updmap'}{$origin}{'maps'}{$m}{'type'} eq "Map"); + } + } + return $data; } sub warning { @@ -223,14 +491,14 @@ sub warning { # sub version { - my $ret = sprintf "%s (TeX Live, multi) version %s\n", $short_progname, $version; + my $ret = sprintf "%s (TeX Live, multi) version %s\n", $prg, $version; return $ret; } sub help { my $usage = <<"EOF"; -Usage: $short_progname [OPTION] ... [COMMAND] - or: $short_progname-sys [OPTION] ... [COMMAND] +Usage: $prg [OPTION] ... [COMMAND] + or: $prg-sys [OPTION] ... [COMMAND] Update the default font map files used by pdftex, dvips, and dvipdfm(x), as determined by the configuration file updmap.cfg (the one returned by -- cgit v1.2.3