ftp.nice.ch/pub/next/text/framemaker/fmbib.1.3.s.tar.gz#/bibdata.c

This is bibdata.c in view mode; [Download] [Up]

/* bibdata.c
 * cm, 20 Dec 90
 *
 * module to handle inserting/retrieving bibliography data items
 *
 * HISTORY
 *  27 May 92, neek: Added (-a) support for user-specified bib. doc. sorting.
 *  28 May 92, neek: Fixed broken ieee style (sort_by_cite) bib sorting.
 *  28 May 92, dmw:  Added ieeetrans style for IEEE Transactons, 
 *					 which use bracket references.
 * 					 Hank Walker (dmw) at Carnegie Mellon University.
 *
 */

/*
 * Copyright (c) 1991 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */
#include <stdio.h>
#include <ctype.h>
#include <mif.h>
#include <bib.h>
#include <bibstyles.h>

#define MAX_SORT_KEYS 10

extern char *reftypes[];
extern char *reffieldtypes[]; 
extern char *bibstyle;
static BibEnt *retrieve_bibent();
static char *get_auth();
static char *get_yr();
char *bib_templatefile();

static BibEnt *bibent_root;	/* top-o-the tree of parsed bib entries. */
static BibList *sorted_bibs;	/* list of pointers into bibent tree, sorted
				 * the way they should be output as dictated by
				 * the 'BibStyle' variable in the mif files.
				 */

static BibStyle bibstyles[] = {
{ "apa", cite_paren, cite_paren_commas, sort_by_alpha, pgf_author_comma_year, 0},
{ "apadraft", cite_paren, cite_paren_commas, sort_by_alpha, pgf_author_comma_year, 0},
{ "cacm", cite_bracket, cite_bracket_commas, sort_by_alpha, pgf_numeric, ref_cacm },
{ "cacmdraft", cite_bracket, cite_bracket_commas, sort_by_alpha, pgf_numeric, ref_cacm },
{ "ieee", cite_super_commas, cite_super_commas,  sort_by_cite, pgf_numeric, ref_ieee },
{ "ieeedraft", cite_super_commas, cite_super_commas,  sort_by_cite, pgf_numeric, ref_ieee },
{ "ieeetrans", cite_bracket, cite_bracket_commas,  sort_by_cite, pgf_numeric, ref_ieeetrans },
{ "ieeetransdraft", cite_bracket, cite_bracket_commas,  sort_by_cite, pgf_numeric, ref_ieeetrans },
{ "stdnum", cite_bracket, cite_bracket_commas,  sort_by_alpha, 
		pgf_numeric, ref_stdnumeric },
{ "stdnumdraft", cite_bracket, cite_bracket_commas,  sort_by_alpha, 
		pgf_numeric, ref_stdnumeric },
{ "stdalpha", cite_bracket, cite_bracket_commas, sort_by_alpha, 
		pgf_author_year, ref_stdalphabetic },
{ "stdalphadraft", cite_bracket, cite_bracket_commas, sort_by_alpha, 
		pgf_author_year, ref_stdalphabetic },
{ "stdident", cite_bracket, cite_bracket_commas, sort_by_alpha, pgf_authyr, ref_stdidentifier },
{ "stdidentdraft", cite_bracket, cite_bracket_commas, sort_by_alpha, pgf_authyr, ref_stdidentifier },
{ 0 },
};

static BibStyle default_bibstyle = 
{ "stdnum", cite_bracket, cite_bracket_commas,  sort_by_alpha, 
		pgf_numeric, ref_stdnumeric };


static BibStyle *crrnt_bibstyle;
static FldType  bf_key, bf_author, bf_fullauthor, bf_title, bf_year;
static FldType  bf_journal, bf_publisher, bf_editor, bf_editors; 
static FldType	bf_institution, bf_organization;
static int crrnt_pgf_num;
static FldType sort_matrix[MAX_SORT_KEYS];
static FldType default_sort_matrix[MAX_SORT_KEYS];
static int num_sortkeys;	/* no. of valid Fields entered in sort_matrix */



