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