#!/bin/bash
# runbib - creates bibliography file from either a
# SGML/XML file or a LaTeX file
# Markus Hoenicka <markus@mhoenicka.de> 010510
# $Id: runbib.in,v 1.14.2.6 2006/01/02 22:38:16 mhoenicka Exp $
# OPTIONS: -d (database) -h (invoke help), -S bibliography-style,
#          -t type (db31|db31x|teix|bibtex)
# relies on these external programs: (open)jade (db31)
#                                    xsltproc (db31x, teix)
#                                    textutils (bibtex)

### start user-customizable section
# stylesheets
citlist="/usr/share/refdb/dsssl/citations.dsl"
makecss="/usr/share/refdb/dsssl/makecss.dsl"
citlistx="/usr/share/refdb/xsl/citations.xsl"
db2teix="/usr/share/refdb/xsl/bibdb2tei.xsl"
makecssx="/usr/share/refdb/xsl/makecss.xsl"
teihtml="/usr/share/refdb/xsl/tei-refdb-xsl/tei-html/tei-refdb-html.xsl"
teifo="/usr/share/refdb/xsl/tei-refdb-xsl/tei-fo/tei-refdb-fo.xsl"
docbkhtml="/usr/share/refdb/xsl/docbk-refdb-xsl/docbk-html/docbk-refdb-html.xsl"
docbkxhtml="/usr/share/refdb/xsl/docbk-refdb-xsl/docbk-xhtml/docbk-refdb-xhtml.xsl"
docbkfo="/usr/share/refdb/xsl/docbk-refdb-xsl/docbk-fo/docbk-refdb-fo.xsl"

# the programs used to extract the IDs from the document sources
myjade=""
myxsltproc=""

# the textutils commands
mysort=sort
myuniq=uniq

# the refdbib command
myrefdbib=refdbib

# the SGML and XML declarations
sgmldecl="/usr/share/refdb/declarations/docbook.dcl"
xmldecl="/usr/share/refdb/declarations/xml.dcl"

### end user-customizable section

# some initialization
databaseopt=""
encodingopt=""
outtype=db31
username=""
useropt=""
passwd=""
passwdopt=""
portarg=""
skip_id=""
startnumber="1"
numopt=""
cssfile=""

# this allows to include or ignore marked sections in the SGML file
includearg=""

# the server IP address is passed to refdbib
iparg=""

# functions
fixdoctype ()
{
# jade and openjade erroneously forget a space in the doctype line
# this problem is *only* fixed in OpenJade 1.3.1, but this function
# will not alter this version's correct output
    sed 's/\(<?.*\)\"\"\(.*\)/\1\" \"\2/' < $1 > $1.$$

    if [ $? -ne 0 ]; then
        echo "error while post-processing id file"
        exit 1
    fi
	
    mv $1.$$ $1
}

