From ddcc0620fff468b40381749690f0a5d14ff7178d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Thu, 25 Aug 2011 17:24:11 +0000 Subject: fully functional version of multi-updmap.pl, bugs not excluded of course ;-) git-svn-id: svn://tug.org/texlive/trunk@23689 c570f23f-e606-0410-a88d-b1316a301751 --- Master/tlpkg/dev/multi-updmap.pl | 559 +++++++++++++++++++++++++++------------ 1 file changed, 391 insertions(+), 168 deletions(-) (limited to 'Master/tlpkg/dev') diff --git a/Master/tlpkg/dev/multi-updmap.pl b/Master/tlpkg/dev/multi-updmap.pl index fd41e98cb3d..a6ba04f5e35 100644 --- a/Master/tlpkg/dev/multi-updmap.pl +++ b/Master/tlpkg/dev/multi-updmap.pl @@ -1,7 +1,6 @@ #!/usr/bin/env perl # updmap: utility to maintain map files for outline fonts. # -# # Copyright 2011 Norbert Preining # This file is licensed under the GNU General Public License version 2 # or any later version. @@ -9,15 +8,21 @@ # History: # Original shell script (C) 2002 Thomas Esser # first perl variant (C) Fabrice Popineau +# later adaptions by Reinhard Kotucha and Karl Berry # the original version where licensed under the following agreement: # Anyone may freely use, modify, and/or distribute this file, without # limitation. # # TODO: -# - implement missing functionality -# - if a font is defined in two map files, warn and use the top one +# DONE - if a font is defined in two map files, warn and use the top one +# - in syncwithtrees: if we actually disabled fonts, should we +# run mkMap afterwards? The original didn't do it AFAIR?!? # DONE - ignore texmf/web2c/updmap.cfg # DONE - sort output by map name, not font name! +# - general problem: we currently ship updmap.cfg in TEXMFSYSCONFIG +# which *overrides* TEXMFLOCAL, so local sysadmins cannot disable +# any fonts. The updmap.cfg has to me moved into TEXMFDIST/web2c/ +# and tlmgr needs to update this file from the installed fonts. my ($TEXMFROOT, $TEXMFMAIN, $TEXMFVAR); @@ -44,9 +49,6 @@ use Pod::Usage; my $prg = TeXLive::TLUtils::basename($0); -# used for testing only -use Data::Dumper; - my %opts = ( quiet => 0, nohash => 0, nomkmap => 0 ); my $alldata; my $updLSR; @@ -57,7 +59,9 @@ my @cmdline_options = ( "disable=s@", "dvipdfmoutputdir=s", "dvipsoutputdir=s", - "enable=s{1,2}", + # the following does not work, Getopt::Long looses the first + # entry in a multi setting, treat it separately in processOptions + #"enable=s{1,2}", "edit", "force", "listavailablemaps", @@ -96,12 +100,19 @@ sub main { help() if $opts{'help'}; if ($opts{'showoptions'}) { - showOptions(@{$opts{'showoptions'}}); + for my $o (@{$opts{'showoptions'}}) { + if (defined($settings{$o})) { + print "@{$settings{$o}}\n"; + } else { + print "$prg: unknown option: $o\n"; + } + } exit 0; } - # determine which config files shold be used + # determine which config files should be used # replaces the former "setupCfgFile" + # we do NOT read texmf/web2c/updmap.cfg if ($opts{'cnffile'}) { for my $f (@{$opts{'cnffile'}}) { if (! -f $f) { @@ -113,7 +124,7 @@ sub main { chomp(@all_files); my @used_files; for my $f (@all_files) { - if ($f =~ m!/texmf/web2c/updmap.cfg!) { + if ($f =~ m!$TEXMFROOT/texmf/web2c/updmap.cfg!) { warning("Ignoring $f, it is only a sample file!\n"); } else { push @used_files, $f; @@ -121,17 +132,21 @@ sub main { } @{$opts{'cnffile'}} = @used_files; } + print "$prg is using the following updmap.cfg files (in precedence order):\n"; + for my $f (@{$opts{'cnffile'}}) { + print " $f\n"; + } + read_updmap_files(@{$opts{'cnffile'}}); if ($opts{'listmaps'}) { - listMaps(); + for my $m (keys %{$alldata->{'maps'}}) { + my $origin = $alldata->{'maps'}{$m}{'origin'}; + print $alldata->{'updmap'}{$origin}{'maps'}{$m}{'type'}, " $m ", + $alldata->{'updmap'}{$origin}{'maps'}{$m}{'status'}, " in $origin\n"; + } 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'}}; @@ -139,8 +154,20 @@ sub main { $bakFile =~ s/\.cfg$/.bak/; my $changed = 0; + if ($opts{'syncwithtrees'}) { + my @missing = read_map_files(); + if (@missing) { + print "Missing map files found, disabling them in $top_config_file\n"; + for my $m (@missing) { + $changed ||= disableMap($m); + } + # the original script did not run any update of the map files here, + # should we do that? + } + exit 0; + } + my $cmd; - 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. @@ -155,14 +182,17 @@ sub main { $changed = setOptions (@{$opts{'setoption'}}); } elsif ($opts{'enable'}) { $cmd = 'enableMap'; - warning("NOT IMPLEMENTED enable!\n"); - exit 1; + for my $l (@{$opts{'enable'}}) { + $changed ||= enableMap(split('=', $l)); + } } elsif ($opts{'disable'}) { $cmd = 'disableMap'; - warning("NOT IMPLEMENTED disable!\n"); - exit 1; + for my $m (@{$opts{'disable'}}) { + $changed ||= disableMap($m); + } } + # what does this? $updLSR = &mktexupd(); $updLSR->{mustexist}(0); @@ -173,6 +203,23 @@ sub main { if (!$opts{'nomkmap'}) { setupOutputDir("dvips"); setupOutputDir("pdftex"); + my @missing = read_map_files(); + if (@missing) { + print STDERR "\nERROR: The following map file(s) couldn't be found:\n"; + for my $m (@missing) { + my $orig = $alldata->{'maps'}{$m}{'origin'}; + print STDERR "\t$m (in $orig)\n"; + } + print STDERR "\n\tDid you run mktexlsr?\n\n" . + "\tYou can disable non-existent map entries using the option\n". + "\t --syncwithtrees.\n\n"; + exit 1; + } + merge_data(); + # for inspecting the output + #use Data::Dumper; + #$Data::Dumper::Indent = 1; + #print STDERR Data::Dumper->Dump([$alldata], [qw(mapdata)]); mkMaps(); } unlink ($bakFile) if (-r $bakFile); @@ -184,18 +231,33 @@ sub main { } } +################################################################## +# +# + sub getFonts { + my ($first, @rest) = @_; + my $getall = 0; + my @maps = (); + if ($first eq "-all") { + $getall = 1; + @maps = @rest; + } else { + @maps = ($first, @rest); + } my @lines = (); - for my $m (@_) { + for my $m (@maps) { if (defined($alldata->{'maps'}{$m})) { push @lines, "% $m"; - for my $k (keys %{$alldata->{'maps'}{$m}{'fonts'}}) { - if (defined($alldata->{'maps'}{$m}{'fonts'}{$k})) { - push @lines, "$k " . $alldata->{'maps'}{$m}{'fonts'}{$k}; - } else { - print "undefined fonts for $k in $m ?!?!?\n"; + for my $k (sort keys %{$alldata->{'maps'}{$m}{'fonts'}}) { + if ($getall || $alldata->{'fonts'}{$k}{'origin'} eq $m) { + if (defined($alldata->{'maps'}{$m}{'fonts'}{$k})) { + push @lines, "$k " . $alldata->{'maps'}{$m}{'fonts'}{$k}; + } else { + print "undefined fonts for $k in $m ?!?!?\n"; + } + print LOG "$k\n"; } - print LOG "$k\n"; } } } @@ -369,7 +431,7 @@ sub transLW35 { ); my @fileURW = ( - 's/\buagd8a.pfb\b/a010015l.pfb/', + 's/\buagd8a.pfb\b/a010015l.pfb/', 's/\buagdo8a.pfb\b/a010035l.pfb/', 's/\buagk8a.pfb\b/a010013l.pfb/', 's/\buagko8a.pfb\b/a010033l.pfb/', @@ -466,15 +528,9 @@ sub transLW35 { sub mkMaps { my $logfile; - $Data::Dumper::Indent = 1; - read_map_files(); - merge_data(); - - if (! $opts{'dry-run'}) { $logfile = "$TEXMFVAR/web2c/updmap.log"; mkdirhier "$TEXMFVAR/web2c"; -print "logfile = $logfile\n"; open LOG, ">$logfile" or die "$prg: Can't open log file \"$logfile\": $!"; print LOG &version(); @@ -500,52 +556,46 @@ print "logfile = $logfile\n"; print LOG "\n"; } } - - my ($mode, $mode_origin, $dvipsPreferOutline, $dvipsPreferOutline_origin, - $dvipsDownloadBase35, $dvipsDownloadBase35_origin, - $pdftexDownloadBase14, $pdftexDownloadBase14_origin); - if (defined($alldata->{'merged'}{'setting'}{'LW35'}{'val'})) { - $mode = $alldata->{'merged'}{'setting'}{'LW35'}{'val'}; - $mode_origin = $alldata->{'merged'}{'setting'}{'LW35'}{'origin'}; - } else { - $mode = "URWkb"; - $mode_origin = "default"; - } - if (defined($alldata->{'merged'}{'setting'}{'dvipsPreferOutline'})) { - $dvipsPreferOutline = $alldata->{'merged'}{'setting'}{'dvipsPreferOutline'}{'val'}; - $dvipsPreferOutline_origin = $alldata->{'merged'}{'setting'}{'dvipsPreferOutline'}{'origin'}; - } else { - $dvipsPreferOutline = 1; - $dvipsPreferOutline_origin = "default"; - } - if (defined($alldata->{'merged'}{'setting'}{'dvipsDownloadBase35'})) { - $dvipsDownloadBase35 = $alldata->{'merged'}{'setting'}{'dvipsDownloadBase35'}{'val'}; - $dvipsDownloadBase35_origin = $alldata->{'merged'}{'setting'}{'dvipsDownloadBase35'}{'origin'}; - } else { - $dvipsDownloadBase35 = 1; - $dvipsDownloadBase35_origin = "default"; - } - if (defined($alldata->{'merged'}{'setting'}{'pdftexDownloadBase14'})) { - $pdftexDownloadBase14 = $alldata->{'merged'}{'setting'}{'pdftexDownloadBase14'}{'val'}; - $pdftexDownloadBase14_origin = $alldata->{'merged'}{'setting'}{'pdftexDownloadBase14'}{'origin'}; - } else { - $pdftexDownloadBase14 = 1; - $pdftexDownloadBase14_origin = "default"; + sub get_cfg { + my ($v, $def, $opt) = @_; + if (defined($alldata->{'merged'}{'setting'}{$v})) { + if (defined($opt) && $opt eq "-str") { + return ( $alldata->{'merged'}{'setting'}{$v}{'val'}, + $alldata->{'merged'}{'setting'}{$v}{'origin'} ); + } else { + return ( ($alldata->{'merged'}{'setting'}{$v}{'val'} eq "true" ? 1 : 0), + $alldata->{'merged'}{'setting'}{$v}{'origin'} ); + } + } else { + return ($def, "default"); + } } - &wlog ("\n$0 " + my ($mode, $mode_origin) = + get_cfg('LW35', 'URWkb', '-str'); + my ($dvipsPreferOutline, $dvipsPreferOutline_origin) = + get_cfg('dvipsPreferOutline', 1); + my ($dvipsDownloadBase35, $dvipsDownloadBase35_origin) = + get_cfg('dvipsDownloadBase35', 1); + my ($pdftexDownloadBase14, $pdftexDownloadBase14_origin) = + get_cfg('pdftexDownloadBase14', 1); + + &wlog ("\n$prg " . ($opts{'dry-run'} ? "would create" : "is creating") . " new map files" . "\nusing the following configuration:" . "\n LW35 font names : " . "$mode ($mode_origin)" . "\n prefer outlines : " - . "$dvipsPreferOutline ($dvipsPreferOutline_origin)" + . ($dvipsPreferOutline ? "true" : "false") + . " ($dvipsPreferOutline_origin)" . "\n texhash enabled : " . ($opts{'nohash'} ? "false" : "true") . "\n download standard fonts (dvips) : " - . "$dvipsDownloadBase35 ($dvipsDownloadBase35_origin)" + . ($dvipsDownloadBase35 ? "true" : "false") + . " ($dvipsDownloadBase35_origin)" . "\n download standard fonts (pdftex) : " - . "$pdftexDownloadBase14 ($pdftexDownloadBase14_origin)" + . ($pdftexDownloadBase14 ? "true" : "false" ) + . " ($pdftexDownloadBase14_origin)" . "\n\n"); &wlog ("Scanning for LW35 support files"); @@ -587,7 +637,7 @@ print "logfile = $logfile\n"; } &newline; printf " [%3d files]\n", scalar @mixedmaps - unless ($opts{'quiet'} || $opts{'dry-run'}); + unless ($opts{'quiet'} || $opts{'dry-run'}); &wlog ("Scanning for Map entries"); &newline(); @@ -602,9 +652,7 @@ print "logfile = $logfile\n"; printf " [%3d files]\n\n", scalar @notmixedmaps unless ($opts{'quiet'} || $opts{'dry-run'}); - # TODO: NOT REALLY!!! for now!! - #exit (0) if ($opts{'dry-run'}); - warn("WE SHOULD EXIT HERE IN DRY RUN MODE!") if ($opts{'dry-run'}); + exit (0) if ($opts{'dry-run'}); # Create psfonts_t1.map, psfonts_pk.map, ps2pk.map and pdftex.map: my $dvipsoutputdir = $opts{'dvipsoutputdir'}; @@ -618,35 +666,38 @@ print "logfile = $logfile\n"; "$dvipsoutputdir/ps2pk.map") { open FILE, ">$file"; print FILE "% $file:\ -% maintained by updmap[-sys].\ -% Don't change this file directly. Use updmap[-sys] instead.\ -% See the updmap documentation.\ +% maintained by updmap[-sys] (multi).\ +% Don't change this file directly. Use updmap[-sys] instead.\ +% See the updmap documentation.\ % A log of the run that created this file is available here:\ -% $logfile\ +% $logfile\ "; close FILE; } print "Generating output for ps2pk...\n" if !$opts{'quiet'}; - my @ps2pk_fonts = sort keys %{$alldata->{'maps'}{"ps2pk35.map"}{'fonts'}}; + my @ps2pk_fonts = getFonts('-all', "ps2pk35.map"); my @ps2pk_map; push @ps2pk_map, "% ps2pk35.map"; push @ps2pk_map, transLW35($mode, @ps2pk_fonts); push @ps2pk_map, getFonts(@mixedmaps); push @ps2pk_map, getFonts(@notmixedmaps); - &writeLines(">$dvipsoutputdir/ps2pk.map", @ps2pk_map); + &writeLines(">$dvipsoutputdir/ps2pk.map", + normalizeLines(@ps2pk_map)); print "Generating output for dvips...\n" if !$opts{'quiet'}; my @download35_map; push @download35_map, "% ps2pk35.map"; push @download35_map, transLW35($mode, @ps2pk_fonts); - &writeLines(">$dvipsoutputdir/download35.map", @download35_map); + &writeLines(">$dvipsoutputdir/download35.map", + normalizeLines(@download35_map)); my @builtin35_map; - my @dvips35_fonts = sort keys %{$alldata->{'maps'}{"dvips35.map"}{'fonts'}}; + my @dvips35_fonts = getFonts('-all', "dvips35.map"); push @builtin35_map, "% dvips35.map"; push @builtin35_map, transLW35($mode, @dvips35_fonts); - &writeLines(">$dvipsoutputdir/builtin35.map", @builtin35_map); + &writeLines(">$dvipsoutputdir/builtin35.map", + normalizeLines(@builtin35_map)); my @dftdvips_fonts = ($dvipsDownloadBase35 ? @ps2pk_fonts : @dvips35_fonts); @@ -661,31 +712,39 @@ print "logfile = $logfile\n"; push @psfonts_t1_map, transLW35($mode, @dftdvips_fonts); push @psfonts_t1_map, getFonts(@mixedmaps); push @psfonts_t1_map, getFonts(@notmixedmaps); - &writeLines(">$dvipsoutputdir/psfonts_t1.map", @psfonts_t1_map); + &writeLines(">$dvipsoutputdir/psfonts_t1.map", + normalizeLines(@psfonts_t1_map)); my @psfonts_pk_map; push @psfonts_pk_map, transLW35($mode, @dftdvips_fonts); push @psfonts_pk_map, getFonts(@notmixedmaps); - &writeLines(">$dvipsoutputdir/psfonts_pk.map", @psfonts_pk_map); + &writeLines(">$dvipsoutputdir/psfonts_pk.map", + normalizeLines(@psfonts_pk_map)); print "Generating output for pdftex...\n" if !$opts{'quiet'}; # remove PaintType due to Sebastian's request - my @pdftex35_fonts = sort keys %{$alldata->{'maps'}{"pdftex35.map"}{'fonts'}}; - my @pdftexmaps_ndl = transLW35($mode, @pdftex35_fonts); + my @pdftex35_fonts = getFonts('-all', "pdftex35.map"); + my @pdftexmaps_ndl; + push @pdftexmaps_ndl, "% pdftex35.map"; + push @pdftexmaps_ndl, transLW35($mode, @pdftex35_fonts); push @pdftexmaps_ndl, getFonts(@mixedmaps); push @pdftexmaps_ndl, getFonts(@notmixedmaps); - @pdftexmaps_ndl = grep { $_ !~ m/(^%|PaintType)/ } @pdftexmaps_ndl; + @pdftexmaps_ndl = grep { $_ !~ m/(^%\|PaintType)/ } @pdftexmaps_ndl; - my @pdftexmaps_dl = transLW35($mode, @ps2pk_fonts); + my @pdftexmaps_dl; + push @pdftexmaps_dl, "% ps2pk35.map"; + push @pdftexmaps_dl, transLW35($mode, @ps2pk_fonts); push @pdftexmaps_dl, getFonts(@mixedmaps); push @pdftexmaps_dl, getFonts(@notmixedmaps); - @pdftexmaps_dl = grep { $_ !~ m/(^%|PaintType)/ } @pdftexmaps_dl; + @pdftexmaps_dl = grep { $_ !~ m/(^%\|PaintType)/ } @pdftexmaps_dl; my @pdftex_ndl14_map = @pdftexmaps_ndl; + @pdftex_ndl14_map = &normalizeLines(@pdftex_ndl14_map); @pdftex_ndl14_map = &to_pdftex(@pdftex_ndl14_map); &writeLines(">$pdftexoutputdir/pdftex_ndl14.map", @pdftex_ndl14_map); my @pdftex_dl14_map = @pdftexmaps_dl; + @pdftex_dl14_map = &normalizeLines(@pdftex_dl14_map); @pdftex_dl14_map = &to_pdftex(@pdftex_dl14_map); &writeLines(">$pdftexoutputdir/pdftex_dl14.map", @pdftex_dl14_map); @@ -735,10 +794,9 @@ print "logfile = $logfile\n"; close LOG; print "\nTranscript written on \"$logfile\".\n" if !$opts{'quiet'}; - # warning("NOT IMPLEMENTED mkMaps ... dumping data structure for now!\n"); - #print STDERR Data::Dumper->Dump([$alldata], [qw(mapdata)]); } + sub locateMap { my $map = shift; my $ret = `kpsewhich --format=map $map`; @@ -750,7 +808,9 @@ 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 + my @enable; + GetOptions("setoption=s{1,2}" => \@setoptions, + "enable=s{1,2}" => \@enable) or die "Try \"$prg --help\" for more information.\n"; Getopt::Long::Configure($oldconfig); @@ -770,6 +830,22 @@ sub processOptions { if (@realset) { @{$opts{'setoption'}} = @realset; } + my @realenable; + while (@enable) { + my $t = shift @enable; + if ($t =~ m/=/) { + push @realenable, $t; + } else { + my $tt = shift @enable; + die "Try \"$prg --help\" for more information.\n" + if !defined($tt); + push @realenable, "$t=$tt"; + } + } + if (@realenable) { + @{$opts{'enable'}} = @realenable; + } + # now continue with normal option handling @@ -818,6 +894,79 @@ sub setOptions { return save_updmap($alldata->{'top_config'}); } +sub enableMap { + my ($type, $map) = @_; + + my $tc = $alldata->{'top_config'}; + + die "$prg: invalid mapType $type" if ($type !~ m/^(Map|MixedMap)$/); + die "$prg: top config file $tc has not been read." + if (!defined($alldata->{'updmap'}{$tc})); + + if (defined($alldata->{'updmap'}{$tc}{'maps'}{$map})) { + # the map data has already been read in, no special precautions necessary + if (($alldata->{'updmap'}{$tc}{'maps'}{$map}{'status'} eq "enabled") && + ($alldata->{'updmap'}{$tc}{'maps'}{$map}{'type'} eq $type)) { + # nothing to do here ... be happy! + return 0; + } else { + $alldata->{'updmap'}{$tc}{'maps'}{$map}{'status'} = "enabled"; + $alldata->{'updmap'}{$tc}{'maps'}{$map}{'type'} = $type; + $alldata->{'maps'}{$map}{'origin'} = $tc; + $alldata->{'updmap'}{$tc}{'changed'} = 1; + return save_updmap($tc); + } + } else { + # add a new map file! + $alldata->{'updmap'}{$tc}{'maps'}{$map}{'type'} = $type; + $alldata->{'updmap'}{$tc}{'maps'}{$map}{'status'} = "enabled"; + $alldata->{'updmap'}{$tc}{'maps'}{$map}{'line'} = -1; + $alldata->{'updmap'}{$tc}{'changed'} = 1; + $alldata->{'maps'}{$map}{'origin'} = $tc; + return save_updmap($tc); + } +} + +sub disableMap { + my $map = shift; + + my $tc = $alldata->{'top_config'}; + + die "$prg: top config file $tc has not been read." + if (!defined($alldata->{'updmap'}{$tc})); + + if (defined($alldata->{'updmap'}{$tc}{'maps'}{$map})) { + # the map data has already been read in, no special precautions necessary + if ($alldata->{'updmap'}{$tc}{'maps'}{$map}{'status'} eq "disabled") { + # nothing to do here ... be happy! + return 0; + } else { + $alldata->{'updmap'}{$tc}{'maps'}{$map}{'status'} = "disabled"; + $alldata->{'updmap'}{$tc}{'changed'} = 1; + return save_updmap($tc); + } + } else { + # disable a Map type that might be activated in a lower ranked updmap.cfg + if (!defined($alldata->{'maps'}{$map})) { + warning("Map is not present anywhere, why should I disable it?\n"); + return 0; + } + my $orig = $alldata->{'maps'}{$map}{'origin'}; + # add a new entry to the top level where we disable it + # copy over the type from the last entry + $alldata->{'updmap'}{$tc}{'maps'}{$map}{'type'} = + $alldata->{'updmap'}{$orig}{'maps'}{$map}{'type'}; + $alldata->{'updmap'}{$tc}{'maps'}{$map}{'status'} = "enabled"; + $alldata->{'updmap'}{$tc}{'maps'}{$map}{'line'} = -1; + # rewrite the origin + $alldata->{'maps'}{$map}{'origin'} = $tc; + # go on for writing + $alldata->{'updmap'}{$tc}{'changed'} = 1; + return save_updmap($tc); + } +} + + # returns 1 if actually saved due to changes sub save_updmap { my $fn = shift; @@ -887,28 +1036,21 @@ sub save_updmap { sub setOption { my ($opt, $val) = @_; - if ($opt eq "LW35") { - if ($val !~ m/^(URWkb|URW|ADOBE|ADOBEkb)$/) { - die "$0: Invalid value $val for option $opt.\n"; - } - } elsif ($opt =~ -m/^(dvipsPreferOutline|dvipsDownloadBase35|(pdftex|dvipdfm)DownloadBase14)$/) { - if ($val !~ m/^(true|false)$/) { - die "$0: Invalid value $val for option $opt; should be \"true\" or \"false\".\n"; - } - } else { - die "$0: Unsupported option $opt.\n"; - } + die "$prg: Unsupported option $opt." if (!defined($settings{$opt})); + die "$0: Invalid value $val for option $opt." + if (!member($val, @{$settings{$opt}})); # silently accept this old option name, just in case. return if $opt eq "dvipdfmDownloadBase14"; #print "Setting option $opt to $val...\n" if !$opts{'quiet'}; my $tc = $alldata->{'top_config'}; - if (!defined($alldata->{'updmap'}{$tc})) { - die "$prg: top config file $tc has not been read."; - } + + die "$prg: top config file $tc has not been read." + if (!defined($alldata->{'updmap'}{$tc})); + if (defined($alldata->{'updmap'}{$tc}{'setting'}{$opt}{'val'})) { + # the value is already set, do nothing if ($alldata->{'updmap'}{$tc}{'setting'}{$opt}{'val'} eq $val) { return; } @@ -922,42 +1064,6 @@ m/^(dvipsPreferOutline|dvipsDownloadBase35|(pdftex|dvipdfm)DownloadBase14)$/) { } -############################################################################# -# 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 { - read_updmap_files(@{$opts{'cnffile'}}); - for my $m (keys %{$alldata->{'maps'}}) { - my $origin = $alldata->{'maps'}{$m}{'origin'}; - print $alldata->{'updmap'}{$origin}{'maps'}{$m}{'type'}, " $m ", - $alldata->{'updmap'}{$origin}{'maps'}{$m}{'status'}, " in $origin\n"; - } -} - ############################################################################### # copyFile() # copy file $src to $dst, sets $dst creation and mod time @@ -1022,6 +1128,31 @@ sub equalize_file { return join('X', sort(@temp)); } +############################################################################### +# normalizeLines() +# not the original function, we want it to keep comments, that are +# anyway only the file names we are adding! +# whitespace is exactly one space, no empty lines, +# no whitespace at end of line, one space before and after " +# +sub normalizeLines { + my @lines = @_; + my %count = (); + + # @lines = grep { $_ !~ m/^[*#;%]/ } @lines; + map {$_ =~ s/\s+/ /gx } @lines; + @lines = grep { $_ !~ m/^\s*$/x } @lines; + map { $_ =~ s/\s$//x ; + $_ =~ s/\s*\"\s*/ \" /gx; + $_ =~ s/\" ([^\"]*) \"/\"$1\"/gx; + } @lines; + + # @lines = grep {++$count{$_} < 2 } (sort @lines); + @lines = grep {++$count{$_} < 2 } (@lines); + + return @lines; +} + ################################################################# # @@ -1044,9 +1175,11 @@ sub equalize_file { # = 'enabled'|'disabled' # $alldata->{'updmap'}{$full_path_name_of_updmap}{'maps'}{$mapname}{'line'} = $i # $alldata->{'maps'}{$m}{'origin'} = $updmap_path_name +# $alldata->{'maps'}{$m}{'status'} = enabled | disabled # # initialized by read_map_files -# $alldata->{'maps'}{$m}{'fonts'}{$font} = $rest +# $alldata->{'maps'}{$m}{'fonts'}{$font} = $definition +# $alldata->{'fonts'}{$f}{'origin'} = $map # # initialized by merge_data # $alldata->{'merged'}{'setting'}{$key}{'val'} = $val @@ -1085,6 +1218,7 @@ sub read_updmap_files { if (defined($alldata->{'updmap'}{$l}{'maps'})) { for my $m (keys %{$alldata->{'updmap'}{$l}{'maps'}}) { $alldata->{'maps'}{$m}{'origin'} = $l; + $alldata->{'maps'}{$m}{'status'} = $alldata->{'updmap'}{$l}{'maps'}{$m}{'status'}; } } } @@ -1158,39 +1292,89 @@ sub read_updmap_file { sub read_map_files { if (!defined($alldata->{'updmap'})) { - return $alldata; + return; } - for my $f (keys %{$alldata->{'updmap'}}) { + my @missing; + my @l = @{$alldata->{'order'}}; + # first collect all the map files we are interested in + # and determine whether they exist, and get their full path + my @maps; + for my $f (@l) { next if !defined($alldata->{'updmap'}{$f}{'maps'}); - my @maps = keys %{$alldata->{'updmap'}{$f}{'maps'}}; - push @maps, qw/dvips35.map pdftex35.map ps2pk35.map/; - my @fullpath = `kpsewhich --format=map @maps`; - chomp @fullpath; - my @missing; - foreach my $map (@maps) { - my ($ff) = grep /\/$map(\.map)?$/, @fullpath; - if (! $ff) { - push @missing, $map; - } else { - $alldata->{'maps'}{$map}{'fullpath'} = $ff; - } + for my $m (keys %{$alldata->{'updmap'}{$f}{'maps'}}) { + # only read a map file if its final status is enabled! + push @maps, $m if ($alldata->{'maps'}{$m}{'status'} eq 'enabled'); + } + } + for my $m (qw/dvips35.map pdftex35.map ps2pk35.map/) { + push @maps, $m; + $alldata->{'maps'}{$m}{'status'} = 'enabled'; + } + @maps = TeXLive::TLUtils::sort_uniq(@maps); + my @fullpath = `kpsewhich --format=map @maps`; + chomp @fullpath; + foreach my $map (@maps) { + my ($ff) = grep /\/$map(\.map)?$/, @fullpath; + if ($ff) { + $alldata->{'maps'}{$map}{'fullpath'} = $ff; + } else { + # if the map file is not found, then push it onto the list of + # missing map files, since we know that it is enabled + push @missing, $map; } + } + + # + # read in the three basic fonts definition maps + for my $m (qw/dvips35.map pdftex35.map ps2pk35.map/) { + my $ret = read_map_file($alldata->{'maps'}{$m}{'fullpath'}); + my @ff = (); + for my $font (keys %$ret) { + $alldata->{'fonts'}{$font}{'origin'} = $m; + $alldata->{'maps'}{$m}{'fonts'}{$font} = $ret->{$font}; + } + } + # we read the updmap in reverse directions, since we + # replace the origin field of font definition always with the + # top one + for my $f (reverse @l) { + my @maps = keys %{$alldata->{'updmap'}{$f}{'maps'}}; for my $m (@maps) { # we do not read a map file multiple times, if $alldata{'maps'}{$m} is # defined we expect that it was read and do skip it next if defined($alldata->{'maps'}{$m}{'fonts'}); + # we do not read a map files content if it is disabled + next if ($alldata->{'maps'}{$m}{'status'} eq 'disabled'); if (!defined($alldata->{'maps'}{$m}{'fullpath'})) { - print "cannot find full path for $m?!?!\n"; + # we have already pushed these map files onto the list of missing + # map files, so do nothing here next; } my $ret = read_map_file($alldata->{'maps'}{$m}{'fullpath'}); if (defined($ret)) { for my $font (keys %$ret) { + if (defined($alldata->{'fonts'}{$font})) { + # we got another definition, warn on that + # if the origin is not defined by now, the font is defined + # multiple times in the same map file, otherwise it is + # defined in another map file already + if (defined($alldata->{'fonts'}{$font}{'origin'})) { + my $fontorig = $alldata->{'fonts'}{$font}{'origin'}; + my $maporig = $alldata->{'maps'}{$fontorig}{'origin'}; + warning("$prg: font $font is defined multiple times:\n"); + warning("$prg: $fontorig (from $maporig)\n"); + warning("$prg: $m (from $f) (used)\n"); + } else { + warning("$prg: font $font is multiply defined in $m, using an arbitrary instance!\n"); + } + } + $alldata->{'fonts'}{$font}{'origin'} = $m; $alldata->{'maps'}{$m}{'fonts'}{$font} = $ret->{$font}; } } } } + return (@missing); } sub read_map_file { @@ -1245,11 +1429,14 @@ sub merge_data { next if !defined($origin); next if ($alldata->{'updmap'}{$origin}{'maps'}{$m}{'status'} eq "disabled"); for my $f (keys %{$alldata->{'maps'}{$m}{'fonts'}}) { - $alldata->{'merged'}{'allMaps'}{'fonts'}{$f} = - $alldata->{'maps'}{$m}{'fonts'}{$f}; - $alldata->{'merged'}{'noMixedMaps'}{'fonts'}{$f} = - $alldata->{'maps'}{$m}{'fonts'}{$f} - if ($alldata->{'updmap'}{$origin}{'maps'}{$m}{'type'} eq "Map"); + # use the font definition only for those fonts where the origin matches + if ($alldata->{'fonts'}{$f}{'origin'} eq $m) { + $alldata->{'merged'}{'allMaps'}{'fonts'}{$f} = + $alldata->{'maps'}{$m}{'fonts'}{$f}; + $alldata->{'merged'}{'noMixedMaps'}{'fonts'}{$f} = + $alldata->{'maps'}{$m}{'fonts'}{$f} + if ($alldata->{'updmap'}{$origin}{'maps'}{$m}{'type'} eq "Map"); + } } } } @@ -1283,7 +1470,9 @@ fonts are included in the output. By default, the TeX filename database (ls-R) is also updated. Options: - --cnffile FILE read FILE for the updmap configuration + --cnffile FILE read FILE for the updmap configuration + (can be given multiple times, in which case + all the files are used) --dvipsoutputdir DIR specify output directory (dvips syntax) --pdftexoutputdir DIR specify output directory (pdftex syntax) --outputdir DIR specify output directory (for all files) @@ -1341,8 +1530,42 @@ Explanation of the --setoption possibilities: Explanation of trees and files normally used: - updmap both reads and writes TEXMFCONFIG/web2c/updmap.cfg, according to - the actions specified. + updmap reads all the updmap.cfg found by + kpsewhich -all updmap.cfg + or those given on the command line with --cnffile. + According to the actions it might write to the so called "top level" + updmap.cfg file. This "top level" file is either the *first* one given + on the command line, or the first one found with kpsewhich -all updmap.cfg. + + If multiple updmap.cfg files are found, all the map files mentioned + in all the updmap.cfg files are merged. + + CAVEATS with multiple updmap.cfg files + * multiple font definitions + If a font is defined multiple times in different maps, then the + definition of the map file that comes from the highest priority + updmap.cfg file is used. + If a font is defined multiple times in the same map file, an + arbitrary definition is used. + In both cases warnings are issued. + + * disabling map files + updmap.cfg files with higher priority can disable map files that + are mentioned in lower priority updmap.cfg files by disabling + them, i.e., writing + \#! Map mapname.map + or + \#! MixedMap mapname.map + into the higher prioprity updmap.cfg file. + + As an example take a user with a copy of the commercial MTPRO fonts. + He wants to disable the belleek version of the fonts, that is + disable the map belleek.map. The user should create a updmap.cfg file + in \$TEXMFCONFIG/web2c/updmap.cfg with the content + #! Map belleek.map + Map mt-plus.map + Map mt-yy.map + and call $prg. updmap writes the map files for dvips (psfonts.map) and pdftex (pdftex.map) to the TEXMFVAR/fonts/map/updmap/{dvips,pdftex}/ -- cgit v1.2.3