|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)bib.c 2.10 3/5/87"; ! 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 bibtmpfile[] = 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 bibtmpfile 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(bibtmpfile); ! 86: tfd = fopen(bibtmpfile,"w"); ! 87: if (tfd == NULL) ! 88: error("can't open temporary output file, %s", bibtmpfile); ! 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(bibtmpfile,"r"); ! 115: if (tfd == NULL) ! 116: error("can't open temporary output file %s for reading", bibtmpfile); ! 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(bibtmpfile); ! 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.