// cpphigh (c) 2011 org100h.com

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

const string header = "<html><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><body><font face=\"Consolas, Meiryo\">";
const string footer = "</font></body></html>";

const string hightable[] = {
    "#if", "#ifdef", "#ifndef", "#elif", "#else",
    "#endif", "#include", "#define", "#undef", "#line",
    "#error", "#pragma",

    "const_cast", "reinterpret_cast", "static_cast", "unsigned",

    "asm",          "auto",      "bool",     "break",            "case",
    "catch",        "char",      "class",    "const",            "const_cast",
    "continue",     "default",   "delete",   "do",               "double",
    "dynamic_cast", "else",      "enum",     "explicit",         "export",
    "extern",       "false",     "float",    "for",              "friend",
    "goto",         "if",        "inline",   "int",              "long",
    "mutable",      "namespace", "new",      "operator",         "private",
    "protected",    "public",    "register", "reinterpret_cast", "return",
    "short",        "signed",    "sizeof",   "static",           "static_cast",
    "struct",       "switch",    "template", "this",             "throw",
    "true",         "try",       "typedef",  "typeid",           "typename",
    "union",        "unsigned",  "using",    "virtual",          "void",
    "volatile",     "wchar_t",   "while",
};
const auto hightablesize = sizeof(hightable) / sizeof(*hightable);

const string delim = "{}[]#();:?.+-*/%^&|~!=<>, ";

const struct {
    const char * ch;
    const char * esc;
} esctable[] = {
    "<", "&lt;",
    ">", "&gt;",
    "&", "&amp;",
    "\"", "&quot;",
    " ", "&nbsp;",
};
const auto esctablesize = sizeof(esctable) / sizeof(*esctable);

string tab2space(const string & line, long tabstop) {
    string dst;
    auto index = 0;
    for(auto I = line.begin(); I != line.end(); I++) {
        if(*I == '\t') {
            do {
                dst.push_back(' ');
                index++;
            } while(index % tabstop != 0);
        } else {
            dst.push_back(*I);
            index++;
        }
    }
    return dst;
}

string line_escape(const string & line) {
    string dst;
    string target;
    for(auto I = line.begin(); I != line.end(); ++I) {
        target = *I;
        for(auto index = 0; index < esctablesize; index++) {
            if(string(esctable[index].ch) == target) {
                target = esctable[index].esc;
            }
        }
        dst += target;
    }
    return dst;
}

bool is_in_quot(const string & line) {
    const string sq = "'";
    const auto sql = sq.length();
    const string dq = "&quot;";
    const auto dql = dq.length();
    bool single_open = false;
    bool double_open = false;
    for(auto pos = 0; pos < line.length(); pos++) {
        if(pos + sql <= line.length() && line.substr(pos, sql) == sq) {
            if(single_open) {
                if(!double_open) {
                    single_open = false;
                }
            } else {
                single_open = true;
            }
        }
        if(pos + dql <= line.length() && line.substr(pos, dql) == dq) {
            if(double_open) {
                double_open = false;
            } else {
                double_open = true;
            }
        }
    }
    return double_open;
}

string make_newword(const string & target) {
    stringstream dst;
    dst << "&#" << dec << static_cast<unsigned int>(target[0]) << ";" << target.substr(1);
    return dst.str();
}

bool is_delim(char ch) {
    return delim.find(ch) != string::npos;
}

bool is_pure_target(const string & line, const string & target, string::size_type pos) {
    const auto tl = target.length();
    if(pos + tl == line.length() || (pos + tl < line.length() && is_delim(line[pos + tl]))) {
        if(pos == 0 || is_delim(line[pos - 1])) {
            return true;
        }
    }
    return false;
}

bool one_replace(string & line, const string & target, const string & newword) {
    auto pos = line.find(target);
    if(pos == string::npos) return false;
    if(is_pure_target(line, target, pos) && !is_in_quot(line.substr(0, pos))) {
        line = line.substr(0, pos) + "<font color=\"#00f\">" + newword + "</font>" + line.substr(pos + target.length());
        return true;
    }
    return false;
}

string all_replace(const string & line) {
    string dst = line;
    for(auto index = 0; index < hightablesize; index++) {
        const string & target = hightable[index];
        const string newword = make_newword(target);
        while(one_replace(dst, target, newword));
    }
    return dst;
}

int main(int argc, char * argv[]) {
    try {
        if(argc > 2) throw "too many parameters.";
        auto tabstop = (argc == 2) ? atol(argv[1]) : 4;
        cout << header;
        cin.unsetf(ios_base::skipws);
        string line;
        for(;;) {
            getline(cin, line);
            if(!cin) break;
            cout << "<nobr>" << all_replace(line_escape(tab2space(line, tabstop))) << "</nobr><br />";
        }
        cout << footer;
        return EXIT_SUCCESS;
    } catch(const char * cause) {
        cout << "error: " << cause << endl;
    } catch(...) {
        cout << "unknown error." << endl;
    }
    return EXIT_FAILURE;
}