#!/usr/bin/perl -- #-*-perl-*- # Alf-Christian Achilles # # This script resolves crossreferences in BibTeX files. # It replaces crossreferences with the data given in the crossreferenced entry. # # # Usage: expand.crossrefs [bibtex-file[.gz] ...] > file.expanded.bib # # The bibtex file(s) must be given on the command line, they may be compressed # with gzip. The bibtex data must have been successfully prettyprinted # with bibclean (available at ftp://ftp.math.utah.edu/pub/tex/bib/bibclean) # # The expanded BiTeX entries are written to stdout. # # If there is more than one file on the command line, then all the files # will be treated as one happy bibliography in the order in which they appear. # # This script does not care about the position of crossreferenced BibTeX # entries in the file. # If there are crossreferenced BibTeX entries with # the same key then only the one appearing later in the file will be # recognized. # This does not comply with the BibTeX definition, but will be fine # with most currently existing BibTeX bibliographies. @bibfiles = (); @crossrefsonly = (); while( $ARGV[0] =~ /^-/ ) { $_ = $ARGV[0]; shift; if (/^-crossrefs$/) { if (! -f $ARGV[0]) { die "File $ARGV[0] does not exist! Stopped at"; } push(@crossrefsonly,($ARGV[0])); shift; next; } print STDERR "Unknown option \"$_\"\n\n"; } @bibfiles =(@ARGV); if (scalar(@bibfiles) == 0) { die "No bibtex files given on command line, stopped at "; } else { foreach (@bibfiles) { if (! -f $_) { die "File $_ does not exist! Stopped at"; } } } %crossrefs = (); foreach $file ((@crossrefsonly),(@bibfiles)) { if ($file =~ /\.(z|gz|Z)$/) { if (!open(CROSSREFS,"gunzip -c $file |")) { die "Could not open pipe from \"gunzip -c $file |\""; } } else { if (!open(CROSSREFS,$file)) { die "Could not open file $file"; } } while ($_ = ) { # handle @string entries if (/^@(Book|Collection|Proceedings)\{(.*),$/i) { $crossrefkey = $2; $crossrefkey =~ y/A-Z/a-z/; $crossref = ''; while (($_ = ) && !/^\}$/) { $crossref .= $_; } $* = 1; if ($crossref =~ /^ title/i) { if ($crossref =~ /^ booktitle =/i) { $crossref =~ s/^ booktitle =(.|\n )+\n//i; } $crossref =~ s/ title = / booktitle =/i; } $crossref =~ s/^ author =(.|\n )+\n//i; $* = 0; $crossrefs{$crossrefkey} = $crossref; } } close(CROSSREFS); } foreach $file (@bibfiles) { if ($file =~ /\.(z|gz|Z)$/) { if (!open(BIBTEX,"gunzip -c $file |")) { die "Could not open pipe from \"gunzip -c $file |\""; } } else { if (!open(BIBTEX,$file)) { die "Could not open file $file"; } } while ($_ = ) { if (/^ crossref = *"(\S+)",$/) { ($crossrefkey = $1) =~ y/A-Z/a-z/; if (defined($crossrefs{$crossrefkey})) { print $crossrefs{$crossrefkey}; } else { print $_; } } else { print $_; } } close(BIBTEX); }