#!/bin/sh

###############################################################################
# updmap: utility to maintain map files for outline fonts.
#
# Thomas Esser, (C) 2002. Public domain.
# Usage: updmap [option] ... [command]
#
# Valid options:
#   --cnffile file             specify configuration file
#   --outputdir directory      specify output directory
#   --nohash                   do not run texhash
#   --nomkmap                  do not recreate map files
#   --quiet                    reduce verbosity
#
# Valid commands:
#   --edit                     edit $cnfFileShort file
#   --help                     show this message
#   --showoptions item         show alternatives for options
#   --setoption option value   set option where option is one
#                              of dvipsPreferOutline, LW35, dvipsDownloadBase35
#                              or pdftexDownloadBase14
#   --enable maptype mapfile   add or enable a Map or MixedMap
#   --disable mapfile          disable Map or MixedMap for mapfile
#   --listmaps                 list all active and inactive maps
#
###############################################################################

###############################################################################
# program history:
#   Mon Jan 27 22:38:44 CET 2003
#      don't call a function before processOptions; we may loose our
#      argument list with some broken shells
#   Mon Jan 27 06:55:28 CET 2003
#      fix unportable egrep / sed
#   Sat Jan 18 10:10:26 CET 2003
#      use $tmp8 in dvips2dvipdfm()
#   Thu Jan  2 23:14:34 CET 2003
#      add umask 022, so generated files are always world-readable
#   Sun Oct 27 11:33:04 CET 2002
#      write output in normalized format
#      add support for dvipdfm
#   Mon Sep 22 19:18:57 CEST 2002
#      fix typo: buildin -> builtin
#   Mon Sep  2 19:18:57 CEST 2002
#      fix condensed <-> narrow mapping
#   Sun Sep  1 15:02:28 CEST 2002
#      add dvipsDownloadBase35 / pdftexDownloadBase14 options
#   Wed May 22 20:00:13 CEST 2002
#      listmaps option added by Gerben Wierda
#   Tue May 21 05:27:37 CEST 2002
#      now removing map files before rewriting them; fixes permission problems
#   Tue May 21 05:05:34 CEST 2002:
#      cli options added: showoptions, setoption, enable, disable, nomkmap
#      now even more verbose; now reporting non-existing map files
#      fixing trap for MAC OS/X compatibility
#   Fri May 17 22:38:37 CEST 2002:
#      rewritten from teTeX-1.0 version; Completely new designed.
###############################################################################

test -f /bin/sh5 && test -z "$RUNNING_SH5" \
  && { UNAMES=`uname -s`; test "x$UNAMES" = xULTRIX; } 2>/dev/null \
  && { RUNNING_SH5=true; export RUNNING_SH5; exec /bin/sh5 $0 ${1+"$@"}; }
unset RUNNING_SH5

test -f /bin/bsh && test -z "$RUNNING_BSH" \
  && { UNAMES=`uname -s`; test "x$UNAMES" = xAIX; } 2>/dev/null \
  && { RUNNING_BSH=true; export RUNNING_BSH; exec /bin/bsh $0 ${1+"$@"}; }
unset RUNNING_BSH

# hack around a bug in zsh:
test -n "${ZSH_VERSION+set}" && alias -g '${1+"$@"}'='"$@"'

version=2.0

###############################################################################
# help()
#   display help message and exit
###############################################################################
help()
{
  cat <<eof
Usage: updmap [option] ... [command]

Valid options:
  --cnffile file             specify configuration file
  --outputdir directory      specify output directory
  --nohash                   do not run texhash
  --nomkmap                  do not recreate map files
  --quiet                    reduce verbosity

Valid commands:
  --edit                     edit $cnfFileShort file
  --help                     show this message
  --showoptions item         show alternatives for options
  --setoption option value   set option where option is one
                             of dvipsPreferOutline, LW35, dvipsDownloadBase35
                             or pdftexDownloadBase14
  --enable maptype mapfile   add or enable a Map or MixedMap
  --disable mapfile          disable Map or MixedMap for mapfile
  --listmaps                 list all active and inactive maps
eof
  exit
}

###############################################################################
# verboseMsg(msg)
#   print `msg' to stderr is $verbose is true
###############################################################################
verboseMsg() { $verbose && echo ${1+"$@"} >&2; }

###############################################################################
# warn(msg)
#   print `msg' to stderr
###############################################################################
warn()
{
  echo "$progname: $1." >&2
}

###############################################################################
# abort(errmsg)
#   print `errmsg' to stderr and exit with error code 1
###############################################################################
abort()
{
  echo "$progname: $1." >&2
  false  # some systems need this to set nonzero $?
  cleanup
  exit 1
}

###############################################################################
# cfgval(variable)
#   read variable ($1) from config file
###############################################################################
cfgval()
{
  cat $cnfFile | sed -n 's/^'"$1"'[	 =][	 =]*//p' | tail -1
}