/* point to the bibstyle structure specified by user in the
 * BibStyle statement.
 */
init_bibstyle( style )
	char *style;
{
	static int found=0;
	register BibStyle *bsp;
	static char	lcase[128];
	char buf[256];

	if( found )
		return;

	bf_key = fldtype("key");
	bf_author = fldtype("author");
	bf_fullauthor = fldtype("fullauthor");
	bf_title = fldtype("title");
	bf_journal = fldtype("journal");
	bf_publisher = fldtype("publisher");
	bf_editor = fldtype("editor");
	bf_editors = fldtype("editors");
	bf_institution = fldtype("institution");
	bf_organization = fldtype("organization");
	bf_year = fldtype("year");

	/* initialize the structure used to sort the bibliography */
	build_sort_matrix();
		
	/* if multiple docs, just use first one found */
	if( !style )
	{
		crrnt_bibstyle = &default_bibstyle;
		bibstyle = crrnt_bibstyle->bs_style;
		found++;
		return;
	}

	strtolower( lcase, style );
	for( bsp = bibstyles; bsp->bs_style; bsp++ )
		if( streq( lcase, bsp->bs_style ))
		{
			found++;
			crrnt_bibstyle = bsp;
			bibstyle = lcase;
			break;
		}
	if( !found )
	{
		crrnt_bibstyle = &default_bibstyle;
		bibstyle = crrnt_bibstyle->bs_style;
		err( WARN, "No such bib style as <%s>, using default '%s'\n",
			style, bibstyle );
		for( buf[0]=0, bsp = bibstyles; bsp->bs_style; bsp++ )
		{
			if( buf[0] != 0 )
				strcat( buf, ", " );
			strcat( buf, bsp->bs_style );
		}
		err( WARN, "Supported bib styles are: %s\n", buf );
	}
}

/* build an array which specifies the order (of fields) which the
 * bib entries should be sorted by.  The user could alter the default
 * w/ the -a command line switch.
 */
static
build_sort_matrix()
{
	char *fldptr;
	char *next_custom_sortfld();
	FldType tmp_fldtype;

	/* we get here if user didn't specify a custom_sort or failed
	 * to specify any valid fields in the custom_sort parameter.
	 */
	default_sort_matrix[0] = sort_matrix[0] = bf_key;
	default_sort_matrix[1] = sort_matrix[1] = bf_author;
	default_sort_matrix[2] = sort_matrix[2] = bf_fullauthor;
	default_sort_matrix[3] = sort_matrix[3] = bf_title;
	default_sort_matrix[4] = sort_matrix[4] = bf_journal;
	default_sort_matrix[5] = sort_matrix[5] = bf_publisher;
	default_sort_matrix[6] = sort_matrix[6] = bf_editor;
	default_sort_matrix[7] = sort_matrix[7] = bf_editors;
	default_sort_matrix[8] = sort_matrix[8] = bf_institution;
	default_sort_matrix[9] = sort_matrix[9] = bf_organization;		
		/* don't go past MAX_SORT_KEYS entries */

	num_sortkeys = MAX_SORT_KEYS;

	if( custom_sort ) {
		for( num_sortkeys=0; num_sortkeys<MAX_SORT_KEYS; ) {
			fldptr = next_custom_sortfld();
			if( !fldptr )	
				break;
			if(( tmp_fldtype = fldtype(fldptr)) == -1 ) {
				err(WARN, "Disregarding illegal sort field: %s\n", fldptr );
				continue;	
			}
			sort_matrix[num_sortkeys] = tmp_fldtype;
			num_sortkeys++;
		}
		if( num_sortkeys < 1 )
			err(WARN, "No legal sort keys entered, using default" );
		else
			return;
	}
}