manglexsl ()
{
# refdb sends us a generic xsl stylesheet. We need to create
# one html stylesheet and one fo stylesheet by importing the proper
# refdb xsl stylesheets. DocBook gets an additional xhtml stylesheet
# we'll also create a CSS file for all (x)html output
    local basename=${1%.*}

    $myxsltproc $makecssx $1 > $basename.css

# todo: test whether $cssfile is an url
    if [ -n "$cssfile" ] && [ "$cssfile" != "$basename.css" ]; then
	if [ $2 = "TEI" ]; then
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$teihtml\"/>& ; s&<!-- REFDBBIBSTYLE -->.*<!-- /REFDBBIBSTYLE -->&& ; s&<!--CSSFILE/-->&<xsl:param name=\"html.stylesheet\">$cssfile</xsl:param>&' < $1 > $basename.html.xsl" | sh
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$teifo\"/>& ; s&<!--CSSFILE/-->&&' < $1 > $basename.fo.xsl" | sh
	elif [ $2 = "DOCBOOK" ]; then
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$docbkhtml\"/>& ; s&<!-- REFDBBIBSTYLE -->.*<!-- /REFDBBIBSTYLE -->&& ; s&<!--CSSFILE/-->&<xsl:param name=\"html.stylesheet\">$cssfile</xsl:param>&' < $1 > $basename.html.xsl" | sh
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$docbkxhtml\"/>& ; s&<!-- REFDBBIBSTYLE -->.*<!-- /REFDBBIBSTYLE -->&& ; s&<!--CSSFILE/-->&<xsl:param name=\"html.stylesheet\">$cssfile</xsl:param>&' < $1 > $basename.xhtml.xsl" | sh
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$docbkfo\"/>& ; s&<!--CSSFILE/-->&&' < $1 > $basename.fo.xsl" | sh
	fi
    elif [ -s "$basename.css" ]; then
	if [ $2 = "TEI" ]; then
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$teihtml\"/>& ; s&<!-- REFDBBIBSTYLE -->.*<!-- /REFDBBIBSTYLE -->&& ; s&<!--CSSFILE/-->&<xsl:param name=\"html.stylesheet\">$basename.css</xsl:param>&' < $1 > $basename.html.xsl" | sh
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$teifo\"/>& ; s&<!--CSSFILE/-->&&' < $1 > $basename.fo.xsl" | sh
	elif [ $2 = "DOCBOOK" ]; then
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$docbkhtml\"/>& ; s&<!-- REFDBBIBSTYLE -->.*<!-- /REFDBBIBSTYLE -->&& ; s&<!--CSSFILE/-->&<xsl:param name=\"html.stylesheet\">$basename.css</xsl:param>&' < $1 > $basename.html.xsl" | sh
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$docbkxhtml\"/>& ; s&<!-- REFDBBIBSTYLE -->.*<!-- /REFDBBIBSTYLE -->&& ; s&<!--CSSFILE/-->&<xsl:param name=\"html.stylesheet\">$basename.css</xsl:param>&' < $1 > $basename.xhtml.xsl" | sh
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$docbkfo\"/>& ; s&<!--CSSFILE/-->&&' < $1 > $basename.fo.xsl" | sh
	fi
    else
	if [ $2 = "TEI" ]; then
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$teihtml\"/>& ; s&<!-- REFDBBIBSTYLE -->.*<!-- /REFDBBIBSTYLE -->&& ; s&<!--CSSFILE/-->&&' < $1 > $basename.html.xsl" | sh
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$teifo\"/>& ; s&<!--CSSFILE/-->&&' < $1 > $basename.fo.xsl" | sh
	elif [ $2 = "DOCBOOK" ]; then
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$docbkhtml\"/>& ; s&<!-- REFDBBIBSTYLE -->.*<!-- /REFDBBIBSTYLE -->&& ; s&<!--CSSFILE/-->&&' < $1 > $basename.html.xsl" | sh
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$docbkxhtml\"/>& ; s&<!-- REFDBBIBSTYLE -->.*<!-- /REFDBBIBSTYLE -->&& ; s&<!--CSSFILE/-->&&' < $1 > $basename.xhtml.xsl" | sh
	    echo "sed 's&<!-- REFDBSTYLESHEET -->.*<!-- /REFDBSTYLESHEET -->&<xsl:import href=\"$docbkfo\"/>& ; s&<!--CSSFILE/-->&&' < $1 > $basename.fo.xsl" | sh
	fi
    fi

    rm $1
}