###############################################################################
# setupSymlinks()
#   set symlink for psfonts.map according to dvipsPreferOutline variable
###############################################################################
setupSymlinks()
{
  rm -f $outputdir/psfonts.map
  if test "x$dvipsPreferOutline" = xtrue; then
    ln -s psfonts_t1.map $outputdir/psfonts.map
  else
    ln -s psfonts_pk.map $outputdir/psfonts.map
  fi

  rm -f $outputdir/pdftex.map
  if test "x$pdftexDownloadBase14" = xtrue; then
    ln -s pdftex_dl14.map $outputdir/pdftex.map
  else
    ln -s pdftex_ndl14.map $outputdir/pdftex.map
  fi
  rm -f $outputdir/dvipdfm.map
  if test "x$dvipdfmDownloadBase14" = xtrue; then
    ln -s dvipdfm_dl14.map $outputdir/dvipdfm.map
  else
    ln -s dvipdfm_ndl14.map $outputdir/dvipdfm.map
  fi
}

###############################################################################
# transLW35(args ...)
#   transform fontname and filenames according to transformation specified
#   by mode
###############################################################################
transLW35()
{
  case $mode in
    ""|URWkb)
      cat ${1+"$@"}
      ;;
    URW)
      fileURW ${1+"$@"}
      ;;
    ADOBE|ADOBEkb)
      psADOBE ${1+"$@"} | file$mode
      ;;
  esac  
}

###############################################################################
# catMaps(regex)
#   filter config file by regex for map lines and extract the map filenames.
#   These are then looked up (by kpsewhich in locateMap) and the content of
#   all map files is send to stdout.
###############################################################################
catMaps()
{
  egrep "$1" $cnfFile \
    | sed 's@#.*@@' \
       | awk '{print $2}' \
       | sort \
       | uniq \
       | grep . > $tmp4

  while read map; do
    file=`locateMap "$map"`

    # output the file; also output a newline, because the final newline
    # might be missing in the map file; Empty lines are filtered out later,
    # so it does not really hurt do do this here.
    test -n "$file" && { cat "$file"; echo; }
  done < $tmp4
}

###############################################################################
# configReplace(file, pattern, line)
#   The first line in file that matches pattern gets replaced by line.
#   line will be added at the end of the file if pattern does not match.
###############################################################################
configReplace()
{
  file=$1; pat=$2; line=$3

  if grep "$pat" "$file" >/dev/null; then
    ed "$file" >/dev/null 2>&1 <<-eof
	/$pat/
	c
	$line
	.
	w
	q
eof
  else
    echo "$line" >> $file
  fi
}

###############################################################################
# setOption (option, value)
#   sets option to value in the config file (replacing the existing setting
#   or by adding a new line to the config file).
###############################################################################
setOption()
{
  opt=$1
  val=$2
  case "$opt" in
    LW35)
      case "$val" in
        URWkb|URW|ADOBE|ADOBEkb)
          ;;
        *)
          abort "invalid value $val for option $opt"
          ;;
      esac
      ;;
    dvipsPreferOutline|dvipsDownloadBase35|pdftexDownloadBase14|dvipdfmDownloadBase14)
      case "$val" in
        true|false)
          ;;
        *)
          abort "invalid value $val for option $opt"
      esac
      ;;
    *)
      abort "unsupported option $opt"
      ;;
  esac

  configReplace "$cnfFile" "^$opt[ 	]" "$opt $val"
}

###############################################################################
# DebianMapWarn
#   Warn that --enable and --disable do not work permanently in Debian
###############################################################################
DebianMapWarn(){
  # we will be called recursively (enableMap calls disableMap)
  test $DebianWarnShown = true && return 0

  # if the user has choosen to manually manage updmap.cfg, we shouldn't do
  # anything.  To find out, we check whether /var/lib/texmf/web2c/updmap.cfg
  # is a symlink.  Test needs the full path because the builtin might not 
  # understand -L
  /usr/bin/test -L /var/lib/texmf/web2c/updmap.cfg && return 0

  warn "The options --enable and --disable work differently on Debian systems!"
  warn ""
  warn "You cannot use them to permanently enable or disable Map files. Instead,"
  warn "you have to use the mechanism described in"
  warn "/usr/share/doc/tetex-bin/README.Debian.gz"
  warn ""
  warn "If you don't know which lines to add to the files in /etc/texmf/updmap.d/,"
  warn "press ENTER now and take the resulting line from"
  warn "/var/lib/texmf/web2c/updmap.cfg"
  warn ""
  warn "Press ENTER to continue anyway, or Ctrl-c to quit."
  read

  DebianWarnShown=true
  return 0
} 

###############################################################################
# enableMap (type, map)
#   enables an entry in the config file for map with a given type.
###############################################################################
enableMap()
{
  case $1 in
    Map|MixedMap)
      ;;
    *)
      abort "invalid mapType $1"
      ;;
  esac
  DebianMapWarn

  # a map can only have one type, so we carefully disable everything
  # about map here:
  disableMap "$2"

  # now enable with the right type:
  configReplace "$cnfFile" "^#![ 	]*$1[ 	]*$2" "$1 $2"
}

###############################################################################
# disableMap (map)
#   disables map in config file (any type)
###############################################################################
disableMap()
{
  DebianMapWarn
  mapType=`awk '($1 == "MixedMap" || $1 == "Map") && $2 == map { print $1 }' \
             map=$1 <"$cnfFile" | sort | uniq`
  for type in $mapType; do
    configReplace "$cnfFile" "^$type[ 	]*$1" "#! $type $1"
  done
}

