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