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: }