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

Defined functions

addc defined in line 260; used 3 times
changefmt defined in line 564; used 1 times
citemark defined in line 239; used 3 times
citesort defined in line 398; used 1 times
cleanup defined in line 129; used 2 times
fhunt defined in line 371; used 4 times
getref defined in line 272; used 2 times
hunt defined in line 345; used 2 times
intr defined in line 124; used 2 times
main defined in line 55; never used
pass2 defined in line 523; used 1 times
putrefs defined in line 406; used 1 times
rdcite defined in line 187; used 1 times
rdtext defined in line 143; used 1 times
  • in line 97
refssearch defined in line 327; used 2 times

Defined variables

changecite defined in line 238; used 2 times
common defined in line 45; used 1 times
findex defined in line 46; used 2 times
ncitetemplate defined in line 237; used 6 times
numrefs defined in line 42; used 13 times
reffile defined in line 36; used 4 times
refinfo defined in line 38; used 11 times
refshash defined in line 40; used 3 times
rend defined in line 41; used 1 times
sccsid defined in line 2; never used
tmpfile defined in line 44; used 6 times

Defined struct's

cite defined in line 394; used 6 times

Defined macros

HUNTSIZE defined in line 25; used 7 times
MAXATONCE defined in line 27; used 1 times
MAXREFS defined in line 26; used 3 times
echoc defined in line 30; used 1 times
getch defined in line 29; used 14 times
testc defined in line 31; used 3 times
Last modified: 1986-01-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2098
Valid CSS Valid XHTML 1.0 Strict