#include #include #include #include char *title; char *string; int offset, length; int partype, nexttype; int blanklines; char peek; int quotedepth; int stylestack[3], stylecount; int inited; int inblock, inverse, reopen, tailpar, indiv; int forcenewline; int footnotecount, oldcount, infootnotes; char footnoteref[3*sizeof(int) + 1]; char code[5]; int codelength; int startofline; int oldchar; char *styles[] = {"i", "strong", "b"}; char *accent[1 << (8*sizeof(char))]; char *codefrom[] = { "''", "<", ">", "**", "o", "L", "p", "-", "P", "ss", "(r)", "(c)", "TM", "AE", "oo", "+-", "<=", ">=", "Y", "mu", "d", "S", "Pi", "pi", "I", "a_", "o_", "O", "ae", "?", "!", "-.", "./", "f", "~~", "D", "OE", "oe", "/", "<>", ">0<", "++", ".", "%%" /* "@" */, "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; char *codeto[] = { "\"", "<", ">", "†", "°", "£", "§", "•", "¶", "ß", "®", "©", "™", "Æ", "∞", "±", "≤", "≥", "¥", "μ", "∂", "Σ", "Π", "π", "∫", "ª", "º", "Ω", "æ", "¿", "¡", "¬", "√", "ƒ", "≈", "Δ", "Œ", "œ", "÷", "◊", "¤", "‡", "·", "‰" /* apple logo */, "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; #define CODECOUNT ((int) (sizeof(codefrom)/sizeof(char *))) char *header1 = "\n" "\n" "\n" "\n\n" "", *header2 = "\n\n" "\n" "\n" "\n\n", *footer = "\n" "\n"; int getchar1() { int c; if ((c = oldchar) >= -1) { oldchar = -2; return c; } c = getchar(); if (startofline) { if (infootnotes) { while (c != '|') { while ((c = getchar()) != EOF && c != '\n') ; if (c == EOF) break; c = getchar(); } if (c != EOF) { c = getchar(); if (c == ' ') c = getchar(); } } else { while (c == '|' || c == '\t') { while ((c = getchar()) != EOF && c != '\n') ; if (c == EOF) break; c = getchar(); } } } startofline = (c == '\n'); return c; } void ungetc1(c) int c; { oldchar = c; } void peekchar() { peek = getchar1(); ungetc1(peek); } void error(s) char *s; { fprintf(stderr, "%s\n", s); exit(1); } void init() { oldchar = -2; startofline = 1; length = 1; string = malloc(length); if (!string) error("out of memory"); offset = 0; string[offset] = 0; accent['\''] = "acute"; accent['`'] = "grave"; accent['"'] = "uml"; accent['^'] = "circ"; accent['/'] = "slash"; accent[','] = "cedil"; accent['~'] = "tilde"; accent['o'] = "ring"; } void addchar(c) char c; { while (offset + 1 >= length) { length *= 2; string = realloc(string, length); if (!string) error("out of memory"); } string[offset++] = c; string[offset] = 0; } void addstring(s) char *s; { char c; while ((c = *s++)) { while (offset + 1 >= length) { length *= 2; string = realloc(string, length); if (!string) error("out of memory"); } string[offset++] = c; } string[offset] = 0; } void addchar1(c) char c; { switch (c) { case '<': addstring("<"); break; case '>': addstring(">"); break; case '&': addstring("&"); break; default: addchar(c); } } void reset() { int i; offset = 0; string[offset] = 0; for (i = 0; i < stylecount; i++) { addstring("<"); addstring(styles[stylestack[i]]); addstring(">"); } } void addstyle(o, i) int o, i; { addstring(o ? "'); } void dostyle(c) int c; { int i, j, k; for (i = 0; i < stylecount; i++) if (stylestack[i] == c) break; if (i < stylecount) { for (j = stylecount - 1; j > i; j--) addstyle(1, stylestack[j]); addstyle(1, c); for (j = i; j < stylecount - 1; j++) { k = stylestack[j + 1]; stylestack[j] = k; addstyle(0, k); } stylecount = j; } else { stylestack[stylecount++] = c; addstyle(0, c); } } int noskip(type) int type; { int o, c, n, r, savedoldchar, savedstartofline; o = ftell(stdin); savedoldchar = oldchar; savedstartofline = startofline; if (inblock) { while ((c = getchar1()) != EOF) { if (c == '\n') { n = 0; while ((c = getchar1()) != EOF && c == ' ') n++; if (n == 0 && c != '\n') continue; if (n != type && !((n == 4 && type == 6) || (n == 6 && type == 4)) && !((n == 5 && type == 10) || (n == 10 && type == 5))) { r = (n != 0); break; } if (c == EOF) break; } } if (c == EOF) r = 0; } else { while ((c = getchar1()) != EOF) { if (c == '\n') { n = 0; while ((c = getchar1()) != EOF && c == ' ') n++; if (n == 0 && c != '\n') continue; if (n == 0 || (n >= 4 && n <= 6)) { r = (n != 0); break; } if (c == EOF) break; } } if (c == EOF) r = 0; } oldchar = savedoldchar; startofline = savedstartofline; fseek(stdin, o, SEEK_SET); return r; } void printpar() { int i; for (i = stylecount - 1; i >= 0; i--) { addstring(""); } if (partype >= 4 && partype <= 6) { if (partype != inblock && !((partype == 4 && inblock == 6) || (partype == 6 && inblock == 4)) && !((partype == 5 && inblock == 10) || (partype == 10 && inblock == 5))) { printf(""); } inblock = partype; } if (!indiv) { printf("= 4 && nexttype <= 6) || noskip(partype))) printf(" class=\"noskip\""); printf(">"); tailpar = 0; indiv = 1; } if (!inverse || reopen) { printf(""); } if (inverse) printf("", partype == 4 ? "" : " class=\"indent\""); printf("%s", string); if (inverse) printf(""); if (inverse && (nexttype == 4 || nexttype == 6) && !blanklines) printf("
"); else { printf("

