#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); }