31 #define PR(x) cout << #x << " = " << (x) << endl;
33 typedef map<string, string, less<string> > keywordMap_type;
34 typedef keywordMap_type::value_type keyword_type;
36 template<
class A,
class B>
37 ostream& operator<<(ostream& out, const pair<A,B> &p)
39 out << p.first <<
" is defined in " << p.second;
46 string& filename() {
return mFilename;}
47 string& htmlFile() {
return mHTMLFile;}
48 vector<string>& keywords() {
return mKeywords;}
49 vector<string>& body() {
return mBody;}
50 string basename()
const;
55 vector<string> mKeywords;
60 FileInfo::FileInfo() { }
62 FileInfo::FileInfo(
const string& fname)
65 pos = fname.rfind(
".out");
66 if (pos == string::npos) {
67 throw(invalid_argument(
"FileInfo::FileInfo(): error file must have extension '.out'"));
70 ifstream ifs(mFilename.c_str());
72 throw(invalid_argument(
"FileInfo::FileInfo(): cannot open file."));
76 getline(ifs, line,
'\n');
78 if (line.empty())
continue;
79 mBody.push_back(line);
82 string keyfile = mFilename;
83 pos = keyfile.find(
".out", pos);
84 keyfile.replace(keyfile.find(
".out", pos), 4 ,
".keywords");
85 if (access(keyfile.c_str(), R_OK) == 0) {
86 ifs.open(keyfile.c_str());
88 throw(invalid_argument(
"FileInfo::FileInfo(): cannot open keywords file."));
91 getline(ifs, line,
'\n');
93 if (line.empty())
continue;
94 mKeywords.push_back(line);
98 mHTMLFile = basename();
102 string FileInfo::basename()
const
105 string bname = mFilename;
106 pos = bname.rfind(
".out");
107 if (pos != string::npos)
108 bname.erase(pos, bname.size()-pos);
109 pos = bname.rfind(
"/");
110 if (pos != string::npos)
115 void writeHtmlHeader(ostream& ofs,
const string& name)
117 string context(name);
118 size_t pos = context.rfind(
".");
119 if (pos != string::npos)
120 context.erase(pos, context.size()-pos);
122 ofs <<
"<html>" << endl;
123 ofs <<
"<!-- This code is generated automatically. Dont' modify it! -->" << endl;
124 ofs <<
"<head>" << endl;
125 ofs <<
"<title>StarClassLibrary: " << context <<
"</title>" << endl;
126 ofs <<
"</head>" << endl;
127 ofs <<
"<body bgcolor=#ffffff text=#000000>" << endl;
128 ofs <<
"<table border=0 width=110% cellpadding=0>" << endl;
129 ofs <<
"<tr bgcolor=darkblue>" << endl;
130 ofs <<
"<td align=left valign=top>" << endl;
131 ofs <<
"<ul>" << endl;
132 ofs <<
"<h4><br></h4>" << endl;
133 ofs <<
"<h1><font color=white>StarClassLibrary: </font><font color=red>"
134 << context <<
"</font></h1>" << endl;
135 ofs <<
"</ul>" << endl;
136 ofs <<
"</td>" << endl;
137 ofs <<
"<tr>" << endl;
138 ofs <<
"<td align=left> <font size=-1>" << endl;
139 ofs <<
" <a href=index.html>Back to Index</a>" << endl;
140 ofs <<
"</td>" << endl;
141 ofs <<
"</tr>" << endl;
142 ofs <<
"</table>" << endl;
144 ofs <<
"<h3>Synopsis</h3>" << endl;
145 ofs <<
"<pre>" << endl;
146 ofs <<
"#include \"" << name <<
"\"" << endl;
149 void writeHtmlTrailor(ostream& ofs)
151 time_t now = time(0);
152 ofs <<
"<hr noshade=noshade>" << endl;
153 ofs <<
"See the <font color=green><i>StarClassLibrary User Guide and Reference Manual</i></font> for more.<br>" << endl;
154 ofs <<
"File generated on " << ctime(&now);
155 ofs <<
"</body>" << endl;
156 ofs <<
"</html>" << endl;
159 void writeLine(ostream& ofs,
const string& str,
const keywordMap_type &theMap)
167 pos = line.find(
"<",0);
168 if (pos == string::npos)
break;
169 line.replace(pos, 1 ,
"<");
172 pos = line.find(
">",0);
173 if (pos == string::npos)
break;
174 line.replace(pos, 1 ,
">");
176 pos = line.find(
" ;");
177 if (pos != string::npos)
178 line.replace(pos, 2 ,
";");
183 keywordMap_type::const_iterator iter;
187 for (iter = theMap.begin(); iter != theMap.end(); iter++) {
189 while (lpos < line.size()) {
190 const string& search = iter->first;
191 pos = line.find(search,lpos);
192 if (pos == string::npos)
break;
196 lpos = pos+search.size();
197 if (lpos < line.size() && isalnum(line[lpos])) isComplete =
false;
198 if (pos > 5 && line.substr(pos-5, 5) == string(
"href=")) isComplete =
false;
201 html += iter->second;
205 line.replace(pos, search.size(), html);
206 lpos = pos+html.size();
215 int main(
int argc,
char* argv[])
220 cerr <<
"Usage: " << argv[0] <<
" file ..." << endl;
227 vector<FileInfo> files;
228 for (i=1; i<argc; i++) {
231 info =
new FileInfo(
string(argv[i]));
233 catch (exception &e) {
234 cerr << e.what() << endl;
237 files.push_back(*info);
243 for (i=0; i<files.size(); i++) {
245 PR(files[i].basename());
246 PR(files[i].filename());
247 PR(files[i].htmlFile());
248 PR(files[i].keywords().size());
249 PR(files[i].body().size());
256 keywordMap_type keywordMap, emptyMap;
258 for (i=0; i<files.size(); i++) {
259 hname = files[i].htmlFile();
260 for (k=0; k<files[i].keywords().size(); k++)
261 keywordMap.insert(keyword_type(files[i].keywords()[k], hname));
264 copy(keywordMap.begin(), keywordMap.end(), ostream_iterator<keyword_type>(cout,
"\n"));
271 for (i=0; i<files.size(); i++) {
272 ofs.open(files[i].htmlFile().c_str());
274 cerr << argv[0] <<
": error cannot open file " << files[i].htmlFile() << endl;
277 cout <<
"writing file " << files[i].htmlFile() <<
" .";
279 writeHtmlHeader(ofs,files[i].basename());
280 cout <<
'.'; cout.flush();
285 vector<string> &theBody = files[i].body();
290 for (k=0; k<theBody.size(); k++) {
291 if (k+1 >= theBody.size())
continue;
292 if (theBody[k+1][0] !=
'{')
continue;
293 for (j=0; j<files[i].keywords().size(); j++) {
295 search += files[i].keywords()[j];
297 if (theBody[k].find(search) != string::npos) {
299 pos = line.find(
":");
300 if (pos != string::npos)
301 line.erase(pos, line.size()-pos);
303 writeLine(ofs, line, emptyMap);
307 ofs <<
"</pre>" << endl;
308 cout <<
'.'; cout.flush();
312 const int indentSpaces = 3;
313 for (k=0; k<theBody.size(); k++) {
314 if (theBody[k].find(
"}") != string::npos) indentLevel--;
315 assert(indentLevel >= 0);
316 if (theBody[k].find(
"public:") != string::npos && indentLevel > 0)
317 theBody[k].insert(0,
string((indentLevel-1)*indentSpaces,
' '));
319 theBody[k].insert(0,
string(indentLevel*indentSpaces,
' '));
320 if (theBody[k].find(
"{") != string::npos) indentLevel++;
322 cout <<
'.'; cout.flush();
325 ofs <<
"<h3>Interface</h3>" << endl;
326 ofs <<
"<pre>" << endl;
327 for (k=0; k<theBody.size(); k++) {
328 writeLine(ofs, theBody[k], keywordMap);
330 ofs <<
"</pre>" << endl;
331 ofs <<
"<p>" << endl;
332 cout <<
'.'; cout.flush();
334 writeHtmlTrailor(ofs);
336 cout <<
". done" << endl;