#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "c2html.h"


/*Zustandsflags*/
static int komment=0;    /*Kommentarflag*/
static int single_quote=0; /*Einfaches Anführungszeichen*/
static int double_quote=0; /*Doppeltes Anführungszeichen*/
static int hash=0;         /*Hash-Zeichen*/
static int newline=0;      /*Neue Zeile*/
static int nl=1;           /*Zeilenzähler*/


int main(int argc, char *argv[])
{
 if(argc < 2)
  {
   fprintf(stderr, "usage: c2html file.c > file.html\n");
   exit(0);
  }
 if( freopen(argv[1], "r", stdin) == NULL)
  {
   fprintf(stderr, "Konnte %s nicht öffnen......\n",argv[1]);
   exit(0);
  }
 /*HTML-Kopfzeile schreiben*/
 HTML_head(argv[1]);
 /*Nun die Konvertierung........*/
 c2html();
 /*Nur noch das Ende der HTML-Datei schreiben*/
 HTML_end();

 return 0;
}


/*Kopfzeile für HTML-Dokument.......*/
static void HTML_head(char *name)
{
 fprintf(stdout,"<HTML>\n<HEAD>\n<TITLE>%s</TITLE>\n",name);
 fprintf(stdout,"<BODY BGCOLOR=\"%s\" TEXT=%s>\n",background,textcolor);
 fprintf(stdout,"<H2><A HREF=\"%s\">/*%s*/</A></H2>\n<P><PRE>\n",name,name);
}

/*Fusszeile für HTML-Dokument.......*/
static void HTML_end()
{
 fprintf(stdout, "</PRE></P>\n</BODY>\n</HEAD>\n</HTML>\n");
}


static void c2html()
{
 char word[MAXWORD];
 int ch,c;
 int zeilennummer=1;

 while( (ch = read_word(word, MAXWORD)) != EOF)
  {
    switch(ch)
     {
      case ALPHABET : if(komment || single_quote || double_quote)
                        fprintf(stdout, "%s", word); /*kommentar o. string*/
                      else if(hash && is_key_word(word,P_key_words,P_keys) >=0)
                        fprintf(stdout, "<FONT COLOR=%s><B>%s</B></FONT>",
                                         praeproze,word); /*Präprozessordirekt.*/
                      else if(!hash && is_key_word(word,C_key_words,C_keys) >=0)
                        fprintf(stdout, "<FONT COLOR=%s><B>%s</B></FONT>",
                                         keyscolor,word); /*Schlüsselwort*/
                      else if(!hash && is_key_word(word, C_typen, C_typs) >=0)
                        fprintf(stdout, "<FONT COLOR=%s>%s</FONT>",types,word);
                                /*Datentypen wie int, long.........*/
                      else
                        fprintf(stdout,"%s",word); /*sonstiges Wort*/
                        break;
      case HASH       : fprintf(stdout,"<FONT COLOR=%s>%s",praeproze,word);
                        fprintf(stdout,"</FONT>");
                        break;
      case KOMMENTAR_S: fprintf(stdout,"<FONT COLOR=%s><I>%s",kommentar,word);
                        break;
      case KOMMENTAR_E: fprintf(stdout,"%s</I></FONT>",word);
                        break;
      case BLOCK_S    : fprintf(stdout,"<B>%s</B>\n",word);
                        break;
      case BLOCK_E    : fprintf(stdout,"<B>%s</B>",word);
                        break;
      case QUOTING_A  : fprintf(stdout,"<FONT COLOR=%s>&quot;",strings);
                        break;
      case QUOTING_E  : fprintf(stdout,"&quot</FONT>");
                        break;
      case CHAR_A     : fprintf(stdout,"<FONT COLOR=%s>\'",zeichen);
                        break;
      case CHAR_E     : fprintf(stdout, "\'</FONT>");
                        break;
      case MASK       : fprintf(stdout,"%s",word);
                        break;
      /*HTML - SONDERZEICHEN BEHANDELN*/
      case '<'        : fprintf(stdout, "&lt;"); break;
      case '>'        : fprintf(stdout, "&gt;"); break;
      case '\"'       : fprintf(stdout, "&quot;"); break;
      case '&'        : fprintf(stdout, "&amp;"); break;

      case '\n'       : if( (c=getc(stdin)) != EOF && newline)
                         {
                          ungetc(c, stdin);
                          if(komment)
                           {
                            fprintf(stdout,"</I></FONT>");
                            fprintf(stdout,"<FONT COLOR=%s><I>",kommentar);
                           }
                          else
                           {
                            fprintf(stdout,"<BR>");
                            nl++;
                           }
                          }
                         break;
      default         : fprintf(stdout, "%c", ch);
                        break;
     }/*Ende switch*/
    }/*Ende while....*/
}

