1: #ifndef lint
   2: static char sccsid[] = "@(#)bibargs.c	2.10	11/22/85";
   3: #endif not lint
   4: /*
   5:         Authored by: Tim Budd, University of Arizona, 1983.
   6:                 version 7/4/83
   7: 
   8:         Various modifications suggested by:
   9:                 David Cherveny - Duke University Medical Center
  10:                 Phil Garrison - UC Berkeley
  11:                 M. J. Hawley - Yale University
  12: 
  13: 
  14: 
  15: 
  16:         read argument strings for bib and listrefs
  17:         do name formatting, printing lines, other actions common to both
  18:                                                         */
  19: # include <stdio.h>
  20: # include <ctype.h>
  21: # include "bib.h"
  22: # define LINELENGTH 1024
  23: # define MAXDEFS     500             /* maximum number of defined words */
  24: 
  25: /* global variables */
  26:    char bibfname[120];          /* file name currently being read            */
  27:    int  biblineno;              /* line number currently being referenced    */
  28:    int  abbrev       = false;   /* automatically abbreviate names            */
  29:    int  capsmcap     = false;   /* print names in caps small caps (CACM form)*/
  30:    int  numrev       = 0;       /* number of authors names to reverse        */
  31:    int  edabbrev     = false;   /* abbreviate editors names ?                */
  32:    int  edcapsmcap   = false;   /* print editors in cap small caps           */
  33:    int  ednumrev     = 0;       /* number of editors to reverse              */
  34:    int  max_klen     = 6;   /* max size of key			     */
  35:    int  sort         = false;   /* sort references ? (default no)            */
  36:    int  foot         = false;   /* footnoted references ? (default endnotes) */
  37:    int  doacite      = true;    /* place citations ? */
  38:    int  hyphen       = false;   /* hypenate contiguous references            */
  39:    int  ordcite      = true;    /* order multiple citations                  */
  40:    char sortstr[80]  = "1";     /* sorting template                          */
  41:    char trailstr[80] = "";      /* trailing characters to output             */
  42:    char pfile[400];             /* private file name                         */
  43:    int  personal = false;       /* personal file given ? (default no)        */
  44:    char citetemplate[80] = "1"; /* citation template                         */
  45:    struct wordinfo words[MAXDEFS];     /* defined words */
  46:    struct wordinfo *wordhash[HASHSIZE];
  47:    struct wordinfo *wordsearch();
  48:    int  wordtop = 0;           /* number of defined words         */
  49: 
  50: /* where output goes */
  51:    extern FILE *tfd;
  52: /* reference file information */
  53:    extern struct refinfo refinfo[];
  54:    extern char reffile[];
  55: #ifndef INCORE
  56:    extern FILE *rfd;
  57: #endif not INCORE
  58:    extern int numrefs;
  59: 
  60: /* doargs - read command argument line for both bib and listrefs
  61:             set switch values
  62:             call rdtext on file arguments, after dumping
  63:             default style file if no alternative style is given
  64: */
  65:    int doargs(argc, argv, defstyle)
  66:    int argc;
  67:    char **argv, defstyle[];
  68: {  int numfiles, i, style;
  69:    char *p, *q, *walloc();
  70:    FILE *fd;
  71: 
  72:    numfiles = 0;
  73:    style = true;
  74:    newbibdir(BMACLIB);
  75: 
  76:    for (i = 1; i < argc; i++)
  77:       if (argv[i][0] == '-')
  78:          switch(argv[i][1]) {
  79:             case 'd':
  80:                 if (argv[i][2])
  81:                     p = &argv[i][2];
  82:                 else {  /* take next arg */
  83:                     i++;
  84:                     p = argv[i];
  85:             }
  86:             newbibdir(p);
  87:             case 'a':  for (p = &argv[i][2]; *p; p++)
  88:                           if (*p == 'a' || *p == 0)
  89:                              abbrev = true;
  90:                            else if (*p == 'x')
  91:                              capsmcap = true;
  92:                            else if (*p == 'r') {
  93:                              if (*(p+1))
  94:                                 numrev = atoi(p+1);
  95:                               else
  96:                                 numrev = 1000;
  97:                               break;
  98:                               }
  99:                        break;
 100: 
 101:             case 'c':  if (argv[i][2] == 0)
 102:                           error("citation string expected for 'c'");
 103:                        else
 104:                           for (p = citetemplate,q = &argv[i][2]; *p++ = *q++; );
 105:                        break;
 106: 
 107:             case 'e':  for (p = &argv[i][2]; *p; p++)
 108:                           if (*p == 'a')
 109:                              edabbrev = true;
 110:                            else if (*p == 'x')
 111:                              edcapsmcap = true;
 112:                            else if (*p == 'r') {
 113:                              if (*(p+1))
 114:                                 ednumrev = atoi(p+1);
 115:                               else
 116:                                 ednumrev = 1000;
 117:                               break;
 118:                               }
 119:                        break;
 120: 
 121:         case 'l':  if (argv[i][2]){
 122:                           max_klen  = atoi(&argv[i][2]);
 123:               if (max_klen > REFSIZE)
 124:                   error("too long key size");
 125:                } else {
 126:               error("-l needs a numeric value");
 127:                }
 128:                break;
 129: 
 130:             case 'v':  doacite = false;
 131:             /*FALLTHROUGH*/
 132:             case 'f':  foot = true;
 133:                        hyphen = false;
 134:                        break;
 135: 
 136:             case 'h':  hyphen = ordcite = true;
 137:                        break;
 138: 
 139:             case 'n':  for (p = &argv[i][2]; *p; p++)
 140:                           if (*p == 'a')
 141:                              abbrev = false;
 142:                           else if (*p == 'v')
 143:                              doacite = true;
 144:                           else if (*p == 'f')
 145:                              foot = false;
 146:                           else if (*p == 'h')
 147:                              hyphen = false;
 148:                           else if (*p == 'o')
 149:                              ordcite = false;
 150:                           else if (*p == 'r')
 151:                              numrev = 0;
 152:                           else if (*p == 's')
 153:                              sort = false;
 154:                           else if (*p == 'x')
 155:                              capsmcap = false;
 156:                        break;
 157: 
 158:             case 'o':  ordcite = true;
 159:                        break;
 160: 
 161:             case 'p':  if (argv[i][2])
 162:                           p = &argv[i][2];
 163:                        else {  /* take next arg */
 164:                           i++;
 165:                           p = argv[i];
 166:                           }
 167:                        strcpy(pfile, p);
 168:                        personal = true;
 169:                        break;
 170: 
 171:             case 'r':  if (argv[i][2] == 0)  /* this is now replaced by -ar */
 172:                           numrev = 1000;
 173:                        else
 174:                           numrev = atoi(&argv[i][2]);
 175:                        break;
 176: 
 177:             case 's':  sort = true;
 178:                        if (argv[i][2])
 179:                           for (p = sortstr,q = &argv[i][2]; *p++ = *q++; );
 180:                        break;
 181: 
 182:             case 't':  style = false;           /* fall through */
 183:             case 'i':  if (argv[i][2])
 184:                           p = &argv[i][2];
 185:                        else { /* take next arg */
 186:                           i++;
 187:                           p = argv[i];
 188:                           }
 189:                        incfile(p);
 190:                        break;
 191: 
 192:             case 'x':  capsmcap = true; /* this is now replaced by -ax */
 193:                        break;
 194: 
 195:             case 0:    if (style) {  /* no style command given, take default */
 196:                           style = false;
 197:                           incfile( defstyle );
 198:                           }
 199:                        strcpy(bibfname,"<stdin>");
 200:                        rdtext(stdin);
 201:                        numfiles++;
 202:                        break;
 203: 
 204:             default:   fputs(argv[i], stderr);
 205:                        error("'%c' invalid switch", argv[i][1]);
 206:             }
 207:       else { /* file name */
 208:          numfiles++;
 209:          if (style) {
 210:             style = false;
 211:             incfile( defstyle );
 212:             }
 213:          fd = fopen(argv[i], "r");
 214:          if (fd == NULL) {
 215:             error("can't open file %s", argv[i]);
 216:             }
 217:          else {
 218:             strcpy(bibfname, argv[i]);
 219:             rdtext(fd);
 220:             fclose(fd);
 221:             }
 222:          }
 223: 
 224:    if (style) incfile( defstyle );
 225:    return(numfiles);
 226: 
 227: }
 228: 
 229: newbibdir(name)
 230:     char *name;
 231: {
 232:     strreplace(COMFILE, BMACLIB, name);
 233:     strreplace(DEFSTYLE, BMACLIB, name);
 234:     strcpy(BMACLIB, name);
 235:     wordstuff("BMACLIB", BMACLIB);
 236:     fprintf(tfd, ".ds l] %s\n", BMACLIB);
 237: }
 238: 
 239: /* incfile - read in an included file  */
 240: incfile(np)
 241:    char *np;
 242: {  char name[120];
 243:    FILE *fd;
 244:    char *p, line[LINELENGTH], dline[LINELENGTH], word[80], *tfgets();
 245:    int  i, getwrd();
 246: 
 247:    strcpy(bibfname, np);
 248:    fd = fopen(np, "r");
 249:    if (fd == NULL && *np != '/') {
 250:       strcpy(name, "bib.");
 251:       strcat(name, np);
 252:       strcpy(bibfname, name);
 253:       fd = fopen(name, "r");
 254:       }
 255:    if (fd == NULL && *np != '/') {
 256:       strcpy(name,BMACLIB);
 257:       strcat(name, "/bib.");
 258:       strcat(name, np);
 259:       strcpy(bibfname, name);
 260:       fd = fopen(name, "r");
 261:       }
 262:    if (fd == NULL) {
 263:       bibwarning("%s: can't open", np);
 264:       exit(1);
 265:       }
 266: 
 267:    /* now go off and process file */
 268:    biblineno = 1;
 269:    while (tfgets(line, LINELENGTH, fd) != NULL) {
 270:       biblineno++;
 271:       switch(line[0]) {
 272: 
 273:          case '#': break;
 274: 
 275:          case 'A': for (p = &line[1]; *p; p++)
 276:                       if (*p == 'A' || *p == '\0')
 277:                          abbrev = true;
 278:                       else if (*p == 'X')
 279:                          capsmcap = true;
 280:                       else if (*p == 'R') {
 281:                          if (*(p+1))
 282:                             numrev = atoi(p+1);
 283:                          else
 284:                             numrev = 1000;
 285:                          break;
 286:                          }
 287:                    break;
 288: 
 289:          case 'C': for (p = &line[1]; *p == ' '; p++) ;
 290:                    strcpy(citetemplate, p);
 291:                    break;
 292: 
 293:          case 'D': if ((i = getwrd(line, 1, word)) == 0)
 294:                       error("word expected in definition");
 295:            if (wordsearch(word)) { /* already there-toss rest of def.*/
 296:             while(line[strlen(line)-1] == '\\' ) {
 297:                             if (tfgets(line, LINELENGTH, fd) == NULL) break;
 298:             }
 299:             break;
 300:            }
 301:                    for (p = &line[i]; *p == ' '; p++) ;
 302:                    for (strcpy(dline, p); dline[strlen(dline)-1] == '\\'; ){
 303:                        dline[strlen(dline)-1] = '\n';
 304:                        if (tfgets(line, LINELENGTH, fd) == NULL) break;
 305:                        strcat(dline, line);
 306:                        }
 307:            wordstuff(word, dline);
 308:                    break;
 309: 
 310:          case 'E': for (p = &line[1]; *p; p++)
 311:                       if (*p == 'A')
 312:                          edabbrev = true;
 313:                       else if (*p == 'X')
 314:                          edcapsmcap = true;
 315:                       else if (*p == 'R') {
 316:                          if (*(p+1))
 317:                             ednumrev = atoi(p+1);
 318:                          else
 319:                             ednumrev = 1000;
 320:                          break;
 321:                          }
 322:                    break;
 323: 
 324:          case 'F': foot = true;
 325:                    hyphen = false;
 326:                    break;
 327: 
 328:          case 'I': for (p = &line[1]; *p == ' '; p++);
 329:                    expand(p);
 330:                    incfile(p);
 331:                    break;
 332: 
 333:          case 'H': hyphen = ordcite = true;
 334:                    break;
 335: 
 336:          case 'O': ordcite = true;
 337:                    break;
 338: 
 339:          case 'R': if (line[1] == 0)  /* this is now replaced by AR */
 340:                       numrev = 1000;
 341:                    else
 342:                       numrev = atoi(&line[1]);
 343:                    break;
 344: 
 345:          case 'S': sort = true;
 346:                    for (p = &line[1]; *p == ' '; p++) ;
 347:                    strcpy(sortstr, p);
 348:                    break;
 349: 
 350:          case 'T': for (p = &line[1]; *p == ' '; p++) ;
 351:                    strcpy(trailstr, p);
 352:                    break;
 353: 
 354:          case 'X': capsmcap = true;     /* this is now replace by AX */
 355:                    break;
 356: 
 357:          default:  fprintf(tfd,"%s\n",line);
 358:                    while (fgets(line, LINELENGTH, fd) != NULL)
 359:                       fputs(line, tfd);
 360:                    return;
 361:          }
 362: 
 363:    }
 364:    /* close up */
 365:    fclose(fd);
 366: }
 367: 
 368: /* bibwarning - print out a warning message */
 369:   /*VARARGS1*/
 370:   bibwarning(msg, a1, a2)
 371:   char *msg;
 372: {
 373:   fprintf(stderr,"`%s', line %d: ", bibfname, biblineno);
 374:   fprintf(stderr, msg, a1, a2);
 375:   fprintf(stderr, "\n");
 376: }
 377: 
 378: /* error - report unrecoverable error message */
 379:   /*VARARGS1*/
 380:   error(str, a1, a2)
 381:   char *str;
 382: {
 383:   bibwarning(str, a1, a2);
 384:   /*
 385:    *	clean up temp files and exit
 386:    */
 387:   cleanup(1);
 388: }
 389: 
 390: #ifndef INCORE
 391: #ifdef READWRITE
 392: /*
 393: ** fixrfd( mode ) -- re-opens the rfd file to be read or write,
 394: **      depending on the mode.  Uses a static int to save the current mode
 395: **      and avoid unnecessary re-openings.
 396: */
 397: fixrfd( mode )
 398: register int mode;
 399: {
 400:     static int cur_mode = WRITE;    /* rfd open for writing initially */
 401: 
 402:     if (mode != cur_mode)
 403:     {
 404:         rfd = freopen(reffile, ((mode == READ)? "r" : "a"), rfd);
 405:         cur_mode = mode;
 406:         if (rfd == NULL)
 407:               error("Hell!  Couldn't re-open reference file %s",
 408:             reffile);
 409:     }
 410: }
 411: #endif
 412: #endif not INCORE
 413: 
 414: 
 415: /* tfgets - fgets which trims off newline */
 416:    char *tfgets(line, n, ptr)
 417:    char line[];
 418:    int  n;
 419:    FILE *ptr;
 420: {  reg char *p;
 421: 
 422:    p = fgets(line, n, ptr);
 423:    if (p == NULL)
 424:       return(NULL);
 425:    else
 426:       for (p = line; *p; p++)
 427:          if (*p == '\n')
 428:             *p = 0;
 429:    return(line);
 430: }
 431: 
 432: /* getwrd - place next word from in[i] into out */
 433: int getwrd(in, i, out)
 434:    reg char in[], out[];
 435:    reg int i;
 436: {  int j;
 437: 
 438:    j = 0;
 439:    while (in[i] == ' ' || in[i] == '\n' || in[i] == '\t')
 440:       i++;
 441:    if (in[i])
 442:       while (in[i] && in[i] != ' ' && in[i] != '\t' && in[i] != '\n')
 443:          out[j++] = in[i++];
 444:    else
 445:       i = 0;    /* signals end of in[i..]   */
 446:    out[j] = 0;
 447:    return (i);
 448: }
 449: 
 450: /* walloc - allocate enough space for a word */
 451: char *walloc(word)
 452:    char *word;
 453: {  char *i, *malloc();
 454:    i = malloc(1 + strlen(word));
 455:    if (i == NULL)
 456:       error("out of storage");
 457:    strcpy(i, word);
 458:    return(i);
 459: }
 460: 
 461: /* isword - see if character is legit word char */
 462: int iswordc(c)
 463: char c;
 464: {
 465:    if (isalnum(c) || c == '&' || c == '_')
 466:       return(true);
 467:    return(false);
 468: }
 469:    expand(line)
 470:    char *line;
 471: {  char line2[REFSIZE], word[LINELENGTH];
 472:    reg  struct wordinfo *wp;
 473:    reg  char *p, *q, *w;
 474: 
 475:     q = line2;
 476:     for (p = line; *p; /*VOID*/){
 477:         if (isalnum(*p)) {
 478:             for (w = word; *p && iswordc(*p); ) *w++ = *p++;
 479:             *w = 0;
 480:             if (wp = wordsearch(word)){
 481:                 strcpy(word, wp->wi_def);
 482:                 expand(word);
 483:             }
 484:             strcpy(q, word);
 485:             q += strlen(q);
 486:         } else {
 487:             *q++ = *p++;
 488:         }
 489:     }
 490:     *q = 0;
 491:     strcpy(line, line2);
 492: }
 493: 
 494: /* wordstuff- save a word and its definition, building a hash table */
 495:    wordstuff(word, def)
 496:    char *word, *def;
 497: {
 498:    int i;
 499:    if (wordtop >= MAXDEFS)
 500:     error("too many definitions, max of %d", MAXDEFS);
 501:    words[wordtop].wi_length = strlen(word);
 502:    words[wordtop].wi_word = word ? walloc(word) : 0;
 503:    words[wordtop].wi_def = def ? walloc(def) : 0;
 504:    i = strhash(word);
 505:    words[wordtop].wi_hp = wordhash[i];
 506:    wordhash[i] = &words[wordtop];
 507:    wordtop++;
 508: }
 509:    struct wordinfo *wordsearch(word)
 510:    char *word;
 511: {
 512:    reg int lg;
 513:    reg struct wordinfo *wp;
 514:    lg = strlen(word);
 515:    for (wp = wordhash[strhash(word)]; wp; wp = wp->wi_hp){
 516:     if (wp->wi_length == lg && (strcmp(wp->wi_word, word) == 0)){
 517:         return(wp);
 518:     }
 519:    }
 520:    return(0);
 521: }
 522: 
 523:    int strhash(str)
 524:    reg char *str;
 525: {
 526:    reg int value = 0;
 527:    for (value = 0; *str; value <<= 2, value += *str++)/*VOID*/;
 528:    value %= HASHSIZE;
 529:    if (value < 0)
 530:     value += HASHSIZE;
 531:    return(value);
 532: }
 533: 
 534: /* rdref - read text for an already cited reference */
 535:    rdref(p, ref)
 536:    struct refinfo *p;
 537:    char ref[REFSIZE];
 538: {
 539:    ref[0] = 0;
 540: #ifndef INCORE
 541: #ifdef READWRITE
 542:    fixrfd( READ );                      /* fix access mode of rfd, if nec. */
 543: #endif
 544:    fseek(rfd, p->ri_pos, 0);
 545:    fread(ref, p->ri_length, 1, rfd);
 546: #else INCORE
 547:    strcpy(ref, p->ri_ref);
 548: #endif INCORE
 549: }
 550: 
 551: /* wrref - write text for a new reference */
 552:    wrref(p, ref)
 553:    struct refinfo *p;
 554:    char ref[REFSIZE];
 555: {
 556: #ifndef INCORE
 557: #ifdef READWRITE
 558:     fixrfd( WRITE );                 /* fix access mode of rfd, if nec. */
 559: #else
 560:     fseek(rfd, p->ri_pos, 0);        /* go to end of rfd */
 561: #endif
 562:     fwrite(ref, p->ri_length, 1, rfd);
 563: #else INCORE
 564:    p->ri_ref = walloc(ref);
 565: #endif INCORE
 566: }
 567: 
 568: /* breakname - break a name into first and last name */
 569:    breakname(line, first, last)
 570:    char line[], first[], last[];
 571: {  reg char *t, *f, *q, *r, *p;
 572: 
 573:    for (t = line; *t != '\n'; t++);
 574:    for (t--; isspace(*t); t--);
 575: 
 576:    /* now strip off last name */
 577:    for (q = t; isspace(*q) == 0 || ((*q == ' ') & (*(q-1) == '\\')); q--)
 578:       if (q == line)
 579:          break;
 580:    f = q;
 581:    if (q != line) {
 582:       q++;
 583:       for (; isspace(*f); f--);
 584:       f++;
 585:       }
 586: 
 587:    /* first name is start to f, last name is q to t */
 588: 
 589:    for (r = first, p = line; p != f; )
 590:       *r++ = *p++;
 591:    *r = 0;
 592:    for (r = last, p = q, t++; q != t; )
 593:       *r++ = *q++;
 594:    *r = 0;
 595: 
 596: }
 597: 
 598: /* match - see if string1 is a substring of string2 (case independent)*/
 599:    int match(str1, str2)
 600:    reg char str1[], str2[];
 601: {  reg int  j, i;
 602:    char a, b;
 603: 
 604:    for (i = 0; str2[i]; i++) {
 605:       for (j = 0; str1[j]; j++) {
 606:          if (isupper(a = str2[i+j]))
 607:             a = (a - 'A') + 'a';
 608:          if (isupper(b = str1[j]))
 609:             b = (b - 'A') + 'a';
 610:          if (a != b)
 611:             break;
 612:          }
 613:       if (str1[j] == 0)
 614:          return(true);
 615:       }
 616:    return(false);
 617: }
 618: 
 619: /* scopy - append a copy of one string to another */
 620:    char *scopy(p, q)
 621:    reg char *p, *q;
 622: {
 623:    while (*p++ = *q++)
 624:       ;
 625:    return(--p);
 626: }
 627: 
 628: /* rcomp - reference comparison routine for qsort utility */
 629:    int rcomp(ap, bp)
 630:    struct refinfo *ap, *bp;
 631: {  char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD];
 632:    reg  char *p, *q;
 633:    char *getfield();
 634:    int  neg, res;
 635:    int  fields_found;
 636: 
 637:    rdref(ap, ref1);
 638:    rdref(bp, ref2);
 639:    for (p = sortstr; *p; p = q) {
 640:       if (*p == '-') {
 641:          p++;
 642:          neg = true;
 643:          }
 644:       else
 645:          neg = false;
 646:       q = getfield(p, field1, ref1);
 647:       fields_found = true;
 648:       if (q == 0) {
 649:      res = 1;
 650:      fields_found = false;
 651:       } else if (strcmp (field1, "") == 0) {    /* field not found */
 652:          if (*p == 'A') {
 653:             getfield("F", field1, ref1);
 654:         if (strcmp (field1, "") == 0) {
 655:                getfield("I", field1, ref1);
 656:            if (strcmp (field1, "") == 0) {
 657:               res = 1;
 658:           fields_found = false;
 659:            }
 660:         }
 661:      } else {
 662:         res = 1;
 663:         fields_found = false;
 664:      }
 665:       }
 666: 
 667:       if (getfield(p, field2, ref2) == 0) {
 668:      res = -1;
 669:      fields_found = false;
 670:       } else if (strcmp (field2, "") == 0) {    /* field not found */
 671:          if (*p == 'A') {
 672:             getfield("F", field2, ref2);
 673:         if (strcmp (field2, "") == 0) {
 674:                getfield("I", field2, ref2);
 675:            if (strcmp (field2, "") == 0) {
 676:               res = -1;
 677:           fields_found = false;
 678:            }
 679:         }
 680:      } else {
 681:         res = -1;
 682:         fields_found = false;
 683:      }
 684:       }
 685:       if (fields_found) {
 686:          if (*p == 'A') {
 687:             if (isupper(field1[0]))
 688:                field1[0] -= 'A' - 'a';
 689:             if (isupper(field2[0]))
 690:                field2[0] -= 'A' - 'a';
 691:             }
 692:          res = strcmp(field1, field2);
 693:          }
 694:       if (neg)
 695:          res = - res;
 696:       if (res != 0)
 697:          break;
 698:       }
 699:    if (res == 0)
 700:       if (ap < bp)
 701:          res = -1;
 702:       else
 703:          res = 1;
 704:    return(res);
 705: }
 706: 
 707: /* makecites - make standard citation strings, using citetemplate currently in effect */
 708:    makecites()
 709: {  char ref[REFSIZE], tempcite[100], *malloc();
 710:    reg int  i;
 711: 
 712:    for (i = 0; i < numrefs; i++) {
 713:       rdref(&refinfo[i], ref);
 714:       bldcite(tempcite, i, ref);
 715:       refinfo[i].ri_cite = malloc(2 + strlen(tempcite));
 716:       if (refinfo[i].ri_cite == NULL)
 717:          error("out of storage");
 718:       strcpy(refinfo[i].ri_cite, tempcite);
 719:       }
 720: }
 721: 
 722: /* bldcite - build a single citation string */
 723:    bldcite(cp, i, ref)
 724:    char *cp, ref[];
 725:    int  i;
 726: {  reg char *p, *q, *fp;
 727:    char c;
 728:    char field[REFSIZE];
 729:    char *getfield(), *aabet(), *aabetlast(), *fullaabet(), *astro();
 730: 
 731:    getfield("F", field, ref);
 732:    if (field[0] != 0)
 733:       for (p = field; *p; p++)
 734:          *cp++ = *p;
 735:    else {
 736:       p = citetemplate;
 737:       field[0] = 0;
 738:       while (c = *p++) {
 739:          if (isalpha(c)) {                      /* field name   */
 740:             q = getfield(p-1, field, ref);
 741:             if (q != 0) {
 742:                p = q;
 743:                for (fp = field; *fp; )
 744:                   *cp++ = *fp++;
 745:                }
 746:             }
 747:          else if (c == '1') {                   /* numeric  order */
 748:             sprintf(field,"%d",1 + i);
 749:             for (fp = field; *fp; )
 750:                *cp++ = *fp++;
 751:             }
 752:          else if (c == '2')                     /* alternate alphabetic */
 753:             cp = aabet(cp, ref);
 754:          else if (c == '3')                     /* Astrophysical Journal style*/
 755:             cp = astro(cp, ref);
 756:      else if (c == '8')         /* Full alphabetic */
 757:         cp = fullaabet(cp, ref);
 758:          else if (c == '9')                     /* Last name of Senior Author*/
 759:             cp = aabetlast(cp, ref);
 760:      else if (c == '0') {           /* print nothing */
 761:             for (fp = field; *fp; )
 762:                *cp++ = *fp++;
 763:             }
 764: /*       else if (c == '4')          here is how to add new styles */
 765:          else if (c == '{') {                   /* other information   */
 766:             while (*p != '}')
 767:                if (*p == 0)
 768:                   error("unexpected end of citation template");
 769:                else
 770:                   *cp++ = *p++;
 771:             p++;
 772:             }
 773:          else if (c == '<') {
 774:             while (*p != '>') {
 775:                if (*p == 0)
 776:                   error("unexpected end of citation template");
 777:                else
 778:                   *cp++ = *p++;
 779:                }
 780:             p++;
 781:             }
 782:          else if (c != '@')
 783:             *cp++ = c;
 784:          }
 785:       }
 786:    *cp++ = 0;
 787: }
 788: 
 789: /* alternate alphabetic citation style -
 790:         if 1 author - first three letters of last name
 791:         if 2 authors - first two letters of first, followed by first letter of
 792:                                 seond
 793:         if 3 or more authors - first letter of first three authors */
 794:    char *aabet(cp, ref)
 795:    char *cp, ref[];
 796: {  char field[REFSIZE], temp[100];
 797:    reg char *np, *fp;
 798:    int j, getname();
 799: 
 800:    if (getname(1, field, temp, ref)) {
 801:       np = cp;
 802:       fp = field;
 803:       for (j = 1; j <= 3; j++)
 804:          if (*fp != 0)
 805:             *cp++ = *fp++;
 806:       if (getname(2, field, temp, ref))
 807:          np[2] = field[0];
 808:       if (getname(3, field, temp, ref)) {
 809:          np[1] = np[2];
 810:          np[2] = field[0];
 811:          }
 812:       }
 813: return(cp);
 814: }
 815: 
 816: /* alternate alphabetic citation style -
 817: 	first two characters of last names of all authors
 818: 	up to max_klen characters.
 819: */
 820:    char *fullaabet(cp, ref)
 821:    char *cp, ref[];
 822: {  char field[REFSIZE], temp[100];
 823:    reg char *fp;
 824:    char *lastcp;
 825:    int getname();
 826:    int i;
 827: 
 828:    lastcp = cp + max_klen;
 829:    for (i= 1; getname(i, field, temp, ref); i++) {
 830:       for (fp = field; *fp && (fp < &(field[3])); )
 831:      if (cp > lastcp)
 832:          break;
 833:          else if (isalpha(*fp))
 834:          *cp++ = *fp++;
 835:      else
 836:          fp++;
 837:    }
 838:    return(cp);
 839: }
 840: 
 841: 
 842: /* alternate alphabetic citation style -
 843: 	entire last name of senior author
 844: */
 845:    char *aabetlast(cp, ref)
 846:    char *cp, ref[];
 847: {  char field[REFSIZE], temp[100];
 848:    reg char *fp;
 849:    int getname();
 850: 
 851:    if (getname(1, field, temp, ref)) {
 852:       for (fp = field; *fp; )
 853:          *cp++ = *fp++;
 854:    }
 855:    return(cp);
 856: }
 857: 
 858: /* Astrophysical Journal style
 859:         if 1 author - last name date
 860:         if 2 authors - last name and last name date
 861:         if 3 authors - last name, last name and last name date
 862:         if 4 or more authors - last name et al. date */
 863:    char *astro(cp, ref)
 864:    char *cp, ref[];
 865: {  char name1[100], name2[100], name3[100], temp[100];
 866:    reg char *fp;
 867:    int getname();
 868: 
 869:    if (getname(1, name1, temp, ref)) {
 870:       for (fp = name1; *fp; )
 871:          *cp++ = *fp++;
 872:       if (getname(4, name3, temp, ref)) {
 873:          for (fp = " et al."; *fp; )
 874:             *cp++ = *fp++;
 875:          }
 876:       else if (getname(2, name2, temp, ref)) {
 877:          if (getname(3, name3, temp, ref)) {
 878:             for (fp = "\\*(c]"; *fp; )
 879:                *cp++ = *fp++;
 880:             for (fp = name2; *fp; )
 881:                *cp++ = *fp++;
 882:             for (fp = "\\*(m]"; *fp; )
 883:                *cp++ = *fp++;
 884:             for (fp = name3; *fp; )
 885:                *cp++ = *fp++;
 886:             }
 887:          else {
 888:             for (fp = "\\*(n]"; *fp; )
 889:                *cp++ = *fp++;
 890:             for (fp = name2; *fp; )
 891:                *cp++ = *fp++;
 892:             }
 893:          }
 894:     }
 895: return(cp);
 896: }
 897: 
 898: /* getfield - get a single field from reference */
 899:    char *getfield(ptr, field, ref)
 900:    char *ptr, field[], ref[];
 901: {  reg  char *p, *q;
 902:    char temp[100];
 903:    int  n, len, i, getname();
 904: 
 905:    field[0] = 0;
 906:    if (*ptr == 'A')
 907:       getname(1, field, temp, ref);
 908:    else
 909:       for (p = ref; *p; p++)
 910:          if (*p == '%' && *(p+1) == *ptr) {
 911:             for (p = p + 2; *p == ' '; p++)
 912:                ;
 913:             for (q = field; (*p != '\n') && (*p != '\0'); )
 914:                *q++ = *p++;
 915:             *q = 0;
 916:             break;
 917:             }
 918:    n = 0;
 919:    len = strlen(field);
 920:    if (*++ptr == '-') {
 921:       for (ptr++; isdigit(*ptr); ptr++)
 922:          n = 10 * n + (*ptr - '0');
 923:       if (n > len)
 924:          n = 0;
 925:       else
 926:          n = len - n;
 927:       for (i = 0; field[i] = field[i+n]; i++)
 928:          ;
 929:       }
 930:    else if (isdigit(*ptr)) {
 931:       for (; isdigit(*ptr); ptr++)
 932:          n = 10 * n + (*ptr - '0');
 933:       if (n > len)
 934:          n = len;
 935:       field[n] = 0;
 936:       }
 937: 
 938:    if (*ptr == 'u') {
 939:       ptr++;
 940:       for (p = field; *p; p++)
 941:          if (islower(*p))
 942:             *p = (*p - 'a') + 'A';
 943:       }
 944:    else if (*ptr == 'l') {
 945:       ptr++;
 946:       for (p = field; *p; p++)
 947:          if (isupper(*p))
 948:             *p = (*p - 'A') + 'a';
 949:       }
 950:    return(ptr);
 951: }
 952: 
 953: /* getname - get the nth name field from reference, breaking into
 954:              first and last names */
 955:    int getname(n, last, first, ref)
 956:    int  n;
 957:    char last[], first[], ref[];
 958: {  reg char *p;
 959:    int  m;
 960: 
 961:    m = n;
 962:    for (p = ref; *p; p++)
 963:       if (*p == '%' & *(p+1) == 'A') {
 964:          n--;
 965:          if (n == 0) {
 966:             for (p = p + 2; *p == ' '; p++) ;
 967:             breakname(p, first, last) ;
 968:             return(true);
 969:             }
 970:          }
 971: 
 972:    if (n == m)          /* no authors, try editors */
 973:       for (p = ref; *p; p++)
 974:          if (*p == '%' & *(p+1) == 'E') {
 975:             n--;
 976:             if (n == 0) {
 977:                for (p = p + 2; *p == ' '; p++) ;
 978:                breakname(p, first, last) ;
 979:                return(true);
 980:                }
 981:             }
 982: 
 983:    if (n == m) {        /* no editors, either, try institution */
 984:       first[0] = last[0] = '\0';
 985:       getfield("I", last, ref);
 986:       if (last[0] != '\0')
 987:          return(true);
 988:       }
 989: 
 990:    return(false);
 991: }
 992: 
 993: /* disambiguate - compare adjacent citation strings, and if equal, add
 994:                   single character disambiguators */
 995:    disambiguate()
 996: {  reg int i, j;
 997:     char adstr;
 998: 
 999:    for (i = 0; i < numrefs-1; i = j) {
1000:       j = i + 1;
1001:       if (strcmp(refinfo[i].ri_cite, refinfo[j].ri_cite)==0) {
1002:          adstr = 'a';
1003:          for(j = i+1;
1004:          j<numrefs && strcmp(refinfo[i].ri_cite,refinfo[j].ri_cite) == 0;
1005:          j++) {
1006:             adstr = 'a' + (j-i);
1007:         refinfo[j].ri_disambig[0] = adstr;
1008:             }
1009:      refinfo[i].ri_disambig[0] = 'a';
1010:          }
1011:      }
1012:   for (i = 0; i < numrefs; i++){
1013:     strcat(refinfo[i].ri_cite, refinfo[i].ri_disambig);
1014:   }
1015: }
1016: 
1017: 
1018: /* bldname - build a name field
1019:              doing abbreviations, reversals, and caps/small caps
1020: */
1021:    bldname(first, last, name, reverse)
1022:    char *first, *last, name[];
1023:    int reverse;
1024: {
1025:    char newfirst[120], newlast[120];
1026:    reg char *p, *q, *f, *l;
1027:    char *scopy();
1028:    int  flag;
1029: 
1030:    if (abbrev) {
1031:       p = first;
1032:       q = newfirst;
1033:       flag = false;
1034:       while (*p) {
1035:          while (*p == ' ')
1036:             p++;
1037:          if (*p == 0)
1038:             break;
1039:          if (isupper(*p)) {
1040:             if (flag)           /* between initial gap */
1041:                q = scopy(q, "\\*(a]");
1042:             flag = true;
1043:             *q++ = *p;
1044:             q = scopy(q, "\\*(p]");
1045:             }
1046:          if (*++p == '.')
1047:             p++;
1048:          else while (*p != 0 && ! isspace(*p))
1049:             p++;
1050:          }
1051:       *q = 0;
1052:       f = newfirst;
1053:       }
1054:    else
1055:       f = first;
1056: 
1057:    if (capsmcap) {
1058:       p = last;
1059:       q = newlast;
1060:       flag = 0;  /* 1 - printing cap, 2 - printing small */
1061:       while (*p)
1062:          if (islower(*p)) {
1063:             if (flag != 2)
1064:                q = scopy(q, "\\s-2");
1065:             flag = 2;
1066:             *q++ = (*p++ - 'a') + 'A';
1067:             }
1068:          else {
1069:             if (flag == 2)
1070:                q = scopy(q,"\\s+2");
1071:             flag = 1;
1072:             *q++ = *p++;
1073:             }
1074:       if (flag == 2)
1075:          q = scopy(q, "\\s+2");
1076:       *q = 0;
1077:       l = newlast;
1078:       }
1079:    else
1080:       l = last;
1081: 
1082:    if (f[0] == 0)
1083:       sprintf(name, "%s\n", l);
1084:    else if (reverse)
1085:       sprintf(name, "%s\\*(b]%s\n", l, f);
1086:    else
1087:       sprintf(name, "%s %s\n", f, l);
1088: }
1089: 
1090: /* prtauth - print author or editor field */
1091:    prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev)
1092:    char c, *line;
1093:    int  num, max, abbrev, capsmcap, numrev;
1094:    FILE *ofd;
1095: {  char first[LINELENGTH], last[LINELENGTH];
1096: 
1097:    if (num <= numrev || abbrev || capsmcap) {
1098:       breakname(line, first, last);
1099:       bldname(first, last, line, num <= numrev);
1100:       }
1101:    if (num == 1)
1102:       fprintf(ofd,".ds [%c %s", c, line);
1103:    else if (num < max)
1104:       fprintf(ofd,".as [%c \\*(c]%s", c, line);
1105:    else if (max == 2)
1106:       fprintf(ofd,".as [%c \\*(n]%s", c, line);
1107:    else
1108:       fprintf(ofd,".as [%c \\*(m]%s", c, line);
1109:    if (num == max && index(trailstr, c))
1110:       fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
1111: }
1112: 
1113: /* doline - actually print out a line of reference information */
1114:    doline(c, line, numauths, maxauths, numeds, maxeds, ofd)
1115:    char c, *line;
1116:    int numauths, maxauths, numeds, maxeds;
1117:    FILE *ofd;
1118: {
1119: 
1120:    switch(c) {
1121:       case 'A':
1122:           prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev);
1123:           break;
1124: 
1125:        case 'E':
1126:           prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, ednumrev);
1127:           if (numeds == maxeds)
1128:              fprintf(ofd,".nr [E %d\n", maxeds);
1129:           break;
1130: 
1131:        case 'P':
1132:           if (index(line, '-'))
1133:              fprintf(ofd,".nr [P 1\n");
1134:           else
1135:              fprintf(ofd,".nr [P 0\n");
1136:           fprintf(ofd,".ds [P %s",line);
1137:           if (index(trailstr, 'P'))
1138:              fprintf(ofd,".ds ]P %c\n",line[strlen(line)-2]);
1139:           break;
1140: 
1141:        case 'F':
1142:        case 'K': break;
1143: 
1144:        default:
1145:           fprintf(ofd,".ds [%c %s", c, line);
1146:           if (index(trailstr, c))
1147:              fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
1148:           }
1149: }
1150: 
1151: /* dumpref - dump reference number i */
1152:    dumpref(i, ofd)
1153:    int i;
1154:    FILE *ofd;
1155: {  char ref[REFSIZE], line[REFSIZE];
1156:    reg char *p, *q;
1157:    char *from;
1158:    int numauths, maxauths, numeds, maxeds;
1159: 
1160:    rdref(&refinfo[i], ref);
1161:    maxauths = maxeds = 0;
1162:    numauths = numeds = 0;
1163:    for (p = ref; *p; p++)
1164:       if (*p == '%')
1165:          if (*(p+1) == 'A') maxauths++;
1166:          else if (*(p+1) == 'E') maxeds++;
1167:    fprintf(ofd, ".[-\n");
1168:    fprintf(ofd, ".ds [F %s\n", refinfo[i].ri_cite);
1169: #ifndef INCORE
1170:    fseek(rfd, (long)refinfo[i].ri_pos, 0);
1171:    while (fgets(line, REFSIZE, rfd) != NULL) {
1172: #else INCORE
1173:    for (q = line, from = refinfo[i].ri_ref; *from; /*VOID*/) { /*} */
1174:     if (*from == '\n'){
1175:         *q++ = '\n';
1176:         *q = 0;
1177:         q = line;
1178:         from++;
1179:     } else {
1180:         *q++ = *from++;
1181:         continue;
1182:     }
1183: #endif INCORE
1184:     switch(line[0]){
1185:     case 0:
1186:         goto doneref;
1187:     case '.':
1188:         fprintf(ofd, "%s", line);
1189:         break;
1190:     case '%':
1191:         switch(line[1]){
1192:         case 'A':   numauths++; break;
1193:         case 'E':   numeds++;   break;
1194:         }
1195:         for (p = &line[2]; *p == ' '; p++) /*VOID*/;
1196:         doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd);
1197:     }
1198:    }
1199:    doneref:;
1200:    fprintf(ofd,".][\n");
1201: }

