00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <string>
00018 #include <fstream.h>
00019 #include <cstdlib>
00020 #include <unistd.h>
00021 #include <stdio.h>
00022 #include <utility>
00023 #include <list>
00024 #include <vector>
00025 #include <map>
00026 #include <stdexcept>
00027 #include <time.h>
00028 #include <assert.h>
00029
00030
00031 #define PR(x) cout << #x << " = " << (x) << endl;
00032
00033 typedef map<string, string, less<string> > keywordMap_type;
00034 typedef keywordMap_type::value_type keyword_type;
00035
00036 template<class A, class B>
00037 ostream& operator<<(ostream& out, const pair<A,B> &p)
00038 {
00039 out << p.first << " is defined in " << p.second;
00040 return out;
00041 }
00042
00043 class FileInfo {
00044 public:
00045 FileInfo(const string&);
00046 string& filename() {return mFilename;}
00047 string& htmlFile() {return mHTMLFile;}
00048 vector<string>& keywords() {return mKeywords;}
00049 vector<string>& body() {return mBody;}
00050 string basename() const;
00051
00052 private:
00053 string mFilename;
00054 string mHTMLFile;
00055 vector<string> mKeywords;
00056 vector<string> mBody;
00057 FileInfo();
00058 };
00059
00060 FileInfo::FileInfo() { }
00061
00062 FileInfo::FileInfo(const string& fname)
00063 {
00064 size_t pos;
00065 pos = fname.rfind(".out");
00066 if (pos == string::npos) {
00067 throw(invalid_argument("FileInfo::FileInfo(): error file must have extension '.out'"));
00068 }
00069 mFilename = fname;
00070 ifstream ifs(mFilename.c_str());
00071 if (!ifs) {
00072 throw(invalid_argument("FileInfo::FileInfo(): cannot open file."));
00073 }
00074 string line;
00075 while (ifs.good()) {
00076 getline(ifs, line, '\n');
00077 if (ifs.eof()) break;
00078 if (line.empty()) continue;
00079 mBody.push_back(line);
00080 }
00081 ifs.close();
00082 string keyfile = mFilename;
00083 pos = keyfile.find(".out", pos);
00084 keyfile.replace(keyfile.find(".out", pos), 4 , ".keywords");
00085 if (access(keyfile.c_str(), R_OK) == 0) {
00086 ifs.open(keyfile.c_str());
00087 if (!ifs) {
00088 throw(invalid_argument("FileInfo::FileInfo(): cannot open keywords file."));
00089 }
00090 while (ifs.good()) {
00091 getline(ifs, line, '\n');
00092 if (ifs.eof()) break;
00093 if (line.empty()) continue;
00094 mKeywords.push_back(line);
00095 }
00096 ifs.close();
00097 }
00098 mHTMLFile = basename();
00099 mHTMLFile += ".html";
00100 }
00101
00102 string FileInfo::basename() const
00103 {
00104 size_t pos;
00105 string bname = mFilename;
00106 pos = bname.rfind(".out");
00107 if (pos != string::npos)
00108 bname.erase(pos, bname.size()-pos);
00109 pos = bname.rfind("/");
00110 if (pos != string::npos)
00111 bname.erase(0, pos);
00112 return bname;
00113 }
00114
00115 void writeHtmlHeader(ostream& ofs, const string& name)
00116 {
00117 string context(name);
00118 size_t pos = context.rfind(".");
00119 if (pos != string::npos)
00120 context.erase(pos, context.size()-pos);
00121
00122 ofs << "<html>" << endl;
00123 ofs << "<!-- This code is generated automatically. Dont' modify it! -->" << endl;
00124 ofs << "<head>" << endl;
00125 ofs << "<title>StarClassLibrary: " << context << "</title>" << endl;
00126 ofs << "</head>" << endl;
00127 ofs << "<body bgcolor=#ffffff text=#000000>" << endl;
00128 ofs << "<table border=0 width=110% cellpadding=0>" << endl;
00129 ofs << "<tr bgcolor=darkblue>" << endl;
00130 ofs << "<td align=left valign=top>" << endl;
00131 ofs << "<ul>" << endl;
00132 ofs << "<h4><br></h4>" << endl;
00133 ofs << "<h1><font color=white>StarClassLibrary: </font><font color=red>"
00134 << context << "</font></h1>" << endl;
00135 ofs << "</ul>" << endl;
00136 ofs << "</td>" << endl;
00137 ofs << "<tr>" << endl;
00138 ofs << "<td align=left> <font size=-1>" << endl;
00139 ofs << " <a href=index.html>Back to Index</a>" << endl;
00140 ofs << "</td>" << endl;
00141 ofs << "</tr>" << endl;
00142 ofs << "</table>" << endl;
00143
00144 ofs << "<h3>Synopsis</h3>" << endl;
00145 ofs << "<pre>" << endl;
00146 ofs << "#include \"" << name << "\"" << endl;
00147 }
00148
00149 void writeHtmlTrailor(ostream& ofs)
00150 {
00151 time_t now = time(0);
00152 ofs << "<hr noshade=noshade>" << endl;
00153 ofs << "See the <font color=green><i>StarClassLibrary User Guide and Reference Manual</i></font> for more.<br>" << endl;
00154 ofs << "File generated on " << ctime(&now);
00155 ofs << "</body>" << endl;
00156 ofs << "</html>" << endl;
00157 }
00158
00159 void writeLine(ostream& ofs, const string& str, const keywordMap_type &theMap)
00160 {
00161
00162
00163
00164 string line(str);
00165 size_t pos;
00166 while (true) {
00167 pos = line.find("<",0);
00168 if (pos == string::npos) break;
00169 line.replace(pos, 1 , "<");
00170 }
00171 while (true) {
00172 pos = line.find(">",0);
00173 if (pos == string::npos) break;
00174 line.replace(pos, 1 , ">");
00175 }
00176 pos = line.find(" ;");
00177 if (pos != string::npos)
00178 line.replace(pos, 2 , ";");
00179
00180
00181
00182
00183 keywordMap_type::const_iterator iter;
00184 size_t lpos;
00185 string html;
00186 bool isComplete;
00187 for (iter = theMap.begin(); iter != theMap.end(); iter++) {
00188 lpos = 0;
00189 while (lpos < line.size()) {
00190 const string& search = iter->first;
00191 pos = line.find(search,lpos);
00192 if (pos == string::npos) break;
00193
00194
00195 isComplete = true;
00196 lpos = pos+search.size();
00197 if (lpos < line.size() && isalnum(line[lpos])) isComplete = false;
00198 if (pos > 5 && line.substr(pos-5, 5) == string("href=")) isComplete = false;
00199 if (isComplete) {
00200 html = "<a href=";
00201 html += iter->second;
00202 html += '>';
00203 html += iter->first;
00204 html += "</a>";
00205 line.replace(pos, search.size(), html);
00206 lpos = pos+html.size();
00207 }
00208 }
00209 }
00210
00211
00212 ofs << line << endl;
00213 }
00214
00215 int main(int argc, char* argv[])
00216 {
00217 int i, j, k;
00218
00219 if (argc < 2) {
00220 cerr << "Usage: " << argv[0] << " file ..." << endl;
00221 return 2;
00222 }
00223
00224
00225
00226
00227 vector<FileInfo> files;
00228 for (i=1; i<argc; i++) {
00229 FileInfo *info;
00230 try {
00231 info = new FileInfo(string(argv[i]));
00232 }
00233 catch (exception &e) {
00234 cerr << e.what() << endl;
00235 continue;
00236 }
00237 files.push_back(*info);
00238 delete info;
00239 }
00240
00241 #ifdef DEBUG
00242 PR(files.size());
00243 for (i=0; i<files.size(); i++) {
00244 PR(i);
00245 PR(files[i].basename());
00246 PR(files[i].filename());
00247 PR(files[i].htmlFile());
00248 PR(files[i].keywords().size());
00249 PR(files[i].body().size());
00250 }
00251 #endif
00252
00253
00254
00255
00256 keywordMap_type keywordMap, emptyMap;
00257 string hname;
00258 for (i=0; i<files.size(); i++) {
00259 hname = files[i].htmlFile();
00260 for (k=0; k<files[i].keywords().size(); k++)
00261 keywordMap.insert(keyword_type(files[i].keywords()[k], hname));
00262 }
00263 #ifdef DEBUG
00264 copy(keywordMap.begin(), keywordMap.end(), ostream_iterator<keyword_type>(cout, "\n"));
00265 #endif
00266
00267
00268
00269
00270 ofstream ofs;
00271 for (i=0; i<files.size(); i++) {
00272 ofs.open(files[i].htmlFile().c_str());
00273 if (!ofs) {
00274 cerr << argv[0] << ": error cannot open file " << files[i].htmlFile() << endl;
00275 continue;
00276 }
00277 cout << "writing file " << files[i].htmlFile() << " .";
00278
00279 writeHtmlHeader(ofs,files[i].basename());
00280 cout << '.'; cout.flush();
00281
00282
00283
00284
00285 vector<string> &theBody = files[i].body();
00286
00287
00288 string search, line;
00289 size_t pos;
00290 for (k=0; k<theBody.size(); k++) {
00291 if (k+1 >= theBody.size()) continue;
00292 if (theBody[k+1][0] != '{') continue;
00293 for (j=0; j<files[i].keywords().size(); j++) {
00294 search = "class ";
00295 search += files[i].keywords()[j];
00296 search += ' ';
00297 if (theBody[k].find(search) != string::npos) {
00298 line = theBody[k];
00299 pos = line.find(":");
00300 if (pos != string::npos)
00301 line.erase(pos, line.size()-pos);
00302 line += ';';
00303 writeLine(ofs, line, emptyMap);
00304 }
00305 }
00306 }
00307 ofs << "</pre>" << endl;
00308 cout << '.'; cout.flush();
00309
00310
00311 int indentLevel = 0;
00312 const int indentSpaces = 3;
00313 for (k=0; k<theBody.size(); k++) {
00314 if (theBody[k].find("}") != string::npos) indentLevel--;
00315 assert(indentLevel >= 0);
00316 if (theBody[k].find("public:") != string::npos && indentLevel > 0)
00317 theBody[k].insert(0, string((indentLevel-1)*indentSpaces, ' '));
00318 else
00319 theBody[k].insert(0, string(indentLevel*indentSpaces, ' '));
00320 if (theBody[k].find("{") != string::npos) indentLevel++;
00321 }
00322 cout << '.'; cout.flush();
00323
00324
00325 ofs << "<h3>Interface</h3>" << endl;
00326 ofs << "<pre>" << endl;
00327 for (k=0; k<theBody.size(); k++) {
00328 writeLine(ofs, theBody[k], keywordMap);
00329 }
00330 ofs << "</pre>" << endl;
00331 ofs << "<p>" << endl;
00332 cout << '.'; cout.flush();
00333
00334 writeHtmlTrailor(ofs);
00335 ofs.close();
00336 cout << ". done" << endl;
00337 }
00338 return 0;
00339 }