|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.