#! /usr/bin/perl
# -*- Mode: perl; -*-
# DO NOT EDIT
# This file created by configure from the "sowing" package
#
# Minimal processing of a BibTeX database file to make it html
# Usage:
# bib2html filename > output.html
# bib2html -group gfilename filename > output.html
#     where gfilename is a file containing regular expressions for
#     author's names and matching URLs.  See mpich.group for an example.
# -ignore value specifies a field to ignore (e.g., -ignore annote eliminates
# annote fields from the output.
#
# Add header/tail (with link to this code)
# Convert comments to %...<BR>
# Convert @<name>{ or ( to <b>@<name></b>
#
# To customize for yourself, change the following three lines.
$UserName = "William Gropp";
$userURL = "http://www.cs.illinois.edu/~wgropp";
# This is W. or William (the W(\.|illiam)), optionally followed by D. (the
# ( D\.)?), followed by Gropp.
$UserREName = "W(\.|illiam)( D\.)? Gropp";
# For names that have accents, e.g., \'e, use the HTML entity:
#     J(\.|orge) Mor&eaccute;
# for Jorge Mor\'e
#
# Using styles
# You can define
# <style type="text/css">
# <!--
# body { font-size: 10pt }
# p.petsc { background:#CCCCFF }
# p.other { background:#FFFFFF }
# -->
# </style>
# and then use
# $EntryStart = "<p class=\"petsc\">\n";
# $EntryEnd = "</p>\n";
# to group an entry.
# Other style elements that can be used are
#   font-family
#   font-weight
#   text-align
#   color
#   width
#   margin-left
#   margin-right
#
$GroupEmphStart = "<b>";
$GroupEmphEnd   = "</b>";
#
$includeCreateTime = 1;
$announce_oldstyle = 0;
$groupsize = 0;
$ignoresize = 0;
$outlist = 0;
$debug = 0;
$special_entity = 1;
$check_valid_fields = 0;

# The following variables are often set in the listconfig file
$ListHeader = "";
$ListFooter = "";
$BibFileName = "";
$EntryStart = "";
$EntryEnd = "";
#
# ignorefields gives the names of fields that should not be noted as
# "not known".  These apply to every entry type.
%ignorefields = ( 'area' => 1, 'areaseq' => 1, 'bibsource' => 1, 'ee' => 1,
    'preprintof' => 1, 'doi' => 1, 'eprint' => 1, 'webloc' => 1,
    'acmid' => 1, 'isbn' => 1, 'biburl' => 1, 'language' => 1,
  );
# Default Formats for outlist
# Book
    # title, author, publisher, year.
    %htmlformatsBook = ( 'starttitle' => '<I>',
			 'endtitle' => '</I>' );
    @fieldlistBook = ('title', 'author', 'publisher', 'note', 'year');
    @fieldlistoptionalBook = ('address', 'pages', 'isbn', 'lccn', 'series',
	'keywords', 'editor', 'annote', 'pubaddress', 'key', 'edition',
        'source', 'location', 'month', 'url',
     );
#
# Booklet
    # title, author, publisher, year.
    %htmlformatsBooklet = ( 'starttitle' => '<I>',
			 'endtitle' => '</I>' );
    @fieldlistBooklet = ('title', 'author', 'publisher', 'note', 'month',
			 'year');
    @fieldlistoptionalBooklet = ('address', 'pages', 'isbn', 'lccn', 'series',
	'keywords', 'editor', 'annote', 'pubaddress', 'key', 'url' );
#
# Article
    # title, author, journal, volume, number, pages, year.
    %htmlformatsArticle = ( 'starttitle' => '<I>',
			   'endtitle' => '</I>' );
    @fieldlistArticle = ('title', 'author', 'journal', 'volume', 'number',
	'pages', 'note', 'year');
    @fieldlistoptionalArticle = ('month', 'annote', 'url', 'acknowledgement',
	'bibdate', 'issn', 'coden', 'keywords',
	'classification', 'conflocation', 'corpsource',
	'conftitle', 'sponsororg', 'treatment', 'key',
	'affiliation', 'thesaurus', 'key', 'journalabr',
        'publisher', 'address', 'officialurl', 'issue_date', 'numpages',
        'articleno', 'timestamp', );
# InBook
    # title, author, publisher, year.
    %htmlformatsInBook = ( 'starttitle' => '<I>',
			   'endtitle' => '</I>',
			   'startbooktitle' => 'in <i>',
			   'endbooktitle' => '</i>',
    );
    # chapter is the chapter title.
    @fieldlistInBook = ('chapter', 'author', 'title', 'publisher', 'note',
	'year', 'booktitle' );
    @fieldlistoptionalInBook = ('address', 'pages', 'isbn', 'lccn', 'series',
	'keywords', 'editor', 'annote', 'pubaddress', 'key', 'number', 'url',
        'keyword', 'organization', 'volume', 'editors', 'edition' );

