www.xbdev.net xbdev - software development
Tuesday April 24, 2018
home | about | contact | Donations

     
 

Image Formats

A single picture is worth a thousand words...

 

C to HTML Converter Explained

by bkenwright@xbdev.net

 

This is one of those things that I use from time to time to produce the nice colour formatting syntax for my website.  I mean if you look at the source code below, that was generated with this very demo code!  Its a bit long, and its only a simple version, but it does its job.

 

To use, you simple, just run the app from the dos prompt, passing the file as the parameter to it, then it outputs it to the dos window.

i.e.

C:> c2html.exe test.cpp

 

Note, I usually channel the output to a nice new file, so you can do this:

 

C:> c2html.exe test.cpp > myop.html

 

Which will take the output from the dos window and give you a nice file called myop.html in the same directory as the test.cpp...and you can open it in exporer to view it...it can't get any more easier that that.

 

 

Download Source Code (5kb)
/********************************************************************************/
/*                                                                              */
/*  File:   c2html.cpp                                                          */
/*  Auth:   Ben Kenwright                                                       */
/*  Email:  bkenwright@xbdev.net                                                */
/*  Url:    www.xbdev.net                                                       */
/*  Date:   01/01/06                                                            */
/*                                                                              */
/********************************************************************************/
/*
	About?
	Well its such a simple program, and I'm sure everyone has wrote one, one time
	or another.
	Convert our code, c/c++ so that its colour coded!  This code takes it a bit
	further and generates a html file, so you can take your c/c++ text file
	and output a html file which will have all the great colour coding!

	I've kept it simple, as you can mix the html so it uses styles and .css files
	but I like to use the font color html tag....but its very easy to convert
	to the alternative method if you prefair.

	To use?
	Open a dos prompt, and do:
	C:>c2html.exe test.cpp test.html

	Which will take test.cpp and create test.html as your output html file :)

	Note:
	Because, fopen was depreciated by ms! To compile under visual studio we
	have to include the '_CRT_SECURE_NO_DEPRECATE' macro

	Further work / Thinking:
	o Bit of modification a simple notepad c/c++ colour coding app can be done.
	o Put the dos app in your C directory, and then you can convert any code
	to colour coded html whenever you want :)
*/
/********************************************************************************/

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

//--------------------------------------------------------------------------------

#define ZCOMMENT		"<font color=\"navy\">"
#define ZSTRING			"<font color=\"green\">"
#define ZMACRO			"<font color=\"violet\">"
#define ZKEYWORDS		"<font color=\"maroon\">"
#define ZDECLARATIONS	        "<font color=\"maroon\">"
#define ZUNIQUE			"<font color=\"red\">"

//--------------------------------------------------------------------------------
void  Parse(FILE *fd);
bool  IsMacro(char *buffer);
void  IsToken(char *buffer);
void  PutChar(int c);
//--------------------------------------------------------------------------------
void  PageHead(void);
void  PageFoot(void);
void  FileStart(char *file);
void  FileEnd(void);
//--------------------------------------------------------------------------------

//#define DEBUGME

/********************************************************************************/
/*                                                                              */
/*  Program Entry Point                                                         */
/*                                                                              */
/********************************************************************************/

int main(int argc, char **argv)
{
	FILE *fd;

#ifdef DEBUGME
	fd = fopen("c2html.cpp", "r");
	PageHead();
	FileStart(*argv);
	Parse(fd);
	FileEnd();
	PageFoot();
	fclose(fd);
	return 0;
#endif // DEBUGME
	


	if (argc < 2) 
	{
		fprintf(stderr, "./c2html file1, file2, ..\n");
		return 0;
	}
	PageHead();

	// This is so we can parse multiple files
	while (--argc > 0) 
	{
		if ((fd = fopen(*++argv, "r")) == NULL) 
		{
			fprintf(stderr, "Error: Unable to open file\n");
			return -1;
		}
		FileStart(*argv);
		Parse(fd);
		FileEnd();

		fclose(fd);
	}

	PageFoot();

	return 0;
}// End main(..)


//--------------------------------------------------------------------------------