mangledsssl ()
{
# refdb sends us a dsssl stylesheet. We need to create
# a CSS file for all (x)html output. We first send the driver file through
# a dsssl script to isolate the html section (otherwise we'd get another
# definition for each variable from the print section), then grep for the
# definitions, and convert them to css
    local basename=${1%.*}

    $myjade -t sgml -d $makecss $1 | grep "(define refdb-" | sed 's/(define refdb-text-indent \(.*\))/p.BIBLIOMIXED {text-indent: \1;}/ ;  s/(define refdb-start-indent \(.*\))/p.BIBLIOMIXED {margin-left: \1;}/ ; s/(define refdb-font-size \(.*\))/p.BIBLIOMIXED {font-size: \1;}/' > $basename.css

    if [ -n "$cssfile" ] && [ "$cssfile" != "$basename.css" ]; then
	    echo "sed 's&(define %stylesheet% #f)&(define %stylesheet% \"$cssfile\")&' < $1 > $basename.dsl$$" | sh
	    mv $basename.dsl$$ $basename.dsl
    elif [ -s "$basename.css" ]; then
	    echo "sed 's&(define %stylesheet% #f)&(define %stylesheet% \"$basename.css\")&' < $1 > $basename.dsl$$" | sh
	    mv $basename.dsl$$ $basename.dsl
    fi
}

# read the command line options
while getopts ":d:E:G:hi:Im:N:p:S:t:u:w:" opt; do
  case $opt in
    d  ) databaseopt="-d "$OPTARG;;
    E  ) encodingopt="-E "$OPTARG;;
    G  ) cssfile=$OPTARG;;
    h  ) echo "creates refdb bibliography from a SGML, XML, or Latex document"
	 echo 'usage: runbib [-d database] [-E encoding] [-G cssfile] [-h] [-i server-ip] [-I] [-m includevar] [-N number] [-S style] [-t type] [-u username] [-w password] file1 [file2...]'
	 echo "Options: -d select default database"
	 echo "         -E set output character encoding"
	 echo "         -G set the path or URL of a CSS file for (x)html output"
	 echo "         -h print this help and exit"
	 echo "         -i set server IP address"
	 echo "         -I skip ID extraction (provide your own IDs)"
	 echo "         -m specify variable to include marked sections"
	 echo "         -N set start of reference numbering"
	 echo "         -S select bibliography style"
	 echo "         -t select output type (db31|db31x|teix|bibtex)"
	 echo "         -u set username"
	 echo "         -w set password"
	 exit 0 ;;
    i  ) iparg=" -i "$OPTARG;;
    I  ) skip_id="t";;
    m  ) includearg=$includearg" -i "$OPTARG;;
    N  ) startnumber=$OPTARG;;
    p  ) portarg=" -p $OPTARG";;
    S  ) style=$OPTARG;;
    t  ) outtype=$OPTARG;;
    u  ) username=$OPTARG;;
    w  ) passwd=$OPTARG;;
    \? ) echo 'usage: runbib [-d database] [-G cssfile] [-h] [-i server-ip] [-I] [-i includevar] [-N number] [-S style] [-t type] [-u username] [-w password] file1 [file2...]'
	 echo 'type runbib -h to invoke help'
	 exit 1;;
  esac
done

# correct the index so the filename argument is always $1
shift $(($OPTIND - 1))

# check arguments
if [ $outtype != "db31" ] && [ $outtype != "bibtex" ] &&
    [ $outtype != "db31x" ] && [ $outtype != "teix" ]; then
    echo "invalid output type"
    exit 1
fi

if [ -n "$username" ]; then
    useropt=" -u $username"
fi

if [ -n "$passwd" ]; then
    passwdopt=" -w $passwd"
fi

if [ -n "$startnumber" ]; then
    numopt=" -N $startnumber"
fi

for filename in $*; do
    # extract the basename from the argument
    basename=${filename%.*}

