#!/bin/ksh93
##
## This is file `bibexport.sh', initially generated with the docstrip utility.
## The original source files were: bibexport.dtx  (with options: `script')
## 
## This work may  be distributed and/or modified under  the conditions of
## the LaTeX Project  Public License, either version 1.3  of this license
## or (at  your option)  any later version.   The latest version  of this
## license is in
## 
##   http://www.latex-project.org/lppl.txt
## 
## and version 1.3 or later is part of all distributions of LaTeX version
## 2005/12/01 or later.
## 
## This work has the LPPL maintenance status `maintained'.
## The Current Maintainer of this work is Nicolas Markey.
## 
## \CharacterTable
##  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
##   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
##   Digits        \0\1\2\3\4\5\6\7\8\9
##   Exclamation   \!     Double quote  \"     Hash (number) \#
##   Dollar        \$     Percent       \%     Ampersand     \&
##   Acute accent  \'     Left paren    \(     Right paren   \)
##   Asterisk      \*     Plus          \+     Comma         \,
##   Minus         \-     Point         \.     Solidus       \/
##   Colon         \:     Semicolon     \;     Less than     \<
##   Equals        \=     Greater than  \>     Question mark \?
##   Commercial at \@     Left bracket  \[     Backslash     \\
##   Right bracket \]     Circumflex    \^     Underscore    \_
##   Grave accent  \`     Left brace    \{     Vertical bar  \|
##   Right brace   \}     Tilde         \~}
##

## Version number
VERSION="3.01";
## Release date
VDATE="2011/11/28";

