113109Srrh #ifndef lint 2*15902Srrh static char sccsid[] = "@(#)bib.c 2.4 01/29/84"; 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 1715066Sgarrison 1815066Sgarrison 1915066Sgarrison 2015066Sgarrison */ 2112909Sgarrison # include <stdio.h> 2212909Sgarrison # include <ctype.h> 2312909Sgarrison # include "bib.h" 2412909Sgarrison 2512909Sgarrison # define HUNTSIZE 512 /* maximum size of hunt string */ 2612909Sgarrison # define MAXREFS 300 /* maximum number of references */ 2712909Sgarrison # define MAXATONCE 35 /* maximum references at one location */ 2812909Sgarrison 2912909Sgarrison # define getch(c,fd) (c = getc(fd)) 3012909Sgarrison # define echoc(c,ifd,ofd) (getch(c,ifd) == EOF ? c : putc(c,ofd)) 3112909Sgarrison # define testc(c,d,ifd,ofd) (getch(c, ifd) == d ? putc(c, ofd) : 0) 3212909Sgarrison 3312909Sgarrison /* global variables */ 3412909Sgarrison FILE *rfd; /* reference temporary file */ 3512909Sgarrison char reffile[] = TMPREFFILE ;/* temporary file (see bib.h) */ 36*15902Srrh struct refinfo refinfo[MAXREFS]; /* reference information */ 37*15902Srrh struct refinfo *refssearch(); 38*15902Srrh struct refinfo *refshash[HASHSIZE]; 3912909Sgarrison long int rend = 1; /* last position in rfd (first char unused)*/ 40*15902Srrh int numrefs = 0; /* number of references generated so far */ 4112909Sgarrison FILE *tfd; /* output of pass 1 of file(s) */ 4212909Sgarrison char tmpfile[] = TMPTEXTFILE ; /* output of pass 1 */ 4312909Sgarrison char common[] = COMFILE ; /* common word file */ 4412909Sgarrison int findex = false; /* can we read the file INDEX ? */ 4512909Sgarrison 4612909Sgarrison /* global variables in bibargs */ 4712909Sgarrison extern int foot, sort, personal; 4815066Sgarrison extern int hyphen, ordcite, biblineno; 4915066Sgarrison extern char sortstr[], pfile[], citetemplate[], bibfname[]; 5012909Sgarrison 51*15902Srrh #include <signal.h> 5212909Sgarrison 5312909Sgarrison main(argc, argv) 5412909Sgarrison int argc; 5512909Sgarrison char **argv; 5612909Sgarrison { int rcomp(); 57*15902Srrh int intr(); 5812909Sgarrison 5912909Sgarrison /* the file INDEX in the current directory is the default index, 6012909Sgarrison if it is present */ 6112909Sgarrison 62*15902Srrh signal(SIGINT, intr); 6312909Sgarrison rfd = fopen( INDXFILE , "r"); 6412909Sgarrison if (rfd != NULL) { 6512909Sgarrison findex = true; 6612909Sgarrison fclose(rfd); 6712909Sgarrison } 6812909Sgarrison 69*15902Srrh #ifndef INCORE 7012909Sgarrison /* open temporaries, reffile will contain references collected in 7112909Sgarrison pass 1, and tmpfile will contain text. 7212909Sgarrison */ 7312909Sgarrison mktemp(reffile); 7412909Sgarrison rfd = fopen(reffile,"w+"); 7512909Sgarrison if (rfd == NULL) 76*15902Srrh error("can't open temporary reference file, %s", reffile); 7715066Sgarrison putc('x', rfd); /* put garbage in first position (not used) */ 78*15902Srrh #endif not INCORE 7912909Sgarrison mktemp(tmpfile); 8012909Sgarrison tfd = fopen(tmpfile,"w"); 8112909Sgarrison if (tfd == NULL) 82*15902Srrh error("can't open temporary output file, %s", tmpfile); 8312909Sgarrison 8412909Sgarrison /* 8512909Sgarrison pass1 - read files, looking for citations 8612909Sgarrison arguments are read by doargs (bibargs.c) 8712909Sgarrison */ 8812909Sgarrison 8915066Sgarrison if (doargs(argc, argv, DEFSTYLE ) == 0) { 9015066Sgarrison strcpy(bibfname, "<stdin>"); 9112909Sgarrison rdtext(stdin); 9215066Sgarrison } 9312909Sgarrison 9412909Sgarrison /* 9512909Sgarrison sort references, make citations, add disambiguating characters 9612909Sgarrison */ 9712909Sgarrison 9812909Sgarrison if (sort) 99*15902Srrh qsort(refinfo, numrefs, sizeof(struct refinfo), rcomp); 100*15902Srrh makecites(); 10112909Sgarrison disambiguate(); 10212909Sgarrison 10312909Sgarrison /* 10412909Sgarrison reopen temporaries 10512909Sgarrison */ 10612909Sgarrison 10712909Sgarrison fclose(tfd); 10812909Sgarrison tfd = fopen(tmpfile,"r"); 10912909Sgarrison if (tfd == NULL) 110*15902Srrh error("can't open temporary output file %s for reading", tmpfile); 11112909Sgarrison /* 11212909Sgarrison pass 2 - reread files, replacing references 11312909Sgarrison */ 11412909Sgarrison pass2(tfd, stdout); 115*15902Srrh cleanup(0); 116*15902Srrh } 117*15902Srrh /* interrupt processing */ 118*15902Srrh intr() 119*15902Srrh { 120*15902Srrh cleanup(1); 121*15902Srrh } 122*15902Srrh /* clean up and exit */ 123*15902Srrh cleanup(val) 124*15902Srrh { 12512909Sgarrison fclose(tfd); 126*15902Srrh #ifndef INCORE 12712909Sgarrison fclose(rfd); 128*15902Srrh unlink(reffile); 129*15902Srrh #endif INCORE 130*15902Srrh #ifndef DEBUG 13112909Sgarrison unlink(tmpfile); 132*15902Srrh #endif DEBUG 133*15902Srrh exit(val); 13412909Sgarrison } 13512909Sgarrison 13612909Sgarrison /* rdtext - read and process a text file, looking for [. commands */ 13712909Sgarrison rdtext(fd) 13812909Sgarrison FILE *fd; 13912909Sgarrison { char lastc, c, d; 14012909Sgarrison 14115066Sgarrison lastc = '\0'; 14215066Sgarrison biblineno = 1; 14312909Sgarrison while (getch(c, fd) != EOF) 14412909Sgarrison if (c == '[' || c == '{') 14512909Sgarrison if (getch(d, fd) == '.') { /* found a reference */ 14612909Sgarrison if (c == '{') { if (lastc) putc(lastc, tfd);} 14712909Sgarrison else 14815066Sgarrison switch (lastc) { 14915066Sgarrison case '\0': break; 15015066Sgarrison case ' ': fputs("\\*([<", tfd); break; 15115066Sgarrison case '.': case ',': case '?': case ':': 15215066Sgarrison case ';': case '!': case '"': case '\'': 15315066Sgarrison fputs("\\*([", tfd); /* fall through */ 15415066Sgarrison default: putc(lastc, tfd); break; 15515066Sgarrison } 15612909Sgarrison rdcite(fd, c); 15712909Sgarrison if (c == '[') 15815066Sgarrison switch (lastc) { 15915066Sgarrison case '\0': break; 16015066Sgarrison case ' ': fputs("\\*(>]", tfd); break; 16115066Sgarrison case '.': case ',': case '?': case ':': 16215066Sgarrison case ';': case '!': case '"': case '\'': 16315066Sgarrison fprintf(tfd,"\\*(%c]", lastc); break; 16415066Sgarrison } 16515066Sgarrison lastc = '\0'; 16612909Sgarrison } 16712909Sgarrison else { 16815066Sgarrison if (lastc != '\0') putc(lastc, tfd); 16912909Sgarrison ungetc(d, fd); 17012909Sgarrison lastc = c; 17112909Sgarrison } 17212909Sgarrison else { 17315066Sgarrison if (lastc != '\0') putc(lastc, tfd); 17412909Sgarrison lastc = c; 17515066Sgarrison if (c == '\n') biblineno++; 17612909Sgarrison } 17715066Sgarrison if (lastc != '\0') putc(lastc, tfd); 17812909Sgarrison } 17912909Sgarrison 18012909Sgarrison /* rdcite - read citation information inside a [. command */ 18112909Sgarrison rdcite(fd, ch) 18212909Sgarrison FILE *fd; 18312909Sgarrison char ch; 184*15902Srrh { int n, getref(); 18512909Sgarrison char huntstr[HUNTSIZE], c, info[HUNTSIZE]; 18612909Sgarrison 18712909Sgarrison if (ch == '[') 18812909Sgarrison fputs("\\*([[", tfd); 18912909Sgarrison else 19012909Sgarrison fputs("\\*([{", tfd); 19112909Sgarrison huntstr[0] = info[0] = 0; 19212909Sgarrison while (getch(c, fd) != EOF) 19312909Sgarrison switch (c) { 19412909Sgarrison case ',': 195*15902Srrh citemark(info, huntstr, (char *)0); 19612909Sgarrison huntstr[0] = info[0] = 0; 19712909Sgarrison break; 19812909Sgarrison case '.': 19912909Sgarrison while (getch(c, fd) == '.') ; 20012909Sgarrison if (c == ']') { 201*15902Srrh citemark(info, huntstr, "\\*(]]"); 20212909Sgarrison return; 20312909Sgarrison } 20412909Sgarrison else if (c == '}') { 205*15902Srrh citemark(info, huntstr, "\\*(}]"); 20612909Sgarrison return; 20712909Sgarrison } 20812909Sgarrison else 20912909Sgarrison addc(huntstr, c); 21012909Sgarrison break; 21112909Sgarrison 21212909Sgarrison case '{': 21312909Sgarrison while (getch(c, fd) != '}') 21412909Sgarrison if (c == EOF) { 215*15902Srrh error("ill formed reference"); 21612909Sgarrison } 21712909Sgarrison else 21812909Sgarrison addc(info, c); 21912909Sgarrison break; 22012909Sgarrison 22112909Sgarrison case '\n': 22215066Sgarrison biblineno++; 22312909Sgarrison case '\t': 22412909Sgarrison c = ' '; /* fall through */ 22512909Sgarrison 22612909Sgarrison default: 22712909Sgarrison addc(huntstr,c); 22812909Sgarrison } 22912909Sgarrison error("end of file reading citation"); 23012909Sgarrison } 231*15902Srrh citemark(info, huntstr, tail) 232*15902Srrh char *info, *huntstr, *tail; 233*15902Srrh { 234*15902Srrh char c = CITEMARK; 235*15902Srrh long int n; 236*15902Srrh n = getref(huntstr); 237*15902Srrh fprintf(tfd, "%c%d%c%s%c%s", c ,n, c, info, CITEEND, tail); 238*15902Srrh } 23912909Sgarrison 24012909Sgarrison /* addc - add a character to hunt string */ 24112909Sgarrison addc(huntstr, c) 24212909Sgarrison char huntstr[HUNTSIZE], c; 24312909Sgarrison { int i; 24412909Sgarrison 24512909Sgarrison i = strlen(huntstr); 24612909Sgarrison if (i > HUNTSIZE) 247*15902Srrh error("citation too long, max of %d", HUNTSIZE); 24812909Sgarrison huntstr[i] = c; 24912909Sgarrison huntstr[i+1] = 0; 25012909Sgarrison } 25112909Sgarrison 252*15902Srrh /* getref - if an item was already referenced, return its reference index 253*15902Srrh otherwise create a new entry */ 254*15902Srrh int getref(huntstr) 25512909Sgarrison char huntstr[HUNTSIZE]; 256*15902Srrh { char rf[REFSIZE], *r, *hunt(); 257*15902Srrh reg int i; 258*15902Srrh int match(), getwrd(); 25915891Srrh char *realhstr; 260*15902Srrh int hash; 261*15902Srrh struct refinfo *rp; 262*15902Srrh int lg; 26312909Sgarrison 26415891Srrh realhstr = huntstr; 26515891Srrh if (strncmp(huntstr, "$C$", 3) == 0){ 26615891Srrh char *from, *to; 26715891Srrh for(from = huntstr + 3, to = citetemplate; *from; from++, to++){ 26815891Srrh switch(*from){ 26915891Srrh case '\0': 27015891Srrh case ' ': 27115891Srrh case '\n': 27215891Srrh case '\t': goto outcopy; 27315891Srrh default: *to = *from; 27415891Srrh } 27515891Srrh } 27615891Srrh outcopy: ; 27715891Srrh *to = 0; 27815891Srrh *from = 0; 27915891Srrh realhstr = from + 1; 28015891Srrh } 28115891Srrh r = hunt(realhstr); 28212909Sgarrison if (r != NULL) { 283*15902Srrh /* expand defined string */ 28412909Sgarrison strcpy(rf, r); 28512909Sgarrison free(r); 28612909Sgarrison expand(rf); 28712909Sgarrison /* see if reference has already been cited */ 288*15902Srrh if (foot == false && (rp = refssearch(rf))){ 289*15902Srrh return(rp - refinfo); 290*15902Srrh } 29112909Sgarrison /* didn't match any existing reference, create new one */ 292*15902Srrh if (numrefs >= MAXREFS) 293*15902Srrh error("too many references, max of %d", MAXREFS); 294*15902Srrh hash = strhash(rf); 295*15902Srrh lg = strlen(rf) + 1; 296*15902Srrh refinfo[numrefs].ri_pos = rend; 297*15902Srrh refinfo[numrefs].ri_length = lg; 298*15902Srrh refinfo[numrefs].ri_hp = refshash[hash]; 299*15902Srrh refinfo[numrefs].ri_n = numrefs; 300*15902Srrh refshash[hash] = &refinfo[numrefs]; 301*15902Srrh wrref(&refinfo[numrefs], rf); 302*15902Srrh return(numrefs++); 30312909Sgarrison } 30412909Sgarrison else { 30515891Srrh bibwarning("no reference matching %s\n", realhstr); 306*15902Srrh return(-1); 30712909Sgarrison } 30812909Sgarrison } 309*15902Srrh struct refinfo *refssearch(rf) 310*15902Srrh char *rf; 311*15902Srrh { 312*15902Srrh char ref[REFSIZE]; 313*15902Srrh reg int i; 314*15902Srrh int lg; 315*15902Srrh reg struct refinfo *rp; 316*15902Srrh lg = strlen(rf) + 1; 317*15902Srrh for (rp = refshash[strhash(rf)]; rp; rp = rp->ri_hp){ 318*15902Srrh if (rp->ri_length == lg){ 319*15902Srrh rdref(rp, ref); 320*15902Srrh if (strcmp(ref, rf) == 0) 321*15902Srrh return(rp); 322*15902Srrh } 323*15902Srrh } 324*15902Srrh return(0); 325*15902Srrh } 32612909Sgarrison /* hunt - hunt for reference from either personal or system index */ 32712909Sgarrison char *hunt(huntstr) 32812909Sgarrison char huntstr[]; 32912909Sgarrison { char *fhunt(), *r, *p, *q, fname[120]; 33012909Sgarrison 33112909Sgarrison if (personal) { 33212909Sgarrison for (p = fname, q = pfile; ; q++) 33312909Sgarrison if (*q == ',' || *q == 0) { 33412909Sgarrison *p = 0; 33512909Sgarrison if ((r = fhunt(fname, huntstr)) != NULL) 33612909Sgarrison return(r); 33712909Sgarrison else if (*q == 0) 33812909Sgarrison break; 33912909Sgarrison p = fname; 34012909Sgarrison } 34112909Sgarrison else *p++ = *q; 34212909Sgarrison } 34312909Sgarrison else if (findex) { 34412909Sgarrison if ((r = fhunt( INDXFILE , huntstr)) != NULL) 34512909Sgarrison return(r); 34612909Sgarrison } 34712909Sgarrison if ((r = fhunt(SYSINDEX , huntstr)) != NULL) 34812909Sgarrison return(r); 34912909Sgarrison return(NULL); 35012909Sgarrison } 35112909Sgarrison 35212909Sgarrison /* fhunt - hunt from a specific file */ 35312909Sgarrison char *fhunt(file, huntstr) 35412909Sgarrison char file[], huntstr[]; 35512909Sgarrison { char *p, *r, *locate(); 35612909Sgarrison 35712909Sgarrison r = locate(huntstr, file, 6, common); 35812909Sgarrison 35912909Sgarrison if (r == NULL) 36012909Sgarrison return(NULL); /* error */ 36112909Sgarrison if (*r == 0) 36212909Sgarrison return(NULL); /* no match */ 36312909Sgarrison 36412909Sgarrison for (p = r; *p; p++) 36512909Sgarrison if (*p == '\n') 36612909Sgarrison if (*(p+1) == '\n') { /* end */ 36712909Sgarrison if (*(p+2) != 0) 36815066Sgarrison bibwarning("multiple references match %s\n",huntstr); 36912909Sgarrison *(p+1) = 0; 37012909Sgarrison break; 37112909Sgarrison } 37212909Sgarrison else if (*(p+1) != '%' && *(p+1) != '.') /* unnecessary newline */ 37312909Sgarrison *p = ' '; 37412909Sgarrison return(r); 37512909Sgarrison } 376*15902Srrh struct cite{ 377*15902Srrh int num; 378*15902Srrh char *info; 379*15902Srrh }; 380*15902Srrh citesort(p1, p2) 381*15902Srrh struct cite *p1, *p2; 382*15902Srrh { 383*15902Srrh return(p1->num - p2->num); 384*15902Srrh } 38512909Sgarrison 38612909Sgarrison /* putrefs - gather contiguous references together, sort them if called 38712909Sgarrison for, hyphenate if necessary, and dump them out */ 38812909Sgarrison int putrefs(ifd, ofd, footrefs, fn) 38912909Sgarrison FILE *ifd, *ofd; 39012909Sgarrison int fn, footrefs[]; 391*15902Srrh { 392*15902Srrh struct cite cites[MAXATONCE]; 393*15902Srrh char infoword[HUNTSIZE]; /* information line */ 394*15902Srrh reg int i; 395*15902Srrh reg char *p; 396*15902Srrh reg int ncites, n, j; /* number of citations being dumped */ 397*15902Srrh char c, *walloc(); 398*15902Srrh int neg; 399*15902Srrh /* 400*15902Srrh * first gather contiguous references together, 401*15902Srrh * and order them if required 402*15902Srrh */ 40312909Sgarrison 404*15902Srrh ncites = 0; 405*15902Srrh neg = 1; 406*15902Srrh do { 407*15902Srrh n = 0; 408*15902Srrh do{ 409*15902Srrh getch(c, ifd); 410*15902Srrh if (isdigit(c)) 411*15902Srrh n = 10 * n + (c - '0'); 412*15902Srrh else if (c == '-') 413*15902Srrh neg *= -1; 414*15902Srrh else if (c == CITEMARK) 415*15902Srrh break; 416*15902Srrh else 417*15902Srrh error("bad cite char 0%03o in pass two",c); 418*15902Srrh } while(1); 419*15902Srrh if (neg < 0) { /* reference not found */ 420*15902Srrh cites[ncites].num = -1; 421*15902Srrh cites[ncites].info = 0; 422*15902Srrh ncites++; 423*15902Srrh } else { 424*15902Srrh /* 425*15902Srrh * Find reference n in the references 426*15902Srrh */ 427*15902Srrh int i; 428*15902Srrh for (i = 0; i < numrefs; i++){ 429*15902Srrh if (refinfo[i].ri_n == n){ 430*15902Srrh cites[ncites].num = i; 431*15902Srrh cites[ncites].info = 0; 432*15902Srrh ncites++; 433*15902Srrh break; 434*15902Srrh } 435*15902Srrh } 436*15902Srrh if (i == numrefs) 437*15902Srrh error("citation %d not found in pass 2", n); 438*15902Srrh } 439*15902Srrh if (getch(c, ifd) != CITEEND) { 440*15902Srrh for (p = infoword; c != CITEEND ; ) { 441*15902Srrh *p++ = c; 442*15902Srrh getch(c, ifd); 443*15902Srrh } 444*15902Srrh *p = 0; 445*15902Srrh cites[ncites-1].info = walloc(infoword); 446*15902Srrh } 447*15902Srrh getch(c, ifd); 448*15902Srrh } while (c == CITEMARK); 449*15902Srrh ungetc(c, ifd); 450*15902Srrh if (ordcite) 451*15902Srrh qsort(cites, ncites, sizeof(struct cite), citesort); 45212909Sgarrison 453*15902Srrh /* now dump out values */ 454*15902Srrh for (i = 0; i < ncites; i++) { 455*15902Srrh if (cites[i].num >= 0) 456*15902Srrh fputs(refinfo[cites[i].num].ri_cite, ofd); 457*15902Srrh if (cites[i].info) { 458*15902Srrh fputs(cites[i].info, ofd); 459*15902Srrh free(cites[i].info); 460*15902Srrh } 461*15902Srrh if (hyphen) { 462*15902Srrh for (j = 1; 463*15902Srrh j + i <= ncites && cites[i+j].num == cites[i].num + j; 464*15902Srrh j++)/*VOID*/; 465*15902Srrh if (j + i > ncites) 466*15902Srrh j = ncites; 467*15902Srrh else 468*15902Srrh j = j + i - 1; 469*15902Srrh } else { 470*15902Srrh j = i; 471*15902Srrh } 472*15902Srrh if (j > i + 1) { 473*15902Srrh fputs("\\*(]-", ofd); 474*15902Srrh i = j - 1; 475*15902Srrh } else if (i != ncites - 1) { 476*15902Srrh fputs("\\*(],", ofd); 477*15902Srrh } 478*15902Srrh if (foot) { 479*15902Srrh fn++; 480*15902Srrh footrefs[fn] = cites[i].num; 481*15902Srrh } 482*15902Srrh } 483*15902Srrh return(fn); 48412909Sgarrison } 48512909Sgarrison 48612909Sgarrison /* pass2 - read pass 1 files entering citation */ 48712909Sgarrison pass2(ifd, ofd) 48812909Sgarrison FILE *ifd, *ofd; 48912909Sgarrison { 49012909Sgarrison char c; 49112909Sgarrison int i, fn, footrefs[25], dumped; 49212909Sgarrison 49312909Sgarrison fn = -1; 49412909Sgarrison dumped = foot; 49512909Sgarrison while (getch(c, ifd) != EOF) { 49612909Sgarrison while (c == '\n') { 49712909Sgarrison putc(c, ofd); 49812909Sgarrison if (foot && fn >= 0) { 49912909Sgarrison for (i = 0; i <= fn; i++) 50012909Sgarrison dumpref(footrefs[i], ofd); 50112909Sgarrison fn = -1; 50212909Sgarrison } 50312909Sgarrison if (testc(c, '.', ifd, ofd)) 50412909Sgarrison if (testc(c, '[', ifd, ofd)) 50512909Sgarrison if (testc(c, ']', ifd, ofd)) { 50612909Sgarrison while (echoc(c, ifd, ofd) != '\n') 50712909Sgarrison ; 50812909Sgarrison dumped = true; 509*15902Srrh for (i = 0; i < numrefs; i++){ 51012909Sgarrison dumpref(i, ofd); 511*15902Srrh } 51212909Sgarrison getch(c, ifd); 51312909Sgarrison } 51412909Sgarrison } 51512909Sgarrison if (c == CITEMARK) 51612909Sgarrison fn = putrefs(ifd, ofd, footrefs, fn); 51712909Sgarrison else if (c != EOF) 51812909Sgarrison putc(c, ofd); 51912909Sgarrison } 52012909Sgarrison if (dumped == false) 52115066Sgarrison bibwarning("Warning: references never dumped\n",""); 52212909Sgarrison } 523