361 lines
8.2 KiB
C
361 lines
8.2 KiB
C
|
/*
|
||
|
CopyRight (C) 1999, Dmitry Obukhov, dso@usa.net
|
||
|
mailto: dso@usa.net
|
||
|
http://www.EmbeddedStuff.com
|
||
|
|
||
|
----------------------------------------------
|
||
|
Last modified 6 Apr 97
|
||
|
----------------------------------------------
|
||
|
Converts C (C++) source to HTML code fragment
|
||
|
with syntax highlighting.
|
||
|
Since program written for personal purpose
|
||
|
the <TABLE> tags generated. This is optional
|
||
|
page format specific thing.
|
||
|
|
||
|
Usage: CTHM <input_file>. All output is done
|
||
|
to STDOUTPUT, error messages to STDERR.
|
||
|
For HTML fragment generation:
|
||
|
CHTM file.c > file.htm
|
||
|
|
||
|
- Some input convertion required to use this
|
||
|
code as CGI module. Will be done soon.
|
||
|
- Optimization required for blocks of EOL
|
||
|
comments
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
// ------------------- Decoding status values
|
||
|
|
||
|
#define START 0
|
||
|
#define INLINE 1
|
||
|
#define DEFINE 2
|
||
|
// ------------------- Decoding Remark
|
||
|
#define REM1 20
|
||
|
#define REM2 21
|
||
|
#define REM_END 22
|
||
|
#define REM_STAR 23
|
||
|
#define REM_STAR_1 24
|
||
|
#define STRING 25 // String is "like" remark
|
||
|
|
||
|
|
||
|
// ------------------- HTML TAG Generation
|
||
|
#define ON 1
|
||
|
#define OFF 0
|
||
|
|
||
|
// ------------------- HTML TAG type
|
||
|
#define MODE_KEYWORD 0
|
||
|
#define MODE_REMARK 2
|
||
|
#define MODE_REMARK_EOL 4
|
||
|
#define MODE_DEFINE 6
|
||
|
#define MODE_STRING 8
|
||
|
|
||
|
|
||
|
int is_delimeter(char c)
|
||
|
{
|
||
|
int ii=0;
|
||
|
char dlms[] =
|
||
|
"\t\r\n (){}[]+-*/%\"'&|^~:;<>.,";
|
||
|
//--------------------------------
|
||
|
while (dlms[ii])
|
||
|
{
|
||
|
if (c==dlms[ii++]) return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int is_keyword(char * str)
|
||
|
{
|
||
|
char * kwords[] =
|
||
|
{
|
||
|
"asm", "auto",
|
||
|
"break", "case",
|
||
|
"cdecl", "char",
|
||
|
"class", "const",
|
||
|
"continue", "default",
|
||
|
"delete", "do",
|
||
|
"double", "else",
|
||
|
"enum", "extern",
|
||
|
"far", "float",
|
||
|
"for", "friend",
|
||
|
"goto", "huge",
|
||
|
"if", "inline",
|
||
|
"int", "interrupt",
|
||
|
"long", "near",
|
||
|
"new", "operator",
|
||
|
"pascal", "private",
|
||
|
"protected", "public",
|
||
|
"register", "return",
|
||
|
"short", "signed",
|
||
|
"sizeof", "static",
|
||
|
"struct", "switch",
|
||
|
"template", "this",
|
||
|
"typedef", "union",
|
||
|
"unsigned", "virtual",
|
||
|
"void", "volatile",
|
||
|
"while", NULL
|
||
|
};
|
||
|
int ii=0;
|
||
|
int jj;
|
||
|
int check;
|
||
|
|
||
|
while (kwords[ii])
|
||
|
{
|
||
|
jj = 0;
|
||
|
check = 1;
|
||
|
while (kwords[ii][jj] && check)
|
||
|
{
|
||
|
if (str[jj] != kwords[ii][jj])
|
||
|
{
|
||
|
check = 0;
|
||
|
}
|
||
|
jj++;
|
||
|
}
|
||
|
if (check) return 1;
|
||
|
ii++;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void set_mode(int on_off, int mode)
|
||
|
{
|
||
|
char * tags[] =
|
||
|
{
|
||
|
//-------------------- KEYWORD
|
||
|
"<strong>",
|
||
|
"</strong>",
|
||
|
//-------------------- Classic remarks
|
||
|
"<font color=\"#336600\">",
|
||
|
"</font>",
|
||
|
//-------------------- EOL Remarks
|
||
|
"<font color=\"#336600\">",
|
||
|
"</font>",
|
||
|
//-------------------- #DEFINE
|
||
|
"<font color=\"#663300\"><strong>",
|
||
|
"</strong></font>",
|
||
|
//-------------------- "string"
|
||
|
"<font color=\"#0000CC\">",
|
||
|
"</font>",
|
||
|
NULL, NULL
|
||
|
};
|
||
|
fprintf(stdout,tags[mode + 1 - on_off]);
|
||
|
}
|
||
|
|
||
|
void print_char_html(char c)
|
||
|
{
|
||
|
switch (c)
|
||
|
{
|
||
|
case '<':
|
||
|
fprintf(stdout,"<");
|
||
|
break;
|
||
|
case '>':
|
||
|
fprintf(stdout,">");
|
||
|
break;
|
||
|
case '"':
|
||
|
fprintf(stdout,""");
|
||
|
break;
|
||
|
case '&':
|
||
|
fprintf(stdout,"&");
|
||
|
break;
|
||
|
case '|':
|
||
|
fprintf(stdout,"¦");
|
||
|
break;
|
||
|
default:
|
||
|
fprintf(stdout,"%c",c);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
int main(int _argc, char** _argv)
|
||
|
{
|
||
|
FILE *in, *out;
|
||
|
char c;
|
||
|
int mode;
|
||
|
char buf[80];
|
||
|
int bufidx = 0;
|
||
|
int progress = 1;
|
||
|
int echo;
|
||
|
int saved_mode;
|
||
|
int kw;
|
||
|
char tmpc;
|
||
|
char prevc;
|
||
|
|
||
|
if (_argc < 2)
|
||
|
{
|
||
|
fprintf(stderr,
|
||
|
"USAGE: c2html <file>\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ((in = fopen(_argv[1], "rt")) == NULL)
|
||
|
{
|
||
|
fprintf(stderr,
|
||
|
"Cannot open input file.\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
fprintf(stdout, "<pre>");
|
||
|
mode = START;
|
||
|
|
||
|
while (!feof(in) && progress)
|
||
|
{
|
||
|
echo = 1;
|
||
|
prevc = c;
|
||
|
c = fgetc(in);
|
||
|
|
||
|
if (c=='/' && (mode < REM1))
|
||
|
{
|
||
|
saved_mode = mode;
|
||
|
mode = REM1;
|
||
|
}
|
||
|
|
||
|
switch (mode)
|
||
|
{
|
||
|
case REM1:
|
||
|
echo = 0;
|
||
|
mode = REM2;
|
||
|
break;
|
||
|
|
||
|
case REM2:
|
||
|
if (c=='/')
|
||
|
{
|
||
|
if (saved_mode == DEFINE)
|
||
|
{
|
||
|
set_mode(OFF, MODE_DEFINE);
|
||
|
}
|
||
|
mode = REM_END;
|
||
|
set_mode(ON, MODE_REMARK_EOL);
|
||
|
}
|
||
|
else if (c=='*')
|
||
|
{
|
||
|
if (saved_mode == DEFINE)
|
||
|
{
|
||
|
set_mode(OFF, MODE_DEFINE);
|
||
|
}
|
||
|
mode = REM_STAR;
|
||
|
set_mode(ON, MODE_REMARK);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mode = saved_mode;
|
||
|
}
|
||
|
printf("/");
|
||
|
break;
|
||
|
|
||
|
case REM_END:
|
||
|
if (c=='\n')
|
||
|
{
|
||
|
set_mode(OFF, MODE_REMARK_EOL);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case REM_STAR:
|
||
|
if (c=='*')
|
||
|
{
|
||
|
mode = REM_STAR_1;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case REM_STAR_1:
|
||
|
if (c=='/')
|
||
|
{
|
||
|
mode = INLINE;
|
||
|
fprintf(stdout,"/");
|
||
|
echo = 0;
|
||
|
set_mode(OFF, MODE_REMARK);
|
||
|
}
|
||
|
else mode = REM_STAR;
|
||
|
break;
|
||
|
|
||
|
case START:
|
||
|
if (c=='#')
|
||
|
{
|
||
|
mode = DEFINE;
|
||
|
set_mode(ON, MODE_DEFINE);
|
||
|
break;
|
||
|
}
|
||
|
else if (c==' ') break;
|
||
|
|
||
|
mode = INLINE;
|
||
|
// and continue in next case
|
||
|
|
||
|
case INLINE:
|
||
|
if (c=='"' && //
|
||
|
prevc != 0x27 && //
|
||
|
prevc != '\\') //
|
||
|
{
|
||
|
set_mode(ON, MODE_STRING);
|
||
|
mode = STRING;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case STRING:
|
||
|
if (c=='"' && prevc != '\\')
|
||
|
{
|
||
|
print_char_html('"');
|
||
|
set_mode(OFF, MODE_STRING);
|
||
|
echo = 0;
|
||
|
mode = INLINE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DEFINE:
|
||
|
if (c=='\n')
|
||
|
{
|
||
|
set_mode(OFF, MODE_DEFINE);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (echo && //
|
||
|
(mode == INLINE || //
|
||
|
(mode!=INLINE && //
|
||
|
bufidx))) //
|
||
|
{
|
||
|
buf[bufidx++] = c;
|
||
|
buf[bufidx] = 0;
|
||
|
if (is_delimeter(c))
|
||
|
{
|
||
|
kw = 0;
|
||
|
if (bufidx>2)
|
||
|
{
|
||
|
kw = is_keyword(buf);
|
||
|
}
|
||
|
if (kw)
|
||
|
{
|
||
|
set_mode(ON, MODE_KEYWORD);
|
||
|
}
|
||
|
tmpc = buf[bufidx-1];
|
||
|
buf[bufidx-1] = 0;
|
||
|
fprintf(stdout,"%s",buf);
|
||
|
if (kw)
|
||
|
{
|
||
|
set_mode(OFF, MODE_KEYWORD);
|
||
|
}
|
||
|
print_char_html(tmpc);
|
||
|
bufidx = 0;
|
||
|
buf[0] = 0;
|
||
|
}
|
||
|
}
|
||
|
else if (echo) print_char_html(c);
|
||
|
|
||
|
if (c=='\n' && mode != REM_STAR)
|
||
|
{
|
||
|
mode = START;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fclose(in);
|
||
|
fprintf(stdout,"</pre>\n");
|
||
|
fprintf(stdout,
|
||
|
"<!-- == Generated by CHTM convertor -->\n");
|
||
|
fprintf(stdout,
|
||
|
"<!-- == CopyRight (C) 1999, Dmitry Obukhov, dso@usa.net -->\n");
|
||
|
|
||
|
return 0;
|
||
|
}
|