void Parse(FILE *fd)
{
	// temp character
	int c;

	while (true)
	{

		// Reached the end of the file
		if ((c = getc(fd)) == EOF)
			return;

		// Start of a comment
		if (c == '/') 
		{
			// Reached end of the file
			if ((c = getc(fd)) == EOF)
				return;

			if (c == '/' || c == '*') 
			{
				// Its a comment
				int ch[2];
				int comment;

				ch[0] = c;

				// This is so we know what type of comment where looking at
				// Either /* or //, so we know to look for the */ or /n to end
				// the comment
				comment = c;
				printf(ZCOMMENT "/");

				PutChar(c);

				for (;;) 
				{
					if ((ch[1] = getc(fd)) == EOF)
						return;

					PutChar(ch[1]);

					if (comment == '/' && ch[1] == '\n')
					{
						// End of the comment
						break;
					}
					else if (comment == '*' && ch[0] == '*' && ch[1] == '/')
					{
						// End of comment
						break;
					}

					ch[0] = ch[1];
				}

				printf("</font>");
			} 
			else 
			{
				ungetc(c, fd);
				printf("/");
			}
		} 
		else if (c == '\'' || c == '"') 
		{
			// Quotation
			int quote;
			int back_slash;
			printf(ZSTRING);

			quote = c;
			back_slash = 0;

			PutChar(c);

			for (;;) 
			{
				if ((c = getc(fd)) == EOF)
				{
					return;
				}
				PutChar(c);
				if (c == quote && !back_slash)
				{
					break;
				}
				if (c == '\\' && !back_slash)
				{
					back_slash = 1;
				}
				else
				{
					back_slash = 0;
				}
			}

			printf("</font>");
		} 
		else if (c == '#') 
		{
			// Start of a macro
			printf(ZMACRO);
			PutChar(c);

			for (;;) 
			{
				if ((c = getc(fd)) == EOF)
				{
					return;
				}

				if (isspace(c))
				{
					PutChar(c);
				}
				else
				{
					break;
				}
			}

			char buffer[32];
			memset(buffer, 0, 32);
			buffer[0] = c;

			for (int i = 1; i < 32; i++) 
			{
				if ((c = getc(fd)) == EOF)
					return;

				if (isalpha(c))
					buffer[i] = c;
				else
					break;
			}

			if (IsMacro(buffer))
			{
				// Is End Macro
				printf("%s</font>", buffer);
			}
			else
			{
				// Is Start Macro
				printf("</font>%s", buffer);
			}

			PutChar(c);
		} 
		else 
		{
			if (islower(c) || isalnum(c) || c == '_') 
			{
				int i;
				char buffer[32];

				memset(buffer, 0, 32);

				buffer[0] = c;

				for (i = 1; i < 32; i++) 
				{
					if ((c = getc(fd)) == EOF)
						return;
					if (islower(c) || isalnum(c) ||
					    c == '_')
						buffer[i] = c;
					else
						break;
				}
				IsToken(buffer);
				PutChar(c);
			} 
			else 
			{
				PutChar(c);
			}
		}
	}

	return;
}// End Parse(..)

//--------------------------------------------------------------------------------

bool IsKeyword(char *buffer)
{
	const char *keywords[] = 
	{
		"break", "case", "continue", "default", "do", "else", "for",
		"goto", "if", "return", "sizeof", "switch", "while"
	};

	for (int i = 0; i < sizeof(keywords) / sizeof(*keywords); i++)
	{
		if (!strcmp(keywords[i], buffer))
		{
			return true;
		}
	}

	return false;
}// End IsKeyword(..)

//--------------------------------------------------------------------------------

bool IsDecl(char *buffer)
{
	const char *declarations[] = 
	{
		"auto", "char", "const", "DIR", "double", "enum", "extern",
		"FILE", "float", "fpos_t", "int", "int8_t", "int16_t",
		"int32_t", "int64_t", "long", "mode_t", "pid_t", "register",
		"short", "signed", "size_t", "ssize_t", "static", "struct",
		"typedef", "union", "unsigned", "va_list", "void", "volatile",
		"class", "public", "protected", "private"
	};

	for (int i = 0; i < sizeof(declarations) / sizeof(*declarations); i++)
	{
		if (!strcmp(declarations[i], buffer))
		{
			return true;
		}
	}

	return false;
}// End IsDecl(..)

//--------------------------------------------------------------------------------

bool IsUniq(char *buffer)
{
	const char *unique[] = 
	{
		"__DATE__",	"__TIME__",	"EACCES",	"EAGAIN",	"EBADF", 
		"EBUSY",	"EOF",		"ECHILD",	"EDEADLK",	"EDOM", 
		"EFAULT",	"EINVAL",	"EILSEQ",	"EINTR",	"EFBIG", 
		"EISDIR",	"stdin", 	"EMFILE",	"EMLINK",	"EMSGSIZE",
		 "ENFILE",	"ENODEV",	"ENOENT",	"ENOLCK",	"stdout",
		"ENOMEM",	"ENOTDIR",	"ENOSPC",	"ENOSYS",	"ENOTEMPTY",
		"ENOTSUP",	"ENOTTY",	"ENOEXEC",	"ENXIO",	"ECANCELED" 
		"EPIPE",	"ERANGE",	"EROFS",	"ESPIPE",	"ESRCH", 
		"EXDEV",	"__FILE__",	"__LINE__",	"NULL",		"SEEK_SET",
		"SEEK_CUR",	"SEEK_END",	"SIGABRT",	"SIGALRM",	"SIGCHLD",
		"SIGCONT",	"SIG_DFL",	"SIG_ERR",	"SIGHUP",	"SIG_IGN", 
		"SIGINT",	"SIGFPE",	"SIGKILL",	"SIGQUIT",	"SIGSEGV", 
		"SIGSTP",	"SIGTERM",	"SIGTRAP",	"SIGTTIN",	"SIGTTOU",
		"SIGUSR1",	"SIGUSR2",	"__STDC__", "stderr",	"EINPROGRESS",
		"E2BIG"		"EBADMSG",	"EEXIST",	"EIO",		"ENAMETOOLONG",
		"SIGILL",	"EPERM",	"SIGSTOP",	"ETIMEDOUT",
	};

	for (int i = 0; i < sizeof(unique) / sizeof(*unique); i++)
	{
		if (!strcmp(unique[i], buffer))
		{
			return true;
		}
	}

	return false;
}// End IsUniq(..)

