1 #ifndef lint 2 static char sccsid[] = "@(#)bibargs.c 2.12 11/16/87"; 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(), 730 *fullaabet(), *multfull(); 731 732 getfield("F", field, ref); 733 if (field[0] != 0) 734 for (p = field; *p; p++) 735 *cp++ = *p; 736 else { 737 p = citetemplate; 738 field[0] = 0; 739 while (c = *p++) { 740 if (isalpha(c)) { /* field name */ 741 q = getfield(p-1, field, ref); 742 if (q != 0) { 743 p = q; 744 for (fp = field; *fp; ) 745 *cp++ = *fp++; 746 } 747 } 748 else if (c == '1') { /* numeric order */ 749 sprintf(field,"%d",1 + i); 750 for (fp = field; *fp; ) 751 *cp++ = *fp++; 752 } 753 else if (c == '2') /* alternate alphabetic */ 754 cp = aabet(cp, ref); 755 else if (c == '3') /* Astrophysical Journal style*/ 756 cp = multfull(cp, ref, 3); 757 else if (c == '4') /* Computing Surveys style*/ 758 cp = multfull(cp, ref, 2); 759 else if (c == '8') /* Full alphabetic */ 760 cp = fullaabet(cp, ref); 761 else if (c == '9') /* Last name of Senior Author*/ 762 cp = aabetlast(cp, ref); 763 else if (c == '0') { /* print nothing */ 764 for (fp = field; *fp; ) 765 *cp++ = *fp++; 766 } 767 /* else if (c == '4') here is how to add new styles */ 768 else if (c == '{') { /* other information */ 769 while (*p != '}') 770 if (*p == 0) 771 error("unexpected end of citation template"); 772 else 773 *cp++ = *p++; 774 p++; 775 } 776 else if (c == '<') { 777 while (*p != '>') { 778 if (*p == 0) 779 error("unexpected end of citation template"); 780 else 781 *cp++ = *p++; 782 } 783 p++; 784 } 785 else if (c != '@') 786 *cp++ = c; 787 } 788 } 789 *cp++ = 0; 790 } 791 792 /* alternate alphabetic citation style - 793 if 1 author - first three letters of last name 794 if 2 authors - first two letters of first, followed by first letter of 795 seond 796 if 3 or more authors - first letter of first three authors */ 797 char *aabet(cp, ref) 798 char *cp, ref[]; 799 { char field[REFSIZE], temp[100]; 800 reg char *np, *fp; 801 int j, getname(); 802 803 if (getname(1, field, temp, ref)) { 804 np = cp; 805 fp = field; 806 for (j = 1; j <= 3; j++) 807 if (*fp != 0) 808 *cp++ = *fp++; 809 if (getname(2, field, temp, ref)) 810 np[2] = field[0]; 811 if (getname(3, field, temp, ref)) { 812 np[1] = np[2]; 813 np[2] = field[0]; 814 } 815 } 816 return(cp); 817 } 818 819 /* alternate alphabetic citation style - 820 first two characters of last names of all authors 821 up to max_klen characters. 822 */ 823 char *fullaabet(cp, ref) 824 char *cp, ref[]; 825 { char field[REFSIZE], temp[100]; 826 reg char *fp; 827 char *lastcp; 828 int getname(); 829 int i; 830 831 lastcp = cp + max_klen; 832 for (i= 1; getname(i, field, temp, ref); i++) { 833 for (fp = field; *fp && (fp < &(field[3])); ) 834 if (cp > lastcp) 835 break; 836 else if (isalpha(*fp)) 837 *cp++ = *fp++; 838 else 839 fp++; 840 } 841 return(cp); 842 } 843 844 845 /* alternate alphabetic citation style - 846 entire last name of senior author 847 */ 848 char *aabetlast(cp, ref) 849 char *cp, ref[]; 850 { char field[REFSIZE], temp[100]; 851 reg char *fp; 852 int getname(); 853 854 if (getname(1, field, temp, ref)) { 855 for (fp = field; *fp; ) 856 *cp++ = *fp++; 857 } 858 return(cp); 859 } 860 861 /* 862 Multiple full authors last names (1, 2 or 3 full names). 863 864 If maxauthors<3 865 if 1 author - last name date 866 if 2 authors - last name and last name date 867 if 3 or more authors - last name et al. date 868 If maxauthors>=3 869 if 1 author - last name date 870 if 2 authors - last name and last name date 871 if 3 authors - last name, last name and last name date 872 if 4 or more authors - last name et al. date */ 873 char *multfull(cp, ref, maxauthors) 874 char *cp, ref[]; 875 int maxauthors; 876 { char name1[100], name2[100], name3[100], temp[100]; 877 reg char *fp; 878 int getname(); 879 880 if (getname(1, name1, temp, ref)) { 881 for (fp = name1; *fp; ) 882 *cp++ = *fp++; 883 if (((maxauthors >= 3) && (getname(4, name3, temp, ref))) 884 || ((maxauthors < 3) && (getname(3, name3, temp, ref)))) { 885 for (fp = " \\*(e]"; *fp; ) 886 *cp++ = *fp++; 887 } 888 else if (getname(2, name2, temp, ref)) { 889 if (getname(3, name3, temp, ref)) { 890 for (fp = "\\*(c]"; *fp; ) 891 *cp++ = *fp++; 892 for (fp = name2; *fp; ) 893 *cp++ = *fp++; 894 for (fp = "\\*(m]"; *fp; ) 895 *cp++ = *fp++; 896 for (fp = name3; *fp; ) 897 *cp++ = *fp++; 898 } 899 else { 900 for (fp = "\\*(n]"; *fp; ) 901 *cp++ = *fp++; 902 for (fp = name2; *fp; ) 903 *cp++ = *fp++; 904 } 905 } 906 } 907 return(cp); 908 } 909 910 /* getfield - get a single field from reference */ 911 char *getfield(ptr, field, ref) 912 char *ptr, field[], ref[]; 913 { reg char *p, *q; 914 char temp[100]; 915 int n, len, i, getname(); 916 917 field[0] = 0; 918 if (*ptr == 'A') 919 getname(1, field, temp, ref); 920 else 921 for (p = ref; *p; p++) 922 if (*p == '%' && *(p+1) == *ptr) { 923 for (p = p + 2; *p == ' '; p++) 924 ; 925 for (q = field; (*p != '\n') && (*p != '\0'); ) 926 *q++ = *p++; 927 *q = 0; 928 break; 929 } 930 n = 0; 931 len = strlen(field); 932 if (*++ptr == '-') { 933 for (ptr++; isdigit(*ptr); ptr++) 934 n = 10 * n + (*ptr - '0'); 935 if (n > len) 936 n = 0; 937 else 938 n = len - n; 939 for (i = 0; field[i] = field[i+n]; i++) 940 ; 941 } 942 else if (isdigit(*ptr)) { 943 for (; isdigit(*ptr); ptr++) 944 n = 10 * n + (*ptr - '0'); 945 if (n > len) 946 n = len; 947 field[n] = 0; 948 } 949 950 if (*ptr == 'u') { 951 ptr++; 952 for (p = field; *p; p++) 953 if (islower(*p)) 954 *p = (*p - 'a') + 'A'; 955 } 956 else if (*ptr == 'l') { 957 ptr++; 958 for (p = field; *p; p++) 959 if (isupper(*p)) 960 *p = (*p - 'A') + 'a'; 961 } 962 return(ptr); 963 } 964 965 /* getname - get the nth name field from reference, breaking into 966 first and last names */ 967 int getname(n, last, first, ref) 968 int n; 969 char last[], first[], ref[]; 970 { reg char *p; 971 int m; 972 973 m = n; 974 for (p = ref; *p; p++) 975 if (*p == '%' & *(p+1) == 'A') { 976 n--; 977 if (n == 0) { 978 for (p = p + 2; *p == ' '; p++) ; 979 breakname(p, first, last) ; 980 return(true); 981 } 982 } 983 984 if (n == m) /* no authors, try editors */ 985 for (p = ref; *p; p++) 986 if (*p == '%' & *(p+1) == 'E') { 987 n--; 988 if (n == 0) { 989 for (p = p + 2; *p == ' '; p++) ; 990 breakname(p, first, last) ; 991 return(true); 992 } 993 } 994 995 if (n == m) { /* no editors, either, try institution */ 996 first[0] = last[0] = '\0'; 997 getfield("I", last, ref); 998 if (last[0] != '\0') 999 return(true); 1000 } 1001 1002 return(false); 1003 } 1004 1005 /* disambiguate - compare adjacent citation strings, and if equal, add 1006 single character disambiguators */ 1007 disambiguate() 1008 { reg int i, j; 1009 char adstr; 1010 1011 for (i = 0; i < numrefs-1; i = j) { 1012 j = i + 1; 1013 if (strcmp(refinfo[i].ri_cite, refinfo[j].ri_cite)==0) { 1014 adstr = 'a'; 1015 for(j = i+1; 1016 j<numrefs && strcmp(refinfo[i].ri_cite,refinfo[j].ri_cite) == 0; 1017 j++) { 1018 adstr = 'a' + (j-i); 1019 refinfo[j].ri_disambig[0] = adstr; 1020 } 1021 refinfo[i].ri_disambig[0] = 'a'; 1022 } 1023 } 1024 for (i = 0; i < numrefs; i++){ 1025 strcat(refinfo[i].ri_cite, refinfo[i].ri_disambig); 1026 } 1027 } 1028 1029 1030 /* bldname - build a name field 1031 doing abbreviations, reversals, and caps/small caps 1032 */ 1033 bldname(first, last, name, reverse) 1034 char *first, *last, name[]; 1035 int reverse; 1036 { 1037 char newfirst[120], newlast[120]; 1038 reg char *p, *q, *f, *l; 1039 char *scopy(); 1040 int flag; 1041 1042 if (abbrev) { 1043 p = first; 1044 q = newfirst; 1045 flag = false; 1046 while (*p) { 1047 while (*p == ' ') 1048 p++; 1049 if (*p == 0) 1050 break; 1051 if (isupper(*p)) { 1052 if (flag) /* between initial gap */ 1053 q = scopy(q, "\\*(a]"); 1054 flag = true; 1055 *q++ = *p; 1056 q = scopy(q, "\\*(p]"); 1057 } 1058 if (*++p == '.') 1059 p++; 1060 else while (*p != 0 && ! isspace(*p)) 1061 p++; 1062 } 1063 *q = 0; 1064 f = newfirst; 1065 } 1066 else 1067 f = first; 1068 1069 if (capsmcap) { 1070 p = last; 1071 q = newlast; 1072 flag = 0; /* 1 - printing cap, 2 - printing small */ 1073 while (*p) 1074 if (islower(*p)) { 1075 if (flag != 2) 1076 q = scopy(q, "\\s-2"); 1077 flag = 2; 1078 *q++ = (*p++ - 'a') + 'A'; 1079 } 1080 else { 1081 if (flag == 2) 1082 q = scopy(q,"\\s+2"); 1083 flag = 1; 1084 *q++ = *p++; 1085 } 1086 if (flag == 2) 1087 q = scopy(q, "\\s+2"); 1088 *q = 0; 1089 l = newlast; 1090 } 1091 else 1092 l = last; 1093 1094 if (f[0] == 0) 1095 sprintf(name, "%s\n", l); 1096 else if (reverse) 1097 sprintf(name, "%s\\*(b]%s\n", l, f); 1098 else 1099 sprintf(name, "%s %s\n", f, l); 1100 } 1101 1102 /* prtauth - print author or editor field */ 1103 prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev) 1104 char c, *line; 1105 int num, max, abbrev, capsmcap, numrev; 1106 FILE *ofd; 1107 { char first[LINELENGTH], last[LINELENGTH]; 1108 1109 if (num <= numrev || abbrev || capsmcap) { 1110 breakname(line, first, last); 1111 bldname(first, last, line, num <= numrev); 1112 } 1113 if (num == 1) 1114 fprintf(ofd,".ds [%c %s", c, line); 1115 else if (num < max) 1116 fprintf(ofd,".as [%c \\*(c]%s", c, line); 1117 else if (max == 2) 1118 fprintf(ofd,".as [%c \\*(n]%s", c, line); 1119 else 1120 fprintf(ofd,".as [%c \\*(m]%s", c, line); 1121 if (num == max && index(trailstr, c)) 1122 fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]); 1123 } 1124 1125 /* doline - actually print out a line of reference information */ 1126 doline(c, line, numauths, maxauths, numeds, maxeds, ofd) 1127 char c, *line; 1128 int numauths, maxauths, numeds, maxeds; 1129 FILE *ofd; 1130 { 1131 1132 switch(c) { 1133 case 'A': 1134 prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev); 1135 break; 1136 1137 case 'E': 1138 prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, ednumrev); 1139 if (numeds == maxeds) 1140 fprintf(ofd,".nr [E %d\n", maxeds); 1141 break; 1142 1143 case 'P': 1144 if (index(line, '-')) 1145 fprintf(ofd,".nr [P 1\n"); 1146 else 1147 fprintf(ofd,".nr [P 0\n"); 1148 fprintf(ofd,".ds [P %s",line); 1149 if (index(trailstr, 'P')) 1150 fprintf(ofd,".ds ]P %c\n",line[strlen(line)-2]); 1151 break; 1152 1153 case 'F': 1154 case 'K': break; 1155 1156 default: 1157 fprintf(ofd,".ds [%c %s", c, line); 1158 if (index(trailstr, c)) 1159 fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]); 1160 } 1161 } 1162 1163 /* dumpref - dump reference number i */ 1164 dumpref(i, ofd) 1165 int i; 1166 FILE *ofd; 1167 { char ref[REFSIZE], line[REFSIZE]; 1168 reg char *p, *q; 1169 char *from; 1170 int numauths, maxauths, numeds, maxeds; 1171 1172 if ( i < 0 ) ref[0] = 0; /* ref not found */ 1173 else { 1174 rdref(&refinfo[i], ref); 1175 maxauths = maxeds = 0; 1176 numauths = numeds = 0; 1177 for (p = ref; *p; p++) 1178 if (*p == '%') 1179 if (*(p+1) == 'A') maxauths++; 1180 else if (*(p+1) == 'E') maxeds++; 1181 fprintf(ofd, ".[-\n"); 1182 fprintf(ofd, ".ds [F %s\n", refinfo[i].ri_cite); 1183 #ifndef INCORE 1184 fseek(rfd, (long)refinfo[i].ri_pos, 0); 1185 while (fgets(line, REFSIZE, rfd) != NULL) { 1186 #else INCORE 1187 for (q = line, from = refinfo[i].ri_ref; *from; /*VOID*/) { /*} */ 1188 if (*from == '\n'){ 1189 *q++ = '\n'; 1190 *q = 0; 1191 q = line; 1192 from++; 1193 } else { 1194 *q++ = *from++; 1195 continue; 1196 } 1197 #endif INCORE 1198 switch(line[0]){ 1199 case 0: 1200 goto doneref; 1201 case '.': 1202 fprintf(ofd, "%s", line); 1203 break; 1204 case '%': 1205 switch(line[1]){ 1206 case 'A': numauths++; break; 1207 case 'E': numeds++; break; 1208 } 1209 for (p = &line[2]; *p == ' '; p++) /*VOID*/; 1210 doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd); 1211 } 1212 } 1213 doneref:; 1214 fprintf(ofd,".][\n"); 1215 } 1216 } 1217