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.