//: C04:Showerr.cpp {RunByHand} // From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison. // (c) 1995-2004 MindView, Inc. All Rights Reserved. // See source code use permissions stated in the file 'License.txt', // distributed with the code package available at www.MindView.net. // Un-comment error generators. #include #include #include #include #include #include #include #include "../require.h" using namespace std; const string USAGE = "usage: showerr filename chapnum\n" "where filename is a C++ source file\n" "and chapnum is the chapter name it's in.\n" "Finds lines commented with //! and removes\n" "the comment, appending //(#) where # is unique\n" "across all files, so you can determine\n" "if your compiler finds the error.\n" "showerr /r\n" "resets the unique counter."; class Showerr { const int CHAP; const string MARKER, FNAME; // File containing error number counter: const string ERRNUM; // File containing error lines: const string ERRFILE; stringstream edited; // Edited file int counter; public: Showerr(const string& f, const string& en, const string& ef, int c) : CHAP(c), MARKER("//!"), FNAME(f), ERRNUM(en), ERRFILE(ef), counter(0) {} void replaceErrors() { ifstream infile(FNAME.c_str()); assure(infile, FNAME.c_str()); ifstream count(ERRNUM.c_str()); if(count) count >> counter; int linecount = 1; string buf; ofstream errlines(ERRFILE.c_str(), ios::app); assure(errlines, ERRFILE.c_str()); while(getline(infile, buf)) { // Find marker at start of line: size_t pos = buf.find(MARKER); if(pos != string::npos) { // Erase marker: buf.erase(pos, MARKER.size() + 1); // Append counter & error info: ostringstream out; out << buf << " // (" << ++counter << ") " << "Chapter " << CHAP << " File: " << FNAME << " Line " << linecount << endl; edited << out.str(); errlines << out.str(); // Append error file } else edited << buf << "\n"; // Just copy ++linecount; } } void saveFiles() { ofstream outfile(FNAME.c_str()); // Overwrites assure(outfile, FNAME.c_str()); outfile << edited.rdbuf(); ofstream count(ERRNUM.c_str()); // Overwrites assure(count, ERRNUM.c_str()); count << counter; // Save new counter } }; int main(int argc, char* argv[]) { const string ERRCOUNT("../errnum.txt"), ERRFILE("../errlines.txt"); requireMinArgs(argc, 1, USAGE.c_str()); if(argv[1][0] == '/' || argv[1][0] == '-') { // Allow for other switches: switch(argv[1][1]) { case 'r': case 'R': cout << "reset counter" << endl; remove(ERRCOUNT.c_str()); // Delete files remove(ERRFILE.c_str()); return EXIT_SUCCESS; default: cerr << USAGE << endl; return EXIT_FAILURE; } } if(argc == 3) { Showerr s(argv[1], ERRCOUNT, ERRFILE, atoi(argv[2])); s.replaceErrors(); s.saveFiles(); } } ///:~