bib - bibliographic formatter
lookup routines supplied by gary levin 2/82
reworked several new features added, 11/82.
# define HUNTSIZE 512 /* maximum size of hunt string */
# define MAXFIELD 250 /* maximum field length */
# 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) */
long int refspos
[MAXREFS
]; /* reference seek positions */
long int rend
= 1; /* last position in rfd (first char unused)*/
int numrefs
= -1; /* number of references generated so far */
FILE *tfd
; /* output of pass 1 of file(s) */
char tmpfile
[] = TMPTEXTFILE
; /* output of pass 1 */
char common
[] = COMFILE
; /* common word file */
char *citestr
[MAXREFS
]; /* citation strings */
int findex
= false; /* can we read the file INDEX ? */
/* global variables in bibargs */
extern int foot
, sort
, personal
;
extern int hyphen
, ordcite
;
extern char sortstr
[], pfile
[], citetemplate
[];
/* the file INDEX in the current directory is the default index,
rfd
= fopen( INDXFILE
, "r");
/* open temporaries, reffile will contain references collected in
pass 1, and tmpfile will contain text.
rfd
= fopen(reffile
,"w+");
error("can't open temporary reference file");
tfd
= fopen(tmpfile
,"w");
error("can't open temporary output file");
pass1 - read files, looking for citations
arguments are read by doargs (bibargs.c)
if (doargs(argc
, argv
, DEFSTYLE
) == 0)
sort references, make citations, add disambiguating characters
qsort(refspos
, numrefs
+1, sizeof(long), rcomp
);
tfd
= fopen(tmpfile
,"r");
error("can't open temporary output file for reading");
pass 2 - reread files, replacing references
/* 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
);
case '.': fputs("\\*([.", tfd
);
case ',': fputs("\\*([,", tfd
);
case '?': fputs("\\*([?", tfd
);
case ':': fputs("\\*([:", tfd
);
case ';': fputs("\\*([;", tfd
);
case '!': fputs("\\*([!", tfd
);
case '"': fputs("\\*([\"", tfd
);
case '\'': fputs("\\*(['", tfd
);
default : putc(lastc
, tfd
);
case ' ': fputs("\\*(<]", tfd
);
case '.': fputs("\\*(.]", tfd
);
case ',': fputs("\\*(,]", tfd
);
case '?': fputs("\\*(?]", tfd
);
case ':': fputs("\\*(:]", tfd
);
case ';': fputs("\\*(;]", tfd
);
case '!': fputs("\\*(!]", tfd
);
case '"': fputs("\\*(\"]", tfd
);
case '\'': fputs("\\*(']", tfd
);
if (lastc
) putc(lastc
, tfd
);
if (lastc
) putc(lastc
, tfd
);
if (lastc
) putc(lastc
, tfd
);
/* rdcite - read citation information inside a [. command */
char huntstr
[HUNTSIZE
], c
, info
[HUNTSIZE
];
huntstr
[0] = info
[0] = 0;
while (getch(c
, fd
) != EOF
)
fprintf(tfd
, "%c%ld%c%s%c", CITEMARK
, n
, CITEMARK
, info
, CITEEND
);
fprintf(tfd
, "%c0%c%s%s%c", CITEMARK
, CITEMARK
,
huntstr
[0] = info
[0] = 0;
while (getch(c
, fd
) == '.') ;
fprintf(tfd
, "%c%ld%c%s%c\\*(]]", CITEMARK
, n
,
CITEMARK
, info
, CITEEND
);
fprintf(tfd
, "%c0%c%s%s%c\\*(]]", CITEMARK
, CITEMARK
,
fprintf(tfd
, "%c%ld%c%s%c\\*(}]", CITEMARK
, n
,
CITEMARK
, info
, CITEEND
);
fprintf(tfd
, "%c0%c%s%s%c\\*(}]", CITEMARK
, CITEMARK
,
while (getch(c
, fd
) != '}')
fprintf(stderr
, "Error: ill formed reference\n");
c
= ' '; /* fall through */
error("end of file reading citation");
/* addc - add a character to hunt string */
char huntstr
[HUNTSIZE
], c
;
error("citation too long");
/* getref - if an item was already referenced, return its pointer in
the reference file, otherwise create a new entry */
{ char rf
[REFSIZE
], ref
[REFSIZE
], *r
, *hunt();
int i
, match(), getwrd();
/* exapand defined string */
/* see if reference has already been cited */
for (i
= 0; i
<= numrefs
; i
++) {
if (strcmp(ref
, rf
) == 0)
/* didn't match any existing reference, create new one */
return(refspos
[numrefs
]);
fprintf(stderr
,"no reference matching %s\n", huntstr
);
/* rdref - read text for an already cited reference */
fread(ref
, 1, REFSIZE
, rfd
);
/* hunt - hunt for reference from either personal or system index */
{ char *fhunt(), *r
, *p
, *q
, fname
[120];
for (p
= fname
, q
= pfile
; ; q
++)
if (*q
== ',' || *q
== 0) {
if ((r
= fhunt(fname
, huntstr
)) != NULL
)
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
, 6, common
);
return(NULL
); /* error */
return(NULL
); /* no match */
if (*(p
+1) == '\n') { /* end */
fprintf(stderr
,"multiple references match %s\n",huntstr
);
else if (*(p
+1) != '%' && *(p
+1) != '.') /* unnecessary newline */
/* rcomp - reference comparison routine for qsort utility */
{ char ref1
[REFSIZE
], ref2
[REFSIZE
], field1
[MAXFIELD
], field2
[MAXFIELD
];
char *p
, *q
, *getfield();
for (p
= sortstr
; *p
; p
= q
) {
q
= getfield(p
, field1
, ref1
);
} else if (strcmp (field1
, "") == 0) { /* field not found */
getfield("F", field1
, ref1
);
if (strcmp (field1
, "") == 0) {
getfield("I", field1
, ref1
);
if (strcmp (field1
, "") == 0) {
if (getfield(p
, field2
, ref2
) == 0) {
} else if (strcmp (field2
, "") == 0) { /* field not found */
getfield("F", field2
, ref2
);
if (strcmp (field2
, "") == 0) {
getfield("I", field2
, ref2
);
if (strcmp (field2
, "") == 0) {
res
= strcmp(field1
, field2
);
/* makecites - make citation strings */
{ char ref
[REFSIZE
], tempcite
[100], *malloc();
for (i
= 0; i
<= numrefs
; i
++) {
bldcite(tempcite
, i
, ref
);
citestr
[i
] = malloc(2 + strlen(tempcite
)); /* leave room for disambig */
strcpy(citestr
[i
], tempcite
);
/* bldcite - build a single citation string */
{ char *p
, *q
, c
, *fp
, *np
, field
[REFSIZE
], temp
[100], *getfield();
getfield("F", field
, ref
);
q
= getfield(p
-1, field
, ref
);
sprintf(field
,"%d",1 + i
);
if (getname(1, field
, temp
, ref
)) {
if (getname(2, field
, temp
, ref
))
if (getname(3, field
, temp
, ref
)) {
error("unexpected end of citation template");
error("unexpected end of citation template");
/* getfield - get a single field from reference */
char *getfield(ptr
, field
, ref
)
char *ptr
, field
[], ref
[];
{ char *p
, *q
, temp
[100];
int n
, len
, i
, getname();
getname(1, field
, temp
, ref
);
if (*p
== '%' && *(p
+1) == *ptr
) {
for (p
= p
+ 2; *p
== ' '; p
++)
for (q
= field
; *p
!= '\n'; )
for (ptr
++; isdigit(*ptr
); ptr
++)
n
= 10 * n
+ (*ptr
- '0');
for (i
= 0; field
[i
] = field
[i
+n
]; i
++)
else if (isdigit(*ptr
)) {
for (; isdigit(*ptr
); ptr
++)
n
= 10 * n
+ (*ptr
- '0');
/* getname - get the nth name field from reference, breaking into
int getname(n
, last
, first
, ref
)
char last
[], first
[], ref
[];
if (*p
== '%' & (*(p
+1) == 'A' || *(p
+1) == 'E')) {
for (p
= p
+ 2; *p
== ' '; p
++) ;
breakname(p
, first
, last
) ;
/* disambiguate - compare adjacent citation strings, and if equal, add
single character disambiguators */
for (i
= 0; i
< numrefs
; i
= j
) {
if (strcmp(citestr
[i
], citestr
[j
])==0) {
adstr
[0] = 'a'; adstr
[1] = 0;
for (j
= i
+1; strcmp(citestr
[i
],citestr
[j
]) == 0; j
++) {
strcat(citestr
[j
], adstr
);
strcat(citestr
[i
], adstr
);
/* putrefs - gather contiguous references together, sort them if called
for, hyphenate if necessary, and dump them out */
int putrefs(ifd
, ofd
, footrefs
, fn
)
{ int citenums
[MAXATONCE
]; /* reference numbers */
char *citeinfo
[MAXATONCE
]; /* reference information */
char infoword
[HUNTSIZE
]; /* information line */
int rtop
, n
, i
, j
; /* number of citations being dumped */
/* first gather contiguous references together, and order them if
while (isdigit(getch(c
, ifd
)))
error("inconsistant citation found in pass two");
if (n
== 0) { /* reference not found */
for (i
= 0; i
<= numrefs
; i
++)
if (refspos
[i
] == n
) { /* its the ith item in reference list */
for ( ; j
> 0 && citenums
[j
-1] > i
; j
--) {
citenums
[j
] = citenums
[j
-1];
citeinfo
[j
] = citeinfo
[j
-1];
error("citation not found in pass two");
if (getch(c
, ifd
) != CITEEND
) {
for (p
= infoword
; c
!= CITEEND
; ) {
citeinfo
[j
] = walloc(infoword
);
/* now dump out values */
for (i
= 0; i
<= rtop
; i
++) {
fputs(citestr
[citenums
[i
]], ofd
);
for (j
= 1; j
+ i
<= rtop
&& citenums
[i
+j
] == citenums
[i
] + j
; j
++);
if (j
+ i
> rtop
) j
= rtop
;
footrefs
[fn
] = citenums
[i
];
/* 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
);
fprintf(stderr
,"Warning: references never dumped\n");
/* dumpref - dump reference number i */
{ char ref
[REFSIZE
], *p
, line
[REFSIZE
];
int numauths
, maxauths
, numeds
, maxeds
;
if (*(p
+1) == 'A') maxauths
++;
else if (*(p
+1) == 'E') maxeds
++;
fprintf(ofd
, ".ds [F %s\n",citestr
[i
]);
fseek(rfd
, (long) refspos
[i
], 0);
while (fgets(line
, REFSIZE
, rfd
) != NULL
) {
else if (line
[0] == '.') fprintf(ofd
,"%s",line
);
for (p
= &line
[2]; *p
== ' '; p
++);
if (line
[1] == 'A') numauths
++;
else if (line
[1] == 'E') numeds
++;
doline(line
[1], p
, numauths
, maxauths
, numeds
, maxeds
, ofd
);