static char sccsid
[] = "@(#)bib.c 2.11 %G%";
Bib - bibliographic formatter
Authored by: Tim Budd, University of Arizona, 1983.
lookup routines written by gary levin 2/82
Various modifications suggested by:
David Cherveny - Duke University Medical Center
Phil Garrison - UC Berkeley
M. J. Hawley - Yale University
Adapted to use TiB style macro calls (i.e. |macro|)
# define HUNTSIZE 512 /* maximum size of hunt string */
# define MAXREFS 300 /* maximum number of references */
# define MAXATONCE 35 /* maximum references at one location */
# define getch(c,fd) (c = getc(fd))
# define echoc(c,ifd,ofd) (getch(c,ifd) == EOF ? c : putc(c,ofd))
# define testc(c,d,ifd,ofd) (getch(c, ifd) == d ? putc(c, ofd) : 0)
FILE *rfd
; /* reference temporary file */
char reffile
[] = TMPREFFILE
;/* temporary file (see bib.h) */
struct refinfo refinfo
[MAXREFS
]; /* reference information */
struct refinfo
*refssearch();
struct refinfo
*refshash
[HASHSIZE
];
long int rend
= 1; /* last position in rfd (first char unused)*/
int numrefs
= 0; /* number of references generated so far */
FILE *tfd
; /* output of pass 1 of file(s) */
char bibtmpfile
[] = TMPTEXTFILE
; /* output of pass 1 */
char *common
= COMFILE
; /* common word file */
int findex
= false; /* can we read the file INDEX ? */
/* global variables in bibargs */
extern int foot
, doacite
, sort
, max_klen
, personal
;
extern int hyphen
, ordcite
, biblineno
;
extern char sortstr
[], pfile
[], citetemplate
[], bibfname
[];
/* the file INDEX in the current directory is the default index,
InitDirectory(BMACLIB
,N_BMACLIB
);
InitDirectory(COMFILE
,N_COMFILE
);
InitDirectory(DEFSTYLE
,N_DEFSTYLE
);
rfd
= fopen( INDXFILE
, "r");
/* open temporaries, reffile will contain references collected in
pass 1, and bibtmpfile will contain text.
rfd
= fopen(reffile
,"w+");
error("can't open temporary reference file, %s", reffile
);
putc('x', rfd
); /* put garbage in first position (not used) */
tfd
= fopen(bibtmpfile
,"w");
error("can't open temporary output file, %s", bibtmpfile
);
pass1 - read files, looking for citations
arguments are read by doargs (bibargs.c)
if (doargs(argc
, argv
, DEFSTYLE
) == 0) { /* may not return */
strcpy(bibfname
, "<stdin>");
sort references, make citations, add disambiguating characters
qsort(refinfo
, numrefs
, sizeof(struct refinfo
), rcomp
);
tfd
= fopen(bibtmpfile
,"r");
error("can't open temporary output file %s for reading", bibtmpfile
);
pass 2 - reread files, replacing references
/* interrupt processing */
/* rdtext - read and process a text file, looking for [. commands */
while (getch(c
, fd
) != EOF
)
if (c
== '[' || c
== '{')
if (getch(d
, fd
) == '.') { /* found a reference */
if (c
== '{') { if (lastc
) putc(lastc
, tfd
);}
case ' ': fputs("\\*([<", tfd
); break;
case '.': case ',': case '?': case ':':
case ';': case '!': case '"': case '\'':
fputs("\\*([", tfd
); /* fall through */
default: putc(lastc
, tfd
); break;
case ' ': fputs("\\*(>]", tfd
); break;
case '.': case ',': case '?': case ':':
case ';': case '!': case '"': case '\'':
fprintf(tfd
,"\\*(%c]", lastc
); break;
if (lastc
!= '\0') putc(lastc
, tfd
);
if (lastc
!= '\0') putc(lastc
, tfd
);
if (c
== '\n') biblineno
++;
if (lastc
!= '\0') putc(lastc
, tfd
);
/* rdcite - read citation information inside a [. command */
char huntstr
[HUNTSIZE
], c
, info
[HUNTSIZE
];
if (doacite
) fputs("\\*([[", tfd
);
if (doacite
) fputs("\\*([{", tfd
);
huntstr
[0] = info
[0] = 0;
while (getch(c
, fd
) != EOF
)
citemark(info
, huntstr
, "");
huntstr
[0] = info
[0] = 0;
while (getch(c
, fd
) == '.') ;
citemark(info
, huntstr
, "\\*(]]");
citemark(info
, huntstr
, "\\*(}]");
while (getch(c
, fd
) != '}')
error("ill formed reference");
c
= ' '; /* fall through */
error("end of file reading citation");
citemark(info
, huntstr
, tail
)
char *info
, *huntstr
, *tail
;
* getref sets ncitetemplate as a side effect
fprintf(tfd
, "%c%s%c", FMTSTART
, ncitetemplate
, FMTEND
);
fprintf(tfd
, "%c%d%c%s%c%s", c
,n
, c
, info
, CITEEND
, doacite
?tail
:"");
/* addc - add a character to hunt string */
char huntstr
[HUNTSIZE
], c
;
error("citation too long, max of %d", HUNTSIZE
);
/* getref - if an item was already referenced, return its reference index
otherwise create a new entry */
{ char rf
[REFSIZE
], *r
, *hunt();
if (strncmp(huntstr
, "$C$", 3) == 0){
for(from
= huntstr
+ 3, to
= ncitetemplate
; *from
; from
++, to
++){
/* expand defined string */
/* see if reference has already been cited */
if (foot
== false && (rp
= refssearch(rf
))){
/* didn't match any existing reference, create new one */
error("too many references, max of %d", MAXREFS
);
refinfo
[numrefs
].ri_pos
= rend
;
refinfo
[numrefs
].ri_length
= lg
;
refinfo
[numrefs
].ri_hp
= refshash
[hash
];
refinfo
[numrefs
].ri_n
= numrefs
;
refshash
[hash
] = &refinfo
[numrefs
];
wrref(&refinfo
[numrefs
], rf
);
bibwarning("no reference matching %s\n", realhstr
);
struct refinfo
*refssearch(rf
)
for (rp
= refshash
[strhash(rf
)]; rp
; rp
= rp
->ri_hp
){
if (rp
->ri_length
== lg
){
if (strcmp(ref
, rf
) == 0)
/* hunt - hunt for reference from either personal or system index */
/* the old versions would stop at the first index file where a citation
* matched. This is NOT what is desired. I have changed it so that it still
* returns the first citation found, but also reports the existence of
* duplicate entries in an INDEX file as well as across INDEX files.
* Also, we do NOT assume that the SYSINDEX has been Tib'd. Therefore,
* if tib style expansion is in effect, the SYSINDEX is not searched.
* (Besides which, on Sun systems at least, the SYSINDEX files are
* created by refer, not bib, so we can't use them very effectively
* anyway. Besides which again, everything in SYSINDEX is in our
{ char *found
, *fhunt(), *r
, *tp
, *sp
, fname
[120];
for (tp
= fname
, sp
= pfile
; ; sp
++)
if (*sp
== ',' || *sp
== '\0') {
if ((r
= fhunt(fname
, huntstr
)) != NULL
) {
/* we need an option to suppress this message -ads 5/89 */
bibwarning("multiple INDEX files match citation %s\n",
if (found
!= NULL
) return (found
);
if ((r
= fhunt(INDXFILE
, huntstr
)) != NULL
)
if ((r
= fhunt(SYSINDEX
, huntstr
)) != NULL
)
/* fhunt - hunt from a specific file */
char *fhunt(file
, huntstr
)
{ char *p
, *r
, *locate();
r
= locate(huntstr
, file
, max_klen
, common
);
return(NULL
); /* error */
return(NULL
); /* no match */
if (*(p
+1) == '\n') { /* end */
bibwarning("multiple references match %s\n",huntstr
);
else if (*(p
+1) != '%' && *(p
+1) != '.') /* unnecessary newline */
return(p1
->num
- p2
->num
);
/* putrefs - gather contiguous references together, sort them if called
for, hyphenate if necessary, and dump them out */
int putrefs(ifd
, ofd
, footrefs
, fn
)
struct cite cites
[MAXATONCE
];
char infoword
[HUNTSIZE
]; /* information line */
reg
int ncites
, n
, j
; /* number of citations being dumped */
* first gather contiguous references together,
* and order them if required
error("bad cite char 0%03o in pass two",c
);
if (neg
< 0) { /* reference not found */
* Find reference n in the references
for (i
= 0; i
< numrefs
; i
++){
if (refinfo
[i
].ri_n
== n
){
error("citation %d not found in pass 2", n
);
if (getch(c
, ifd
) != CITEEND
) {
for (p
= infoword
; c
!= CITEEND
; ) {
cites
[ncites
-1].info
= walloc(infoword
);
qsort(cites
, ncites
, sizeof(struct cite
), citesort
);
/* now dump out values */
for (i
= 0; i
< ncites
; i
++) {
* rebuild the citation string,
* using the current template in effect
p
= &refinfo
[cites
[i
].num
];
bldcite(tempcite
, cites
[i
].num
, ref
);
strcat(tempcite
, p
->ri_disambig
);
if (doacite
) fputs(tempcite
, ofd
);
if (doacite
) fputs(refinfo
[cites
[i
].num
].ri_cite
, ofd
);
if (!doacite
) fputs("\\&", ofd
);
if (doacite
) fputs(cites
[i
].info
, ofd
);
if (!doacite
) fputs("\\&", ofd
);
j
+ i
<= ncites
&& cites
[i
+j
].num
== cites
[i
].num
+ j
;
} else if (i
!= ncites
- 1) {
footrefs
[fn
] = cites
[i
].num
;
/* pass2 - read pass 1 files entering citation */
int i
, fn
, footrefs
[25], dumped
;
while (getch(c
, ifd
) != EOF
) {
for (i
= 0; i
<= fn
; i
++)
dumpref(footrefs
[i
], ofd
);
if (testc(c
, '.', ifd
, ofd
))
if (testc(c
, '[', ifd
, ofd
))
if (testc(c
, ']', ifd
, ofd
)) {
while (echoc(c
, ifd
, ofd
) != '\n')
for (i
= 0; i
< numrefs
; i
++){
fn
= putrefs(ifd
, ofd
, footrefs
, fn
);
bibwarning("Warning: references never dumped\n","");
while (getch(c
, ifd
) != FMTEND
)
strcpy(citetemplate
, ncitetemplate
);