[comp.text.tex] bibmake - a BibTeX database utility

davidp@pico.oz (David Pascoe) (07/03/90)

Following is a utility create and use BibTeX bibliographies, written mostly 
for Unix boxes that have LaTeX and BibTeX installed.
------------------------Cut Here ---------------------------------------------
echo x - README
sed 's/^X//' >README <<'*-*-END-of-README-*-*'
XPermission is granted to anyone to use this software for any purpose
Xon any computer system subject to the following restrictions.
X 
X   a. The author is not responsible for the consequences of use of this
X      software, even if it defects arise from it
X
X   b. The origin of the software must not be misrepresented either by
X      explicit claim or omission
X
XThis shell script makes the building of a reading list or text bibliography
Xfile easy. 
X
XThis shar archive contains
XREADME		this file
XMakefile	simple makefile for partbibtex.c
Xbibmake		csh shell script
Xpartbibtex.c	prog to extract entries from a bib file by keyword
Xbibmake.1	man entry in nroff format
X
XThe file bibmake should be altered to suit the local installation of TeX.
XAlso the following programs must be available.
XLaTeX 
XBibTeX
Xsed
Xcsh    (bibmake is a csh script so you need to able to run csh scripts)
Xgrep
Xdvips (or whatever you use)
X
XThis script was written originally to take advantage of existing bibliography
Xdatabases written in BibTeX format. Macintosh users needed some way of 
Xtransfering a BibTeX bibliography in text format so that is also supported.
XThis way users of other document preparation systems can still use the power
Xof BibTeX in formating their bibliographies. Also, entire bibliographies can be
Xprinted by specifying keyword \@ (for those not running the latest version of
XBibTeX).
X
XBibmake is a useful tool for keeping track of databases and formatting keyword
Xsearches.
X
XThe manual entry discusses in more detail the operation of bibmake.
*-*-END-of-README-*-*
echo x - Makefile
sed 's/^X//' >Makefile <<'*-*-END-of-Makefile-*-*'
X
Xpartbibtex: partbibtex.c
X	cc -O -o partbibtex partbibtex.c
*-*-END-of-Makefile-*-*
echo x - bibmake
sed 's/^X//' >bibmake <<'*-*-END-of-bibmake-*-*'
X#!/bin/csh -f
X#
X# bibmake V1.00
X#
X# Script to extract entries from bibliographies and format 
X#
X# Written David Pascoe December 1989
X#
X# davidp@pico.qpsx.oz
X#
X# default is text output and alpha bibliography style
X# see bibmake(l) for more info.
X
Xset file=0			# file name is not specified
Xset out=file			# default is text output
Xset key=0			# keys are empty
Xset num=0			# number of entries
Xset style=alpha			# default style name
Xset stat=0			# return status
Xset pages=0			# number of A4 pages generated
Xset sourcefiles=""		# source bibliography files
Xset bibtexfiles=""
X
Xif ($#argv < 3) then
Xer:
X     echo "Usage: bibmake [-t|-p|-l] [-s style] -f bib_files .... -k keywords ....." 
X     exit(1)
X   endif
Xtop:
X
Xif ($#argv >= 2) then
X   switch ($argv[1])
X
X  case -t:  		# output type is text
X      set out=file
X      shift argv
X      goto top   
X
X  case -p:		# output type is printed document
X      set out=lw
X      shift argv
X      goto top
X
X  case -l:		# output type is suitable for straight LaTeX
X      set out=latex
X      shift argv
X      goto top
X
X  case -s:		# specify the name of the style to use
X      shift argv
X      set style = $argv[1]
X      shift argv
X      goto top
X
X  case -k:		# now read in the keywords
X   set key=1
X   if ($file != 0) then
Xlab:
X     shift argv
X     if ($argv[1] != "") then
X	   partbibtex $argv[1] $sourcefiles >> /tmp/$$.bib
X	      if ($#argv > 1) then
X	        goto lab
X              else
X    	       set num = `grep -c \@ /tmp/$$.bib`
X	       	if ($num == "0") then
X	           echo "bibmake: No matching entries found"
X		   exit(1)
X                else
X 		   if ($num == 1) then
X                     echo $sourcefiles : 1 entry found
X                   else
X                     echo $sourcefiles : $num entries found 
X                   endif
X                endif
X     endif
X   endif
X   goto top
X   else
X      # the filename for the bib file must be given first
X      echo "bibmake: Database file name must be specified first"
X      echo
X      exit(1)
X   endif
X			
X    case -f:		# read in the name of the bib file 
X        shift argv
X    loop:
X	set file=$argv[1]
X	if !(-e $file.bib) then
X	   echo "bibmake: Bibliography File "$file.bib" Not Found"
X	   echo
X	   exit(1)
X        else
X           cp $file.bib /tmp
X           set sourcefiles=($sourcefiles" "$file.bib)
X	   if ($bibtexfiles == "") then
X              set bibtexfiles=$file
X           else
X              set bibtexfiles=($bibtexfiles","$file)
X	   endif
X           shift argv
X           if ($argv[1] == "-k") then
X             goto top
X           else
X             goto loop
X           endif
X	endif
X	shift argv
X   echo $files
X	goto top
X
X    default:
X        goto er
X
X endsw
X
Xendif
Xif ($key == 0) then
X    echo "bibmake: no keywords specified"
X    exit(1)
Xendif
Xif ($out == "file" || $out == "latex") then
X#
X# create an .aux file to run straight through BibTeX and then
X# massage the .bbl file to output a "text" form of the database
X#
X    # put in the requested style types and bibfile location
X    echo "\bibstyle{"$style"}" > /tmp/$$.aux
X    echo "\bibdata{"$bibtexfiles"}" >> /tmp/$$.aux
X    # change all of the key fields into citations
X    sed -n -e 's/^.*@.*{\([^,]*\),\(.*\)$/\\citation{\1}/p' < /tmp/$$.bib >> /tmp/$$.aux
X    # attempt to catch an unknown style file error in BibTeX
X    set stat = `bibtex /tmp/$$ >& /dev/null`
X    if (-z /tmp/$$.bbl) then 
X      echo bibmake: BibTeX failed. possibly style file: $style not available
X      echo bibmake: or execeeded BibTeX string limit.
X      rm -f /tmp/$$.*
X      exit(1) 
X    endif
X    if ($out == "latex") then
X      cat /tmp/$$.bbl
X    else
X      sed -e 1d -e \$d -e 's/\\newblock//' -e 's/\\bibitem\(\[.*\]\).*}/\1/' -e 's/\~/ /g' -e 's/\\bibitem{.*}//' -e 's/{\([^}]\)}/\1/g' < /tmp/$$.bbl
X    endif
X    rm /tmp/$$.*
X    rm /tmp/*.bib
Xelse
X#
X#  create a .tex file to run twice through LaTeX and then BibTeX and twice
X#  through LaTeX to incorporate the bibliography.
X# 
X    cd /tmp
X    echo "\documentstyle[a4]{article} \begin{document}\scriptsize" > /tmp/$$.tex
X    echo "\bibliographystyle{"$style"}\bibliography{"$bibtexfiles"}" >> /tmp/$$.tex
X    # find the key fields in the .bib file and change to nocites
X    sed -n -e 's/^.*@.*{\([^,]*\),\(.*\)$/\\nocite{\1}/p' < /tmp/$$.bib >> /tmp/$$.tex
X    echo "\end{document}" >> /tmp/$$.tex
X    # run through twice to get the .aux file ok
X    latex /tmp/$$  >& /dev/null
X    latex /tmp/$$  >& /dev/null
X    # attempt to catch an unkown style file error in BibTeX
X    set stat = `bibtex /tmp/$$ >& /dev/null`
X    # if the .bbl file is empty 
X    if (-z /tmp/$$.bbl) then
X      echo bibmake: BibTeX failed. possibly style file: $style not available
X      echo bibmake: or exceeded BibTeX string limit.
X      rm  /tmp/$$.*
X      exit(1) 
X    endif
X    latex /tmp/$$  >& /dev/null
X    latex /tmp/$$  >& /dev/null
X    # find the number of pages that were generated by looking at the .log file
X    set pages = `sed -n -e 's/Output written.*(\(.*\),.*)./\1/p' < /tmp/$$.log`
X    dvi2ps /tmp/$$ -q | lpr -v -Plw
X    echo $file.bib: $pages generated
X    rm /tmp/$$.*
X    rm /tmp/*.bib
X  endif
Xendif
X
Xdone:
*-*-END-of-bibmake-*-*
echo x - bibmake.1
sed 's/^X//' >bibmake.1 <<'*-*-END-of-bibmake.1-*-*'
X.TH bibmake 1-local
X.SH NAME
Xbibmake \- Create a bibliography
X.sp
X.SH SYNOPSIS
X\fBbibmake  \fI [-t|-p|l][-s style] -f bib-files ... -k keywords ...\fR
X.sp
X.SH DESCRIPTION
X.I Bibmake
Xallows the user to specify entries in a 
X.I BibTeX
Xdatabase file to use in making a bibliography file that is suitable
Xfor text transfer to a macintosh, straight input to LaTeX, or a hard copy at the laser writer.
X
X.I Bibmake
Xwas written so that large bibliography databases could be used easily by
Xpeople wishing to get a reading list on a topic. Also the power of
X.I BibTeX
Xcan be used to generate a consistent and alphabetically ordered bibliography. This also has the advantage
Xof the availability of different bibliography styles (
X.I .bst
Xfiles ). A program called
X.I partbibtex
Xis used to search for keywords and then pull out the whole matching entry.
X
X.I Bibmake 
Xmay take a few minutes to generate in printout format if given
Xmore than about 100 entries.
X
X.I Bibmake
Xassumes that the files specified will be in 
X.I BibTeX
Xformat. Refer bibliographies may be transformed into 
X.I BibTeX
Xformat by using r2bib(1l).
X
X.SH OPTIONS
X.TP
X.B \-l
XPrint to stdout the resulting .bbl file. This is useful to users that only
Xhave access to LaTeX on another machine. In this way BibTeX can be used to
Xbuild a database on one machine and if only LaTeX is available on another
Xmachine, the bibliographies are easily accessable
X.TP
X.B \-p
XPrint out all of the matching entries, about 35 to a page. The output is automatically sent to the laser writer. 
XThis option is quite slow because a few passes through 
X.I LaTeX
Xand
X.I BibTeX
Xare needed to generate a printable document. The actual number of pages 
Xthat will appear at the laser writer is reported.
X.TP
X.B \-t
XSend to standard out a text file that lists all of the details of the chosen
Xentries in a form suitable for a text transfer. Most 
X.I LaTeX
Xformatting commands have been stripped, except for   
X.I \\\it
Xand
X\fI\\em\fR
Xwhich are left in to indicate that the text enclosed in brackets should be placed in
X.I italics.
X.TP
X.B \-s style
XSpecify 
X.I style
Xto be the .bst file that 
X.I BibTeX
Xwill use to format the bibliography. 
X.I BibTeX
Xwill consult the shell environment variable TEXINPUTS in looking for the
Xrequired .bst file. Examples of this field are acm, plain, unsort, thesis.
X.TP
X.B \-f bib_file ...
XThe base 
X.I BibTeX
Xdatabase files that will be checked against the keywords given. These files 
X.I must
Xbe specified
X.I before
Xthe keywords. This is because of the nature of the command line calling for
Xpartbibtex(1l). 
X.TP
X.B \-k keywords ...
XList the keywords that will result in an entry in the bibliography. Key fields
Xor any word in the whole entry may be specified.
X.SH DEFAULTS
X.TP
X.B \-m
X.TP
X.B \-s alpha
X.SH EXAMPLES
X.TP
Xbibmake -s ieeetr -f mybib -k stereo marr
XCreate a text ieeetr formated bibliography from mybib.bib using all entries with stereo or marr in them.
X.TP
Xbibmake -p -s plain -f read -k \
X\\\@
XSend to the laser writer in plain form ALL of the entries in read.bib
X.TP
Xbibmake -l -f vis rob conn -k motion
XFind all of the motion refernces in the vis, rob, and conn bibliographies and
Xcat out the resulting .bbl file.
X.SH DIAGNOSTICS
XMost of the common errors possible are detected but it is possible for some
Xof the more bizarre errors to hang the program. For instance if 
X.I LaTeX
Xfinds an illegal character when formatting a bibliography it will hang. Unfortuantely
Xthere is no simple way of detecting this. 
X.I BibTeX 
Xand
X.I LaTeX
Xrun with stderr and stdout redirected to /dev/null so that the screen does not fill of
Xgarbage.
X
XIf the program does hang, ^Z and then bg to watch if it has in fact hung, and
Xthen the offending command will be seen using ps. Try executing that command
Xfrom /tmp and the error will become obvious.
X
X.SH FILES
X.TP 2.5 i
X/dev/null
Xwhere the output while 
X.I LaTeX
Xand
X.I BibTeX
Xare working is sent.
X
X.TP
X/tmp/$$.{tex,aux,bbl,blg,bib,dvi,log}
XScratch files that may be used by bibmake.
X
X.SH AUTHOR
X David Pascoe 1989 davidp@pico.qpsx.oz
X.SH "SEE ALSO"
Xpartbibtex(1l),bibtex(1l),latex(1l)
*-*-END-of-bibmake.1-*-*
echo x - partbibtex.c
sed 's/^X//' >partbibtex.c <<'*-*-END-of-partbibtex.c-*-*'
X/* partbibtex.c */
X
Xstatic char rcsid[] = "$Header$";
X/*
X**
X**     Author unknown
X**
X*/
X#include <stdio.h>
X#ifdef SYSV
X#include <string.h>
X#define index strchr
X#endif
X#ifdef BSD
X#include <strings.h>
X#endif
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
XFILE * in;
X#define BUFLEN 600000
X#define STRLEN 400
X
Xextern char *getenv();
X
Xmain (argc, argv)
Xint argc;
Xchar * argv[];
X{
X	FILE * fopen();
X	char * key;
X	int caseop = 1;
X	int ret ,length, iseof, print, lnlen, keylen, i, j;
X	struct stat stbuf;
X	char buf[BUFLEN];
X	char filename[STRLEN];
X	char actstr[STRLEN];
X	char *texinputs, *top, *end;
X
X	argv++, argc--;
X	if (!argc)
X		fprintf(stderr,"usage:partbibtex [-c] keyword <files>\n"), exit(1);
X	if (argv[0][0] == '-')
X	{
X		if (argv[0][1] == 'c')
X			caseop = 0;
X		else
X		    fprintf(stderr,"usage:partbibtex [-c] keyword <files>\n"), exit(1);
X		argv++, argc--;
X	}
X	key = *argv;
X	keylen = strlen(key);
X	if (argc <= 1)
X		fprintf(stderr,"usage:partbibtex [-c] keyword <files>\n"), exit(1);
X	texinputs = getenv("TEXINPUTS");
X	while (--argc,++argv, argc>0 ) {
X		if ((texinputs != NULL) && (**argv != '/')) {
X			if (STRLEN <= (strlen(texinputs) + strlen(*argv)))
X			  fprintf(stderr, "Warning: Environment String too long\n");
X			strncpy(actstr,texinputs,STRLEN);
X			top = actstr;
X			end = actstr;
X			ret = -1;
X			while (end != NULL) { /* evaluate TEXINPUTS */
X				end = index(top,':'); /* Search for first : */
X				if (end != NULL) *end = '\0'; /* modify : to \0 */
X				strncpy(filename,top,STRLEN);
X				if (end != NULL) top = ++end;
X				if (!(length = strlen(filename))) continue;
X				filename[length++] = '/';
X				filename[length] = '\0';
X				strcat(filename,*argv);
X				if ((ret = stat(filename,&stbuf)) ==  0)  break;
X			}
X			if (ret < 0) {
X				fprintf(stderr,"file not found: %s\n",*argv);
X				continue;
X			}
X		}
X		else strcpy(filename,*argv); /* TEXINPUTS was not set or filename
X					begins with a / */
X
X		if (stat(filename,&stbuf) < 0) {
X			fprintf(stderr,"file not found: %s\n",filename);
X			continue;
X		}
X		if ((stbuf.st_mode & S_IFMT) != S_IFREG) {
X			fprintf(stderr," %s is not an ordinary file\n",filename);
X			continue;
X		}
X		if ((in=fopen(filename,"r")) == NULL) {
X			fprintf(stderr,"%s can not be opened\n",filename);
X			continue;
X		}
X		print = lnlen = 0;
X		while (1) {
X			iseof = getline(buf,&lnlen);
X			for (i=j=0; i<(lnlen+j-keylen) ; i++)
X				if (key[j] == buf[i] || (caseop && (
X				(key[j] == (buf[i]+32) && isupper(buf[i])) ||
X				    (key[j] == (buf[i]-32) && isupper(key[j]))))) {
X					if (++j == keylen) {
X						print = 1;
X						break;
X					}
X				}
X				else
X					j=0;
X			if (print) {
X				for (i=0 ; i<lnlen ; i++)
X					putchar(buf[i]);
X				print = 0;
X			}
X			if (iseof == EOF)
X				break;
X		}
X	}
X	exit(0);
X}
X
X
Xint getline(line,len)
Xchar * line;
Xint * len;
X{
X	int count = 0;
X
X	if ((*line = getc(in)) == EOF)
X		return(EOF);
X	else
X	    count++, line++;
X	while ((*line = getc(in)) != EOF && *line != '@' ) {
X		count++;
X		line++;
X		if (count > BUFLEN) {
X			fprintf(stderr,"Entry too long\n");
X			exit(1);
X		}
X	}
X	*len = count;
X	if (*line == EOF)
X		return(EOF);
X	else
X		ungetc(*line, in);
X	return(count);
X}
*-*-END-of-partbibtex.c-*-*
echo x - partbibtex.1
sed 's/^X//' >partbibtex.1 <<'*-*-END-of-partbibtex.1-*-*'
X.TH PARTBIBTEX 1-local
X.SH NAME
Xpartbibtex \- Extract entries from a BIBTeX database
X.sp
X.SH SYNOPSIS
X\fBpartbibtex  \fI [-c] keyword <file>\fR
X.sp
X.SH DESCRIPTION
X.I partbibtex
Xallows the extraction of entries from a \fIBIBTeX\fR database by the given
Xkeyword.
XEntries in which this key word is found are displayed on <stdout> in the
Xformat that they appear in the database.
X.br
XThis can be used, for example, to extract all entries with a common subject
Xor author.
X.br
X.I partbibtex
Xnormally ignores the case of letters when performing comparisons.
XThe -c options causes upper and lower case letters to be differentiated.
X.SH "SEE ALSO"
Xaddbibtex(1l), sortbibtex(1l)
*-*-END-of-partbibtex.1-*-*
exit