header2=
http://www.borlandforum.com/impboard/impboard.dll?action=read&db=cpp_tip&no=36
에 올린 팁에 있는 C++ 소스코드를 Syntax-Highlighted HTML로 변환하는 코드를 약간
수정했습니다.
정규표현식이 소스 코드내에 하드 코딩된 것을 수정하여, 별도의 텍스트 파일(cpp.stx)에서
읽어들이는 방식으로 고쳤습니다.
소스 코드를 수정하실 필요없이 cpp.stx 파일만 수정하면 HTML의 양식을 고칠
수 있고, cpp.stx 뿐만 아니라, pas.stx와 같이 다른 언어도 변환할 수 있도록 고쳐봤습니다.
문법 정의 파일은 src2html.exe와 같은 폴더에 넣어 두시면 됩니다.
IDE나 에디터에서 외부 프로그램으로 등록시켜서 사용해도 좋고, 웹 프로그래밍하시는
분들은 CGI에 응용하셔도 좋겠네요.
/*
* FILE: src2html.cpp
* VERSION: 0.1
* DESCRIPTION: Converts a source file to syntax highlighted HTML.
*/
//---------------------------------------------------------------------------
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#pragma hdrstop
#include <iterator>
#include <map>
#include <boost/regex.hpp>
//---------------------------------------------------------------------------
using namespace std;
inline string extract_filepath(const string& filename)
{ // 윈도가 아닌 OS에서 수정 필요.
return filename.substr(0, filename.rfind('\\'));
}
inline string extract_fileext(const string& filename)
{
return filename.substr(filename.rfind('.') + 1, filename.length());
}
void load_syntax(map<string, string>& syntax, const string& filename);
string make_expression(map<string, string>& syntax);
string make_format(map<string, string>& syntax);
int main(int argc, char* argv[])
{
if (argc < 1) exit(-1);
try{
string syntax_filename = extract_filepath(string(argv[0])) + '\\' +
extract_fileext(string(argv[1])) + ".stx";
map<string, string> syntax;
load_syntax(syntax, syntax_filename);
string header1 = syntax["header1"], header2 = syntax["header2"],
footer = syntax["footer"], pre_format = syntax["pre_format"],
s_expression = make_expression(syntax),
s_format = make_format(syntax);
cout << header1 << argv[1] << header2 << endl
<< s_expression << endl << s_format << endl
<< footer << endl;
boost::regex pre_expression(syntax["pre_expression"]),
expression(s_expression);
ifstream fin; ofstream fout;
ostringstream t(ios::out | ios::binary);
string in_filename, out_filename, in_filedata;
for (int i = 1; i < argc; ++i)
{
in_filename = argv[i];
cout << "Processing file " << in_filename << endl;
syntax.clear();
fin.open(in_filename.c_str());
in_filedata.assign((istreambuf_iterator<char>(fin)),
istreambuf_iterator<char>());
fin.close();
out_filename = in_filename + ".htm";
fout.open(out_filename.c_str());
fout << header1 << in_filename << header2;
// strip '<' and '>' first by outputting to a
// temporary string stream
boost::regex_merge(ostream_iterator<char>(t),
in_filedata.begin(), in_filedata.end(),
pre_expression, pre_format);
// then output to final output stream
// adding syntax highlighting:
string s(t.str());
boost::regex_merge(ostream_iterator<char>(fout),
s.begin(), s.end(), expression, s_format);
fout << "footer";
fout.close();
system(out_filename.c_str()); // 윈도가 아닌 OS에서 수정 필요.
}
}
catch(...) { return -1; }
return 0;
}
//---------------------------------------------------------------------------
void load_syntax(map<string, string>& syntax, const string& filename)
{
ifstream fin(filename.c_str());
if (!fin) exit(0);
string line, key, value;
int pos;
while (getline(fin, line)) {
if (line.length() < 3 || line[0] == ';') continue;
pos = line.find('=');
if (pos < 2 || pos == string::npos) continue;
key = line.substr(0, pos);
value = line.substr(pos + 1, line.length());
if (value.length() < 1) continue;
syntax.insert(map<string, string>::value_type(key, value));
}
}
string make_expression(map<string, string>& syntax)
{
string expression_num = "expression1", expressions = syntax[expression_num];
for (char i = '2'; i <= '9'; ++i) {
expression_num[10] = i;
if (!syntax.count(expression_num)) break;
expressions += '|' + syntax[expression_num];
}
return expressions;
}
string make_format(map<string, string>& syntax)
{
string format_num = "format#", formats;
for (char i = '1'; i <= '9'; ++i) {
format_num[6] = i;
if (!syntax.count(format_num)) break;
formats += "(?" + (i + syntax[format_num] + ')');
}
return formats;
}