/*Such nach einem Schlüsselwort oder Präprozessordirektive*/
static int is_key_word(char *word, const char *keys[],const int n)
{
 int i;
 for(i=0; i<n; i++)
  {
   if(strcmp(word,keys[i]) == 0)
    return 1;
  }
 return -1;
}


static int read_word(char *word, int n)
{
 int c, cc, ch;
 int flag=0;

 c=getc(stdin); /*Ein Zeichen einlese*/
 if(!isalpha(c))/*keine Buchstaben?*/
  {
   if(c=='\n') /*ist es ein newline*/
    {
     newline=1;
     hash=0;
    }
   /*Ist das newline-flag gesetzt und c == # -> Präprozessordirektive*/
   else if((newline || nl==1)&&!komment&&!single_quote&&!double_quote&& c == '#')
    {
     hash=1;
     *word++=c;
     while(--n > 0)
      {
       flag=0;
       c=getc(stdin);
       if(c != '\n')
        {
         if(c == '<'){  /*HTML-Sonderzeichen*/
           *word++='&';*word++='l';*word++='t';*word++=';';
           }
         else if(c == '>'){ /*HTML-Sonderzeichen*/
           *word++='&';*word++='g';*word++='t';*word++=';';
           }
         else
           *word++=c;
        }
       else
        {
         ungetc(c,stdin); /*newline wieder zurück nach stdin*/
         *word='\0';
         break;
        }
      }
     return HASH;
    }
   else if(newline) /*newline-flag gesetzt*/
     newline=0;
   /*Makierung*/
   if(c=='\\' && !komment)  /*c== \ und nicht das Kommentar-flag*/
    {
     cc=getc(stdin); /*Noch ein Zeichen einlesen*/
     *word++=c;
     *word++=cc;
     if(isdigit(cc)) /*Eine dezimal Ziffer*/
      {
       while(--n > 2)
        {
         c=getc(stdin);
         if(!isdigit(c)) /*Keine dazimal Ziffer*/
          {
           ungetc(c,stdin);
           break;
          }
         *word++=c;
        }
       }
      *word='\0'; /*Terminieren*/
      return MASK;
     }
    /*Einfaches Zeichen*/
    else if(c== '\'' && !komment && !double_quote)
     {
      if(single_quote) /*Das Flag bereits gesetzt?*/
       {
        single_quote=0; /*Flag wieder löschen*/
        return CHAR_E;  /*Zeichenende gefunden*/
       }
      else  /*Flag noch nicht gesetzt....*/
       {
        single_quote=1;
        return CHAR_A;
       }
      }
     /*String*/
     else if(c=='\"' && !komment && !single_quote)
      {
       if(double_quote) /*Flag bereits gesetzte*/
        {
         double_quote=0;
         return QUOTING_E;
        }
       else
        {
         double_quote=1;
         return QUOTING_A;
        }
       }
      /*Beginn Anweisungsblock*/
      else if(c=='{' && !komment && !double_quote && !single_quote)
       {
        *word++=c;
        *word='\0';
        return BLOCK_S;
       }
      else if(c=='}' && !komment && !double_quote && !single_quote)
       {
        *word++=c;
        *word='\0';
        return BLOCK_E;
       }
      /*Kommentar Beginn*/
      else if(c=='/' && !komment && !double_quote && !single_quote)
       {
        if((cc = getc(stdin)) == '*')
         {
          komment=1;
          *word++=c;
          *word++=cc;
          *word='\0';
          return KOMMENTAR_S;
         }
        ungetc(cc, stdin);
       }
      /*Kommentar Ende*/
      else if(c=='*' && komment && !double_quote && !single_quote)
       {
        if(( cc = getc(stdin)) == '/')
         {
          komment=0;
          *word++=c;
          *word++=cc;
          *word='\0';
          return KOMMENTAR_E;
         }
        ungetc(cc,stdin);
       }
      *word++=c;
      *word='\0';
      return c;
     }/*Ende !isalpha*/
    *word++=c;
    while(--n > 0)
     {
      c=getc(stdin);
      if(!isalpha(c) && !isdigit(c))
       {
        ungetc(c, stdin);
        break;
       }
      *word++=c;
     }
    *word='\0';
    return ALPHABET;
}

