#!/bin/sh
#
#	shell script to convert refer (or bib) databases to BiBTeX format
#
#	Most of the shell script is based on that by Jonathan Bowen
#	The awk and sed scripts are the work of Peter King
#	with some ideas stolen from Jonathan Bowen
#
#
SEDFILE=${TMP-/tmp}/ref2b$$.sed
AWKFILE=${TMP-/tmp}/ref2b$$.awk
KEYFILE=${TMP-/tmp}/ref2b$$.key
NKEYFILE=${TMP-/tmp}/ref2b$$.nkey
AKEYFILE=
CAPSFILE=
PROGNAME=`basename $0`
NAUTHOR=3
LAUTHOR=3
ERRFILE=${PROGNAME}.errs
DEFAULTWIDTH=72
WIDTH=$DEFAULTWIDTH
NAMEDFILES=false
BIB=bib
DEBUG=false

GEN=`date`" on "`hostname`
NAME=$BIB
STDIN=''
NEWFILE=""

while expr X$1 : X'-' > /dev/null
do
    case "$1" in
    -|-0|-w)
	WIDTH=-1
	;;
    -[1-9]|-[1-9][0-9]|-[1-9][0-9][0-9])
	WIDTH=`expr X"$1" : X'-\(.*\)'`
	;;
    -c) : capitals file
	CAPSFILE="$2"
	shift
	;;
    -d) : Enable debugging
	DEBUG=true
	;;
    -e) : error file
	ERRFILE="$2"
	shift
	;;
    -kf) : key used file
	AKEYFILE=$2
	shift
	;;
    -k) : no of authors in key
	NAUTHOR=$2
	shift
	;;
    -l) : no of authors name letters to use
	LAUTHOR=$2
	shift
	;;
    -n) : Named output files
	NAMEDFILES=true
	;;
    -u|-U)
	echo "Usage: $PROGNAME [ options ] [ file ... ]
Converts Unix \"refer\" format to \"BibTeX\" database format.
-c file Use file as source of protected words in titles
-d	enable debugging			(default=$DEBUG)
-e file error output in "file"			(default=$ERRFILE)
-kf file Use file to initialise keys used
-k N 	Use N author's names for key 		(default=$NAUTHOR)
-l N 	Use N characters of author's name for key (default=$LAUTHOR)
-n	output to named files (ext \".$BIB\")	(default=$NAMEDFILES)
-w	no maximum width
-u	display usage information
-N	maximum width of N characters (1-999)	(default=$DEFAULTWIDTH)"
	exit 0
	;;
    -*)
	echo "Usage: $PROGNAME [ -[width] ] [ file ... ]"
	exit 0
	;;
    esac
    shift
done

trap "rm -f $SEDFILE $AWKFILE $KEYFILE $NKEYFILE ;exit" 0 1 2 3 15

cat </dev/null > $ERRFILE
cat </dev/null > $KEYFILE
[ $AKEYFILE  ] && [ -r $AKEYFILE ]  && cat $AKEYFILE > $KEYFILE

# although # introduces a comment to sed, this is undocumented,
# and we might as well strip it first if the file is to be used many times
# but this should work with cat replacing the sed -e here