#
# InProceedings
    # title, author, booktitle, editors, pages, year
    %htmlformatsInProc = ( 'starttitle' => '<I>',
			  'endtitle' => '</I>' );
    @fieldlistInProc = ('title', 'author', 'booktitle', 'editor', 'pages',
	'note', 'year');
    @fieldlistoptionalInProc = ('number', 'month', 'series', 'publisher',
	'address', 'volume', 'keywords', 'acknowledgement', 'treatment',
	'keyword', 'numpages', 'organizers', 'annoteps',
	'corpsource', 'conftitle', 'classification',
	'isbn', 'organization', 'confdate',
	'meetingdate', 'meetingdate2', 'sponsor',
	'sponsororg', 'thesaurus', 'affiliation', 'bibdate',
	'annote', 'url', 'issn', 'confloc', 'eariler', 'owner',
        'articleno',
	'conflocation', 'crossref', 'editors',
	'conference', 'meetingaddress', 'earlier',
	'coden', 'key', 'pubaddress', 'category', 'place',
	'affiliationaddress', 'journalabr', 'location', 'student' );

    %htmlformatsInColl = %htmlformatsInBook;
    @fieldlistInColl = @fieldlistInBook;
    @fieldlistoptionalInColl = @fieldlistoptionalInBook;
#
# Techreport
    # title, author, institution, number, year
    %htmlformatsTech = ( 'starttitle' => '<I>',
			'endtitle' => '</I>' );
    @fieldlistTech = ('title', 'author', 'institution', 'organization',
	'number', 'note', 'year');
    @fieldlistoptionalTech = ('month', 'keywords', 'url', 'language', 'notes',
	'pages', 'bibdate', 'later', 'scope', 'type', 'abstract-url',
  	'annote', 'address', 'key', 'location', 'category', 'parallelissues' );
#
# Misc
    # title, author, institution, number, year
    %htmlformatsMisc = ( 'starttitle' => '<I>',
			'endtitle' => '</I>' );
    @fieldlistMisc = ('title', 'author', 'institution', 'organization',
	'number', 'note', 'year');
    @fieldlistoptionalMisc = ( 'month', 'annote', 'key', 'address', 'type',
    'howpublished' );

# Manual, Unpublished come from Misc for now.  We don't need to define these
# because Misc is the default
  #%htmlformatsManual = %htmlformatsMisc;
  #@fieldlistManual = @fieldlistMisc;
  #%htmlformatsUnpublished = %htmlformatsUnpublished;
  #@fieldlistUnpublished = @fieldlistMisc;

# Bibtex entry type mappings
%shortentrynames = ( 'Book' => 'Book',
		     'Inbook' => 'InBook',
		     'Article' => 'Article',
		     'Inproceedings' => 'InProc',
		     'Incollection' => 'InColl',
		     'Techreport' => 'Tech',
		     'Misc' => 'Misc',
		     'Unpublished' => 'Misc',
		     'Manual' => 'Misc' );

