xref: /csrg-svn/contrib/bib/src/bib.c (revision 13109)
1*13109Srrh #ifndef lint
2*13109Srrh static char sccsid[] = "@(#)bib.c	1.4	06/14/83";
3*13109Srrh #endif not lint
4*13109Srrh 
512909Sgarrison /*
612909Sgarrison    bib - bibliographic formatter
712909Sgarrison          timothy a. budd, 1/82
812909Sgarrison          lookup routines supplied by gary levin 2/82
912909Sgarrison          reworked several new features added, 11/82.
1012909Sgarrison */
1112909Sgarrison # include <stdio.h>
1212909Sgarrison # include <ctype.h>
1312909Sgarrison # include "bib.h"
1412909Sgarrison 
1512909Sgarrison # define HUNTSIZE 512                /* maximum size of hunt string         */
1612909Sgarrison # define MAXFIELD 250                /* maximum field length                */
1712909Sgarrison # define MAXREFS  300                /* maximum number of references        */
1812909Sgarrison # define MAXATONCE 35                /* maximum references at one location  */
1912909Sgarrison 
2012909Sgarrison # define getch(c,fd) (c = getc(fd))
2112909Sgarrison # define echoc(c,ifd,ofd) (getch(c,ifd) == EOF ? c : putc(c,ofd))
2212909Sgarrison # define testc(c,d,ifd,ofd) (getch(c, ifd) == d ? putc(c, ofd) : 0)
2312909Sgarrison 
2412909Sgarrison /* global variables */
2512909Sgarrison    FILE *rfd;                   /* reference temporary file              */
2612909Sgarrison    char reffile[] = TMPREFFILE ;/* temporary file (see bib.h)            */
2712909Sgarrison    long int refspos[MAXREFS];   /* reference seek positions              */
2812909Sgarrison    long int rend = 1;           /* last position in rfd (first char unused)*/
2912909Sgarrison    int numrefs = -1;            /* number of references generated so far */
3012909Sgarrison    FILE *tfd;                   /* output of pass 1 of file(s)           */
3112909Sgarrison    char tmpfile[] = TMPTEXTFILE ; /* output of pass 1                    */
3212909Sgarrison    char common[] = COMFILE ;    /* common word file                      */
3312909Sgarrison    char *citestr[MAXREFS];      /* citation strings                      */
3412909Sgarrison    int  findex = false;         /* can we read the file INDEX ?          */
3512909Sgarrison 
3612909Sgarrison /* global variables in bibargs */
3712909Sgarrison    extern int foot, sort, personal;
3812909Sgarrison    extern int hyphen, ordcite;
3912909Sgarrison    extern char sortstr[], pfile[], citetemplate[];
4013107Srrh    char *bibfname;		/* file name currently reading */
4113107Srrh    char *biblineno;		/* line number in that file */
4212909Sgarrison 
4312909Sgarrison 
4412909Sgarrison main(argc, argv)
4512909Sgarrison    int argc;
4612909Sgarrison    char **argv;
4712909Sgarrison {  int rcomp();
4812909Sgarrison 
4912909Sgarrison    /* the file INDEX in the current directory is the default index,
5012909Sgarrison       if it is present */
5112909Sgarrison 
5212909Sgarrison    rfd = fopen( INDXFILE , "r");
5312909Sgarrison    if (rfd != NULL) {
5412909Sgarrison       findex = true;
5512909Sgarrison       fclose(rfd);
5612909Sgarrison       }
5712909Sgarrison 
5812909Sgarrison    /* open temporaries, reffile will contain references collected in
5912909Sgarrison       pass 1, and tmpfile will contain text.
6012909Sgarrison    */
6112909Sgarrison    mktemp(reffile);
6212909Sgarrison    rfd = fopen(reffile,"w+");
6312909Sgarrison    if (rfd == NULL)
6412909Sgarrison       error("can't open temporary reference file");
6512909Sgarrison    mktemp(tmpfile);
6612909Sgarrison    tfd = fopen(tmpfile,"w");
6712909Sgarrison    if (tfd == NULL)
6812909Sgarrison       error("can't open temporary output file");
6912909Sgarrison 
7012909Sgarrison     /*
7112909Sgarrison        pass1 - read files, looking for citations
7212909Sgarrison                arguments are read by doargs (bibargs.c)
7312909Sgarrison     */
7412909Sgarrison 
7513107Srrh    if (doargs(argc, argv, DEFSTYLE ) == 0){
7613107Srrh       bibfname = "<stdin>";
7712909Sgarrison       rdtext(stdin);
7813107Srrh    }
7912909Sgarrison 
8012909Sgarrison    /*
8112909Sgarrison     sort references, make citations, add disambiguating characters
8212909Sgarrison    */
8312909Sgarrison 
8412909Sgarrison    if (sort)
8512909Sgarrison       qsort(refspos, numrefs+1, sizeof(long), rcomp);
8612909Sgarrison    makecites(citestr);
8712909Sgarrison    disambiguate();
8812909Sgarrison 
8912909Sgarrison    /*
9012909Sgarrison    reopen temporaries
9112909Sgarrison    */
9212909Sgarrison 
9312909Sgarrison    fclose(tfd);
9412909Sgarrison    tfd = fopen(tmpfile,"r");
9512909Sgarrison    if (tfd == NULL)
9612909Sgarrison       error("can't open temporary output file for reading");
9712909Sgarrison 
9812909Sgarrison    /*
9912909Sgarrison    pass 2 - reread files, replacing references
10012909Sgarrison    */
10112909Sgarrison 
10212909Sgarrison    pass2(tfd, stdout);
10312909Sgarrison 
10412909Sgarrison    /*
10512909Sgarrison    clean up
10612909Sgarrison    */
10712909Sgarrison 
10812909Sgarrison    fclose(tfd);
10912909Sgarrison    fclose(rfd);
11012909Sgarrison    unlink(tmpfile);
11112909Sgarrison    unlink(reffile);
11212909Sgarrison    exit(0);
11312909Sgarrison }
11412909Sgarrison 
11512909Sgarrison /* rdtext - read and process a text file, looking for [. commands */
11612909Sgarrison    rdtext(fd)
11712909Sgarrison    FILE *fd;
11812909Sgarrison {  char lastc, c, d;
11912909Sgarrison 
12013107Srrh    biblineno = 0;
12112909Sgarrison    lastc = 0;
12212909Sgarrison    while (getch(c, fd) != EOF)
12312909Sgarrison       if (c == '[' || c == '{')
12412909Sgarrison          if (getch(d, fd) == '.') { /* found a reference */
12512909Sgarrison             if (c == '{') { if (lastc) putc(lastc, tfd);}
12612909Sgarrison             else
12712960Sgarrison 	       switch (lastc) {
12812960Sgarrison 	       case ' ': fputs("\\*([<", tfd);
12912960Sgarrison 			 break;
13012960Sgarrison                case '.': fputs("\\*([.", tfd);
13112960Sgarrison 			 break;
13212960Sgarrison                case ',': fputs("\\*([,", tfd);
13312960Sgarrison 			 break;
13412960Sgarrison                case '?': fputs("\\*([?", tfd);
13512960Sgarrison 			 break;
13612960Sgarrison                case ':': fputs("\\*([:", tfd);
13712960Sgarrison 			 break;
13812960Sgarrison                case ';': fputs("\\*([;", tfd);
13912960Sgarrison 			 break;
14012960Sgarrison                case '!': fputs("\\*([!", tfd);
14112960Sgarrison 			 break;
14212960Sgarrison                case '"': fputs("\\*([\"", tfd);
14312960Sgarrison 			 break;
14412960Sgarrison                case '\'': fputs("\\*(['", tfd);
14512960Sgarrison 			 break;
14612960Sgarrison 	       default : putc(lastc, tfd);
14712960Sgarrison 			 break;
14812960Sgarrison 	       }
14912909Sgarrison             rdcite(fd, c);
15012909Sgarrison             if (c == '[')
15112960Sgarrison 	       switch (lastc) {
15212960Sgarrison 	       case ' ': fputs("\\*(<]", tfd);
15312960Sgarrison 			 break;
15412960Sgarrison                case '.': fputs("\\*(.]", tfd);
15512960Sgarrison 			 break;
15612960Sgarrison                case ',': fputs("\\*(,]", tfd);
15712960Sgarrison 			 break;
15812960Sgarrison                case '?': fputs("\\*(?]", tfd);
15912960Sgarrison 			 break;
16012960Sgarrison                case ':': fputs("\\*(:]", tfd);
16112960Sgarrison 			 break;
16212960Sgarrison                case ';': fputs("\\*(;]", tfd);
16312960Sgarrison 			 break;
16412960Sgarrison                case '!': fputs("\\*(!]", tfd);
16512960Sgarrison 			 break;
16612960Sgarrison                case '"': fputs("\\*(\"]", tfd);
16712960Sgarrison 			 break;
16812960Sgarrison                case '\'': fputs("\\*(']", tfd);
16912960Sgarrison 			 break;
17012960Sgarrison 	       }
17112909Sgarrison             lastc = 0;
17212909Sgarrison             }
17312909Sgarrison          else {
17412909Sgarrison             if (lastc) putc(lastc, tfd);
17512909Sgarrison             ungetc(d, fd);
17612909Sgarrison             lastc = c;
17712909Sgarrison             }
17812909Sgarrison       else {
17912909Sgarrison          if (lastc) putc(lastc, tfd);
18012909Sgarrison          lastc = c;
18113107Srrh 	 if (c == '\n')
18213107Srrh 		biblineno++;
18312909Sgarrison          }
18412909Sgarrison    if (lastc) putc(lastc, tfd);
18512909Sgarrison }
18612909Sgarrison 
18712909Sgarrison /* rdcite - read citation information inside a [. command */
18812909Sgarrison    rdcite(fd, ch)
18912909Sgarrison    FILE *fd;
19012909Sgarrison    char ch;
19112909Sgarrison {  long int n, getref();
19212909Sgarrison    char huntstr[HUNTSIZE], c, info[HUNTSIZE];
19312909Sgarrison 
19412909Sgarrison    if (ch == '[')
19512909Sgarrison       fputs("\\*([[", tfd);
19612909Sgarrison    else
19712909Sgarrison       fputs("\\*([{", tfd);
19812909Sgarrison    huntstr[0] = info[0] = 0;
19912909Sgarrison    while (getch(c, fd) != EOF)
20012909Sgarrison       switch (c) {
20112909Sgarrison          case ',':
20212909Sgarrison             n = getref(huntstr);
20312909Sgarrison             if (n > 0)
20412909Sgarrison                fprintf(tfd, "%c%ld%c%s%c", CITEMARK, n, CITEMARK, info, CITEEND);
20512909Sgarrison             else
20612909Sgarrison                fprintf(tfd, "%c0%c%s%s%c", CITEMARK, CITEMARK,
20712909Sgarrison                                            huntstr, info, CITEEND);
20812909Sgarrison             huntstr[0] = info[0] = 0;
20912909Sgarrison             break;
21012909Sgarrison 
21112909Sgarrison          case '.':
21212909Sgarrison             while (getch(c, fd) == '.') ;
21312909Sgarrison             if (c == ']') {
21412909Sgarrison                n = getref(huntstr);
21512909Sgarrison                if (n > 0)
21612909Sgarrison                   fprintf(tfd, "%c%ld%c%s%c\\*(]]", CITEMARK, n,
21712909Sgarrison                                                   CITEMARK, info, CITEEND);
21812909Sgarrison                else
21912909Sgarrison                   fprintf(tfd, "%c0%c%s%s%c\\*(]]", CITEMARK, CITEMARK,
22012909Sgarrison                                               huntstr, info, CITEEND);
22112909Sgarrison                return;
22212909Sgarrison                }
22312909Sgarrison             else if (c == '}') {
22412909Sgarrison                n = getref(huntstr);
22512909Sgarrison                if (n > 0)
22612909Sgarrison                   fprintf(tfd, "%c%ld%c%s%c\\*(}]", CITEMARK, n,
22712909Sgarrison                                                     CITEMARK, info, CITEEND);
22812909Sgarrison                else
22912909Sgarrison                   fprintf(tfd, "%c0%c%s%s%c\\*(}]", CITEMARK, CITEMARK,
23012909Sgarrison                                               huntstr, info, CITEEND);
23112909Sgarrison                return;
23212909Sgarrison                }
23312909Sgarrison             else
23412909Sgarrison                addc(huntstr, c);
23512909Sgarrison             break;
23612909Sgarrison 
23712909Sgarrison          case '{':
23812909Sgarrison             while (getch(c, fd) != '}')
23912909Sgarrison                if (c == EOF) {
24012909Sgarrison                   fprintf(stderr, "Error: ill formed reference\n");
24112909Sgarrison                   exit(1);
24212909Sgarrison                   }
24312909Sgarrison                 else
24412909Sgarrison                   addc(info, c);
24512909Sgarrison             break;
24612909Sgarrison 
24712909Sgarrison          case '\n':
24812909Sgarrison          case '\t':
24912909Sgarrison             c = ' ';   /* fall through */
25012909Sgarrison 
25112909Sgarrison          default:
25212909Sgarrison             addc(huntstr,c);
25312909Sgarrison          }
25412909Sgarrison    error("end of file reading citation");
25512909Sgarrison }
25612909Sgarrison 
25712909Sgarrison /* addc - add a character to hunt string */
25812909Sgarrison    addc(huntstr, c)
25912909Sgarrison    char huntstr[HUNTSIZE], c;
26012909Sgarrison {  int  i;
26112909Sgarrison 
26212909Sgarrison    i = strlen(huntstr);
26312909Sgarrison    if (i > HUNTSIZE)
26412909Sgarrison       error("citation too long");
26512909Sgarrison    huntstr[i] = c;
26612909Sgarrison    huntstr[i+1] = 0;
26712909Sgarrison }
26812909Sgarrison 
26912909Sgarrison /* getref - if an item was already referenced, return its pointer in
27012909Sgarrison                 the reference file, otherwise create a new entry */
27112909Sgarrison    long int getref(huntstr)
27212909Sgarrison    char huntstr[HUNTSIZE];
27312909Sgarrison {  char rf[REFSIZE], ref[REFSIZE], *r, *hunt();
27412909Sgarrison    int  i, match(), getwrd();
27512909Sgarrison 
27612909Sgarrison    r = hunt(huntstr);
27712909Sgarrison    if (r != NULL) {
27812909Sgarrison       /* exapand defined string */
27912909Sgarrison       strcpy(rf, r);
28012909Sgarrison       free(r);
28112909Sgarrison       expand(rf);
28212909Sgarrison 
28312909Sgarrison       /* see if reference has already been cited */
28412909Sgarrison 
28512909Sgarrison       if (foot == false)
28612909Sgarrison          for (i = 0; i <= numrefs; i++) {
28712909Sgarrison              rdref(refspos[i], ref);
28812909Sgarrison              if (strcmp(ref, rf) == 0)
28912909Sgarrison                 return(refspos[i]);
29012909Sgarrison           }
29112909Sgarrison 
29212909Sgarrison       /* didn't match any existing reference, create new one */
29312909Sgarrison 
29412909Sgarrison       numrefs++;
29512909Sgarrison       refspos[numrefs] = rend;
29612909Sgarrison       fseek(rfd, rend, 0);
29712909Sgarrison       i = strlen(rf) + 1;
29812909Sgarrison       fwrite(rf, 1, i, rfd);
29912909Sgarrison       rend = rend + i;
30012909Sgarrison       return(refspos[numrefs]);
30112909Sgarrison       }
30212909Sgarrison    else {
30313107Srrh       bibwarning("no reference matching %s\n", huntstr);
30412909Sgarrison       return( (long) -1 );
30512909Sgarrison       }
30612909Sgarrison }
30712909Sgarrison 
30812909Sgarrison /* rdref - read text for an already cited reference */
30912909Sgarrison    rdref(i, ref)
31012909Sgarrison    long int  i;
31112909Sgarrison    char ref[REFSIZE];
31212909Sgarrison {
31312909Sgarrison    ref[0] = 0;
31412909Sgarrison    fseek(rfd, i, 0);
31512909Sgarrison    fread(ref, 1, REFSIZE, rfd);
31612909Sgarrison }
31712909Sgarrison 
31812909Sgarrison /* hunt - hunt for reference from either personal or system index */
31912909Sgarrison    char *hunt(huntstr)
32012909Sgarrison    char huntstr[];
32112909Sgarrison {  char *fhunt(), *r, *p, *q, fname[120];
32212909Sgarrison 
32312909Sgarrison    if (personal) {
32412909Sgarrison       for (p = fname, q = pfile; ; q++)
32512909Sgarrison          if (*q == ',' || *q == 0) {
32612909Sgarrison             *p = 0;
32712909Sgarrison             if ((r = fhunt(fname, huntstr)) != NULL)
32812909Sgarrison                return(r);
32912909Sgarrison             else if (*q == 0)
33012909Sgarrison                break;
33112909Sgarrison             p = fname;
33212909Sgarrison             }
33312909Sgarrison          else *p++ = *q;
33412909Sgarrison       }
33512909Sgarrison    else if (findex) {
33612909Sgarrison       if ((r = fhunt( INDXFILE , huntstr)) != NULL)
33712909Sgarrison          return(r);
33812909Sgarrison       }
33912909Sgarrison    if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
34012909Sgarrison       return(r);
34112909Sgarrison    return(NULL);
34212909Sgarrison }
34312909Sgarrison 
34412909Sgarrison /* fhunt - hunt from a specific file */
34512909Sgarrison    char *fhunt(file, huntstr)
34612909Sgarrison    char file[], huntstr[];
34712909Sgarrison {  char *p, *r, *locate();
34812909Sgarrison 
34912909Sgarrison    r = locate(huntstr, file, 6, common);
35012909Sgarrison 
35112909Sgarrison    if (r == NULL)
35212909Sgarrison       return(NULL);  /* error */
35312909Sgarrison    if (*r == 0)
35412909Sgarrison       return(NULL);  /* no match */
35512909Sgarrison 
35612909Sgarrison    for (p = r; *p; p++)
35712909Sgarrison       if (*p == '\n')
35812909Sgarrison          if (*(p+1) == '\n') { /* end */
35912909Sgarrison             if (*(p+2) != 0)
36013107Srrh                bibwarning("multiple references match %s\n", huntstr);
36112909Sgarrison             *(p+1) = 0;
36212909Sgarrison             break;
36312909Sgarrison             }
36412909Sgarrison          else if (*(p+1) != '%' && *(p+1) != '.') /* unnecessary newline */
36512909Sgarrison             *p = ' ';
36612909Sgarrison    return(r);
36712909Sgarrison }
36812909Sgarrison 
36912909Sgarrison /* rcomp - reference comparison routine for qsort utility */
37012909Sgarrison    int rcomp(ap, bp)
37112909Sgarrison    long int *ap, *bp;
37212909Sgarrison {  char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD];
37312909Sgarrison    char *p, *q, *getfield();
37412909Sgarrison    int  neg, res;
37512960Sgarrison    int  fields_found;
37612909Sgarrison 
37712909Sgarrison    rdref(*ap, ref1);
37812909Sgarrison    rdref(*bp, ref2);
37912909Sgarrison    for (p = sortstr; *p; p = q) {
38012909Sgarrison       if (*p == '-') {
38112909Sgarrison          p++;
38212909Sgarrison          neg = true;
38312909Sgarrison          }
38412909Sgarrison       else
38512909Sgarrison          neg = false;
38612909Sgarrison       q = getfield(p, field1, ref1);
38712960Sgarrison       fields_found = true;
38812960Sgarrison       if (q == 0) {
38912960Sgarrison 	 res = 1;
39012960Sgarrison 	 fields_found = false;
39112960Sgarrison       } else if (strcmp (field1, "") == 0) {	/* field not found */
39212909Sgarrison          if (*p == 'A') {
39312960Sgarrison             getfield("F", field1, ref1);
39412960Sgarrison 	    if (strcmp (field1, "") == 0) {
39512960Sgarrison                getfield("I", field1, ref1);
39612960Sgarrison 	       if (strcmp (field1, "") == 0) {
39712960Sgarrison 	          res = 1;
39812960Sgarrison 		  fields_found = false;
39912960Sgarrison 	       }
40012960Sgarrison 	    }
40112960Sgarrison 	 } else {
40212960Sgarrison 	    res = 1;
40312960Sgarrison 	    fields_found = false;
40412960Sgarrison 	 }
40512960Sgarrison       }
40612960Sgarrison 
40712960Sgarrison       if (getfield(p, field2, ref2) == 0) {
40812960Sgarrison 	 res = -1;
40912960Sgarrison 	 fields_found = false;
41012960Sgarrison       } else if (strcmp (field2, "") == 0) {	/* field not found */
41112960Sgarrison          if (*p == 'A') {
41212960Sgarrison             getfield("F", field2, ref2);
41312960Sgarrison 	    if (strcmp (field2, "") == 0) {
41412960Sgarrison                getfield("I", field2, ref2);
41512960Sgarrison 	       if (strcmp (field2, "") == 0) {
41612960Sgarrison 	          res = -1;
41712960Sgarrison 		  fields_found = false;
41812960Sgarrison 	       }
41912960Sgarrison 	    }
42012960Sgarrison 	 } else {
42112960Sgarrison 	    res = -1;
42212960Sgarrison 	    fields_found = false;
42312960Sgarrison 	 }
42412960Sgarrison       }
42512960Sgarrison       if (fields_found) {
42612960Sgarrison          if (*p == 'A') {
42712909Sgarrison             if (isupper(field1[0]))
42812909Sgarrison                field1[0] -= 'A' - 'a';
42912909Sgarrison             if (isupper(field2[0]))
43012909Sgarrison                field2[0] -= 'A' - 'a';
43112909Sgarrison             }
43212909Sgarrison          res = strcmp(field1, field2);
43312909Sgarrison          }
43412909Sgarrison       if (neg)
43512909Sgarrison          res = - res;
43612909Sgarrison       if (res != 0)
43712909Sgarrison          break;
43812909Sgarrison       }
43912909Sgarrison    if (res == 0)
44012909Sgarrison       if (ap < bp)
44112909Sgarrison          res = -1;
44212909Sgarrison       else
44312909Sgarrison          res = 1;
44412909Sgarrison    return(res);
44512909Sgarrison }
44612909Sgarrison 
44712909Sgarrison /* makecites - make citation strings */
44812909Sgarrison    makecites(citestr)
44912909Sgarrison    char *citestr[];
45012909Sgarrison {  char ref[REFSIZE], tempcite[100], *malloc();
45112909Sgarrison    int  i;
45212909Sgarrison 
45312909Sgarrison    for (i = 0; i <= numrefs; i++) {
45412909Sgarrison       rdref(refspos[i], ref);
45512909Sgarrison       bldcite(tempcite, i, ref);
45612909Sgarrison       citestr[i] = malloc(2 + strlen(tempcite)); /* leave room for disambig */
45712909Sgarrison       if (citestr[i] == NULL)
45812909Sgarrison          error("out of storage");
45912909Sgarrison       strcpy(citestr[i], tempcite);
46012909Sgarrison       }
46112909Sgarrison }
46212909Sgarrison 
46312909Sgarrison /* bldcite - build a single citation string */
46412909Sgarrison    bldcite(cp, i, ref)
46512909Sgarrison    char *cp, ref[];
46612909Sgarrison    int  i;
46712909Sgarrison {  char *p, *q, c, *fp, *np, field[REFSIZE], temp[100], *getfield();
46812909Sgarrison    int  j;
46912909Sgarrison 
47012909Sgarrison    getfield("F", field, ref);
47112909Sgarrison    if (field[0] != 0)
47212909Sgarrison       for (p = field; *p; p++)
47312909Sgarrison          *cp++ = *p;
47412909Sgarrison    else {
47512909Sgarrison       p = citetemplate;
47612909Sgarrison       field[0] = 0;
47712909Sgarrison       while (c = *p++)
47812909Sgarrison          if (isalpha(c)) {
47912909Sgarrison             q = getfield(p-1, field, ref);
48012909Sgarrison             if (q != 0) {
48112909Sgarrison                p = q;
48212909Sgarrison                for (fp = field; *fp; )
48312909Sgarrison                   *cp++ = *fp++;
48412909Sgarrison                }
48512909Sgarrison             }
48612909Sgarrison          else if (c == '1') {
48712909Sgarrison             sprintf(field,"%d",1 + i);
48812909Sgarrison             for (fp = field; *fp; )
48912909Sgarrison                *cp++ = *fp++;
49012909Sgarrison             }
49112909Sgarrison          else if (c == '2') {
49212909Sgarrison             if (getname(1, field, temp, ref)) {
49312909Sgarrison                np = cp;
49412909Sgarrison                fp = field;
49512909Sgarrison                for (j = 1; j <= 3; j++)
49612909Sgarrison                   if (*fp != 0)
49712909Sgarrison                      *cp++ = *fp++;
49812909Sgarrison                if (getname(2, field, temp, ref))
49912909Sgarrison                   np[2] = field[0];
50012909Sgarrison                if (getname(3, field, temp, ref)) {
50112909Sgarrison                   np[1] = np[2];
50212909Sgarrison                   np[2] = field[0];
50312909Sgarrison                   }
50412909Sgarrison                }
50512909Sgarrison             }
50612909Sgarrison          else if (c == '{') {
50712909Sgarrison             while (*p ^= '}')
50812909Sgarrison                if (*p == 0)
50912909Sgarrison                   error("unexpected end of citation template");
51012909Sgarrison                else
51112909Sgarrison                   *cp++ = *p++;
51212909Sgarrison             p++;
51312909Sgarrison             }
51412909Sgarrison          else if (c == '<') {
51512909Sgarrison             while (*p ^= '>')
51612909Sgarrison                if (*p == 0)
51712909Sgarrison                   error("unexpected end of citation template");
51812909Sgarrison                else
51912909Sgarrison                   *cp++ = *p++;
52012909Sgarrison             p++;
52112909Sgarrison             }
52212909Sgarrison          else if (c != '@')
52312909Sgarrison             *cp++ = c;
52412909Sgarrison       }
52512909Sgarrison    *cp++ = 0;
52612909Sgarrison }
52712909Sgarrison 
52812909Sgarrison /* getfield - get a single field from reference */
52912909Sgarrison    char *getfield(ptr, field, ref)
53012909Sgarrison    char *ptr, field[], ref[];
53112909Sgarrison {  char *p, *q, temp[100];
53212909Sgarrison    int  n, len, i, getname();
53312909Sgarrison 
53412909Sgarrison    field[0] = 0;
53512909Sgarrison    if (*ptr == 'A')
53612909Sgarrison       getname(1, field, temp, ref);
53712909Sgarrison    else
53812909Sgarrison       for (p = ref; *p; p++)
53912909Sgarrison          if (*p == '%' && *(p+1) == *ptr) {
54012909Sgarrison             for (p = p + 2; *p == ' '; p++)
54112909Sgarrison                ;
54212909Sgarrison             for (q = field; *p != '\n'; )
54312909Sgarrison                *q++ = *p++;
54412909Sgarrison             *q = 0;
54512909Sgarrison             break;
54612909Sgarrison             }
54712909Sgarrison    n = 0;
54812909Sgarrison    len = strlen(field);
54912909Sgarrison    if (*++ptr == '-') {
55012909Sgarrison       for (ptr++; isdigit(*ptr); ptr++)
55112909Sgarrison          n = 10 * n + (*ptr - '0');
55212909Sgarrison       if (n > len)
55312909Sgarrison          n = 0;
55412909Sgarrison       else
55512909Sgarrison          n = len - n;
55612909Sgarrison       for (i = 0; field[i] = field[i+n]; i++)
55712909Sgarrison          ;
55812909Sgarrison       }
55912909Sgarrison    else if (isdigit(*ptr)) {
56012909Sgarrison       for (; isdigit(*ptr); ptr++)
56112909Sgarrison          n = 10 * n + (*ptr - '0');
56212909Sgarrison       if (n > len)
56312909Sgarrison          n = len;
56412909Sgarrison       field[n] = 0;
56512909Sgarrison       }
56612909Sgarrison 
56712909Sgarrison    if (*ptr == 'u') {
56812909Sgarrison       ptr++;
56912909Sgarrison       for (p = field; *p; p++)
57012909Sgarrison          if (islower(*p))
57112909Sgarrison             *p = (*p - 'a') + 'A';
57212909Sgarrison       }
57312909Sgarrison    else if (*ptr == 'l') {
57412909Sgarrison       ptr++;
57512909Sgarrison       for (p = field; *p; p++)
57612909Sgarrison          if (isupper(*p))
57712909Sgarrison             *p = (*p - 'A') + 'a';
57812909Sgarrison       }
57912909Sgarrison    return(ptr);
58012909Sgarrison }
58112909Sgarrison 
58212909Sgarrison /* getname - get the nth name field from reference, breaking into
58312909Sgarrison              first and last names */
58412909Sgarrison    int getname(n, last, first, ref)
58512909Sgarrison    int  n;
58612909Sgarrison    char last[], first[], ref[];
58712909Sgarrison {  char *p;
58812909Sgarrison 
58912909Sgarrison    for (p = ref; *p; p++)
59012960Sgarrison       if (*p == '%' & (*(p+1) == 'A' || *(p+1) == 'E')) {
59112909Sgarrison          n--;
59212909Sgarrison          if (n == 0) {
59312909Sgarrison             for (p = p + 2; *p == ' '; p++) ;
59412909Sgarrison             breakname(p, first, last) ;
59512909Sgarrison             return(true);
59612909Sgarrison             }
59712909Sgarrison          }
59812909Sgarrison    return(false);
59912909Sgarrison }
60012909Sgarrison 
60112909Sgarrison /* disambiguate - compare adjacent citation strings, and if equal, add
60212909Sgarrison                   single character disambiguators */
60312909Sgarrison    disambiguate()
60412909Sgarrison {  int i, j;
60512909Sgarrison    char adstr[2];
60612909Sgarrison 
60712909Sgarrison    for (i = 0; i < numrefs; i = j) {
60812909Sgarrison       j = i + 1;
60912909Sgarrison       if (strcmp(citestr[i], citestr[j])==0) {
61012909Sgarrison          adstr[0] = 'a'; adstr[1] = 0;
61112909Sgarrison          for (j = i+1; strcmp(citestr[i],citestr[j]) == 0; j++) {
61212909Sgarrison             adstr[0] = 'a' + (j-i);
61312909Sgarrison             strcat(citestr[j], adstr);
61412909Sgarrison             if (j == numrefs)
61512909Sgarrison                break;
61612909Sgarrison             }
61712909Sgarrison          adstr[0] = 'a';
61812909Sgarrison          strcat(citestr[i], adstr);
61912909Sgarrison          }
62012909Sgarrison      }
62112909Sgarrison }
62212909Sgarrison 
62312909Sgarrison /* putrefs - gather contiguous references together, sort them if called
62412909Sgarrison    for, hyphenate if necessary, and dump them out */
62512909Sgarrison int putrefs(ifd, ofd, footrefs, fn)
62612909Sgarrison FILE *ifd, *ofd;
62712909Sgarrison int  fn, footrefs[];
62812909Sgarrison {  int  citenums[MAXATONCE];   /* reference numbers */
62912909Sgarrison    char *citeinfo[MAXATONCE];  /* reference information */
63012909Sgarrison    char infoword[HUNTSIZE];    /* information line */
63112909Sgarrison    int  rtop, n, i, j;         /* number of citations being dumped */
63212909Sgarrison    char c, *p, *walloc();
63312909Sgarrison 
63412909Sgarrison /* first gather contiguous references together, and order them if
63512909Sgarrison    required      */
63612909Sgarrison 
63712909Sgarrison    rtop = -1;
63812909Sgarrison    do {
63912909Sgarrison       n = 0;
64012909Sgarrison       while (isdigit(getch(c, ifd)))
64112909Sgarrison          n = 10 * n + (c - '0');
64212909Sgarrison       if (c ^= CITEMARK)
64312909Sgarrison          error("inconsistant citation found in pass two");
64412909Sgarrison       if (n == 0) {     /* reference not found */
64512909Sgarrison          rtop++;
64612909Sgarrison          j = rtop;
64712909Sgarrison          citenums[j] = -1;
64812909Sgarrison          citeinfo[j] = 0;
64912909Sgarrison          }
65012909Sgarrison       else {
65112909Sgarrison          for (i = 0; i <= numrefs; i++)
65212909Sgarrison             if (refspos[i] == n) { /* its the ith item in reference list */
65312909Sgarrison                rtop++;
65412909Sgarrison                j = rtop;
65512909Sgarrison                if (ordcite)
65612909Sgarrison                   for ( ; j > 0 && citenums[j-1] > i; j--) {
65712909Sgarrison                      citenums[j] = citenums[j-1];
65812909Sgarrison                      citeinfo[j] = citeinfo[j-1];
65912909Sgarrison                      }
66012909Sgarrison                citenums[j] = i;
66112909Sgarrison                citeinfo[j] = 0;
66212909Sgarrison                break;
66312909Sgarrison                }
66412909Sgarrison          if (i > numrefs)
66512909Sgarrison             error("citation not found in pass two");
66612909Sgarrison          }
66712909Sgarrison       if (getch(c, ifd) != CITEEND) {
66812909Sgarrison          for (p = infoword; c != CITEEND ; ) {
66912909Sgarrison             *p++ = c;
67012909Sgarrison             getch(c, ifd);
67112909Sgarrison             }
67212909Sgarrison          *p = 0;
67312909Sgarrison          citeinfo[j] = walloc(infoword);
67412909Sgarrison          }
67512909Sgarrison       getch(c, ifd);
67612909Sgarrison       }  while (c == CITEMARK);
67712909Sgarrison    ungetc(c, ifd);
67812909Sgarrison 
67912909Sgarrison    /* now dump out values */
68012909Sgarrison    for (i = 0; i <= rtop; i++) {
68112909Sgarrison       if (citenums[i] >= 0)
68212909Sgarrison          fputs(citestr[citenums[i]], ofd);
68312909Sgarrison       if (citeinfo[i]) {
68412909Sgarrison          fputs(citeinfo[i], ofd);
68512909Sgarrison          free(citeinfo[i]);
68612909Sgarrison          }
68712909Sgarrison       if (hyphen) {
68812909Sgarrison          for (j = 1; j + i <= rtop && citenums[i+j] == citenums[i] + j; j++);
68912909Sgarrison          if (j + i > rtop) j = rtop;
69012909Sgarrison          else j = j + i - 1;
69112909Sgarrison          }
69212909Sgarrison       else
69312909Sgarrison          j = i;
69412909Sgarrison       if (j > i + 1) {
69512909Sgarrison          fputs("\\*(]-", ofd);
69612909Sgarrison          i = j - 1;
69712909Sgarrison          }
69812909Sgarrison       else if (i != rtop)
69912909Sgarrison          fputs("\\*(],", ofd);
70012909Sgarrison       if (foot) {
70112909Sgarrison          fn++;
70212909Sgarrison          footrefs[fn] = citenums[i];
70312909Sgarrison          }
70412909Sgarrison       }
70512909Sgarrison    return(fn);
70612909Sgarrison }
70712909Sgarrison 
70812909Sgarrison /* pass2 - read pass 1 files entering citation */
70912909Sgarrison    pass2(ifd, ofd)
71012909Sgarrison    FILE *ifd, *ofd;
71112909Sgarrison {
71212909Sgarrison    char c;
71312909Sgarrison    int  i, fn, footrefs[25], dumped;
71412909Sgarrison 
71512909Sgarrison    fn = -1;
71612909Sgarrison    dumped = foot;
71712909Sgarrison    while (getch(c, ifd) != EOF) {
71812909Sgarrison       while (c == '\n') {
71912909Sgarrison          putc(c, ofd);
72012909Sgarrison          if (foot && fn >= 0) {
72112909Sgarrison             for (i = 0; i <= fn; i++)
72212909Sgarrison                 dumpref(footrefs[i], ofd);
72312909Sgarrison             fn = -1;
72412909Sgarrison             }
72512909Sgarrison          if (testc(c, '.', ifd, ofd))
72612909Sgarrison             if (testc(c, '[', ifd, ofd))
72712909Sgarrison                if (testc(c, ']', ifd, ofd)) {
72812909Sgarrison                   while (echoc(c, ifd, ofd) != '\n')
72912909Sgarrison                      ;
73012909Sgarrison                   dumped = true;
73112909Sgarrison                   for (i = 0; i <= numrefs; i++)
73212909Sgarrison                      dumpref(i, ofd);
73312909Sgarrison                   getch(c, ifd);
73412909Sgarrison                   }
73512909Sgarrison          }
73612909Sgarrison       if (c == CITEMARK)
73712909Sgarrison          fn = putrefs(ifd, ofd, footrefs, fn);
73812909Sgarrison       else if (c != EOF)
73912909Sgarrison          putc(c, ofd);
74012909Sgarrison       }
74112909Sgarrison    if (dumped == false)
74213107Srrh       bibwarning("Warning: references never dumped\n", (char *)0);
74312909Sgarrison }
74412909Sgarrison 
74512909Sgarrison 
74612909Sgarrison /* dumpref - dump reference number i */
74712909Sgarrison    dumpref(i, ofd)
74812909Sgarrison    int i;
74912909Sgarrison    FILE *ofd;
75012909Sgarrison {  char ref[REFSIZE], *p, line[REFSIZE];
75112909Sgarrison    int numauths, maxauths, numeds, maxeds;
75212909Sgarrison 
75312909Sgarrison    rdref(refspos[i], ref);
75412909Sgarrison    maxauths = maxeds = 0;
75512909Sgarrison    numauths = numeds = 0;
75612909Sgarrison    for (p = ref; *p; p++)
75712909Sgarrison       if (*p == '%')
75812909Sgarrison          if (*(p+1) == 'A') maxauths++;
75912909Sgarrison          else if (*(p+1) == 'E') maxeds++;
76012909Sgarrison    fprintf(ofd, ".[-\n");
76112909Sgarrison    fprintf(ofd, ".ds [F %s\n",citestr[i]);
76212909Sgarrison    fseek(rfd, (long) refspos[i], 0);
76312909Sgarrison    while (fgets(line, REFSIZE, rfd) != NULL) {
76412909Sgarrison       if (line[0] == 0)        break;
76512909Sgarrison       else if (line[0] == '.') fprintf(ofd,"%s",line);
76612909Sgarrison       else {
76712909Sgarrison          if (line[0] == '%') {
76812909Sgarrison             for (p = &line[2]; *p == ' '; p++);
76912909Sgarrison             if (line[1] == 'A')       numauths++;
77012909Sgarrison             else if (line[1] == 'E')  numeds++;
77112909Sgarrison 
77212909Sgarrison             doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd);
77312909Sgarrison             }
77412909Sgarrison          }
77512909Sgarrison       }
77612909Sgarrison    fprintf(ofd,".][\n");
77712909Sgarrison }
77813107Srrh /*
77913107Srrh  *	print out a warning message
78013107Srrh  */
78113107Srrh bibwarning(msg, arg)
78213107Srrh 	char	*msg;
78313107Srrh 	char	*arg;
78413107Srrh {
78513107Srrh 	fprintf(stderr, "`%s', line %d: ", bibfname, biblineno);
78613107Srrh 	fprintf(stderr, msg, arg);
78713107Srrh }
788