typeset -r FPROG=${.sh.file}
typeset -r PROG=${FPROG##*/}
SDIR=${FPROG%/*}
if [[ ${ uname -s; } == 'SunOS' ]]; then
	SED='gsed'
	GREP='/usr/xpg4/bin/grep'
else
	SED='sed'
	GREP='grep'
fi

function showUsage {
    getopts -a ${PROG} "${ print ${USAGE} ; }" OPT --man
}

function checkversion {
	kpsewhich expcites.bst > /dev/null || print '
-----------
--Warning-- file expcites.bst not found.
-----------'
	${GREP} -q "${VDATE}" ${ kpsewhich expkeys.bst ; } ||
	print '
-----------
--Warning-- the version of the .bst files does not match with that of this
            script.
-----------'
}

USAGE='[-?'"${VERSION}"' ]
[-copyright?Copyright (c) 2011 Nicolas Markey <markey@lsv.ens-cachan.fr>.]
[-copyright?Copyright (c) 2015 Jens Elkner (ksh93 port).]
[-license?LaTeX Project Public License 1.3]
[+NAME?'"${PROG}"' - extract BibTeX entries out of .bib files]
[+DESCRIPTION?'"${PROG}"' is a tool to extract BibTeX entries out of the given \b.bib\b \afile\as. The first option block show generic options for all ksh scripts (if possible), whereby the second block shows basic, and the third one advanced options. NOTE that the old non-POSIX compatible options -es and -ec are deprecated and need to be prefixed with two dashes instead of one, i.e. --es and --ec.]
[h:help?Print this help and exit.]
[F:functions?Print a list of all functions available.]
[T:trace]:[fnList?A comma separated list of functions of this script to trace (convinience for troubleshooting).]
[+?]
[a:all?Export the entire .bib files.]
[o:output-file]:[bib?Write output to file \abib\a. Default: \bbibexport.bib\b]
[t:terse?Operate silently.]
[v:version?Print version number and exit.]
[+?]
[b:file]:[file?Use the \b.bst\b style \afile\a. Default: \bexport.bst\b]
[c:crossref?Preserve crossref field.]
[n:no-crossref?Remove crossreferenced entries.]
[e:extra]:[file?Extra \b.bib\b \afile\a to be used (crossrefs and strings).]
[S:extras]:[file?Extra \b.bib\b \afile\a to be used (for strings).]
[C:extrac]:[file?Extra \b.bib\b \afile\a to be used (for crossrefs).]
[98:es]:[file?Deprecated. Use -S \afile\a instead.]
[99:ec]:[file?Deprecated. Use -C \afile\a instead.]
[p:preamble?Write a preamble at beginning of output.]
[r:replace]:[file?Replace \b.bib\b \afile\a(s) in the .aux file.]
[d:dry?Create intermediate files but do not run BibTeX.]
\n\n\afile\a ...
'

# DRY is used to create files but not run BibTeX.
# CREF is the number of citations of crossrefs from which the crossref'd entry
#   must be included.
# BANNER is used to turn on or off the preamble informations in the output.
# ALL is a flag set to 1 when '-a' is given.
# REPLACEBIB ('-r') is set to 1 when the \bibdata of the .aux input file
#   must be ignores (then '-e' must be used).
# TERSE '-terse' will be used if '-t' is given.
integer DRY=0 CREF=0 BANNER=0 ALL=0 REPLACEBIB=0 TERSE=0
# For DRY
ARGS="$@"

# EXT is the extension of the input file(s) (.aux, or .bib if '-a')
EXT='.aux'
# EXTRA and EXTRABIB are two copies of the extra files ('-e'), used to
# include crossref'd entries and @string's
EXTRA=
EXTRABIB=
# NEWBIB will contain the argument given to -r
NEWBIB=
# BST is the .bst file to be used (default to export.bst)
BST='export'


function doMain {
	[[ -z $1 ]] && getopts -a ${PROG} "${ print ${USAGE} ; }" OPT '-?' && exit 1
	checkversion

	# FILE will be the main input file(s) (.aux or .bib, depending on '-a')
	typeset FILE= T SPACE= TMPFILE

	while [[ -n $1 ]]; do
		## - list of input files
		T=${1%/*}
		[[ -z ${sh.match} || $T == '.' ]] && T="${1##*/}" || T="$1"
		FILE+="${SPACE}${T%${EXT}}${EXT}"
		(( ALL )) && SPACE=',' || SPACE=' '
		shift
	done

	FINALFILE=${OUTPUT};
	[[ -z ${FINALFILE} ]] && FINALFILE="bibexport.bib";

	TMPFILE="bibexp.${ date +%s ; }"
	if [[ -z ${EXT} ]]; then				## we export all entries
		if [[ -z ${EXTRA} ]]; then			## we have no extra files
			cat > ${TMPFILE}.aux <<EOF
\citation{*}
\bibdata{${FILE}}
\bibstyle{${BST}}
EOF
		else
			## we have extra files (e.g. for crossrefs) but want all entries
			## from ${FILE} we first extract the keys to be used:
			cat > ${TMPFILE}.aux <<EOF
\citation{*}
\bibdata{${FILE}}
\bibstyle{expkeys}
EOF
			## This run may generate errors. We redirect the output:
			bibtex -min-crossrefs=${CREF} -terse ${TMPFILE} >/dev/null 2>&1
			mv -f ${TMPFILE}.bbl ${TMPFILE}.aux
			## and then prepare the .aux file for exporting:
			cat >> ${TMPFILE}.aux <<EOF
\bibdata{${EXTRA}${FILE}${EXTRABIB}}
\bibstyle{${BST}}
EOF
		fi
	else
		## we only export entries listed in the given .aux file:
		if (( REPLACEBIB )); then
			${SED} -e "s/bibstyle{.*}/bibstyle{${BST}}/" \
				-e "s/bibdata{.*}/bibdata{${EXTRA}${NEWBIB%,}${EXTRABIB}}/" \
				${FILE} > ${TMPFILE}.aux;
		else
			${SED} -e "s/bibstyle{.*}/bibstyle{${BST}}/" ${FILE} >${TMPFILE}.aux
		fi
	fi

	(( TERSE )) && T='-terse' T=
	if (( DRY )); then
		print "bibtex -min-crossrefs=${CREF} ${T} ${TMPFILE}"
	else
		bibtex -min-crossrefs=${CREF} ${T} ${TMPFILE}
		[[ -e ${FINALFILE} ]] && \
			mv ${FINALFILE} ${FINALFILE}-save-${ date "+%Y.%m.%d:%H.%M.%S" ; }
		print > ${FINALFILE}
	fi

	if (( BANNER )); then
		## list of cited entries
		if (( ! DRY )); then
			${SED} -i -e "s/\\\bibstyle{.*}/\\\bibstyle{expcites}/" \
				${TMPFILE}.aux
			mv ${TMPFILE}.aux ${TMPFILE}-cites.aux
			bibtex -terse -min-crossrefs=${CREF} ${TMPFILE}-cites
			print '@comment{generated using bibexport:
  creation date:\t'"${ date +'%c' ; }"'
  command:\t\t'"${PROG} ${ARGS}" >> ${FINALFILE};
			[[ -z ${EXT} ]] && \
				print "  source files:\t\t${FILETAB}\t\t\t${EXTRABIBTAB}" \
					>> ${FINALFILE}
			cat ${TMPFILE}-cites.bbl >> ${FINALFILE}
			print "  bibexport-version:\tv${VERSION} (${VDATE})"'
  bibexport-maintainer:\tmarkey(at)lsv.ens-cachan.fr' >> ${FINALFILE}
			${SED} -i -e 's/}/)/g' ${FINALFILE}
			print '}\n\n\n' >> ${FINALFILE}
			rm -f ${TMPFILE}-cites.bbl ${TMPFILE}-cites.aux ${TMPFILE}-cites.blg
		fi
	fi

	if (( CREF != 1 )); then
		if (( DRY )); then
			print "${GREP} -ivE '^ *crossref *= *[^,]+,?$' ${TMPFILE}.bbl >>" \
				${FINALFILE}
		else
			${GREP} -ivE '^ *crossref *= *[^,]+,?$' ${TMPFILE}.bbl >> \
				${FINALFILE}
		fi
	else
		if (( DRY )); then
			print "cat ${TMPFILE}.bbl >> ${FINALFILE}"
		else
			cat ${TMPFILE}.bbl >> ${FINALFILE}
		fi
	fi

	if (( DRY )); then
		print "rm -f ${TMPFILE}.bbl ${TMPFILE}.aux ${TMPFILE}.blg"
	else
		rm -f ${TMPFILE}.bbl ${TMPFILE}.aux ${TMPFILE}.blg
	fi
}

