1 #ifndef lint 2 static char sccsid[] = "@(#)bibargs.c 2.9 06/11/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[120]; /* 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 } 1202