static char *
next_custom_sortfld()
{
	/* currently this routine is set up to be called once
	 * to initialize the sort_matrix[].  Returns pointer
	 * to the next field parsed in the comma separated list
 	 * provided on the command line (-a switch).  Returns NULL
	 * at the end of the list.
	 */
	static char *fldptr = (char *)-1;
	register char *sp, *dp;
	static char fldbuf[128];

	if( fldptr == (char *)-1 )
		fldptr = custom_sort;
	if( !fldptr || ! *fldptr )
		return( NULL );
	
	for( sp=fldptr, dp=fldbuf; *sp; sp++, dp++ ) {
		if( *sp == ',' ) {
			break;
		}
		*dp = *sp;
	}
	fldptr = *sp ? sp+1 : sp;
	*dp = 0;
	return( dp == fldbuf ? NULL : &fldbuf[0] );
}


/* allocate memory for new bib entry 
 */
static BibEnt *
new_bibent()
{
	register BibEnt *bp = (BibEnt *) getmem( sizeof( BibEnt ));

	bp->be_fields = NULL;
	bp->be_l = bp->be_r = NULL;
	bp->be_rollcall = 0;
	bp->be_found = 0;
	return( bp );
}
	

/* store a new field and its data in a bib entry.
 * sort list alphanumerically by type.
 */
store_bibfield( bp, type, val )
	register BibEnt *bp;
	FldType		type;
	register char   *val; 
{
	register BibField *bfp;

	bp->be_rollcall |= (1<<type);	

	bfp = (BibField *)getmem( sizeof( BibField ) ); 
	bfp->bf_type = type;	
	bfp->bf_val = getmem( strlen(val) + 1 );
	strcpy( bfp->bf_val, val );
	bfp->bf_l = bfp->bf_r = NULL;

	/* link into list */
	insert_bibfield( &(bp->be_fields), bfp );

}


static 
insert_bibfield( root, bfp )
	register BibField **root;
	register BibField *bfp;
{
	
	if( *root == NULL )
	{
		*root = bfp;
		return;
	}

	if( bfp->bf_type < (*root)->bf_type )
		insert_bibfield( &(*root)->bf_l, bfp );
	else 
		insert_bibfield( &(*root)->bf_r, bfp );


}

/* find the specified BibField entry.
 */
BibField *
find_bibfield( bep, fld )
	BibEnt	*bep;
	FldType fld;
{
	BibField *get_bibfld();

	if( ! (bep->be_rollcall & (1<<fld)))
		return( NULL );
	return( get_bibfld( bep->be_fields, fld ));	
}


/* traverse the fields tree looking for specified fld.
 */
static BibField *
get_bibfld( root, fld )
	register BibField *root;
	register FldType fld;
{
	if( !root )
		return( NULL );
	if( fld == root->bf_type )
		return( root );
	if( fld < root->bf_type )
		return( get_bibfld( root->bf_l, fld ));
	else
		return( get_bibfld( root->bf_r, fld ));
}


/* create a new bibent node, w/ the specified key.
 * enter it into the tree.  This is called from
 * parsing the mif file and finding Bibliography
 * markers, and begins the creation of the BibEnt tree.
 * note: keys are case insensitive.
 */
store_xrefkey( xrefkey )
	register char *xrefkey;
{
	register BibEnt *bp;

	if( !xrefkey ) return;

	bp = new_bibent();
	bp->be_xref = getmem( strlen( xrefkey ) + 1 );
	strtoupper( bp->be_xref, xrefkey );
	insert_bibent( &bibent_root, bp );
}



/* insert a bibentry into a sorted tree.
 * store sorted according to the style's sort function.
 */ 
static
insert_bibent( root, bp )
	register BibEnt **root;
	register BibEnt *bp;
{
	int	cmp;
	register BibEnt *newp;

	if( *root == NULL )	 {
		*root = bp;
		return;
	}

	if( crrnt_bibstyle->bs_sortfunc == sort_by_cite ) {
		/* sort by citation order, linear list */
		for(newp = *root; newp->be_r; newp = newp->be_r)
			if(strcmp(bp->be_xref, newp->be_xref) == 0 )
				return; 	/* a repeat */
		newp->be_r = bp;	/* add to end of list */
		return;
	} else {
		/* alpha-numeric sort. */
		cmp = strcmp(bp->be_xref, (*root)->be_xref); 
		if( cmp<0 ) 
			insert_bibent( &((*root)->be_l), bp );
		else if( cmp>0 )
			insert_bibent( &((*root)->be_r), bp );
	}
	/* if equal, it's already in tree, skip it. */
}


