diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /biblio/tib/src/tib.c |
Initial commit
Diffstat (limited to 'biblio/tib/src/tib.c')
-rw-r--r-- | biblio/tib/src/tib.c | 775 |
1 files changed, 775 insertions, 0 deletions
diff --git a/biblio/tib/src/tib.c b/biblio/tib/src/tib.c new file mode 100644 index 0000000000..fe448c10fe --- /dev/null +++ b/biblio/tib/src/tib.c @@ -0,0 +1,775 @@ +/* + Tib - TeX bibliographic formatter + + Written by J.C. Alexander, University of Maryland + based on "bib," a troff formatter, + written by Tim Budd, University of Arizona. */ + +#include <stdio.h> +#include <ctype.h> +#include "tib.h" + +#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) + +/* 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 */ + + rfd = fopen( INDXFILE , "r"); + if (rfd != NULL) { + findex = true; + tfgets(headerline,240,rfd); + fclose(rfd); + chkindex(indx, headerline, false); + } + + /* get file names from environment */ + + pcom = getenv("COMFILE"); + if (pcom != NULL) + strcpy(common,pcom); + ptemp = getenv("TMPDIR"); + if (ptemp != NULL) { + strcpy(reffile,ptemp); + strcat(reffile,dirsp2); + strcat(reffile,"tibrXXXXXX"); + strcpy(tmp_file,ptemp); + strcat(tmp_file,dirsp2); + strcat(tmp_file,"tibpXXXXXX"); + } + else { + strcat(reffile,TMPREFFILE); + strcat(tmp_file,TMPTEXTFILE); + } + + /* 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) + */ + + pdefst = getenv("DEFSTYLE"); + if (pdefst == NULL) { + if (doargs(argc, argv, DEFSTYLE ) == 0) { + strcpy(bibfname, "<stdin>"); + rdtext(stdin); + } + } + else { + if (doargs(argc, argv, pdefst ) == 0) { + strcpy(bibfname, "<stdin>"); + rdtext(stdin); + } + } + + /* + 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); +} + +/* pass2 - read pass 1 files entering citation */ + pass2(ifd, ofd) + FILE *ifd, *ofd; +{ + char c, d, e; + int i, fn, footrefs[25], dumped; + + fn = -1; + if ((foot) || (c0)) dumped = true; + else dumped = false; + while (getch(c, ifd) != EOF) { + while (c == '\n') { + putc(c, ofd); + if (((foot) || (c0)) && fn >= 0) { + for (i = 0; i <= fn; i++) + dumpref(footrefs[i], ofd); + fn = -1; + } + if (getch(c,ifd) != '.') + ; + else if (getch(d,ifd) != '[') + ungetc(d,ifd); + else if (getch(e,ifd) != ']') { + ungetc(e,ifd); + ungetc(d,ifd);} + else if ((foot == false) && (c0 == false)) { + while (echoc(c, ifd, ofd) != '\n') + ; + dumped = true; + fprintf(ofd,"\\message{REFERENCE LIST}\n\n"); + for (i = 0; i <= numrefs; i++) + dumpref(i, ofd); + getch(c, ifd); + } + } + if (c == CITEMARK) + fn = putrefs(ifd, ofd, footrefs, fn); + else if (c != EOF) + putc(c, ofd); + } + if (dumped == false) + bibwarning("Warning: reference list not made -- .[] not encountered\n",""); +} |