###############################################################################
# psADOBE()
#   transform fontnames from URW to Adobe
###############################################################################
psADOBE()
{
  sed \
    -e 's/ URWGothicL-Demi / AvantGarde-Demi /' \
    -e 's/ URWGothicL-DemiObli / AvantGarde-DemiOblique /' \
    -e 's/ URWGothicL-Book / AvantGarde-Book /' \
    -e 's/ URWGothicL-BookObli / AvantGarde-BookOblique /' \
    -e 's/ URWBookmanL-DemiBold / Bookman-Demi /' \
    -e 's/ URWBookmanL-DemiBoldItal / Bookman-DemiItalic /' \
    -e 's/ URWBookmanL-Ligh / Bookman-Light /' \
    -e 's/ URWBookmanL-LighItal / Bookman-LightItalic /' \
    -e 's/ NimbusMonL-Bold / Courier-Bold /' \
    -e 's/ NimbusMonL-BoldObli / Courier-BoldOblique /' \
    -e 's/ NimbusMonL-Regu / Courier /' \
    -e 's/ NimbusMonL-ReguObli / Courier-Oblique /' \
    -e 's/ NimbusSanL-Bold / Helvetica-Bold /' \
    -e 's/ NimbusSanL-BoldCond / Helvetica-Narrow-Bold /' \
    -e 's/ NimbusSanL-BoldItal / Helvetica-BoldOblique /' \
    -e 's/ NimbusSanL-BoldCondItal / Helvetica-Narrow-BoldOblique /' \
    -e 's/ NimbusSanL-Regu / Helvetica /' \
    -e 's/ NimbusSanL-ReguCond / Helvetica-Narrow /' \
    -e 's/ NimbusSanL-ReguItal / Helvetica-Oblique /' \
    -e 's/ NimbusSanL-ReguCondItal / Helvetica-Narrow-Oblique /' \
    -e 's/ CenturySchL-Bold / NewCenturySchlbk-Bold /' \
    -e 's/ CenturySchL-BoldItal / NewCenturySchlbk-BoldItalic /' \
    -e 's/ CenturySchL-Roma / NewCenturySchlbk-Roman /' \
    -e 's/ CenturySchL-Ital / NewCenturySchlbk-Italic /' \
    -e 's/ URWPalladioL-Bold / Palatino-Bold /' \
    -e 's/ URWPalladioL-BoldItal / Palatino-BoldItalic /' \
    -e 's/ URWPalladioL-Roma / Palatino-Roman /' \
    -e 's/ URWPalladioL-Ital / Palatino-Italic /' \
    -e 's/ StandardSymL / Symbol /' \
    -e 's/ NimbusRomNo9L-Medi / Times-Bold /' \
    -e 's/ NimbusRomNo9L-MediItal / Times-BoldItalic /' \
    -e 's/ NimbusRomNo9L-Regu / Times-Roman /' \
    -e 's/ NimbusRomNo9L-ReguItal / Times-Italic /' \
    -e 's/ URWChanceryL-MediItal / ZapfChancery-MediumItalic /' \
    -e 's/ Dingbats / ZapfDingbats /' \
    ${1+"$@"}
}