# Example Header entries for a listfile configuration file.
#  $HeaderRE = "Section:";
#  $HeaderStart = "<H2 style=\"color:blue;align=center\">";
#  $HeaderEnd   = "</H2>";
#
$LiteralHTML = "LiteralHTML:";
while ($_ = $ARGV[0]) {
    shift;
    if ($_ eq "-group") {
	# Read from group file $ARGV[0]
	# Format is RE!URL
        # (RE is regular expression for matching the name)
	$groupname = $ARGV[0];
	shift;
	open( GROUP, "<$groupname" ) || die "Could not open group $groupname!\n";
	while (<GROUP>) {
	    chop;
	    if ($_ ne "") {  # Do we want !/^\s*$/?
	        ($GroupREName[$groupsize],$GroupURL[$groupsize]) = split(/!/);
	        $groupsize ++;
	    }
	}
    }
    elsif ($_ eq "-ignore") {
	# Read name from cmdline
	$IgnoreFields[$ignoresize] = lc( $ARGV[0] );
	$ignoresize++;
	shift;
    }
    elsif ($_ eq "-listfile") {
	$outlist = 1;
	$listfile = $ARGV[0];
	shift;
    }
    elsif ($_ eq "-listconfig") {
	$listconfig = $ARGV[0];
	shift;
    }
    elsif ($_ eq "-title") {
	$TitleString = $ARGV[0];
	shift;
    }
    elsif ($_ eq "-debug") {
	$debug = 1;
    }
    elsif ($_ eq "-nospecials") {
	$special_entity = 0;
    }
    elsif ($_ eq "-nooldstyle") {
        $announce_oldstyle = 1;
    }
    elsif ($_ eq "-nocreatetime") {
	# Mostly useful in automating tests
	$includeCreateTime = 0;
    }
    elsif ($_ eq "-check") {
	$check_valid_fields = 1;
    }
    elsif ($_ eq "-help" || $_ eq "-usage") {
	print "bib2html [ -listfile name ] [ -listconfig name ] \
         [ -group name ] [ -ignore name ] [ -title name ] [ -nospecials ]\
         [ -nooldstyle ] [ -check ] filename \
         -listfile name  - output a bibliography listing on file name\
         -listconfig name - Use file name to control the format of\
                            the list file.  This is a Perl script defining\
                \$ListHeader - HTML file header (to BODY)\
                \$ListFooter - HTML file footer (from BODY)\
                \$BibFileName - Name of bib file (used for links)\
                \$HeaderRE   - Regular expression that will be matched in
                               TeX comments for a header\
                \$HeaderStart - HTML inserted in listfile before header\
                \$HeaderEnd   - HTML inserted in listfile after header\
		\$LiteralHTML - Regular expression that will be matched in
		               TeX comments for explicit HTML in output\
                \$GroupEmphStart - HTML inserted before names found in the\
                                   group file\
                \$GroupEmphEnd - HTML inserted after names found in the\
                                 group file\
                \%htmlformatsBook - A Perl has containing HTML commands for\
                                    formatting a Book entry\
                \@fieldlistBook   - A Perl array containing the BibTeX fields\
                                 to use when formatting a book\
                   (Similarly for Article, Techreport, InProc (proceedings)\
                    and Misc)\
        A typical listconfig file might contain:\
\
           \$ListHeader = \"<HTML><HEAD><TITLE>Bib for me</TITLE></HEAD>\\\
           <style type=\"text/css\">\
           h2 { color:blue; align:center }\
           </style>\
           <BODY style=\\\"background-color=#FFFFFF\\\">\\n\";\
           \$ListFooter = \"</body></html>\\n\";\
           \$BibFileName = \"mpich2-bib.htm\";\
           \$EntryStart = \"\";\
           \$EntryEnd = \"<P>\\n\";\
           \$HeaderRE = \"Section:\";\
           \$HeaderStart = \"<H2>\";\
           \$HeaderEnd   = \"</H2>\";\
	   \$LiteralHTML = \"LiteralHTML:\";\
           \$GroupEmphStart = \"<b>\";\
           \$GroupEmphEnd = \"</b>\";\
           1;\n\
       -group name   - File containing author names and associated URLs\
       -ignore name  - Ignore field \"name\" in each bib entry\
       -title name   - Name to use in the title of the BiBTeX page\
       -nospecials   - Do not use certain valid HTML character entities\
                       such as endash that some older browers do not \
                       recognize.\
       -nooldstyle   - Print uses of oldstyle LaTeX to stderr.\
       -check        - Warn about unrecogonized BibTeX fields names.\
\n";

  	print "To customize the display of an entry, you can modify the\
\"htmlformats<entryname>\" hash to define how to display each entry.  For example,\
the default definition for the \"InBook\" entry type is\
\
    %htmlformatsInBook = ( \'starttitle\' => \'<I>\',
			   \'endtitle\' => \'</I>\' );
\
You could redefine these for each entry that you wanted to change.  The names\
of the keys are start<name> and end<name>, where <name> is one of the\
recognized fields (e.g., title, author, year).  The recognized fields are\
defined by the fieldlist<entryname> array, where <entryname> is an entry type.\n";

	print "The entry names must be chosen from the right hand side of the\
following list; the left hand side is the full (BibTeX) name of the entry.\
If the entry name is not listed here, use the BibTeX name, with the first \
character capitalized and the other characters in lower case (e.g., Booklet,\
not BookLet)\n";
	foreach my $key (keys(%shortentrynames)) {
	    my $name = $shortentrynames{$key};
	    print "    $key => $name\n";
	}

	exit 0;
    }
    else {
	$bibfile=$_;
    }
}

open( BIB, "<$bibfile" ) || die "Could not open $bibfile!\n";