Defined functions

aabet defined in line 794; used 2 times
aabetlast defined in line 845; used 2 times
astro defined in line 863; used 2 times
bibwarning defined in line 370; used 5 times
bldcite defined in line 723; used 2 times
bldname defined in line 1021; used 1 times
breakname defined in line 569; used 3 times
disambiguate defined in line 995; used 2 times
doargs defined in line 65; used 2 times
doline defined in line 1114; used 1 times
dumpref defined in line 1152; used 3 times
error defined in line 380; used 24 times
expand defined in line 469; used 4 times
fixrfd defined in line 397; used 2 times
fullaabet defined in line 820; used 2 times
getfield defined in line 899; used 11 times
getname defined in line 955; used 15 times
getwrd defined in line 433; used 3 times
incfile defined in line 240; used 5 times
iswordc defined in line 462; used 1 times
makecites defined in line 708; used 2 times
match defined in line 599; used 1 times
newbibdir defined in line 229; used 2 times
prtauth defined in line 1091; used 2 times
rcomp defined in line 629; used 4 times
rdref defined in line 535; used 6 times
scopy defined in line 620; used 6 times
strhash defined in line 523; used 6 times
tfgets defined in line 416; used 4 times
walloc defined in line 451; used 6 times
wordsearch defined in line 509; used 3 times
wordstuff defined in line 495; used 2 times
wrref defined in line 552; used 2 times

Defined variables

abbrev defined in line 28; used 8 times
bibfname defined in line 26; used 7 times
biblineno defined in line 27; used 9 times
capsmcap defined in line 29; used 10 times
citetemplate defined in line 44; used 4 times
doacite defined in line 37; used 10 times
edabbrev defined in line 31; used 3 times
edcapsmcap defined in line 32; used 3 times
ednumrev defined in line 33; used 5 times
foot defined in line 36; used 7 times
hyphen defined in line 38; used 6 times
max_klen defined in line 34; used 3 times
numrev defined in line 30; used 14 times
ordcite defined in line 39; used 6 times
personal defined in line 43; used 2 times
pfile defined in line 42; used 2 times
sccsid defined in line 2; never used
sort defined in line 35; used 5 times
sortstr defined in line 40; used 3 times
trailstr defined in line 41; used 4 times
wordhash defined in line 46; used 3 times
words defined in line 45; used 5 times
wordtop defined in line 48; used 7 times

Defined macros

LINELENGTH defined in line 22; used 9 times
MAXDEFS defined in line 23; used 3 times
Last modified: 1985-11-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3300
Valid CSS Valid XHTML 1.0 Strict