###############################################################################
# fileADOBEkb()
#   transform filenames from URW to ADOBE (both berry names)
###############################################################################
fileADOBEkb()
{
  sed \
    -e 's/\([^A-Za-z]\)uagd8a.pfb/\1pagd8a.pfb/' \
    -e 's/\([^A-Za-z]\)uagdo8a.pfb/\1pagdo8a.pfb/' \
    -e 's/\([^A-Za-z]\)uagk8a.pfb/\1pagk8a.pfb/' \
    -e 's/\([^A-Za-z]\)uagko8a.pfb/\1pagko8a.pfb/' \
    -e 's/\([^A-Za-z]\)ubkd8a.pfb/\1pbkd8a.pfb/' \
    -e 's/\([^A-Za-z]\)ubkdi8a.pfb/\1pbkdi8a.pfb/' \
    -e 's/\([^A-Za-z]\)ubkl8a.pfb/\1pbkl8a.pfb/' \
    -e 's/\([^A-Za-z]\)ubkli8a.pfb/\1pbkli8a.pfb/' \
    -e 's/\([^A-Za-z]\)ucrb8a.pfb/\1pcrb8a.pfb/' \
    -e 's/\([^A-Za-z]\)ucrbo8a.pfb/\1pcrbo8a.pfb/' \
    -e 's/\([^A-Za-z]\)ucrr8a.pfb/\1pcrr8a.pfb/' \
    -e 's/\([^A-Za-z]\)ucrro8a.pfb/\1pcrro8a.pfb/' \
    -e 's/\([^A-Za-z]\)uhvb8a.pfb/\1phvb8a.pfb/' \
    -e 's/\([^A-Za-z]\)uhvb8ac.pfb/\1phvb8an.pfb/' \
    -e 's/\([^A-Za-z]\)uhvbo8a.pfb/\1phvbo8a.pfb/' \
    -e 's/\([^A-Za-z]\)uhvbo8ac.pfb/\1phvbo8an.pfb/' \
    -e 's/\([^A-Za-z]\)uhvr8a.pfb/\1phvr8a.pfb/' \
    -e 's/\([^A-Za-z]\)uhvr8ac.pfb/\1phvr8an.pfb/' \
    -e 's/\([^A-Za-z]\)uhvro8a.pfb/\1phvro8a.pfb/' \
    -e 's/\([^A-Za-z]\)uhvro8ac.pfb/\1phvro8an.pfb/' \
    -e 's/\([^A-Za-z]\)uncb8a.pfb/\1pncb8a.pfb/' \
    -e 's/\([^A-Za-z]\)uncbi8a.pfb/\1pncbi8a.pfb/' \
    -e 's/\([^A-Za-z]\)uncr8a.pfb/\1pncr8a.pfb/' \
    -e 's/\([^A-Za-z]\)uncri8a.pfb/\1pncri8a.pfb/' \
    -e 's/\([^A-Za-z]\)uplb8a.pfb/\1pplb8a.pfb/' \
    -e 's/\([^A-Za-z]\)uplbi8a.pfb/\1pplbi8a.pfb/' \
    -e 's/\([^A-Za-z]\)uplr8a.pfb/\1pplr8a.pfb/' \
    -e 's/\([^A-Za-z]\)uplri8a.pfb/\1pplri8a.pfb/' \
    -e 's/\([^A-Za-z]\)usyr.pfb/\1psyr.pfb/' \
    -e 's/\([^A-Za-z]\)utmb8a.pfb/\1ptmb8a.pfb/' \
    -e 's/\([^A-Za-z]\)utmbi8a.pfb/\1ptmbi8a.pfb/' \
    -e 's/\([^A-Za-z]\)utmr8a.pfb/\1ptmr8a.pfb/' \
    -e 's/\([^A-Za-z]\)utmri8a.pfb/\1ptmri8a.pfb/' \
    -e 's/\([^A-Za-z]\)uzcmi8a.pfb/\1pzcmi8a.pfb/' \
    -e 's/\([^A-Za-z]\)uzdr.pfb/\1pzdr.pfb/' \
    ${1+"$@"}
}

###############################################################################
# fileURW()
#   transform filenames from URWkb (berry names) to URW (vendor names)
###############################################################################
fileURW()
{
  sed \
    -e 's/\([^A-Za-z]\)uagd8a.pfb/\1a010015l.pfb/' \
    -e 's/\([^A-Za-z]\)uagdo8a.pfb/\1a010035l.pfb/' \
    -e 's/\([^A-Za-z]\)uagk8a.pfb/\1a010013l.pfb/' \
    -e 's/\([^A-Za-z]\)uagko8a.pfb/\1a010033l.pfb/' \
    -e 's/\([^A-Za-z]\)ubkd8a.pfb/\1b018015l.pfb/' \
    -e 's/\([^A-Za-z]\)ubkdi8a.pfb/\1b018035l.pfb/' \
    -e 's/\([^A-Za-z]\)ubkl8a.pfb/\1b018012l.pfb/' \
    -e 's/\([^A-Za-z]\)ubkli8a.pfb/\1b018032l.pfb/' \
    -e 's/\([^A-Za-z]\)ucrb8a.pfb/\1n022004l.pfb/' \
    -e 's/\([^A-Za-z]\)ucrbo8a.pfb/\1n022024l.pfb/' \
    -e 's/\([^A-Za-z]\)ucrr8a.pfb/\1n022003l.pfb/' \
    -e 's/\([^A-Za-z]\)ucrro8a.pfb/\1n022023l.pfb/' \
    -e 's/\([^A-Za-z]\)uhvb8a.pfb/\1n019004l.pfb/' \
    -e 's/\([^A-Za-z]\)uhvb8ac.pfb/\1n019044l.pfb/' \
    -e 's/\([^A-Za-z]\)uhvbo8a.pfb/\1n019024l.pfb/' \
    -e 's/\([^A-Za-z]\)uhvbo8ac.pfb/\1n019064l.pfb/' \
    -e 's/\([^A-Za-z]\)uhvr8a.pfb/\1n019003l.pfb/' \
    -e 's/\([^A-Za-z]\)uhvr8ac.pfb/\1n019043l.pfb/' \
    -e 's/\([^A-Za-z]\)uhvro8a.pfb/\1n019023l.pfb/' \
    -e 's/\([^A-Za-z]\)uhvro8ac.pfb/\1n019063l.pfb/' \
    -e 's/\([^A-Za-z]\)uncb8a.pfb/\1c059016l.pfb/' \
    -e 's/\([^A-Za-z]\)uncbi8a.pfb/\1c059036l.pfb/' \
    -e 's/\([^A-Za-z]\)uncr8a.pfb/\1c059013l.pfb/' \
    -e 's/\([^A-Za-z]\)uncri8a.pfb/\1c059033l.pfb/' \
    -e 's/\([^A-Za-z]\)uplb8a.pfb/\1p052004l.pfb/' \
    -e 's/\([^A-Za-z]\)uplbi8a.pfb/\1p052024l.pfb/' \
    -e 's/\([^A-Za-z]\)uplr8a.pfb/\1p052003l.pfb/' \
    -e 's/\([^A-Za-z]\)uplri8a.pfb/\1p052023l.pfb/' \
    -e 's/\([^A-Za-z]\)usyr.pfb/\1s050000l.pfb/' \
    -e 's/\([^A-Za-z]\)utmb8a.pfb/\1n021004l.pfb/' \
    -e 's/\([^A-Za-z]\)utmbi8a.pfb/\1n021024l.pfb/' \
    -e 's/\([^A-Za-z]\)utmr8a.pfb/\1n021003l.pfb/' \
    -e 's/\([^A-Za-z]\)utmri8a.pfb/\1n021023l.pfb/' \
    -e 's/\([^A-Za-z]\)uzcmi8a.pfb/\1z003034l.pfb/' \
    -e 's/\([^A-Za-z]\)uzdr.pfb/\1d050000l.pfb/' \
    ${1+"$@"}
}