if ($outlist) {
    open( LISTFILE, ">$listfile" ) || die "Could not open $listfile\n";
    if (defined($listconfig) && $listconfig ne "") {
	require $listconfig;
	print LISTFILE $ListHeader;
    }
}
if (!defined($TitleString) || $TitleString eq "") {
    $TitleString = "Bibliography for $UserName";
}
print "<!DOCTYPE html>\n";
print "<html lang=en>\n<head>\n<meta charset=\"utf-8\">\n";
print "<title>$TitleString</title>\n";
print "<!-- Automatically generated by bib2html available from\n";
print "   http://www.cs.illinois.edu/~wgropp/projects/software/sowingbib2html -->\n";
print "<style type=\"text/css\">\
<!--\
table.bib2html {\
 border: 0px;\
 border-spacing: 0;\
}\
table.bib2html tr {\
 vertical-align:top;\
}\
-->\
</style>\n";
print "</head>\n";
print "<body style=\"background-color:#FFFFFF\">\n";
#
# Still to do:
# Process @string(name=value); replace all uses of @name with
# value in formatted (listfile) version.
# Allow multiple HeaderRE's
# Allow fields in the entryinfo to modify the formatting.  For example,
# we might let @field@ be replaced by the value of entryinfo{'field'}.
#
%bibstrings = ();
$inrow   = "";
$intable = 0;
$dooutput = 1;
$line_count = 0;
$MakeBold = "";
$fieldname = "";
# Format as table.  Output to stdout is the formatted version of the
# bib database file, and includes any comments from the bib file.
#
while (<BIB>) {
    s/\r//g; # remove DOS newlines
    $line = $_;
    $line_count++;
    # Look for a new bib entry starting a line
    if (/^\s*\@[Ss][Tt][Rr][Ii][Nn][Gg]\s*[\(\{]\s*([^=\s]*)\s*=\s*(.*)\s*[\)\}]/) {
	# Found @string name = value
	$bibstrings{$1} = $2;
	next;
    }
    elsif (/^\s*\@([a-zA-Z]*)\s*[\(\{]/) {
	# Found the beginning of a BibTeX entry (@....)
	$entry_type = lc( $1 );
	if ($intable == 1) {
	    # Finish off the previous table
            print "</td></tr></table>\n";
	}
	#$line = $entryinfo{$fieldname};
	#$line =~ s%[^=]*=%%;
	#$entryinfo{$fieldname} = $line;
	%entryinfo = ();   # Clear entry info
	$entryinfo{"entry_type"} = $entry_type;
	$inrow = "";
        $intable = 1;
	$dooutput = 1;
	# Check for a name on the entry type line
	# Note that the containing test ensures there are only blanks
	# before the @
	if (/\@([a-zA-Z]*)([\(\{])\s*(.*)\s*,\s*$/) {
	    $_ = "\@<b>$1</b>$2<span id=\"$3\">$3</span>,\n<table class=\"bib2html\">\n";
	}
	else {
	    print STDERR "Entry $entry_type without a key on the same line\n";
	}
        #s%\@([a-zA-Z]*)([\(\{])\s*(.*)\s*,\s*$%\@<b>$1</b>$2<span id=\"$3\">$3</span>,\n<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>%g;
	$entryinfo{'key'} = $3;
        # Setup the list of expected field names based on the entry_type
        %knownfields = ();
        $entryname = ucfirst $entry_type;
        if (defined($shortentrynames{$entryname})) {
	    $entryname = $shortentrynames{$entryname};
	}
	$fieldref = "fieldlist$entryname";
        # @$fieldref is the array @fieldlist$entryname
        #$fieldref->[i] accesses the ith element of the fieldlist
        %knownfields = ();
	for ($k=0; $k <= $#$fieldref; $k++) {
	    $knownfields{$fieldref->[$k]} = 1;
	}
	$fieldoptref = "fieldlistoptional$entryname";
	for ($k=0; $k <= $#$fieldoptref; $k++) {
	    $knownfields{$fieldoptref->[$k]} = 1;
	}
	$knownfields{'abstract'} = 1;
    }
    elsif (defined($HeaderRE) && $HeaderRE ne "" &&
	   /^\s*%\s*($HeaderRE)(.*)$/) {
	# Found a special comment that we want modified and added to the
	# LISTFILE.
	$headertext = $2;
        if ($outlist &&
            ($HeaderRE ne "" || $HeaderEnd ne "" || $HeaderStart ne "")) {
            print LISTFILE "$HeaderStart $headertext $HeaderEnd\n";
        }
    }
    elsif (defined($LiteralHTML) && $LiteralHTML ne "" &&
	   /^\s*%\s*($LiteralHTML)(.*)$/) {
	# Found a special comment that we want modified and added to the
	# LISTFILE.
	$headertext = $2;
        print LISTFILE "$headertext\n";
	# Also add to stdout, and bypass any further processing of this line
	# Add a BR to preserve formating outside of tables
	if ($intable == 0) { s/$/<BR>/; }
	print $headertext . "\n" if $dooutput == 1;
	next;
    }
    else {
        # Look for a new item entry in a bib entry
	# We may want to skip some items
	# One thing to be careful of is multi-line items.
        # Ignore lines that are NOT field asignments, such as
	# abstract entries that include an = sign.
	# (This isn't quite right, because a line within an entry that
	# is <blank><word><blanks>= will still match
        if (/^\s*(\w+)\s*=/) {
	    # Found field = ....
	    print "matched $1 in $_" if $debug;
	    $fieldname = lc($1);

	    # First, a field name outside of an entry is an error
	    if ($intable == 0) {
		print STDERR "Missing bibtex entry type for line #$line_count:$_\n";
		print "<table class=\"bib2html\">\n";
		$intable = 1;
	    }
	    # Finish off the previous line
	    print "$MakeBold$inrow\n" ;
	    $inrow = "</tr>";

	    # Check to see if this line is one that we wish to
	    # suppress
	    # ---- not completely implemented
	    if ($fieldname eq "") {
		print STDERR "Matched empty field in $_";
	    }
	    else {
	        for ($i = 0; $i <= $#IgnoreFields; $i++) {
		    if ($IgnoreFields[$i] eq $fieldname) {
		        $dooutput=0; last;
  	    	    }
	        }
	        if ($check_valid_fields && !defined($knownfields{$fieldname})) {
		    # Ignore "opt" fieldnames
		    if (! ($fieldname =~ /^opt/) &&
			! defined($ignorefields{$fieldname}) ) {
 	  	        print STDERR "Field $fieldname not known for $entryname on line $line_count\n";
		    }
	        }
	        $entryinfo{$fieldname} = "";
	        print "Found $fieldname\n" if $debug;
	        if ($fieldname eq "title" || $fieldname eq "chapter") {
	            $MakeBold="<b>"; }
	        else { $MakeBold = ""; }
            }
	    $line =~ s/^\s*[^=%]*\s*=//;
	    # ----
	    # Make the "title" text bold, others regular
	    # Output this line
	    # (tr style="vertical-align:top")
            s%^([^=]*)[ ]*=\s*(.*)\s*$%<tr><td style=\"width:20\"></td><td><i>$1</i></td><td style=\"text-align:center;width:15\"> = </td><td>$MakeBold$2%;
	    if ($MakeBold ne "") { $MakeBold = "</b>"; }
        }

        # Check of the end of entry (must be alone on a separate line)
        # fix emacs broken matching mode })}
        else {
	    if (/^\s*[\}\)]\s*$/) {
 	        if ($dooutput == 1) { #({
		    s%^\s*([\}\)])\s*$%</td></tr></table>\n$1%;
		    }
 	        else {
		    s%^\s*([\}\)])\s*$%</table>\n$1%;
	        }
 	        if ($outlist && defined($entryinfo{"entry_type"})) {
		    &PrintEntry( %entryinfo );
	        }
	        elsif ($debug && $outlist) {
		    print %entryinfo;
	        }
	        %entryinfo = ();   # Clear entry info
         	$fieldname = "";
	        $intable = 0;
	        $dooutput = 1;
            }
	    elsif (/^\s*%/) {
		# Note that for a comment, we need to convert raw text
		# to valid html.  This is handled below.
		$dooutput = 1;
	    }
        }
    }

    print "Current line[$line_count] = \"$line\"\n" if $debug;
    $original_line = $line;
    # # Fix HTML reserved characters
    # $line =~ s%[\\]+&%&amp;%;
    # $line =~ s%[\\]+<%&lt;%;
    # $line =~ s%[\\]+>%&gt;%;
    # # Convert various TeX commands
    # # $...$
    # $line =~ s%\$([^\$]*)\$%<EM>$1</EM>%;
    # # ~ (but not \~)
    # $line =~ s%([^\\]{1})~%$1&nbsp;%;
    # # \textrm{} (currently only strips out the command)
    # $line =~ s%\\textrm{([^}]*)}%$1%;
    # # \textem{} (set to em, won't work if nested)
    # $line =~ s%\\textem{([^}]*)}%<EM>$1</EM>%;
    # # \texttt{} (set to tt, won't work if nested)
    # $line =~ s%\\texttt{([^}]*)}%<TT>$1</TT>%;
    # # \url{}
    # $line =~ s%\\url{([^}]*)}%<A HREF=\"$1\">$1</A>%;
    # # {\tt ... }
    # if ($announce_oldstyle && /\\tt /) {
    #     print STDERR "line $line_count: \\tt in $original_line";
    # }
    # $line =~ s%{\\tt([^}]*)}%<TT>$1</TT>%;
    # # {\it ... }
    # if ($announce_oldstyle && /\\it /) {
    #     print STDERR "line $line_count: \\it in $original_line";
    # }
    # $line =~ s%{\\it([^}]*)}%<EM>$1</EM>%;
    # # \~{ }
    # $line =~ s%\\~\{\s*\}%~%g;
    # # \#
    # $line =~ s%\\#%#%g;
    # # \o
    # $line =~ s%\\o([^A-Za-z]{1})%&oslash;$1%;
    # # \O
    # $line =~ s%\\O([^A-Za-z]{1})%&Oslash;$1%;
    # # _{} -> <SUB>...</SUB>
    # # ^{} -> <SUP>...</SUP>
    # # \_ -> _
    # # \{ -> {
    # # \} -> }
    # # \(.*\) -> <EM>...</EM>
    # # \'{letter} {} is optional
    # $line =~ s%\\'\{([AEIOUYaeiouy]{1})\}%&$1acute;%;
    # $line =~ s%\\'([AEIOUYaeiouy]{1})%&$1acute;%;
    # # \~
    # $line =~ s%\\~\{([ANOano]{1})\}%&$1tilde;%;
    # $line =~ s%\\~([ANOano]{1})%&$1tilde;%;
    # # \"
    # $line =~ s%\\"\{([AEIOUaeiou]{1})\}%&$1uml;%;
    # $line =~ s%\\"([AEIOUYaeiouy]{1})%&$1uml;%;
    # # \`
    # $line =~ s%\\`\{([AEIOUaeiou]{1})\}%&$1grave;%;
    # $line =~ s%\\`([AEIOUaeiou]{1})%&$1grave;%;
    # #
    # # \.
    # $line =~ s%\\`\{([AEIOUaeiou]{1})\}%&$1circ;%;
    # $line =~ s%\\`([AEIOUaeiou]{1})%&$1circ;%;
    # # --- -> &mdash;
    # $line =~ s%---%&mdash;% if $special_entity;
    # # -- -> &ndash;
    # $line =~ s%--%&ndash;% if $special_entity;

    if ($line =~ /^\s*%/) {
	$line = &CleanHTML($line);
    }
    else {
	$line = &CleanLaTeX($line);
    }

    if (defined($fieldname) && $fieldname ne "") {
        print "Adding field $fieldname with text $line" if $debug;
        $entryinfo{ $fieldname } .= $line;
    }
