#!/bin/sh
#!/bin/sh -x
#!/bin/bash
#
# listbib
#
# List the contents of all given BibTeX files (bibliographic data bases,
# extension .bib).
# Prerequisites:
#   LaTeX 2e, <1999/06/01> will work (earlier ones might)
#   bibtex 0.99b
#   package listbib, version 2.0 or later
#
# If we had bash, we could do some decent programming. However, listbib
# must also work with something as braindead as solaris 2.7 /bin/sh,
# so we won't...
#
# Copyright Volker Kuhlmann <v.kuhlmann@elec.canterbury.ac.nz>
# Released under the GNU General Public License (GPL) Version 2.
#
# Volker Kuhlmann
#   15, 16, 17 Mar; 12, 15 Apr; 30 Jul; 28 Aug 2000
#

VERSION="VK 1.2.3, 28 Aug 2000"

# The root of the filenames generated by latex etc.
#outfile="listbib-$$"	# numbers are awkward
#outfile="listbib"   	# not good!
outfile="listedbibs"


####
#### Usage
#
usage() {
    echo "
Usage: `basename $0` [OPTIONS] [BIBFILE[.bib] ..] BIBFILE_N[.bib]
Version $VERSION

Options:
  -h|--help              shows help
  -o|--output FILE       generates FILE.dvi / FILE.ps (default $outfile)
  -O|--same              as -o, but generate FILE.dvi and BIBFILE_N.ps
  -p|--ps|--postscript   generate PostScript as well as dvi
  -d|--deltemp           delete all generated files but .dvi
  -P|--psonly            generate only PostScript (delete all generated files
                           but .ps)
  --                     stop option processing; only .bib files remain

Examples:
  List contents of mystrings.bib and mybib.bib, generating $outfile.dvi:
      listbib -d mystrings.bib mybib.bib
  As before, but only generate $outfile.ps:
      listbib -P mystrings.bib mybib.bib
  Generate mybib.ps instead:
      listbib -P -O mystrings.bib mybib.bib
"
    exitwith ErrUsage
}

####
#### Error/Exit codes
#
exitwith() {
    exec 1>&2  # write stdout on stderr instead
  case "$1" in
    ErrUsage|ErrHelp)
	# usage already displayed
	exit 1;;
    ErrTex)
    	echo "File '$2' already exists."
	exit 2;;
    ErrListbibtex)
    	echo "Refusing to create temp file 'listbib.tex'. That file already"
	echo "exists, and an infinite loop would result."
	exit 3;;
    ErrCall)
    	echo "An error occured."
	echo "Investigate by running $2 on '$3',"
	echo "or by examining log file '$outfile$4'."
	exit 4;;
    ErrStop)
    	exit 8;;
    ErrMissingParameter)
	echo "A required parameter for option $2 is missing."
	echo "Call with -h for help."
	exit 9;;
    *)
	echo "Error: exitwith() was called with illegal error code '$1'."
	exit 19;;
  esac
}

####
#### Parse command line
#
checkargmm() {
    test "$1" != "--" -a "$2" != "--"
    #true  # uncomment this to allow "--" as argument to an option
}
checkarg2() {
    test $# -ge 2 && checkargmm "$2" && return
    exitwith ErrMissingParameter "$1"
}
parse_cmd_line() {
    unset -v ps deltmp psonly outfileps
    if [ $# -eq 0 ]; then usage; fi
    while [ -n "$1" ]; do
    	case "$1" in
	    -h|--help)
	    	    usage;;
	    -o|--output)
	    	    checkarg2 "$@"; outfile="$2"; shift;;
	    -O|--same)
	    	    test -z "$2" && usage
		    eval outfileps=\${$#}
		    # strip trailing ".bib":
		    concat_bibnames "$outfileps"; outfileps="$listbibs";;
	    -p|--ps|--postscript)
	    	    ps="1";;
	    -d|--deltemp)
	    	    deltmp="1";;
	    -P|--psonly)
	    	    psonly="1";;
	    -PO|-OP)
	    	    shift; set FILL -P -O "$@";;
	    -po)
	    	    shift; set FILL -p -o "$@";;
	    -dpo|-pdo)
	    	    shift; set FILL -d -p -o "$@";;
	    --)     shift;;
	    *)	    break;;
	esac
	shift
    done
    #fileargs=("$@")
    fileargs="$@"
}

