4.4BSD/usr/src/contrib/bib/src/bibinc.c
#include "comments.h"
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/malloc.h>
#include <string.h>
#define NODEBUG /* */
#include "adsdebug.h"
FILE *outfull, *outshort, *inall;
char inbuf[512];
char outbuf[512];
int state, lineno;
bool tibOption, bibOption, troffOption, texOption;
bool usingTibMacros;
bool usingTexProcessor;
bool emittingForTib;
bool emittingForTex;
bool outputRestricted;
#define commentChar '#'
#define restrictChar '?'
#define escapeChar '+'
#define macroChar '|'
#define backwhack '\\'
#define skipBlanks(p) \
while (isspace(*p)) p++; \
if (*p == commentChar) while (*++p != '\0')
#define maxNofLetters 128
#define maxNofFilesPerLetter 8
char letter[maxNofLetters]; int nofLetters;
FILE *letterFiles[maxNofLetters][maxNofFilesPerLetter];
char letterState[maxNofLetters];
# define donothing ' '
# define outfile 'O'
# define deffile 'D'
char *filename[maxNofLetters]; int nofFilenames;
int outputIdx = 0;
void
flushOutbuf()
{
int j;
if (*outbuf != '\0') {
if (outbuf[j=strlen(outbuf)] != '\n') outbuf[j] = '\n';
outbuf[j+1] = '\0';
for (j=0; letterFiles[outputIdx][j] != NULL; j++) {
fputs(outbuf, letterFiles[outputIdx][j]);
}
*outbuf = '\0';
}
}
closeAllFiles()
{
int lidx,j;
flushOutbuf();
fclose(inall);
for (lidx = 1; lidx < nofLetters; lidx++) {
for (j = 0; letterFiles[lidx][j] != NULL; j++) {
fclose(letterFiles[lidx][j]);
}
}
}
error(s)
char *s;
{
fprintf(stderr, "%s\n", s);
fprintf(stderr, "Error near line %d:\n", lineno);
fprintf(stderr, "%s\n", inbuf);
closeAllFiles();
exit(1);
}
ready2out(fileIdx,buf)
int fileIdx;
char *buf;
{
register char *ip;
register char *op;
register char *tp;
bool seenOneBar;
int j;
/* first write outbuf, if it is there (had to wait to write it until
* the continuation slash was appended, if necessary)
*/
flushOutbuf();
outputIdx = fileIdx;
ip = buf;
op = outbuf;
seenOneBar = false;
while (*ip != '\0') {
if (*ip == backwhack) {
/* \& if usingTexProcessor, remove
if usingTibMacros, remove
if usingTroffProcessor, keep
if usingBibMacros, keep
\\ if usingTexProcessor, reduce to \
else keep
\<NULL> remove
/* */
if (*(ip+1) == '\0') ip += 2; /* cont'n slash; ignore it */
else {
if (*(ip+1) == backwhack) {
if (usingTexProcessor) {
*op++ = *ip++; ip++; /* reduce to \ */
}
else { *op++ = *ip++; *op++ = *ip++; } /* keep */
}
else if (*(ip+1) == '&') {
if (usingTexProcessor || usingTibMacros) {
ip += 2; /* skip it */
}
else { *op++ = *ip++; *op++ = *ip++; } /* keep */
}
else { *op++ = *ip++; *op++ = *ip++; } /* keep */
}
}
else if (*ip == macroChar) {
if (seenOneBar) {
if (!usingTibMacros) {
/* check the following character:
* if alphabetic, turn into \& */
if (isalpha(*(ip+1))) {
*op++ = backwhack;
*op++ = '&';
}
}
else *op++ = macroChar;
seenOneBar = false;
}
else {
if (!usingTibMacros) {
/* check the preceding char: if alphabetic, turn into \& */
if (op != outbuf && isalpha(*(op-1))) {
*op++ = backwhack;
*op++ = '&';
}
}
else *op++ = macroChar;
seenOneBar = true;
}
ip++;
}
else if (*ip == commentChar) {
while (op != outbuf && isspace(*--op));
op++;
break;
}
else {
*op++ = *ip++;
}
}
if (seenOneBar) {
fprintf(stderr,"Oops: misbalanced |bars| detected\n%s",buf);
}
*op = '\0';
}
main(argc, argv)
int argc;
char **argv;
{
int opt;
register char *inp;
int lidx;
int i,j;
tibOption = bibOption = troffOption = texOption = false;
for (i=1; i<argc; i++) {
char *cp;
dbg(loop) dbgd(i) dbgs(argv[i])
dbgb(tibOption) dbgb(bibOption) dbgb(troffOption) dbgb(texOption)
eor;
j = 0;
if (argv[i][0] == '-') j = 1;
cp = argv[i];
while (*cp != '\0') {
if (isupper(*cp)) *cp = tolower(*cp);
cp++;
}
if (strcmp(&argv[i][j], "tib") == 0) tibOption = true;
else if (strcmp(&argv[i][j], "troff") == 0) troffOption = true;
else if (strcmp(&argv[i][j], "tex") == 0) texOption = true;
else if (strcmp(&argv[i][j], "bib") == 0) bibOption = true;
else error("Unknown option on invocation line");
}
dbg(opts) dbgb(tibOption) dbgb(bibOption) dbgb(troffOption) dbgb(texOption)
eor;
if (!texOption && !troffOption) troffOption = true;
if (!bibOption && !tibOption) bibOption = true;
if (bibOption) troffOption = true;
if (texOption) tibOption = true;
if ((bibOption && tibOption)
|| (troffOption && texOption)
|| (bibOption && texOption)
|| (troffOption && !bibOption && !tibOption)
|| (tibOption && !troffOption && !texOption)) {
error("Cannot specify this combination of invocation line parameters");
}
usingTibMacros = tibOption;
usingTexProcessor = texOption;
emittingForTib = usingTibMacros;
emittingForTex = usingTexProcessor;
inall = stdin;
state = donothing;
lineno = 0;
fgets(inbuf, sizeof(inbuf), inall);
{ register int i; if (inbuf[i=strlen(inbuf)-1] == '\n') inbuf[i] = '\0'; }
nofLetters = 0;
while (!feof(inall)) {
/* note that state is set across line boundaries and maintained
* across iterations of this loop! */
lineno++;
inp = inbuf;
if (*inp == commentChar)
state = donothing;
else if (*inp == restrictChar) {
inp++;
skipBlanks(inp);
if (*inp == '\0') {
emittingForTib = usingTibMacros;
emittingForTex = usingTexProcessor;
}
else if (strncmp(inp, "bib", 3) == 0) emittingForTib = false;
else if (strncmp(inp, "tib", 3) == 0) emittingForTib = true;
else if (strncmp(inp, "troff", 5) == 0) emittingForTex = false;
else if (strncmp(inp, "tex", 3) == 0) emittingForTex = true;
else error("Unknown restriction word");
while (!isspace(*inp) && *inp != '\0') inp++;
skipBlanks(inp);
if (*inp != '\0')
error("Illegal restriction syntax");
outputRestricted =
(usingTibMacros && !emittingForTib)
|| (!usingTibMacros && emittingForTib)
|| (usingTexProcessor && !emittingForTex)
|| (!usingTexProcessor && emittingForTex);
state = donothing;
}
else if (outputRestricted) {
state = donothing;
}
else if (*inp == escapeChar) {
int cidx;
char flagChar = *++inp;
if (!(flagChar > ' ' && flagChar <= '~')) {
error("Illegal character follows escape char ");
}
state = deffile;
for (lidx=0; lidx < nofLetters; lidx++) {
if (letter[lidx] == flagChar) {
state = letterState[lidx];
break;
}
}
if (state == outfile) {
if (isspace(*(inp+1))) {
*inp = 'D'; /* turn into D <word> <stuff> */
}
else {
inp++; /* arbitrary stuff */
}
ready2out(lidx, inp);
}
else if (state == deffile) {
/* syntax: +<flagChar> <filename>
or: +<flagChar> +<flagChar2> ...
where <flagChar2> has already been defined
/* */
int j;
if (!isspace(*++inp)) {
fprintf(stderr,"%s\n", inp);
error("Single character expected in char definition");
}
/* has this letter already been defined? */
for (j=0; j < nofLetters; j++)
if (letter[j] == flagChar) error("letter already defined");
letter[nofLetters]
= flagChar; /* but don't bump nofLetters yet */
/* do we have a <filename> or +<letter2> ? */
skipBlanks(inp);
if (*inp == escapeChar) {
int k;
/* use this letter's files;
* notice that this letter has not yet been added to the
* letter array; and it won't be until we check to see
* if letter2 exists */
k = 0; /* current letter's file index */
while (*inp == escapeChar) {
bool found;
int i;
found = false;
inp++;
for (i=0; i<nofLetters; i++) {
if (*inp == letter[i]) {
found = true;
for (j=0; letterFiles[i][j] != NULL; j++) {
if (k > maxNofFilesPerLetter)
error(
"Too many files defined for letter");
letterFiles[nofLetters][k++] =
letterFiles[i][j];
}
break;
}
}
if (!found) error("undefined letter in letter list");
inp++;
while (isspace(*inp)) inp++;
}
letterState[nofLetters] = outfile;
letterFiles[nofLetters++][k] = NULL;
/* now the letter is defined */
}
else { /* then we have a file name */
int k;
char tbuf[255];
char *tp;
/* this better define a writable file */
if (nofFilenames == maxNofLetters)
error("too many files defined");
tp = tbuf;
while (isgraph(*inp) && *inp != commentChar) {
*tp++ = *inp++;
if (tp == &tbuf[255]) error("filename too long(?)");
}
*tp = '\0';
filename[nofFilenames] = (char *)malloc(strlen(tbuf)+1);
strcpy(filename[nofFilenames],tbuf);
for (k=0; k < nofFilenames; k++)
if (strcmp(filename[k],tbuf) == 0)
error("File defined twice");
for (k=0; letterFiles[nofLetters][k] != NULL; k++);
if (k > maxNofFilesPerLetter) {
error("Too many files defined for letter");
}
if ((letterFiles[nofLetters][k] =
fopen(filename[nofFilenames],"w")) == NULL)
error("cannot open file");
nofFilenames++;
letterState[nofLetters++] = outfile;
}
while (isspace(*inp)) inp++;
if (*inp != commentChar && *inp != '\0') {
error("Illegal input on file definition line");
}
}
}
else if (state == outfile) {
/* continuation line skip white space */
int j;
if (*outbuf != '\0') strcat(outbuf, "\\");
while (isspace(*inp)) inp++;
ready2out(lidx, inp);
}
fgets(inbuf, sizeof(inbuf), inall);
{ register int i;
if (inbuf[i=strlen(inbuf)-1] == '\n') inbuf[i] = '\0';
}
}
closeAllFiles();
exit(0);
}