#    else {
#        # Add this info to an "empty" element.  This holds, for example,
#        # comments from the bibtex file
#        #$entryinfo{ "" } .= $line;
#    }

    # Turn URLs into links in $_
    s%(http:[^ }"]*)%<a href="$1">$1</a>%g;
    s%(ftp:[^ }"]*)%<a href="$1">$1</a>%g;

    # Comment the following to not use links for author names
    # This also makes the author name bold
    s%($UserREName)%<A HREF="$userURL">$GroupEmphStart$1$GroupEmphEnd</A>%g;

    # For a group's bibliography, an array of UserREs and the corresponding
    # URLs could be used (preloaded as an option to this command)
    for ($i = 1; $i <= $#GroupURL; $i++) {
        s%($GroupREName[$i])%<A HREF="$GroupURL[$i]">$GroupEmphStart$1$GroupEmphEnd</A>%g;
    }

    # Add a BR to preserve formating outside of tables
    if ($intable == 0) { s/$/<br>/; }
    print $_ if $dooutput == 1;
}

if ($includeCreateTime) {
    $curtime = localtime;
    print "Generated on $curtime with <A HREF=\"http://www.mcs.anl.gov/~gropp/bib2html\">bib2html</A>\n";
}
print "</body>\n";
print "</html>\n";

if (defined($listconfig) && $listconfig ne "") {
    print LISTFILE $ListFooter;
}

#
# This routine replaces @xxx@ with the value of xxx in the entry info.
# This allows you to use bibtex fields to control formatting by using
# the class=name style directive.
sub ReplaceParms {
    $textline = $_[0];
    $default  = $_[1];
    if ($textline =~ /\@([a-z]+)\@/) {
	$token = $1;
	$replacement = $entryinfo{$token};
	$replacement =~ s/^\s*//;
	if ($replacement eq "") { $replacement = $default; }
	$textline =~ s/\@$token\@/$replacement/;
    }
    return $textline;
}

# Print out an entry
sub PrintEntry {
    my $entry_type = $entryinfo{"entry_type"};
    print "Printing $entry_type\n" if $debug;
    # First, clean up values
    foreach $key (keys %entryinfo) {
        $value = $entryinfo{$key};
	$value =~ s/,\s*$//s;
	$value =~ s/^\s*(\"|\{){1}(.*)(\"|\}){1}/$2/s;
	chomp $value;
	$entryinfo{$key} = $value;
    }
    if ($debug) { print %entryinfo ; }
    if (defined($entryinfo{'key'})) {
	my $keyname = $entryinfo{'key'};
	print LISTFILE "<span id=\"$keyname\"></span>\n";
    }
    if ($EntryStart ne "") {
	$textline = &ReplaceParms( $EntryStart );
        print LISTFILE $textline;
    }
    if ($entry_type eq "book") {
	&PrintBook;
    }
    elsif ($entry_type eq "article") {
	&PrintArticle;
    }
    elsif ($entry_type eq "inproceedings") {
	&PrintInProceedings;
    }
    elsif ($entry_type eq "incollection") {
	&PrintInCollection;
    }
    elsif ($entry_type eq "techreport") {
	&PrintTechreport;
    }
    else {
	# Works for manual, unpublished, misc, etc
	&PrintArbEntry( $entry_type );
    }
    if ($EntryEnd ne "") {
	$textline = &ReplaceParms( $EntryEnd );
        print LISTFILE $textline;
    }
}

sub TitleCase {
    # Convert to title case, but don't change case inside of {}.
    # FIXME: To be implemented
}
# Clean up an author list (name and name and name ... goes to name, name,
# ..., and name; may also map authors to URLs).
sub AuthorList {
    my $fieldname = $_[0];
    # Convert all but last "and" into ,
    if (defined($entryinfo{$fieldname})) {
	$author = $entryinfo{$fieldname};
	@authors = split /\s+and\s+/, $author;
	print @authors if $debug;
	print "n = $#authors\n" if $debug;
	if ($#authors > 1) {
	    $author = "";
	    for ($i=0; $i<$#authors; $i++) {
		$author .= $authors[$i];
		$author .= ", ";
	    }
	    $author .= "and $authors[$#authors]";
	}
	# Comment the following to not use links for author names
	# This also makes the author name bold
	$author =~ s%($UserREName)%<A HREF="$userURL">$GroupEmphStart$1$GroupEmphEnd</A>%g;

	# For a group's bibliography, an array of UserREs and the corresponding
	# URLs could be used (preloaded as an option to this command)
	for ($i = 1; $i <= $#GroupURL; $i++) {
	    $author =~ s%($GroupREName[$i])%<A HREF="$GroupURL[$i]">$GroupEmphStart$1$GroupEmphEnd</A>%g;
	}
	$entryinfo{$fieldname} = $author;
    }
}

sub PrintBook {
    # title, author, publisher, year.
    %htmlformats = %htmlformatsBook;
    # We should really check for author; if no author but an editor,
    # use the editor field instead.
    @fieldlist = @fieldlistBook;
    if (!defined($entryinfo{'author'}) &&
	defined($entryinfo{'editor'})) {
	for ($i=0; $i<$#fieldlist; $i++) {
	    if ($fieldlist[$i] eq 'author') {
		$fieldlist[$i] = 'editor';
		last;
	    }
	}
    }
    &PrintGeneral;
}

sub PrintArticle {
    # title, author, journal, volume, number, pages, year.
    %htmlformats = %htmlformatsArticle;
    @fieldlist = @fieldlistArticle;
    &PrintGeneral;
}

sub PrintInProceedings {
    # title, author, booktitle, editors, pages, year
    %htmlformats = %htmlformatsInProc;
    @fieldlist = @fieldlistInProc;
    &PrintGeneral;
}

#
# Print an arbitrary entry type.  Use Misc if the type is not defined
sub PrintArbEntry {
    my $entrytype = $1;
    my $entryname = ucfirst $entry_type;
    my $var = "htmlformats$entryname";
    if (%$var) {
	%htmlformats = %$var;
    }
    else {
	print "No $var found for entry $entry_type\n";
	%htmlformats = %htmlformatsMisc;
    }
    $var = "fieldlist$entryname";
    if (@$var) {
	@fieldlist = @$var;
    }
    else {
	print "No $var found for entry $entry_type\n";
	@fieldlist = @fieldlistMisc;
    }
    &PrintGeneral;
}

sub PrintInBook {
    # chapter, author, title, editors, pages, year
    %htmlformats = %htmlformatsInBook;
    @fieldlist = @fieldlistInBook;
    &PrintGeneral;
}

sub PrintInCollection {
    # chapter, author, title, editors, pages, year
    %htmlformats = %htmlformatsInBook;
    @fieldlist = @fieldlistInBook;
    &PrintGeneral;
}

sub PrintTechreport {
    # title, author, institution, number, year
    %htmlformats = %htmlformatsTech;
    @fieldlist = @fieldlistTech;
    &PrintGeneral;
}

sub PrintMisc {
    # title, author, institution, number, year
    %htmlformats = %htmlformatsMisc;
    @fieldlist = @fieldlistMisc;
    &PrintGeneral;
}

sub CleanString {
    $value = $_[0];
    # Remove extra {} pairs
    $value =~ s/{([^{}]*)}/$1/gs;
    return $value;
}

sub PrintGeneral {
    # Clean up any author or editor list
    &AuthorList( 'author' );
    &AuthorList( 'editor' );

    $firstitem = 1;
    foreach $key (@fieldlist) {
	if (!defined($entryinfo{$key})) { next; }
	$value = $entryinfo{$key};
        if ($value eq "") { next; }
	if (!$firstitem) { print LISTFILE ", ";}
	else { $firstitem = 0; }
	$keyname = "start$key";
	if (defined($htmlformats{$keyname})) {
            print LISTFILE "$htmlformats{$keyname}";
        }
	$value = &CleanString( $value );
        #
        # Here is where we look for @name and then look up name
	# in bibstrings.  Or we could just keep a list of strings and
	# replacements (just like the GroupREName and GroupURL)
	if ($key eq 'title' && defined($entryinfo{'officialurl'})) {
	    $url = $entryinfo{'officialurl'};
	    print LISTFILE "<A HREF=\"$url\">$value</A>";
        }
	elsif ($key eq 'title' && defined($entryinfo{'url'})) {
	    $url = $entryinfo{'url'};
	    print LISTFILE "<A HREF=\"$url\">$value</A>";
        }
	else {
            print LISTFILE "$value";
        }
	$keyname = "end$key";
	if (defined($htmlformats{$keyname})) {
            print LISTFILE "$htmlformats{$keyname}";
        }
    }
    print LISTFILE ".\n";
    if ($BibFileName ne "") {
	# If the BibFileName is not set, this link will not be correct
	print LISTFILE "<A HREF=\"$BibFileName#$entryinfo{'key'}\">BibTeX</A>\n";
    }
}

# Replace latex commands with HTML
sub CleanLaTeX {
    my $line = $_[0];

    # Fix HTML reserved characters
    $line =~ s%[\\]+&%&amp;%;
    $line =~ s%[\\]+<%&lt;%;
    $line =~ s%[\\]+>%&gt;%;
    # Convert various TeX commands
    # $...$
    $line =~ s%\$([^\$]*)\$%<EM>$1</EM>%;
    # ~ (but not \~)
    $line =~ s%([^\\]{1})~%$1&nbsp;%;
    # \textrm{} (currently only strips out the command)
    $line =~ s%\\textrm{([^}]*)}%$1%;
    # \textem{} (set to em, won't work if nested)
    $line =~ s%\\textem{([^}]*)}%<EM>$1</EM>%;
    # \texttt{} (set to tt, won't work if nested)
    $line =~ s%\\texttt{([^}]*)}%<TT>$1</TT>%;
    # \url{}
    $line =~ s%\\url{([^}]*)}%<A HREF=\"$1\">$1</A>%;
    # {\tt ... }
    if ($announce_oldstyle && /\\tt /) {
        print STDERR "line $line_count: \\tt in $original_line";
    }
    $line =~ s%{\\tt([^}]*)}%<TT>$1</TT>%;
    # {\it ... }
    if ($announce_oldstyle && /\\it /) {
        print STDERR "line $line_count: \\it in $original_line";
    }
    $line =~ s%{\\it([^}]*)}%<EM>$1</EM>%;
    # \~{ }
    $line =~ s%\\~\{\s*\}%~%g;
    # \#
    $line =~ s%\\#%#%g;
    # \o
    $line =~ s%\\o([^A-Za-z]{1})%&oslash;$1%;
    # \O
    $line =~ s%\\O([^A-Za-z]{1})%&Oslash;$1%;
    # _{} -> <SUB>...</SUB>
    # ^{} -> <SUP>...</SUP>
    # \_ -> _
    # \{ -> {
    # \} -> }
    # \(.*\) -> <EM>...</EM>
    # \'{letter} {} is optional
    $line =~ s%\\'\{([AEIOUYaeiouy]{1})\}%&$1acute;%;
    $line =~ s%\\'([AEIOUYaeiouy]{1})%&$1acute;%;
    # \~
    $line =~ s%\\~\{([ANOano]{1})\}%&$1tilde;%;
    $line =~ s%\\~([ANOano]{1})%&$1tilde;%;
    # \"
    $line =~ s%\\"\{([AEIOUaeiou]{1})\}%&$1uml;%;
    $line =~ s%\\"([AEIOUYaeiouy]{1})%&$1uml;%;
    # \`
    $line =~ s%\\`\{([AEIOUaeiou]{1})\}%&$1grave;%;
    $line =~ s%\\`([AEIOUaeiou]{1})%&$1grave;%;
    #
    # \.
    $line =~ s%\\`\{([AEIOUaeiou]{1})\}%&$1circ;%;
    $line =~ s%\\`([AEIOUaeiou]{1})%&$1circ;%;
    # --- -> &mdash;
    $line =~ s%---%&mdash;% if $special_entity;
    # -- -> &ndash;
    $line =~ s%--%&ndash;% if $special_entity;

    return $line;
}

sub CleanHTML {
    my $line = $_[0];

    $line =~ s%&%--amp--%g;
    $line =~ s%<%&lt;%g;
    $line =~ s%>%&gt;%g;
    $line =~ s%--amp--%&amp;%g;

    return $line;
}
