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