xref: /csrg-svn/contrib/bib/src/bib.c (revision 15891)
113109Srrh #ifndef lint
2*15891Srrh static char sccsid[] = "@(#)bib.c	2.3	01/24/84";
313109Srrh #endif not lint
415066Sgarrison /*
515066Sgarrison         Bib - bibliographic formatter
613109Srrh 
715066Sgarrison         Authored by: Tim Budd, University of Arizona, 1983.
815066Sgarrison                 lookup routines written by gary levin 2/82
915066Sgarrison 
1015066Sgarrison                 version 7/4/83
1115066Sgarrison 
1215066Sgarrison         Various modifications suggested by:
1315066Sgarrison                 David Cherveny - Duke University Medical Center
1415066Sgarrison                 Phil Garrison - UC Berkeley
1515066Sgarrison                 M. J. Hawley - Yale University
1615066Sgarrison 
1715066Sgarrison 
1815066Sgarrison 
1915066Sgarrison 
2015066Sgarrison                                                         */
2112909Sgarrison # include <stdio.h>
2212909Sgarrison # include <ctype.h>
2312909Sgarrison # include "bib.h"
2412909Sgarrison 
2512909Sgarrison # define HUNTSIZE 512                /* maximum size of hunt string         */
2612909Sgarrison # define MAXREFS  300                /* maximum number of references        */
2712909Sgarrison # define MAXATONCE 35                /* maximum references at one location  */
2812909Sgarrison 
2912909Sgarrison # define getch(c,fd) (c = getc(fd))
3012909Sgarrison # define echoc(c,ifd,ofd) (getch(c,ifd) == EOF ? c : putc(c,ofd))
3112909Sgarrison # define testc(c,d,ifd,ofd) (getch(c, ifd) == d ? putc(c, ofd) : 0)
3212909Sgarrison 
3312909Sgarrison /* global variables */
3412909Sgarrison    FILE *rfd;                   /* reference temporary file              */
3512909Sgarrison    char reffile[] = TMPREFFILE ;/* temporary file (see bib.h)            */
3612909Sgarrison    long int refspos[MAXREFS];   /* reference seek positions              */
3712909Sgarrison    long int rend = 1;           /* last position in rfd (first char unused)*/
3812909Sgarrison    int numrefs = -1;            /* number of references generated so far */
3912909Sgarrison    FILE *tfd;                   /* output of pass 1 of file(s)           */
4012909Sgarrison    char tmpfile[] = TMPTEXTFILE ; /* output of pass 1                    */
4112909Sgarrison    char common[] = COMFILE ;    /* common word file                      */
4212909Sgarrison    char *citestr[MAXREFS];      /* citation strings                      */
4312909Sgarrison    int  findex = false;         /* can we read the file INDEX ?          */
4412909Sgarrison 
4512909Sgarrison /* global variables in bibargs */
4612909Sgarrison    extern int foot, sort, personal;
4715066Sgarrison    extern int hyphen, ordcite, biblineno;
4815066Sgarrison    extern char sortstr[], pfile[], citetemplate[], bibfname[];
4912909Sgarrison 
5012909Sgarrison 
5112909Sgarrison main(argc, argv)
5212909Sgarrison    int argc;
5312909Sgarrison    char **argv;
5412909Sgarrison {  int rcomp();
5512909Sgarrison 
5612909Sgarrison    /* the file INDEX in the current directory is the default index,
5712909Sgarrison       if it is present */
5812909Sgarrison 
5912909Sgarrison    rfd = fopen( INDXFILE , "r");
6012909Sgarrison    if (rfd != NULL) {
6112909Sgarrison       findex = true;
6212909Sgarrison       fclose(rfd);
6312909Sgarrison       }
6412909Sgarrison 
6512909Sgarrison    /* open temporaries, reffile will contain references collected in
6612909Sgarrison       pass 1, and tmpfile will contain text.
6712909Sgarrison    */
6812909Sgarrison    mktemp(reffile);
6912909Sgarrison    rfd = fopen(reffile,"w+");
7012909Sgarrison    if (rfd == NULL)
7112909Sgarrison       error("can't open temporary reference file");
7215066Sgarrison    putc('x', rfd);      /* put garbage in first position (not used) */
7312909Sgarrison    mktemp(tmpfile);
7412909Sgarrison    tfd = fopen(tmpfile,"w");
7512909Sgarrison    if (tfd == NULL)
7612909Sgarrison       error("can't open temporary output file");
7712909Sgarrison 
7812909Sgarrison     /*
7912909Sgarrison        pass1 - read files, looking for citations
8012909Sgarrison                arguments are read by doargs (bibargs.c)
8112909Sgarrison     */
8212909Sgarrison 
8315066Sgarrison    if (doargs(argc, argv, DEFSTYLE ) == 0) {
8415066Sgarrison       strcpy(bibfname, "<stdin>");
8512909Sgarrison       rdtext(stdin);
8615066Sgarrison       }
8712909Sgarrison 
8812909Sgarrison    /*
8912909Sgarrison     sort references, make citations, add disambiguating characters
9012909Sgarrison    */
9112909Sgarrison 
9212909Sgarrison    if (sort)
9312909Sgarrison       qsort(refspos, numrefs+1, sizeof(long), rcomp);
9412909Sgarrison    makecites(citestr);
9512909Sgarrison    disambiguate();
9612909Sgarrison 
9712909Sgarrison    /*
9812909Sgarrison    reopen temporaries
9912909Sgarrison    */
10012909Sgarrison 
10112909Sgarrison    fclose(tfd);
10212909Sgarrison    tfd = fopen(tmpfile,"r");
10312909Sgarrison    if (tfd == NULL)
10412909Sgarrison       error("can't open temporary output file for reading");
10512909Sgarrison 
10612909Sgarrison    /*
10712909Sgarrison    pass 2 - reread files, replacing references
10812909Sgarrison    */
10912909Sgarrison 
11012909Sgarrison    pass2(tfd, stdout);
11112909Sgarrison 
11212909Sgarrison    /*
11312909Sgarrison    clean up
11412909Sgarrison    */
11512909Sgarrison 
11612909Sgarrison    fclose(tfd);
11712909Sgarrison    fclose(rfd);
11812909Sgarrison    unlink(tmpfile);
11912909Sgarrison    unlink(reffile);
12012909Sgarrison    exit(0);
12112909Sgarrison }
12212909Sgarrison 
12312909Sgarrison /* rdtext - read and process a text file, looking for [. commands */
12412909Sgarrison    rdtext(fd)
12512909Sgarrison    FILE *fd;
12612909Sgarrison {  char lastc, c, d;
12712909Sgarrison 
12815066Sgarrison    lastc = '\0';
12915066Sgarrison    biblineno = 1;
13012909Sgarrison    while (getch(c, fd) != EOF)
13112909Sgarrison       if (c == '[' || c == '{')
13212909Sgarrison          if (getch(d, fd) == '.') { /* found a reference */
13312909Sgarrison             if (c == '{') { if (lastc) putc(lastc, tfd);}
13412909Sgarrison             else
13515066Sgarrison                switch (lastc) {
13615066Sgarrison                   case '\0': break;
13715066Sgarrison                   case ' ': fputs("\\*([<", tfd); break;
13815066Sgarrison                   case '.': case ',': case '?': case ':':
13915066Sgarrison                   case ';': case '!': case '"': case '\'':
14015066Sgarrison                             fputs("\\*([", tfd);  /* fall through */
14115066Sgarrison                   default:  putc(lastc, tfd); break;
14215066Sgarrison                   }
14312909Sgarrison             rdcite(fd, c);
14412909Sgarrison             if (c == '[')
14515066Sgarrison                switch (lastc) {
14615066Sgarrison                   case '\0': break;
14715066Sgarrison                   case ' ': fputs("\\*(>]", tfd); break;
14815066Sgarrison                   case '.': case ',': case '?': case ':':
14915066Sgarrison                   case ';': case '!': case '"': case '\'':
15015066Sgarrison                             fprintf(tfd,"\\*(%c]", lastc); break;
15115066Sgarrison                   }
15215066Sgarrison             lastc = '\0';
15312909Sgarrison             }
15412909Sgarrison          else {
15515066Sgarrison             if (lastc != '\0') putc(lastc, tfd);
15612909Sgarrison             ungetc(d, fd);
15712909Sgarrison             lastc = c;
15812909Sgarrison             }
15912909Sgarrison       else {
16015066Sgarrison          if (lastc != '\0') putc(lastc, tfd);
16112909Sgarrison          lastc = c;
16215066Sgarrison          if (c == '\n') biblineno++;
16312909Sgarrison          }
16415066Sgarrison    if (lastc != '\0') putc(lastc, tfd);
16512909Sgarrison }
16612909Sgarrison 
16712909Sgarrison /* rdcite - read citation information inside a [. command */
16812909Sgarrison    rdcite(fd, ch)
16912909Sgarrison    FILE *fd;
17012909Sgarrison    char ch;
17112909Sgarrison {  long int n, getref();
17212909Sgarrison    char huntstr[HUNTSIZE], c, info[HUNTSIZE];
17312909Sgarrison 
17412909Sgarrison    if (ch == '[')
17512909Sgarrison       fputs("\\*([[", tfd);
17612909Sgarrison    else
17712909Sgarrison       fputs("\\*([{", tfd);
17812909Sgarrison    huntstr[0] = info[0] = 0;
17912909Sgarrison    while (getch(c, fd) != EOF)
18012909Sgarrison       switch (c) {
18112909Sgarrison          case ',':
18212909Sgarrison             n = getref(huntstr);
18312909Sgarrison             if (n > 0)
18412909Sgarrison                fprintf(tfd, "%c%ld%c%s%c", CITEMARK, n, CITEMARK, info, CITEEND);
18512909Sgarrison             else
18612909Sgarrison                fprintf(tfd, "%c0%c%s%s%c", CITEMARK, CITEMARK,
18712909Sgarrison                                            huntstr, info, CITEEND);
18812909Sgarrison             huntstr[0] = info[0] = 0;
18912909Sgarrison             break;
19012909Sgarrison 
19112909Sgarrison          case '.':
19212909Sgarrison             while (getch(c, fd) == '.') ;
19312909Sgarrison             if (c == ']') {
19412909Sgarrison                n = getref(huntstr);
19512909Sgarrison                if (n > 0)
19612909Sgarrison                   fprintf(tfd, "%c%ld%c%s%c\\*(]]", CITEMARK, n,
19712909Sgarrison                                                   CITEMARK, info, CITEEND);
19812909Sgarrison                else
19912909Sgarrison                   fprintf(tfd, "%c0%c%s%s%c\\*(]]", CITEMARK, CITEMARK,
20012909Sgarrison                                               huntstr, info, CITEEND);
20112909Sgarrison                return;
20212909Sgarrison                }
20312909Sgarrison             else if (c == '}') {
20412909Sgarrison                n = getref(huntstr);
20512909Sgarrison                if (n > 0)
20612909Sgarrison                   fprintf(tfd, "%c%ld%c%s%c\\*(}]", CITEMARK, n,
20712909Sgarrison                                                     CITEMARK, info, CITEEND);
20812909Sgarrison                else
20912909Sgarrison                   fprintf(tfd, "%c0%c%s%s%c\\*(}]", CITEMARK, CITEMARK,
21012909Sgarrison                                               huntstr, info, CITEEND);
21112909Sgarrison                return;
21212909Sgarrison                }
21312909Sgarrison             else
21412909Sgarrison                addc(huntstr, c);
21512909Sgarrison             break;
21612909Sgarrison 
21712909Sgarrison          case '{':
21812909Sgarrison             while (getch(c, fd) != '}')
21912909Sgarrison                if (c == EOF) {
22012909Sgarrison                   fprintf(stderr, "Error: ill formed reference\n");
22112909Sgarrison                   exit(1);
22212909Sgarrison                   }
22312909Sgarrison                 else
22412909Sgarrison                   addc(info, c);
22512909Sgarrison             break;
22612909Sgarrison 
22712909Sgarrison          case '\n':
22815066Sgarrison             biblineno++;
22912909Sgarrison          case '\t':
23012909Sgarrison             c = ' ';   /* fall through */
23112909Sgarrison 
23212909Sgarrison          default:
23312909Sgarrison             addc(huntstr,c);
23412909Sgarrison          }
23512909Sgarrison    error("end of file reading citation");
23612909Sgarrison }
23712909Sgarrison 
23812909Sgarrison /* addc - add a character to hunt string */
23912909Sgarrison    addc(huntstr, c)
24012909Sgarrison    char huntstr[HUNTSIZE], c;
24112909Sgarrison {  int  i;
24212909Sgarrison 
24312909Sgarrison    i = strlen(huntstr);
24412909Sgarrison    if (i > HUNTSIZE)
24512909Sgarrison       error("citation too long");
24612909Sgarrison    huntstr[i] = c;
24712909Sgarrison    huntstr[i+1] = 0;
24812909Sgarrison }
24912909Sgarrison 
25012909Sgarrison /* getref - if an item was already referenced, return its pointer in
25112909Sgarrison                 the reference file, otherwise create a new entry */
25212909Sgarrison    long int getref(huntstr)
25312909Sgarrison    char huntstr[HUNTSIZE];
25412909Sgarrison {  char rf[REFSIZE], ref[REFSIZE], *r, *hunt();
25512909Sgarrison    int  i, match(), getwrd();
256*15891Srrh    char	*realhstr;
25712909Sgarrison 
258*15891Srrh    realhstr = huntstr;
259*15891Srrh    if (strncmp(huntstr, "$C$", 3) == 0){
260*15891Srrh 	char *from, *to;
261*15891Srrh 	for(from = huntstr + 3, to = citetemplate; *from; from++, to++){
262*15891Srrh 		switch(*from){
263*15891Srrh 		case '\0':
264*15891Srrh 		case ' ':
265*15891Srrh 		case '\n':
266*15891Srrh 		case '\t':	goto outcopy;
267*15891Srrh 		default:	*to = *from;
268*15891Srrh 		}
269*15891Srrh 	}
270*15891Srrh    outcopy: ;
271*15891Srrh 	*to = 0;
272*15891Srrh 	*from = 0;
273*15891Srrh 	realhstr = from + 1;
274*15891Srrh    }
275*15891Srrh    r = hunt(realhstr);
27612909Sgarrison    if (r != NULL) {
27712909Sgarrison       /* exapand defined string */
27812909Sgarrison       strcpy(rf, r);
27912909Sgarrison       free(r);
28012909Sgarrison       expand(rf);
28112909Sgarrison 
28212909Sgarrison       /* see if reference has already been cited */
28312909Sgarrison 
28412909Sgarrison       if (foot == false)
28512909Sgarrison          for (i = 0; i <= numrefs; i++) {
28612909Sgarrison              rdref(refspos[i], ref);
28712909Sgarrison              if (strcmp(ref, rf) == 0)
28812909Sgarrison                 return(refspos[i]);
28912909Sgarrison           }
29012909Sgarrison 
29112909Sgarrison       /* didn't match any existing reference, create new one */
29212909Sgarrison 
29312909Sgarrison       numrefs++;
29412909Sgarrison       refspos[numrefs] = rend;
29515066Sgarrison #ifdef READWRITE
29615066Sgarrison       fixrfd( WRITE );                 /* fix access mode of rfd, if nec. */
29715066Sgarrison #else
29815066Sgarrison       fseek(rfd, rend, 0);             /* go to end of rfd */
29915066Sgarrison #endif
30012909Sgarrison       i = strlen(rf) + 1;
30112909Sgarrison       fwrite(rf, 1, i, rfd);
30212909Sgarrison       rend = rend + i;
30312909Sgarrison       return(refspos[numrefs]);
30412909Sgarrison       }
30512909Sgarrison    else {
306*15891Srrh       bibwarning("no reference matching %s\n", realhstr);
30712909Sgarrison       return( (long) -1 );
30812909Sgarrison       }
30912909Sgarrison }
31012909Sgarrison 
31112909Sgarrison /* hunt - hunt for reference from either personal or system index */
31212909Sgarrison    char *hunt(huntstr)
31312909Sgarrison    char huntstr[];
31412909Sgarrison {  char *fhunt(), *r, *p, *q, fname[120];
31512909Sgarrison 
31612909Sgarrison    if (personal) {
31712909Sgarrison       for (p = fname, q = pfile; ; q++)
31812909Sgarrison          if (*q == ',' || *q == 0) {
31912909Sgarrison             *p = 0;
32012909Sgarrison             if ((r = fhunt(fname, huntstr)) != NULL)
32112909Sgarrison                return(r);
32212909Sgarrison             else if (*q == 0)
32312909Sgarrison                break;
32412909Sgarrison             p = fname;
32512909Sgarrison             }
32612909Sgarrison          else *p++ = *q;
32712909Sgarrison       }
32812909Sgarrison    else if (findex) {
32912909Sgarrison       if ((r = fhunt( INDXFILE , huntstr)) != NULL)
33012909Sgarrison          return(r);
33112909Sgarrison       }
33212909Sgarrison    if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
33312909Sgarrison       return(r);
33412909Sgarrison    return(NULL);
33512909Sgarrison }
33612909Sgarrison 
33712909Sgarrison /* fhunt - hunt from a specific file */
33812909Sgarrison    char *fhunt(file, huntstr)
33912909Sgarrison    char file[], huntstr[];
34012909Sgarrison {  char *p, *r, *locate();
34112909Sgarrison 
34212909Sgarrison    r = locate(huntstr, file, 6, common);
34312909Sgarrison 
34412909Sgarrison    if (r == NULL)
34512909Sgarrison       return(NULL);  /* error */
34612909Sgarrison    if (*r == 0)
34712909Sgarrison       return(NULL);  /* no match */
34812909Sgarrison 
34912909Sgarrison    for (p = r; *p; p++)
35012909Sgarrison       if (*p == '\n')
35112909Sgarrison          if (*(p+1) == '\n') { /* end */
35212909Sgarrison             if (*(p+2) != 0)
35315066Sgarrison                bibwarning("multiple references match %s\n",huntstr);
35412909Sgarrison             *(p+1) = 0;
35512909Sgarrison             break;
35612909Sgarrison             }
35712909Sgarrison          else if (*(p+1) != '%' && *(p+1) != '.') /* unnecessary newline */
35812909Sgarrison             *p = ' ';
35912909Sgarrison    return(r);
36012909Sgarrison }
36112909Sgarrison 
36212909Sgarrison /* putrefs - gather contiguous references together, sort them if called
36312909Sgarrison    for, hyphenate if necessary, and dump them out */
36412909Sgarrison int putrefs(ifd, ofd, footrefs, fn)
36512909Sgarrison FILE *ifd, *ofd;
36612909Sgarrison int  fn, footrefs[];
36712909Sgarrison {  int  citenums[MAXATONCE];   /* reference numbers */
36812909Sgarrison    char *citeinfo[MAXATONCE];  /* reference information */
36912909Sgarrison    char infoword[HUNTSIZE];    /* information line */
37012909Sgarrison    int  rtop, n, i, j;         /* number of citations being dumped */
37112909Sgarrison    char c, *p, *walloc();
37212909Sgarrison 
37312909Sgarrison /* first gather contiguous references together, and order them if
37412909Sgarrison    required      */
37512909Sgarrison 
37612909Sgarrison    rtop = -1;
37712909Sgarrison    do {
37812909Sgarrison       n = 0;
37912909Sgarrison       while (isdigit(getch(c, ifd)))
38012909Sgarrison          n = 10 * n + (c - '0');
38112909Sgarrison       if (c ^= CITEMARK)
38212909Sgarrison          error("inconsistant citation found in pass two");
38312909Sgarrison       if (n == 0) {     /* reference not found */
38412909Sgarrison          rtop++;
38512909Sgarrison          j = rtop;
38612909Sgarrison          citenums[j] = -1;
38712909Sgarrison          citeinfo[j] = 0;
38812909Sgarrison          }
38912909Sgarrison       else {
39012909Sgarrison          for (i = 0; i <= numrefs; i++)
39112909Sgarrison             if (refspos[i] == n) { /* its the ith item in reference list */
39212909Sgarrison                rtop++;
39312909Sgarrison                j = rtop;
39412909Sgarrison                if (ordcite)
39512909Sgarrison                   for ( ; j > 0 && citenums[j-1] > i; j--) {
39612909Sgarrison                      citenums[j] = citenums[j-1];
39712909Sgarrison                      citeinfo[j] = citeinfo[j-1];
39812909Sgarrison                      }
39912909Sgarrison                citenums[j] = i;
40012909Sgarrison                citeinfo[j] = 0;
40112909Sgarrison                break;
40212909Sgarrison                }
40312909Sgarrison          if (i > numrefs)
40412909Sgarrison             error("citation not found in pass two");
40512909Sgarrison          }
40612909Sgarrison       if (getch(c, ifd) != CITEEND) {
40712909Sgarrison          for (p = infoword; c != CITEEND ; ) {
40812909Sgarrison             *p++ = c;
40912909Sgarrison             getch(c, ifd);
41012909Sgarrison             }
41112909Sgarrison          *p = 0;
41212909Sgarrison          citeinfo[j] = walloc(infoword);
41312909Sgarrison          }
41412909Sgarrison       getch(c, ifd);
41512909Sgarrison       }  while (c == CITEMARK);
41612909Sgarrison    ungetc(c, ifd);
41712909Sgarrison 
41812909Sgarrison    /* now dump out values */
41912909Sgarrison    for (i = 0; i <= rtop; i++) {
42012909Sgarrison       if (citenums[i] >= 0)
42112909Sgarrison          fputs(citestr[citenums[i]], ofd);
42212909Sgarrison       if (citeinfo[i]) {
42312909Sgarrison          fputs(citeinfo[i], ofd);
42412909Sgarrison          free(citeinfo[i]);
42512909Sgarrison          }
42612909Sgarrison       if (hyphen) {
42712909Sgarrison          for (j = 1; j + i <= rtop && citenums[i+j] == citenums[i] + j; j++);
42812909Sgarrison          if (j + i > rtop) j = rtop;
42912909Sgarrison          else j = j + i - 1;
43012909Sgarrison          }
43112909Sgarrison       else
43212909Sgarrison          j = i;
43312909Sgarrison       if (j > i + 1) {
43412909Sgarrison          fputs("\\*(]-", ofd);
43512909Sgarrison          i = j - 1;
43612909Sgarrison          }
43712909Sgarrison       else if (i != rtop)
43812909Sgarrison          fputs("\\*(],", ofd);
43912909Sgarrison       if (foot) {
44012909Sgarrison          fn++;
44112909Sgarrison          footrefs[fn] = citenums[i];
44212909Sgarrison          }
44312909Sgarrison       }
44412909Sgarrison    return(fn);
44512909Sgarrison }
44612909Sgarrison 
44712909Sgarrison /* pass2 - read pass 1 files entering citation */
44812909Sgarrison    pass2(ifd, ofd)
44912909Sgarrison    FILE *ifd, *ofd;
45012909Sgarrison {
45112909Sgarrison    char c;
45212909Sgarrison    int  i, fn, footrefs[25], dumped;
45312909Sgarrison 
45412909Sgarrison    fn = -1;
45512909Sgarrison    dumped = foot;
45612909Sgarrison    while (getch(c, ifd) != EOF) {
45712909Sgarrison       while (c == '\n') {
45812909Sgarrison          putc(c, ofd);
45912909Sgarrison          if (foot && fn >= 0) {
46012909Sgarrison             for (i = 0; i <= fn; i++)
46112909Sgarrison                 dumpref(footrefs[i], ofd);
46212909Sgarrison             fn = -1;
46312909Sgarrison             }
46412909Sgarrison          if (testc(c, '.', ifd, ofd))
46512909Sgarrison             if (testc(c, '[', ifd, ofd))
46612909Sgarrison                if (testc(c, ']', ifd, ofd)) {
46712909Sgarrison                   while (echoc(c, ifd, ofd) != '\n')
46812909Sgarrison                      ;
46912909Sgarrison                   dumped = true;
47012909Sgarrison                   for (i = 0; i <= numrefs; i++)
47112909Sgarrison                      dumpref(i, ofd);
47212909Sgarrison                   getch(c, ifd);
47312909Sgarrison                   }
47412909Sgarrison          }
47512909Sgarrison       if (c == CITEMARK)
47612909Sgarrison          fn = putrefs(ifd, ofd, footrefs, fn);
47712909Sgarrison       else if (c != EOF)
47812909Sgarrison          putc(c, ofd);
47912909Sgarrison       }
48012909Sgarrison    if (dumped == false)
48115066Sgarrison       bibwarning("Warning: references never dumped\n","");
48212909Sgarrison }
483