/* cross-post bibentry to a list sorted according
 * the the dictates of the current Reference style, ie how the
 * bibentries will actually be output.
 */
sort_bibent( bp )
	BibEnt *bp;
{
	register BibList *blp;

	blp = (BibList *)getmem( sizeof(BibList) );
	blp->bl_bep = bp;
	blp->bl_next = NULL;

	/* resort by current alpha numeric key[s] if that is the
	 * chosed style.  If sorting by citation order, the bibent_root
	 * tree will already be in that order, no need to cross-post.
	 */
	if( crrnt_bibstyle->bs_sortfunc == sort_by_alpha )
		sort_by_alpha( blp );
}


BibEnt *
find_bibent( lookup )
	char * lookup;
{
	BibEnt *retrieve_bibent();

	return( retrieve_bibent( bibent_root, lookup ));
}


/* retrieve a bib entry from the tree, based on its
 * be_xref field. Return NULL if not found.
 */
static BibEnt *
retrieve_bibent( root, lookup )
	register BibEnt *root;
	register char *lookup;
{
	int	cmp;
	register BibEnt *bp;

	if( root == NULL )
		return( (BibEnt *)NULL );

	if( crrnt_bibstyle->bs_sortfunc == sort_by_cite ) {
		for(bp=root; bp; bp = bp->be_r)
			if( strcmp( lookup, bp->be_xref ) == 0)
				return(bp);
		return(NULL);
	} else {
		/* alpha-numerically sorted */
		cmp = strcmp(  lookup, root->be_xref );

		if( cmp == 0 )
			return( root );
		else if( cmp < 0) 
			return(retrieve_bibent( root->be_l, lookup ));	
		else 
			return(retrieve_bibent( root->be_r, lookup ));	
	}
}

/* consistency check:
 * check all bibentries found in the input Frame documents
 * and validate that associated bibliography data was found
 * in the bib files.  If not, let the user know.
 */
chk_bibs()
{
	chk_bibent(bibent_root);
}

chk_bibent( bep )
	register BibEnt *bep;
{
	if( !bep )
		return;
	chk_bibent( bep->be_l );
	if( !bep->be_found )
		err(WARN, "WARNING: No bib data found for <%s> bib marker\n",
			bep->be_xref );
	chk_bibent( bep->be_r );
}

/* verify the integrity of the bib database fields, versus the
 * mandatory/optional definitions in .style file.
 */
verify_bibs()
{
	verify_bibent(bibent_root);
}


/* generate a reference string, depending on the current style.
 * this is only relevant if the current style does not use
 * auto-numbering scheme for the references.
 */
prt_refstring(bep)
	register BibEnt *bep;
{
	if( crrnt_bibstyle->bs_reffunc )
		crrnt_bibstyle->bs_reffunc(bep);
}
		


/**************************************************
 * routines to output .mif bibligraphy statements
 * based on the current bib style selected by user
 * the BibStyle variable.
 *************************************************/


/* write out the correct xref format statements according to
 * the user-selected BibStyle variable. 
 */
create_xrefformats()
{
	register type;
	char	buf[256];
	char	**xrefstyles = crrnt_bibstyle->bs_citestyles;

	if( contiguous_cites )
		xrefstyles = crrnt_bibstyle->bs_multicitestyles;
	else
		xrefstyles = crrnt_bibstyle->bs_citestyles;

	for( type=0; type<4; type++ )
	{
		mif_writeln( O_TMP, "  <XRefFormat ");
		sprintf( buf, "   <XRefName `%s'>", xrefnames[type] );
		mif_writeln( O_TMP, buf);
		sprintf( buf, "   <XRefDef `%s'>", xrefstyles[type] );
		mif_writeln( O_TMP, buf);
		mif_writeln( O_TMP, "  > # end of XRefFormat" );
	}
}

/* simply add to the end of the list, 
 * duplicates are thrown away.
 */
