summaryrefslogtreecommitdiff
path: root/biblio/bibtex/utils/ams2bib/ams2bib
diff options
context:
space:
mode:
Diffstat (limited to 'biblio/bibtex/utils/ams2bib/ams2bib')
-rw-r--r--biblio/bibtex/utils/ams2bib/ams2bib287
1 files changed, 287 insertions, 0 deletions
diff --git a/biblio/bibtex/utils/ams2bib/ams2bib b/biblio/bibtex/utils/ams2bib/ams2bib
new file mode 100644
index 0000000000..967bcb6f04
--- /dev/null
+++ b/biblio/bibtex/utils/ams2bib/ams2bib
@@ -0,0 +1,287 @@
+#!/usr/bin/perl
+
+# ams2bib: convert AmSTeX bibliography into BibTeX
+# usage: ams2bib [-o file.bib] file[.tex]
+#
+# author: A. G. Werschulz <agw@cs.columbia.edu>
+# date: 10 September 2000
+# version: 1.0
+#
+# Copyright (C) Arthur G. Werschulz 2000 (agw@cs.columbia.edu)
+#
+# May be freely redistributed under the Gnu Public License.
+# Send me mail if you like it or if you have any questions or suggestions.
+
+# modules I use:
+
+use strict;
+use vars qw($opt_h $opt_o);
+use Getopt::Std;
+
+my($prog, $usage, $bibfile, $still_more);
+
+# I should really clean this up, given the unpleasantness of
+# global variables ...
+
+my $current_author;
+my %keys = ();
+
+# ye olde error msg
+
+$prog = $0;
+$usage="Usage: $prog [-o file.bib] file[.tex]";
+
+# handle options
+
+if (!getopts('ho:')) {
+ print STDERR $usage, "\n";
+ exit 1;
+}
+
+if ($opt_h) {
+ print STDERR $usage, "\n";
+ exit 0;
+}
+
+$bibfile = $opt_o if ($opt_o);
+
+# there should be exactly one input filename at this point
+# default extension is ".tex" if no extension is explicitly given
+
+die $usage if ($#ARGV != 0);
+
+# set up input (AmSTeX) and output (BibTeX) files
+
+my $dotspot = index($ARGV[0], ".");
+if ($dotspot > 0) {
+ my $root = substr($ARGV[0], 0, $dotspot);
+ $bibfile = $root . ".bib" unless defined $bibfile;
+}
+else {
+ $bibfile = $ARGV[0] . ".bib";
+ $ARGV[0] .= ".tex";
+}
+
+open (INFILE, $ARGV[0]) || die "$prog: can't read $ARGV[0]: $!\n";
+open (OUTFILE, ">$bibfile") ||
+ die "$prog: can't open $bibfile for output: $!\n";
+
+# main processing loop
+
+do {
+ $still_more = process_one_ref();
+} while $still_more;
+
+# bring 'em all home, now
+
+close INFILE;
+close OUTFILE;
+
+exit 0;
+
+#
+# process a single entry from the INFILE filehandle
+# an entry has the form
+# \ref
+# \keyword blah blah blah
+# \endref
+#
+# keywords are listed below
+# assumption: a keyword can only appear at the beginning of a line
+# (possibly preceded by whitespac)
+# blank lines are ignored, as are instances of \pointer
+# returns false when eof occurs on INFILE
+#
+# this subroutine does no error checking ... it assumes that the entry
+# has the stated form
+#
+
+sub process_one_ref()
+{
+ my $keywords =
+ "\\book \\bookinfo \\by \\bysame \\endref \\inbook \\jour
+ \\manyby \\pages \\paper \\paperinfo \\publ \\publaddr
+ \\toappear \\vol \\yr";
+
+ my (%bibentry, $currentword, $firstword, @remainder,
+ $current_keyword, $rhs, $keyword);
+
+ # if there's nothing there, we're done
+
+ return 0 if (eof(INFILE));
+
+ # first, go past anything that doesn't match \ref
+ # (blank lines, \\pointer, etc.)
+
+ while (<INFILE>) {
+ s/%.+//; # strip out comments
+ last if index($_, "\\ref") >= 0;
+ }
+ return 0 if (eof(INFILE));
+
+ # store contents of entry into a hash, indexed by the keywords
+
+ while (<INFILE>) {
+ s/%.+//; # again with the comments??
+ last if index($_, "\\endref") >= 0;
+ ($firstword, @remainder) = split;
+ if (index($keywords, $firstword) >= 0) {
+ $firstword = substr($firstword, 1); # strip off leading slash
+ $current_keyword = $firstword;
+ $rhs = join(" ", @remainder);
+ #
+ # handle the various different fields
+ #
+ # here we deal with the \manyby ... \bysame construction
+ if ($current_keyword eq "manyby") {
+ $bibentry{"by"} = $rhs;
+ $current_author = $rhs;
+ } elsif ($current_keyword eq "bysame") {
+ $bibentry{"by"} = $current_author;
+ } else {
+ # handle all remaining keywords
+ $bibentry{$current_keyword} = $rhs;
+ }
+ } else { # firstword not a keyword, so this is a continuation line
+ $bibentry{$current_keyword} .=
+ " " . join(" ", $firstword, @remainder);
+ }
+ }
+
+ if (exists $bibentry{"book"}) {
+ handle_book(%bibentry);
+ } elsif (exists $bibentry{"inbook"}) {
+ handle_inbook(%bibentry);
+ } elsif (exists $bibentry{"paper"}) {
+ handle_paper(%bibentry);
+ } else {
+ print STDERR "$prog: unknown bibliographic entry\n";
+ foreach $keyword (keys(%bibentry)) {
+ print STDERR "$keyword: ", $bibentry{$keyword}, "\n";
+ }
+ }
+
+ return 1;
+
+}
+
+#
+# a book appearing in the bibliography
+#
+
+sub handle_book
+{
+ my %bibentry = @_;
+ my $author = adjust_author($bibentry{"by"});
+ my $bibkey = bib_key($author, $bibentry{"yr"});
+ print OUTFILE '@Book{', $bibkey, ",\n",
+ " author = {$author},\n",
+ " title = {", $bibentry{"book"}, "},\n",
+ " publisher = {", $bibentry{"publ"}, "},\n",
+ " address = {", $bibentry{"publaddr"}, "},\n",
+ " year = {", $bibentry{"yr"}, "},\n";
+ if (exists $bibentry{"bookinfo"}) {
+ print OUTFILE " note = {", $bibentry{"bookinfo"}, "},\n";
+ }
+ print OUTFILE "}\n\n";
+}
+
+#
+# part of a book (e.g., a contributed paper or a chapter) appearing
+# in the bibliography
+#
+
+sub handle_inbook
+{
+ my %bibentry = @_;
+ my $author = adjust_author($bibentry{"by"});
+ my $bibkey = bib_key($author, $bibentry{"yr"});
+ print OUTFILE '@InCollection{', $bibkey, ",\n",
+ " author = {$author},\n",
+ " title = {", $bibentry{"paper"}, "},\n",
+ " booktitle = {", $bibentry{"inbook"}, "},\n",
+ " pages = {", $bibentry{"pages"}, "},\n",
+ " publisher = {", $bibentry{"publ"}, "},\n",
+ " address = {", $bibentry{"publaddr"}, "},\n",
+ " year = {", $bibentry{"yr"}, "},\n";
+ if (exists $bibentry{"bookinfo"}) {
+ print OUTFILE " note = {", $bibentry{"bookinfo"}, "},\n";
+ }
+ print OUTFILE "}\n\n";
+}
+
+#
+# a paper appearing in the bibliography
+#
+
+sub handle_paper
+{
+ my %bibentry = @_;
+ my $author = adjust_author($bibentry{"by"});
+ my $bibkey = bib_key($author, $bibentry{"yr"});
+ print OUTFILE '@Article{', $bibkey, ",\n",
+ " author = {$author},\n",
+ " title = {", $bibentry{"paper"}, "},\n",
+ " journal = {", $bibentry{"jour"}, "},\n",
+ " volume = {", $bibentry{"vol"}, "},\n",
+ " year = {", $bibentry{"yr"}, "},\n",
+ " pages = {", $bibentry{"pages"}, "},\n";
+ if (exists $bibentry{"paperinfo"}) {
+ print OUTFILE " note = {", $bibentry{"paperinfo"}, "},\n";
+ }
+ print OUTFILE "}\n\n";
+}
+
+#
+# fix the author
+#
+# If a reference has more than two authors, then the AmSTeX file will
+# have a comma separating the authors (with the exception of the last two).
+# BibTeX requires "and" to separate the authors.
+#
+# Example:
+# Aziz, A. K., Kellogg, R. B., and Stephens, A. B.
+# becomes
+# Aziz, A. K. and Kellogg, R. B. and Stephens, A. B.
+#
+
+sub adjust_author
+{
+ my ($orig_author) = @_;
+ my @parsed_list = split(",", $orig_author);
+ my $length = scalar(@parsed_list);
+ return $orig_author if $length < 4;
+ my $author = "";
+ for (my $i = 0; $i < $length - 2; $i += 2) {
+ $author .= $parsed_list[$i] . "," . $parsed_list[$i+1]. " and";
+ }
+ $author .= $parsed_list[$length - 2] . "," . $parsed_list[$length - 1];
+ $author =~ s/and and/and/;
+
+ return $author;
+}
+
+#
+# generate a key from the author(s) and publication year
+#
+
+sub bib_key
+{
+ my ($author, $year) = @_;
+ $author =~ s/(.+),.+$/$1/; # clean out stuff that's not in last names
+ $author =~ s/,.+ and//g; # clean out separators: comma, " and"
+ $author =~ s/\W//g;
+ $author =~ s/\\[^\s{]+([\s{])/$1/g; # clean out TeX control sequences
+ my $key_sofar = $author . $year ;
+#
+# has this key already appeared?
+#
+ if (! exists $keys{$key_sofar}) {
+ $keys{$key_sofar} = 1;
+ return $key_sofar;
+ }
+ my $key;
+ my $addon = $keys{$key_sofar}++;
+ $addon =~ tr/1-9/b-j/;
+ return $key_sofar . $addon;
+}