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.