sort_by_cite( new )
	register BibList *new;
{
	register BibList *bl;
		

	if( sorted_bibs == NULL )
	{
		sorted_bibs = new;
		return;
	}
	for( bl=sorted_bibs; bl->bl_next; bl=bl->bl_next )
		if( bl->bl_bep == new->bl_bep )
			return;
		;
	bl->bl_next = new;
}


/* sort (case insensitive) by bibent's Key, then Author, then Title., etc 
 */
sort_by_alpha( new )
	register BibList *new;
{
	register BibList *bl;
	register BibEnt *bp = new->bl_bep;
	BibField *bf=NULL;
	register char	 *sortkey, *sortkey1;
	char		 *cp;
	char 	 *find_sortkey();
	int		i, cmp;
	char	lcase1[256];
	char	lcase2[256];
	
	sortkey = find_sortkey(bp, 0);

	if( !sortkey )
	{
		err( WARN, "No appropriate sort key for %s citation, using <%s>\n",
			bp->be_xref, bp->be_xref );
		sortkey = bp->be_xref;
	}
	new->bl_key =  sortkey;

	if( !sorted_bibs )
	{
		sorted_bibs = new;
		return;
	}
	
	strtolower( lcase1, sortkey );
	sortkey1 = find_sortkey(sorted_bibs->bl_bep, 0);
	strtolower( lcase2, sortkey1);
		
	cmp = strcmp( lcase1, lcase2);	
	if( !cmp )	{	
			/* assure this entry has really been entered by
         	 * making sure it has the same xref fields..
         	 */
         	 cp = sorted_bibs->bl_bep->be_xref;
         	 sortkey1 = bp->be_xref;
         	 strtolower( lcase2, cp );
         	 strtolower( lcase1, sortkey1 );
         	 if((cmp = strcmp( lcase1, lcase2 )) == 0)
        		return;
			
			/* If xref fields differ, then only the current
			 * sortkeys matched.  Try the next level[s] of sortkeys.
	         */
			for( i=1; i<MAX_SORT_KEYS; i++ ) {
				sortkey = find_sortkey(bp, i);
				sortkey1 = find_sortkey(sorted_bibs->bl_bep, i);
				if( ! (sortkey && sortkey1))
						continue;
         	 	strtolower( lcase2, sortkey);
         	 	strtolower( lcase1, sortkey1 );
				if( cmp = strcmp( lcase1, lcase2) )
					break;
			}
			if( i == MAX_SORT_KEYS )
				return; 	/* everything but xref matched, 
						     * treat as same entry */
	}
	
	if( cmp < 0 )		/* insert at head ? */
	{
		new->bl_next = sorted_bibs;
		sorted_bibs = new;
		return;
	}
	for( bl=sorted_bibs; bl->bl_next; bl=bl->bl_next )
	{
		sortkey1 = find_sortkey(bl->bl_next->bl_bep, 0);
		strtolower( lcase2, sortkey1);
		cmp = strcmp( lcase1, lcase2 );	
		if( !cmp )	{	
			/* assure this entry has really been entered by
         	 * making sure it has the same xref fields..
         	 */
	     	 cp = bl->bl_next->bl_bep->be_xref; 
         	 sortkey = bp->be_xref;
         	 strtolower( lcase1, sortkey );
         	 strtolower( lcase2, cp );
         	 if((cmp = strcmp( lcase1, lcase2 )) == 0)
        		return;
			
			/* If xref fields differ, then only the current
			 * sortkeys matched.  Try the next level[s] of sortkeys.
	         */
			for( i=1; i<MAX_SORT_KEYS; i++ ) {
				sortkey = find_sortkey(bp, i);
				sortkey1 = find_sortkey(bl->bl_next->bl_bep, i);
				if( ! (sortkey && sortkey1))
						continue;
         	 	strtolower( lcase2, sortkey);
         	 	strtolower( lcase1, sortkey1 );
				if( cmp = strcmp( lcase1, lcase2) )
					break;
			}
			if( i == MAX_SORT_KEYS )
				return; 	/* everything but xref matched, 
						 	 * treat as same entry */
		}
		if( cmp > 0 )
			continue;
		break;
	}
	if( !bl->bl_next )	 /* add to tail */
		bl->bl_next = new;
	else			 /* insert */
	{
		new->bl_next = bl->bl_next;
		bl->bl_next = new;
	}
}

 
static 
pgf_numeric(bp)
	BibEnt *bp;	
{
	char	buf[128];

	sprintf(buf, "    <PgfTag `%d'>", crrnt_pgf_num);
	mif_writeln(O_BIB, buf);
}

