28 #define PR(x) cout << #x << " = " << (x) << endl;
39 ClassInfo::ClassInfo() : correct(false), bodyStart(0), bodyEnd(0) {}
41 void ClassInfo::print()
43 cout <<
"name = " << name << endl;
44 cout <<
"bodyStart = " << bodyStart << endl;
45 cout <<
"bodyEnd = " << bodyEnd << endl;
48 size_t ccount(
string& s,
char c)
51 for (
int i=0; i<s.size(); i++)
56 int main(
int argc,
char* argv[])
61 cerr <<
"Usage: " << argv[0] <<
" file ..." << endl;
65 vector<string> inputFileList;
66 for (i=1; i<argc; i++)
67 inputFileList.push_back(argv[i]);
70 for (
int iFile=0; iFile<inputFileList.size(); iFile++) {
72 string inputfile = inputFileList[iFile];
74 if (access(inputfile.c_str(), R_OK) != 0) {
75 cerr << argv[0] <<
": cannot access file " << inputfile << endl;
79 cout <<
"preparing file " << inputfile <<
" .";
81 string tempfile1(tempnam(
".",0)); tempfile1 +=
".cc";
82 string tempfile2(tempnam(
".",0)); tempfile2 +=
".cc";
94 command +=
"| sed 's/\\#.*include/\\/\\/&/g' > ";
97 cout << command << endl;
99 system(command.c_str());
100 cout <<
'.'; cout.flush();
107 command += tempfile1;
108 command +=
" | grep -v ";
109 command += tempfile1;
111 command += tempfile2;
113 cout << command << endl;
115 system(command.c_str());
116 cout <<
'.'; cout.flush();
128 ifstream ifs(tempfile2.c_str());
130 getline(ifs, line,
'\n');
131 if (ifs.eof())
break;
132 if (line.empty())
continue;
134 for (i=0; i<line.size(); i++) {
144 if (i+1 < line.size() && line[i+1] ==
';') {
160 cout <<
'.'; cout.flush();
162 while(pos < bigLine.size()) {
163 pos = bigLine.find(
"public:", pos);
164 if (pos != string::npos) {
165 bigLine.replace(pos, 7 ,
"public:\n");
172 while(pos < bigLine.size()) {
173 pos = bigLine.find(
"private:", pos);
174 if (pos != string::npos) {
175 bigLine.replace(pos, 8 ,
"private:\n");
182 while(pos < bigLine.size()) {
183 pos = bigLine.find(
"protected:", pos);
184 if (pos != string::npos) {
185 bigLine.replace(pos, 10 ,
"protected:\n");
191 cout <<
'.'; cout.flush();
197 while(pos < bigLine.size()) {
198 pos = bigLine.find(
"inline ", pos);
199 if (pos != string::npos) {
200 bigLine.erase(pos, 7);
205 cout <<
'.'; cout.flush();
211 while(pos < bigLine.size()) {
212 pos = bigLine.find(
":", pos);
213 if (pos != string::npos) {
214 bigLine.replace(pos, 1,
" : ");
220 cout <<
'.'; cout.flush();
228 pos = bigLine.find(
" ", pos);
229 if (pos != string::npos) {
230 bigLine.erase(pos, 1);
236 if (pos >= bigLine.size()) {
241 cout <<
'.'; cout.flush();
246 vector<string> allLines;
248 bool beginLine =
true;
249 for (i=0; i<bigLine.size(); i++) {
259 allLines.push_back(line);
271 cout <<
'.'; cout.flush();
274 copy(allLines.begin(), allLines.end(), ostream_iterator<string>(cout));
281 for (i=0; i<allLines.size(); i++) {
283 pos = line.find(
"operator ",0);
284 if (pos != string::npos) line.replace(pos, 9 ,
"operator");
285 pos = line.find(
"< class",0);
286 if (pos != string::npos) line.replace(pos, 7 ,
"<class");
287 pos = line.find(
" < ",0);
288 if (pos != string::npos) line.replace(pos, 3 ,
"<");
289 pos = line.find(
" > ",0);
290 if (pos != string::npos) line.replace(pos, 3 ,
"> ");
291 pos = line.find(
" >",0);
292 if (pos != string::npos) line.replace(pos, 2 ,
">");
293 pos = line.find(
" & ",0);
294 if (pos != string::npos) line.replace(pos, 3 ,
"& ");
295 pos = line.find(
"template <",0);
296 if (pos != string::npos) line.replace(pos, 10 ,
"template<");
297 pos = line.find(
"private :",0);
298 if (pos != string::npos) line.replace(pos, 9 ,
"private:");
299 pos = line.find(
"protected :",0);
300 if (pos != string::npos) line.replace(pos, 11 ,
"protected:");
301 pos = line.find(
"public :",0);
302 if (pos != string::npos) line.replace(pos, 8 ,
"public:");
303 pos = line.find(
": :",0);
304 if (pos != string::npos) line.replace(pos, 3 ,
"::");
305 pos = line.find(
" :: ",0);
306 if (pos != string::npos) line.replace(pos, 4 ,
"::");
309 cout <<
'.'; cout.flush();
314 vector<string>::iterator viter;
315 vector<string> theText;
316 bool inPrivateRegion =
false;
317 bool inProtectedRegion =
false;
318 for (viter = allLines.begin(); viter != allLines.end(); viter++) {
319 if (inPrivateRegion) {
320 if (viter->find(
"protected:") != string::npos ||
321 viter->find(
"public:") != string::npos ||
322 *viter == string(
"};\n"))
323 inPrivateRegion =
false;
326 if (viter->find(
"private:") != string::npos)
327 inPrivateRegion =
true;
329 if (inProtectedRegion) {
330 if (viter->find(
"private:") != string::npos ||
331 viter->find(
"public:") != string::npos ||
332 *viter == string(
"};\n"))
333 inProtectedRegion =
false;
336 if (viter->find(
"protected:") != string::npos)
337 inProtectedRegion =
true;
340 if (!inPrivateRegion && !inProtectedRegion &&
341 *viter !=
string(
"\n") && !viter->empty())
342 theText.push_back(*viter);
345 cout <<
'.'; cout.flush();
350 vector<ClassInfo> classInfo;
352 for (k=0; k<theText.size(); k++) {
353 if ((pos=theText[k].rfind(
"class ")) != string::npos &&
354 theText[k].rfind(
";") == string::npos ) {
356 if (theText[k][pos-1] ==
'<' ||
357 theText[k][pos-1] ==
',')
continue;
360 if (theText[k][pos-2] ==
'<' ||
361 theText[k][pos-2] ==
',')
continue;
364 pos1 = theText[k].find_first_not_of(
' ', pos+5);
365 pos2 = theText[k].find_first_of(
' ', pos1)-1;
366 info.name = theText[k].substr(pos1, pos2-pos1+1);
367 info.bodyStart = k+1;
368 classInfo.push_back(info);
370 if ((pos=theText[k].find(
"enum ")) != string::npos) {
372 pos1 = theText[k].find_first_not_of(
' ', pos+4);
373 pos2 = theText[k].find_first_of(
' ', pos1)-1;
374 info.name = theText[k].substr(pos1, pos2-pos1+1);
375 info.bodyStart = k+1;
376 classInfo.push_back(info);
378 if ((pos=theText[k].find(
"struct ")) != string::npos) {
380 pos1 = theText[k].find_first_not_of(
' ', pos+4);
381 pos2 = theText[k].find_first_of(
' ', pos1)-1;
382 info.name = theText[k].substr(pos1, pos2-pos1+1);
383 info.bodyStart = k+1;
384 classInfo.push_back(info);
387 cout <<
'.'; cout.flush();
394 for (k = 0; k<theText.size(); k++) {
395 if (theText[k].find(
"};") != string::npos) {
401 PR(classInfo.size());
403 if (tmp.size() != classInfo.size()) {
404 cout <<
" . error" << endl;
405 cout << argv[0] <<
": tmp.size() != classInfo.size()" << endl;
406 remove(tempfile1.c_str());
407 remove(tempfile2.c_str());
414 pair<size_t, size_t> minPair;
417 while (nMatches != classInfo.size()) {
418 minDist = theText.size();
419 for (k=0; k<tmp.size(); k++) {
420 if (tmp[k] == 0)
continue;
421 for (i=0; i<classInfo.size(); i++) {
422 if (classInfo[i].correct)
continue;
423 dist = tmp[k]-classInfo[i].bodyStart;
424 if (dist < 0)
continue;
425 if (dist < minDist) {
432 classInfo[minPair.second].bodyEnd = tmp[minPair.first];
433 classInfo[minPair.second].correct =
true;
434 tmp[minPair.first] = 0;
437 cout <<
'.'; cout.flush();
439 for (i=0; i<classInfo.size(); i++) {
440 classInfo[i].print();
449 vector<bool> markForDelete(theText.size(),
false);
452 size_t rightBrackets;
453 for (k=0; k<theText.size(); k++) {
454 if (theText[k][0] ==
'{') {
456 for (i=0; i<classInfo.size(); i++) {
457 if (classInfo[i].bodyStart == k) {
463 theText[k-1].find(
"namespace") != string::npos &&
464 theText[k-1].find(
"using") == string::npos) {
469 leftBrackets = rightBrackets = 0;
470 theText[k-1].insert(theText[k-1].size()-1,
";");
471 for (j=k; j<theText.size(); j++) {
472 markForDelete[j] =
true;
475 leftBrackets += ccount(theText[j],
'{');
476 rightBrackets += ccount(theText[j],
'}');
477 if (j > k && leftBrackets == rightBrackets) {
486 for (k=0; k<theText.size(); k++) {
487 if (markForDelete[k]) cout <<
"DELETE>>>";
491 for (k=0; k<theText.size(); k++)
492 if (markForDelete[k]) theText[k].erase();
493 cout <<
'.'; cout.flush();
501 bool isClassDeclaration;
502 bool isInsideClassBody;
503 for (k=0; k<theText.size(); k++) {
504 if (theText[k].find(
"::") != string::npos) {
505 isInsideClassBody =
false;
506 for (i=0; i<classInfo.size(); i++) {
507 if (k > classInfo[i].bodyStart && k < classInfo[i].bodyEnd)
508 isInsideClassBody =
true;
510 if (!isInsideClassBody) theText[k].erase();
512 if (theText[k].find(
"extern \"C\"") != string::npos) theText[k].erase();
513 pos = theText[k].find(
" ;",0);
514 if (pos != string::npos) theText[k].replace(pos, 2 ,
";");
515 isClassDeclaration =
false;
516 for (i=0; i<classInfo.size(); i++) {
517 if (classInfo[i].bodyStart-1 == k)
518 isClassDeclaration =
true;
520 if (!isClassDeclaration) {
521 pos = theText[k].find(
" : ",0);
522 if (pos != string::npos) {
523 theText[k].erase(pos, theText[k].size()-pos);
528 cout <<
'.'; cout.flush();
533 pos = inputfile.rfind(
'/');
534 if (pos != string::npos)
535 inputfile.erase(0, pos+1);
537 string keywordFile(inputfile); keywordFile +=
".keywords";
538 string outFile(inputfile); outFile +=
".out";
543 ofstream keyfs(keywordFile.c_str());
544 ofstream outfs(outFile.c_str());
545 for (k=0; k<theText.size(); k++) {
546 if (!theText[k].empty() && theText[k] !=
"\n")
549 for (i=0; i<classInfo.size(); i++) keyfs << classInfo[i].name << endl;
550 cout <<
'.'; cout.flush();
555 remove(tempfile1.c_str());
556 remove(tempfile2.c_str());
560 copy(theText.begin(), theText.end(), ostream_iterator<string>(cout,
"\n"));
562 cout <<
". done" << endl;