/* global variables */
FILE *rfd; /* reference temporary file */
char reffile[120]; /* temporary file (see tib.h) */
long int refspos[MAXREFS]; /* reference seek positions */
int unlmark[MAXREFS]; /* underline flags */
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 tmp_file[120]; /* 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 tibargs */
extern int foot, sort, personal, underline, silent, loccit, ibidflag[];
extern int hyphen, ordcite, biblineno, stndout, locflag[], optch2[], c0;
extern int inputflag;
extern char sortstr[], pfile[], citetemplate[], bibfname[], dirsp2[];
extern char suffix[];
main(argc, argv)
int argc;
char **argv;
{ int rcomp1();
FILE *ofd; /* output file */
char *outname;
char *outfname(), *getenv(), *pcom, *pdefst, *ptemp;
int undrline();
char headerline[240];
char *indx = INDXFILE;
char *tfgets(), argchk[3];
int i, strcmp(), clnup();
/* header */
for (i = 1; i < argc; i++) {
strcpy(argchk,OPTCH);
strcat(argchk,"z");
if (strcmp(argv[i],argchk) == 0)
silent = true;
strcpy(argchk,OPTCH);
strcat(argchk,"|");
if (strcmp(argv[i],argchk) == 0)
silent = true;
}
if (silent == false)
fprintf (stderr, "Tib -- version %s, released %s.\n", VERSION, RDATE);
/* the file INDEX in the current directory is the default index,
if it is present */
/* open temporaries, reffile will contain references collected in
pass 1, and tmp_file will contain text. */
mktemp(reffile);
rfd = fopen(reffile,"w+");
if (rfd == NULL)
error("can't open temporary reference file");
putc('x', rfd); /* put garbage in first position (not used) */
mktemp(tmp_file);
tfd = fopen(tmp_file,"w");
if (tfd == NULL)
error("can't open temporary output file");
/*
pass1 - read files, looking for citations
arguments are read by doargs (tibargs.c)
*/
/*
sort references, make citations, add disambiguating characters
*/
if (silent == 0)
fprintf(stderr, "Processing citations ...\n");
if (sort)
qsort(refspos, numrefs+1, sizeof(long), rcomp1);
makecites(citestr);
if (underline)
undrline();
if (citetemplate[0] != '0')
disambiguate();
/*
reopen temporaries
*/
fclose(tfd);
tfd = fopen(tmp_file,"r");
if (tfd == NULL)
error("can't open temporary output file for reading");
/*
pass 2 - reread files, replacing references
*/
if (stndout == true && bibfname != "<stdin>")
pass2(tfd, stdout);
else {
outname = outfname (bibfname);
ofd = fopen (outname, "w");
if (ofd == NULL) {
fprintf(stderr,"can't open %s\n", outname);
clnup();
exit(1);
}
else {
if (silent == 0)
fprintf(stderr, "Writing output file ...\n");
pass2 (tfd, ofd);
fprintf(ofd,"\n");
fclose (ofd);
fprintf (stderr,"Output of tib in %s.\n", outname);
}
}
fclose(tfd);
fclose(rfd);
clnup();
exit(0);
}
/* clean up */
clnup()
{
unlink(tmp_file);
unlink(reffile);
return;
}
/* getwd - get the next 'word' (terminated by non-alpha) from a file */
char *
getwd(fd,getwdflag)
FILE *fd;
int getwdflag;
/* The next word is terminated by non-alpha if getwdflag = 0,
by whitespace if getwdflag != 0 */
/* The result is returned in str. */
{ char c;
char str[120], *pstr;
int bracketflag; /* 1 if file name is enclosed in brackets */
bracketflag = 0;
pstr = str;
*pstr = NULL;
getch(c,fd);
if (getwdflag == 0) {
while (isalpha(c) != 0) {
*pstr++ = c;
getch(c,fd);
}
}
else {
while (c == ' '
|| c == '\n'
|| c == '\t'
|| c == '\%'
|| c == '{'
|| c == EOF) {
if (c == EOF)
error("end of file after \\input");
if (c == '{') bracketflag = 1;
if (c == '\n') biblineno++;
if (c == '\%') {
while (c != '\n') getch(c,fd);
ungetc(c,fd);
}
getch(c,fd);
}
if (bracketflag == 0) {
while (c != ' '
&& c != '\n'
&& c != '\t'
&& c != EOF) {
*pstr++ = c;
getch(c,fd);
}
}
else {
while (c != '}') {
if (c == EOF
|| c == '\n'
|| c == '\%') error("no right brackets on \\input file name");
*pstr++ = c;
getch(c,fd);
while (c == ' ' || c == '\t') getch(c,fd);
}
}
}
*pstr = NULL;
if (bracketflag == 0)
ungetc(c,fd); /* put the first char after wd back */
return(str);
}
/* rdtext - read and process a text file, looking for [. commands */
rdtext(fd)
FILE *fd;
{ char lastc, c, d;
char cmd[120], *getwd();
char lastlc;
int sortdefs();
int percentflag; /* is there % so far on line? */
int putback;
int fctr = 0; /* count of input/include files in stack */
FILE *fstack[32]; /* stack of input/include files */
char fnm[32][120]; /* stack of input/include files names */
char bibfnamet[120]; /* temporary file name */
int biblinenostack[32]; /* stack of line numbers */
sortdefs();
lastc = '\0';
lastlc = '\0';
percentflag = false;
biblineno = 1;
fprintf(tfd,"%cmessage {DOCUMENT TEXT}\n",'\\');
while (getch(c, fd) != EOF || fctr != 0) {
if (c == EOF && fctr != 0) { /* pop file from stack */
fprintf(tfd,"%c",lastc);
fclose(fd);
strcpy(bibfnamet, bibfname);
strcpy(bibfname, fnm[--fctr]);
biblineno = biblinenostack[fctr];
fd = fstack[fctr];
fprintf(stderr, "... processing of %s complete, returning to %s ...\n", bibfnamet, bibfname);
fprintf(tfd,"\\message{)}%%");
c = NULL;
}
if (c == '\\' && percentflag == false && inputflag == true) {
if (lastc != NULL) putc(lastc,tfd);
strcpy(cmd,getwd(fd,0));
if (strcmp(cmd,"input")==0) {
/* found an input file */
strcpy(fnm[fctr], bibfname); /* push current file */
biblinenostack[fctr] = biblineno;
biblineno = 1;
if (fctr == 32)
error("\\input files nested too deeply");
fstack[fctr++] = fd;
strcpy(bibfname,getwd(fd,1)); /* get new file name */
putback = false;
fd = fopen(bibfname,"r");
if (fd == NULL) { /* file not found; */
strcpy(bibfnamet,bibfname); /* try adding .tex */
strcat(bibfname,suffix);
fd = fopen(bibfname,"r");
if (fd == NULL) { /* still can't be found; */
strcpy(bibfname, fnm[--fctr]); /* pop file */
fd = fstack[fctr];
biblineno = biblinenostack[fctr];
if (stndout == false && silent == false)
fprintf (stderr, "'%s', line %d: unable to locate %s, assuming it has no references\n", bibfname, biblineno, bibfnamet);
putback = true;
}
}
if (putback == false) {
if (stndout == false && silent == false)
fprintf(stderr, "Reading input document file %s and looking up references ...\n", bibfname);
fprintf(tfd,"\\message{(%s input by Tib}%%\n", bibfname);
}
else {
fprintf(tfd,"%c",'\\'); /* pass chars on to */
fprintf(tfd,"%s",cmd); /* output file */
fprintf(tfd,"%c",' ');
fprintf(tfd,"%s",bibfnamet);
putback = false;
}
}
else { /* this is just text; */
fprintf(tfd,"%c",'\\'); /* pass it to the file */
fprintf(tfd,"%s",cmd);
}
c = NULL;
lastc = NULL;
}
if (c == '\%')
if (percentflag == false)
if (lastc != '\\') {
percentflag = true;
if (isalpha(lastc) == 0)
if (lastc != '\n')
if (lastc != '\0')
if (lastc != ']')
if (lastc != '>') {
lastlc = lastc;
lastc = '\0';
}
}
if ((c == '[' || c == '<') && lastc != '\\')
if (getch(d, fd) == '.') { /* found a reference */
if (c == '<') { if (lastc) fprintf(tfd,"%c",lastc);}
else
switch (lastc) {
case '\0':
case ' ': fprintf(tfd,"%cLspace ",'\\'); break;
case '.': fprintf(tfd,"%cLperiod ",'\\'); break;
case ',': fprintf(tfd,"%cLcomma ",'\\'); break;
case '?': fprintf(tfd,"%cLquest ",'\\'); break;
case ':': fprintf(tfd,"%cLcolon ",'\\'); break;
case ';': fprintf(tfd,"%cLscolon ",'\\'); break;
case '!': fprintf(tfd,"%cLbang ",'\\'); break;
case '\'': fprintf(tfd,"%cLquote ",'\\'); break;
case '"': fprintf(tfd,"%cLqquote ",'\\'); break;
case '`': fprintf(tfd,"%cLrquote ",'\\'); break;
default: fprintf(tfd,"%c",lastc); break;
}
rdcite(fd, c);
if (c == '[')
switch (lastc) {
case '\0': break;
case ' ': fprintf(tfd,"%cRspace{}",'\\'); break;
case '\n': fprintf(tfd,"%cRspace{}",'\\'); break;
case '.': fprintf(tfd,"%cRperiod{}",'\\'); break;
case ',': fprintf(tfd,"%cRcomma{}",'\\'); break;
case '?': fprintf(tfd,"%cRquest{}",'\\'); break;
case ':': fprintf(tfd,"%cRcolon{}",'\\'); break;
case ';': fprintf(tfd,"%cRscolon{}",'\\'); break;
case '!': fprintf(tfd,"%cRbang{}",'\\'); break;
case '\'': fprintf(tfd,"%cRquote{}",'\\'); break;
case '"': fprintf(tfd,"%cRqquote{}",'\\'); break;
case '`': fprintf(tfd,"%cRrquote{}",'\\'); break;
}
lastc = '\0';
}
else {
if (lastc != '\0') putc(lastc, tfd);
ungetc(d, fd);
lastc = c;
}
else {
if (lastc != '\0') putc(lastc, tfd);
lastc = c;
if (c == '\n' || c == EOF) {
biblineno++;
percentflag = false;
if (lastlc != '\0') {
putc(c,tfd);
getch(d, fd);
if (d == ' ' || d == '\n' || d == '\t' || d == '\%'
|| d == '.') {
ungetc(d, fd);
putc(lastlc,tfd);
lastlc = '\0';
putc('\%',tfd);
/* putc('\n',tfd); */
}
else {
ungetc(d, fd);
lastc = lastlc;
lastlc = '\0';
}
}
}
}
}
if (lastc != '\0') putc(lastc, tfd);
}
/* rdcite - read citation information inside a [. command */
rdcite(fd, ch)
FILE *fd;
char ch;
{ long int n, getref();
char huntstr[HUNTSIZE], c, info[HUNTSIZE], footch[2], c0ch[2];
if (foot)
strcpy(footch,"\n");
else
strcpy(footch,"");
if (c0)
strcpy(c0ch,"\n");
else
strcpy(c0ch,"");
if (ch == '[')
fprintf(tfd,"%cLcitemark ", '\\');
else
fprintf(tfd,"%cLAcitemark ", '\\');
huntstr[0] = info[0] = 0;
while (getch(c, fd) != EOF)
switch (c) {
case ',':
n = getref(huntstr);
if (n > 0)
fprintf(tfd, "%c%ld%c%s%c", CITEMARK, n, CITEMARK, info,
CITEEND);
else
fprintf(tfd, "%c0%c%s%s%c", CITEMARK, CITEMARK,
huntstr, info, CITEEND);
huntstr[0] = info[0] = 0;
break;
case '.':
while (getch(c, fd) == '.') ;
if (c == ']') {
n = getref(huntstr);
if (n > 0) {
fprintf(tfd, "%c%ld%c%s%c%s%cRcitemark %s", CITEMARK, n,
CITEMARK, info, CITEEND, c0ch,'\\',footch);
/* if (foot) {
getch(c, fd);
if (c == ' '|| c== '\n')
fprintf(tfd, "%c ", '\\');
else
putc(c, tfd);
fprintf(tfd, "\n");
}*/
}
else {
fprintf(tfd, "%c0%c%s%s%c%s%cRcitemark%s ", CITEMARK, CITEMARK,
huntstr, info, CITEEND,c0ch, '\\',footch);
/* if (foot) {
getch(c, fd);
if (c == ' '|| c== '\n')
fprintf(tfd, "%c ", '\\');
else
putc(c, tfd);
fprintf(tfd, "\n");
}*/
}
return;
}
else if (c == '>') {
n = getref(huntstr);
if (n > 0) {
fprintf(tfd, "%c%ld%c%s%c%s%cRAcitemark{}%s", CITEMARK, n,
CITEMARK, info, CITEEND,c0ch,'\\',footch);
}
else {
fprintf(tfd, "%c0%c%s%s%c%s%cRAcitemark{}%s", CITEMARK,
CITEMARK,huntstr, info, CITEEND,c0ch,'\\',footch);
}
return;
}
else
addc(huntstr, c);
break;
case '<':
strcat(info, "\\LIcitemark{}");
while (getch(c, fd) != '>')
if (c == EOF) {
fprintf(stderr, "Error: ill formed reference\n");
clnup();
exit(1);
}
else
addc(info, c);
strcat(info, "\\RIcitemark ");
break;
case '\n':
biblineno++;
case '\t':
c = ' '; /* fall through */
default:
addc(huntstr,c);
}
error("end of file reading citation");
}
/* addc - add a character to hunt string */
addc(huntstr, c)
char huntstr[HUNTSIZE], c;
{ int i;
i = strlen(huntstr);
if (i > HUNTSIZE)
error("citation too long");
huntstr[i] = c;
huntstr[i+1] = 0;
}
/* getref - if an item was already referenced, return its pointer in
the reference file, otherwise create a new entry */
long int getref(huntstr)
char huntstr[HUNTSIZE];
{ char rf[REFSIZE], ref[REFSIZE], *r, *hunt();
int i, match(), getwrd();
r = hunt(huntstr);
if (r != NULL) {
/* expand defined string */
strcpy(rf, r);
free(r);
expnd2(rf);
/* see if reference has already been cited */
if (foot == false)
for (i = 0; i <= numrefs; i++) {
rdref(refspos[i], ref);
if (strcmp(ref, rf) == 0)
return(refspos[i]);
}
if (loccit) {
ibidflag[numrefs+1] = false;
locflag[numrefs+1] = false;
for (i = 0; i <= numrefs; i++) {
rdref(refspos[i], ref);
if (strcmp(ref, rf) == 0) {
locflag[numrefs+1] = true;
break;
}
}
rdref(refspos[numrefs], ref);
if (strcmp(ref, rf) == 0)
ibidflag[numrefs+1] = true;
}
/* didn't match any existing reference, create new one */
numrefs++;
refspos[numrefs] = rend;
#ifdef READWRITE
fixrfd( WRITE ); /* fix access mode of rfd, if nec. */
#else
fseek(rfd, rend, 0); /* go to end of rfd */
#endif
i = strlen(rf) + 1;
fwrite(rf, 1, i, rfd);
rend = rend + i;
return(refspos[numrefs]);
}
else {
bibwarning("no reference matching %s\n", huntstr);
return( (long) -1 );
}
}
/* hunt - hunt for reference from either personal or system index */
char *hunt(huntstr)
char huntstr[];
{ char *fhunt(), *r, *p, *q, fname[120];
char *getenv(), *pindx;
if (personal) {
for (p = fname, q = pfile; ; q++)
if (*q == ',' || *q == 0) {
*p = 0;
if ((r = fhunt(fname, huntstr)) != NULL)
return(r);
else if (*q == 0)
break;
p = fname;
}
else *p++ = *q;
}
else if (findex) {
if ((r = fhunt( INDXFILE , huntstr)) != NULL)
return(r);
}
pindx = getenv("SYSINDEX");
if (pindx == NULL) {
if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
return(r);
}
else {
if ((r = fhunt(pindx , huntstr)) != NULL)
return(r);
}
return(NULL);
}
/* fhunt - hunt from a specific file */
char *fhunt(file, huntstr)
char file[], huntstr[];
{ char *p, *r, *locate();
r = locate(huntstr, file, 6, common);
if (r == NULL)
return(NULL); /* error */
if (*r == 0)
return(NULL); /* no match */
for (p = r; *p; p++)
if (*p == '\n')
if (*(p+1) == '\n') { /* end */
if (*(p+2) != 0)
bibwarning("multiple references match %s\n",huntstr);
*(p+1) = 0;
break;
}
else if (*(p+1) != '%' && *(p+1) != '.') /* unnecessary newline */
*p = ' ';
return(r);
}
/* putrefs - gather contiguous references together, sort them if called
for, hyphenate if necessary, and dump them out */
int putrefs(ifd, ofd, footrefs, fn)
FILE *ifd, *ofd;
int fn, footrefs[];
{ 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 */
char c, *p, *walloc();
/* first gather contiguous references together, and order them if
required */
rtop = -1;
do {
n = 0;
while (isdigit(getch(c, ifd)))
n = 10 * n + (c - '0');
if (c ^= CITEMARK)
error("inconsistant citation found in pass two");
if (n == 0) { /* reference not found */
rtop++;
j = rtop;
citenums[j] = -1;
citeinfo[j] = 0;
}
else {
for (i = 0; i <= numrefs; i++)
if (refspos[i] == n) { /* its the ith item in reference list */
rtop++;
j = rtop;
if (ordcite)
for ( ; j > 0 && citenums[j-1] > i; j--) {
citenums[j] = citenums[j-1];
citeinfo[j] = citeinfo[j-1];
}
citenums[j] = i;
citeinfo[j] = 0;
break;
}
if (i > numrefs)
error("citation not found in pass two");
}
if (getch(c, ifd) != CITEEND) {
for (p = infoword; c != CITEEND ; ) {
*p++ = c;
getch(c, ifd);
}
*p = 0;
citeinfo[j] = walloc(infoword);
}
getch(c, ifd);
} while (c == CITEMARK);
ungetc(c, ifd);
/* now dump out values */
for (i = 0; i <= rtop; i++) {
if (citenums[i] >= 0)
fputs(citestr[citenums[i]], ofd);
if (citeinfo[i]) {
fputs(citeinfo[i], ofd);
free(citeinfo[i]);
}
if (hyphen) {
for (j = 1; j + i <= rtop && citenums[i+j] == citenums[i] + j; j++);
if (j + i > rtop) j = rtop;
else j = j + i - 1;
}
else
j = i;
if (j > i + 1) {
fputs("\\Citehyphen ", ofd);
i = j - 1;
}
else if (i != rtop)
if (!c0) fputs("\\Citecomma\n", ofd);
if ((foot) || (c0)) {
fn++;
footrefs[fn] = citenums[i];
}
}
return(fn);
}