####
#### Functions
#
concat_bibnames() {
    listbibs=
    while [ -n "$1" ]; do
    	#listbibs="$listbibs,$1"
	if [ -n "$listbibs" ]; then listbibs="$listbibs,"; fi
    	listbibs="$listbibs`echo $1 | sed -e 's,\.$,,' -e 's,.bib$,,'`"
	shift
    done
}

idstring="% listbib $VERSION"
check_tex_is_ours() {
    # exit with error if existing .tex is not a listbib one
    test -f "$outfile".tex || return
    awk "/$idstring/ {exit 0}; {exit 1}" "$outfile".tex \
    	|| exitwith ErrTex "$outfile".tex
}

create_latexfile() {
    test "$outfile" = "listbib" && exitwith ErrListbibtex
    
    cat >"$outfile".tex - <<EOF
    	$idstring
	% File automatically generated by listbib. Delete if you wish.
	\\batchmode
	\\def\\listbibs{$listbibs}
	\\input{listbib}
EOF
}

run_latex() {
    echo "Running latex ..."
    latex >/dev/null </dev/null "$outfile"
    # a non-zero exit code means termination with error
    # This assumes the latex program does set the exit status. Tough if not...
    test $? -ne 0 && exitwith ErrCall "latex" "$outfile" .log
    true
}

run_bibtex() {
    echo "Running bibtex ..."
    #bibtex >/dev/null </dev/null "$outfile"
    bibtex "$outfile"
    test $? -ne 0 && exitwith ErrCall "bibtex" "$outfile" .blg
    true
}

#LaTeX Warning: There were undefined references.
#LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
#LaTeX Warning: Citation `Book' undefined on input line 8.
make_dvi() {
    test -r "$outfile".aux && { rm "$outfile".aux || return; }
    test -r "$outfile".bbl && { rm "$outfile".bbl || return; }
    run_latex
    run_bibtex
    run_latex
    # just in case...
    warn1='There were undefined references\.'
    warn2='Label\(s\) may have changed\. Rerun to get cross-references right.'
    warn3="Citation \`Book\' undefined on input line "
    egrep >/dev/null "LaTeX Warning: ($warn1|$warn2|$warn3)" "$outfile".log \
    	&& {
	#cp "$outfile".log debug.log
	echo "Again"
	run_latex
    }
    true
}

run_dvips() {
    [ -z "$outfileps" ] && outfileps="$outfile"
    if [ -n "$ps" -o -n "$psonly" ]; then
        echo "Running dvips ..."
        dvips >/dev/null 2>&1 -o "$outfileps.ps" "$outfile"
    fi
}

rm_temp() {
    if [ -n "$deltmp" -o -n "$psonly" ]; then
        rm  >/dev/null 2>&1 "$outfile".aux "$outfile".bbl "$outfile".blg \
	    	"$outfile".log "$outfile".tex
    fi
    test -n "$psonly" && rm >/dev/null 2>&1 "$outfile".dvi
    test -n "$signal" && rm >/dev/null 2>&1 "$outfileps".ps
    true
}

####
#### Main

parse_cmd_line "$@"
concat_bibnames $fileargs
echo "listbib $VERSION"
echo "Listing bibliographies:" $listbibs
check_tex_is_ours
signal=""
trap "echo >&2 'Deleting temp files';\
      psonly=1 signal=1 rm_temp; exitwith ErrStop" HUP INT QUIT PIPE TERM
create_latexfile
make_dvi    || exit $?
run_dvips   || exit $?
rm_temp     || exit $?