###############################################################################
# fileADOBE()
#   transform filenames from URWkb (berry names) to ADOBE (vendor names)
###############################################################################
fileADOBE()
{
  sed \
    -e 's/\([^A-Za-z]\)uagd8a.pfb/\1agd_____.pfb/' \
    -e 's/\([^A-Za-z]\)uagdo8a.pfb/\1agdo____.pfb/' \
    -e 's/\([^A-Za-z]\)uagk8a.pfb/\1agw_____.pfb/' \
    -e 's/\([^A-Za-z]\)uagko8a.pfb/\1agwo____.pfb/' \
    -e 's/\([^A-Za-z]\)ubkd8a.pfb/\1bkd_____.pfb/' \
    -e 's/\([^A-Za-z]\)ubkdi8a.pfb/\1bkdi____.pfb/' \
    -e 's/\([^A-Za-z]\)ubkl8a.pfb/\1bkl_____.pfb/' \
    -e 's/\([^A-Za-z]\)ubkli8a.pfb/\1bkli____.pfb/' \
    -e 's/\([^A-Za-z]\)ucrb8a.pfb/\1cob_____.pfb/' \
    -e 's/\([^A-Za-z]\)ucrbo8a.pfb/\1cobo____.pfb/' \
    -e 's/\([^A-Za-z]\)ucrr8a.pfb/\1com_____.pfb/' \
    -e 's/\([^A-Za-z]\)ucrro8a.pfb/\1coo_____.pfb/' \
    -e 's/\([^A-Za-z]\)uhvb8a.pfb/\1hvb_____.pfb/' \
    -e 's/\([^A-Za-z]\)uhvb8ac.pfb/\1hvnb____.pfb/' \
    -e 's/\([^A-Za-z]\)uhvbo8a.pfb/\1hvbo____.pfb/' \
    -e 's/\([^A-Za-z]\)uhvbo8ac.pfb/\1hvnbo___.pfb/' \
    -e 's/\([^A-Za-z]\)uhvr8a.pfb/\1hv______.pfb/' \
    -e 's/\([^A-Za-z]\)uhvr8ac.pfb/\1hvn_____.pfb/' \
    -e 's/\([^A-Za-z]\)uhvro8a.pfb/\1hvo_____.pfb/' \
    -e 's/\([^A-Za-z]\)uhvro8ac.pfb/\1hvno____.pfb/' \
    -e 's/\([^A-Za-z]\)uncb8a.pfb/\1ncb_____.pfb/' \
    -e 's/\([^A-Za-z]\)uncbi8a.pfb/\1ncbi____.pfb/' \
    -e 's/\([^A-Za-z]\)uncr8a.pfb/\1ncr_____.pfb/' \
    -e 's/\([^A-Za-z]\)uncri8a.pfb/\1nci_____.pfb/' \
    -e 's/\([^A-Za-z]\)uplb8a.pfb/\1pob_____.pfb/' \
    -e 's/\([^A-Za-z]\)uplbi8a.pfb/\1pobi____.pfb/' \
    -e 's/\([^A-Za-z]\)uplr8a.pfb/\1por_____.pfb/' \
    -e 's/\([^A-Za-z]\)uplri8a.pfb/\1poi_____.pfb/' \
    -e 's/\([^A-Za-z]\)usyr.pfb/\1sy______.pfb/' \
    -e 's/\([^A-Za-z]\)utmb8a.pfb/\1tib_____.pfb/' \
    -e 's/\([^A-Za-z]\)utmbi8a.pfb/\1tibi____.pfb/' \
    -e 's/\([^A-Za-z]\)utmr8a.pfb/\1tir_____.pfb/' \
    -e 's/\([^A-Za-z]\)utmri8a.pfb/\1tii_____.pfb/' \
    -e 's/\([^A-Za-z]\)uzcmi8a.pfb/\1zcmi____.pfb/' \
    -e 's/\([^A-Za-z]\)uzdr.pfb/\1zd______.pfb/' \
    ${1+"$@"}
}

base14RemovePSName()
{
  sed \
    -e '/^[^ 	]*[ 	]Courier[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Courier-Bold[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Courier-Oblique[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Courier-BoldOblique[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Helvetica[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Helvetica-Bold[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Helvetica-Oblique[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Helvetica-BoldOblique[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Symbol[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Times-Roman[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Times-Bold[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Times-Italic[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]Times-BoldItalic[ 	]/s/[ 	][^ 	]*//' \
    -e '/^[^ 	]*[ 	]ZapfDingbats[ 	]/s/[ 	][^ 	]*//'
}