"); tailpar = (partype == nexttype); if (blanklines || (!inblock && nexttype >= 4 && nexttype <= 6)) { printf(""); indiv = 0; } if (inverse) reopen = 1; } if (inblock && (blanklines > 1 || (partype != nexttype && !((partype == 4 && nexttype == 6) || (partype == 6 && nexttype == 4)) && !((partype == 5 && nexttype == 10) || (partype == 10 && nexttype == 5))))) { if (indiv) { printf(""); indiv = 0; } printf(""); inblock = 0; inverse = 0; } printf("\n"); if (blanklines) { printf("\n"); blanklines--; } if (blanklines) { if (infootnotes) blanklines--; else printf("
\n"); } while (blanklines) { printf("\n"); blanklines--; } blanklines = 0; reset(); partype = nexttype; nexttype = 0; forcenewline = 0; } void process() { int c, d, n, i, j; char *s; while ((c = getchar1()) != EOF) { if (c == '\t') { while ((c = getchar1()) != '\n') if (c == EOF) { ungetc1(c); break; } continue; } if (c == '\n') { blanklines++; continue; } if (c == ' ') { nexttype = 1; while ((c = getchar1()) != EOF) { if (c != ' ') break; nexttype++; } if (inited) printpar(); else { inited = 1; blanklines = 0; partype = nexttype; nexttype = 0; } ungetc1(c); } else { addchar('\n'); ungetc1(c); } while ((c = getchar1()) != EOF) { if (c == '\n') break; else switch (c) { case ' ': n = 1; while ((c = getchar1()) == ' ') n++; ungetc1(c); if (n < 3) { if (forcenewline) n--; while (n--) addchar(' '); } else addstring(" "); if (forcenewline) { addchar('\n'); forcenewline = 0; } break; case '-': peekchar(); switch (peek) { case '-': (void) getchar1(); peekchar(); if (peek == '-') { (void) getchar1(); addstring("—"); } else addstring("–"); break; case ' ': addchar('-'); n = 0; while ((c = getchar1()) == ' ') n++; if (c == EOF) ungetc1(c); else if (c == '\n') { if (n == 1) forcenewline = 1; else addchar(c); } else { while (n--) addchar(' '); ungetc1(c); } break; case '\n': (void) getchar1(); forcenewline = 1; break; default: addchar('-'); } break; case '`': n = 1; peekchar(); while (peek == '~') { quotedepth--; (void) getchar1(); peekchar(); if (peek == '`') { n++; (void) getchar1(); peekchar(); } else break; } while (n--) { addstring(quotedepth & 1 ? "“" : "‘"); quotedepth++; } break; case '\'': peekchar(); if (isalnum(peek) || peek == '<' || peek == '"' || peek == '~') addstring("’"); else { if (quotedepth > 0) quotedepth--; else fprintf(stderr, "negative quote depth?\n"); addstring(quotedepth & 1 ? "”" : "’"); } break; case '_': case '=': case '*': dostyle(c == '_' ? 0 : c == '=' ? 1 : 2); break; case '<': while ((c = getchar1()) != '>') { if (c == EOF || c == '\n') { ungetc1(c); break; } d = getchar1(); if (d == '>') break; else if (d == EOF || d == '\n') { ungetc1(d); break; } s = accent[d]; if (s) { addchar('&'); addchar(c); addstring(s); addchar(';'); } else { addchar(c); addchar(d); } } break; case '"': i = 0; while ((c = getchar1()) != '"') { if (c == EOF || c == '\n') { ungetc1(c); break; } code[i++] = c; if (i > 4) break; } if (i < 4) { code[i] = 0; for (j = 0; j < CODECOUNT; j++) if (strcmp(code, codefrom[j]) == 0) { addstring(codeto[j]); break; } if (j >= CODECOUNT) for (j = 0; j < i; j++) addchar1(code[j]); } else for (j = 0; j < i; j++) addchar1(code[j]); break; case '~': break; case '&': addstring("&"); break; case '^': while ((c = getchar1()) != EOF) { if (c == '^') break; if (c == '"') { while ((c = getchar1()) != EOF) if (c == '\n' || c == '"') break; } else if (c == '<') { while ((c = getchar1()) != EOF) if (c == '\n' || c == '>') break; } if (c == '\n' || c == EOF) { fprintf(stderr, "unfinished footnote reference?\n"); ungetc1(c); break; } } sprintf(footnoteref, "%d", ++footnotecount); if (infootnotes) { addstring(""); addstring(footnoteref); addstring(". "); } else { addstring(""); addstring(footnoteref); addstring(""); } break; case '{': addstring(""); n = 1; peekchar(); if (peek == '\n') (void) getchar1(); else { while (peek == '{') { n++; (void) getchar1(); peekchar(); } if (n > 1 && peek == '[') { (void) getchar1(); if (peek == '\n') (void) getchar1(); } else for (i = 0; i < n - 1; i++) addchar('{'); } while (n > 0) { if (oldchar >= -1) { c = oldchar; oldchar = -2; } else c = getchar(); switch (c) { case '{': n++; addchar(c); break; case '}': n--; if (n > 0) addchar(c); break; case ']': i = 0; peekchar(); while (n > 0 && peek == '}') { i++; n--; (void) getchar1(); peekchar(); } if (n > 0) { addchar(']'); for (j = 0; j < i; j++) addchar('}'); } if (i == 1) addchar(']'); break; case '\n': addstring("
"); break; case ' ': addstring(" "); break; default: addchar1(c); } } startofline = 0; addstring("
"); break; default: addchar(c); } } } blanklines = 1; printpar(); if (quotedepth != 0) fprintf(stderr, "non-zero quote depth at end?\n"); if (stylecount != 0) fprintf(stderr, "non-zero style count at end?\n"); } int main(argc, argv) int argc; char **argv; { if (argc != 3) error("wrong number of arguments"); title = argv[2]; if (!freopen(argv[1], "r", stdin)) error("could not open file"); init(); printf("%s%s%s%s", header1, title, header2, header3); process(); if (footnotecount) { fseek(stdin, 0, SEEK_SET); oldchar = -2; startofline = 1; stylecount = 0; oldcount = footnotecount; footnotecount = 0; infootnotes = 1; indiv = 0; printf("
\n\n"); reset(); inited = 0; process(); if (footnotecount != oldcount) fprintf(stderr, "footnote counts don't match?\n"); } printf("%s", footer); return 0; }