//
// hakihaki.c by Graham Toal; 30 minute hack on 14 May 2007.
//
// I lost my twiki wiki in a disk crash, and anyway I was fed up
// with the wiki-spam it was getting, so when I rebuilt my machine
// I didn't recreate the wiki.  However there were some wiki
// pages that were linked to from other sites, so in order to
// recreate them, I built this trivial hack to create html files
// from the twiki input files which had (mostly) survived the crash.
//
// This will *NOT* develop into a full wiki.  It started off and
// will always remain a quick hack.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void cleanup(int n, int lineno)
{
  if (n != 0) {
    fprintf(stdout, "\n</UL></UL></UL></UL></UL></UL></UL><ADDRESS>GRAHAM!  You messed up the wiki markup again!!!  Detected at line %d</ADDRESS></BODY>\n</HTML>\n",lineno);
  } else {
    fprintf(stdout, "\n<ADDRESS><HR>This page generated by <A HREF=\"http://www.gtoal.com/src/hakihaki/hakihaki.c.html\">HakiHaki</A></ADDRESS>\n</BODY>\n</HTML>\n");
  }
  exit(n);
}

#define exit(n) cleanup(n, __LINE__)

int main(int argc, char **argv)
{
  // This is pretty much the project specification:

  // Keeping track of indents
  // === xx ===for headings
  // ''''s for formatting
  // [] links of various sorts
  // -- sig?
  // WikiWords???
  // maybe embedded HTML?
  int indent = 0;
  int nest[128];
  int level = 0;  // 0 means not in a list, > 0 means in a list
  int em = 0, bf = 0;
  char *s, title[128];
  int c;

  nest[0] = 0;
  c = fgetc(stdin);
  if (c == '#') {
    s = title;
    for (;;) {
      c = fgetc(stdin); if (c == EOF) exit(1); if (c == '\n') break;
      *s++ = c; // 128 limit
    }
    *s = '\0';
  } else {
    ungetc(c, stdin); strcpy(title, "HakiHaki page");
  }
  fprintf(stdout, "<HTML>\n<HEAD>\n<TITLE>%s</TITLE>\n</HEAD>\n<BODY>\n", title);
  for (;;) {
    for (;;) {
      c = fgetc(stdin);
      if (c == EOF) {
          if (em != 0) fprintf(stdout, "</EM>");
          if (bf != 0) fprintf(stdout, "</B>");
          while (level > 0) { fprintf(stdout, "</UL>\n"); level -= 1; }
          fprintf(stdout, "<BR>");
        exit(0);
      }
      if (c == ' ') {
        indent += 1;
      } else if (c == '\t') {
        // align to 8 char
        indent = (indent + 8) & (~7);
      } else {
        ungetc(c, stdin);
        break;
      }
    }
    // now, do we trigger anything based on previous indents?
    if (c == '*') {
      if ((level > 0) && (indent == nest[level])) {
        fprintf(stdout, "<LI>"); (void)fgetc(stdin);
      } else if ((level > 0) && (indent < nest[level])) {
        fprintf(stdout, "</UL><BR>\n<LI>"); (void)fgetc(stdin);
        level -= 1;
      } else {
        // deeper
        nest[++level] = indent; // 128 limit
        fprintf(stdout, "<UL>\n<LI>"); (void)fgetc(stdin);
      }
    } else if (c == '=') {
          int depth = 0;
          if (em != 0) fprintf(stdout, "</EM>");
          if (bf != 0) fprintf(stdout, "</B>");
          while (level > 0) { fprintf(stdout, "</UL>\n"); level -= 1; }
          fprintf(stdout, "<BR>");
          for (;;) {
            c = fgetc(stdin); if (c == EOF) exit(1);
            if (c != '=') break;
            depth += 1;
          }
          if (depth == 1) fprintf(stdout, "<CENTER>");
          fprintf(stdout, "\n<HR><H%0d>", depth+1);
          for (;;) {
            fputc(c, stdout); if (c == EOF) exit(1);
            c = fgetc(stdin);
            if (c == '=') break;
          }
          fprintf(stdout, "</H%0d>", depth+1);
          if (depth == 1) fprintf(stdout, "</CENTER>");
          for (;;) {
            depth -= 1;
            if (depth == 0) break;
            c = fgetc(stdin); if (c == EOF) exit(1);
            if (c != '=') exit(1);
          }
    } else if (c == '\n') {
      if (level == 0) fprintf(stdout, "<P>"); else fprintf(stdout, "<BR>");
      (void)fgetc(stdin);indent = 0;
    } else {
      if (indent < level) {
        fprintf(stdout, "</UL><BR>\n");
        level -= 1;
      }
      if (indent != 0) fprintf(stdout, "<P>");
      if (c == '#') (void)fgetc(stdin);// GT hack to escape leading characters (*, = etc)
      for (;;) {
        c = fgetc(stdin);
        if (c == EOF) {
          if (em != 0) fprintf(stdout, "</EM>");
          if (bf != 0) fprintf(stdout, "</B>");
          while (level > 0) { fprintf(stdout, "</UL>\n"); level -= 1; }
          fprintf(stdout, "<BR>");
          exit(0); //NORMAL EXIT
        }
        if (c == '[') {
          c = fgetc(stdin); if (c == EOF) exit(1);
          if (c == '[') {
            fprintf(stdout, "<");
            for (;;) {
              c = fgetc(stdin); if ((c == '\n') || (c == EOF)) exit(1);
              if (c == ']') break;
              fputc(c, stdout);
            }
            c = fgetc(stdin); if (c == EOF) exit(1);
            if (c != ']') exit(1);
            fprintf(stdout, ">");
          } else {
            s = title;
            for (;;) {
              if ((c == ' ') || (c == ']')) break;
              if ((c == '\n') || (c == EOF)) exit(1);
              *s++ = c;
              c = fgetc(stdin);
            }
            *s = '\0';
            if (strncmp(title, "wiki:Self:", strlen("wiki:Self:")) == 0) {
              fprintf(stdout, "<A HREF=\"../%s\">", title+strlen("wiki:Self:"));
              for (;;) {
                c = fgetc(stdin); if (c == EOF) exit(1);
                if (c == ']') break; if (c == '\n') exit(1);
                fputc(c, stdout);
              }
              fprintf(stdout, "</A>");
            } else if (strncmp(title, "http", strlen("http")) == 0) {
	      fprintf(stdout, "<A HREF=\"%s\">", title);
              for (;;) {
                c = fgetc(stdin); if (c == EOF) exit(1);
                if (c == ']') break; if (c == '\n') exit(1);
                fputc(c, stdout);
              }
            fprintf(stdout, "</A>");
            } else {
	      fprintf(stdout, "[%s%c", title, c);
              if (c == ' ') {
                for (;;) {
                  c = fgetc(stdin); if (c == EOF) exit(1);
                  fputc(c, stdout);
                  if (c == ']') break;
                }
              }
            }
          }
        } else if (c == '\'') {
          int count = 1;
          c = fgetc(stdin);
          if (c == '\'') { // 2
            c = fgetc(stdin);
            if ((c == '\'') && (em == 0)) {
              c = fgetc(stdin); //only for ungetc
              // we have 3 quotes
              if (bf == 0) {
               fprintf(stdout, "<B>");
              } else {
               fprintf(stdout, "</B>");
              }
              bf = 1-bf;
            } else {
              // we have 2 quotes
              if (em == 0) {
               fprintf(stdout, "<EM>");
              } else {
               fprintf(stdout, "</EM>");
              }
              em = 1-em;
            }
          } else {
            // we have 1 quote
            fputc('\'', stdout);
          }
          ungetc(c, stdin);
        } else fputc(c, stdout);
        if (c == '\n') break;
      }
      indent = 0;
    }
  }

  return 0;
}