//--------------------------------------------------------------------------------

bool IsNumber(char *buffer)
{
	int i = 1, hex = 0;

	while (*buffer) 
	{
		if (isdigit(*buffer))
		{
			;
		}
		else if ((*buffer == 'x' || *buffer == 'X') && i == 2)
		{
			hex = 1;
		}
		else if (hex &&
				 (*buffer == 'a' || *buffer == 'A' ||
				 *buffer == 'b' || *buffer == 'B' ||
				 *buffer == 'c' || *buffer == 'C' ||
				 *buffer == 'd' || *buffer == 'D' ||
				 *buffer == 'e' || *buffer == 'E' ||
				 *buffer == 'f' || *buffer == 'F'))
		{
			;
		}
		else
		{
			return false;
		}
		buffer++;
		i++;
	}

	return true;
}// End IsNumber(..)

//--------------------------------------------------------------------------------

bool IsMacro(char *buffer)
{
	const char *macros[] = 
	{
		"define", "elif",   "else",    "endif", "error", "if", 
		"ifdef",  "ifndef", "include", "line",  "pragma"
	};

	for (int i = 0; i < sizeof(macros) / sizeof(*macros); i++)
	{
		if (!strcmp(macros[i], buffer))
		{
			return true;
		}
	}

	return false;
}// End IsMacro(..)

//--------------------------------------------------------------------------------

void IsToken(char *buffer)
{
	if (IsKeyword(buffer))
	{
		printf(ZKEYWORDS "%s</font>", buffer);
	}
	else if (IsDecl(buffer))
	{
		printf(ZDECLARATIONS "%s</font>", buffer);
	}
	else if (IsUniq(buffer) || IsNumber(buffer))
	{
		printf(ZUNIQUE "%s</font>", buffer);
	}
	else
	{
		printf(buffer);
	}
}// End IsToken(..)

//--------------------------------------------------------------------------------

void PutChar(int c)
{
	switch (c) 
	{
	    case '<':
		{
			printf("&lt;");
		}
		break;
	    
		case '>':
		{
			printf("&gt;");
		}
		break;

	    case '&':
		{
			printf("&amp;");
		}
		break;

	    default:
		{
			printf("%c", c);
		}
		break;
	}
}// End PutChar(..)

//--------------------------------------------------------------------------------

void PageHead(void)
{
	printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
	printf("<html>\n");
	printf("<head>\n");
	printf("<title>www.xbdev.net c2html demo</title>\n");
	printf("</head>\n");
	printf("<body>\n\n");
}// End PageHead(..)

//--------------------------------------------------------------------------------

void PageFoot(void)
{
	printf("\n\n</body>\n");
	printf("</html>\n");
}// End PageFoot(..)

//--------------------------------------------------------------------------------

void FileStart(char *file) 
{
	printf("<h2>%s</h2>\n", file);
	printf("<pre>\n");
}// End FileStart(..)

//--------------------------------------------------------------------------------

void FileEnd(void) 
{
	printf("</pre>\n");
	printf("<hr />\n");
}// End FileEnd(..)

//--------------------------------------------------------------------------------

 

If you find that you like the app, well I'd recommend putting it in your windows directory or on your C drive, then you can access it any time you need it....just open a dos window, go to the directory where the c/++ file is, and then you can type c2html.exe somefile.cpp > somefile.html .... and it give you the colour formated html file!

 

There a lot that could be done to improve the code that little bit more.  I mean I've kept it at its simplest...but you could easily do a nice gui interface for it, which could show the final web page, our view the produced source.

 

 

 

 

 

 

 

 

 

 

 

 
 Visitor: 9534626  { 209.237.238.175 } Copyright (c) 2002-2017 xbdev.net - All rights reserved.
Designated tutorial and software are the property of their respective owners.