#include #include #include typedef int boolean; #define TRUE 1 #define FALSE 0 typedef enum { NORMAL, STRING, CHAR, LINE_COMMENT, BLOCK_COMMENT, PREPROCESSOR } State; #define C (1 << 0) #define CPP (1 << 1) #define OBJC (1 << 2) unsigned int language; #define NUM_EXTENSIONS 10 struct { const char* extension; unsigned int language; } EXTENSIONS[NUM_EXTENSIONS] = { { "h", C | CPP | OBJC }, { "hh", C | CPP }, { "hpp", C | CPP }, { "c", C }, { "cc", C | CPP }, { "cpp", C | CPP }, { "c++", C | CPP }, { "cxx", C | CPP }, { "m", C | OBJC }, { "mm", C | CPP | OBJC } }; const char* KEYWORDS[] = { "auto", "break", "case", "const", "continue", "default", "do", "else", "enum", "extern", "for", "goto", "if", "register", "return", "sizeof", "static", "struct", "switch", "typedef", "union", "volatile", "while", NULL }; const char* CPP_KEYWORDS[] = { "catch", "class", "delete", "dynamic_cast", "false", "inline", "mutable", "namespace", "new", "private", "protected", "public", "reinterpret_cast", "static_cast", "template", "this", "throw", "true", "try", "typeid", "typename", "using", "virtual", NULL }; const char* OBJC_KEYWORDS[] = { "@class", "@defs", "@encode", "@end", "@implementation", "@interface", "@private", "@protected", "@protocol", "@public", "@selector", "_cmd", "bycopy", "byref", "in", "inout", "oneway", "out", "self", "super", NULL }; const char* TYPES[] = { "char", "double", "float", "int", "long", "short", "signed", "unsigned", "void", NULL }; const char* CPP_TYPES[] = { "bool", NULL }; const char* OBJC_TYPES[] = { "BOOL", "Class", "id", "IMP", "SEL", NULL }; #define biggy this #define runs \ over multiple \ lines /* "string within comment" */ /* //comment within comment */ // /* comment within comment */ // #define within comment //this is a comment /* so is this it goes over multiple lines */ void parse_language(const char* string) { unsigned int i; for (i = 0; i < NUM_EXTENSIONS; ++i) { if (strcasecmp(string, EXTENSIONS[i].extension) == 0) { language = EXTENSIONS[i].language; return; } } language = 0; } boolean is_identifier_char(int c) { return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_') || ((language & OBJC) && c == '@'); } boolean hilite(const char* word, const char* const* LIST, const char* Class) { unsigned i; for (i = 0; LIST[i] != NULL; ++i) { if (strcmp(word, LIST[i]) == 0) { printf("%s", Class, word); return TRUE; } } return FALSE; } void print_word(const char* word) { if (!(((language & C) && hilite(word, KEYWORDS, "keyword")) || ((language & CPP) && hilite(word, CPP_KEYWORDS, "keyword")) || ((language & OBJC) && hilite(word, OBJC_KEYWORDS, "keyword")) || ((language & C) && hilite(word, TYPES, "type")) || ((language & CPP) && hilite(word, CPP_TYPES, "type")) || ((language & OBJC) && hilite(word, OBJC_TYPES, "type")))) { printf("%s", word); } } int main(int argc, const char* argv[]) //so is this { #if defined(RUN_AS_CGI) printf("Content-type: text/HTML\n\n"); printf(" "); #endif #if !defined(RUN_AS_CGI) int file; for (file = 1; file < argc; ++file) { #endif FILE* cfile = NULL; char* extension_string = NULL; #if defined(RUN_AS_CGI) const char* filename = getenv("PATH_TRANSLATED"); #else const char* filename = argv[file]; #endif State state = NORMAL; boolean escape = FALSE; boolean slash_seen = FALSE; boolean star_seen = FALSE; char word[4096] = {'\0'}; unsigned int word_length = 0; extension_string = strrchr(filename, '.'); if (extension_string == NULL) { language = C | CPP | OBJC; } else { parse_language(extension_string + 1); } cfile = fopen(filename, "r"); #if defined(RUN_AS_CGI) printf("

%s (%s%s%s)

", strrchr(getenv("PATH_INFO"), '/') + 1, (language & OBJC ? "Obj" : ""), (language & C ? "C" : ""), (language & CPP ? "++" : "")); #endif printf("
");
        
        while(!feof(cfile))
        {
            int c = getc(cfile);
            if (c == EOF)
            {
                break;
            }
            
            if (!is_identifier_char(c))
            {
                print_word(word);
                word[0] = '\0';
                word_length = 0;
            }
            
            if (c == '&')
            {
                printf("&");
            }
            else if (c == '<')
            {
                printf("<");
            }
            else if (c == '>')
            {
                printf(">");
            }
            else if (c == '\t')
            {
                printf("    ");
            }
            else if (c == '\n')
            {
                if (state == LINE_COMMENT ||
                    (state == PREPROCESSOR && !escape))
                {
                    printf("");
                    state = NORMAL;
                }
                putchar('\n');
            }
            else if (c == '\\')
            {
                escape = !escape;
                putchar('\\');
            }
            else if (c == '#')
            {
                if (state == NORMAL)
                {
                    printf("#");
                    state = PREPROCESSOR;
                }
                else
                {
                    putchar('#');
                }
            }
            else if (c == '/')
            {
                if (state == NORMAL)
                {
                    if (slash_seen)
                    {
                        slash_seen = FALSE;
                        printf("//");
                        state = LINE_COMMENT;
                    }
                    else
                    {
                        slash_seen = TRUE;
                    }
                }
                else if (state == BLOCK_COMMENT && star_seen)
                {
                    printf("/");
                    state = NORMAL;
                }
                else
                {
                    putchar('/');
                }
            }
            else if (c == '*')
            {
                if (state == NORMAL && slash_seen)
                {
                    printf("/*");
                    state = BLOCK_COMMENT;
                }
                else if (state == BLOCK_COMMENT)
                {
                    star_seen = TRUE;
                    putchar('*');
                }
                else
                {
                    putchar('*');
                }
            }
            else if (c == '\'')
            {
                if (escape)
                {
                    putchar('\'');
                }
                else if (state == NORMAL)
                {
                    printf("'");
                    state = CHAR;
                }
                else if (state == CHAR)
                {
                    printf("'");
                    state = NORMAL;
                }
                else
                {
                    putchar('\'');
                }
            }
            else if (c == '"')
            {
                if (escape)
                {
                    putchar('"');
                }
                else if (state == NORMAL)
                {
                    printf("\"");
                    state = STRING;
                }
                else if (state == STRING)
                {
                    printf("\"");
                    state = NORMAL;
                }
                else
                {
                    putchar('"');
                }
            }
            else if (state == NORMAL && is_identifier_char(c))
            {
                word[word_length++] = c;
                word[word_length] = '\0';
            }
            else
            {
                putchar(c);
            }
            
            if (c != '\\')
            {
                escape = FALSE;
            }
            if (c != '/')
            {
                slash_seen = FALSE;
            }
            if (c != '*')
            {
                star_seen = FALSE;
            }
        }
        
        printf("
"); #if !defined(RUN_AS_CGI) } #endif #if defined(RUN_AS_CGI) printf(""); #endif return EXIT_SUCCESS; }