sed -e '/^#/d' << 'ZZ' >$SEDFILE
#
# sed script to do some of the ref to bib database conversion
#
# written by Peter King, Heriot-Watt University
# You may do anything you like with this code
# EXCEPT claim that you wrote it
#
# remove as many redundant characters as possible
s/	/ /g
s/  */ /g
# convert dashes
s/ - / --- /g
s/ $//
#
# First alter the TeX special characters
# but not the first %
s/\(.\)%/\1{\\%}/g
#
s/[&#_{}]/{\\&}/g
# you may want to leave dollars (especially if you have eqn in your refs
s/\$/\\$/g
# convert the special characters and accents from troff to BibTeX
# assumes the accents are those of the Berkeley -ms with .AM
#
# convert any font rubbish  (assumes that \fR is the default )
/\\\\*f./{
	s/\\\\*f[I2]/{\\em /g
	s/\\\\*f[B3]/{\\bf /g
	s/\\\\*f[1PR]/}/g
}
/\\\\*[-*0('`^:~_/o,v".8?!QU ]/{
	s/\(.\)\\\\*\*'/{\\'\1}/g
	s/\(.\)\\\\*\*`/{\\`\1}/g
	s/\(.\)\\\\*\*^/{\\^\1}/g
	s/\(.\)\\\\*\*:/{\\"\1}/g
	s/\(.\)\\\\*\*~/{\\~\1}/g
	s/\(.\)\\\\*\*_/{\\=\1}/g
	s/\([oO]\)\\\\*\*\//{\\\1}/g
	s/\([aA]\)\\\\*\*o/{\\\1\1}/g
	s/\(.\)\\\\*\*,/{\\c{\1}}/g
	s/\(.\)\\\\*\*v/{\\v{\1}}/g
	s/\(.\)\\\\*\*"/{\\H{\1}}/g
	s/\(.\)\\\\*\*\./{\\d{\1}}/g
	s/\\\\*\*8/{\\ss}/g
	s/\\\\*\*?/{?`}/g
	s/\\\\*\*!/{!`}/g
	s/\\\\*\*(P\([lL]\)/{\\\1}/g
	s/\\\\*\*(ae\//{\\ae}/g
	s/\\\\*\*(Ae\//{\\AE}/g
	s/\\\\*\*(oe\//{\\oe}/g
	s/\\\\*\*(Oe\//{\\OE}/g
# quotes
	s/\\\\*\*Q/``/g
	s/\\\\*\*U/''/g
	s/\\\\*\*-/---/g
# convert \[space] to \0 for convenience
	s/\\\\* /\\0/g
# \0 as space between surname de\0Souza etc.
	s/\\\\*0\([a-z]*\)\\\\*0/\\0\1 /g
	s/ \([a-z]*\)\\\\*0/ \1 /g
# but trap the ones that start with a capital letter and convert them to
# ties
	s/\\\\*0/~/g
#
# now deal with special characters and Greek
	s/\\\\*(hy/-/g
	s/\\\\*(em/---/g
	s/\\\\*(co/{\\copyright}/g
	s/\\\\*(sc/{\\S}/g
	s/\\\\*(if/$\\infty$/g
	s/\\\\*(\*a/$\\alpha$/g
	s/\\\\*(\*b/$\\beta$/g
	s/\\\\*(\*g/$\\gamma$/g
	s/\\\\*(\*d/$\\delta$/g
	s/\\\\*(\*e/$\\epsilon$/g
	s/\\\\*(\*z/$\\zeta$/g
	s/\\\\*(\*y/$\\eta$/g
	s/\\\\*(\*h/$\\theta$/g
	s/\\\\*(\*i/$\\iota$/g
	s/\\\\*(\*k/$\\kappa$/g
	s/\\\\*(\*l/$\\lambda$/g
	s/\\\\*(\*m/$\\mu$/g
	s/\\\\*(\*n/$\\nu$/g
	s/\\\\*(\*c/$\\xi$/g
	s/\\\\*(\*o/$o$/g
	s/\\\\*(\*p/$\\pi$/g
	s/\\\\*(\*r/$\\rho$/g
	s/\\\\*(\*s/$\\sigma$/g
	s/\\\\*(\*t/$\\tau$/g
	s/\\\\*(\*u/$\\upsilon$/g
	s/\\\\*(\*f/$\\phi$/g
	s/\\\\*(\*x/$\\chi$/g
	s/\\\\*(\*q/$\\psi$/g
	s/\\\\*(\*w/$\\omega$/g
	s/\\\\*(\*A/A/g
	s/\\\\*(\*B/B/g
	s/\\\\*(\*G/$\\Gamma$/g
	s/\\\\*(\*D/$\\Delta$/g
	s/\\\\*(\*E/E/g
	s/\\\\*(\*Z/Z/g
	s/\\\\*(\*Y/H/g
	s/\\\\*(\*H/$\\Theta$/g
	s/\\\\*(\*I/I/g
	s/\\\\*(\*K/K/g
	s/\\\\*(\*L/$\\Lambda$/g
	s/\\\\*(\*M/M/g
	s/\\\\*(\*N/N/g
	s/\\\\*(\*C/$\\Xi$/g
	s/\\\\*(\*O/$O$/g
	s/\\\\*(\*P/$\\Pi$/g
	s/\\\\*(\*R/P/g
	s/\\\\*(\*S/$\\Sigma$/g
	s/\\\\*(\*T/T/g
	s/\\\\*(\*U/$\\Upsilon$/g
	s/\\\\*(\*F/$\\Phi$/g
	s/\\\\*(\*X/X/g
	s/\\\\*(\*Q/$\\Psi$/g
	s/\\\\*(\*W/$\\Omega$/g
}
# Now trap title words that must be capitalised
/^%[^T]/b
#
# first all words that are all capitals (at least two consecutive)
# we need the slashes to allow for M/M/1 queues
s;[A-Z][A-Z/][A-Z/0-9]*;{&};g
# and single letters (except A!)
s/\([{ ]\)\([B-Z]\)\([ :\.,}]\)/\1{\2}\3/g
s/ \([B-Z]\)$/ {\1}/
ZZ

# Now append to this any proper name that might appear in titles
# Use sed to generate a sed script !
# the input is a list of words which must remain capitalised
# one to a line
# a trailing * will be converted into a pattern at the end to get Markov,
# Markovian, etc.

cat - $CAPSFILE << ZZ | sed -e '/^#/d;s/\*$/[^ -,;]*/;s=^..*$=s/&/{\&}/g=' >> $SEDFILE
# File of Title information that must maintain its capitalised state
#
# some proper names
#
# first some mathematicians
Abel
Bernoulli
Bessel
Beta
Borel
Cauchy
Church
Rosser
Dedekind
Descartes
Dirichlet
Euclid*
Euler
Fibonacci
Fermat
Fourier
Fresnel
Frobenius
Perron
Gamma
Gauss*
Hadamard
Hilbert
Horner
Holder
Jacobi*
Jensen
Markov*
Arnoldi
Laplace
Laguerre
Lagrang*
Legendre
Leibnitz
Lipschitz
# this is really Poincare (acute accent), but the accent processing will disrupt it
Poincar
Hermite
Rayleigh
Ritz
Riemann
# this is really Rouche (acute accent), but the accent processing will disrupt it
Rouch
Stieltjes
Stiener
Schwarz
Weibull
Wald
Kronecker
Karmarkar
Kendall
Diophantine
Delbrouck
Bayes*
Schafer
Dempster
Runge
Kutta
Pollaczek
Khinchin
Palm
Erlang
Engset
Little's
Kosten
Gittins
Feller
Cox*
Poisson
Chapman
Kolmogorov
Smirnov
Weiner
Hopf
Stirling

# computing
Buzen
Gordon
Newell
Lemoine
Pierce
Jackson
Newhall
Turing
Norton
Petri
Wilkinson
Skinner
Harrison
Cambridge
Ethernet
Aloha

# coding theory
Hamming
Huffman
Reed
Shannon
Solomon
Viterbi
ZZ

# strip out the comments from the AWKFILE, just to cut down on the character count
# that awk needs to read before starting.  For a single file conversion
# this will probably make no difference
# but this should work with cat replacing the sed -e here

sed -e '/^[ 	]*#/d' -e '/#/s/[ 	]*#.*$//' << 'ZZ' > $AWKFILE
#
#	awk script to convert refer (or bib) format databases
#	to BiBTeX format.
#
#	written by Peter King, Heriot-Watt University
#	use freely, but don't claim that you wrote it
#
#	Generates keys using authors names and year
#
#	You may wish to alter treatment of key fields that are ignored
#	such as %U %W %Y etc.
#
#	NB because awk recognises end of line as a statement terminator
#	   you cannot reliably split the long lines in the script
#
#  regular expressions should be sorted according to frequency
#  so that minimal tests are made
#  From tests in a local data base the order given appears quite good
#	2883 %A
#	1813   blank lines
#	1774 %T
#	1764 %D
#	1505 %P
#	1347 %J
#	1331 %V
#	1201 %N
#	773 .. continuation lines
#	501 %C
#	424 %I
#	192 %B
#	187 %E
#	92 %S
#	89 %R
#	33 %X
#	30 %K
#	16 %O
#
BEGIN	{
	# suffices for the key generation process
	for(i=1;i<=26;i++)
		addkey[i] = substr("abcdefghijklmnopqrstuvwxyz",i,1)
	# standard BiBTeX types so that you can change the case to BOOK
	# or book, as required. Not all are used
	article = "Article"	# the @ will be added later
	book = "Book"
	booklet = "Booklet"
	inbook = "InBook"
	incollection = "InCollection"
	inproceedings = "InProceedings"
	manual = "Manual"
	mastersthesis = "MastersThesis"
	misc = "Misc"
	phdthesis = "PhDThesis"
	proceedings = "Proceedings"
	techreport = "TechReport"
	unpublished = "Unpublished"

	bibtype = misc
ZZ

# the following 'echo' commands communicate shell variables to
# the awk script.

echo >> $AWKFILE	lkey = $LAUTHOR # number of characters used from authors to make key
echo >> $AWKFILE	maxauthor = $NAUTHOR # maximum number of authors to use in
			# constructing key
echo >> $AWKFILE	errfil = \"$ERRFILE\"
echo >> $AWKFILE	keyfil = \"$KEYFILE\"
echo >> $AWKFILE	nkeyfil = \"$NKEYFILE\"
echo >> $AWKFILE	lwidth = $WIDTH
echo >> $AWKFILE	print \"@Comment{ Database converted by $PROGNAME\\n\\t$GEN}\\n\"

sed -e '/^[ 	]*#/d' -e '/#/s/[ 	]*#.*$//' << 'ZZ' >> $AWKFILE
	rx = 1
	percent = 0 # not in a reference
	}

/[^{$]\\/ || /^\\/ {	# we've protecetd all the \ we introduced in {}
	err = 1
	print "Non translated \\ symbol : Reference " rx >> errfil
	print  $0 >> errfil
	}

/^%/	{	# any % entry
	percent = 1 # in a reference
	entry = substr($0,4)
	pctchar = substr($0,2,1)
	}

/^%[AQ]/	{	# authors (multiple occurrences possible)
	A ++
	if ( $1 == "%A" ) authors[A] = entry
	else authors[A] = "{"entry"}"	# corporate authors need protection!
	if (A> maxauthor) next
		# generate the key string
	ic = 0
	lc = 1
	if ( $1 == "%A" ) keyfield = $NF
	else keyfield = $2	# corporate authors use first word
	while(ic < lkey && lc <= length(keyfield) ){
		kc = substr( keyfield, lc, 1)
		if ( kc ~ /[a-zA-Z]/ ){
			keys = keys kc
			ic++
			if (ic==lkey) next
			}
		else if ( kc == "\\" ) lc ++
		lc ++
		}
	next
	}

/^$/	{	# blank line
	if (percent) {
		# end of a reference
	refs ++
	if (T==0)	print "No title : Reference "refs" "keys >> errfil
	if (A==0)	print "No author : Reference "refs" "keys >> errfil
	if (D==0)	print "No date : Reference "refs" "keys >> errfil
	if ((!T)||(!A)||(!D))err=1


	# date processing
	nf = split(date,z)
	year = date
	kyear = year
	if(nf>1){
		xmonth = z[1]
		mm = 1
		i = 2
		while ( z[i] !~ /^[0-9][0-9][0-9][0-9]/ ) {
			xmonth = xmonth " " z[i]
			i++
			mm = 0
			}
		month = "{ " xmonth " }"

		year = z[i]
		kyear = year	# in case there is any extraneous info
		i++
		while ( i <= nf ) {
			year = year " " z[i]
			i++
			}
		if((mm) && ( xmonth ~ /^[A-Za-z.]*$/ )){
			#if the month is only letters and .
			if(xmonth ~ /^Ja/) month = "jan"
			if(xmonth ~ /^Fe/) month = "feb"
			if(xmonth ~ /^Mar/) month = "mar"
			if(xmonth ~ /^Ap/) month = "apr"
			if(xmonth ~ /^May/) month = "may"
			if(xmonth ~ /^Jun/) month = "jun"
			if(xmonth ~ /^Jul/) month = "jul"
			if(xmonth ~ /^Aug/) month = "jan"
			if(xmonth ~ /^Se/) month = "sep"
			if(xmonth ~ /^O/) month = "oct"
			if(xmonth ~ /^N/) month = "nov"
			if(xmonth ~ /^D/) month = "dec"
			}
		}
	if ( year !~ /^[0-9][0-9]*$/ ) year = "{ " year " }"

		#  sort out the editors
	if (E) {
		tew = split(alleditors,z)
		E = 1
		editor[E] = z[1]
		sc = " "
		i = 2
		while( i <= tew ){
			if ( z[i] == "and" ) {
				E++
				editor[E] = ""
				sc = ""
				}
			else {
				lastc = substr(z[i],length(z[i]),1)
				if(lastc == "," && z[i+1] !~ /^Jn*r\./ ) {
					editor[E] = editor[E] sc substr(z[i], 1, length(z[i])-1)
					if ( z[i+1] != "and" ) {
						E++
						editor[E] = ""
						sc = ""
						}
					}
				else {
					editor[E] = editor[E] sc z[i]
					sc = " "
					}
				}
			i++
			}
		}

		# classify the reference

	if (J) {
		#journal or conference

		if (C||I||((!V)&&(!N))) {
			# its a conference if there is a city, publisher
			# or no volume or issue number
			conf++
			bibtype = inproceedings
			jnl = "Booktitle"
			jtype = "Conference proceedings"
			}
		else {
			jour ++
			bibtype = article
			jnl = "Journal"
			jtype = "Journal"
			}

		if ( B||E||R||(!P)) {
			err=1
			if (B||E||R)
				print "Journal & book?: Reference "refs" "keys >> errfil
			if (!P) print "No page nos.? : Reference "refs" "keys >> errfil
			}
		if (err){
			print jtype " reference in error" >> errfil
			}
		}
	else
	if (B) {
		# article in book
		bibtype = incollection

		if (N||R||(!E)||(!I)||(!C)||(!P)||(V&&(!S))){
			err=1
			if (!E) print "No editor? Reference "refs" " keys >> errfil
			if (!I) print "No publisher? Reference "refs" " keys >> errfil
			if (!C) print "No city? Reference "refs" " keys >> errfil
			if (!P) print "No page nos.? Reference "refs" " keys >> errfil
			if (V&&(!S)) print "Volume but no Series Reference "refs" " keys >> errfil
			if (N) print "Issue no.? Reference "refs" " keys >> errfil
			if (R) print "Report? Reference "refs" " keys >> errfil

			}
		if (err) print "Article in book reference in error" >> errfil
		}
	else
	if (R) {
		#report
		bibtype = techreport

		if (E||N){
			err=1
			if (N) print "Issue no.? Reference "refs" " keys >> errfil
			if (E) print "Editor? Reference "refs" " keys >> errfil
			}
		if (err) print "Report reference in error" >> errfil
		if ( report ~ /M.*[Tt]hesis/ )	bibtype = mastersthesis
		if ( report ~ /M.*[Dd]issert/ )	bibtype = mastersthesis
		if ( report ~ /D.*[Tt]hesis/ )	bibtype = phdthesis
		if ( report ~ /D.*[Dd]issert/ )	bibtype = phdthesis
		# Working papers and preprints are classified as techreports
		# if ( report ~ /[Ww]orking/ )	bibtype = unpublished
		# if ( report ~ /[Pp]reprint/ )	bibtype = unpublished
		if ( report ~ /[Uu]npublish/ )	bibtype = unpublished
		if ( report ~ /[Mm]anual/ )	bibtype = manual

		if (bibtype== unpublished ) {
			if (other == "") other = report
			else other = report " " other
			R = 0
			report = ""
			O = 1
		}
		else
		if (bibtype == manual ) {
			TY = 1
			type = report
			# the publisher is really the organisation
			report = publisher
			R = I
			I = 0
			institute = "Organization"
			}
		else
		if ( bibtype == techreport ) {
			trw = split(report,z)
			if ( trw == 1 ) {
				N = 1
				number = z[1]
				}
			else	{
				if ( ( z[1] ~ /^Tech/ ) && ( z[2] ~ /^Rep/ ) )
					{
					z[1] = ""
					z[2] = ""
					TY = 0
					number = z[3]
					for(i=4;i<=trw;i++)
						number = number " " z[i]
					if (trw >=3) N = 1
					}
				else 	{
					type = z[1]
					i = 2
					while( i <= trw && ( z[i] !~ /^[0-9A-Z-]*$/ ) ) {
						type = type " " z[i]
						i++
						}
					if(i<trw || z[trw] ~ /^[0-9A-Z][0-9A-Z-]*$/ )
						N = 1
					while ( i <= trw ) {
						number = number " " z[i]
						i++
						}
					TY = 1
					}
				}
			# the publisher is really the institution
			report = publisher
			R = I
			I = 0
			institute = "Institution"
			}
		else
		if ( (bibtype == mastersthesis ) || ( bibtype = phdthesis )) {
			type = report
			TY = 1 # the publisher is really the school
			report = publisher
			R = I
			I = 0
			institute = "School"
			if ( ( bibtype == phdthesis ) && ( type ~ /^ *PhD  *thesis *$/ ) ) {
				type = ""
				TY = 0
				}
			if ( ( bibtype == mastersthesis ) && ( type ~ /^ *Master's  *thesis *$/ ) ) {
				type = ""
				TY = 0
				}
			}
		}
	else
	if (I) {
		# book
		bibtype = book

		if (N||E||(!C)||(V&&(!S))) {
			err=1
			if (!C)	print "No city? Reference "refs" " keys >> errfil
			if (N)	print "Issue no.? Reference "refs" " keys >> errfil
			if (E)	print "Editor? Reference "refs" " keys >> errfil
			if (V&&(!S)) print "Volume but no Series Reference "refs" " keys >> errfil
			}
		if (err) print "Book reference in error" >> errfil

		if (S && (( series ~ /[Tt]ech.*[Rr]eport/ ) || ( series ~ /[Tt]ech.*[Mm]ono/ ))){
				bibtype = techreport
				type = series
				TY = 0
				if ( series ~ /[Mm]ono/ ) TY = 1
				institute = "Institution"
				R = I
				I = 0
				report = publisher
				publisher = ""
				}
		}
	else {
		bibtype = misc
		err=1
		if( other ~ /[Uu]npublished/ ) bibtype = unpublished
		print "Unclassified reference" >> errfil
		}

	# generate key
	if(keys == "") keys = "ANON"
	keys = keys substr(kyear,3,2)
	if(keyused[keys] >=1) {
		key_suffix = keyused[keys]++
		keys = keys addkey[key_suffix]
		}
	else keyused[keys] = 1

	if (err)  {
			print "Key: " keys >> errfil
			if(A) for (i=1;i<=A;i++)
				print "%A " authors[i] >> errfil
			if(T) print "%T " title >> errfil
			if(J) print "%J "journal >> errfil
			if(B) print "%B "booktitle >> errfil
			if(V) print "%V "volume >> errfil
			if(N) print "%N "number >> errfil
			if(I) print "%I "publisher >> errfil
			if(C) print "%C "city >> errfil
			if(E) for (i=1;i<=E;i++)
				print "%E "editor[i] >> errfil
			if(S) print "%S "series >> errfil
			if(P) print "%P "pages >> errfil
			if(R) print "%R "report >> errfil
			if(D) print "%D "date >> errfil
			if(O) print "%O "other >> errfil
			print "" >> errfil
		}

	if ( other ~ /[Uu]npublished/ ) bibtype = unpublished
	if ( other ~ /[Ee]dition/ ) {
			twc = split(other,z)
			for(i=1;i<=twc;i++)
				if(z[i] ~ /[Ee]dition/) {
						edition = z[i-1]
						z[i-1] = ""
						z[i] = ""
						}
			other = z[1];
			for(i=2;i<=twc;i++) {
				other = other " " z[i]
				}
			if(!(other ~ /[^ 	]/ )) {
				# no non space characters
				other = ""
				O = 0
				}
			}

	if(O&&H) other = header " " other
	else if(H) {
		O = H
		other = header
		}

	if (J) {

		# substitute the journal abbreviations from the standard styles

		journal = "{ " journal " }"
		# {acmcs} {"ACM Computing Surveys"}
		if ( journal ~ /Comp.* Sur/ ) journal = "acmcs"
		# {acta} {"Acta Informatica"}
		if ( journal ~ /Acta Inf/ ) journal = "acta"
		# {cacm} {"Communications of the ACM"}
		if ( journal ~ /Com.* ACM/ ) journal = "cacm"
		if ( journal ~ /CACM/ ) journal = "cacm"
		# {ibmjrd} {"IBM Journal of Research and Development"}
		if ( journal ~ /IBM J.*R.*D/ ) journal = "ibmjrd"
		# {ibmsj} {"IBM Systems Journal"}
		if ( journal ~ /IBM Sy.*J/ ) journal = "ibmsj"
		# {ieeese} {"IEEE Transactions on Software Engineering"}
		if ( journal ~ /IEEE Tran.*Soft.*Eng/ ) journal = "ieeese"
		# {ieeetc} {"IEEE Transactions on Computers"}
		if ( journal ~ /IEEE Tran.*Computers/ ) journal = "ieeetc"
		# {ieeetcad}
		if ( journal ~ /IEEE Tran.*Comp.*Desig/ ) journal = "ieeetcad"
		# {ipl} {"Information Processing Letters"}
		if ( journal ~ /Inf.*Proc.*Lett/ ) journal = "ipl"
		# {jacm} {"Journal of the ACM"}
		if ( journal ~ /Jou.* ACM/ ) journal = "jacm"
		if ( journal ~ /JACM/ ) journal = "jacm"
		# {jcss} {"Journal of Computer and System Sciences"}
		if ( journal ~ /J.*Comp.*Sys.*Sc/ ) journal = "jcss"
		# {scp} {"Science of Computer Programming"}
		if ( journal ~ /Sc.*Comp.*Prog/ ) journal = "scp"
		# {sicomp} {"SIAM Journal on Computing"}
		if ( journal ~ /SIAM .*Comp/ ) journal = "sicomp"
		# {tocs} {"ACM Transactions on Computer Systems"}
		if ( journal ~ /ACM Tran.*Comp.*Sys/ ) journal = "tocs"
		# {tods} {"ACM Transactions on Database Systems"}
		if ( journal ~ /ACM Tran.*Data.*Sys/ ) journal = "tods"
		# {tog} {"ACM Transactions on Graphics"}
		if ( journal ~ /ACM Tran.*Grap/ ) journal = "tog"
		# {toms} {"ACM Transactions on Mathematical Software"}
		if ( journal ~ /ACM Tran.*Math.*Soft/ ) journal = "toms"
		# {toois} {"ACM Transactions on Office Information Systems"}
		if ( journal ~ /ACM Tran.*Off.*Inf.*Sys/ ) journal = "toois"
		# {toplas} {"ACM Transactions on Programming Languages and Systems"}
		if ( journal ~ /ACM Tran.*Prog.*Lan.*Sys/ ) journal = "toplas"
		# {tcs} {"Theoretical Computer Science"}
		if ( journal ~ /Th.*Comp.*Sci/ ) journal = "tcs"

		}

	if(lwidth>0) { # split lines of potential over length
		# titles, book titles, notes, abstracts, addresses,
		# journals ( which may be conference proceedings) and institutions
		if(T){
			twc = split(title,z)
			title = z[1];
			lt = length(z[1])+13+length("Title")
			for(i=2;i<=twc;i++) {
				if(lt + length(z[i]) >= lwidth)
					{sc = "\n\t\t";lt = 15;}
				else sc = " ";
				title = title sc z[i]
				lt += length(z[i]) + 1
				}
			}

		if(J){	# it may be a conference
			twc = split(journal,z)
			journal = z[1];
			if(twc>1) {	# if its 1 then we have an abbreviation
				lt = length(z[1])+11+length(jnl)
				for(i=2;i<=twc;i++) {
					if(lt + length(z[i]) >= lwidth)
						{sc = "\n\t\t";lt = 15;}
					else sc = " ";
					journal = journal sc z[i]
					lt += length(z[i]) + 1
					}
				}
			}

		if(B){
			twc = split(booktitle,z)
			booktitle = z[1];
			lt = length(z[1])+13+length("Booktitle")
			for(i=2;i<=twc;i++) {
				if(lt + length(z[i]) >= lwidth)
					{sc = "\n\t\t";lt = 15;}
				else sc = " ";
				booktitle = booktitle sc z[i]
				lt += length(z[i]) + 1
				}
		}

		if(C){
			twc = split(city,z)
			city = z[1];
			lt = length(z[1])+13+length("Address")
			for(i=2;i<=twc;i++) {
				if(lt + length(z[i]) >= lwidth)
					{sc = "\n\t\t";lt = 15;}
				else sc = " ";
				city = city sc z[i]
				lt += length(z[i]) + 1
				}
			}

		if(O){
			twc = split(other,z)
			other = z[1];
			lt = length(z[1])+13+length("Note")
			for(i=2;i<=twc;i++) {
				if(lt + length(z[i]) >= lwidth)
					{sc = "\n\t\t";lt = 15;}
				else sc = " ";
				other = other sc z[i]
				lt += length(z[i]) + 1
				}
			}

		if(R){
			twc = split(report,z)
			report = z[1];
			lt = length(z[1])+13+length( institute )
			for(i=2;i<=twc;i++) {
				if(lt + length(z[i]) >= lwidth)
					{sc = "\n\t\t";lt = 15;}
				else sc = " ";
				report = report sc z[i]
				lt += length(z[i]) + 1
				}
			}

		if(X){
			twc = split(abstr,z)
			abstr = z[1];
			lt = length(z[1])+13+length("Annote")
			for(i=2;i<=twc;i++) {
				if(lt + length(z[i]) >= lwidth)
					{sc = "\n\t\t";lt = 15;}
				else sc = " ";
				abstr = abstr sc z[i]
				lt += length(z[i]) + 1
				}
			}
		}

	# fiddle fields that might contain only digits
	if ( volume !~ /^ *[0-9][0-9]* *$/ ) volume = "{ " volume " }"
	if ( number !~ /^ *[0-9][0-9]* *$/ ) number = "{ " number " }"
	if ( pages !~ /^ *[0-9][0-9]* *$/ ) pages = "{ " pages " }"
	# print the reference

	bibs[bibtype] ++;
	printf "@%s{\t%s",bibtype,keys
	if(A) {
		printf ",\n\tAuthor = { %s",authors[1]
		for(i=2;i<=A;i++) printf " and\n\t\t%s",authors[i]
		printf " }"
		}
	if(TY) printf ",\n\tType = { %s }", type
	if(T) printf ",\n\tTitle = { %s }", title
	if(B) printf ",\n\tBooktitle = { %s }", booktitle
	if(E) {
		printf ",\n\tEditor = { %s", editor[1]
		for(i=2;i<=E;i++) printf " and\n\t\t%s", editor[i]
		printf " }"
		}
	if(J) printf ",\n\t%s = %s", jnl, journal
	if(S) printf ",\n\tSeries = { %s }", series
	if(V) printf ",\n\tVolume = %s", volume
	if(N) printf ",\n\tNumber = %s", number
	if(P) printf ",\n\tPages = %s", pages
	if(O) printf ",\n\tNote = { %s }", other
	if( edition != "" )
		printf ",\n\tEdition = { %s }", edition
	if(R) printf ",\n\t%s = { %s }", institute, report
		# Non standard fields start
	if(G) printf ",\n\tGovernmentNo = { %s }", govtorder
	if(M) printf ",\n\tBellLabsMemo = { %s }", bellmemo
		# Non standard end
	if(I) printf ",\n\tPublisher = { %s }", publisher
	if(C) printf ",\n\tAddress = { %s }", city
	if(month != "") printf ",\n\tMonth = %s", month
	if(D) printf ",\n\tYear = %s", year
	if(L) printf ",\n\tKey = { %s }", label
	if(K) printf ",\n\tKeywords = { %s }", keywords
	if(X) printf ",\n\tAnnote = { %s }", abstr
	printf "\t}\n\n"

	# initialise for next reference

	A=0;B=0;C=0;D=0;E=0;F=0;G=0;H=0;I=0;J=0;
	K=0;L=0;M=0;N=0;O=0;P=0;Q=0;R=0;S=0;T=0;
	U=0;V=0;W=0;X=0;Y=0;Z=0; TY=0;
	bibtype = misc
	edition = ""
	type = ""
	institute = ""
	booktitle = ""
	title = ""
	volume = ""
	alleditors = ""
	city = ""
	date = ""
	month = ""
	xmonth = ""
	kyear = ""
	year = ""
	publisher = ""
	journal = ""
	number = ""
	other = ""
	page = ""
	report = ""
	series = ""
	abstr = ""
	bellmemo = ""
	govtorder = ""
	keywords = ""
	label = ""
	keys = ""
	toterr +=err
	rx++
	}
	else if (comment) print "\t}\n"
	err = 0
	percent = 0 # not in a reference
	comment = 0 # not in a comment
	pctchar = ""
	next
	}

/^%T/	{
	T ++
	if (T>1) {
		err=1
		print "Two titles: Reference " rx >> errfil
		print title >> errfil
		}
	title = entry
	next
	}

/^%D/	{
	D ++
	if (D>1) {
		err=1
		print "Two dates: Reference " rx >> errfil
		print date >> errfil
		}
	if (($NF<1900)||($NF>=2000)) {
		err=1
		print "Date error? : Reference " rx >> errfil
		}
	date = entry
	next
	}

/^%P/	{
	P ++
	if ( P>1 ) {
		err=1
		print "Two page nos? : Reference " rx >> errfil
		print pages >> errfil
		}
	pages = entry
	next
	}

/^%J/	{
	J ++
	if ( J>1 ) {
		err=1
		print "Two journals: Reference " rx >> errfil
		print journal >> errfil
		}
	journal = entry
	next
	}

/^%V/	{
	V ++
	if ( V>1 ) {
		err=1
		print "Two volumes: Reference " rx >> errfil
		print volume >> errfil
		}
	volume = entry
	next
	}

/^%N/	{
	N ++
	if ( N>1 ) {
		err=1
		print "Two issue numbers: Reference " rx >> errfil
		print number >> errfil
		}
	number = entry
	next
	}

/^[^%]/	{	# non-blank-non-% lines

	if(FILENAME == keyfil )
		keyused[$1] = $2
	else
	if(percent)
	{	# in the references

	if( pctchar == "A") authors[A] = authors[A]  " " $0
	if( pctchar == "B") booktitle = booktitle " " $0
	if( pctchar == "C") city = city " " $0
	if( pctchar == "D") date = date " " $0
	if( pctchar == "E") alleditors = alleditors " " $0
	if( pctchar == "G") govtorder = govtorder " " $0
	if( pctchar == "H") header = header " " $0
	if( pctchar == "I") publisher = publisher " " $0
	if( pctchar == "J") journal =  journal " " $0
	if( pctchar == "K") keywords = keywords " " $0
	if( pctchar == "L") label = label " " $0
	if( pctchar == "M") bellmemo = bellmemo " " $0
	if( pctchar == "N") number = number " " $0
	if( pctchar == "O") other = other " " $0
	if( pctchar == "P") pages = pages " " $0
	if( pctchar == "Q") authors[A] = authors[A]  " " $0
	if( pctchar == "R") report = report " " $0
	if( pctchar == "S") series = series " " $0
	if( pctchar == "T") title = title " " $0
	if( pctchar == "V") volume = volume " " $0
	if( pctchar == "X") abstr = abstr " " $0
	}
	else {
		if (!comment) print "@Comment{"
		print $0
		comment = 1
		}
	next
	}

/^%C/	{
	C ++
	if ( C>1 ) {
		err=1
		print "Two cities: Reference " rx >> errfil
		print city >> errfil
		}
	city = entry
	next
	}

/^%I/	{
	I ++
	if ( I>1 ) {
		err=1
		print "Two publishers: Reference " rx >> errfil
		print publisher >> errfil
		}
	publisher = entry
	next
	}

/^%B/	{
	B ++
	if ( B>1 ) {
		err=1
		print "Two books: Reference " rx >> errfil
		print booktitle >> errfil
		}
	booktitle = entry
	next
	}

/^%E/	{	# this really deals with 'bib' format which allows multiple
		# %E fields
		# refer only allows one %E field
		# we split it when the reference is printed
	E++
	if ( alleditors == "" ) alleditors = entry
	else alleditors = alleditors " and " entry
	next
	}

/^%O/	{
	O ++
	if ( O>1 ) {
		err=1
		print "Two others: Reference " rx >> errfil
		print other >> errfil
		}
	other = entry
	next
	}

/^%H/	{
	H ++
	if ( H>1 ) {
		err=1
		print "Two headers: Reference " rx >> errfil
		print header >> errfil
		}
	header = entry
	next
	}

/^%S/	{
	S ++
	if ( S>1 ) {
		err=1
		print "Two series: Reference " rx >> errfil
		print series >> errfil
		}
	series = entry
	next
	}

/^%R/	{
	R ++
	if ( R>1 ) {
		err=1
		print "Two reports: Reference " rx >> errfil
		print report >> errfil
		}
	report = entry
	next
	}

/^%X/	{
	X ++
	abstr = entry
	if ( X>1 ) {
		err=1
		print "Two abstracts: Reference " rx >> errfil
		}
	next
	}

/^%K/	{
	K++
	if (K>1) {
		err=1
		print "Two keywords: Reference " rx >> errfil
		print keywords >> errfil
		}
	keywords = entry
	next
	}

/^%L/	{
	L++
	if (L>1) {
		err=1
		print "Two labels: Reference " rx >> errfil
		print label >> errfil
		}
	label = entry
	next
	}

/^%G/	{
	G++
	if (G>1) {
		err=1
		print "Two Gov't order Nos: Reference " rx >> errfil
		print govtorder >> errfil
		}
	govtorder = entry
	next
	}

/^%M/	{
	M++
	if (M>1) {
		err=1
		print "Two Bell Labs Memo Nos: Reference " rx >> errfil
		print bellmemo >> errfil
		}
	bellmemo = entry
	next
	}

/^%/	{	# should not get these
	F ++
	print "Unexpected flag: Reference " rx >> errfil
	print $0 >> errfil
	err = 1
	next
	}

END	{
	print refs " references" >> errfil
	if(toterr) print toterr " erroneous" >> errfil
	if(bibs[article]>0) print bibs[article], " journal articles" >> errfil
	if(bibs[book]>0) print bibs[book], " books" >> errfil
	if(bibs[booklet]>0) print bibs[booklet], " booklets" >> errfil
	if(bibs[inbook]>0) print bibs[inbook], " book extracts" >> errfil
	if(bibs[incollection]>0) print bibs[incollection], " book articles" >> errfil
	if(bibs[inproceedings]>0) print bibs[inproceedings], " conference papers" >> errfil
	if(bibs[manual]>0) print bibs[manual], " manuals" >> errfil
	if(bibs[mastersthesis]>0) print bibs[mastersthesis], " Master's theses" >> errfil
	if(bibs[misc]>0) print bibs[misc], " miscellaneous" >> errfil
	if(bibs[phdthesis]>0) print bibs[phdthesis], " PhD theses" >> errfil
	if(bibs[proceedings]>0) print bibs[proceedings], " conference proceedings" >> errfil
	if(bibs[techreport]>0) print bibs[techreport], " technical reports" >> errfil
	if(bibs[unpublished]>0) print bibs[unpublished], " unpublished papers" >> errfil

	for(k in keyused) print k, keyused[k] > nkeyfil

	}
ZZ

$DEBUG && echo "Generated: <$GEN>" 1>&2
$DEBUG && echo "Width: <$WIDTH>" 1>&2
$DEBUG && echo "Errors in: <$ERRFILE>" 1>&2
$DEBUG && echo "Authors used in Keys: <$NAUTHOR>" 1>&2
$DEBUG && echo "Characters/Author used in Keys: <$LAUTHOR>" 1>&2

# Process each file, or if none given, standard input
for FILE in ${*-$STDIN}
do
    cp $KEYFILE $NKEYFILE

# First set up shell variables as required
    if [ "$FILE" = "$STDIN" ]
    then
	NEWFILE=$NAME.$BIB
    else
	if [ -r "$FILE" -a -f "$FILE" ]
	then
		NAME=`basename $FILE`
		NEWFILE=$FILE.$BIB
	else
		NAME=""
		echo "$PROGNAME: Can't read $FILE" 1>&2
	fi
    fi

# If all is OK, read input and terminate with a blank line.
    if [ "$NAME" ]
    then
	if [ "$FILE" = "$STDIN" ]
	then
# If no files given, read from standard input.
	    $DEBUG && echo "Reading from standard input" 1>&2
	    cat
	    echo
	else
	    $DEBUG && echo "Reading <$FILE>" 1>&2
	    cat $FILE
	    echo
	fi |
# do the conversions
	sed -f $SEDFILE |
	awk -f $AWKFILE $KEYFILE - |
# Finally, output to named files or standard output
	if $NAMEDFILES
	then
		$DEBUG && echo "Output to <$NEWFILE>" 1>&2
		cat > $NEWFILE
	else
		cat
	fi
    fi
    cp $NKEYFILE $KEYFILE
done

echo >> $ERRFILE Key Frequencies
sort < $KEYFILE >> $ERRFILE
[ $AKEYFILE ] && [ -w $AKEYFILE ]  && cat $KEYFILE > $AKEYFILE
exit 0
