xref: /csrg-svn/contrib/bib/src/bib.c (revision 15066)
113109Srrh #ifndef lint
2*15066Sgarrison static char sccsid[] = "@(#)bib.c	2.2	09/23/83";
313109Srrh #endif not lint
4*15066Sgarrison /*
5*15066Sgarrison         Bib - bibliographic formatter
613109Srrh 
7*15066Sgarrison         Authored by: Tim Budd, University of Arizona, 1983.
8*15066Sgarrison                 lookup routines written by gary levin 2/82
9*15066Sgarrison 
10*15066Sgarrison                 version 7/4/83
11*15066Sgarrison 
12*15066Sgarrison         Various modifications suggested by:
13*15066Sgarrison                 David Cherveny - Duke University Medical Center
14*15066Sgarrison                 Phil Garrison - UC Berkeley
15*15066Sgarrison                 M. J. Hawley - Yale University
16*15066Sgarrison 
17*15066Sgarrison 
18*15066Sgarrison 
19*15066Sgarrison 
20*15066Sgarrison                                                         */
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;
47*15066Sgarrison    extern int hyphen, ordcite, biblineno;
48*15066Sgarrison    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");
72*15066Sgarrison    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 
83*15066Sgarrison    if (doargs(argc, argv, DEFSTYLE ) == 0) {
84*15066Sgarrison       strcpy(bibfname, "<stdin>");
8512909Sgarrison       rdtext(stdin);
86*15066Sgarrison       }
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 
128*15066Sgarrison    lastc = '\0';
129*15066Sgarrison    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
135*15066Sgarrison                switch (lastc) {
136*15066Sgarrison                   case '\0': break;
137*15066Sgarrison                   case ' ': fputs("\\*([<", tfd); break;
138*15066Sgarrison                   case '.': case ',': case '?': case ':':
139*15066Sgarrison                   case ';': case '!': case '"': case '\'':
140*15066Sgarrison                             fputs("\\*([", tfd);  /* fall through */
141*15066Sgarrison                   default:  putc(lastc, tfd); break;
142*15066Sgarrison                   }
14312909Sgarrison             rdcite(fd, c);
14412909Sgarrison             if (c == '[')
145*15066Sgarrison                switch (lastc) {
146*15066Sgarrison                   case '\0': break;
147*15066Sgarrison                   case ' ': fputs("\\*(>]", tfd); break;
148*15066Sgarrison                   case '.': case ',': case '?': case ':':
149*15066Sgarrison                   case ';': case '!': case '"': case '\'':
150*15066Sgarrison                             fprintf(tfd,"\\*(%c]", lastc); break;
151*15066Sgarrison                   }
152*15066Sgarrison             lastc = '\0';
15312909Sgarrison             }
15412909Sgarrison          else {
155*15066Sgarrison             if (lastc != '\0') putc(lastc, tfd);
15612909Sgarrison             ungetc(d, fd);
15712909Sgarrison             lastc = c;
15812909Sgarrison             }
15912909Sgarrison       else {
160*15066Sgarrison          if (lastc != '\0') putc(lastc, tfd);
16112909Sgarrison          lastc = c;
162*15066Sgarrison          if (c == '\n') biblineno++;
16312909Sgarrison          }
164*15066Sgarrison    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':
228*15066Sgarrison             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();
25612909Sgarrison 
25712909Sgarrison    r = hunt(huntstr);
25812909Sgarrison    if (r != NULL) {
25912909Sgarrison       /* exapand defined string */
26012909Sgarrison       strcpy(rf, r);
26112909Sgarrison       free(r);
26212909Sgarrison       expand(rf);
26312909Sgarrison 
26412909Sgarrison       /* see if reference has already been cited */
26512909Sgarrison 
26612909Sgarrison       if (foot == false)
26712909Sgarrison          for (i = 0; i <= numrefs; i++) {
26812909Sgarrison              rdref(refspos[i], ref);
26912909Sgarrison              if (strcmp(ref, rf) == 0)
27012909Sgarrison                 return(refspos[i]);
27112909Sgarrison           }
27212909Sgarrison 
27312909Sgarrison       /* didn't match any existing reference, create new one */
27412909Sgarrison 
27512909Sgarrison       numrefs++;
27612909Sgarrison       refspos[numrefs] = rend;
277*15066Sgarrison #ifdef READWRITE
278*15066Sgarrison       fixrfd( WRITE );                 /* fix access mode of rfd, if nec. */
279*15066Sgarrison #else
280*15066Sgarrison       fseek(rfd, rend, 0);             /* go to end of rfd */
281*15066Sgarrison #endif
28212909Sgarrison       i = strlen(rf) + 1;
28312909Sgarrison       fwrite(rf, 1, i, rfd);
28412909Sgarrison       rend = rend + i;
28512909Sgarrison       return(refspos[numrefs]);
28612909Sgarrison       }
28712909Sgarrison    else {
28813107Srrh       bibwarning("no reference matching %s\n", huntstr);
28912909Sgarrison       return( (long) -1 );
29012909Sgarrison       }
29112909Sgarrison }
29212909Sgarrison 
29312909Sgarrison /* hunt - hunt for reference from either personal or system index */
29412909Sgarrison    char *hunt(huntstr)
29512909Sgarrison    char huntstr[];
29612909Sgarrison {  char *fhunt(), *r, *p, *q, fname[120];
29712909Sgarrison 
29812909Sgarrison    if (personal) {
29912909Sgarrison       for (p = fname, q = pfile; ; q++)
30012909Sgarrison          if (*q == ',' || *q == 0) {
30112909Sgarrison             *p = 0;
30212909Sgarrison             if ((r = fhunt(fname, huntstr)) != NULL)
30312909Sgarrison                return(r);
30412909Sgarrison             else if (*q == 0)
30512909Sgarrison                break;
30612909Sgarrison             p = fname;
30712909Sgarrison             }
30812909Sgarrison          else *p++ = *q;
30912909Sgarrison       }
31012909Sgarrison    else if (findex) {
31112909Sgarrison       if ((r = fhunt( INDXFILE , huntstr)) != NULL)
31212909Sgarrison          return(r);
31312909Sgarrison       }
31412909Sgarrison    if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
31512909Sgarrison       return(r);
31612909Sgarrison    return(NULL);
31712909Sgarrison }
31812909Sgarrison 
31912909Sgarrison /* fhunt - hunt from a specific file */
32012909Sgarrison    char *fhunt(file, huntstr)
32112909Sgarrison    char file[], huntstr[];
32212909Sgarrison {  char *p, *r, *locate();
32312909Sgarrison 
32412909Sgarrison    r = locate(huntstr, file, 6, common);
32512909Sgarrison 
32612909Sgarrison    if (r == NULL)
32712909Sgarrison       return(NULL);  /* error */
32812909Sgarrison    if (*r == 0)
32912909Sgarrison       return(NULL);  /* no match */
33012909Sgarrison 
33112909Sgarrison    for (p = r; *p; p++)
33212909Sgarrison       if (*p == '\n')
33312909Sgarrison          if (*(p+1) == '\n') { /* end */
33412909Sgarrison             if (*(p+2) != 0)
335*15066Sgarrison                bibwarning("multiple references match %s\n",huntstr);
33612909Sgarrison             *(p+1) = 0;
33712909Sgarrison             break;
33812909Sgarrison             }
33912909Sgarrison          else if (*(p+1) != '%' && *(p+1) != '.') /* unnecessary newline */
34012909Sgarrison             *p = ' ';
34112909Sgarrison    return(r);
34212909Sgarrison }
34312909Sgarrison 
34412909Sgarrison /* putrefs - gather contiguous references together, sort them if called
34512909Sgarrison    for, hyphenate if necessary, and dump them out */
34612909Sgarrison int putrefs(ifd, ofd, footrefs, fn)
34712909Sgarrison FILE *ifd, *ofd;
34812909Sgarrison int  fn, footrefs[];
34912909Sgarrison {  int  citenums[MAXATONCE];   /* reference numbers */
35012909Sgarrison    char *citeinfo[MAXATONCE];  /* reference information */
35112909Sgarrison    char infoword[HUNTSIZE];    /* information line */
35212909Sgarrison    int  rtop, n, i, j;         /* number of citations being dumped */
35312909Sgarrison    char c, *p, *walloc();
35412909Sgarrison 
35512909Sgarrison /* first gather contiguous references together, and order them if
35612909Sgarrison    required      */
35712909Sgarrison 
35812909Sgarrison    rtop = -1;
35912909Sgarrison    do {
36012909Sgarrison       n = 0;
36112909Sgarrison       while (isdigit(getch(c, ifd)))
36212909Sgarrison          n = 10 * n + (c - '0');
36312909Sgarrison       if (c ^= CITEMARK)
36412909Sgarrison          error("inconsistant citation found in pass two");
36512909Sgarrison       if (n == 0) {     /* reference not found */
36612909Sgarrison          rtop++;
36712909Sgarrison          j = rtop;
36812909Sgarrison          citenums[j] = -1;
36912909Sgarrison          citeinfo[j] = 0;
37012909Sgarrison          }
37112909Sgarrison       else {
37212909Sgarrison          for (i = 0; i <= numrefs; i++)
37312909Sgarrison             if (refspos[i] == n) { /* its the ith item in reference list */
37412909Sgarrison                rtop++;
37512909Sgarrison                j = rtop;
37612909Sgarrison                if (ordcite)
37712909Sgarrison                   for ( ; j > 0 && citenums[j-1] > i; j--) {
37812909Sgarrison                      citenums[j] = citenums[j-1];
37912909Sgarrison                      citeinfo[j] = citeinfo[j-1];
38012909Sgarrison                      }
38112909Sgarrison                citenums[j] = i;
38212909Sgarrison                citeinfo[j] = 0;
38312909Sgarrison                break;
38412909Sgarrison                }
38512909Sgarrison          if (i > numrefs)
38612909Sgarrison             error("citation not found in pass two");
38712909Sgarrison          }
38812909Sgarrison       if (getch(c, ifd) != CITEEND) {
38912909Sgarrison          for (p = infoword; c != CITEEND ; ) {
39012909Sgarrison             *p++ = c;
39112909Sgarrison             getch(c, ifd);
39212909Sgarrison             }
39312909Sgarrison          *p = 0;
39412909Sgarrison          citeinfo[j] = walloc(infoword);
39512909Sgarrison          }
39612909Sgarrison       getch(c, ifd);
39712909Sgarrison       }  while (c == CITEMARK);
39812909Sgarrison    ungetc(c, ifd);
39912909Sgarrison 
40012909Sgarrison    /* now dump out values */
40112909Sgarrison    for (i = 0; i <= rtop; i++) {
40212909Sgarrison       if (citenums[i] >= 0)
40312909Sgarrison          fputs(citestr[citenums[i]], ofd);
40412909Sgarrison       if (citeinfo[i]) {
40512909Sgarrison          fputs(citeinfo[i], ofd);
40612909Sgarrison          free(citeinfo[i]);
40712909Sgarrison          }
40812909Sgarrison       if (hyphen) {
40912909Sgarrison          for (j = 1; j + i <= rtop && citenums[i+j] == citenums[i] + j; j++);
41012909Sgarrison          if (j + i > rtop) j = rtop;
41112909Sgarrison          else j = j + i - 1;
41212909Sgarrison          }
41312909Sgarrison       else
41412909Sgarrison          j = i;
41512909Sgarrison       if (j > i + 1) {
41612909Sgarrison          fputs("\\*(]-", ofd);
41712909Sgarrison          i = j - 1;
41812909Sgarrison          }
41912909Sgarrison       else if (i != rtop)
42012909Sgarrison          fputs("\\*(],", ofd);
42112909Sgarrison       if (foot) {
42212909Sgarrison          fn++;
42312909Sgarrison          footrefs[fn] = citenums[i];
42412909Sgarrison          }
42512909Sgarrison       }
42612909Sgarrison    return(fn);
42712909Sgarrison }
42812909Sgarrison 
42912909Sgarrison /* pass2 - read pass 1 files entering citation */
43012909Sgarrison    pass2(ifd, ofd)
43112909Sgarrison    FILE *ifd, *ofd;
43212909Sgarrison {
43312909Sgarrison    char c;
43412909Sgarrison    int  i, fn, footrefs[25], dumped;
43512909Sgarrison 
43612909Sgarrison    fn = -1;
43712909Sgarrison    dumped = foot;
43812909Sgarrison    while (getch(c, ifd) != EOF) {
43912909Sgarrison       while (c == '\n') {
44012909Sgarrison          putc(c, ofd);
44112909Sgarrison          if (foot && fn >= 0) {
44212909Sgarrison             for (i = 0; i <= fn; i++)
44312909Sgarrison                 dumpref(footrefs[i], ofd);
44412909Sgarrison             fn = -1;
44512909Sgarrison             }
44612909Sgarrison          if (testc(c, '.', ifd, ofd))
44712909Sgarrison             if (testc(c, '[', ifd, ofd))
44812909Sgarrison                if (testc(c, ']', ifd, ofd)) {
44912909Sgarrison                   while (echoc(c, ifd, ofd) != '\n')
45012909Sgarrison                      ;
45112909Sgarrison                   dumped = true;
45212909Sgarrison                   for (i = 0; i <= numrefs; i++)
45312909Sgarrison                      dumpref(i, ofd);
45412909Sgarrison                   getch(c, ifd);
45512909Sgarrison                   }
45612909Sgarrison          }
45712909Sgarrison       if (c == CITEMARK)
45812909Sgarrison          fn = putrefs(ifd, ofd, footrefs, fn);
45912909Sgarrison       else if (c != EOF)
46012909Sgarrison          putc(c, ofd);
46112909Sgarrison       }
46212909Sgarrison    if (dumped == false)
463*15066Sgarrison       bibwarning("Warning: references never dumped\n","");
46412909Sgarrison }
465