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