xref: /csrg-svn/contrib/bib/src/bib.c (revision 12960)
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[];
3612909Sgarrison 
3712909Sgarrison 
3812909Sgarrison main(argc, argv)
3912909Sgarrison    int argc;
4012909Sgarrison    char **argv;
4112909Sgarrison {  int rcomp();
4212909Sgarrison 
4312909Sgarrison    /* the file INDEX in the current directory is the default index,
4412909Sgarrison       if it is present */
4512909Sgarrison 
4612909Sgarrison    rfd = fopen( INDXFILE , "r");
4712909Sgarrison    if (rfd != NULL) {
4812909Sgarrison       findex = true;
4912909Sgarrison       fclose(rfd);
5012909Sgarrison       }
5112909Sgarrison 
5212909Sgarrison    /* open temporaries, reffile will contain references collected in
5312909Sgarrison       pass 1, and tmpfile will contain text.
5412909Sgarrison    */
5512909Sgarrison    mktemp(reffile);
5612909Sgarrison    rfd = fopen(reffile,"w+");
5712909Sgarrison    if (rfd == NULL)
5812909Sgarrison       error("can't open temporary reference file");
5912909Sgarrison    mktemp(tmpfile);
6012909Sgarrison    tfd = fopen(tmpfile,"w");
6112909Sgarrison    if (tfd == NULL)
6212909Sgarrison       error("can't open temporary output file");
6312909Sgarrison 
6412909Sgarrison     /*
6512909Sgarrison        pass1 - read files, looking for citations
6612909Sgarrison                arguments are read by doargs (bibargs.c)
6712909Sgarrison     */
6812909Sgarrison 
6912909Sgarrison    if (doargs(argc, argv, DEFSTYLE ) == 0)
7012909Sgarrison       rdtext(stdin);
7112909Sgarrison 
7212909Sgarrison    /*
7312909Sgarrison     sort references, make citations, add disambiguating characters
7412909Sgarrison    */
7512909Sgarrison 
7612909Sgarrison    if (sort)
7712909Sgarrison       qsort(refspos, numrefs+1, sizeof(long), rcomp);
7812909Sgarrison    makecites(citestr);
7912909Sgarrison    disambiguate();
8012909Sgarrison 
8112909Sgarrison    /*
8212909Sgarrison    reopen temporaries
8312909Sgarrison    */
8412909Sgarrison 
8512909Sgarrison    fclose(tfd);
8612909Sgarrison    tfd = fopen(tmpfile,"r");
8712909Sgarrison    if (tfd == NULL)
8812909Sgarrison       error("can't open temporary output file for reading");
8912909Sgarrison 
9012909Sgarrison    /*
9112909Sgarrison    pass 2 - reread files, replacing references
9212909Sgarrison    */
9312909Sgarrison 
9412909Sgarrison    pass2(tfd, stdout);
9512909Sgarrison 
9612909Sgarrison    /*
9712909Sgarrison    clean up
9812909Sgarrison    */
9912909Sgarrison 
10012909Sgarrison    fclose(tfd);
10112909Sgarrison    fclose(rfd);
10212909Sgarrison    unlink(tmpfile);
10312909Sgarrison    unlink(reffile);
10412909Sgarrison    exit(0);
10512909Sgarrison }
10612909Sgarrison 
10712909Sgarrison /* rdtext - read and process a text file, looking for [. commands */
10812909Sgarrison    rdtext(fd)
10912909Sgarrison    FILE *fd;
11012909Sgarrison {  char lastc, c, d;
11112909Sgarrison 
11212909Sgarrison    lastc = 0;
11312909Sgarrison    while (getch(c, fd) != EOF)
11412909Sgarrison       if (c == '[' || c == '{')
11512909Sgarrison          if (getch(d, fd) == '.') { /* found a reference */
11612909Sgarrison             if (c == '{') { if (lastc) putc(lastc, tfd);}
11712909Sgarrison             else
118*12960Sgarrison 	       switch (lastc) {
119*12960Sgarrison 	       case ' ': fputs("\\*([<", tfd);
120*12960Sgarrison 			 break;
121*12960Sgarrison                case '.': fputs("\\*([.", tfd);
122*12960Sgarrison 			 break;
123*12960Sgarrison                case ',': fputs("\\*([,", tfd);
124*12960Sgarrison 			 break;
125*12960Sgarrison                case '?': fputs("\\*([?", tfd);
126*12960Sgarrison 			 break;
127*12960Sgarrison                case ':': fputs("\\*([:", tfd);
128*12960Sgarrison 			 break;
129*12960Sgarrison                case ';': fputs("\\*([;", tfd);
130*12960Sgarrison 			 break;
131*12960Sgarrison                case '!': fputs("\\*([!", tfd);
132*12960Sgarrison 			 break;
133*12960Sgarrison                case '"': fputs("\\*([\"", tfd);
134*12960Sgarrison 			 break;
135*12960Sgarrison                case '\'': fputs("\\*(['", tfd);
136*12960Sgarrison 			 break;
137*12960Sgarrison 	       default : putc(lastc, tfd);
138*12960Sgarrison 			 break;
139*12960Sgarrison 	       }
14012909Sgarrison             rdcite(fd, c);
14112909Sgarrison             if (c == '[')
142*12960Sgarrison 	       switch (lastc) {
143*12960Sgarrison 	       case ' ': fputs("\\*(<]", tfd);
144*12960Sgarrison 			 break;
145*12960Sgarrison                case '.': fputs("\\*(.]", tfd);
146*12960Sgarrison 			 break;
147*12960Sgarrison                case ',': fputs("\\*(,]", tfd);
148*12960Sgarrison 			 break;
149*12960Sgarrison                case '?': fputs("\\*(?]", tfd);
150*12960Sgarrison 			 break;
151*12960Sgarrison                case ':': fputs("\\*(:]", tfd);
152*12960Sgarrison 			 break;
153*12960Sgarrison                case ';': fputs("\\*(;]", tfd);
154*12960Sgarrison 			 break;
155*12960Sgarrison                case '!': fputs("\\*(!]", tfd);
156*12960Sgarrison 			 break;
157*12960Sgarrison                case '"': fputs("\\*(\"]", tfd);
158*12960Sgarrison 			 break;
159*12960Sgarrison                case '\'': fputs("\\*(']", tfd);
160*12960Sgarrison 			 break;
161*12960Sgarrison 	       }
16212909Sgarrison             lastc = 0;
16312909Sgarrison             }
16412909Sgarrison          else {
16512909Sgarrison             if (lastc) putc(lastc, tfd);
16612909Sgarrison             ungetc(d, fd);
16712909Sgarrison             lastc = c;
16812909Sgarrison             }
16912909Sgarrison       else {
17012909Sgarrison          if (lastc) putc(lastc, tfd);
17112909Sgarrison          lastc = c;
17212909Sgarrison          }
17312909Sgarrison    if (lastc) putc(lastc, tfd);
17412909Sgarrison }
17512909Sgarrison 
17612909Sgarrison /* rdcite - read citation information inside a [. command */
17712909Sgarrison    rdcite(fd, ch)
17812909Sgarrison    FILE *fd;
17912909Sgarrison    char ch;
18012909Sgarrison {  long int n, getref();
18112909Sgarrison    char huntstr[HUNTSIZE], c, info[HUNTSIZE];
18212909Sgarrison 
18312909Sgarrison    if (ch == '[')
18412909Sgarrison       fputs("\\*([[", tfd);
18512909Sgarrison    else
18612909Sgarrison       fputs("\\*([{", tfd);
18712909Sgarrison    huntstr[0] = info[0] = 0;
18812909Sgarrison    while (getch(c, fd) != EOF)
18912909Sgarrison       switch (c) {
19012909Sgarrison          case ',':
19112909Sgarrison             n = getref(huntstr);
19212909Sgarrison             if (n > 0)
19312909Sgarrison                fprintf(tfd, "%c%ld%c%s%c", CITEMARK, n, CITEMARK, info, CITEEND);
19412909Sgarrison             else
19512909Sgarrison                fprintf(tfd, "%c0%c%s%s%c", CITEMARK, CITEMARK,
19612909Sgarrison                                            huntstr, info, CITEEND);
19712909Sgarrison             huntstr[0] = info[0] = 0;
19812909Sgarrison             break;
19912909Sgarrison 
20012909Sgarrison          case '.':
20112909Sgarrison             while (getch(c, fd) == '.') ;
20212909Sgarrison             if (c == ']') {
20312909Sgarrison                n = getref(huntstr);
20412909Sgarrison                if (n > 0)
20512909Sgarrison                   fprintf(tfd, "%c%ld%c%s%c\\*(]]", CITEMARK, n,
20612909Sgarrison                                                   CITEMARK, info, CITEEND);
20712909Sgarrison                else
20812909Sgarrison                   fprintf(tfd, "%c0%c%s%s%c\\*(]]", CITEMARK, CITEMARK,
20912909Sgarrison                                               huntstr, info, CITEEND);
21012909Sgarrison                return;
21112909Sgarrison                }
21212909Sgarrison             else if (c == '}') {
21312909Sgarrison                n = getref(huntstr);
21412909Sgarrison                if (n > 0)
21512909Sgarrison                   fprintf(tfd, "%c%ld%c%s%c\\*(}]", CITEMARK, n,
21612909Sgarrison                                                     CITEMARK, info, CITEEND);
21712909Sgarrison                else
21812909Sgarrison                   fprintf(tfd, "%c0%c%s%s%c\\*(}]", CITEMARK, CITEMARK,
21912909Sgarrison                                               huntstr, info, CITEEND);
22012909Sgarrison                return;
22112909Sgarrison                }
22212909Sgarrison             else
22312909Sgarrison                addc(huntstr, c);
22412909Sgarrison             break;
22512909Sgarrison 
22612909Sgarrison          case '{':
22712909Sgarrison             while (getch(c, fd) != '}')
22812909Sgarrison                if (c == EOF) {
22912909Sgarrison                   fprintf(stderr, "Error: ill formed reference\n");
23012909Sgarrison                   exit(1);
23112909Sgarrison                   }
23212909Sgarrison                 else
23312909Sgarrison                   addc(info, c);
23412909Sgarrison             break;
23512909Sgarrison 
23612909Sgarrison          case '\n':
23712909Sgarrison          case '\t':
23812909Sgarrison             c = ' ';   /* fall through */
23912909Sgarrison 
24012909Sgarrison          default:
24112909Sgarrison             addc(huntstr,c);
24212909Sgarrison          }
24312909Sgarrison    error("end of file reading citation");
24412909Sgarrison }
24512909Sgarrison 
24612909Sgarrison /* addc - add a character to hunt string */
24712909Sgarrison    addc(huntstr, c)
24812909Sgarrison    char huntstr[HUNTSIZE], c;
24912909Sgarrison {  int  i;
25012909Sgarrison 
25112909Sgarrison    i = strlen(huntstr);
25212909Sgarrison    if (i > HUNTSIZE)
25312909Sgarrison       error("citation too long");
25412909Sgarrison    huntstr[i] = c;
25512909Sgarrison    huntstr[i+1] = 0;
25612909Sgarrison }
25712909Sgarrison 
25812909Sgarrison /* getref - if an item was already referenced, return its pointer in
25912909Sgarrison                 the reference file, otherwise create a new entry */
26012909Sgarrison    long int getref(huntstr)
26112909Sgarrison    char huntstr[HUNTSIZE];
26212909Sgarrison {  char rf[REFSIZE], ref[REFSIZE], *r, *hunt();
26312909Sgarrison    int  i, match(), getwrd();
26412909Sgarrison 
26512909Sgarrison    r = hunt(huntstr);
26612909Sgarrison    if (r != NULL) {
26712909Sgarrison       /* exapand defined string */
26812909Sgarrison       strcpy(rf, r);
26912909Sgarrison       free(r);
27012909Sgarrison       expand(rf);
27112909Sgarrison 
27212909Sgarrison       /* see if reference has already been cited */
27312909Sgarrison 
27412909Sgarrison       if (foot == false)
27512909Sgarrison          for (i = 0; i <= numrefs; i++) {
27612909Sgarrison              rdref(refspos[i], ref);
27712909Sgarrison              if (strcmp(ref, rf) == 0)
27812909Sgarrison                 return(refspos[i]);
27912909Sgarrison           }
28012909Sgarrison 
28112909Sgarrison       /* didn't match any existing reference, create new one */
28212909Sgarrison 
28312909Sgarrison       numrefs++;
28412909Sgarrison       refspos[numrefs] = rend;
28512909Sgarrison       fseek(rfd, rend, 0);
28612909Sgarrison       i = strlen(rf) + 1;
28712909Sgarrison       fwrite(rf, 1, i, rfd);
28812909Sgarrison       rend = rend + i;
28912909Sgarrison       return(refspos[numrefs]);
29012909Sgarrison       }
29112909Sgarrison    else {
29212909Sgarrison       fprintf(stderr,"no reference matching %s\n", huntstr);
29312909Sgarrison       return( (long) -1 );
29412909Sgarrison       }
29512909Sgarrison }
29612909Sgarrison 
29712909Sgarrison /* rdref - read text for an already cited reference */
29812909Sgarrison    rdref(i, ref)
29912909Sgarrison    long int  i;
30012909Sgarrison    char ref[REFSIZE];
30112909Sgarrison {
30212909Sgarrison    ref[0] = 0;
30312909Sgarrison    fseek(rfd, i, 0);
30412909Sgarrison    fread(ref, 1, REFSIZE, rfd);
30512909Sgarrison }
30612909Sgarrison 
30712909Sgarrison /* hunt - hunt for reference from either personal or system index */
30812909Sgarrison    char *hunt(huntstr)
30912909Sgarrison    char huntstr[];
31012909Sgarrison {  char *fhunt(), *r, *p, *q, fname[120];
31112909Sgarrison 
31212909Sgarrison    if (personal) {
31312909Sgarrison       for (p = fname, q = pfile; ; q++)
31412909Sgarrison          if (*q == ',' || *q == 0) {
31512909Sgarrison             *p = 0;
31612909Sgarrison             if ((r = fhunt(fname, huntstr)) != NULL)
31712909Sgarrison                return(r);
31812909Sgarrison             else if (*q == 0)
31912909Sgarrison                break;
32012909Sgarrison             p = fname;
32112909Sgarrison             }
32212909Sgarrison          else *p++ = *q;
32312909Sgarrison       }
32412909Sgarrison    else if (findex) {
32512909Sgarrison       if ((r = fhunt( INDXFILE , huntstr)) != NULL)
32612909Sgarrison          return(r);
32712909Sgarrison       }
32812909Sgarrison    if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
32912909Sgarrison       return(r);
33012909Sgarrison    return(NULL);
33112909Sgarrison }
33212909Sgarrison 
33312909Sgarrison /* fhunt - hunt from a specific file */
33412909Sgarrison    char *fhunt(file, huntstr)
33512909Sgarrison    char file[], huntstr[];
33612909Sgarrison {  char *p, *r, *locate();
33712909Sgarrison 
33812909Sgarrison    r = locate(huntstr, file, 6, common);
33912909Sgarrison 
34012909Sgarrison    if (r == NULL)
34112909Sgarrison       return(NULL);  /* error */
34212909Sgarrison    if (*r == 0)
34312909Sgarrison       return(NULL);  /* no match */
34412909Sgarrison 
34512909Sgarrison    for (p = r; *p; p++)
34612909Sgarrison       if (*p == '\n')
34712909Sgarrison          if (*(p+1) == '\n') { /* end */
34812909Sgarrison             if (*(p+2) != 0)
34912909Sgarrison                fprintf(stderr,"multiple references match %s\n",huntstr);
35012909Sgarrison             *(p+1) = 0;
35112909Sgarrison             break;
35212909Sgarrison             }
35312909Sgarrison          else if (*(p+1) != '%' && *(p+1) != '.') /* unnecessary newline */
35412909Sgarrison             *p = ' ';
35512909Sgarrison    return(r);
35612909Sgarrison }
35712909Sgarrison 
35812909Sgarrison /* rcomp - reference comparison routine for qsort utility */
35912909Sgarrison    int rcomp(ap, bp)
36012909Sgarrison    long int *ap, *bp;
36112909Sgarrison {  char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD];
36212909Sgarrison    char *p, *q, *getfield();
36312909Sgarrison    int  neg, res;
364*12960Sgarrison    int  fields_found;
36512909Sgarrison 
36612909Sgarrison    rdref(*ap, ref1);
36712909Sgarrison    rdref(*bp, ref2);
36812909Sgarrison    for (p = sortstr; *p; p = q) {
36912909Sgarrison       if (*p == '-') {
37012909Sgarrison          p++;
37112909Sgarrison          neg = true;
37212909Sgarrison          }
37312909Sgarrison       else
37412909Sgarrison          neg = false;
37512909Sgarrison       q = getfield(p, field1, ref1);
376*12960Sgarrison       fields_found = true;
377*12960Sgarrison       if (q == 0) {
378*12960Sgarrison 	 res = 1;
379*12960Sgarrison 	 fields_found = false;
380*12960Sgarrison       } else if (strcmp (field1, "") == 0) {	/* field not found */
38112909Sgarrison          if (*p == 'A') {
382*12960Sgarrison             getfield("F", field1, ref1);
383*12960Sgarrison 	    if (strcmp (field1, "") == 0) {
384*12960Sgarrison                getfield("I", field1, ref1);
385*12960Sgarrison 	       if (strcmp (field1, "") == 0) {
386*12960Sgarrison 	          res = 1;
387*12960Sgarrison 		  fields_found = false;
388*12960Sgarrison 	       }
389*12960Sgarrison 	    }
390*12960Sgarrison 	 } else {
391*12960Sgarrison 	    res = 1;
392*12960Sgarrison 	    fields_found = false;
393*12960Sgarrison 	 }
394*12960Sgarrison       }
395*12960Sgarrison 
396*12960Sgarrison       if (getfield(p, field2, ref2) == 0) {
397*12960Sgarrison 	 res = -1;
398*12960Sgarrison 	 fields_found = false;
399*12960Sgarrison       } else if (strcmp (field2, "") == 0) {	/* field not found */
400*12960Sgarrison          if (*p == 'A') {
401*12960Sgarrison             getfield("F", field2, ref2);
402*12960Sgarrison 	    if (strcmp (field2, "") == 0) {
403*12960Sgarrison                getfield("I", field2, ref2);
404*12960Sgarrison 	       if (strcmp (field2, "") == 0) {
405*12960Sgarrison 	          res = -1;
406*12960Sgarrison 		  fields_found = false;
407*12960Sgarrison 	       }
408*12960Sgarrison 	    }
409*12960Sgarrison 	 } else {
410*12960Sgarrison 	    res = -1;
411*12960Sgarrison 	    fields_found = false;
412*12960Sgarrison 	 }
413*12960Sgarrison       }
414*12960Sgarrison       if (fields_found) {
415*12960Sgarrison          if (*p == 'A') {
41612909Sgarrison             if (isupper(field1[0]))
41712909Sgarrison                field1[0] -= 'A' - 'a';
41812909Sgarrison             if (isupper(field2[0]))
41912909Sgarrison                field2[0] -= 'A' - 'a';
42012909Sgarrison             }
42112909Sgarrison          res = strcmp(field1, field2);
42212909Sgarrison          }
42312909Sgarrison       if (neg)
42412909Sgarrison          res = - res;
42512909Sgarrison       if (res != 0)
42612909Sgarrison          break;
42712909Sgarrison       }
42812909Sgarrison    if (res == 0)
42912909Sgarrison       if (ap < bp)
43012909Sgarrison          res = -1;
43112909Sgarrison       else
43212909Sgarrison          res = 1;
43312909Sgarrison    return(res);
43412909Sgarrison }
43512909Sgarrison 
43612909Sgarrison /* makecites - make citation strings */
43712909Sgarrison    makecites(citestr)
43812909Sgarrison    char *citestr[];
43912909Sgarrison {  char ref[REFSIZE], tempcite[100], *malloc();
44012909Sgarrison    int  i;
44112909Sgarrison 
44212909Sgarrison    for (i = 0; i <= numrefs; i++) {
44312909Sgarrison       rdref(refspos[i], ref);
44412909Sgarrison       bldcite(tempcite, i, ref);
44512909Sgarrison       citestr[i] = malloc(2 + strlen(tempcite)); /* leave room for disambig */
44612909Sgarrison       if (citestr[i] == NULL)
44712909Sgarrison          error("out of storage");
44812909Sgarrison       strcpy(citestr[i], tempcite);
44912909Sgarrison       }
45012909Sgarrison }
45112909Sgarrison 
45212909Sgarrison /* bldcite - build a single citation string */
45312909Sgarrison    bldcite(cp, i, ref)
45412909Sgarrison    char *cp, ref[];
45512909Sgarrison    int  i;
45612909Sgarrison {  char *p, *q, c, *fp, *np, field[REFSIZE], temp[100], *getfield();
45712909Sgarrison    int  j;
45812909Sgarrison 
45912909Sgarrison    getfield("F", field, ref);
46012909Sgarrison    if (field[0] != 0)
46112909Sgarrison       for (p = field; *p; p++)
46212909Sgarrison          *cp++ = *p;
46312909Sgarrison    else {
46412909Sgarrison       p = citetemplate;
46512909Sgarrison       field[0] = 0;
46612909Sgarrison       while (c = *p++)
46712909Sgarrison          if (isalpha(c)) {
46812909Sgarrison             q = getfield(p-1, field, ref);
46912909Sgarrison             if (q != 0) {
47012909Sgarrison                p = q;
47112909Sgarrison                for (fp = field; *fp; )
47212909Sgarrison                   *cp++ = *fp++;
47312909Sgarrison                }
47412909Sgarrison             }
47512909Sgarrison          else if (c == '1') {
47612909Sgarrison             sprintf(field,"%d",1 + i);
47712909Sgarrison             for (fp = field; *fp; )
47812909Sgarrison                *cp++ = *fp++;
47912909Sgarrison             }
48012909Sgarrison          else if (c == '2') {
48112909Sgarrison             if (getname(1, field, temp, ref)) {
48212909Sgarrison                np = cp;
48312909Sgarrison                fp = field;
48412909Sgarrison                for (j = 1; j <= 3; j++)
48512909Sgarrison                   if (*fp != 0)
48612909Sgarrison                      *cp++ = *fp++;
48712909Sgarrison                if (getname(2, field, temp, ref))
48812909Sgarrison                   np[2] = field[0];
48912909Sgarrison                if (getname(3, field, temp, ref)) {
49012909Sgarrison                   np[1] = np[2];
49112909Sgarrison                   np[2] = field[0];
49212909Sgarrison                   }
49312909Sgarrison                }
49412909Sgarrison             }
49512909Sgarrison          else if (c == '{') {
49612909Sgarrison             while (*p ^= '}')
49712909Sgarrison                if (*p == 0)
49812909Sgarrison                   error("unexpected end of citation template");
49912909Sgarrison                else
50012909Sgarrison                   *cp++ = *p++;
50112909Sgarrison             p++;
50212909Sgarrison             }
50312909Sgarrison          else if (c == '<') {
50412909Sgarrison             while (*p ^= '>')
50512909Sgarrison                if (*p == 0)
50612909Sgarrison                   error("unexpected end of citation template");
50712909Sgarrison                else
50812909Sgarrison                   *cp++ = *p++;
50912909Sgarrison             p++;
51012909Sgarrison             }
51112909Sgarrison          else if (c != '@')
51212909Sgarrison             *cp++ = c;
51312909Sgarrison       }
51412909Sgarrison    *cp++ = 0;
51512909Sgarrison }
51612909Sgarrison 
51712909Sgarrison /* getfield - get a single field from reference */
51812909Sgarrison    char *getfield(ptr, field, ref)
51912909Sgarrison    char *ptr, field[], ref[];
52012909Sgarrison {  char *p, *q, temp[100];
52112909Sgarrison    int  n, len, i, getname();
52212909Sgarrison 
52312909Sgarrison    field[0] = 0;
52412909Sgarrison    if (*ptr == 'A')
52512909Sgarrison       getname(1, field, temp, ref);
52612909Sgarrison    else
52712909Sgarrison       for (p = ref; *p; p++)
52812909Sgarrison          if (*p == '%' && *(p+1) == *ptr) {
52912909Sgarrison             for (p = p + 2; *p == ' '; p++)
53012909Sgarrison                ;
53112909Sgarrison             for (q = field; *p != '\n'; )
53212909Sgarrison                *q++ = *p++;
53312909Sgarrison             *q = 0;
53412909Sgarrison             break;
53512909Sgarrison             }
53612909Sgarrison    n = 0;
53712909Sgarrison    len = strlen(field);
53812909Sgarrison    if (*++ptr == '-') {
53912909Sgarrison       for (ptr++; isdigit(*ptr); ptr++)
54012909Sgarrison          n = 10 * n + (*ptr - '0');
54112909Sgarrison       if (n > len)
54212909Sgarrison          n = 0;
54312909Sgarrison       else
54412909Sgarrison          n = len - n;
54512909Sgarrison       for (i = 0; field[i] = field[i+n]; i++)
54612909Sgarrison          ;
54712909Sgarrison       }
54812909Sgarrison    else if (isdigit(*ptr)) {
54912909Sgarrison       for (; isdigit(*ptr); ptr++)
55012909Sgarrison          n = 10 * n + (*ptr - '0');
55112909Sgarrison       if (n > len)
55212909Sgarrison          n = len;
55312909Sgarrison       field[n] = 0;
55412909Sgarrison       }
55512909Sgarrison 
55612909Sgarrison    if (*ptr == 'u') {
55712909Sgarrison       ptr++;
55812909Sgarrison       for (p = field; *p; p++)
55912909Sgarrison          if (islower(*p))
56012909Sgarrison             *p = (*p - 'a') + 'A';
56112909Sgarrison       }
56212909Sgarrison    else if (*ptr == 'l') {
56312909Sgarrison       ptr++;
56412909Sgarrison       for (p = field; *p; p++)
56512909Sgarrison          if (isupper(*p))
56612909Sgarrison             *p = (*p - 'A') + 'a';
56712909Sgarrison       }
56812909Sgarrison    return(ptr);
56912909Sgarrison }
57012909Sgarrison 
57112909Sgarrison /* getname - get the nth name field from reference, breaking into
57212909Sgarrison              first and last names */
57312909Sgarrison    int getname(n, last, first, ref)
57412909Sgarrison    int  n;
57512909Sgarrison    char last[], first[], ref[];
57612909Sgarrison {  char *p;
57712909Sgarrison 
57812909Sgarrison    for (p = ref; *p; p++)
579*12960Sgarrison       if (*p == '%' & (*(p+1) == 'A' || *(p+1) == 'E')) {
58012909Sgarrison          n--;
58112909Sgarrison          if (n == 0) {
58212909Sgarrison             for (p = p + 2; *p == ' '; p++) ;
58312909Sgarrison             breakname(p, first, last) ;
58412909Sgarrison             return(true);
58512909Sgarrison             }
58612909Sgarrison          }
58712909Sgarrison    return(false);
58812909Sgarrison }
58912909Sgarrison 
59012909Sgarrison /* disambiguate - compare adjacent citation strings, and if equal, add
59112909Sgarrison                   single character disambiguators */
59212909Sgarrison    disambiguate()
59312909Sgarrison {  int i, j;
59412909Sgarrison    char adstr[2];
59512909Sgarrison 
59612909Sgarrison    for (i = 0; i < numrefs; i = j) {
59712909Sgarrison       j = i + 1;
59812909Sgarrison       if (strcmp(citestr[i], citestr[j])==0) {
59912909Sgarrison          adstr[0] = 'a'; adstr[1] = 0;
60012909Sgarrison          for (j = i+1; strcmp(citestr[i],citestr[j]) == 0; j++) {
60112909Sgarrison             adstr[0] = 'a' + (j-i);
60212909Sgarrison             strcat(citestr[j], adstr);
60312909Sgarrison             if (j == numrefs)
60412909Sgarrison                break;
60512909Sgarrison             }
60612909Sgarrison          adstr[0] = 'a';
60712909Sgarrison          strcat(citestr[i], adstr);
60812909Sgarrison          }
60912909Sgarrison      }
61012909Sgarrison }
61112909Sgarrison 
61212909Sgarrison /* putrefs - gather contiguous references together, sort them if called
61312909Sgarrison    for, hyphenate if necessary, and dump them out */
61412909Sgarrison int putrefs(ifd, ofd, footrefs, fn)
61512909Sgarrison FILE *ifd, *ofd;
61612909Sgarrison int  fn, footrefs[];
61712909Sgarrison {  int  citenums[MAXATONCE];   /* reference numbers */
61812909Sgarrison    char *citeinfo[MAXATONCE];  /* reference information */
61912909Sgarrison    char infoword[HUNTSIZE];    /* information line */
62012909Sgarrison    int  rtop, n, i, j;         /* number of citations being dumped */
62112909Sgarrison    char c, *p, *walloc();
62212909Sgarrison 
62312909Sgarrison /* first gather contiguous references together, and order them if
62412909Sgarrison    required      */
62512909Sgarrison 
62612909Sgarrison    rtop = -1;
62712909Sgarrison    do {
62812909Sgarrison       n = 0;
62912909Sgarrison       while (isdigit(getch(c, ifd)))
63012909Sgarrison          n = 10 * n + (c - '0');
63112909Sgarrison       if (c ^= CITEMARK)
63212909Sgarrison          error("inconsistant citation found in pass two");
63312909Sgarrison       if (n == 0) {     /* reference not found */
63412909Sgarrison          rtop++;
63512909Sgarrison          j = rtop;
63612909Sgarrison          citenums[j] = -1;
63712909Sgarrison          citeinfo[j] = 0;
63812909Sgarrison          }
63912909Sgarrison       else {
64012909Sgarrison          for (i = 0; i <= numrefs; i++)
64112909Sgarrison             if (refspos[i] == n) { /* its the ith item in reference list */
64212909Sgarrison                rtop++;
64312909Sgarrison                j = rtop;
64412909Sgarrison                if (ordcite)
64512909Sgarrison                   for ( ; j > 0 && citenums[j-1] > i; j--) {
64612909Sgarrison                      citenums[j] = citenums[j-1];
64712909Sgarrison                      citeinfo[j] = citeinfo[j-1];
64812909Sgarrison                      }
64912909Sgarrison                citenums[j] = i;
65012909Sgarrison                citeinfo[j] = 0;
65112909Sgarrison                break;
65212909Sgarrison                }
65312909Sgarrison          if (i > numrefs)
65412909Sgarrison             error("citation not found in pass two");
65512909Sgarrison          }
65612909Sgarrison       if (getch(c, ifd) != CITEEND) {
65712909Sgarrison          for (p = infoword; c != CITEEND ; ) {
65812909Sgarrison             *p++ = c;
65912909Sgarrison             getch(c, ifd);
66012909Sgarrison             }
66112909Sgarrison          *p = 0;
66212909Sgarrison          citeinfo[j] = walloc(infoword);
66312909Sgarrison          }
66412909Sgarrison       getch(c, ifd);
66512909Sgarrison       }  while (c == CITEMARK);
66612909Sgarrison    ungetc(c, ifd);
66712909Sgarrison 
66812909Sgarrison    /* now dump out values */
66912909Sgarrison    for (i = 0; i <= rtop; i++) {
67012909Sgarrison       if (citenums[i] >= 0)
67112909Sgarrison          fputs(citestr[citenums[i]], ofd);
67212909Sgarrison       if (citeinfo[i]) {
67312909Sgarrison          fputs(citeinfo[i], ofd);
67412909Sgarrison          free(citeinfo[i]);
67512909Sgarrison          }
67612909Sgarrison       if (hyphen) {
67712909Sgarrison          for (j = 1; j + i <= rtop && citenums[i+j] == citenums[i] + j; j++);
67812909Sgarrison          if (j + i > rtop) j = rtop;
67912909Sgarrison          else j = j + i - 1;
68012909Sgarrison          }
68112909Sgarrison       else
68212909Sgarrison          j = i;
68312909Sgarrison       if (j > i + 1) {
68412909Sgarrison          fputs("\\*(]-", ofd);
68512909Sgarrison          i = j - 1;
68612909Sgarrison          }
68712909Sgarrison       else if (i != rtop)
68812909Sgarrison          fputs("\\*(],", ofd);
68912909Sgarrison       if (foot) {
69012909Sgarrison          fn++;
69112909Sgarrison          footrefs[fn] = citenums[i];
69212909Sgarrison          }
69312909Sgarrison       }
69412909Sgarrison    return(fn);
69512909Sgarrison }
69612909Sgarrison 
69712909Sgarrison /* pass2 - read pass 1 files entering citation */
69812909Sgarrison    pass2(ifd, ofd)
69912909Sgarrison    FILE *ifd, *ofd;
70012909Sgarrison {
70112909Sgarrison    char c;
70212909Sgarrison    int  i, fn, footrefs[25], dumped;
70312909Sgarrison 
70412909Sgarrison    fn = -1;
70512909Sgarrison    dumped = foot;
70612909Sgarrison    while (getch(c, ifd) != EOF) {
70712909Sgarrison       while (c == '\n') {
70812909Sgarrison          putc(c, ofd);
70912909Sgarrison          if (foot && fn >= 0) {
71012909Sgarrison             for (i = 0; i <= fn; i++)
71112909Sgarrison                 dumpref(footrefs[i], ofd);
71212909Sgarrison             fn = -1;
71312909Sgarrison             }
71412909Sgarrison          if (testc(c, '.', ifd, ofd))
71512909Sgarrison             if (testc(c, '[', ifd, ofd))
71612909Sgarrison                if (testc(c, ']', ifd, ofd)) {
71712909Sgarrison                   while (echoc(c, ifd, ofd) != '\n')
71812909Sgarrison                      ;
71912909Sgarrison                   dumped = true;
72012909Sgarrison                   for (i = 0; i <= numrefs; i++)
72112909Sgarrison                      dumpref(i, ofd);
72212909Sgarrison                   getch(c, ifd);
72312909Sgarrison                   }
72412909Sgarrison          }
72512909Sgarrison       if (c == CITEMARK)
72612909Sgarrison          fn = putrefs(ifd, ofd, footrefs, fn);
72712909Sgarrison       else if (c != EOF)
72812909Sgarrison          putc(c, ofd);
72912909Sgarrison       }
73012909Sgarrison    if (dumped == false)
73112909Sgarrison       fprintf(stderr,"Warning: references never dumped\n");
73212909Sgarrison }
73312909Sgarrison 
73412909Sgarrison 
73512909Sgarrison /* dumpref - dump reference number i */
73612909Sgarrison    dumpref(i, ofd)
73712909Sgarrison    int i;
73812909Sgarrison    FILE *ofd;
73912909Sgarrison {  char ref[REFSIZE], *p, line[REFSIZE];
74012909Sgarrison    int numauths, maxauths, numeds, maxeds;
74112909Sgarrison 
74212909Sgarrison    rdref(refspos[i], ref);
74312909Sgarrison    maxauths = maxeds = 0;
74412909Sgarrison    numauths = numeds = 0;
74512909Sgarrison    for (p = ref; *p; p++)
74612909Sgarrison       if (*p == '%')
74712909Sgarrison          if (*(p+1) == 'A') maxauths++;
74812909Sgarrison          else if (*(p+1) == 'E') maxeds++;
74912909Sgarrison    fprintf(ofd, ".[-\n");
75012909Sgarrison    fprintf(ofd, ".ds [F %s\n",citestr[i]);
75112909Sgarrison    fseek(rfd, (long) refspos[i], 0);
75212909Sgarrison    while (fgets(line, REFSIZE, rfd) != NULL) {
75312909Sgarrison       if (line[0] == 0)        break;
75412909Sgarrison       else if (line[0] == '.') fprintf(ofd,"%s",line);
75512909Sgarrison       else {
75612909Sgarrison          if (line[0] == '%') {
75712909Sgarrison             for (p = &line[2]; *p == ' '; p++);
75812909Sgarrison             if (line[1] == 'A')       numauths++;
75912909Sgarrison             else if (line[1] == 'E')  numeds++;
76012909Sgarrison 
76112909Sgarrison             doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd);
76212909Sgarrison             }
76312909Sgarrison          }
76412909Sgarrison       }
76512909Sgarrison    fprintf(ofd,".][\n");
76612909Sgarrison }
767