#!/bin/sh ############################################################################### # fmtutil: utility to maintain format files. # # Thomas Esser, (C) 1998, 2001, 2002, 2003. Public domain. # # Commands: # --all recreate all format files # --missing create all missing format files # --byfmt formatname (re)create format for `formatname' # --byhyphen hyphenfile (re)create formats that depend on `hyphenfile' # --showhyphen formatname print name of hyphenfile for format `formatname' # --help show this message # # Options: # --cnffile file set configfile for fmtutil # --fmtdir directory set destination directory for format files ############################################################################### ############################################################################### # program history: # Do Okt 28 11:09:36 CEST 2004 added --refresh # Fr Sep 17 19:25:28 CEST 2004 save $0 in a variable before calling a function # Sun May 9 23:24:06 CEST 2004 changes for new web2c: format names # are now *.fmt, nothing else, disable # "plain" symlinks # Thu May 6 14:16:19 CEST 2004: "mv .../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+"$@"}'='"$@"' progname=fmtutil argv0=$0 version=1098954595 # seconds since `00:00:00 1970-01-01 UTC' # date '+%s' (with GNU date) cnf=fmtutil.cnf # name of the config file ############################################################################### # 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 (umask 077; mkdir "$tmpdir") \ || abort "could not create directory \`$tmpdir'" } ############################################################################### # 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 } ############################################################################### # setmatch(match) # setting the "match state" to true or false. Used to see if there was at # least one match. ############################################################################### setmatch() { match=$1 } ############################################################################### # getmatch() # return success if there was at least one match. ############################################################################### getmatch() { test "x$match" = xtrue } ############################################################################### # cache_vars() # locate files / kpathsea variables and export variables to environment # this speeds up future calls to e.g. mktexupd ############################################################################### cache_vars() { : ${MT_VARTEXFONTS=`kpsewhich --expand-var='$VARTEXFONTS' | sed 's%^!!%%'`} : ${MT_TEXMFMAIN=`kpsewhich --expand-var='$TEXMFMAIN'`} : ${MT_MKTEXNAM=`kpsewhich --format='web2c files' mktexnam`} : ${MT_MKTEXNAM_OPT=`kpsewhich --format='web2c files' mktexnam.opt`} : ${MT_MKTEXDIR=`kpsewhich --format='web2c files' mktexdir`} : ${MT_MKTEXDIR_OPT=`kpsewhich --format='web2c files' mktexdir.opt`} : ${MT_MKTEXUPD=`kpsewhich --format='web2c files' mktexupd`} : ${MT_MKTEX_CNF=`kpsewhich --format='web2c files' mktex.cnf`} : ${MT_MKTEX_OPT=`kpsewhich --format='web2c files' mktex.opt`} : ${MT_LSR_PATH=`kpsewhich -show-path=ls-R`} export MT_VARTEXFONTS MT_TEXMFMAIN MT_MKTEXNAM MT_MKTEXNAM_OPT MT_MKTEXDIR export MT_MKTEXDIR_OPT MT_MKTEXUPD MT_MKTEX_CNF MT_MKTEX_OPT MT_LSR_PATH } ############################################################################### # help() # display help message and exit ############################################################################### help() { cat <<'eof' Usage: fmtutil [option] ... cmd [argument] Valid options: --cnffile file --fmtdir directory --quiet (not implemented, just for compatibility) --test (not implemented, just for compatibility) --dolinks (not implemented, just for compatibility) --force (not implemented, just for compatibility) Valid commands: --all recreate all format files --missing create all missing format files --refresh recreate only existing format files --byfmt formatname (re)create format for `formatname' --byhyphen hyphenfile (re)create formats that depend on `hyphenfile' --enablefmt formatname enable formatname in config file --disablefmt formatname disable formatname in config file --listcfg list (enabled and disabled) configurations --showhyphen formatname print name of hyphenfile for format `formatname' --edit edit fmtutil.cnf file --version show version info --help show this message eof true cleanup } version() { cat <&2 false # some systems need this to set nonzero $? cleanup } ############################################################################### # byebye() # report any failures and exit the program ############################################################################### byebye() { if $has_errors; then { cat <&2 false # some systems need this to set nonzero $? cleanup else true cleanup fi } ############################################################################### # init_log_failure() # reset the list of failure messages ############################################################################### init_log_failure() { log_failure_msg= has_errors=false } ############################################################################### # log_failure(errmsg) # report and save failure message `errmsg' ############################################################################### log_failure() { echo "Error: $@" >&2 if test -z "$log_failure_msg"; then log_failure_msg="$@" else OLDIFS=$IFS; IFS= log_failure_msg="$log_failure_msg $@" IFS=$OLDIFS fi has_errors=true } ############################################################################### # verbose (cmd) # execute cmd. Redirect output depending on $mktexfmtMode. ############################################################################### verbose() { $mktexfmtMode && ${1+"$@"} >&2 || ${1+"$@"} } ############################################################################### # main() # parse commandline arguments, initialize variables, # switch into temp. direcrory, execute desired command ############################################################################### main() { destdir= # global variable: where do we put the format files? cnf_file= # global variable: full name of the config file cmd= # desired action from command line needsCleanup=false need_find_hyphenfile=false # mktexfmtMode: if called as mktexfmt, set to true. Will echo the generated # filename after successful generation to stdout then (and nothing else). mktexfmtMode=false case $argv0 in mktexfmt|*/mktexfmt) mktexfmtMode=true fullfmt=$1; shift case $fullfmt in *.fmt|*.mem|*.base) set x --byfmt `echo $fullfmt | sed 's@\.[a-z]*$@@'` ${1+"$@"}; shift ;; *.*) abort "unknown format type: $fullfmt" ;; "") help ;; *) set x --byfmt $fullfmt; shift ;; esac ;; esac while case $1 in --cnffile) shift; cnf_file=$1;; --cnffile=*) cnf_file=`echo "$1" | sed 's/--cnffile=//'`; shift ;; --fmtdir) shift; destdir=$1;; --fmtdir=*) destdir=`echo "$1" | sed 's/--fmtdir=//'`; shift ;; --all|-a) cmd=all;; --edit|-e) cmd=edit;; --missing|-m) cmd=missing;; --refresh|-r) cmd=refresh;; --byfmt|-f) shift; cmd=byfmt; arg=$1;; --byfmt=*) cmd=byfmt; arg=`echo "$1" | sed 's/--byfmt=//'`; shift ;; --byhyphen|-h) shift; cmd=byhyphen; arg=$1;; --byhyphen=*) cmd=byhyphen; arg=`echo "$1" | sed 's/--byhyphen=//'`; shift ;; --showhyphen|-s) shift; cmd=showhyphen; arg=$1;; --showhyphen=*) cmd=showhyphen; arg=`echo "$1" | sed 's/--showhyphen=//'`; shift ;; --help|-help) cmd=help;; --version) cmd=version;; --enablefmt) shift; cmd=enablefmt; arg=$1;; --enablefmt=*) cmd=enablefmt; arg=`echo "$1" | sed 's/--enablefmt=//'`; shift ;; --disablefmt) shift; cmd=disablefmt; arg=$1;; --disablefmt=*) cmd=disablefmt; arg=`echo "$1" | sed 's/--disablefmt=//'`; shift ;; --listcfg) cmd=listcfg;; --quiet|--test|--dolinks|--force) ;; "") break;; *) echo "$progname: unknown option \`$1' ignored." >&2;; esac do test $# -gt 0 && shift; done case "$cmd" in help|"") help;; version) version;; esac cache_vars # if no cnf_file from command-line, look it up with kpsewhich: test -z "$cnf_file" && cnf_file=`kpsewhich --format='web2c files' $cnf` test -f "$cnf_file" || abort "config file \`$cnf' not found" # showhyphen and edit do not need any temp. directory, so do it here: case "$cmd" in showhyphen) show_hyphen_file "$arg" cleanup ;; edit) ${VISUAL-${EDITOR-vi}} $cnf_file cleanup ;; enablefmt|disablefmt) $cmd $arg cleanup ;; listcfg) listcfg_loop cleanup ;; esac # set up destdir: test -z "$MT_TEXMFMAIN" && abort "could not expand variable \$TEXMFMAIN" if test -z "$destdir"; then : ${VARTEXMF=`kpsewhich -expand-var='$VARTEXMF'`} test -z "$VARTEXMF" && VARTEXMF=$MT_TEXMFMAIN destdir=$VARTEXMF/web2c fi test -d "$destdir" || $MT_MKTEXDIR "$destdir" >/dev/null 2>&1 test -d "$destdir" || abort "format directory \`$destdir' does not exist" # find mktexupd script: test -n "$MT_MKTEXUPD" || MT_MKTEXUPD="$TEXMFMAIN/web2c/mktexupd" thisdir=`pwd` tmpdir=${TMP-/tmp}/$progname.$$ : ${KPSE_DOT=$thisdir} export KPSE_DOT # due to KPSE_DOT, we don't search the current directory, so include # it explicitly for formats that \write and later on \read TEXINPUTS="$tmpdir:$TEXINPUTS"; export TEXINPUTS setupTmpDir cd "$tmpdir" || { false # some systems need this to set nonzero $? cleanup } # make local paths absolute: case "$destdir" in /*) ;; *) destdir="$thisdir/$destdir";; esac case "$cnf_file" in /*) ;; *) cnf_file="$thisdir/$cnf_file";; esac init_log_failure # execute the desired command: case "$cmd" in all) recreate_all;; missing) create_missing;; refresh) recreate_existing;; byfmt) create_one_format "$arg";; byhyphen) recreate_by_hyphenfile "$arg";; esac # install the log files and format files: for i in *.log; do test -f "$i" || continue rm -f "$destdir/$i" # We don't want user-interaction for the following "mv" command: mv "$i" "$destdir/$i" /dev/null 2>&1 } ############################################################################### # find_hyphenfile(format, hyphenation) searches for hyphenation along # searchpath of format # exit code: returns error is file is not found ############################################################################### find_hyphenfile() { format="$1"; hyphenation="$2" case $hyphenation in -) ;; *) kpsewhich -progname="$format" -format=tex "$hyphenation";; esac } ############################################################################### # find_info_for_name(format) # Look up the config line for format `format' and call parse_line to set # global variables. ############################################################################### find_info_for_name() { format="$1" set x `awk '$1 == format {print; exit}' format="$format" "$cnf_file"`; shift test $# = 0 && abort "no info for format \`$format'" parse_line "$@" } ############################################################################### # run_initex() # Calls initex. Assumes that global variables are set by parse_line. ############################################################################### run_initex() { # install a pool file and set tcx flag if requested in lang= option: rm -f *.pool poolfile= tcxflag= test -n "$pool" \ && poolfile=`(kpsewhich -progname=$engine $pool.pool) 2>/dev/null` if test -n "$poolfile" && test -f "$poolfile"; then verbose echo "$progname: attempting to create localized format using pool=$pool and tcx=$tcx." cp "$poolfile" $engine.pool test -n "$tcx" && tcxflag=-translate-file=$tcx localpool=true else localpool=false fi jobswitch="-jobname=$format" case "$format" in metafun) prgswitch=-progname=mpost;; mptopdf|cont-??) prgswitch=-progname=context;; *) prgswitch=-progname=$format;; esac rm -f $fmtfile verbose echo "running \`$engine -ini $tcxflag $jobswitch $prgswitch $texargs' ..." # run in a subshell to get a local effect of TEXPOOL manipulation: ( # If necessary, set TEXPOOL. Use absolute path, because of KPSE_DOT. $localpool && { TEXPOOL="`pwd`:$TEXPOOL"; export TEXPOOL; } verbose $engine -ini $tcxflag $jobswitch $prgswitch $texargs ) /dev/null 2>&1 && log_failure "\`$engine -ini $tcxflag $jobswitch $prgswitch $texargs' possibly failed." else log_failure "\`$engine -ini $tcxflag $jobswitch $prgswitch $texargs' failed" fi } ############################################################################### # recreate_loop(hyphenfile) # for each line in config file: check match-condition and recreate format # if there is a match ############################################################################### recreate_loop() { OIFS=$IFS IFS=' ' set `echo x; sed '/^#/d; /^[ ]*$/d' "$cnf_file"`; shift IFS=$OIFS for line do parse_line $line || continue check_match || continue echo; echo run_initex done } ############################################################################### # listcfg_loop() # prints all format definitions in config files (enabled and disabled ones) # for supported formats (i.e. for those which have an existing ini file) ############################################################################### listcfg_loop() { OIFS=$IFS IFS=' ' set `echo x; sed '/^#$/d; /^#[^!]/d; /^[ ]*$/d' "$cnf_file"`; shift IFS=$OIFS for line do parse_line $line && echo "$line" done } ############################################################################### # check_match() # recreate all formats ############################################################################### check_match() { $need_find_hyphenfile && \ this_hyphenfile=`find_hyphenfile "$format" "$hyphenation"` eval $match_cmd && setmatch true } ############################################################################### # create_one_format(fmtname) # (re)create the format file for the format `fmtname' ############################################################################### create_one_format() { fmtname=$1 find_info_for_name $fmtname || abort "format \`$fmtname' not available" run_initex } ############################################################################### # create_missing() # create all missing format files ############################################################################### create_missing() { # match_cmd='test ! -f $destdir/$fmtfile' match_cmd='test ! -f "`kpsewhich -progname=$format $fmtfile`"' recreate_loop } ############################################################################### # recreate_existing() # recreate only existing format files ############################################################################### recreate_existing() { match_cmd='test -f "`kpsewhich -progname=$format $fmtfile`"' recreate_loop } ############################################################################### # recreate_all() # recreate all formats ############################################################################### recreate_all() { match_cmd=true recreate_loop } ############################################################################### # recreate_by_hyphenfile(hyphenfile) # recreate all formats that depend on hyphenfile ############################################################################### recreate_by_hyphenfile() { hyphenfile=$1 need_find_hyphenfile=true match_cmd="test x\$this_hyphenfile = x$hyphenfile" # No match before the loop: setmatch false recreate_loop # Now check if there was at least one match: getmatch || abort "no format depends on \`$hyphenfile'" } ############################################################################### # show_hyphen_file(format) # prints full name of the hyphenfile for format # # exit code: returns error code if the ini file is not installed or if # the hyphen file cannot be found ############################################################################### show_hyphen_file() { fmtname=$1 find_info_for_name "$fmtname" || abort "no info for format \`$fmtname'" if test "x$hyphenation" = x-; then echo - cleanup fi find_hyphenfile "$format" "$hyphenation" \ || abort "hyphenfile \`$hyphenation' not found" } ############################################################################### # disablefmt(format) # disables format in configuration file ############################################################################### disablefmt() { grep "^$1[ ]" $cnf_file >/dev/null || return 0 ed $cnf_file >/dev/null 2>&1 <<-eof /^$1[ ]/s/^/#! / w q eof return 0 } ############################################################################### # enablefmt(format) # enables format in configuration file ############################################################################### enablefmt() { grep "^#![ ]*$1[ ]" $cnf_file >/dev/null || return 0 ed $cnf_file >/dev/null 2>&1 <<-eof /^#![ ]*$1[ ]/s/..[ ]*// w q eof return 0 } main ${1+"$@"} true cleanup