#!/bin/sh -u # Authors: Marc Boyer # Esa Hyytia (header option) # Date : 10/6/2008 # Version : 0.5 # sh options # -u Treat unset variables as an error when substituting. # -v Print shell input lines as they are read. # -x Print commands and their arguments as they are executed. # Erase de LANG environment variable, because it can create bugs with # sed. With my "fr_FR@euro" value, some regular expression in ps2epsi # fail. LANG= # Tools PS2EPS=ps2epsi PS2EPS_CMDNAME=ps2epsi # Default options METHOD=2 PS2PS_OPT=no EPS2EPS_OPT=no CLEAN_OPT="yes" FORCE_EPSI_OPT="no" OWN_HEADER_OPT="" MASTER_FILE_OPT="" AUTO="no" TMPD=/tmp # usage method usage() { cat < Contributors: Esa Hyytia (header option) Version: 1.0 EOF } detect_ps2eps_filter() { ps2eps -V > /dev/null if [ $? -ne 0 ] then cat< /dev/null if [ $? = "1" ] then echo "Warning: no mktemp foumd" MKTEMP=echo else MKTEMP=mktemp fi \rm -f /tmp/testMktemp-* } # This function is "like" ps2eps except that his second argument is # the name of the output file ps2eps_with_output() { mv $1 $1.ps ps2eps -q $1.ps mv $1.eps $2 } # This function just runs ps2ps on its first argument, and uses # the second argument to store the old file, if the PS2PS_OPT is set # to yes # Classical uses are # ps2psFilter file.ps file.ps.bak # ps2psFilter file.ps file-raw.ps ps2psFilter(){ if [ ${PS2PS_OPT} = "yes" ] then echo " Cleaning ps with ps2ps filter" mv $1 $2 ps2ps $2 $1 fi } # Same as ps2ps with eps eps2epsFilter(){ if [ ${EPS2EPS_OPT} = "yes" ] then echo " Cleaning eps with eps2eps filter" mv $1 $2 eps2eps $2 $1 fi } # This simple version relies on dvips + ps2pdf. # It outputs a too wide bounding box dvi2pdfV0() { echo "Method 0: Trying conversion with dvips -|-> ps2pdf" echo "Converting dvi -> ps (dvips)" FIG_DVIPS=`${MKTEMP} ${TMPD}/${FIGNAME}-dvi2ps.ps.XXXXXX` FIG_DVIPS_RAW=`${MKTEMP} ${TMPD}/${FIGNAME}-dvi2ps-raw.ps.XXXXXX` dvips -f -q ${FIGNAME}.dvi > ${FIG_DVIPS} ps2psFilter ${FIG_DVIPS} ${FIG_DVIPS_RAW} echo "Converting ps -> pdf (ps2pdf)" ps2pdf ${FIG_DVIPS} ${FIGNAME}.pdf cleanfiles ${FIG_DVIPS} {FIG_DVIPS_RAW}; } # This version relies on dvips + PS2EPS + eps2pdf. # It often works dvi2pdfV1() { echo "Method 1: Trying conversion with dvips -|-> "${PS2EPS_CMDNAME}" -|-> epstopdf" dvi2pdfV1_noPrompt; } dvi2pdfV1_noPrompt() { FIG_DVIPS=`${MKTEMP} ${TMPD}/${FIGNAME}-dvi2ps.ps.XXXXXX` FIG_DVIPS_RAW=`${MKTEMP} ${TMPD}/${FIGNAME}-dvi2ps-raw.ps.XXXXXX` FIG_DVIPS_EPS=`${MKTEMP} ${TMPD}/${FIGNAME}-dvi2ps-ps2eps.eps.XXXXXX` FIG_DVIPS_EPS_RAW=`${MKTEMP} ${TMPD}/${FIGNAME}-dvi2ps-ps2eps-raw.eps.XXXXXX` echo "Converting dvi -> ps (dvips)" dvips -f -q ${FIGNAME}.dvi | egrep -v "^%%BoundingBox:" > ${FIG_DVIPS}; ps2psFilter ${FIG_DVIPS} ${FIG_DVIPS_RAW} echo "Converting ps -> eps ("${PS2EPS_CMDNAME}")" ${PS2EPS} ${FIG_DVIPS} ${FIG_DVIPS_EPS} eps2epsFilter ${FIG_DVIPS_EPS} ${FIG_DVIPS_EPS_RAW} echo "Converting eps -> pdf (epstopdf)" epstopdf ${FIG_DVIPS_EPS} --outfile=${FIGNAME}.pdf cleanfiles $FIG_DVIPS $FIG_DVIPS_RAW $FIG_DVIPS_EPS $FIG_DVIPS_EPS_RAW; } # This version relies on dvips + PS2EPS + eps2eps + eps2pdf. dvi2pdfV2() { echo "Method 2: Trying conversion with dvips -|-> " ${PS2EPS_CMDNAME} "-|-> eps2eps -|-> epstopdf" if [ $EPS2EPS_OPT = "yes" ] then dvi2pdfV1_noPrompt; else EPS2EPS_OPT="yes"; dvi2pdfV1_noPrompt; EPS2EPS_OPT="no"; fi } # This version relies on dvips -E + eps2eps + eps2pdf. dvi2pdfV3(){ echo "Trying conversion with dvips -E -|-> eps2eps -|-> eps2pdf" FIG_DVIEPS=`${MKTEMP} ${TMPD}/${FIGNAME}-dvi2eps.eps.XXXXXX` FIG_DVIEPS_RAW=`${MKTEMP} ${TMPD}/${FIGNAME}-dvi2eps-raw.eps.XXXXXX` FIG_DVIEPS_EPS=`${MKTEMP} ${TMPD}/${FIGNAME}-dvi2eps-eps2eps.eps.XXXXXX` echo "Converting dvi -> eps (dvips -E)" dvips -f -q -E ${FIGNAME}.dvi > ${FIG_DVIEPS} echo "Tightening the bounding box (eps2eps)" mv ${FIG_DVIEPS} ${FIG_DVIEPS_RAW} eps2eps ${FIG_DVIEPS_RAW} ${FIG_DVIEPS_EPS} echo "Converting eps -> pdf (epstopdf)" epstopdf ${FIG_DVIEPS_EPS} --outfile=${FIGNAME}.pdf cleanfiles $FIG_DVIEPS $FIG_DVIEPS_RAW $FIG_DVIEPS_EPS; } # Compiling one figure # Input: File ${MAIN}.header # File ${MAIN}.figure # ${FIGNAME}.tex # ${METHOD} compileOneFigure() { echo "Using LaTeX: producting dvi" cat ${MAIN}.header > ${FIGNAME}.tex echo ":pagestyle{empty}:renewcommand{:caption}[1]{}" | \ sed 's/:/\\/g' >> ${FIGNAME}.tex # There could be several pdfrackincludegraphics in the same figure # environment... Then, the script should there just keep one. #set -x # Simple expression: # grep -n "^.*\\pdfrackincludegraphics.*{${FIGNAME}}" ${MAIN}.figure # More precise expression KEEPED_LINE=`grep -n "^.*\\pdfrackincludegraphics\(\[[^]]*\]\)*{${FIGNAME}}" ${MAIN}.figure | cut -f1 -d:` sed ${KEEPED_LINE}!s/pdfrackincludegraphics/pdfracknullcommand/ ${MAIN}.figure \ >> ${FIGNAME}.tex echo ':end{document}' | sed 's/:/\\/g' >> ${FIGNAME}.tex if [ ! -r ${FIGNAME}.tex ] ; then echo "Fail: no readable file "${FIGNAME}.tex return fi latex -interaction=batchmode ${FIGNAME}.tex # The main pb is: how to convert from dvi to pdf, with the right size ? # The option "-E" of dvips "only works [...] at marks made by # characters and rules, not by any included graphics". # So I have tried some versions, and the 2d seems to be the more # efficient, but, sometimes, another is better... if [ -r ${FIGNAME}.dvi ] then case ${METHOD} in 0) echo "Warning: Method 0 should produce bad size"; dvi2pdfV0;; 1) dvi2pdfV1;; 2) dvi2pdfV2;; 3) dvi2pdfV3;; *) echo "Unknown method "${METHOD}; cleantexfiles;; esac else echo "Fail: no readable file "${FIGNAME}.dvi fi } ###################################################################### ## Main # Check paremetes and set options set - - `getopt ahm:H:M:peki $*` if [ $? != 0 ]; then usage; exit; fi #echo "Options are:"$* for i in $* do case $i in -m) METHOD=$3; shift 2;; -p) PS2PS_OPT="yes"; shift 1;; -e) EPS2EPS_OPT="yes"; shift 1;; -a) AUTO="yes"; shift 1;; -k) CLEAN_OPT=no; shift 1;; -i) FORCE_EPSI_OPT="yes"; shift 1;; -H) OWN_HEADER_OPT=$3; shift 2;; -M) MASTER_FILE_OPT=$3; shift 2;; -h) usage; exit;; --) shift break;; esac # echo "Remaining options are:"$* done shift 1; # To drop the -- added by command set - - `getopt cho: $*` #echo "After all Remaining options are:"$* if [ $# -lt 1 ] then echo "Error: No input parameter file"; usage; exit; fi #echo "toto" if [ ! -f $1 -o ! -r $1 ] ; then echo "Error: File $1 unreadable" exit 1 fi if [ $FORCE_EPSI_OPT = no ] ; then detect_ps2eps_filter; fi if [ x$MASTER_FILE_OPT != "x" -a x$OWN_HEADER_OPT != "x" ]; then echo "Error: options -M and -H are incompatible" exit 1 fi if [ x$MASTER_FILE_OPT != "x" ] ; then if [ ! -f $MASTER_FILE_OPT -o ! -r $MASTER_FILE_OPT ]; then echo "Error: file $MASTER_FILE_OPT unreadable" exit 1 fi fi if [ x$OWN_HEADER_OPT != "x" ]; then if [ ! -f $OWN_HEADER_OPT -o ! -r $OWN_HEADER_OPT ]; then echo "Error: file $OWN_HEADER_OPT unreadable" exit 1 fi fi MAIN=`basename $1 "\..*"` # Check for Dos files if [ `wc -l < $1` -eq 1 ] ; then cat < unix-MAIN and then run the script on unix-MAIN EOF echo " (with MAIN="$MAIN")" exit 1 fi # Check for bash noclober option if [ `basename $SHELL` = bash ] ; then set +o noclobber fi detect_mktemp; if [ x$OWN_HEADER_OPT != "x" ]; then cat $OWN_HEADER_OPT > ${MAIN}.header else if [ x$MASTER_FILE_OPT != "x" ]; then # Extract the header of the file, is, all from first line to # the "\]begin{document}" HEADERSIZE=`grep -n "^[\]begin{document}" ${MASTER_FILE_OPT} | head -1 | cut -f1 -d:` if [ x${HEADERSIZE} = "x" ]; then echo "Error: no \\\\begin{document} found in file "${MASTER_FILE_OPT} exit 1 fi head -${HEADERSIZE} ${MASTER_FILE_OPT} > ${MAIN}.header else HEADERSIZE=`grep -n "^[\]begin{document}" $1 | head -1 | cut -f1 -d:` if [ x${HEADERSIZE} = "x" ]; then echo "Error: no \\\\begin{document} found in file "$1 exit 1 fi head -${HEADERSIZE} $1 > ${MAIN}.header fi fi # Create a file with the line number of the figures { grep -n "^[ ]*[\]begin{figure}" $1 ; \ grep -n "^[ ]*[\]end{figure}" $1; } | cut -f1 -d: \ | sort -n > ${MAIN}.figlines # Proceedes the files cat ${MAIN}.figlines | while read BEGIN do { read END # Creates a file DIFF=`expr ${END} - ${BEGIN} + 1` head -${END} $1 | tail -${DIFF} | sed 's/^%.*$//' | \ sed 's/\([^\]\)%.*$/\1/'> ${MAIN}.figure # Debug: grep "\pdfrackincludegraphics\[.*\]{.*}" ${MAIN}.figure # Comment on the regular expression used # The (extended) regular expr for egrep has 4 parts: # - ^[^%] : excludes any '%' in the beginning of the line (to # avoid to match a pdfrackincludegraphics in comments # - \pdfrackincludegraphics : just matches the macro name # - (\[[^]]*\])? : the optionnal options # the (...)? means that this subpart is repeated 0 or 1 time (need egrep) # the \[...\] are juste the delimiters of LaTeX option # the [^]]* matches any sequence without any ']' # - {[^}]*} : the name of the figure # The regular expersions used by sed is quite the same, except that, # - because de (...)? is not allowed, two expressions are used # - there are pair of \( \) is used to capture the name of the figure # - there is a .*$ used to capture the end of the line if [ $AUTO = "no" ]; then egrep "^[^%]*\pdfrackincludegraphics(\[[^]]*\])?{[^}]*}" ${MAIN}.figure | \ sed -e 's/^[^%]*\\pdfrackincludegraphics\[.*\]{\([^}]*\)}.*$/\1/' \ -e 's/^[^%]*\\pdfrackincludegraphics{\([^}]*\)}.*$/\1/' \ > ${MAIN}.fignames else egrep "^[^%]*\includegraphics(\[[^]]*\])?{[^}]*}" ${MAIN}.figure | \ sed -e 's/^[^%]*\\includegraphics\[.*\]{\([^}]*\)}.*$/\1/' \ -e 's/^[^%]*\\includegraphics{\([^}]*\)}.*$/\1/' \ > ${MAIN}.fignames fi for FIGNAME in `cat ${MAIN}.fignames` do echo "----------------------------------------------" echo " ---> Converting figure $FIGNAME" compileOneFigure; done } done \rm ${MAIN}.figlines ${MAIN}.header ${MAIN}.figure ${MAIN}.fignames