/* citation of the form [KNU89]
 */
static
pgf_authyr(bp)
	BibEnt *bp;
{
	char buf[256];
	char *auth;
	char *year;

	auth = get_auth(bp, 1);
	if( year = get_yr(bp) )
		sprintf( buf, "    <PgfTag `%s%s'>", auth, year);
	else
		sprintf( buf, "    <PgfTag `%s'>", auth);

	mif_writeln(O_BIB, buf );
}

/* citation of the form [Knuth 89]
 */
static
pgf_author_year(bp)
	BibEnt *bp;
{
	char buf[256];
	char *auth;
	char *year;

	auth = get_auth(bp, 0 );
	if( year = get_yr(bp) )
		sprintf( buf, "    <PgfTag `%s %s'>", auth, year);
	else
		sprintf( buf, "    <PgfTag `%s'>", auth);

	mif_writeln(O_BIB, buf );
}

/* citation of the form (Knuth, 89)
 */
static
pgf_author_comma_year(bp)
	BibEnt *bp;
{
	char buf[256];
	char *auth;
	char *year;

	auth = get_auth(bp, 0 );
	if( year = get_yr(bp) )
		sprintf( buf, "    <PgfTag `%s, %s'>", auth, year);
	else
		sprintf( buf, "    <PgfTag `%s'>", auth);

	mif_writeln(O_BIB, buf );
}


/**************************************
 * routines to output reference portion
 * of bibliography paragraph.
 **************************************/

static char rbuf[128];

/* cacm ref form: 1.' '
 */
static
ref_cacm(bp)
	BibEnt *bp;
{
	sprintf( rbuf, "    <String `%d. '>", crrnt_pgf_num);
	mif_writeln(O_BIB, rbuf );
}

	
/* ieee ref form: 1.\t
 */
static
ref_ieee(bp)
	BibEnt *bp;
{
	sprintf( rbuf, "    <String `%d. '>", crrnt_pgf_num);
	mif_writeln(O_BIB, rbuf );
	mif_writeln(O_BIB, "    <Char Tab>" );
}

/* ieee ref form: [1]\t
 */
static
ref_ieeetrans(bp)
    BibEnt *bp;
{
    sprintf( rbuf, "    <String `[%d]'>", crrnt_pgf_num);
    mif_writeln(O_BIB, rbuf );
    mif_writeln(O_BIB, "    <Char Tab>" );
}

/* stdnumeric ref form: [1]\t
 */
static
ref_stdnumeric(bp)
	BibEnt *bp;
{
	sprintf( rbuf, "    <String `[%d]'>", crrnt_pgf_num);
	mif_writeln(O_BIB, rbuf );
	mif_writeln(O_BIB, "    <Char Tab>" );
}

/* stdalphabetic reference form [Knuth 90]\t 
 */
static 
ref_stdalphabetic(bp)
	BibEnt *bp;
{
	char *auth;
	char *year;

	auth = get_auth(bp, 0 );
	if( year = get_yr(bp) )
		sprintf( rbuf, "    <String `[%s %s]'>\n", auth, year);
	else
		sprintf( rbuf, "    <String `[%s]'>\n", auth);
	mif_write(O_BIB, rbuf );
	mif_writeln(O_BIB, "    <Char Tab>" );
}

/* stdidentifier reference form, not quite sure yet what this
 * is, assuming for now, its: KNU89\t.
 */
