Сабж, в общем...
Для работы класса нужен класс, который приведен здесь:
SRC: Hash function (based on CRC-32)Автор: Flamer
Дата: 29.08.02
Хидер:
// CPPConv.h header file
//---------------------------------------------------------------------------
#ifndef CPPConvH
#define CPPConvH
//---------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
//---------------------------------------------------------------------------
#include "Hash.h"
//---------------------------------------------------------------------------
#define BUF_SIZE 1024 // размер приемного буфера
#define MAX_KWD_LEN 50 // максимальная длина ключевого слова
#define KEYWORDS_COUNT 95 // количество клчевых слов
//---------------------------------------------------------------------------
typedef enum { // состояния автомата
psEmpty, // пустое
psMultiLineDefine, // обработка многострочного #define
psMultiLineComment // обработка многострочного комментария
}enParseState;
//---------------------------------------------------------------------------
class CPPConv
{
private:
unsigned int HashTable[KEYWORDS_COUNT];
static char* Keywords[KEYWORDS_COUNT];
FILE* fIn;
FILE* fOut;
char* buffer;
enParseState ParseState;
private:
void CloseHandles();
void Reset();
bool MakeHashTable();
void PutString(FILE* outfile, const char* str, bool bConvert);
inline bool IsSingleLineComment(char ch){return (ch=='/');};
inline bool IsMultiLineComment(char ch){return (ch=='*');};
void WriteSpaces(FILE* outfile,int Num);
void ParseString(FILE* outfile, const char* s);
bool IsDelimiter(char ch);
bool IsKeyword(char* s);
bool IsDigit(char* s);
void PutChar(FILE* outfile,char ch);
public:
bool Convert(const char* InputFileName, const char* OutputFileName);
public:
CPPConv();
~CPPConv();
};
//---------------------------------------------------------------------------
#endif
Сорц:
//CPPConv.cpp implementation file
//---------------------------------------------------------------------------
#include "CPPConv.h"
//---------------------------------------------------------------------------
char* CPPConv::Keywords[] = {
"__asm", "__automated","__cdecl","__classid",
"__closure","__declspec","__dispid","__explicit",
"__export","__fastcall","__finally","__import",
"__int16","__int32","__int64","__int8","__pascal",
"__property","__published","__rtti","__stdcall",
"__thread","__try","_asm","_cdecl","_export",
"_fastcall","_import","_pascal","_stdcall","asm",
"auto","bool","break","case","catch","cdecl","char",
"class","const","const_cast","continue","default",
"delete","do","double","dynamic_cast","else","enum",
"explicit","extern","false","float","for","friend",
"goto","if","inline","int","long","mutable","namespace",
"new","operator","pascal","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","while2"
};
//---------------------------------------------------------------------------
CPPConv::CPPConv(): fIn(NULL),fOut(NULL),buffer(NULL),ParseState(psEmpty)
{
}
//---------------------------------------------------------------------------
CPPConv::~CPPConv()
{
CloseHandles();
Reset();
}
//---------------------------------------------------------------------------
void CPPConv::CloseHandles()
{
if(fIn)
{
fclose(fIn);
fIn=NULL;
}
if(fOut)
{
fclose(fOut);
fOut=NULL;
}
}
//---------------------------------------------------------------------------
void CPPConv::Reset()
{
if(buffer)
{
delete [] buffer;
buffer=NULL;
}
ParseState=psEmpty;
}
//---------------------------------------------------------------------------
void CPPConv::WriteSpaces(FILE* outfile,int Num)
{
if(Num) for(int i=0;i<Num;i++)
fputs(" ",outfile);
}
//---------------------------------------------------------------------------
bool CPPConv::Convert(const char* InputFileName, const char* OutputFileName)
{
if(!InputFileName || !OutputFileName) return false;
CloseHandles();
Reset();
buffer = new char[BUF_SIZE];
if(!buffer) return false;
fIn = fopen(InputFileName, "r");
if(!fIn) return false;
fOut = fopen(OutputFileName,"w");
if(!fOut) return false;
if(!MakeHashTable()) return false;
bool EmptyStr;
PutString(fOut,"<DIV STYLE=\"background-color:#FFFFFF\">",false);
PutString(fOut,"<FONT COLOR=\"#000000\">",false);
PutString(fOut,"<FONT FACE=\"Courier New\" STYLE=\"font-size:14px;\">",false);
while(true)
{
if(!fgets(buffer,BUF_SIZE-1,fIn)) break;
int cntr=0;
EmptyStr=false;
int NumSpaces=-1;
while(isspace(buffer[cntr]))
{
if(buffer[cntr]=='\t')NumSpaces+=4;
else NumSpaces+=1;
cntr++;
}
int ended = strlen(buffer);
while(isspace(buffer[ended]))
{
buffer[ended]='\0';
ended--;
}
unsigned cur_buf_len = strlen(buffer);
if((unsigned)cntr == cur_buf_len || !cur_buf_len) EmptyStr=true;
WriteSpaces(fOut,NumSpaces); // write beginning 's
if((unsigned)cntr<cur_buf_len)
{
switch(buffer[cntr])
{
case'#':
{
if(ParseState==psMultiLineDefine)
{
ParseState=psEmpty;
PutString(fOut,"</FONT>",false);
}
if(ParseState!=psMultiLineComment)
PutString(fOut,"<FONT COLOR=#008000>",false);
int ended = strlen(buffer);
while(isspace(buffer[ended])) ended--;
if(ended>=2)// not empty string
{
bool bStringFound=false;
bool bCommentFound=false;
int i;
for(i=cntr;i<ended;i++)
{
if(buffer[i]=='"')
{
if(i>0 && buffer[i-1]!='\\' && !bStringFound) bStringFound=true;
if(i>0 && buffer[i-1]!='\\' && bStringFound) bStringFound=false;
}
if(buffer[i]=='/')
{
if((buffer[i+1]=='*' && !bStringFound) || (buffer[i+1]=='/' && !bStringFound))
{
bCommentFound=true;
if(ParseState!=psEmpty)
{
PutString(fOut,"</FONT>",false);
ParseState=psEmpty;
}
break;
}
}
}//for
if(bCommentFound)
{
char ch = buffer[i-1];
buffer[i-1]='\0';
PutString(fOut,buffer,true);
PutString(fOut,"</FONT>",false);
buffer[i-1]=ch;
char* ptr = &buffer[i-1];
ParseString(fOut,ptr);
}
if(buffer[ended-2]=='\\' && !bCommentFound) // multiline define
{
buffer[i-1]='\0';
PutString(fOut,buffer,true);
ParseState=psMultiLineDefine;
}
else if(!bCommentFound) // singleline define
{
buffer[i-1]='\0';
PutString(fOut,buffer,true);
if(ParseState !=psMultiLineComment) PutString(fOut,"</FONT>",false);
}
}
}
break;
case '/': // possible single- or multiline comment
{
if((unsigned)cntr+1<(unsigned)strlen(buffer))
{
if(IsSingleLineComment(buffer[cntr+1]))
{
if(ParseState != psMultiLineComment)
{
if(ParseState==psMultiLineDefine)
{
PutString(fOut,"</FONT>",false);
ParseState = psEmpty;
}
PutString(fOut,"<FONT COLOR=#008000>",false);
}
PutString(fOut,buffer,true);
if(ParseState != psMultiLineComment) PutString(fOut,"</FONT>",false);
}
else if(IsMultiLineComment(buffer[cntr+1])) // begin multiline comment
{
if(ParseState != psMultiLineComment)
{
ParseState = psMultiLineComment;
PutString(fOut,"<FONT COLOR=#008000>",false);
ParseString(fOut,buffer);
}
}
else ParseString(fOut,buffer);
}
else PutString(fOut,buffer,true);
}
break;
case '*':
{
if((unsigned)cntr+1<(unsigned)strlen(buffer)) // end of multiline comment
ParseString(fOut,buffer);
}
break;
default:
// default string processing
if(ParseState!=psMultiLineDefine)ParseString(fOut,buffer);
else PutString(fOut,buffer,true);
if(ParseState==psMultiLineDefine && buffer[strlen(buffer)-2]!='\\')
{
ParseState=psEmpty;
PutString(fOut,"</FONT>",false);
}
if(ParseState==psMultiLineDefine && EmptyStr) ParseState=psEmpty;
break;
}
}//if(cntr<strlen(buffer))
else
{
if(ParseState==psMultiLineDefine)
{
ParseState=psEmpty;
PutString(fOut,"</FONT>",false);
}
}
memset(buffer,0,BUF_SIZE);
PutString(fOut,"<BR>",false);
}
PutString(fOut,"</FONT></FONT></DIV>",false);
return true;
}
//---------------------------------------------------------------------------
void CPPConv::PutChar(FILE* outfile,char ch)
{
if(ch=='<') PutString(outfile,"<",false);
else if(ch=='>') PutString(outfile,">",false);
else if(ch=='&') PutString(outfile,"&",false);
else fputc(ch,outfile);
}
//---------------------------------------------------------------------------
void CPPConv::ParseString(FILE* outfile, const char* s)
{
if(!s) return;
static char kwd_buff[MAX_KWD_LEN] = {0};
memset(kwd_buff,0,MAX_KWD_LEN);
int s_len = strlen(s);
if(!s_len) return;
int cntr=0;
bool EmptyStr=false;
while(isspace(s[cntr])) cntr++;
if(cntr == s_len) EmptyStr=true;
if(EmptyStr) return;
int buff_offset=0;
bool bStringFound=false;
if(ParseState==psMultiLineComment)
{
bool bEndOfMLFound=false; // end of multiline comment flag
for(int i=cntr;i<s_len;i++)
{
if(s[i]=='"')
{
if(i>0 && s[i-1]!='\\' && !bStringFound) bStringFound=true;
if(i>0 && s[i-1]!='\\' && bStringFound) bStringFound=false;
}
if(s[i]=='*')
{
if(s[i+1]=='/' && !bStringFound)
{
// found end of multiline comment
// copy portion of string (cntr, i+1) to buffer
bEndOfMLFound=true;
for(int y=cntr;y<i+2;y++)
{
PutChar(outfile,s[y]);
}
PutString(outfile,"</FONT>",false);
ParseState=psEmpty;
cntr = i+2; break;
}
}
}//for
if(!bEndOfMLFound)
{
PutString(outfile,s,true);
return;
}
}
for(int i=cntr;i<s_len;i++)
{
if(s[i]=='"' /*&& i>0*/ && s[i-1]!='\\' && s[i-1]!='\'') // string begin
{
PutString(outfile,"<FONT COLOR=#000080><B>",false);
PutChar(outfile,s[i]);
int j;
for(j=i+1;j<s_len;j++)
{
if(s[j]=='"') // end string
{
if((s[j-1] =='\\' && s[j-2] =='\\') || s[j-1] !='\\')
{
fputc(s[j],outfile);
break;
}
}
PutChar(outfile,s[j]);
}
PutString(outfile,"</B></FONT>",false);
i=j; continue;
}
if(IsSingleLineComment(s[i]) && IsSingleLineComment(s[i+1]))
{
//beginning single-line comment
PutString(outfile,kwd_buff,true);
PutString(outfile,"<FONT COLOR=#008000>",false);
for(int j=i;j<s_len;j++)PutChar(outfile,s[j]);
PutString(outfile,"</FONT>",false);
return;
}
if(IsSingleLineComment(s[i]) && IsMultiLineComment(s[i+1])) //begin multi-line comment
{
PutString(outfile,kwd_buff,true);
PutString(outfile,"<FONT COLOR=#008000>",false);
bool bToEnd=true;
int j;
for(j=i;j<s_len;j++)
{
if(IsMultiLineComment(s[j]) && IsSingleLineComment(s[j+1]))
{
PutChar(outfile,s[j]);
PutChar(outfile,s[j+1]);
PutString(outfile,"</FONT>",false);
bToEnd=false;
break;
}
else PutChar(outfile,s[j]);
}
if(bToEnd)
{
ParseState = psMultiLineComment;
return;
}
else
{
buff_offset=0;
memset(kwd_buff,0,MAX_KWD_LEN);
i=j+1;continue;
}
}
if(IsMultiLineComment(s[i]) && IsSingleLineComment(s[i+1])) // End of multiline comment
{
PutString(outfile,kwd_buff,true);
PutChar(outfile,s[i]);
PutChar(outfile,s[i+1]);
PutString(outfile,"</FONT>",false);
ParseState = psEmpty;
buff_offset=0;
memset(kwd_buff,0,MAX_KWD_LEN);
i++; continue;
}
if(isspace(s[i]) ||/* ispunct(s[i]) || */IsDelimiter(s[i]))
{
if(IsKeyword(kwd_buff))
{
PutString(outfile,"<FONT COLOR=#0000FF>",false);
PutString(outfile,kwd_buff,true);
PutString(outfile,"</FONT>",false);
}
else if(IsDigit(kwd_buff))
{
PutString(outfile,"<FONT COLOR=#D00000><B>",false);
PutString(outfile,kwd_buff,true);
PutString(outfile,"</B></FONT>",false);
}
else // simple put !!!
PutString(outfile,kwd_buff,true);
buff_offset=0;
memset(kwd_buff,0,MAX_KWD_LEN);
PutChar(outfile,s[i]);
} //if(isspace(s[i]) || ispunct(s[i]) || is_delimiter(s[i]))
else
{
kwd_buff[buff_offset] = s[i];
buff_offset++;
}
}
}
//---------------------------------------------------------------------------
bool CPPConv::IsDigit(char* s)
{
if(!s) return false;
while(isspace(*s) || IsDelimiter(*s))s++;
int ended = strlen(s);
while(isspace(s[ended]) || IsDelimiter(s[ended]))
{
s[ended]='\0';
ended--;
}
int s_len = strlen(s);
bool bRet=false;
if(s_len==1 && s[0]=='0') bRet=true;
else
{
int result = atoi(s);
if(result!=0) bRet=true;
else
{
if(s_len>2 && s[0]=='0' && s[1]=='x' ) bRet=true;
if(s_len>1 && s[0]=='0' && (s[s_len-1]=='L' || s[s_len-1]=='l')) bRet=true;
}
}
return bRet;
}
//---------------------------------------------------------------------------
bool CPPConv::IsKeyword(char* s)
{
if(!s) return false;
while(isspace(*s) || IsDelimiter(*s))s++;
int ended = strlen(s);
while(isspace(s[ended]) || IsDelimiter(s[ended]))
{
s[ended]='\0';
ended--;
}
unsigned int hash = GetHash(s);
for(int i=0;i<KEYWORDS_COUNT;i++)
if(HashTable[i]==hash) return true;
return false;
}
//---------------------------------------------------------------------------
bool CPPConv::IsDelimiter(char ch)
{
switch(ch)
{
case '|':
case '(':
case ')':
case '&':
case '*':
case '[':
case ']':
case ':':
case ';':
case '/':
case '^':
case '%':
case '!':
case '~':
case '=':
case '+':
case '<':
case '>':
case '\t':
case ' ':
case '.':
case ',':
case '{':
case '}':
case '-':
return true;
default:
return false;
}
}
//---------------------------------------------------------------------------
void CPPConv::PutString(FILE* outfile, const char* str, bool bConvert)
{
if(!str) return;
if(bConvert)
{
for(unsigned int i=0;i<(unsigned)strlen(str);i++)
{
if(str[i]=='<') fputs("<",outfile);
else if(str[i]=='>') fputs(">",outfile);
else if(str[i]=='&') fputs("&",outfile);
else PutChar(outfile,str[i]);
}
}
else fputs(str,outfile);
}
//---------------------------------------------------------------------------
bool CPPConv::MakeHashTable()
{
for(int i=0;i<KEYWORDS_COUNT;i++)
HashTable[i] = GetHash(Keywords[i]);
return true;
}
//---------------------------------------------------------------------------
Пример использования:
#include "CPPConv.h"
CPPConv c;
c.Convert("C:\\test.cpp", "C:\\test.html");