###############################################################################
# locateWeb2c (file ...)
#   apply kpsewhich with format 'web2c files'
###############################################################################
locateWeb2c()
{
  kpsewhich --format='web2c files' ${1+"$@"}
}

###############################################################################
# locateMap (file ...)
#   apply kpsewhich with format 'dvips config'
###############################################################################
locateMap()
{
  for map
  do
    file=`kpsewhich --format='dvips config' "$map"`
    if test -f "$file"; then
      verboseMsg "using map file \`$file'"
      echo "$file"
    else
      warn "map file \`$map' not found"
    fi
  done
}

###############################################################################
# cleanup()
#   clean up the temp area and exit with proper exit status
###############################################################################
cleanup()
{
  rc=$?
  $needsCleanup && test -n "$tmpdir" && test -d "$tmpdir" \
    && { rm -f "$tmpdir"/*; cd /; rmdir "$tmpdir"; }
  exit $rc
}

###############################################################################
# setupTmpDir()
#   set up a temp directory and a trap to remove it
###############################################################################
setupTmpDir()
{
  $needsCleanup && return

  trap 'cleanup' 1 2 3 7 13 15
  needsCleanup=true
  mkdir "$tmpdir" || abort "could not create directory \`$tmpdir'"
}

###############################################################################
# showOptions(item)
#   show Options for an item
###############################################################################
showOptions()
{
  item=$1

  case "$item" in
    LW35)
      echo "URWkb URW ADOBE ADOBEkb"
      ;;
    dvipsPreferOutline|pdftexDownloadBase14|dvipdfmDownloadBase14|dvipsDownloadBase35)
      echo "true false"
      ;;
    *)
      abort "Unknown item \"$item\". Choose one of LW35, dvipsPreferOutline, dvipsDownloadBase35, pdftexDownloadBase14 or dvipdfmDownloadBase14"
      ;;
  esac

  exit 0
}


###############################################################################
# setupDestDir()
#   find an output directory if none specified on cmd line. First choice is
#   $VARTEXMF/dvips/config (if VARTEXMF is set), next is relative to config
#   file location. Fallback is $TEXMFMAIN/dvips/config.
###############################################################################
setupDestDir()
{
  if test -z "$outputdir"; then

    # Try VARTEXMF tree. Use it if variable is set and dvips/config can
    # be written. Copy config file if it does not exist there.
    tf=`kpsewhich -expand-var='$VARTEXMF'`
    if test -n "$tf"; then
      $TEXMFMAIN/web2c/mktexdir "$tf/dvips/config" >/dev/null
      if test ! -d "$tf/dvips/config" || test ! -w "$tf/dvips/config"; then
        # forget about VARTEXMF tree...
        tf=
      fi
    fi
      
    # Try something relative to config file, fall back to $TEXMFMAIN.
    if test -z "$tf"; then
      tf=`echo $cnfFile | sed -n 's@/web2c/[^/]*$@@p'`
      test -z "$tf" && tf=$TEXMFMAIN
    fi

    outputdir=$tf/dvips/config
  fi

  $TEXMFMAIN/web2c/mktexdir "$outputdir"
  test -d "$outputdir" || abort "output directory \`$outputdir' does not exist"
  test -w "$outputdir" || abort "output directory \`$outputdir' is not writable"
  verboseMsg "using output directory $outputdir"
}

###############################################################################
# setupCfgFile()
#   find config file if none specified on cmd line.
###############################################################################
setupCfgFile()
{

  if test -z "$cnfFile"; then

    tf=`kpsewhich -expand-var='$VARTEXMF'`
    if test -n "$tf" && test ! -f "$tf/web2c/$cnfFileShort"; then
      test -d "$tf/web2c" || $TEXMFMAIN/web2c/mktexdir "$tf/web2c" 2>/dev/null
      if test -d "$tf/web2c" && test -w "$tf/web2c"; then
        rm -f "$tf/web2c/$cnfFileShort"
        cp $TEXMFMAIN/web2c/$cnfFileShort "$tf/web2c/$cnfFileShort"
        $TEXMFMAIN/web2c/mktexupd "$tf/web2c" "$cnfFileShort"
      fi
    fi

    cnfFile=`locateWeb2c $cnfFileShort`
    if test -n "$cnfFile"; then
      verboseMsg "using config file $cnfFile"
    else
      abort "config file $cnfFileShort not found"
    fi
  fi
}

###############################################################################
# processOptions()
#   process cmd line options
###############################################################################
processOptions()
{
  while
    case $1 in
      --quiet|-q)
          verbose=false;;
      --cnffile)
          cfgparam=1; cnfFile=$2; shift;;
      --cnffile=*)
          cfgparam=1; cnfFile=`echo "$1" | sed 's/--cnffile=//'`;;
      --outputdir)
          outputdirparam=1; outputdir=$2; shift;;
      --outputdir=*)
          outputdirparam=1; outputdir=`echo "$1" | sed 's/--outputdir=//'`;;
      --setoption)
          test $# -ge 3 || { abort "--setoption needs two parameters: option value"; }
          cmd=setoption; setoptionOpt=$2; setoptionVal=$3; shift; shift
          ;;
      --enable)
          test $# -ge 3 || { abort "--enable needs two parameters: mapType mapFile"; }
          cmd=enable; enableMapType=$2; enableMapFile=$3; shift; shift
          ;;
      --disable)
          cmd=disable; disableMapFile=$2; shift
          ;;
      --edit|-e)
          cmd=edit;;
      --listmaps|-l)
          cmd=listmaps;;
      --showoptions)
          cmd=showoptions; showoptionsItem=$2; shift;;
      --showoptions=*)
          cmd=showoptions; showoptionsItem=`echo "$1" | sed 's/--showoptions=//'`;;
      --nohash)
          texhashEnabled=false;;
      --nomkmap)
          mkmapEnabled=false;;
      --help|-help|-h)
          help;;
      "") break;;
      *) echo "$progname: unknown option \`$1' ignored." >&2;;
    esac
  do test $# -gt 0 && shift; done

  if test -n "$cfgparam"; then
    if test -z "$cnfFile" || test ! -f "$cnfFile"; then
      abort "config file \`$cnfFileShort' not found"
    fi
  fi

  if test -n "$outputdirparam"; then
    if test -z "$outputdir" || test ! -d "$outputdir"; then
      abort "output directory \`$1' not found"
    fi
  fi
}



###############################################################################
# listMaps()
#   list all maps mentioned in the config file
###############################################################################
listMaps()
{
  egrep '^(#! *)?(Mixed)?Map' $cnfFile
}

###############################################################################
# normalizeLines()
#   remove comments, whitespace is exactly one space, no empty lines,
#   no whitespace at end of line, one space before and after "
###############################################################################
normalizeLines()
{
  sed \
      -e '/^%/d' \
      -e 's@[ 	][ 	]*@ @g' \
      -e '/^ *$/d' \
      -e 's@ $@@' \
      -e 's@ *" *@ " @g' | sort | uniq
}

dvips2dvipdfm()
{
  sed -e 's@$@ %@' \
      -e 's@^\(\([^ ]*\).*\)@\1\2@' \
      -e 's@\(.*<\[* *\([^ ]*\)\.enc\(.*\)\)@\1 \2@' \
      -e '/%[^ ]*$/s@$@ default@' \
      -e 's@\(.*<<* *\([^ ]*\)\.pf[ab].*\)@\1 \2@' \
      -e '/%[^ ]* [^ ]*$/s@\( \([^ ]*\).*\)$@\1 \2@' \
      -e 's@\(.* \([.0-9-][.0-9-]*\) *ExtendFont.*\)@\1 -e \2@' \
      -e 's@\(.* \([.0-9-][.0-9-]*\) *SlantFont.*\)@\1 -s \2@' \
      -e 's@.*%@@' |
  awk '$1 == $3 && $2 == "default" {$2=""; $3=""} {print}' > $tmp8
 
  egrep '^(cm|eu|la|lc|line|msam|xy)' $tmp8 | sed 's@$@ -r@'
  egrep -v '^(cm|eu|la|lc|line|msam|xy)' $tmp8
}


###############################################################################
# mkMaps()
#   the main task of this script: create the output files
###############################################################################
mkMaps()
{
  mode=`cfgval LW35`
  dvipsPreferOutline=`cfgval dvipsPreferOutline`
  dvipsDownloadBase35=`cfgval dvipsDownloadBase35`
  pdftexDownloadBase14=`cfgval pdftexDownloadBase14`
  dvipdfmDownloadBase14=`cfgval dvipdfmDownloadBase14`

  # defaults
  test -z "$mode" && mode=URWkb
  test -z "$dvipsPreferOutline" && dvipsPreferOutline=true
  test -z "$dvipsDownloadBase35" && dvipsDownloadBase35=false
  test -z "$pdftexDownloadBase14" && pdftexDownloadBase14=false
  test -z "$dvipdfmDownloadBase14" && dvipdfmDownloadBase14=false

  $verbose && cat >&2 <<-eof

	updmap is creating new map files using the following configuration:
	  prefer outlines: $dvipsPreferOutline
	  texhash enabled: $texhashEnabled
	  download standard fonts (dvips): $dvipsDownloadBase35
	  download standard fonts (pdftex): $pdftexDownloadBase14
	  download standard fonts (dvipdfm): $dvipdfmDownloadBase14
eof

  verboseMsg
  verboseMsg "Scanning for LW35 support files"
  dvips35=`locateMap dvips35.map`
  pdftex35=`locateMap pdftex35.map`
  dvipdfm35=`locateMap dvipdfm35.map`
  ps2pk35=`locateMap ps2pk35.map`

  verboseMsg
  verboseMsg "Scanning for MixedMap entries:"
  catMaps '^MixedMap' > $tmp1

  verboseMsg
  verboseMsg "Scanning for Map entries:"
  catMaps '^Map' > $tmp2
  verboseMsg

  # files should be work-readable
  umask 022

  # Create psfonts_t1.map, psfonts_pk.map, ps2pk.map, pdftex.map and dvipdfm.map:
  for file in download35.map builtin35.map psfonts_t1.map psfonts_pk.map pdftex_dl14.map pdftex_ndl14.map dvipdfm_dl14.map dvipdfm_ndl14.map ps2pk.map; do
    rm -f "$outputdir/$file"
    cat > $outputdir/$file <<-eof
	% $file: maintained by the script updmap.
	%   Don't change this file directly. Edit texmf/web2c/$cnfFileShort
	%   and run updmap to recreate this file.
eof
  done

  { transLW35 $ps2pk35; cat $tmp1 $tmp2; } \
    | normalizeLines >> $outputdir/ps2pk.map

  { transLW35 $ps2pk35; } \
    | normalizeLines >> $outputdir/download35.map
  { transLW35 $dvips35; } \
    | normalizeLines >> $outputdir/builtin35.map

  if test "x$dvipsDownloadBase35" = xtrue; then
    dftdvips=$ps2pk35
  else
    dftdvips=$dvips35
  fi
  { transLW35 $dftdvips; cat $tmp1 $tmp2; } \
    | normalizeLines >> $outputdir/psfonts_t1.map
  { transLW35 $dftdvips; cat $tmp2; } \
    | normalizeLines >> $outputdir/psfonts_pk.map

  # remove PaintType due to Sebastian's request
  { transLW35 $pdftex35; cat $tmp1 $tmp2; } \
    | egrep -v '(^%|PaintType)' | grep . > $tmp3
  { transLW35 $dvipdfm35; cat $tmp1 $tmp2; } \
    | egrep -v '(^%|PaintType)' | grep . > $tmp6
  { transLW35 $ps2pk35; cat $tmp1 $tmp2; } \
    | egrep -v '(^%|PaintType)' | grep . > $tmp7

  # remove PS-Fontname from ExtendFont / SlantFont lines (works around a
  # pdftex bug)
  { <$tmp3 egrep '".*[^A-Za-z](Slant|Extend)Font([^A-Za-z].*"|")' | sed 's@[ 	][^ 	]*@@'
    <$tmp3 egrep -v '".*[^A-Za-z](Slant|Extend)Font([^A-Za-z].*"|")'
  } | normalizeLines >> $outputdir/pdftex_ndl14.map
  { <$tmp7 egrep '".*[^A-Za-z](Slant|Extend)Font([^A-Za-z].*"|")' | sed 's@[ 	][^ 	]*@@'
    <$tmp7 egrep -v '".*[^A-Za-z](Slant|Extend)Font([^A-Za-z].*"|")'
  } | base14RemovePSName | normalizeLines >> $outputdir/pdftex_dl14.map
  <$tmp7 normalizeLines | dvips2dvipdfm | normalizeLines >> $outputdir/dvipdfm_dl14.map
  <$tmp6 normalizeLines | dvips2dvipdfm | normalizeLines >> $outputdir/dvipdfm_ndl14.map
  setupSymlinks
  $texhashEnabled && { $verbose && texhash || texhash >/dev/null 2>&1; }

  verboseMsg
  verboseMsg "Files generated in $outputdir:"
  $verbose && (cd $outputdir; ls -l dvipdfm.map dvipdfm_dl14.map dvipdfm_ndl14.map pdftex.map pdftex_dl14.map pdftex_ndl14.map ps2pk.map psfonts.map psfonts_pk.map psfonts_t1.map builtin35.map download35.map) >&2
  verboseMsg
}

###############################################################################
# main()
#   execution starts here
###############################################################################
main()
{
  # initialize global variables
  progname=updmap
  cmd=

  cfgparam=
  outputdirparam=
  texhashEnabled=true
  mkmapEnabled=true
  verbose=true
  needsCleanup=false
  DebianWarnShown=false

  cnfFileShort=updmap.cfg
  cnfFile=
  outputdir=
  TEXMFMAIN=`kpsewhich --expand-var='$TEXMFMAIN'`

  tmpdir=${TMP-/tmp}/$progname.$$
  tmp1=$tmpdir/a
  tmp2=$tmpdir/b
  tmp3=$tmpdir/c
  tmp4=$tmpdir/d
  tmp5=$tmpdir/e
  tmp6=$tmpdir/f
  tmp7=$tmpdir/g
  tmp8=$tmpdir/h

  processOptions ${1+"$@"}

  case "$cmd" in
    showoptions) showOptions "$showoptionsItem"; exit;;
    help)        help; exit;;
  esac

  setupCfgFile
  case "$cmd" in
    listmaps) listMaps; exit;;
  esac

  # keep a copy of config file, so that we can see if the file was modified
  setupTmpDir
  cp $cnfFile $tmp5

  case "$cmd" in
    edit)
      ${VISUAL-${EDITOR-vi}} $cnfFile;;
    setoption)
      setOption "$setoptionOpt" "$setoptionVal";;
    enable)
      enableMap "$enableMapType" "$enableMapFile";;
    disable)
      disableMap "$disableMapFile";;
  esac

  if test -n "$cmd" && cmp $cnfFile $tmp5 >/dev/null 2>&1; then
    verboseMsg "$cnfFile unchanged. Map files not recreated."
    return
  fi

  $mkmapEnabled || return
  setupDestDir
  mkMaps
}

main ${1+"$@"}
true
cleanup