static
ref_stdidentifier(bp)
	BibEnt *bp;
{
	char *auth;
	char *year;

	auth = get_auth(bp, 1 );
	if( year = get_yr(bp) )
		sprintf( rbuf, "    <String `%s%s'>\n", auth, year);
	else
		sprintf( rbuf, "    <String `%s'>\n", auth);
	mif_write(O_BIB, rbuf );
	mif_writeln(O_BIB, "    <Char Tab>" );
}

 
/* extract from bibentry, a string which is the author.
 * if abbrev is true, return abreviated name, ie KNU, else
 * one full name, ie Knuth.
 */
static char *
get_auth( bp, abbrev )
	register BibEnt *bp;
	int	abbrev;	
{
	static char	buf[128];
	register BibField *bf = NULL;
	register char *sp, *dp;

	/* The pgftag will be the actual next which will be
	 * written as the reference in the bibliography doc.,
	 * but also as the citation in the Frame Doc.
	 */
	if( !(bf = find_bibfield( bp, bf_key)))
	    if( !(bf = find_bibfield( bp, bf_author)))
		if( !(bf = find_bibfield( bp, bf_fullauthor)))
		    if( !(bf = find_bibfield( bp, bf_title)))
			if( !(bf = find_bibfield( bp, bf_journal)))
			   if( !(bf = find_bibfield( bp, bf_publisher)))
			      if( !(bf = find_bibfield( bp, bf_editor)))
			         if( !(bf = find_bibfield( bp, bf_editors)))
			   	    if( !(bf = find_bibfield( bp, bf_institution)))
					bf = find_bibfield( bp, bf_organization);
	if( !bf )
	{
		err( WARN,"pgf_auth_yr(): No Fields in <%s> for PgfTag\n", 
				bp->be_xref ); 
		return("");
	}
	sp = bf->bf_val;
	dp = buf;
	
	if( abbrev )
	{
		*dp++ = islower( *sp ) ? toupper(*sp) : *sp;  sp++;
		*dp++ = islower( *sp ) ? toupper(*sp) : *sp;  sp++;
		*dp++ = islower( *sp ) ? toupper(*sp) : *sp;  
		*dp=0;
	}
	else
	{
		*dp++ = islower( *sp ) ? toupper(*sp) : *sp;  sp++;

		while ( *sp && isalpha(*sp))
		{
			*dp++ = isupper( *sp ) ? tolower(*sp) : *sp;  
			sp++;
		}
		
		*dp++ = ' ';
		*dp = 0;
	}
	return(buf);
}

static char *
get_yr(bp)
	register BibEnt *bp;
{
	static char buf[3];
	register char *dp=buf;
	register char *sp;
	BibField *bf;

	if(bf = find_bibfield( bp, bf_year))
	{
		sp = bf->bf_val+2;
		*dp++ = *sp++;
		*dp++ = *sp++;
		*dp=0;
		return( buf );
	}
	else
		return( NULL );
}


/* print reference according to current style, to bibliography.
 */
prt_tag( bep )
	BibEnt *bep;
{
	crrnt_bibstyle->bs_pgffunc(bep);
}


/* find a field to use as a sort key that's present in 
 * the BibEnt.  The sort_matrix[] is consulted as to the
 * ordering of sort keys to be used.
 */
static char *
find_sortkey( bp, sort_level )
	register BibEnt *bp;
	int sort_level;
{
	register BibField *bf = NULL;
	register i;

	for( i=sort_level; i<num_sortkeys; i++ )
		if( bf = find_bibfield( bp, sort_matrix[i] ))
			return(bf->bf_val);

	/* if we got here, we either ran out of keys supplied by
	 * the user, or no fields were in the bib entry at all.
	 * for the former case, consult a default matrix. For the
	 * latter, return NULL.
	 */
	 while( i < MAX_SORT_KEYS ) {
		if( bf = find_bibfield( bp, default_sort_matrix[i] ))
			return(bf->bf_val);
		i++;
	}

	return( NULL );
}

/* 
 * generate the bibliography document by executing the
 * 'exec-trees' associated w/ each entry found. 
 */