X="${ print ${USAGE} ; }"
while getopts "${X}" OPT ; do
	case ${OPT} in
		h) showUsage ; exit 0 ;;
		T)  if [[ ${OPTARG} == 'ALL' ]]; then
				typeset -ft ${ typeset +f ; }
			else
				typeset -ft ${OPTARG//,/ }
			fi
			;;
		F)
			typeset +f && exit 0
			;;

		a)
			## - export all entries in the input file(s)
			## - the input files are BibTeX files
            EXT= ALL=1
			;;
		b)
			## - specifies the .bst file to use (default to 'export.bst')
			T=${OPTARG%/*}
			[[ -z ${sh.match} || $T == '.' ]] \
				&& T="${OPTARG##*/}" || T="${OPTARG}"
			BST="${T%.bst}.bst"
			;;
		d)
			## - dry mode: we create files but do not run bibtex
			## - instead, we print what we would have done...
			DRY=1
			;;
		e)
			## - extra input files (containing crossrefs or strings)
			## - they will be included twice: once before the main file(s)
			##   (for @string's), once after (for crossrefs). We fool BibTeX
			##   by naming the first one 'file.bib' and the second one
			##   'file.bib.bib', to avoid complains.
			T=${OPTARG%/*}
			[[ -z ${sh.match} || $T == '.' ]] \
				&& T="${OPTARG##*/}" || T="${OPTARG}"
            EXTRA+="${T%.bib},"
            EXTRABIB+=",${T%.bib}.bib"
			;;
        S|98)
			## - extra input files (containing strings)
			## - will be included *before* the main files (hence not suitable
			##   for crossrefs)
			T=${OPTARG%/*}
			[[ -z ${sh.match} || $T == '.' ]] \
				&& T="${OPTARG##*/}" || T="${OPTARG}"
            EXTRA+="${T%.bib},"
			;;
		C|99)
			## - extra input files (containing crossrefs)
			## - will be included only *after* the main files (hence not
			##   suitable for @string's)
			T=${OPTARG%/*}
			[[ -z ${sh.match} || $T == '.' ]] \
				&& T="${OPTARG##*/}" || T="${OPTARG}"
            EXTRABIB+=",${T%.bib}.bib"
			;;
		o)
			## - name of the output file
			## - we force it to end with '.bib'
			T=${OPTARG%/*}
			[[ -z ${sh.match} || $T == '.' ]] \
				&& T="${OPTARG##*/}" || T="${OPTARG}"
			OUTPUT="${T%.bib}.bib"
			;;
		c)
			## - whether or not to preserve 'crossref' keys.
			## - by default, they are removed, but crossref'd entries are
			##   included.
			## - crossrefs are *always* expanded anyway.
			CREF=1
			;;
		n)
			## - to remove crossref'd entries (hence remove 'crossref' keys).
			CREF=20000
			;;
		r)
			## - to replace the file(s) given in \bibdata in the .aux file with
			##   (a) new one(s).
			REPLACEBIB=1
			T=${OPTARG%/*}
			[[ -z ${sh.match} || $T == '.' ]] \
				&& T="${OPTARG##*/}" || T="${OPTARG}"
            NEWBIB+="${T%.bib}.bib,"
			;;
		v)
			print "This is bibexport v${VERSION} (released ${VDATE})"
			exit 0
			;;
        p)
			BANNER=1
			;;
		t)
			TERSE=1
			;;
	esac
done
X=$((OPTIND-1))
shift $X && OPTIND=1
unset X T

doMain "$@"

## 
##
## End of file `bibexport.sh'.
