xref: /csrg-svn/contrib/bib/src/bib.c (revision 12909)
1*12909Sgarrison /*
2*12909Sgarrison    bib - bibliographic formatter
3*12909Sgarrison          timothy a. budd, 1/82
4*12909Sgarrison          lookup routines supplied by gary levin 2/82
5*12909Sgarrison          reworked several new features added, 11/82.
6*12909Sgarrison */
7*12909Sgarrison # include <stdio.h>
8*12909Sgarrison # include <ctype.h>
9*12909Sgarrison # include "bib.h"
10*12909Sgarrison 
11*12909Sgarrison # define HUNTSIZE 512                /* maximum size of hunt string         */
12*12909Sgarrison # define MAXFIELD 250                /* maximum field length                */
13*12909Sgarrison # define MAXREFS  300                /* maximum number of references        */
14*12909Sgarrison # define MAXATONCE 35                /* maximum references at one location  */
15*12909Sgarrison 
16*12909Sgarrison # define getch(c,fd) (c = getc(fd))
17*12909Sgarrison # define echoc(c,ifd,ofd) (getch(c,ifd) == EOF ? c : putc(c,ofd))
18*12909Sgarrison # define testc(c,d,ifd,ofd) (getch(c, ifd) == d ? putc(c, ofd) : 0)
19*12909Sgarrison 
20*12909Sgarrison /* global variables */
21*12909Sgarrison    FILE *rfd;                   /* reference temporary file              */
22*12909Sgarrison    char reffile[] = TMPREFFILE ;/* temporary file (see bib.h)            */
23*12909Sgarrison    long int refspos[MAXREFS];   /* reference seek positions              */
24*12909Sgarrison    long int rend = 1;           /* last position in rfd (first char unused)*/
25*12909Sgarrison    int numrefs = -1;            /* number of references generated so far */
26*12909Sgarrison    FILE *tfd;                   /* output of pass 1 of file(s)           */
27*12909Sgarrison    char tmpfile[] = TMPTEXTFILE ; /* output of pass 1                    */
28*12909Sgarrison    char common[] = COMFILE ;    /* common word file                      */
29*12909Sgarrison    char *citestr[MAXREFS];      /* citation strings                      */
30*12909Sgarrison    int  findex = false;         /* can we read the file INDEX ?          */
31*12909Sgarrison 
32*12909Sgarrison /* global variables in bibargs */
33*12909Sgarrison    extern int foot, sort, personal;
34*12909Sgarrison    extern int hyphen, ordcite;
35*12909Sgarrison    extern char sortstr[], pfile[], citetemplate[];
36*12909Sgarrison 
37*12909Sgarrison 
38*12909Sgarrison main(argc, argv)
39*12909Sgarrison    int argc;
40*12909Sgarrison    char **argv;
41*12909Sgarrison {  int rcomp();
42*12909Sgarrison 
43*12909Sgarrison    /* the file INDEX in the current directory is the default index,
44*12909Sgarrison       if it is present */
45*12909Sgarrison 
46*12909Sgarrison    rfd = fopen( INDXFILE , "r");
47*12909Sgarrison    if (rfd != NULL) {
48*12909Sgarrison       findex = true;
49*12909Sgarrison       fclose(rfd);
50*12909Sgarrison       }
51*12909Sgarrison 
52*12909Sgarrison    /* open temporaries, reffile will contain references collected in
53*12909Sgarrison       pass 1, and tmpfile will contain text.
54*12909Sgarrison    */
55*12909Sgarrison    mktemp(reffile);
56*12909Sgarrison    rfd = fopen(reffile,"w+");
57*12909Sgarrison    if (rfd == NULL)
58*12909Sgarrison       error("can't open temporary reference file");
59*12909Sgarrison    mktemp(tmpfile);
60*12909Sgarrison    tfd = fopen(tmpfile,"w");
61*12909Sgarrison    if (tfd == NULL)
62*12909Sgarrison       error("can't open temporary output file");
63*12909Sgarrison 
64*12909Sgarrison     /*
65*12909Sgarrison        pass1 - read files, looking for citations
66*12909Sgarrison                arguments are read by doargs (bibargs.c)
67*12909Sgarrison     */
68*12909Sgarrison 
69*12909Sgarrison    if (doargs(argc, argv, DEFSTYLE ) == 0)
70*12909Sgarrison       rdtext(stdin);
71*12909Sgarrison 
72*12909Sgarrison    /*
73*12909Sgarrison     sort references, make citations, add disambiguating characters
74*12909Sgarrison    */
75*12909Sgarrison 
76*12909Sgarrison    if (sort)
77*12909Sgarrison       qsort(refspos, numrefs+1, sizeof(long), rcomp);
78*12909Sgarrison    makecites(citestr);
79*12909Sgarrison    disambiguate();
80*12909Sgarrison 
81*12909Sgarrison    /*
82*12909Sgarrison    reopen temporaries
83*12909Sgarrison    */
84*12909Sgarrison 
85*12909Sgarrison    fclose(tfd);
86*12909Sgarrison    tfd = fopen(tmpfile,"r");
87*12909Sgarrison    if (tfd == NULL)
88*12909Sgarrison       error("can't open temporary output file for reading");
89*12909Sgarrison 
90*12909Sgarrison    /*
91*12909Sgarrison    pass 2 - reread files, replacing references
92*12909Sgarrison    */
93*12909Sgarrison 
94*12909Sgarrison    pass2(tfd, stdout);
95*12909Sgarrison 
96*12909Sgarrison    /*
97*12909Sgarrison    clean up
98*12909Sgarrison    */
99*12909Sgarrison 
100*12909Sgarrison    fclose(tfd);
101*12909Sgarrison    fclose(rfd);
102*12909Sgarrison    unlink(tmpfile);
103*12909Sgarrison    unlink(reffile);
104*12909Sgarrison    exit(0);
105*12909Sgarrison }
106*12909Sgarrison 
107*12909Sgarrison /* rdtext - read and process a text file, looking for [. commands */
108*12909Sgarrison    rdtext(fd)
109*12909Sgarrison    FILE *fd;
110*12909Sgarrison {  char lastc, c, d;
111*12909Sgarrison 
112*12909Sgarrison    lastc = 0;
113*12909Sgarrison    while (getch(c, fd) != EOF)
114*12909Sgarrison       if (c == '[' || c == '{')
115*12909Sgarrison          if (getch(d, fd) == '.') { /* found a reference */
116*12909Sgarrison             if (c == '{') { if (lastc) putc(lastc, tfd);}
117*12909Sgarrison             else
118*12909Sgarrison                if (lastc == ' ')       fputs("\\*([<", tfd);
119*12909Sgarrison                else if (lastc == '.')  fputs("\\*([.", tfd);
120*12909Sgarrison                else if (lastc == ',')  fputs("\\*([,", tfd);
121*12909Sgarrison                else if (lastc)         putc(lastc, tfd);
122*12909Sgarrison             rdcite(fd, c);
123*12909Sgarrison             if (c == '[')
124*12909Sgarrison                if (lastc == ' ')       fputs("\\*(>]", tfd);
125*12909Sgarrison                else if (lastc == '.')  fputs("\\*(.]", tfd);
126*12909Sgarrison                else if (lastc == ',')  fputs("\\*(,]", tfd);
127*12909Sgarrison             lastc = 0;
128*12909Sgarrison             }
129*12909Sgarrison          else {
130*12909Sgarrison             if (lastc) putc(lastc, tfd);
131*12909Sgarrison             ungetc(d, fd);
132*12909Sgarrison             lastc = c;
133*12909Sgarrison             }
134*12909Sgarrison       else {
135*12909Sgarrison          if (lastc) putc(lastc, tfd);
136*12909Sgarrison          lastc = c;
137*12909Sgarrison          }
138*12909Sgarrison    if (lastc) putc(lastc, tfd);
139*12909Sgarrison }
140*12909Sgarrison 
141*12909Sgarrison /* rdcite - read citation information inside a [. command */
142*12909Sgarrison    rdcite(fd, ch)
143*12909Sgarrison    FILE *fd;
144*12909Sgarrison    char ch;
145*12909Sgarrison {  long int n, getref();
146*12909Sgarrison    char huntstr[HUNTSIZE], c, info[HUNTSIZE];
147*12909Sgarrison 
148*12909Sgarrison    if (ch == '[')
149*12909Sgarrison       fputs("\\*([[", tfd);
150*12909Sgarrison    else
151*12909Sgarrison       fputs("\\*([{", tfd);
152*12909Sgarrison    huntstr[0] = info[0] = 0;
153*12909Sgarrison    while (getch(c, fd) != EOF)
154*12909Sgarrison       switch (c) {
155*12909Sgarrison          case ',':
156*12909Sgarrison             n = getref(huntstr);
157*12909Sgarrison             if (n > 0)
158*12909Sgarrison                fprintf(tfd, "%c%ld%c%s%c", CITEMARK, n, CITEMARK, info, CITEEND);
159*12909Sgarrison             else
160*12909Sgarrison                fprintf(tfd, "%c0%c%s%s%c", CITEMARK, CITEMARK,
161*12909Sgarrison                                            huntstr, info, CITEEND);
162*12909Sgarrison             huntstr[0] = info[0] = 0;
163*12909Sgarrison             break;
164*12909Sgarrison 
165*12909Sgarrison          case '.':
166*12909Sgarrison             while (getch(c, fd) == '.') ;
167*12909Sgarrison             if (c == ']') {
168*12909Sgarrison                n = getref(huntstr);
169*12909Sgarrison                if (n > 0)
170*12909Sgarrison                   fprintf(tfd, "%c%ld%c%s%c\\*(]]", CITEMARK, n,
171*12909Sgarrison                                                   CITEMARK, info, CITEEND);
172*12909Sgarrison                else
173*12909Sgarrison                   fprintf(tfd, "%c0%c%s%s%c\\*(]]", CITEMARK, CITEMARK,
174*12909Sgarrison                                               huntstr, info, CITEEND);
175*12909Sgarrison                return;
176*12909Sgarrison                }
177*12909Sgarrison             else if (c == '}') {
178*12909Sgarrison                n = getref(huntstr);
179*12909Sgarrison                if (n > 0)
180*12909Sgarrison                   fprintf(tfd, "%c%ld%c%s%c\\*(}]", CITEMARK, n,
181*12909Sgarrison                                                     CITEMARK, info, CITEEND);
182*12909Sgarrison                else
183*12909Sgarrison                   fprintf(tfd, "%c0%c%s%s%c\\*(}]", CITEMARK, CITEMARK,
184*12909Sgarrison                                               huntstr, info, CITEEND);
185*12909Sgarrison                return;
186*12909Sgarrison                }
187*12909Sgarrison             else
188*12909Sgarrison                addc(huntstr, c);
189*12909Sgarrison             break;
190*12909Sgarrison 
191*12909Sgarrison          case '{':
192*12909Sgarrison             while (getch(c, fd) != '}')
193*12909Sgarrison                if (c == EOF) {
194*12909Sgarrison                   fprintf(stderr, "Error: ill formed reference\n");
195*12909Sgarrison                   exit(1);
196*12909Sgarrison                   }
197*12909Sgarrison                 else
198*12909Sgarrison                   addc(info, c);
199*12909Sgarrison             break;
200*12909Sgarrison 
201*12909Sgarrison          case '\n':
202*12909Sgarrison          case '\t':
203*12909Sgarrison             c = ' ';   /* fall through */
204*12909Sgarrison 
205*12909Sgarrison          default:
206*12909Sgarrison             addc(huntstr,c);
207*12909Sgarrison          }
208*12909Sgarrison    error("end of file reading citation");
209*12909Sgarrison }
210*12909Sgarrison 
211*12909Sgarrison /* addc - add a character to hunt string */
212*12909Sgarrison    addc(huntstr, c)
213*12909Sgarrison    char huntstr[HUNTSIZE], c;
214*12909Sgarrison {  int  i;
215*12909Sgarrison 
216*12909Sgarrison    i = strlen(huntstr);
217*12909Sgarrison    if (i > HUNTSIZE)
218*12909Sgarrison       error("citation too long");
219*12909Sgarrison    huntstr[i] = c;
220*12909Sgarrison    huntstr[i+1] = 0;
221*12909Sgarrison }
222*12909Sgarrison 
223*12909Sgarrison /* getref - if an item was already referenced, return its pointer in
224*12909Sgarrison                 the reference file, otherwise create a new entry */
225*12909Sgarrison    long int getref(huntstr)
226*12909Sgarrison    char huntstr[HUNTSIZE];
227*12909Sgarrison {  char rf[REFSIZE], ref[REFSIZE], *r, *hunt();
228*12909Sgarrison    int  i, match(), getwrd();
229*12909Sgarrison 
230*12909Sgarrison    r = hunt(huntstr);
231*12909Sgarrison    if (r != NULL) {
232*12909Sgarrison       /* exapand defined string */
233*12909Sgarrison       strcpy(rf, r);
234*12909Sgarrison       free(r);
235*12909Sgarrison       expand(rf);
236*12909Sgarrison 
237*12909Sgarrison       /* see if reference has already been cited */
238*12909Sgarrison 
239*12909Sgarrison       if (foot == false)
240*12909Sgarrison          for (i = 0; i <= numrefs; i++) {
241*12909Sgarrison              rdref(refspos[i], ref);
242*12909Sgarrison              if (strcmp(ref, rf) == 0)
243*12909Sgarrison                 return(refspos[i]);
244*12909Sgarrison           }
245*12909Sgarrison 
246*12909Sgarrison       /* didn't match any existing reference, create new one */
247*12909Sgarrison 
248*12909Sgarrison       numrefs++;
249*12909Sgarrison       refspos[numrefs] = rend;
250*12909Sgarrison       fseek(rfd, rend, 0);
251*12909Sgarrison       i = strlen(rf) + 1;
252*12909Sgarrison       fwrite(rf, 1, i, rfd);
253*12909Sgarrison       rend = rend + i;
254*12909Sgarrison       return(refspos[numrefs]);
255*12909Sgarrison       }
256*12909Sgarrison    else {
257*12909Sgarrison       fprintf(stderr,"no reference matching %s\n", huntstr);
258*12909Sgarrison       return( (long) -1 );
259*12909Sgarrison       }
260*12909Sgarrison }
261*12909Sgarrison 
262*12909Sgarrison /* rdref - read text for an already cited reference */
263*12909Sgarrison    rdref(i, ref)
264*12909Sgarrison    long int  i;
265*12909Sgarrison    char ref[REFSIZE];
266*12909Sgarrison {
267*12909Sgarrison    ref[0] = 0;
268*12909Sgarrison    fseek(rfd, i, 0);
269*12909Sgarrison    fread(ref, 1, REFSIZE, rfd);
270*12909Sgarrison }
271*12909Sgarrison 
272*12909Sgarrison /* hunt - hunt for reference from either personal or system index */
273*12909Sgarrison    char *hunt(huntstr)
274*12909Sgarrison    char huntstr[];
275*12909Sgarrison {  char *fhunt(), *r, *p, *q, fname[120];
276*12909Sgarrison 
277*12909Sgarrison    if (personal) {
278*12909Sgarrison       for (p = fname, q = pfile; ; q++)
279*12909Sgarrison          if (*q == ',' || *q == 0) {
280*12909Sgarrison             *p = 0;
281*12909Sgarrison             if ((r = fhunt(fname, huntstr)) != NULL)
282*12909Sgarrison                return(r);
283*12909Sgarrison             else if (*q == 0)
284*12909Sgarrison                break;
285*12909Sgarrison             p = fname;
286*12909Sgarrison             }
287*12909Sgarrison          else *p++ = *q;
288*12909Sgarrison       }
289*12909Sgarrison    else if (findex) {
290*12909Sgarrison       if ((r = fhunt( INDXFILE , huntstr)) != NULL)
291*12909Sgarrison          return(r);
292*12909Sgarrison       }
293*12909Sgarrison    if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
294*12909Sgarrison       return(r);
295*12909Sgarrison    return(NULL);
296*12909Sgarrison }
297*12909Sgarrison 
298*12909Sgarrison /* fhunt - hunt from a specific file */
299*12909Sgarrison    char *fhunt(file, huntstr)
300*12909Sgarrison    char file[], huntstr[];
301*12909Sgarrison {  char *p, *r, *locate();
302*12909Sgarrison 
303*12909Sgarrison    r = locate(huntstr, file, 6, common);
304*12909Sgarrison 
305*12909Sgarrison    if (r == NULL)
306*12909Sgarrison       return(NULL);  /* error */
307*12909Sgarrison    if (*r == 0)
308*12909Sgarrison       return(NULL);  /* no match */
309*12909Sgarrison 
310*12909Sgarrison    for (p = r; *p; p++)
311*12909Sgarrison       if (*p == '\n')
312*12909Sgarrison          if (*(p+1) == '\n') { /* end */
313*12909Sgarrison             if (*(p+2) != 0)
314*12909Sgarrison                fprintf(stderr,"multiple references match %s\n",huntstr);
315*12909Sgarrison             *(p+1) = 0;
316*12909Sgarrison             break;
317*12909Sgarrison             }
318*12909Sgarrison          else if (*(p+1) != '%' && *(p+1) != '.') /* unnecessary newline */
319*12909Sgarrison             *p = ' ';
320*12909Sgarrison    return(r);
321*12909Sgarrison }
322*12909Sgarrison 
323*12909Sgarrison /* rcomp - reference comparison routine for qsort utility */
324*12909Sgarrison    int rcomp(ap, bp)
325*12909Sgarrison    long int *ap, *bp;
326*12909Sgarrison {  char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD];
327*12909Sgarrison    char *p, *q, *getfield();
328*12909Sgarrison    int  neg, res;
329*12909Sgarrison 
330*12909Sgarrison    rdref(*ap, ref1);
331*12909Sgarrison    rdref(*bp, ref2);
332*12909Sgarrison    for (p = sortstr; *p; p = q) {
333*12909Sgarrison       if (*p == '-') {
334*12909Sgarrison          p++;
335*12909Sgarrison          neg = true;
336*12909Sgarrison          }
337*12909Sgarrison       else
338*12909Sgarrison          neg = false;
339*12909Sgarrison       q = getfield(p, field1, ref1);
340*12909Sgarrison       if (q == 0)
341*12909Sgarrison          res = 1;
342*12909Sgarrison       else if (getfield(p, field2, ref2) == 0)
343*12909Sgarrison          res = -1;
344*12909Sgarrison       else {
345*12909Sgarrison          if (*p == 'A') {
346*12909Sgarrison             if (isupper(field1[0]))
347*12909Sgarrison                field1[0] -= 'A' - 'a';
348*12909Sgarrison             if (isupper(field2[0]))
349*12909Sgarrison                field2[0] -= 'A' - 'a';
350*12909Sgarrison             }
351*12909Sgarrison          res = strcmp(field1, field2);
352*12909Sgarrison          }
353*12909Sgarrison       if (neg)
354*12909Sgarrison          res = - res;
355*12909Sgarrison       if (res != 0)
356*12909Sgarrison          break;
357*12909Sgarrison       }
358*12909Sgarrison    if (res == 0)
359*12909Sgarrison       if (ap < bp)
360*12909Sgarrison          res = -1;
361*12909Sgarrison       else
362*12909Sgarrison          res = 1;
363*12909Sgarrison    return(res);
364*12909Sgarrison }
365*12909Sgarrison 
366*12909Sgarrison /* makecites - make citation strings */
367*12909Sgarrison    makecites(citestr)
368*12909Sgarrison    char *citestr[];
369*12909Sgarrison {  char ref[REFSIZE], tempcite[100], *malloc();
370*12909Sgarrison    int  i;
371*12909Sgarrison 
372*12909Sgarrison    for (i = 0; i <= numrefs; i++) {
373*12909Sgarrison       rdref(refspos[i], ref);
374*12909Sgarrison       bldcite(tempcite, i, ref);
375*12909Sgarrison       citestr[i] = malloc(2 + strlen(tempcite)); /* leave room for disambig */
376*12909Sgarrison       if (citestr[i] == NULL)
377*12909Sgarrison          error("out of storage");
378*12909Sgarrison       strcpy(citestr[i], tempcite);
379*12909Sgarrison       }
380*12909Sgarrison }
381*12909Sgarrison 
382*12909Sgarrison /* bldcite - build a single citation string */
383*12909Sgarrison    bldcite(cp, i, ref)
384*12909Sgarrison    char *cp, ref[];
385*12909Sgarrison    int  i;
386*12909Sgarrison {  char *p, *q, c, *fp, *np, field[REFSIZE], temp[100], *getfield();
387*12909Sgarrison    int  j;
388*12909Sgarrison 
389*12909Sgarrison    getfield("F", field, ref);
390*12909Sgarrison    if (field[0] != 0)
391*12909Sgarrison       for (p = field; *p; p++)
392*12909Sgarrison          *cp++ = *p;
393*12909Sgarrison    else {
394*12909Sgarrison       p = citetemplate;
395*12909Sgarrison       field[0] = 0;
396*12909Sgarrison       while (c = *p++)
397*12909Sgarrison          if (isalpha(c)) {
398*12909Sgarrison             q = getfield(p-1, field, ref);
399*12909Sgarrison             if (q != 0) {
400*12909Sgarrison                p = q;
401*12909Sgarrison                for (fp = field; *fp; )
402*12909Sgarrison                   *cp++ = *fp++;
403*12909Sgarrison                }
404*12909Sgarrison             }
405*12909Sgarrison          else if (c == '1') {
406*12909Sgarrison             sprintf(field,"%d",1 + i);
407*12909Sgarrison             for (fp = field; *fp; )
408*12909Sgarrison                *cp++ = *fp++;
409*12909Sgarrison             }
410*12909Sgarrison          else if (c == '2') {
411*12909Sgarrison             if (getname(1, field, temp, ref)) {
412*12909Sgarrison                np = cp;
413*12909Sgarrison                fp = field;
414*12909Sgarrison                for (j = 1; j <= 3; j++)
415*12909Sgarrison                   if (*fp != 0)
416*12909Sgarrison                      *cp++ = *fp++;
417*12909Sgarrison                if (getname(2, field, temp, ref))
418*12909Sgarrison                   np[2] = field[0];
419*12909Sgarrison                if (getname(3, field, temp, ref)) {
420*12909Sgarrison                   np[1] = np[2];
421*12909Sgarrison                   np[2] = field[0];
422*12909Sgarrison                   }
423*12909Sgarrison                }
424*12909Sgarrison             }
425*12909Sgarrison          else if (c == '{') {
426*12909Sgarrison             while (*p ^= '}')
427*12909Sgarrison                if (*p == 0)
428*12909Sgarrison                   error("unexpected end of citation template");
429*12909Sgarrison                else
430*12909Sgarrison                   *cp++ = *p++;
431*12909Sgarrison             p++;
432*12909Sgarrison             }
433*12909Sgarrison          else if (c == '<') {
434*12909Sgarrison             while (*p ^= '>')
435*12909Sgarrison                if (*p == 0)
436*12909Sgarrison                   error("unexpected end of citation template");
437*12909Sgarrison                else
438*12909Sgarrison                   *cp++ = *p++;
439*12909Sgarrison             p++;
440*12909Sgarrison             }
441*12909Sgarrison          else if (c != '@')
442*12909Sgarrison             *cp++ = c;
443*12909Sgarrison       }
444*12909Sgarrison    *cp++ = 0;
445*12909Sgarrison }
446*12909Sgarrison 
447*12909Sgarrison /* getfield - get a single field from reference */
448*12909Sgarrison    char *getfield(ptr, field, ref)
449*12909Sgarrison    char *ptr, field[], ref[];
450*12909Sgarrison {  char *p, *q, temp[100];
451*12909Sgarrison    int  n, len, i, getname();
452*12909Sgarrison 
453*12909Sgarrison    field[0] = 0;
454*12909Sgarrison    if (*ptr == 'A')
455*12909Sgarrison       getname(1, field, temp, ref);
456*12909Sgarrison    else
457*12909Sgarrison       for (p = ref; *p; p++)
458*12909Sgarrison          if (*p == '%' && *(p+1) == *ptr) {
459*12909Sgarrison             for (p = p + 2; *p == ' '; p++)
460*12909Sgarrison                ;
461*12909Sgarrison             for (q = field; *p != '\n'; )
462*12909Sgarrison                *q++ = *p++;
463*12909Sgarrison             *q = 0;
464*12909Sgarrison             break;
465*12909Sgarrison             }
466*12909Sgarrison    n = 0;
467*12909Sgarrison    len = strlen(field);
468*12909Sgarrison    if (*++ptr == '-') {
469*12909Sgarrison       for (ptr++; isdigit(*ptr); ptr++)
470*12909Sgarrison          n = 10 * n + (*ptr - '0');
471*12909Sgarrison       if (n > len)
472*12909Sgarrison          n = 0;
473*12909Sgarrison       else
474*12909Sgarrison          n = len - n;
475*12909Sgarrison       for (i = 0; field[i] = field[i+n]; i++)
476*12909Sgarrison          ;
477*12909Sgarrison       }
478*12909Sgarrison    else if (isdigit(*ptr)) {
479*12909Sgarrison       for (; isdigit(*ptr); ptr++)
480*12909Sgarrison          n = 10 * n + (*ptr - '0');
481*12909Sgarrison       if (n > len)
482*12909Sgarrison          n = len;
483*12909Sgarrison       field[n] = 0;
484*12909Sgarrison       }
485*12909Sgarrison 
486*12909Sgarrison    if (*ptr == 'u') {
487*12909Sgarrison       ptr++;
488*12909Sgarrison       for (p = field; *p; p++)
489*12909Sgarrison          if (islower(*p))
490*12909Sgarrison             *p = (*p - 'a') + 'A';
491*12909Sgarrison       }
492*12909Sgarrison    else if (*ptr == 'l') {
493*12909Sgarrison       ptr++;
494*12909Sgarrison       for (p = field; *p; p++)
495*12909Sgarrison          if (isupper(*p))
496*12909Sgarrison             *p = (*p - 'A') + 'a';
497*12909Sgarrison       }
498*12909Sgarrison    return(ptr);
499*12909Sgarrison }
500*12909Sgarrison 
501*12909Sgarrison /* getname - get the nth name field from reference, breaking into
502*12909Sgarrison              first and last names */
503*12909Sgarrison    int getname(n, last, first, ref)
504*12909Sgarrison    int  n;
505*12909Sgarrison    char last[], first[], ref[];
506*12909Sgarrison {  char *p;
507*12909Sgarrison 
508*12909Sgarrison    for (p = ref; *p; p++)
509*12909Sgarrison       if (*p == '%' & *(p+1) == 'A') {
510*12909Sgarrison          n--;
511*12909Sgarrison          if (n == 0) {
512*12909Sgarrison             for (p = p + 2; *p == ' '; p++) ;
513*12909Sgarrison             breakname(p, first, last) ;
514*12909Sgarrison             return(true);
515*12909Sgarrison             }
516*12909Sgarrison          }
517*12909Sgarrison    return(false);
518*12909Sgarrison }
519*12909Sgarrison 
520*12909Sgarrison /* disambiguate - compare adjacent citation strings, and if equal, add
521*12909Sgarrison                   single character disambiguators */
522*12909Sgarrison    disambiguate()
523*12909Sgarrison {  int i, j;
524*12909Sgarrison    char adstr[2];
525*12909Sgarrison 
526*12909Sgarrison    for (i = 0; i < numrefs; i = j) {
527*12909Sgarrison       j = i + 1;
528*12909Sgarrison       if (strcmp(citestr[i], citestr[j])==0) {
529*12909Sgarrison          adstr[0] = 'a'; adstr[1] = 0;
530*12909Sgarrison          for (j = i+1; strcmp(citestr[i],citestr[j]) == 0; j++) {
531*12909Sgarrison             adstr[0] = 'a' + (j-i);
532*12909Sgarrison             strcat(citestr[j], adstr);
533*12909Sgarrison             if (j == numrefs)
534*12909Sgarrison                break;
535*12909Sgarrison             }
536*12909Sgarrison          adstr[0] = 'a';
537*12909Sgarrison          strcat(citestr[i], adstr);
538*12909Sgarrison          }
539*12909Sgarrison      }
540*12909Sgarrison }
541*12909Sgarrison 
542*12909Sgarrison /* putrefs - gather contiguous references together, sort them if called
543*12909Sgarrison    for, hyphenate if necessary, and dump them out */
544*12909Sgarrison int putrefs(ifd, ofd, footrefs, fn)
545*12909Sgarrison FILE *ifd, *ofd;
546*12909Sgarrison int  fn, footrefs[];
547*12909Sgarrison {  int  citenums[MAXATONCE];   /* reference numbers */
548*12909Sgarrison    char *citeinfo[MAXATONCE];  /* reference information */
549*12909Sgarrison    char infoword[HUNTSIZE];    /* information line */
550*12909Sgarrison    int  rtop, n, i, j;         /* number of citations being dumped */
551*12909Sgarrison    char c, *p, *walloc();
552*12909Sgarrison 
553*12909Sgarrison /* first gather contiguous references together, and order them if
554*12909Sgarrison    required      */
555*12909Sgarrison 
556*12909Sgarrison    rtop = -1;
557*12909Sgarrison    do {
558*12909Sgarrison       n = 0;
559*12909Sgarrison       while (isdigit(getch(c, ifd)))
560*12909Sgarrison          n = 10 * n + (c - '0');
561*12909Sgarrison       if (c ^= CITEMARK)
562*12909Sgarrison          error("inconsistant citation found in pass two");
563*12909Sgarrison       if (n == 0) {     /* reference not found */
564*12909Sgarrison          rtop++;
565*12909Sgarrison          j = rtop;
566*12909Sgarrison          citenums[j] = -1;
567*12909Sgarrison          citeinfo[j] = 0;
568*12909Sgarrison          }
569*12909Sgarrison       else {
570*12909Sgarrison          for (i = 0; i <= numrefs; i++)
571*12909Sgarrison             if (refspos[i] == n) { /* its the ith item in reference list */
572*12909Sgarrison                rtop++;
573*12909Sgarrison                j = rtop;
574*12909Sgarrison                if (ordcite)
575*12909Sgarrison                   for ( ; j > 0 && citenums[j-1] > i; j--) {
576*12909Sgarrison                      citenums[j] = citenums[j-1];
577*12909Sgarrison                      citeinfo[j] = citeinfo[j-1];
578*12909Sgarrison                      }
579*12909Sgarrison                citenums[j] = i;
580*12909Sgarrison                citeinfo[j] = 0;
581*12909Sgarrison                break;
582*12909Sgarrison                }
583*12909Sgarrison          if (i > numrefs)
584*12909Sgarrison             error("citation not found in pass two");
585*12909Sgarrison          }
586*12909Sgarrison       if (getch(c, ifd) != CITEEND) {
587*12909Sgarrison          for (p = infoword; c != CITEEND ; ) {
588*12909Sgarrison             *p++ = c;
589*12909Sgarrison             getch(c, ifd);
590*12909Sgarrison             }
591*12909Sgarrison          *p = 0;
592*12909Sgarrison          citeinfo[j] = walloc(infoword);
593*12909Sgarrison          }
594*12909Sgarrison       getch(c, ifd);
595*12909Sgarrison       }  while (c == CITEMARK);
596*12909Sgarrison    ungetc(c, ifd);
597*12909Sgarrison 
598*12909Sgarrison    /* now dump out values */
599*12909Sgarrison    for (i = 0; i <= rtop; i++) {
600*12909Sgarrison       if (citenums[i] >= 0)
601*12909Sgarrison          fputs(citestr[citenums[i]], ofd);
602*12909Sgarrison       if (citeinfo[i]) {
603*12909Sgarrison          fputs(citeinfo[i], ofd);
604*12909Sgarrison          free(citeinfo[i]);
605*12909Sgarrison          }
606*12909Sgarrison       if (hyphen) {
607*12909Sgarrison          for (j = 1; j + i <= rtop && citenums[i+j] == citenums[i] + j; j++);
608*12909Sgarrison          if (j + i > rtop) j = rtop;
609*12909Sgarrison          else j = j + i - 1;
610*12909Sgarrison          }
611*12909Sgarrison       else
612*12909Sgarrison          j = i;
613*12909Sgarrison       if (j > i + 1) {
614*12909Sgarrison          fputs("\\*(]-", ofd);
615*12909Sgarrison          i = j - 1;
616*12909Sgarrison          }
617*12909Sgarrison       else if (i != rtop)
618*12909Sgarrison          fputs("\\*(],", ofd);
619*12909Sgarrison       if (foot) {
620*12909Sgarrison          fn++;
621*12909Sgarrison          footrefs[fn] = citenums[i];
622*12909Sgarrison          }
623*12909Sgarrison       }
624*12909Sgarrison    return(fn);
625*12909Sgarrison }
626*12909Sgarrison 
627*12909Sgarrison /* pass2 - read pass 1 files entering citation */
628*12909Sgarrison    pass2(ifd, ofd)
629*12909Sgarrison    FILE *ifd, *ofd;
630*12909Sgarrison {
631*12909Sgarrison    char c;
632*12909Sgarrison    int  i, fn, footrefs[25], dumped;
633*12909Sgarrison 
634*12909Sgarrison    fn = -1;
635*12909Sgarrison    dumped = foot;
636*12909Sgarrison    while (getch(c, ifd) != EOF) {
637*12909Sgarrison       while (c == '\n') {
638*12909Sgarrison          putc(c, ofd);
639*12909Sgarrison          if (foot && fn >= 0) {
640*12909Sgarrison             for (i = 0; i <= fn; i++)
641*12909Sgarrison                 dumpref(footrefs[i], ofd);
642*12909Sgarrison             fn = -1;
643*12909Sgarrison             }
644*12909Sgarrison          if (testc(c, '.', ifd, ofd))
645*12909Sgarrison             if (testc(c, '[', ifd, ofd))
646*12909Sgarrison                if (testc(c, ']', ifd, ofd)) {
647*12909Sgarrison                   while (echoc(c, ifd, ofd) != '\n')
648*12909Sgarrison                      ;
649*12909Sgarrison                   dumped = true;
650*12909Sgarrison                   for (i = 0; i <= numrefs; i++)
651*12909Sgarrison                      dumpref(i, ofd);
652*12909Sgarrison                   getch(c, ifd);
653*12909Sgarrison                   }
654*12909Sgarrison          }
655*12909Sgarrison       if (c == CITEMARK)
656*12909Sgarrison          fn = putrefs(ifd, ofd, footrefs, fn);
657*12909Sgarrison       else if (c != EOF)
658*12909Sgarrison          putc(c, ofd);
659*12909Sgarrison       }
660*12909Sgarrison    if (dumped == false)
661*12909Sgarrison       fprintf(stderr,"Warning: references never dumped\n");
662*12909Sgarrison }
663*12909Sgarrison 
664*12909Sgarrison 
665*12909Sgarrison /* dumpref - dump reference number i */
666*12909Sgarrison    dumpref(i, ofd)
667*12909Sgarrison    int i;
668*12909Sgarrison    FILE *ofd;
669*12909Sgarrison {  char ref[REFSIZE], *p, line[REFSIZE];
670*12909Sgarrison    int numauths, maxauths, numeds, maxeds;
671*12909Sgarrison 
672*12909Sgarrison    rdref(refspos[i], ref);
673*12909Sgarrison    maxauths = maxeds = 0;
674*12909Sgarrison    numauths = numeds = 0;
675*12909Sgarrison    for (p = ref; *p; p++)
676*12909Sgarrison       if (*p == '%')
677*12909Sgarrison          if (*(p+1) == 'A') maxauths++;
678*12909Sgarrison          else if (*(p+1) == 'E') maxeds++;
679*12909Sgarrison    fprintf(ofd, ".[-\n");
680*12909Sgarrison    fprintf(ofd, ".ds [F %s\n",citestr[i]);
681*12909Sgarrison    fseek(rfd, (long) refspos[i], 0);
682*12909Sgarrison    while (fgets(line, REFSIZE, rfd) != NULL) {
683*12909Sgarrison       if (line[0] == 0)        break;
684*12909Sgarrison       else if (line[0] == '.') fprintf(ofd,"%s",line);
685*12909Sgarrison       else {
686*12909Sgarrison          if (line[0] == '%') {
687*12909Sgarrison             for (p = &line[2]; *p == ' '; p++);
688*12909Sgarrison             if (line[1] == 'A')       numauths++;
689*12909Sgarrison             else if (line[1] == 'E')  numeds++;
690*12909Sgarrison 
691*12909Sgarrison             doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd);
692*12909Sgarrison             }
693*12909Sgarrison          }
694*12909Sgarrison       }
695*12909Sgarrison    fprintf(ofd,".][\n");
696*12909Sgarrison }
697