fmbibgen()
{
	register BibList *blp;
	register BibEnt *bp;

	mif_beginbibdoc();
	
	/* for citation order styles, output directly from
	 * the list of Bibents, since they are a linked list
	 * already in that order.
	 */
	if( crrnt_bibstyle->bs_sortfunc == sort_by_cite ) {
		for( bp=bibent_root; bp; bp = bp->be_r ) {
			 crrnt_pgf_num++;
             do_bibent( bp );
		}
	} else {
		/* alpha numeric sort */
		for( blp=sorted_bibs; blp; blp=blp->bl_next )
			if( blp->bl_bep )
			{
				crrnt_pgf_num++;
				do_bibent( blp->bl_bep );
			}
	}
			
	mif_endbibdoc();
}




char *
bib_templatefile()
{
	return( crrnt_bibstyle->bs_style );
}


/**********************************
 * routines for storing/retreiving
 * @String macros in bib files.
 **********************************/


store_bibdef( key, def )
	char	*key;
	char	*def;
{
	register BibDef *bdp;

	if( !key || !*key || !def || !*def )
		return;

	bdp = (BibDef *)getmem( sizeof( BibDef ) );
	bdp->bd_key = getmem( strlen( key ) + 1);
	bdp->bd_def = getmem( strlen( def ) + 1);
	bdp->bd_l = bdp->bd_r = NULL;
	strcpy( bdp->bd_key, key );
	strcpy( bdp->bd_def, def );
	insert_bibdef( &bibdef_root, bdp );
}	

static 
insert_bibdef( root, bdp )
	register BibDef **root;
	register BibDef *bdp;
{
	register cmp;

	if( !*root )
	{
		*root = bdp;
		return;
	}

	/* sort alphanumerically on bd_key */
	cmp = strcmp( bdp->bd_key, (*root)->bd_key );

	if( cmp == 0 )	/* already inserted */
		return;

	if( cmp<0 )
		insert_bibdef( &((*root)->bd_l), bdp );
	else
		insert_bibdef( &((*root)->bd_r), bdp );
}


char *
find_bibdef( key )
	register char *key;
{
	char *retrieve_bibdef();

	if( !key || !*key )
		return( NULL );

	return( retrieve_bibdef( bibdef_root, key ));
}

static char *
retrieve_bibdef( root, key )
	register BibDef *root;
	register char *key;
{
	register cmp;

	if( !root )
		return( NULL );

	cmp = strcmp( key, root->bd_key );
	if( cmp == 0 )
		return( root->bd_def );
	if( cmp < 0 )
		return( retrieve_bibdef( root->bd_l, key ));
	else
		return( retrieve_bibdef( root->bd_r, key ));
}	

		
print_valid_styles()
{
	register BibStyle *cp;	
	register n;

	printf( "\nCurrently Supported Bibliographic Styles:\n");
	for( n=0, cp=bibstyles; cp->bs_style; cp++ )
	{
		if( n==0 )
			printf( "\t" );
		printf( "%s  ", cp->bs_style );
		n++;
		if( n>5 )
		{
			printf("\n" );
			n=0;
		}
	}
	printf("\n");
}


#ifdef DEBUG
/*****************
 * Debugging routines. 
 *****************/

print_bibs()
{
	printf( "Bib tree\n----------------------------\n");
	print_bibtree( bibent_root );
	printf( "------------ End Bib Tree ----------\n");
}

static
print_bibtree( root )
	register BibEnt *root;
{
	if( !root )
		return;
	print_bibtree( root->be_l );
	print_bibent( root );
	print_bibtree( root->be_r );
}
	
static
print_bibent( bp )
	register BibEnt *bp;
{
	printf("---------- %s ----------\n", refname(bp->be_reftype) );
	printf("Lookup=<%s>\n", bp->be_xref );
	print_bibfields( bp->be_fields );
}

print_bibfields( root )
	register BibField *root;
{
	if( !root )
		return;
	print_bibfields( root->bf_l );
	printf( "%s = %s\n", fldname(root->bf_type), root->bf_val );	
	print_bibfields( root->bf_r );
}
	

static
do_bibtree( root )
	register BibEnt *root;
{
	if( !root )
		return;
	do_bibtree( root->be_l );
	do_bibent( root );
	do_bibtree( root->be_r );
}

#endif DEBUG

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.