xref: /original-bsd/contrib/bib/src/bib.c (revision bd54d768)
11f85f6edSrrh #ifndef lint
2*bd54d768Sbostic static char sccsid[] = "@(#)bib.c	2.12	01/03/94";
31f85f6edSrrh #endif not lint
4b8a08e38Sgarrison /*
5b85ca3f0Sgarrison         Bib - bibliographic formatter
6b85ca3f0Sgarrison 
7b85ca3f0Sgarrison         Authored by: Tim Budd, University of Arizona, 1983.
8b85ca3f0Sgarrison                 lookup routines written by gary levin 2/82
9b85ca3f0Sgarrison 
10b85ca3f0Sgarrison                 version 7/4/83
11b85ca3f0Sgarrison 
12b85ca3f0Sgarrison         Various modifications suggested by:
13b85ca3f0Sgarrison                 David Cherveny - Duke University Medical Center
14b85ca3f0Sgarrison                 Phil Garrison - UC Berkeley
15b85ca3f0Sgarrison                 M. J. Hawley - Yale University
16b85ca3f0Sgarrison 
1799c1622cSbostic 	       version 8/23/1988
18b85ca3f0Sgarrison 
1999c1622cSbostic 	 Adapted to use TiB style macro calls (i.e. |macro|)
2099c1622cSbostic 	       A. Dain Samples
21b85ca3f0Sgarrison 
22b8a08e38Sgarrison                                                         */
2399c1622cSbostic 
24b8a08e38Sgarrison # include <stdio.h>
25b8a08e38Sgarrison # include <ctype.h>
26b8a08e38Sgarrison # include "bib.h"
27b8a08e38Sgarrison 
28b8a08e38Sgarrison # define HUNTSIZE 512                /* maximum size of hunt string         */
29b8a08e38Sgarrison # define MAXREFS  300                /* maximum number of references        */
30b8a08e38Sgarrison # define MAXATONCE 35                /* maximum references at one location  */
31b8a08e38Sgarrison 
32b8a08e38Sgarrison # define getch(c,fd) (c = getc(fd))
33b8a08e38Sgarrison # define echoc(c,ifd,ofd) (getch(c,ifd) == EOF ? c : putc(c,ofd))
34b8a08e38Sgarrison # define testc(c,d,ifd,ofd) (getch(c, ifd) == d ? putc(c, ofd) : 0)
35b8a08e38Sgarrison 
36b8a08e38Sgarrison /* global variables */
37b8a08e38Sgarrison    FILE *rfd;                   /* reference temporary file              */
384664557dSrrh #ifndef INCORE
39b8a08e38Sgarrison    char reffile[] = TMPREFFILE ;/* temporary file (see bib.h)            */
404664557dSrrh #endif not INCORE
4196c4ecf2Srrh    struct refinfo refinfo[MAXREFS];	/* reference information */
4296c4ecf2Srrh    struct refinfo *refssearch();
4396c4ecf2Srrh    struct refinfo *refshash[HASHSIZE];
44b8a08e38Sgarrison    long int rend = 1;           /* last position in rfd (first char unused)*/
4596c4ecf2Srrh    int numrefs = 0;            /* number of references generated so far */
46b8a08e38Sgarrison    FILE *tfd;                   /* output of pass 1 of file(s)           */
475d5714a0Sgarrison    char bibtmpfile[] = TMPTEXTFILE ; /* output of pass 1                    */
484da1f02dSrrh    char *common = COMFILE;       /* common word file                      */
49b8a08e38Sgarrison    int  findex = false;         /* can we read the file INDEX ?          */
50b8a08e38Sgarrison 
5199c1622cSbostic char *programName;
5299c1622cSbostic 
53b8a08e38Sgarrison /* global variables in bibargs */
54917c273dSgarrison    extern int foot, doacite, sort, max_klen, personal;
55b85ca3f0Sgarrison    extern int hyphen, ordcite, biblineno;
56b85ca3f0Sgarrison    extern char sortstr[], pfile[], citetemplate[], bibfname[];
5799c1622cSbostic    extern int TibOption;
58b8a08e38Sgarrison 
5996c4ecf2Srrh #include <signal.h>
60b8a08e38Sgarrison 
main(argc,argv)61b8a08e38Sgarrison main(argc, argv)
62b8a08e38Sgarrison    int argc;
63b8a08e38Sgarrison    char **argv;
64b8a08e38Sgarrison {  int rcomp();
65*bd54d768Sbostic    void intr();
66b8a08e38Sgarrison 
67b8a08e38Sgarrison    /* the file INDEX in the current directory is the default index,
68b8a08e38Sgarrison       if it is present */
69b8a08e38Sgarrison 
7099c1622cSbostic    InitDirectory(BMACLIB,N_BMACLIB);
7199c1622cSbostic    InitDirectory(COMFILE,N_COMFILE);
7299c1622cSbostic    InitDirectory(DEFSTYLE,N_DEFSTYLE);
734da1f02dSrrh 
7496c4ecf2Srrh    signal(SIGINT, intr);
75b8a08e38Sgarrison    rfd = fopen( INDXFILE , "r");
76b8a08e38Sgarrison    if (rfd != NULL) {
77b8a08e38Sgarrison       findex = true;
78b8a08e38Sgarrison       fclose(rfd);
79b8a08e38Sgarrison       }
80b8a08e38Sgarrison 
8196c4ecf2Srrh #ifndef INCORE
82b8a08e38Sgarrison    /* open temporaries, reffile will contain references collected in
835d5714a0Sgarrison       pass 1, and bibtmpfile will contain text.
84b8a08e38Sgarrison    */
85b8a08e38Sgarrison    mktemp(reffile);
86b8a08e38Sgarrison    rfd = fopen(reffile,"w+");
87b8a08e38Sgarrison    if (rfd == NULL)
8896c4ecf2Srrh       error("can't open temporary reference file, %s", reffile);
89b85ca3f0Sgarrison    putc('x', rfd);      /* put garbage in first position (not used) */
9096c4ecf2Srrh #endif not INCORE
915d5714a0Sgarrison    mktemp(bibtmpfile);
925d5714a0Sgarrison    tfd = fopen(bibtmpfile,"w");
93b8a08e38Sgarrison    if (tfd == NULL)
945d5714a0Sgarrison       error("can't open temporary output file, %s", bibtmpfile);
95b8a08e38Sgarrison 
96b8a08e38Sgarrison     /*
97b8a08e38Sgarrison        pass1 - read files, looking for citations
98b8a08e38Sgarrison                arguments are read by doargs (bibargs.c)
99b8a08e38Sgarrison     */
100b8a08e38Sgarrison 
10199c1622cSbostic    if (doargs(argc, argv, DEFSTYLE ) == 0) { /* may not return */
102b85ca3f0Sgarrison       strcpy(bibfname, "<stdin>");
103b8a08e38Sgarrison       rdtext(stdin);
104927ed57bSrrh       }
105b8a08e38Sgarrison 
106b8a08e38Sgarrison    /*
107b8a08e38Sgarrison     sort references, make citations, add disambiguating characters
108b8a08e38Sgarrison    */
109b8a08e38Sgarrison 
110b8a08e38Sgarrison    if (sort)
11196c4ecf2Srrh       qsort(refinfo, numrefs, sizeof(struct refinfo), rcomp);
11296c4ecf2Srrh    makecites();
113b8a08e38Sgarrison    disambiguate();
114b8a08e38Sgarrison 
115b8a08e38Sgarrison    /*
116b8a08e38Sgarrison    reopen temporaries
117b8a08e38Sgarrison    */
118b8a08e38Sgarrison 
119b8a08e38Sgarrison    fclose(tfd);
1205d5714a0Sgarrison    tfd = fopen(bibtmpfile,"r");
121b8a08e38Sgarrison    if (tfd == NULL)
1225d5714a0Sgarrison       error("can't open temporary output file %s for reading", bibtmpfile);
123b8a08e38Sgarrison    /*
124b8a08e38Sgarrison    pass 2 - reread files, replacing references
125b8a08e38Sgarrison    */
126b8a08e38Sgarrison    pass2(tfd, stdout);
12796c4ecf2Srrh    cleanup(0);
12896c4ecf2Srrh }
12996c4ecf2Srrh /* interrupt processing */
130*bd54d768Sbostic void
intr()13196c4ecf2Srrh intr()
13296c4ecf2Srrh {
13396c4ecf2Srrh    cleanup(1);
13496c4ecf2Srrh }
13596c4ecf2Srrh /* clean up and exit */
cleanup(val)13696c4ecf2Srrh cleanup(val)
13796c4ecf2Srrh {
138b8a08e38Sgarrison    fclose(tfd);
13996c4ecf2Srrh #ifndef INCORE
140b8a08e38Sgarrison    fclose(rfd);
141b8a08e38Sgarrison    unlink(reffile);
14296c4ecf2Srrh #endif INCORE
14396c4ecf2Srrh #ifndef DEBUG
1445d5714a0Sgarrison    unlink(bibtmpfile);
14596c4ecf2Srrh #endif DEBUG
14696c4ecf2Srrh    exit(val);
147b8a08e38Sgarrison }
148b8a08e38Sgarrison 
149b8a08e38Sgarrison /* rdtext - read and process a text file, looking for [. commands */
rdtext(fd)150b8a08e38Sgarrison    rdtext(fd)
151b8a08e38Sgarrison    FILE *fd;
152b8a08e38Sgarrison {  char lastc, c, d;
153b8a08e38Sgarrison 
154b85ca3f0Sgarrison    lastc = '\0';
155b85ca3f0Sgarrison    biblineno = 1;
156b8a08e38Sgarrison    while (getch(c, fd) != EOF)
157b8a08e38Sgarrison       if (c == '[' || c == '{')
158b8a08e38Sgarrison          if (getch(d, fd) == '.') { /* found a reference */
159b8a08e38Sgarrison             if (c == '{') { if (lastc) putc(lastc, tfd);}
160b8a08e38Sgarrison             else
161373ab38fSgarrison                switch (lastc) {
162b85ca3f0Sgarrison                   case '\0': break;
163b85ca3f0Sgarrison                   case ' ': fputs("\\*([<", tfd); break;
164b85ca3f0Sgarrison                   case '.': case ',': case '?': case ':':
165b85ca3f0Sgarrison                   case ';': case '!': case '"': case '\'':
166b85ca3f0Sgarrison                             fputs("\\*([", tfd);  /* fall through */
167b85ca3f0Sgarrison                   default:  putc(lastc, tfd); break;
168373ab38fSgarrison                   }
169b8a08e38Sgarrison             rdcite(fd, c);
170b8a08e38Sgarrison             if (c == '[')
171373ab38fSgarrison                switch (lastc) {
172b85ca3f0Sgarrison                   case '\0': break;
173b85ca3f0Sgarrison                   case ' ': fputs("\\*(>]", tfd); break;
174b85ca3f0Sgarrison                   case '.': case ',': case '?': case ':':
175b85ca3f0Sgarrison                   case ';': case '!': case '"': case '\'':
176b85ca3f0Sgarrison                             fprintf(tfd,"\\*(%c]", lastc); break;
177373ab38fSgarrison                   }
178b85ca3f0Sgarrison             lastc = '\0';
179b8a08e38Sgarrison             }
180b8a08e38Sgarrison          else {
181b85ca3f0Sgarrison             if (lastc != '\0') putc(lastc, tfd);
182b8a08e38Sgarrison             ungetc(d, fd);
183b8a08e38Sgarrison             lastc = c;
184b8a08e38Sgarrison             }
185b8a08e38Sgarrison       else {
186b85ca3f0Sgarrison          if (lastc != '\0') putc(lastc, tfd);
187b8a08e38Sgarrison          lastc = c;
188b85ca3f0Sgarrison          if (c == '\n') biblineno++;
189b8a08e38Sgarrison          }
190b85ca3f0Sgarrison    if (lastc != '\0') putc(lastc, tfd);
191b8a08e38Sgarrison }
192b8a08e38Sgarrison 
193b8a08e38Sgarrison /* rdcite - read citation information inside a [. command */
rdcite(fd,ch)194b8a08e38Sgarrison    rdcite(fd, ch)
195b8a08e38Sgarrison    FILE *fd;
196b8a08e38Sgarrison    char ch;
1974664557dSrrh {  int getref();
198b8a08e38Sgarrison    char huntstr[HUNTSIZE], c, info[HUNTSIZE];
199b8a08e38Sgarrison 
200b8a08e38Sgarrison    if (ch == '[')
20100246a29Srrh       if (doacite) fputs("\\*([[", tfd);
202b8a08e38Sgarrison    else
20300246a29Srrh       if (doacite) fputs("\\*([{", tfd);
204b8a08e38Sgarrison    huntstr[0] = info[0] = 0;
205b8a08e38Sgarrison    while (getch(c, fd) != EOF)
206b8a08e38Sgarrison       switch (c) {
207b8a08e38Sgarrison          case ',':
20899c1622cSbostic 	    citemark(info, huntstr, "");
209b8a08e38Sgarrison             huntstr[0] = info[0] = 0;
210b8a08e38Sgarrison             break;
211b8a08e38Sgarrison          case '.':
212b8a08e38Sgarrison             while (getch(c, fd) == '.') ;
213b8a08e38Sgarrison             if (c == ']') {
21496c4ecf2Srrh 	       citemark(info, huntstr, "\\*(]]");
215b8a08e38Sgarrison                return;
216b8a08e38Sgarrison                }
217b8a08e38Sgarrison             else if (c == '}') {
21896c4ecf2Srrh 	       citemark(info, huntstr, "\\*(}]");
219b8a08e38Sgarrison                return;
220b8a08e38Sgarrison                }
221b8a08e38Sgarrison             else
222b8a08e38Sgarrison                addc(huntstr, c);
223b8a08e38Sgarrison             break;
224b8a08e38Sgarrison 
225b8a08e38Sgarrison          case '{':
226b8a08e38Sgarrison             while (getch(c, fd) != '}')
227b8a08e38Sgarrison                if (c == EOF) {
22896c4ecf2Srrh                   error("ill formed reference");
229b8a08e38Sgarrison                   }
230b8a08e38Sgarrison                 else
231b8a08e38Sgarrison                   addc(info, c);
232b8a08e38Sgarrison             break;
233b8a08e38Sgarrison 
234b8a08e38Sgarrison          case '\n':
235b85ca3f0Sgarrison             biblineno++;
236b8a08e38Sgarrison          case '\t':
237b8a08e38Sgarrison             c = ' ';   /* fall through */
238b8a08e38Sgarrison 
239b8a08e38Sgarrison          default:
240b8a08e38Sgarrison             addc(huntstr,c);
241b8a08e38Sgarrison          }
242b8a08e38Sgarrison    error("end of file reading citation");
243b8a08e38Sgarrison }
2444664557dSrrh char	ncitetemplate[64];
2454664557dSrrh int	changecite;
citemark(info,huntstr,tail)24696c4ecf2Srrh citemark(info, huntstr, tail)
24796c4ecf2Srrh 	char *info, *huntstr, *tail;
24896c4ecf2Srrh {
24996c4ecf2Srrh 	char c = CITEMARK;
25096c4ecf2Srrh         long int  n;
2514664557dSrrh 	/*
2524664557dSrrh 	 *	getref sets ncitetemplate as a side effect
2534664557dSrrh 	 */
25496c4ecf2Srrh 	n = getref(huntstr);
2554664557dSrrh 	if (ncitetemplate[0]){
2564664557dSrrh 		fprintf(tfd, "%c%s%c", FMTSTART, ncitetemplate, FMTEND);
2574664557dSrrh 		ncitetemplate[0] = 0;
2584664557dSrrh 	}
25999c1622cSbostic 	fprintf(tfd, "%c%d%c%s%c%s", c ,n, c, info, CITEEND, doacite?tail:"");
260e00c6970Srrh 
26196c4ecf2Srrh }
262b8a08e38Sgarrison 
263b8a08e38Sgarrison /* addc - add a character to hunt string */
addc(huntstr,c)264b8a08e38Sgarrison addc(huntstr, c)
265b8a08e38Sgarrison    char huntstr[HUNTSIZE], c;
266b8a08e38Sgarrison {  int  i;
267b8a08e38Sgarrison 
268b8a08e38Sgarrison    i = strlen(huntstr);
269b8a08e38Sgarrison    if (i > HUNTSIZE)
27096c4ecf2Srrh       error("citation too long, max of %d", HUNTSIZE);
271b8a08e38Sgarrison    huntstr[i] = c;
272b8a08e38Sgarrison    huntstr[i+1] = 0;
273b8a08e38Sgarrison }
27499c1622cSbostic 
27596c4ecf2Srrh /* getref - if an item was already referenced, return its reference index
27696c4ecf2Srrh                 otherwise create a new entry */
getref(huntstr)27796c4ecf2Srrh int getref(huntstr)
278b8a08e38Sgarrison    char huntstr[HUNTSIZE];
27996c4ecf2Srrh {  char rf[REFSIZE], *r, *hunt();
28096c4ecf2Srrh    int	match(), getwrd();
28106f62909Srrh    char	*realhstr;
28296c4ecf2Srrh    int hash;
28396c4ecf2Srrh    struct refinfo *rp;
28496c4ecf2Srrh    int	lg;
285b8a08e38Sgarrison 
28606f62909Srrh    realhstr = huntstr;
28706f62909Srrh    if (strncmp(huntstr, "$C$", 3) == 0){
28806f62909Srrh 	char *from, *to;
2894664557dSrrh 	changecite++;
2904664557dSrrh 	for(from = huntstr + 3, to = ncitetemplate; *from; from++, to++){
29106f62909Srrh 		switch(*from){
29206f62909Srrh 		case '\0':
29306f62909Srrh 		case ' ':
29406f62909Srrh 		case '\n':
29506f62909Srrh 		case '\t':	goto outcopy;
29606f62909Srrh 		default:	*to = *from;
29706f62909Srrh 		}
29806f62909Srrh 	}
29906f62909Srrh    outcopy: ;
30006f62909Srrh 	*to = 0;
30106f62909Srrh 	*from = 0;
30206f62909Srrh 	realhstr = from + 1;
30306f62909Srrh    }
30406f62909Srrh    r = hunt(realhstr);
305b8a08e38Sgarrison    if (r != NULL) {
30696c4ecf2Srrh       /* expand defined string */
307b8a08e38Sgarrison       strcpy(rf, r);
308b8a08e38Sgarrison       free(r);
309b8a08e38Sgarrison       expand(rf);
310b8a08e38Sgarrison       /* see if reference has already been cited */
31196c4ecf2Srrh       if (foot == false && (rp = refssearch(rf))){
31296c4ecf2Srrh 		return(rp - refinfo);
313b8a08e38Sgarrison       }
314b8a08e38Sgarrison       /* didn't match any existing reference, create new one */
31596c4ecf2Srrh       if (numrefs >= MAXREFS)
31696c4ecf2Srrh 	error("too many references, max of %d", MAXREFS);
31796c4ecf2Srrh       hash = strhash(rf);
31896c4ecf2Srrh       lg = strlen(rf) + 1;
31996c4ecf2Srrh       refinfo[numrefs].ri_pos = rend;
32096c4ecf2Srrh       refinfo[numrefs].ri_length = lg;
32196c4ecf2Srrh       refinfo[numrefs].ri_hp = refshash[hash];
32296c4ecf2Srrh       refinfo[numrefs].ri_n = numrefs;
32396c4ecf2Srrh       refshash[hash] = &refinfo[numrefs];
32496c4ecf2Srrh       wrref(&refinfo[numrefs], rf);
32596c4ecf2Srrh       return(numrefs++);
326b8a08e38Sgarrison       }
327b8a08e38Sgarrison    else {
32806f62909Srrh       bibwarning("no reference matching %s\n", realhstr);
32996c4ecf2Srrh       return(-1);
330b8a08e38Sgarrison       }
331b8a08e38Sgarrison }
33299c1622cSbostic 
refssearch(rf)33396c4ecf2Srrh struct refinfo *refssearch(rf)
33496c4ecf2Srrh    char *rf;
33596c4ecf2Srrh {
33696c4ecf2Srrh    char ref[REFSIZE];
33796c4ecf2Srrh    reg	int i;
33896c4ecf2Srrh    int	lg;
33996c4ecf2Srrh    reg	struct refinfo *rp;
34096c4ecf2Srrh    lg = strlen(rf) + 1;
34196c4ecf2Srrh    for (rp = refshash[strhash(rf)]; rp; rp = rp->ri_hp){
34296c4ecf2Srrh 	     if (rp->ri_length == lg){
34396c4ecf2Srrh 		     rdref(rp, ref);
34496c4ecf2Srrh 		     if (strcmp(ref, rf) == 0)
34596c4ecf2Srrh 			return(rp);
34696c4ecf2Srrh 	     }
34796c4ecf2Srrh    }
34896c4ecf2Srrh    return(0);
34996c4ecf2Srrh }
350b8a08e38Sgarrison /* hunt - hunt for reference from either personal or system index */
35199c1622cSbostic /* the old versions would stop at the first index file where a citation
35299c1622cSbostic  * matched.  This is NOT what is desired.  I have changed it so that it still
35399c1622cSbostic  * returns the first citation found, but also reports the existence of
35499c1622cSbostic  * duplicate entries in an INDEX file as well as across INDEX files.
35599c1622cSbostic  * Also, we do NOT assume that the SYSINDEX has been Tib'd.  Therefore,
35699c1622cSbostic  * if tib style expansion is in effect, the SYSINDEX is not searched.
35799c1622cSbostic  * (Besides which, on Sun systems at least, the SYSINDEX files are
35899c1622cSbostic  * created by refer, not bib, so we can't use them very effectively
35999c1622cSbostic  * anyway.  Besides which again, everything in SYSINDEX is in our
36099c1622cSbostic  * local files anyway.)
36199c1622cSbostic  *                   - ads 8/88
36299c1622cSbostic  */
hunt(huntstr)363b8a08e38Sgarrison char *hunt(huntstr)
364b8a08e38Sgarrison    char huntstr[];
36599c1622cSbostic {  char *found, *fhunt(), *r, *tp, *sp, fname[120];
366b8a08e38Sgarrison 
36799c1622cSbostic    found = NULL;
368b8a08e38Sgarrison    if (personal) {
36999c1622cSbostic       for (tp = fname, sp = pfile; ; sp++)
37099c1622cSbostic          if (*sp == ',' || *sp == '\0') {
37199c1622cSbostic             *tp = '\0';
37299c1622cSbostic             if ((r = fhunt(fname, huntstr)) != NULL) {
37399c1622cSbostic 		if (found != NULL) {
37499c1622cSbostic 		    /* we need an option to suppress this message -ads 5/89 */
37599c1622cSbostic 		    bibwarning("multiple INDEX files match citation %s\n",
37699c1622cSbostic 							huntstr);
37799c1622cSbostic 		    return (found);
378b8a08e38Sgarrison 		    }
37999c1622cSbostic 		found = r;
38099c1622cSbostic 		}
38199c1622cSbostic             if (*sp == '\0')
38299c1622cSbostic                break;
38399c1622cSbostic             tp = fname;
38499c1622cSbostic             }
38599c1622cSbostic          else *tp++ = *sp;
38699c1622cSbostic       if (found != NULL) return (found);
387b8a08e38Sgarrison       }
388b8a08e38Sgarrison    else if (findex) {
389b8a08e38Sgarrison       if ((r = fhunt(INDXFILE , huntstr)) != NULL)
390b8a08e38Sgarrison          return(r);
391b8a08e38Sgarrison       }
39299c1622cSbostic    if (!TibOption) {
393b8a08e38Sgarrison       if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
394b8a08e38Sgarrison 	 return(r);
39599c1622cSbostic       }
396b8a08e38Sgarrison    return(NULL);
397b8a08e38Sgarrison }
398b8a08e38Sgarrison 
399b8a08e38Sgarrison /* fhunt - hunt from a specific file */
fhunt(file,huntstr)400b8a08e38Sgarrison    char *fhunt(file, huntstr)
401b8a08e38Sgarrison    char file[], huntstr[];
402b8a08e38Sgarrison {  char *p, *r, *locate();
403b8a08e38Sgarrison 
404917c273dSgarrison    r = locate(huntstr, file, max_klen, common);
405b8a08e38Sgarrison 
406b8a08e38Sgarrison    if (r == NULL)
407b8a08e38Sgarrison       return(NULL);  /* error */
408b8a08e38Sgarrison    if (*r == 0)
409b8a08e38Sgarrison       return(NULL);  /* no match */
410b8a08e38Sgarrison 
411b8a08e38Sgarrison    for (p = r; *p; p++)
412b8a08e38Sgarrison       if (*p == '\n')
413b8a08e38Sgarrison          if (*(p+1) == '\n') { /* end */
414b8a08e38Sgarrison             if (*(p+2) != 0)
415927ed57bSrrh                bibwarning("multiple references match %s\n",huntstr);
416b8a08e38Sgarrison             *(p+1) = 0;
417b8a08e38Sgarrison             break;
418b8a08e38Sgarrison             }
419b8a08e38Sgarrison          else if (*(p+1) != '%' && *(p+1) != '.') /* unnecessary newline */
420b8a08e38Sgarrison             *p = ' ';
421b8a08e38Sgarrison    return(r);
422b8a08e38Sgarrison }
42396c4ecf2Srrh struct cite{
42496c4ecf2Srrh 	int	num;
42596c4ecf2Srrh 	char	*info;
42696c4ecf2Srrh };
42796c4ecf2Srrh citesort(p1, p2)
42896c4ecf2Srrh 	struct cite *p1, *p2;
42996c4ecf2Srrh {
43096c4ecf2Srrh 	return(p1->num - p2->num);
43196c4ecf2Srrh }
432b8a08e38Sgarrison 
433b8a08e38Sgarrison /* putrefs - gather contiguous references together, sort them if called
434b8a08e38Sgarrison    for, hyphenate if necessary, and dump them out */
putrefs(ifd,ofd,footrefs,fn)435b8a08e38Sgarrison int putrefs(ifd, ofd, footrefs, fn)
436b8a08e38Sgarrison FILE *ifd, *ofd;
437b8a08e38Sgarrison int  fn, footrefs[];
43896c4ecf2Srrh {
43996c4ecf2Srrh 	struct cite cites[MAXATONCE];
440b8a08e38Sgarrison 	char	infoword[HUNTSIZE];    /* information line */
44196c4ecf2Srrh 	reg	int i;
44296c4ecf2Srrh 	reg	char *p;
44396c4ecf2Srrh 	reg	int  ncites, n, j;         /* number of citations being dumped */
44496c4ecf2Srrh 	char	c, *walloc();
44596c4ecf2Srrh 	int neg;
44696c4ecf2Srrh 	/*
44796c4ecf2Srrh 	 * first gather contiguous references together,
44896c4ecf2Srrh 	 * and order them if required
44996c4ecf2Srrh 	 */
450b8a08e38Sgarrison 
45196c4ecf2Srrh 	ncites = 0;
452b8a08e38Sgarrison 	do {
453917c273dSgarrison 		neg = 1;
454b8a08e38Sgarrison 		n = 0;
45596c4ecf2Srrh 		do{
45696c4ecf2Srrh 			getch(c, ifd);
45796c4ecf2Srrh 			if (isdigit(c))
458b8a08e38Sgarrison 				n = 10 * n + (c - '0');
45996c4ecf2Srrh 			else if (c == '-')
46096c4ecf2Srrh 				neg *= -1;
46196c4ecf2Srrh 			else if (c == CITEMARK)
46296c4ecf2Srrh 				break;
46396c4ecf2Srrh 			else
46496c4ecf2Srrh 				error("bad cite char 0%03o in pass two",c);
46596c4ecf2Srrh 		} while(1);
46696c4ecf2Srrh 		if (neg < 0) {     /* reference not found */
46796c4ecf2Srrh 			cites[ncites].num = -1;
46896c4ecf2Srrh 			cites[ncites].info = 0;
46996c4ecf2Srrh 			ncites++;
47096c4ecf2Srrh 		} else {
47196c4ecf2Srrh 			/*
47296c4ecf2Srrh 			 * Find reference n in the references
47396c4ecf2Srrh 			 */
47496c4ecf2Srrh 			int i;
47596c4ecf2Srrh 			for (i = 0; i < numrefs; i++){
47696c4ecf2Srrh 				if (refinfo[i].ri_n == n){
47796c4ecf2Srrh 					cites[ncites].num = i;
47896c4ecf2Srrh 					cites[ncites].info = 0;
47996c4ecf2Srrh 					ncites++;
480b8a08e38Sgarrison 					break;
481b8a08e38Sgarrison 				}
48296c4ecf2Srrh 			}
48396c4ecf2Srrh 			if (i == numrefs)
48496c4ecf2Srrh 				error("citation	%d not found in pass 2", n);
485b8a08e38Sgarrison 		}
486b8a08e38Sgarrison 		if (getch(c, ifd) != CITEEND) {
487b8a08e38Sgarrison 			for (p = infoword; c != CITEEND ; ) {
488b8a08e38Sgarrison 				*p++ = c;
489b8a08e38Sgarrison 				getch(c, ifd);
490b8a08e38Sgarrison 			}
491b8a08e38Sgarrison 			*p = 0;
49296c4ecf2Srrh 			cites[ncites-1].info = walloc(infoword);
493b8a08e38Sgarrison 		}
494b8a08e38Sgarrison 		getch(c, ifd);
495b8a08e38Sgarrison 	} while (c == CITEMARK);
496b8a08e38Sgarrison 	ungetc(c, ifd);
49796c4ecf2Srrh 	if (ordcite)
49896c4ecf2Srrh 		qsort(cites, ncites, sizeof(struct cite), citesort);
499b8a08e38Sgarrison 
500b8a08e38Sgarrison 	/* now dump out values */
50196c4ecf2Srrh 	for (i = 0; i < ncites; i++) {
5024664557dSrrh 		if (cites[i].num >= 0) {
5034664557dSrrh 			if (changecite){
5044664557dSrrh 				char tempcite[128];
5054664557dSrrh 				char ref[REFSIZE];
5064664557dSrrh 				struct refinfo *p;
5074664557dSrrh 				/*
5084664557dSrrh 				 * rebuild the citation string,
5094664557dSrrh 				 * using the current template in effect
5104664557dSrrh 				 */
5114664557dSrrh 				p = &refinfo[cites[i].num];
5124664557dSrrh 				rdref(p, ref);
5134664557dSrrh 				bldcite(tempcite, cites[i].num, ref);
5144664557dSrrh 				strcat(tempcite, p->ri_disambig);
51500246a29Srrh 				if (doacite) fputs(tempcite, ofd);
5164664557dSrrh 			} else {
51700246a29Srrh 				if (doacite) fputs(refinfo[cites[i].num].ri_cite, ofd);
5184664557dSrrh 			}
51900246a29Srrh 			if (!doacite) fputs("\\&", ofd);
5204664557dSrrh 		}
52196c4ecf2Srrh 		if (cites[i].info) {
52200246a29Srrh 			if (doacite) fputs(cites[i].info, ofd);
52300246a29Srrh 			if (!doacite) fputs("\\&", ofd);
52496c4ecf2Srrh 			free(cites[i].info);
525b8a08e38Sgarrison 		}
526b8a08e38Sgarrison 		if (hyphen) {
52796c4ecf2Srrh 			for (j = 1;
52896c4ecf2Srrh 			     j + i <= ncites && cites[i+j].num == cites[i].num + j;
52996c4ecf2Srrh 			     j++)/*VOID*/;
53096c4ecf2Srrh 			if (j + i > ncites)
53196c4ecf2Srrh 				j = ncites;
532b8a08e38Sgarrison 			else
53396c4ecf2Srrh 				j = j + i - 1;
53496c4ecf2Srrh 		} else {
535b8a08e38Sgarrison 			j = i;
53696c4ecf2Srrh 		}
537b8a08e38Sgarrison 		if (j > i + 1) {
538b8a08e38Sgarrison 			fputs("\\*(]-", ofd);
539b8a08e38Sgarrison 			i = j - 1;
54096c4ecf2Srrh 		} else if (i != ncites - 1) {
541b8a08e38Sgarrison 			fputs("\\*(],", ofd);
54296c4ecf2Srrh 		}
543b8a08e38Sgarrison 		if (foot) {
544b8a08e38Sgarrison 			fn++;
54596c4ecf2Srrh 			footrefs[fn] = cites[i].num;
546b8a08e38Sgarrison 		}
547b8a08e38Sgarrison 	}
548b8a08e38Sgarrison 	return(fn);
549b8a08e38Sgarrison }
550b8a08e38Sgarrison 
551b8a08e38Sgarrison /* pass2 - read pass 1 files entering citation */
pass2(ifd,ofd)552b8a08e38Sgarrison    pass2(ifd, ofd)
553b8a08e38Sgarrison    FILE *ifd, *ofd;
554b8a08e38Sgarrison {
555b8a08e38Sgarrison    char c;
556b8a08e38Sgarrison    int  i, fn, footrefs[25], dumped;
557b8a08e38Sgarrison 
558b8a08e38Sgarrison    fn = -1;
559b8a08e38Sgarrison    dumped = foot;
560b8a08e38Sgarrison    while (getch(c, ifd) != EOF) {
561b8a08e38Sgarrison       while (c == '\n') {
562b8a08e38Sgarrison          putc(c, ofd);
563b8a08e38Sgarrison          if (foot && fn >= 0) {
564b8a08e38Sgarrison             for (i = 0; i <= fn; i++)
565b8a08e38Sgarrison                 dumpref(footrefs[i], ofd);
566b8a08e38Sgarrison             fn = -1;
567b8a08e38Sgarrison             }
568b8a08e38Sgarrison          if (testc(c, '.', ifd, ofd))
569b8a08e38Sgarrison             if (testc(c, '[', ifd, ofd))
570b8a08e38Sgarrison                if (testc(c, ']', ifd, ofd)) {
571b8a08e38Sgarrison                   while (echoc(c, ifd, ofd) != '\n')
572b8a08e38Sgarrison                      ;
573b8a08e38Sgarrison                   dumped = true;
57496c4ecf2Srrh                   for (i = 0; i < numrefs; i++){
575b8a08e38Sgarrison                      dumpref(i, ofd);
57696c4ecf2Srrh 		  }
577b8a08e38Sgarrison                   getch(c, ifd);
578b8a08e38Sgarrison                   }
579b8a08e38Sgarrison          }
5804664557dSrrh       if (c == FMTSTART)
5814664557dSrrh 	 changefmt(ifd);
5824664557dSrrh       else if (c == CITEMARK)
583b8a08e38Sgarrison          fn = putrefs(ifd, ofd, footrefs, fn);
584b8a08e38Sgarrison       else if (c != EOF)
585b8a08e38Sgarrison          putc(c, ofd);
586b8a08e38Sgarrison       }
587b8a08e38Sgarrison    if (dumped == false)
588b85ca3f0Sgarrison       bibwarning("Warning: references never dumped\n","");
589927ed57bSrrh }
5904664557dSrrh /*
5914664557dSrrh  *	change citation format
5924664557dSrrh  */
changefmt(ifd)5934664557dSrrh changefmt(ifd)
5944664557dSrrh 	FILE	*ifd;
5954664557dSrrh {
5964664557dSrrh 	char	c;
5974664557dSrrh 	char	*to;
5984664557dSrrh 	to = ncitetemplate;
5994664557dSrrh 	while (getch(c, ifd) != FMTEND)
6004664557dSrrh 		*to++ = c;
6014664557dSrrh 	*to = 0;
6024664557dSrrh 	strcpy(citetemplate, ncitetemplate);
6034664557dSrrh }
604