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