### DocBook SGML
    if [ $outtype = "db31" ]; then
	# create a dummy bibliography file to get rid of the error msg
	if [ ! -f "$basename.bib.sgml" ]; then
	    touch $basename.bib.sgml
	fi

	if [ ! -n "$skip_id" ]; then
	    # first we run (open)jade with the citations.dsl stylesheet
            # to extract a list of citations from the source document

	    $myjade $includearg -t xml -d $citlist $sgmldecl $filename > $basename.id.xml
	    # this command will return an error if the bibliography does
	    # not exist yet. Therefore we can't test for an error condition
	    # here
	    #if [ $? -ne 0 ]; then
	        #exit 1
	    #fi

	    # due to a bug in both jade and openjade we need to doctor the
	    # doctype line to get a well-formed document
	    fixdoctype $basename.id.xml

	fi

	# then we run refdbib with the intermediate xml file to retrieve
	# the bibliography file and the style specification file
	
	$myrefdbib $databaseopt $encodingopt $useropt $passwdopt $numopt $portarg $iparg -S $style -D "." -t db31 $basename.id.xml > $basename.bib.sgml
	if [ $? -ne 0 ]; then
	    # move the output to error files so we can use the script
	    # in makefiles
	    mv $basename.bib.sgml $basename.bib.sgml.err
	    mv ${style%.}.dsl ${style%.}.dsl.err
	    exit 1
	fi

	# need to create the css file
	mangledsssl ${style%.}.dsl

### DocBook XML
    elif [ $outtype = "db31x" ]; then
	# create a dummy bibliography file to get rid of the error msg
	if [ ! -f "$basename.bib.xml" ]; then
	    touch $basename.bib.xml
	fi

	if [ ! -n "$skip_id" ]; then
	    # extract IDs with xsltproc
	    $myxsltproc --catalogs $citlistx $filename > $basename.id.xml
	fi

	$myrefdbib $databaseopt $encodingopt $useropt $passwdopt $numopt $portarg $iparg -S $style -D "." -t db31x $basename.id.xml > $basename.bib.xml
	if [ $? -ne 0 ]; then
	    # move the output to error files so we can use the script
	    # in makefiles
	    mv $basename.bib.xml $basename.bib.xml.err
	    mv ${style%.}.xsl ${style%.}.xsl.err
	    exit 1
	fi

	# need to create three (html/xhtml/fo) xsl stylesheets
	manglexsl ${style%.}.xsl "DOCBOOK"

### TEI XML
    elif [ $outtype = "teix" ]; then
	# same procedure as above, but for TEI xml documents
	# create a dummy bibliography file to get rid of the error msg
	if [ ! -f "$basename.bib.xml" ]; then
	    touch $basename.bib.xml
	fi

	if [ ! -n "$skip_id" ]; then
	    # extract IDs with xsltproc
	    $myxsltproc --catalogs $citlistx $filename > $basename.id.xml
	fi

	$myrefdbib $databaseopt $encodingopt $useropt $passwdopt $numopt $portarg $iparg -S $style -D "." -t teix $basename.id.xml > $basename.bib.xml
	if [ $? -ne 0 ]; then
	    # move the output to error files so we can use the script
	    # in makefiles
	    mv $basename.bib.xml $basename.bib.xml.err
	    mv ${style%.}.xsl ${style%.}.xsl.err
	    exit 1
	fi

	# the bibliography is in DocBook notation, transform to TEI
	$myxsltproc --catalogs $db2teix $basename.bib.xml > $basename.bib.xml.$$
	if [ $? -ne 0 ]; then
	    mv $basename.bib.xml.$$ $basename.bib.xml.err
	    mv ${style%.}.xsl ${style%.}.xsl.err
	    exit 1
	fi

	# the bibliography carries its own prolog, comment it out
	sed 's/\(<?xml.*\)/<!-- \1 -->/ ; s/\(<!DOCTYPE.*\)/<!-- \1 -->/' < $basename.bib.xml.$$ > $basename.bib.xml
	rm $basename.bib.xml.$$

	manglexsl ${style%.}.xsl "TEI"

### BibTeX
    else # bibtex output
	if [ ! -r "$filename" ]; then
	    filename=$filename.aux
	    if [ ! -r "$filename" ]; then
		echo "cannot read input file"
		exit 1
            fi
        fi

	$mysort $filename | $myuniq | $myrefdbib $databaseopt $encodingopt $useropt $passwdopt $iparg -S $style -t bibtex > $basename.bib
	if [ $? -ne 0 ]; then
	    echo "No references retrieved from $filename"
	fi
    fi
done

exit 0