/* Convert colorForth to html */
#include <stdio.h>

char ch[] = {' ', 'r', 't', 'o', 'e', 'a', 'n', 'i',
             's', 'm', 'c', 'y', 'l', 'g', 'f', 'w',
             'd', 'v', 'p', 'b', 'h', 'x', 'u', 'q',
             '0', '1', '2', '3', '4', '5', '6', '7',
             '8', '9', 'j', '-', 'k', '.', 'z', '/',
             ';', ':', '!', '+', '@', '*', ',', '?'};

char tbuf[255], *ptbuf;
int isanchor, isanchordef;

void print_start (void) {
    ptbuf = tbuf;
    *ptbuf = 0;
    isanchor = 0;
    isanchordef = 0;
}

void print_flush (void) {
    printf(tbuf);
}

void pchar (unsigned int c) {
    *ptbuf++ = c;
    *ptbuf = 0;
}


char *function[] = {"", "execute", "execute", "define", "compile",
                    "compile", "compile", "compilemacro", "execute",
                    "text", "textcapitalized", "textallcaps",
                    "variable", "", "", "", "", "", "executehex", "",
                    "", "compilehex", "compilehex", "", "executehex"};
                    
int needanchor[] = {0, 1, 1, 1, 1,                  /* 4 */
                    1, 1, 1, 1,                     /* 8 */
                    0, 0, 0,                        /* b */
                    1, 0, 0, 0, 0, 0, 0, 0,         /* 13 */
                    0, 0, 0, 0, 0                   /* 18 */
                    };

void print_end (void) {
    print_flush ();
    if (isanchor) {
        printf ("\">");
        if (isanchordef) { 
            print_flush (); 
            printf ("</a>"); 
        } else {
            printf (" ");        
            printf ("</a>"); 
            print_flush (); 
        }  
    }
    print_start();
}

void print_begin(unsigned int u) {
    if (isanchor) { if (isanchordef) printf ("<a name=\""); else printf ("<a href=\"#"); };
}

void print_tags (int p, int t) {
    if (p) { 
      print_end ();
      printf ("</code>"); 
    }
    if (t == 3 && p) printf ("<br>\n");
    printf ("<code class=%s>", function[t]);
    isanchor = needanchor[t];
    isanchordef = t == 3 || t == 0xc;
    if (t != 3 && !isanchor || t == 0xc) printf (" ");
    if (isanchor) print_begin (t);
}

void print_text (unsigned int t, unsigned int u) {
    while (t) {
        if (!(t & 0x80000000)) {
            pchar (ch[t >> 28]); t <<= 4;
        } else if ((t & 0xc0000000) == 0x80000000) {
            pchar (ch[8 + ((t >> 27) & 7)]); t <<= 5;
        } else {
            pchar (ch[((t >> 28) - 10) * 8 + ((t >> 25) & 7)]); t <<= 7;
        }
    }
}

char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
              '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

void print_hex (unsigned int i) {
    int n = 8, f = 0;
    print_end ();
    if (i == 0) { pchar ('0'); return; }
    while (n--) {
        if (!(i & 0xf0000000)) { if (f) pchar ('0'); }
        else { f = 1; pchar (hex [i >> 28]); }
        i <<= 4;
    }
}

void print_dec (int i) {
    int j, k, f = 0;
    if (i == 0) { pchar ('0'); return; }
    if (i < 0) { pchar ('-'); i = -i; }
    for (j = 1000000000; j != 0; j /= 10) {
        k = i / j;
        if (k == 0) { if (f) pchar ('0'); }
        else { i -= j * k; f = 1; pchar (hex[k]); }
    }
    print_end ();
}

int main (int argc, char *argv[]) {
    FILE* F;
    int b = 0, w, p = 0, t, n;

    if (argc < 1) 
        return 1;
        
    F = fopen(argv[1], "rb");
    if (!F) 
        return 1;
    
    printf ("<html>\n");
    printf ("<link rel=stylesheet type=\"text/css\" href=\"colorforth.css\">\n");
    if (fread (&t, 4, 1, F) == 0) return 0;
    while (1) {
        printf ("<h4><a name=\"%d\">Block %d</a></h4>\n", b, b);
        b++;
        printf ("<div class=code>\n");
        print_start();
        w = 256;
        while (w--) {
            switch (t & 0xf) {
            case 0: print_text (t & 0xfffffff0, t & 0xf); break;
            case 2: case 5:
                print_tags (p, t & 0x1f);
                if (w == 0) break;
                fread (&n, 4, 1, F); w--;
                if (t & 0x10) print_hex (n); else print_dec (n);
                break;
            case 6: case 8:
                print_tags (p, t & 0x1f);
                if (t & 0x10) print_hex (t >> 5); else print_dec (t >> 5);
                break;
            case 0xc: print_tags (p, t & 0xf); print_text (t & 0xfffffff0, t & 0xf);
                if (w == 0) break;
                fread (&t, 4, 1, F); w--;
                print_tags (1, 4); print_dec (t); break;
            case 3:
                print_tags (p, t & 0xf); print_text (t & 0xfffffff0, t & 0xf); 
                break;
            default: print_tags (p, t & 0xf); print_text (t & 0xfffffff0, t & 0xf); break;
            }
            p = 1;
            if (fread (&t, 4, 1, F) == 0) {
                print_end ();
                printf ("</code>\n</div>\n"); goto end;
            }
        }
        
        if (p) { print_end (); printf ("</code>\n"); }
        p = 0;
        printf ("</div>\n<hr>\n");
    }
    end:
    printf ("</html>\n");
    
    fclose(F);
    return 0;
}
