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

#define QUOTE_COLOR "#ff0000"
#define COMMENT_COLOR "#408080"
#define PREPROC_COLOR "#008000"


/*
                     C / C++ to HTML converter.
         Converts C and C++ code to HTML with syntax hilighting...
*/

char *Reserved_Words[]={"asm","catch","double","cgoto","not","return","throw",
			"volatile","and","char","else","if","not_eq","short",
			"true","while","and_eq","class","enum","inline","operator",
			"signed","try","xor","auto","compl","explicit","int","or",
			"sizeof","typedef","xor_eq","bitand","const","extern",
			"long","or_eq","static","typename","bitor","continue",
			"false","mutable","private","struct","union","bool","default",
			"float","namespace","protected","switch","unsigned","break",
			"delete","for","new","public","template","virtual","case",
			"do","friend","not","register","this","void"};
int Num_Reserved = 67;
int IsReservedWord (char *word)
{
  int i;

  for (i = 0; i < Num_Reserved; ++i)
    if (!strcmp(word,Reserved_Words[i]))
      return 1;
  return 0;
}

int fpeek(FILE *f)
{
  int ch;

  ch = fgetc(f);
  ungetc(ch,f);
  return ch;
}


void printchar(char inchar, FILE *fstream)
{
  if ((inchar != '<') && (inchar != '>') && (inchar != '&'))
    fputc(inchar,fstream);
  else if (inchar == '&')
    fprintf(fstream,"&amp;");
  else if (inchar == '>')
    fprintf(fstream,"&gt;");
  else
    fprintf(fstream,"&lt;");
}

int Print_HTML(FILE* fstream, char *Title)
{
  FILE *InFile;
  int  inchar,
       i, 
       newline = 1,
       Multi_Line_Comment = 0,
       WordIdx = 0;
  char word[280];

  for (i=0; i<280; ++i)
    word[i] = 0;
  // Print out the HTML header.
  fprintf(fstream,"<HTML>\n<HEAD>\n<TITLE> %s </TITLE>\n</HEAD>\n",Title);
  fprintf(fstream,"<BODY bgcolor=ffffff><pre>\n");

  // Now we open the file for reading in text mode.
  InFile = fopen(Title,"rt");
  if (InFile == NULL)
    return -1;

  // And start reading it in character by character.
  inchar = fgetc(InFile);
  while (!feof(InFile))
    {
      if (inchar == '\n')
	{
	  newline = 1;
	}
      else if (!isspace(inchar))
	{
	  // Handle all preproccessor directives.
	  if ((inchar == '#') && (!Multi_Line_Comment))
	    {
	      if (newline == 1)
		{
		  fprintf(fstream,"<font color=%s>",PREPROC_COLOR);
		  while ((inchar != '\n')&& (inchar > 0))
		    {
		      printchar(inchar,fstream);
		      inchar = fgetc(InFile);
		    }
		  fprintf(fstream,"</font>");
		  newline = 1;
		  continue;
		}
	    }
	  // Handle single line comments.
	  else if ((inchar == '/') && (fpeek(InFile) == '/') && (!Multi_Line_Comment))
	    {
	      fprintf(fstream,"<font color=%s><i>",COMMENT_COLOR);
	      while ((inchar != '\n') && (inchar > 0))
		{
		  printchar(inchar,fstream);
		  inchar = fgetc(InFile);
		}
	      fprintf(fstream,"</i></font>");
	      newline = 1;
	      continue;
	    }
	  // Handle Multi-line comments.
	  else if ((inchar == '/') && (fpeek(InFile) == '*') && (!Multi_Line_Comment))
	    {
	      Multi_Line_Comment = 1;
	      fprintf(fstream,"<font color=%s><i>/",COMMENT_COLOR);
	      inchar = fgetc(InFile);
	    }
	  else if ((inchar == '*') && (fpeek(InFile) == '/') && (Multi_Line_Comment))
	    {
	      fgetc(InFile);
	      inchar = fgetc(InFile);
	      Multi_Line_Comment = 0;
	      fprintf(fstream,"*/</i></font>",COMMENT_COLOR);
	    }
	  // Handle Double Quotes.
	  else if ((inchar == 34 ) && (!Multi_Line_Comment))
	    {
	      fprintf(fstream,"<font color=%s>%c",QUOTE_COLOR,34);
	      inchar = fgetc(InFile);
	      while ((inchar != 34) && (inchar > 0))
		{
		  printchar(inchar,fstream);
		  inchar = fgetc(InFile);
		}
	      inchar = fgetc(InFile);
	      fprintf(fstream,"%c</font>",34);
	      newline = 0;
	      continue;
	    }
	  // Handle Single Quotes.
	  else if ((inchar == 39 ) && (!Multi_Line_Comment))
	    {
	      fprintf(fstream,"<font color=%s>%c",QUOTE_COLOR,39);
	      inchar = fgetc(InFile);
	      while ((inchar != 39) && (inchar > 0))
		{
		  printchar(inchar,fstream);
		  inchar = fgetc(InFile);
		}
	      inchar = fgetc(InFile);
	      fprintf(fstream,"%c</font>",39);
	      newline = 0;
	      continue;
	    }
	  newline = 0;
	}
      // Everything else.
      if (!isalnum(inchar))
	{
	  if (IsReservedWord(word) && !Multi_Line_Comment)
	    {
	      fprintf(fstream,"<b>%s</b>%c",word,inchar);
	    }
	  else
	    {
	      for (i=0; i < WordIdx; ++i)
		printchar(word[i],fstream);
	      printchar(inchar,fstream);
	    }
	  for (i=0; i < 280; ++i) word[i] = 0;
	  WordIdx = 0;
	}
      else
	{
	  word[WordIdx++] = inchar;
	}
      inchar = fgetc(InFile);
    }
  fprintf(fstream,"\n</pre></BODY></HTML>\n");
  fclose(InFile);
  return 1;
}

int main(int argc,char *argv[])
{
  if (argc < 2)
    {
      printf("Usage: %s [Filename]\n\n",argv[0]);
      return -1;
    }
  Print_HTML(stdout,argv[1]);
  return 0;
}