|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)bib.c 2.9 7/23/85";
3: #endif not lint
4: /*
5: Bib - bibliographic formatter
6:
7: Authored by: Tim Budd, University of Arizona, 1983.
8: lookup routines written by gary levin 2/82
9:
10: version 7/4/83
11:
12: Various modifications suggested by:
13: David Cherveny - Duke University Medical Center
14: Phil Garrison - UC Berkeley
15: M. J. Hawley - Yale University
16:
17:
18:
19:
20: */
21: # include <stdio.h>
22: # include <ctype.h>
23: # include "bib.h"
24:
25: # define HUNTSIZE 512 /* maximum size of hunt string */
26: # define MAXREFS 300 /* maximum number of references */
27: # define MAXATONCE 35 /* maximum references at one location */
28:
29: # define getch(c,fd) (c = getc(fd))
30: # define echoc(c,ifd,ofd) (getch(c,ifd) == EOF ? c : putc(c,ofd))
31: # define testc(c,d,ifd,ofd) (getch(c, ifd) == d ? putc(c, ofd) : 0)
32:
33: /* global variables */
34: FILE *rfd; /* reference temporary file */
35: #ifndef INCORE
36: char reffile[] = TMPREFFILE ;/* temporary file (see bib.h) */
37: #endif not INCORE
38: struct refinfo refinfo[MAXREFS]; /* reference information */
39: struct refinfo *refssearch();
40: struct refinfo *refshash[HASHSIZE];
41: long int rend = 1; /* last position in rfd (first char unused)*/
42: int numrefs = 0; /* number of references generated so far */
43: FILE *tfd; /* output of pass 1 of file(s) */
44: char tmpfile[] = TMPTEXTFILE ; /* output of pass 1 */
45: char *common = COMFILE; /* common word file */
46: int findex = false; /* can we read the file INDEX ? */
47:
48: /* global variables in bibargs */
49: extern int foot, doacite, sort, max_klen, personal;
50: extern int hyphen, ordcite, biblineno;
51: extern char sortstr[], pfile[], citetemplate[], bibfname[];
52:
53: #include <signal.h>
54:
55: main(argc, argv)
56: int argc;
57: char **argv;
58: { int rcomp();
59: int intr();
60:
61: /* the file INDEX in the current directory is the default index,
62: if it is present */
63:
64: strcpy(BMACLIB, N_BMACLIB);
65: strcpy(COMFILE, N_COMFILE);
66: strcpy(DEFSTYLE, N_DEFSTYLE);
67:
68: signal(SIGINT, intr);
69: rfd = fopen( INDXFILE , "r");
70: if (rfd != NULL) {
71: findex = true;
72: fclose(rfd);
73: }
74:
75: #ifndef INCORE
76: /* open temporaries, reffile will contain references collected in
77: pass 1, and tmpfile will contain text.
78: */
79: mktemp(reffile);
80: rfd = fopen(reffile,"w+");
81: if (rfd == NULL)
82: error("can't open temporary reference file, %s", reffile);
83: putc('x', rfd); /* put garbage in first position (not used) */
84: #endif not INCORE
85: mktemp(tmpfile);
86: tfd = fopen(tmpfile,"w");
87: if (tfd == NULL)
88: error("can't open temporary output file, %s", tmpfile);
89:
90: /*
91: pass1 - read files, looking for citations
92: arguments are read by doargs (bibargs.c)
93: */
94:
95: if (doargs(argc, argv, DEFSTYLE ) == 0) {
96: strcpy(bibfname, "<stdin>");
97: rdtext(stdin);
98: }
99:
100: /*
101: sort references, make citations, add disambiguating characters
102: */
103:
104: if (sort)
105: qsort(refinfo, numrefs, sizeof(struct refinfo), rcomp);
106: makecites();
107: disambiguate();
108:
109: /*
110: reopen temporaries
111: */
112:
113: fclose(tfd);
114: tfd = fopen(tmpfile,"r");
115: if (tfd == NULL)
116: error("can't open temporary output file %s for reading", tmpfile);
117: /*
118: pass 2 - reread files, replacing references
119: */
120: pass2(tfd, stdout);
121: cleanup(0);
122: }
123: /* interrupt processing */
124: intr()
125: {
126: cleanup(1);
127: }
128: /* clean up and exit */
129: cleanup(val)
130: {
131: fclose(tfd);
132: #ifndef INCORE
133: fclose(rfd);
134: unlink(reffile);
135: #endif INCORE
136: #ifndef DEBUG
137: unlink(tmpfile);
138: #endif DEBUG
139: exit(val);
140: }
141:
142: /* rdtext - read and process a text file, looking for [. commands */
143: rdtext(fd)
144: FILE *fd;
145: { char lastc, c, d;
146:
147: lastc = '\0';
148: biblineno = 1;
149: while (getch(c, fd) != EOF)
150: if (c == '[' || c == '{')
151: if (getch(d, fd) == '.') { /* found a reference */
152: if (c == '{') { if (lastc) putc(lastc, tfd);}
153: else
154: switch (lastc) {
155: case '\0': break;
156: case ' ': fputs("\\*([<", tfd); break;
157: case '.': case ',': case '?': case ':':
158: case ';': case '!': case '"': case '\'':
159: fputs("\\*([", tfd); /* fall through */
160: default: putc(lastc, tfd); break;
161: }
162: rdcite(fd, c);
163: if (c == '[')
164: switch (lastc) {
165: case '\0': break;
166: case ' ': fputs("\\*(>]", tfd); break;
167: case '.': case ',': case '?': case ':':
168: case ';': case '!': case '"': case '\'':
169: fprintf(tfd,"\\*(%c]", lastc); break;
170: }
171: lastc = '\0';
172: }
173: else {
174: if (lastc != '\0') putc(lastc, tfd);
175: ungetc(d, fd);
176: lastc = c;
177: }
178: else {
179: if (lastc != '\0') putc(lastc, tfd);
180: lastc = c;
181: if (c == '\n') biblineno++;
182: }
183: if (lastc != '\0') putc(lastc, tfd);
184: }
185:
186: /* rdcite - read citation information inside a [. command */
187: rdcite(fd, ch)
188: FILE *fd;
189: char ch;
190: { int getref();
191: char huntstr[HUNTSIZE], c, info[HUNTSIZE];
192:
193: if (ch == '[')
194: if (doacite) fputs("\\*([[", tfd);
195: else
196: if (doacite) fputs("\\*([{", tfd);
197: huntstr[0] = info[0] = 0;
198: while (getch(c, fd) != EOF)
199: switch (c) {
200: case ',':
201: citemark(info, huntstr, (char *)0);
202: huntstr[0] = info[0] = 0;
203: break;
204: case '.':
205: while (getch(c, fd) == '.') ;
206: if (c == ']') {
207: citemark(info, huntstr, "\\*(]]");
208: return;
209: }
210: else if (c == '}') {
211: citemark(info, huntstr, "\\*(}]");
212: return;
213: }
214: else
215: addc(huntstr, c);
216: break;
217:
218: case '{':
219: while (getch(c, fd) != '}')
220: if (c == EOF) {
221: error("ill formed reference");
222: }
223: else
224: addc(info, c);
225: break;
226:
227: case '\n':
228: biblineno++;
229: case '\t':
230: c = ' '; /* fall through */
231:
232: default:
233: addc(huntstr,c);
234: }
235: error("end of file reading citation");
236: }
237: char ncitetemplate[64];
238: int changecite;
239: citemark(info, huntstr, tail)
240: char *info, *huntstr, *tail;
241: {
242: char c = CITEMARK;
243: long int n;
244: /*
245: * getref sets ncitetemplate as a side effect
246: */
247: n = getref(huntstr);
248: if (ncitetemplate[0]){
249: fprintf(tfd, "%c%s%c", FMTSTART, ncitetemplate, FMTEND);
250: ncitetemplate[0] = 0;
251: }
252: if (doacite && (tail != (char *)0))
253: fprintf(tfd, "%c%d%c%s%c%s", c ,n, c, info, CITEEND, tail);
254: else
255: fprintf(tfd, "%c%d%c%s%c", c ,n, c, info, CITEEND);
256:
257: }
258:
259: /* addc - add a character to hunt string */
260: addc(huntstr, c)
261: char huntstr[HUNTSIZE], c;
262: { int i;
263:
264: i = strlen(huntstr);
265: if (i > HUNTSIZE)
266: error("citation too long, max of %d", HUNTSIZE);
267: huntstr[i] = c;
268: huntstr[i+1] = 0;
269: }
270: /* getref - if an item was already referenced, return its reference index
271: otherwise create a new entry */
272: int getref(huntstr)
273: char huntstr[HUNTSIZE];
274: { char rf[REFSIZE], *r, *hunt();
275: int match(), getwrd();
276: char *realhstr;
277: int hash;
278: struct refinfo *rp;
279: int lg;
280:
281: realhstr = huntstr;
282: if (strncmp(huntstr, "$C$", 3) == 0){
283: char *from, *to;
284: changecite++;
285: for(from = huntstr + 3, to = ncitetemplate; *from; from++, to++){
286: switch(*from){
287: case '\0':
288: case ' ':
289: case '\n':
290: case '\t': goto outcopy;
291: default: *to = *from;
292: }
293: }
294: outcopy: ;
295: *to = 0;
296: *from = 0;
297: realhstr = from + 1;
298: }
299: r = hunt(realhstr);
300: if (r != NULL) {
301: /* expand defined string */
302: strcpy(rf, r);
303: free(r);
304: expand(rf);
305: /* see if reference has already been cited */
306: if (foot == false && (rp = refssearch(rf))){
307: return(rp - refinfo);
308: }
309: /* didn't match any existing reference, create new one */
310: if (numrefs >= MAXREFS)
311: error("too many references, max of %d", MAXREFS);
312: hash = strhash(rf);
313: lg = strlen(rf) + 1;
314: refinfo[numrefs].ri_pos = rend;
315: refinfo[numrefs].ri_length = lg;
316: refinfo[numrefs].ri_hp = refshash[hash];
317: refinfo[numrefs].ri_n = numrefs;
318: refshash[hash] = &refinfo[numrefs];
319: wrref(&refinfo[numrefs], rf);
320: return(numrefs++);
321: }
322: else {
323: bibwarning("no reference matching %s\n", realhstr);
324: return(-1);
325: }
326: }
327: struct refinfo *refssearch(rf)
328: char *rf;
329: {
330: char ref[REFSIZE];
331: reg int i;
332: int lg;
333: reg struct refinfo *rp;
334: lg = strlen(rf) + 1;
335: for (rp = refshash[strhash(rf)]; rp; rp = rp->ri_hp){
336: if (rp->ri_length == lg){
337: rdref(rp, ref);
338: if (strcmp(ref, rf) == 0)
339: return(rp);
340: }
341: }
342: return(0);
343: }
344: /* hunt - hunt for reference from either personal or system index */
345: char *hunt(huntstr)
346: char huntstr[];
347: { char *fhunt(), *r, *p, *q, fname[120];
348:
349: if (personal) {
350: for (p = fname, q = pfile; ; q++)
351: if (*q == ',' || *q == 0) {
352: *p = 0;
353: if ((r = fhunt(fname, huntstr)) != NULL)
354: return(r);
355: else if (*q == 0)
356: break;
357: p = fname;
358: }
359: else *p++ = *q;
360: }
361: else if (findex) {
362: if ((r = fhunt( INDXFILE , huntstr)) != NULL)
363: return(r);
364: }
365: if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
366: return(r);
367: return(NULL);
368: }
369:
370: /* fhunt - hunt from a specific file */
371: char *fhunt(file, huntstr)
372: char file[], huntstr[];
373: { char *p, *r, *locate();
374:
375: r = locate(huntstr, file, max_klen, common);
376:
377: if (r == NULL)
378: return(NULL); /* error */
379: if (*r == 0)
380: return(NULL); /* no match */
381:
382: for (p = r; *p; p++)
383: if (*p == '\n')
384: if (*(p+1) == '\n') { /* end */
385: if (*(p+2) != 0)
386: bibwarning("multiple references match %s\n",huntstr);
387: *(p+1) = 0;
388: break;
389: }
390: else if (*(p+1) != '%' && *(p+1) != '.') /* unnecessary newline */
391: *p = ' ';
392: return(r);
393: }
394: struct cite{
395: int num;
396: char *info;
397: };
398: citesort(p1, p2)
399: struct cite *p1, *p2;
400: {
401: return(p1->num - p2->num);
402: }
403:
404: /* putrefs - gather contiguous references together, sort them if called
405: for, hyphenate if necessary, and dump them out */
406: int putrefs(ifd, ofd, footrefs, fn)
407: FILE *ifd, *ofd;
408: int fn, footrefs[];
409: {
410: struct cite cites[MAXATONCE];
411: char infoword[HUNTSIZE]; /* information line */
412: reg int i;
413: reg char *p;
414: reg int ncites, n, j; /* number of citations being dumped */
415: char c, *walloc();
416: int neg;
417: /*
418: * first gather contiguous references together,
419: * and order them if required
420: */
421:
422: ncites = 0;
423: do {
424: neg = 1;
425: n = 0;
426: do{
427: getch(c, ifd);
428: if (isdigit(c))
429: n = 10 * n + (c - '0');
430: else if (c == '-')
431: neg *= -1;
432: else if (c == CITEMARK)
433: break;
434: else
435: error("bad cite char 0%03o in pass two",c);
436: } while(1);
437: if (neg < 0) { /* reference not found */
438: cites[ncites].num = -1;
439: cites[ncites].info = 0;
440: ncites++;
441: } else {
442: /*
443: * Find reference n in the references
444: */
445: int i;
446: for (i = 0; i < numrefs; i++){
447: if (refinfo[i].ri_n == n){
448: cites[ncites].num = i;
449: cites[ncites].info = 0;
450: ncites++;
451: break;
452: }
453: }
454: if (i == numrefs)
455: error("citation %d not found in pass 2", n);
456: }
457: if (getch(c, ifd) != CITEEND) {
458: for (p = infoword; c != CITEEND ; ) {
459: *p++ = c;
460: getch(c, ifd);
461: }
462: *p = 0;
463: cites[ncites-1].info = walloc(infoword);
464: }
465: getch(c, ifd);
466: } while (c == CITEMARK);
467: ungetc(c, ifd);
468: if (ordcite)
469: qsort(cites, ncites, sizeof(struct cite), citesort);
470:
471: /* now dump out values */
472: for (i = 0; i < ncites; i++) {
473: if (cites[i].num >= 0) {
474: if (changecite){
475: char tempcite[128];
476: char ref[REFSIZE];
477: struct refinfo *p;
478: /*
479: * rebuild the citation string,
480: * using the current template in effect
481: */
482: p = &refinfo[cites[i].num];
483: rdref(p, ref);
484: bldcite(tempcite, cites[i].num, ref);
485: strcat(tempcite, p->ri_disambig);
486: if (doacite) fputs(tempcite, ofd);
487: } else {
488: if (doacite) fputs(refinfo[cites[i].num].ri_cite, ofd);
489: }
490: if (!doacite) fputs("\\&", ofd);
491: }
492: if (cites[i].info) {
493: if (doacite) fputs(cites[i].info, ofd);
494: if (!doacite) fputs("\\&", ofd);
495: free(cites[i].info);
496: }
497: if (hyphen) {
498: for (j = 1;
499: j + i <= ncites && cites[i+j].num == cites[i].num + j;
500: j++)/*VOID*/;
501: if (j + i > ncites)
502: j = ncites;
503: else
504: j = j + i - 1;
505: } else {
506: j = i;
507: }
508: if (j > i + 1) {
509: fputs("\\*(]-", ofd);
510: i = j - 1;
511: } else if (i != ncites - 1) {
512: fputs("\\*(],", ofd);
513: }
514: if (foot) {
515: fn++;
516: footrefs[fn] = cites[i].num;
517: }
518: }
519: return(fn);
520: }
521:
522: /* pass2 - read pass 1 files entering citation */
523: pass2(ifd, ofd)
524: FILE *ifd, *ofd;
525: {
526: char c;
527: int i, fn, footrefs[25], dumped;
528:
529: fn = -1;
530: dumped = foot;
531: while (getch(c, ifd) != EOF) {
532: while (c == '\n') {
533: putc(c, ofd);
534: if (foot && fn >= 0) {
535: for (i = 0; i <= fn; i++)
536: dumpref(footrefs[i], ofd);
537: fn = -1;
538: }
539: if (testc(c, '.', ifd, ofd))
540: if (testc(c, '[', ifd, ofd))
541: if (testc(c, ']', ifd, ofd)) {
542: while (echoc(c, ifd, ofd) != '\n')
543: ;
544: dumped = true;
545: for (i = 0; i < numrefs; i++){
546: dumpref(i, ofd);
547: }
548: getch(c, ifd);
549: }
550: }
551: if (c == FMTSTART)
552: changefmt(ifd);
553: else if (c == CITEMARK)
554: fn = putrefs(ifd, ofd, footrefs, fn);
555: else if (c != EOF)
556: putc(c, ofd);
557: }
558: if (dumped == false)
559: bibwarning("Warning: references never dumped\n","");
560: }
561: /*
562: * change citation format
563: */
564: changefmt(ifd)
565: FILE *ifd;
566: {
567: char c;
568: char *to;
569: to = ncitetemplate;
570: while (getch(c, ifd) != FMTEND)
571: *to++ = c;
572: *to = 0;
573: strcpy(citetemplate, ncitetemplate);
574: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.