xref: /csrg-svn/contrib/bib/src/bib.c (revision 65358)
113109Srrh #ifndef lint
2*65358Sbostic static char sccsid[] = "@(#)bib.c	2.12	01/03/94";
313109Srrh #endif not lint
415066Sgarrison /*
515066Sgarrison         Bib - bibliographic formatter
613109Srrh 
715066Sgarrison         Authored by: Tim Budd, University of Arizona, 1983.
815066Sgarrison                 lookup routines written by gary levin 2/82
915066Sgarrison 
1015066Sgarrison                 version 7/4/83
1115066Sgarrison 
1215066Sgarrison         Various modifications suggested by:
1315066Sgarrison                 David Cherveny - Duke University Medical Center
1415066Sgarrison                 Phil Garrison - UC Berkeley
1515066Sgarrison                 M. J. Hawley - Yale University
1615066Sgarrison 
1760507Sbostic 	       version 8/23/1988
1860507Sbostic 
1960507Sbostic 	 Adapted to use TiB style macro calls (i.e. |macro|)
2060507Sbostic 	       A. Dain Samples
2115066Sgarrison 
2260507Sbostic                                                         */
2315066Sgarrison 
2412909Sgarrison # include <stdio.h>
2512909Sgarrison # include <ctype.h>
2612909Sgarrison # include "bib.h"
2712909Sgarrison 
2812909Sgarrison # define HUNTSIZE 512                /* maximum size of hunt string         */
2912909Sgarrison # define MAXREFS  300                /* maximum number of references        */
3012909Sgarrison # define MAXATONCE 35                /* maximum references at one location  */
3112909Sgarrison 
3212909Sgarrison # define getch(c,fd) (c = getc(fd))
3312909Sgarrison # define echoc(c,ifd,ofd) (getch(c,ifd) == EOF ? c : putc(c,ofd))
3412909Sgarrison # define testc(c,d,ifd,ofd) (getch(c, ifd) == d ? putc(c, ofd) : 0)
3512909Sgarrison 
3612909Sgarrison /* global variables */
3712909Sgarrison    FILE *rfd;                   /* reference temporary file              */
3816245Srrh #ifndef INCORE
3912909Sgarrison    char reffile[] = TMPREFFILE ;/* temporary file (see bib.h)            */
4016245Srrh #endif not INCORE
4115902Srrh    struct refinfo refinfo[MAXREFS];	/* reference information */
4215902Srrh    struct refinfo *refssearch();
4315902Srrh    struct refinfo *refshash[HASHSIZE];
4412909Sgarrison    long int rend = 1;           /* last position in rfd (first char unused)*/
4515902Srrh    int numrefs = 0;            /* number of references generated so far */
4612909Sgarrison    FILE *tfd;                   /* output of pass 1 of file(s)           */
4730590Sgarrison    char bibtmpfile[] = TMPTEXTFILE ; /* output of pass 1                    */
4817247Srrh    char *common = COMFILE;       /* common word file                      */
4912909Sgarrison    int  findex = false;         /* can we read the file INDEX ?          */
5012909Sgarrison 
5160507Sbostic char *programName;
5260507Sbostic 
5312909Sgarrison /* global variables in bibargs */
5423484Sgarrison    extern int foot, doacite, sort, max_klen, personal;
5515066Sgarrison    extern int hyphen, ordcite, biblineno;
5615066Sgarrison    extern char sortstr[], pfile[], citetemplate[], bibfname[];
5760507Sbostic    extern int TibOption;
5812909Sgarrison 
5915902Srrh #include <signal.h>
6012909Sgarrison 
main(argc,argv)6112909Sgarrison main(argc, argv)
6212909Sgarrison    int argc;
6312909Sgarrison    char **argv;
6412909Sgarrison {  int rcomp();
65*65358Sbostic    void intr();
6612909Sgarrison 
6712909Sgarrison    /* the file INDEX in the current directory is the default index,
6812909Sgarrison       if it is present */
6912909Sgarrison 
7060507Sbostic    InitDirectory(BMACLIB,N_BMACLIB);
7160507Sbostic    InitDirectory(COMFILE,N_COMFILE);
7260507Sbostic    InitDirectory(DEFSTYLE,N_DEFSTYLE);
7317247Srrh 
7415902Srrh    signal(SIGINT, intr);
7512909Sgarrison    rfd = fopen( INDXFILE , "r");
7612909Sgarrison    if (rfd != NULL) {
7712909Sgarrison       findex = true;
7812909Sgarrison       fclose(rfd);
7912909Sgarrison       }
8012909Sgarrison 
8115902Srrh #ifndef INCORE
8212909Sgarrison    /* open temporaries, reffile will contain references collected in
8330590Sgarrison       pass 1, and bibtmpfile will contain text.
8412909Sgarrison    */
8512909Sgarrison    mktemp(reffile);
8612909Sgarrison    rfd = fopen(reffile,"w+");
8712909Sgarrison    if (rfd == NULL)
8815902Srrh       error("can't open temporary reference file, %s", reffile);
8915066Sgarrison    putc('x', rfd);      /* put garbage in first position (not used) */
9015902Srrh #endif not INCORE
9130590Sgarrison    mktemp(bibtmpfile);
9230590Sgarrison    tfd = fopen(bibtmpfile,"w");
9312909Sgarrison    if (tfd == NULL)
9430590Sgarrison       error("can't open temporary output file, %s", bibtmpfile);
9512909Sgarrison 
9612909Sgarrison     /*
9712909Sgarrison        pass1 - read files, looking for citations
9812909Sgarrison                arguments are read by doargs (bibargs.c)
9912909Sgarrison     */
10012909Sgarrison 
10160507Sbostic    if (doargs(argc, argv, DEFSTYLE ) == 0) { /* may not return */
10215066Sgarrison       strcpy(bibfname, "<stdin>");
10312909Sgarrison       rdtext(stdin);
10415066Sgarrison       }
10512909Sgarrison 
10612909Sgarrison    /*
10712909Sgarrison     sort references, make citations, add disambiguating characters
10812909Sgarrison    */
10912909Sgarrison 
11012909Sgarrison    if (sort)
11115902Srrh       qsort(refinfo, numrefs, sizeof(struct refinfo), rcomp);
11215902Srrh    makecites();
11312909Sgarrison    disambiguate();
11412909Sgarrison 
11512909Sgarrison    /*
11612909Sgarrison    reopen temporaries
11712909Sgarrison    */
11812909Sgarrison 
11912909Sgarrison    fclose(tfd);
12030590Sgarrison    tfd = fopen(bibtmpfile,"r");
12112909Sgarrison    if (tfd == NULL)
12230590Sgarrison       error("can't open temporary output file %s for reading", bibtmpfile);
12312909Sgarrison    /*
12412909Sgarrison    pass 2 - reread files, replacing references
12512909Sgarrison    */
12612909Sgarrison    pass2(tfd, stdout);
12715902Srrh    cleanup(0);
12815902Srrh }
12915902Srrh /* interrupt processing */
130*65358Sbostic void
intr()13115902Srrh intr()
13215902Srrh {
13315902Srrh    cleanup(1);
13415902Srrh }
13515902Srrh /* clean up and exit */
cleanup(val)13615902Srrh cleanup(val)
13715902Srrh {
13812909Sgarrison    fclose(tfd);
13915902Srrh #ifndef INCORE
14012909Sgarrison    fclose(rfd);
14115902Srrh    unlink(reffile);
14215902Srrh #endif INCORE
14315902Srrh #ifndef DEBUG
14430590Sgarrison    unlink(bibtmpfile);
14515902Srrh #endif DEBUG
14615902Srrh    exit(val);
14712909Sgarrison }
14812909Sgarrison 
14912909Sgarrison /* rdtext - read and process a text file, looking for [. commands */
rdtext(fd)15012909Sgarrison    rdtext(fd)
15112909Sgarrison    FILE *fd;
15212909Sgarrison {  char lastc, c, d;
15312909Sgarrison 
15415066Sgarrison    lastc = '\0';
15515066Sgarrison    biblineno = 1;
15612909Sgarrison    while (getch(c, fd) != EOF)
15712909Sgarrison       if (c == '[' || c == '{')
15812909Sgarrison          if (getch(d, fd) == '.') { /* found a reference */
15912909Sgarrison             if (c == '{') { if (lastc) putc(lastc, tfd);}
16012909Sgarrison             else
16115066Sgarrison                switch (lastc) {
16215066Sgarrison                   case '\0': break;
16315066Sgarrison                   case ' ': fputs("\\*([<", tfd); break;
16415066Sgarrison                   case '.': case ',': case '?': case ':':
16515066Sgarrison                   case ';': case '!': case '"': case '\'':
16615066Sgarrison                             fputs("\\*([", tfd);  /* fall through */
16715066Sgarrison                   default:  putc(lastc, tfd); break;
16815066Sgarrison                   }
16912909Sgarrison             rdcite(fd, c);
17012909Sgarrison             if (c == '[')
17115066Sgarrison                switch (lastc) {
17215066Sgarrison                   case '\0': break;
17315066Sgarrison                   case ' ': fputs("\\*(>]", tfd); break;
17415066Sgarrison                   case '.': case ',': case '?': case ':':
17515066Sgarrison                   case ';': case '!': case '"': case '\'':
17615066Sgarrison                             fprintf(tfd,"\\*(%c]", lastc); break;
17715066Sgarrison                   }
17815066Sgarrison             lastc = '\0';
17912909Sgarrison             }
18012909Sgarrison          else {
18115066Sgarrison             if (lastc != '\0') putc(lastc, tfd);
18212909Sgarrison             ungetc(d, fd);
18312909Sgarrison             lastc = c;
18412909Sgarrison             }
18512909Sgarrison       else {
18615066Sgarrison          if (lastc != '\0') putc(lastc, tfd);
18712909Sgarrison          lastc = c;
18815066Sgarrison          if (c == '\n') biblineno++;
18912909Sgarrison          }
19015066Sgarrison    if (lastc != '\0') putc(lastc, tfd);
19112909Sgarrison }
19212909Sgarrison 
19312909Sgarrison /* rdcite - read citation information inside a [. command */
rdcite(fd,ch)19412909Sgarrison    rdcite(fd, ch)
19512909Sgarrison    FILE *fd;
19612909Sgarrison    char ch;
19716245Srrh {  int getref();
19812909Sgarrison    char huntstr[HUNTSIZE], c, info[HUNTSIZE];
19912909Sgarrison 
20012909Sgarrison    if (ch == '[')
20117245Srrh       if (doacite) fputs("\\*([[", tfd);
20212909Sgarrison    else
20317245Srrh       if (doacite) fputs("\\*([{", tfd);
20412909Sgarrison    huntstr[0] = info[0] = 0;
20512909Sgarrison    while (getch(c, fd) != EOF)
20612909Sgarrison       switch (c) {
20712909Sgarrison          case ',':
20860507Sbostic 	    citemark(info, huntstr, "");
20912909Sgarrison             huntstr[0] = info[0] = 0;
21012909Sgarrison             break;
21112909Sgarrison          case '.':
21212909Sgarrison             while (getch(c, fd) == '.') ;
21312909Sgarrison             if (c == ']') {
21415902Srrh 	       citemark(info, huntstr, "\\*(]]");
21512909Sgarrison                return;
21612909Sgarrison                }
21712909Sgarrison             else if (c == '}') {
21815902Srrh 	       citemark(info, huntstr, "\\*(}]");
21912909Sgarrison                return;
22012909Sgarrison                }
22112909Sgarrison             else
22212909Sgarrison                addc(huntstr, c);
22312909Sgarrison             break;
22412909Sgarrison 
22512909Sgarrison          case '{':
22612909Sgarrison             while (getch(c, fd) != '}')
22712909Sgarrison                if (c == EOF) {
22815902Srrh                   error("ill formed reference");
22912909Sgarrison                   }
23012909Sgarrison                 else
23112909Sgarrison                   addc(info, c);
23212909Sgarrison             break;
23312909Sgarrison 
23412909Sgarrison          case '\n':
23515066Sgarrison             biblineno++;
23612909Sgarrison          case '\t':
23712909Sgarrison             c = ' ';   /* fall through */
23812909Sgarrison 
23912909Sgarrison          default:
24012909Sgarrison             addc(huntstr,c);
24112909Sgarrison          }
24212909Sgarrison    error("end of file reading citation");
24312909Sgarrison }
24416245Srrh char	ncitetemplate[64];
24516245Srrh int	changecite;
citemark(info,huntstr,tail)24615902Srrh citemark(info, huntstr, tail)
24715902Srrh 	char *info, *huntstr, *tail;
24815902Srrh {
24915902Srrh 	char c = CITEMARK;
25015902Srrh         long int  n;
25116245Srrh 	/*
25216245Srrh 	 *	getref sets ncitetemplate as a side effect
25316245Srrh 	 */
25415902Srrh 	n = getref(huntstr);
25516245Srrh 	if (ncitetemplate[0]){
25616245Srrh 		fprintf(tfd, "%c%s%c", FMTSTART, ncitetemplate, FMTEND);
25716245Srrh 		ncitetemplate[0] = 0;
25816245Srrh 	}
25960507Sbostic 	fprintf(tfd, "%c%d%c%s%c%s", c ,n, c, info, CITEEND, doacite?tail:"");
26024014Srrh 
26115902Srrh }
26212909Sgarrison 
26312909Sgarrison /* addc - add a character to hunt string */
addc(huntstr,c)26460507Sbostic addc(huntstr, c)
26512909Sgarrison    char huntstr[HUNTSIZE], c;
26612909Sgarrison {  int  i;
26712909Sgarrison 
26812909Sgarrison    i = strlen(huntstr);
26912909Sgarrison    if (i > HUNTSIZE)
27015902Srrh       error("citation too long, max of %d", HUNTSIZE);
27112909Sgarrison    huntstr[i] = c;
27212909Sgarrison    huntstr[i+1] = 0;
27312909Sgarrison }
27460507Sbostic 
27515902Srrh /* getref - if an item was already referenced, return its reference index
27615902Srrh                 otherwise create a new entry */
getref(huntstr)27760507Sbostic int getref(huntstr)
27812909Sgarrison    char huntstr[HUNTSIZE];
27915902Srrh {  char rf[REFSIZE], *r, *hunt();
28015902Srrh    int	match(), getwrd();
28115891Srrh    char	*realhstr;
28215902Srrh    int hash;
28315902Srrh    struct refinfo *rp;
28415902Srrh    int	lg;
28512909Sgarrison 
28615891Srrh    realhstr = huntstr;
28715891Srrh    if (strncmp(huntstr, "$C$", 3) == 0){
28815891Srrh 	char *from, *to;
28916245Srrh 	changecite++;
29016245Srrh 	for(from = huntstr + 3, to = ncitetemplate; *from; from++, to++){
29115891Srrh 		switch(*from){
29215891Srrh 		case '\0':
29315891Srrh 		case ' ':
29415891Srrh 		case '\n':
29515891Srrh 		case '\t':	goto outcopy;
29615891Srrh 		default:	*to = *from;
29715891Srrh 		}
29815891Srrh 	}
29915891Srrh    outcopy: ;
30015891Srrh 	*to = 0;
30115891Srrh 	*from = 0;
30215891Srrh 	realhstr = from + 1;
30315891Srrh    }
30415891Srrh    r = hunt(realhstr);
30512909Sgarrison    if (r != NULL) {
30615902Srrh       /* expand defined string */
30712909Sgarrison       strcpy(rf, r);
30812909Sgarrison       free(r);
30912909Sgarrison       expand(rf);
31012909Sgarrison       /* see if reference has already been cited */
31115902Srrh       if (foot == false && (rp = refssearch(rf))){
31215902Srrh 		return(rp - refinfo);
31315902Srrh       }
31412909Sgarrison       /* didn't match any existing reference, create new one */
31515902Srrh       if (numrefs >= MAXREFS)
31615902Srrh 	error("too many references, max of %d", MAXREFS);
31715902Srrh       hash = strhash(rf);
31815902Srrh       lg = strlen(rf) + 1;
31915902Srrh       refinfo[numrefs].ri_pos = rend;
32015902Srrh       refinfo[numrefs].ri_length = lg;
32115902Srrh       refinfo[numrefs].ri_hp = refshash[hash];
32215902Srrh       refinfo[numrefs].ri_n = numrefs;
32315902Srrh       refshash[hash] = &refinfo[numrefs];
32415902Srrh       wrref(&refinfo[numrefs], rf);
32515902Srrh       return(numrefs++);
32612909Sgarrison       }
32712909Sgarrison    else {
32815891Srrh       bibwarning("no reference matching %s\n", realhstr);
32915902Srrh       return(-1);
33012909Sgarrison       }
33112909Sgarrison }
33260507Sbostic 
refssearch(rf)33315902Srrh struct refinfo *refssearch(rf)
33415902Srrh    char *rf;
33515902Srrh {
33615902Srrh    char ref[REFSIZE];
33715902Srrh    reg	int i;
33815902Srrh    int	lg;
33915902Srrh    reg	struct refinfo *rp;
34015902Srrh    lg = strlen(rf) + 1;
34115902Srrh    for (rp = refshash[strhash(rf)]; rp; rp = rp->ri_hp){
34215902Srrh 	     if (rp->ri_length == lg){
34315902Srrh 		     rdref(rp, ref);
34415902Srrh 		     if (strcmp(ref, rf) == 0)
34515902Srrh 			return(rp);
34615902Srrh 	     }
34715902Srrh    }
34815902Srrh    return(0);
34915902Srrh }
35012909Sgarrison /* hunt - hunt for reference from either personal or system index */
35160507Sbostic /* the old versions would stop at the first index file where a citation
35260507Sbostic  * matched.  This is NOT what is desired.  I have changed it so that it still
35360507Sbostic  * returns the first citation found, but also reports the existence of
35460507Sbostic  * duplicate entries in an INDEX file as well as across INDEX files.
35560507Sbostic  * Also, we do NOT assume that the SYSINDEX has been Tib'd.  Therefore,
35660507Sbostic  * if tib style expansion is in effect, the SYSINDEX is not searched.
35760507Sbostic  * (Besides which, on Sun systems at least, the SYSINDEX files are
35860507Sbostic  * created by refer, not bib, so we can't use them very effectively
35960507Sbostic  * anyway.  Besides which again, everything in SYSINDEX is in our
36060507Sbostic  * local files anyway.)
36160507Sbostic  *                   - ads 8/88
36260507Sbostic  */
hunt(huntstr)36360507Sbostic char *hunt(huntstr)
36412909Sgarrison    char huntstr[];
36560507Sbostic {  char *found, *fhunt(), *r, *tp, *sp, fname[120];
36612909Sgarrison 
36760507Sbostic    found = NULL;
36812909Sgarrison    if (personal) {
36960507Sbostic       for (tp = fname, sp = pfile; ; sp++)
37060507Sbostic          if (*sp == ',' || *sp == '\0') {
37160507Sbostic             *tp = '\0';
37260507Sbostic             if ((r = fhunt(fname, huntstr)) != NULL) {
37360507Sbostic 		if (found != NULL) {
37460507Sbostic 		    /* we need an option to suppress this message -ads 5/89 */
37560507Sbostic 		    bibwarning("multiple INDEX files match citation %s\n",
37660507Sbostic 							huntstr);
37760507Sbostic 		    return (found);
37860507Sbostic 		    }
37960507Sbostic 		found = r;
38060507Sbostic 		}
38160507Sbostic             if (*sp == '\0')
38212909Sgarrison                break;
38360507Sbostic             tp = fname;
38412909Sgarrison             }
38560507Sbostic          else *tp++ = *sp;
38660507Sbostic       if (found != NULL) return (found);
38712909Sgarrison       }
38812909Sgarrison    else if (findex) {
38960507Sbostic       if ((r = fhunt(INDXFILE , huntstr)) != NULL)
39012909Sgarrison          return(r);
39112909Sgarrison       }
39260507Sbostic    if (!TibOption) {
39360507Sbostic       if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
39460507Sbostic 	 return(r);
39560507Sbostic       }
39612909Sgarrison    return(NULL);
39712909Sgarrison }
39812909Sgarrison 
39912909Sgarrison /* fhunt - hunt from a specific file */
fhunt(file,huntstr)40012909Sgarrison    char *fhunt(file, huntstr)
40112909Sgarrison    char file[], huntstr[];
40212909Sgarrison {  char *p, *r, *locate();
40312909Sgarrison 
40423484Sgarrison    r = locate(huntstr, file, max_klen, common);
40512909Sgarrison 
40612909Sgarrison    if (r == NULL)
40712909Sgarrison       return(NULL);  /* error */
40812909Sgarrison    if (*r == 0)
40912909Sgarrison       return(NULL);  /* no match */
41012909Sgarrison 
41112909Sgarrison    for (p = r; *p; p++)
41212909Sgarrison       if (*p == '\n')
41312909Sgarrison          if (*(p+1) == '\n') { /* end */
41412909Sgarrison             if (*(p+2) != 0)
41515066Sgarrison                bibwarning("multiple references match %s\n",huntstr);
41612909Sgarrison             *(p+1) = 0;
41712909Sgarrison             break;
41812909Sgarrison             }
41912909Sgarrison          else if (*(p+1) != '%' && *(p+1) != '.') /* unnecessary newline */
42012909Sgarrison             *p = ' ';
42112909Sgarrison    return(r);
42212909Sgarrison }
42315902Srrh struct cite{
42415902Srrh 	int	num;
42515902Srrh 	char	*info;
42615902Srrh };
42715902Srrh citesort(p1, p2)
42815902Srrh 	struct cite *p1, *p2;
42915902Srrh {
43015902Srrh 	return(p1->num - p2->num);
43115902Srrh }
43212909Sgarrison 
43312909Sgarrison /* putrefs - gather contiguous references together, sort them if called
43412909Sgarrison    for, hyphenate if necessary, and dump them out */
putrefs(ifd,ofd,footrefs,fn)43512909Sgarrison int putrefs(ifd, ofd, footrefs, fn)
43612909Sgarrison FILE *ifd, *ofd;
43712909Sgarrison int  fn, footrefs[];
43815902Srrh {
43915902Srrh 	struct cite cites[MAXATONCE];
44015902Srrh 	char	infoword[HUNTSIZE];    /* information line */
44115902Srrh 	reg	int i;
44215902Srrh 	reg	char *p;
44315902Srrh 	reg	int  ncites, n, j;         /* number of citations being dumped */
44415902Srrh 	char	c, *walloc();
44515902Srrh 	int neg;
44615902Srrh 	/*
44715902Srrh 	 * first gather contiguous references together,
44815902Srrh 	 * and order them if required
44915902Srrh 	 */
45012909Sgarrison 
45115902Srrh 	ncites = 0;
45215902Srrh 	do {
45323484Sgarrison 		neg = 1;
45415902Srrh 		n = 0;
45515902Srrh 		do{
45615902Srrh 			getch(c, ifd);
45715902Srrh 			if (isdigit(c))
45815902Srrh 				n = 10 * n + (c - '0');
45915902Srrh 			else if (c == '-')
46015902Srrh 				neg *= -1;
46115902Srrh 			else if (c == CITEMARK)
46215902Srrh 				break;
46315902Srrh 			else
46415902Srrh 				error("bad cite char 0%03o in pass two",c);
46515902Srrh 		} while(1);
46615902Srrh 		if (neg < 0) {     /* reference not found */
46715902Srrh 			cites[ncites].num = -1;
46815902Srrh 			cites[ncites].info = 0;
46915902Srrh 			ncites++;
47015902Srrh 		} else {
47115902Srrh 			/*
47215902Srrh 			 * Find reference n in the references
47315902Srrh 			 */
47415902Srrh 			int i;
47515902Srrh 			for (i = 0; i < numrefs; i++){
47615902Srrh 				if (refinfo[i].ri_n == n){
47715902Srrh 					cites[ncites].num = i;
47815902Srrh 					cites[ncites].info = 0;
47915902Srrh 					ncites++;
48015902Srrh 					break;
48115902Srrh 				}
48215902Srrh 			}
48315902Srrh 			if (i == numrefs)
48415902Srrh 				error("citation	%d not found in pass 2", n);
48515902Srrh 		}
48615902Srrh 		if (getch(c, ifd) != CITEEND) {
48715902Srrh 			for (p = infoword; c != CITEEND ; ) {
48815902Srrh 				*p++ = c;
48915902Srrh 				getch(c, ifd);
49015902Srrh 			}
49115902Srrh 			*p = 0;
49215902Srrh 			cites[ncites-1].info = walloc(infoword);
49315902Srrh 		}
49415902Srrh 		getch(c, ifd);
49515902Srrh 	} while (c == CITEMARK);
49615902Srrh 	ungetc(c, ifd);
49715902Srrh 	if (ordcite)
49815902Srrh 		qsort(cites, ncites, sizeof(struct cite), citesort);
49912909Sgarrison 
50015902Srrh 	/* now dump out values */
50115902Srrh 	for (i = 0; i < ncites; i++) {
50216245Srrh 		if (cites[i].num >= 0) {
50316245Srrh 			if (changecite){
50416245Srrh 				char tempcite[128];
50516245Srrh 				char ref[REFSIZE];
50616245Srrh 				struct refinfo *p;
50716245Srrh 				/*
50816245Srrh 				 * rebuild the citation string,
50916245Srrh 				 * using the current template in effect
51016245Srrh 				 */
51116245Srrh 				p = &refinfo[cites[i].num];
51216245Srrh 				rdref(p, ref);
51316245Srrh 				bldcite(tempcite, cites[i].num, ref);
51416245Srrh 				strcat(tempcite, p->ri_disambig);
51517245Srrh 				if (doacite) fputs(tempcite, ofd);
51616245Srrh 			} else {
51717245Srrh 				if (doacite) fputs(refinfo[cites[i].num].ri_cite, ofd);
51816245Srrh 			}
51917245Srrh 			if (!doacite) fputs("\\&", ofd);
52016245Srrh 		}
52115902Srrh 		if (cites[i].info) {
52217245Srrh 			if (doacite) fputs(cites[i].info, ofd);
52317245Srrh 			if (!doacite) fputs("\\&", ofd);
52415902Srrh 			free(cites[i].info);
52515902Srrh 		}
52615902Srrh 		if (hyphen) {
52715902Srrh 			for (j = 1;
52815902Srrh 			     j + i <= ncites && cites[i+j].num == cites[i].num + j;
52915902Srrh 			     j++)/*VOID*/;
53015902Srrh 			if (j + i > ncites)
53115902Srrh 				j = ncites;
53215902Srrh 			else
53315902Srrh 				j = j + i - 1;
53415902Srrh 		} else {
53515902Srrh 			j = i;
53615902Srrh 		}
53715902Srrh 		if (j > i + 1) {
53815902Srrh 			fputs("\\*(]-", ofd);
53915902Srrh 			i = j - 1;
54015902Srrh 		} else if (i != ncites - 1) {
54115902Srrh 			fputs("\\*(],", ofd);
54215902Srrh 		}
54315902Srrh 		if (foot) {
54415902Srrh 			fn++;
54515902Srrh 			footrefs[fn] = cites[i].num;
54615902Srrh 		}
54715902Srrh 	}
54815902Srrh 	return(fn);
54912909Sgarrison }
55012909Sgarrison 
55112909Sgarrison /* pass2 - read pass 1 files entering citation */
pass2(ifd,ofd)55212909Sgarrison    pass2(ifd, ofd)
55312909Sgarrison    FILE *ifd, *ofd;
55412909Sgarrison {
55512909Sgarrison    char c;
55612909Sgarrison    int  i, fn, footrefs[25], dumped;
55712909Sgarrison 
55812909Sgarrison    fn = -1;
55912909Sgarrison    dumped = foot;
56012909Sgarrison    while (getch(c, ifd) != EOF) {
56112909Sgarrison       while (c == '\n') {
56212909Sgarrison          putc(c, ofd);
56312909Sgarrison          if (foot && fn >= 0) {
56412909Sgarrison             for (i = 0; i <= fn; i++)
56512909Sgarrison                 dumpref(footrefs[i], ofd);
56612909Sgarrison             fn = -1;
56712909Sgarrison             }
56812909Sgarrison          if (testc(c, '.', ifd, ofd))
56912909Sgarrison             if (testc(c, '[', ifd, ofd))
57012909Sgarrison                if (testc(c, ']', ifd, ofd)) {
57112909Sgarrison                   while (echoc(c, ifd, ofd) != '\n')
57212909Sgarrison                      ;
57312909Sgarrison                   dumped = true;
57415902Srrh                   for (i = 0; i < numrefs; i++){
57512909Sgarrison                      dumpref(i, ofd);
57615902Srrh 		  }
57712909Sgarrison                   getch(c, ifd);
57812909Sgarrison                   }
57912909Sgarrison          }
58016245Srrh       if (c == FMTSTART)
58116245Srrh 	 changefmt(ifd);
58216245Srrh       else if (c == CITEMARK)
58312909Sgarrison          fn = putrefs(ifd, ofd, footrefs, fn);
58412909Sgarrison       else if (c != EOF)
58512909Sgarrison          putc(c, ofd);
58612909Sgarrison       }
58712909Sgarrison    if (dumped == false)
58815066Sgarrison       bibwarning("Warning: references never dumped\n","");
58912909Sgarrison }
59016245Srrh /*
59116245Srrh  *	change citation format
59216245Srrh  */
changefmt(ifd)59316245Srrh changefmt(ifd)
59416245Srrh 	FILE	*ifd;
59516245Srrh {
59616245Srrh 	char	c;
59716245Srrh 	char	*to;
59816245Srrh 	to = ncitetemplate;
59916245Srrh 	while (getch(c, ifd) != FMTEND)
60016245Srrh 		*to++ = c;
60116245Srrh 	*to = 0;
60216245Srrh 	strcpy(citetemplate, ncitetemplate);
60316245Srrh }
604