/*
* Copyright (C) 2008, Chaoji Li<lichaoji@gmail.com>, All rights reserved.
*/
#include <cstdio>
#include <cstring>
#include <cctype>
const char * keywords[] = {
"const", "static", "extern", "friend",
"bool", "sizeof",
"long", "char", "int", "signed", "short", "unsigned",
"float", "double",
"while", "for", "break", "continue", "default", "switch", "case",
"if", "else", "return",
"new", "delete",
"struct", "class", "public", "private", "protected",
"try", "catch", "throw",
"typedef", "enum",
"true", "false", "void",
"#define", "#include", "#if", "#else", "#ifdef",
"#ifndef", "#elsif", "#end", "#endif",
};
bool is_keyword(char *s);
#define COLOR_STRING "#A31515"
#define COLOR_COMMENT "#008000"
#define COLOR_KEYWORD "#0000FF"
#define NKEYWORDS (sizeof(keywords)/sizeof(char*))
#define MAXBUF 1000
char buf[MAXBUF] = "";
int buflen = 0;
bool in_comment = false;
bool in_string = false;
bool in_word = false;
char quote = 0;
enum StringType {
ST_ENUM,
ST_KEYWORD,
ST_STRING,
ST_COMMENT,
ST_NORMAL
};
void print_buf(char *buf, StringType st);
void print_string(char *s);
void add_to_buf(char ch);
int main(int argc, char* argv[])
{
FILE *fp = NULL;
if (argc != 2)
{
fp = stdin;
}
else
{
fp = fopen(argv[1], "r");
if (fp == NULL)
{
fprintf(stderr, "can't open file '%s' for read\n", argv[1]);
return -1;
}
}
printf("<html><body background=#FFFFFF foreground=#000000><pre style=\"font-family: FixedSys\">");
int ch = fgetc(fp);
while (ch != EOF)
{
switch (ch)
{
case '\\':
add_to_buf(ch);
if (in_string)
{
ch = fgetc(fp);
add_to_buf(ch);
}
break;
case '\'':
case '\"':
if (in_string && ch == quote)
{
add_to_buf(ch);
print_buf(buf, ST_STRING);
in_string = false;
}
else if (!in_string)
{
print_buf(buf, ST_NORMAL);
in_string = true;
quote = ch;
add_to_buf(ch);
}
else
{
add_to_buf(ch);
}
break;
case '\n':
if (!in_string && !in_comment)
{
add_to_buf(ch);
print_buf(buf, ST_NORMAL);
}
else
{
add_to_buf(ch);
}
break;
case '/':
if (!in_string && !in_comment)
{
char ch2 = fgetc(fp);
if (ch2 == '/')
{
// One line comment, print at once
print_buf(buf, ST_NORMAL);
add_to_buf(ch);
add_to_buf(ch2);
while ( (ch=fgetc(fp)) != EOF && ch != '\n')
add_to_buf(ch);
if (ch == '\n') add_to_buf(ch);
print_buf(buf, ST_COMMENT);
}
else if (ch2 == '*')
{
// Multiple line comment
print_buf(buf, ST_NORMAL);
add_to_buf(ch);
add_to_buf(ch2);
in_comment = true;
}
else
{
// This is not a comment
add_to_buf(ch);
add_to_buf(ch2);
}
}
else if (in_comment)
{
if (buf[buflen-1] == '*')
{
add_to_buf(ch);
print_buf(buf, ST_COMMENT);
in_comment = false;
}
else
{
add_to_buf(ch);
}
}
else
{
add_to_buf(ch);
}
break;
case '#':
if(!in_string && !in_comment)
{
print_buf(buf, ST_NORMAL);
add_to_buf(ch);
while (isalpha(ch = fgetc(fp)))
{
add_to_buf(ch);
}
if (isspace(ch) && is_keyword(buf))
{
print_buf(buf, ST_KEYWORD);
}
continue;
}
else
{
add_to_buf(ch);
}
break;
default:
if (!in_string && !in_comment && isalpha(ch))
{
print_buf(buf, ST_NORMAL);
while (isalnum(ch) || ch == '_')
{
add_to_buf(ch);
ch = fgetc(fp);
}
if (is_keyword(buf))
{
print_buf(buf, ST_KEYWORD);
}
continue;
}
else
{
add_to_buf(ch);
}
break;
}
ch = fgetc(fp);
}
print_buf(buf,ST_NORMAL);
printf("</pre></body></html>");
fclose(fp);
}
void add_to_buf(char ch)
{
if (buflen < MAXBUF - 1)
{
buf[buflen++] = ch;
buf[buflen] = '\0';
}
}
void print_buf(char *buf, StringType st)
{
if (buflen <= 0 || buf[0] == '\0')
return;
switch (st)
{
case ST_KEYWORD:
printf("<font color=" COLOR_KEYWORD ">");
print_string(buf);
printf("</font>");
break;
case ST_STRING:
printf("<font color=" COLOR_STRING ">");
print_string(buf);
printf("</font>");
break;
case ST_COMMENT:
printf("<font color=" COLOR_COMMENT ">");
print_string(buf);
printf("</font>");
break;
case ST_NORMAL:
default:
print_string(buf);
break;
}
buflen = 0;
buf[0] = '\0';
}
/* Print html representation of string s */
void print_string(char *s)
{
while (*s != '\0')
{
switch (*s)
{
case '<':
case '>':
case '&':
printf("&#%d;", *s);
break;
default:
putchar(*s);
break;
}
s++;
}
}
bool is_keyword(char *s)
{
for (int i = 0; i <NKEYWORDS; i++)
{
if (strcmp(s, keywords[i]) == 0)
return true;
}
return false;
}