00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00016 #include <stdio.h>
00017 #include "findtext.hpp"
00018 #include "stringbuf.hpp"
00019
00020 using namespace std;
00021
00025 class Finder : public Subscriber<FoundMsg>, public Subscriber<ErrorMsg> {
00029 virtual bool regularMsg(const Publisher<FoundMsg>& pub,
00030 const FoundMsg& msg);
00031
00035 virtual bool regularMsg(const Publisher<ErrorMsg>& pub,
00036 const ErrorMsg& msg);
00037 };
00038
00039 bool Finder::regularMsg(const Publisher<FoundMsg>&, const FoundMsg& msg)
00040 {
00041 printf("%s:%d:%s\n", msg.fileName.c_str(), msg.lineNum, msg.lineText.c_str());
00042 return 1;
00043 }
00044
00045 bool Finder::regularMsg(const Publisher<ErrorMsg>&, const ErrorMsg& msg)
00046 {
00047 fprintf(stderr, "%s\n", msg.errMsg.c_str());
00048 return 1;
00049 }
00050
00055 class Logger : public Subscriber<FoundMsg>, public Subscriber<ErrorMsg>,
00056 public Subscriber<InfoMsg> {
00058 FILE* log;
00059
00063 virtual bool regularMsg(const Publisher<FoundMsg>& pub,
00064 const FoundMsg& msg);
00065
00069 virtual bool regularMsg(const Publisher<ErrorMsg>& pub,
00070 const ErrorMsg& msg);
00071
00075 virtual bool regularMsg(const Publisher<InfoMsg>& pub,
00076 const InfoMsg& msg);
00077
00078 public:
00080 int filesOpened;
00082 int filesClosed;
00084 int linesFound;
00086 int errorsEncountered;
00087
00091 Logger(const string& fname);
00092
00096 ~Logger();
00097 };
00098
00099 Logger::Logger(const string& fname)
00100 {
00101 log=fopen(fname.c_str(), "a");
00102 if (!log) {
00103 throw newCException(_FLINE_, StringBuf("Can't open \"")+fname+
00104 "\" file for logging");
00105 }
00106
00107 filesOpened=filesClosed=linesFound=errorsEncountered=0;
00108 }
00109
00110 Logger::~Logger()
00111 {
00112 fputc('\n', log);
00113 #define PR(var) fprintf(log, #var ": %d\n", var)
00114 PR(filesOpened);
00115 PR(filesClosed);
00116 PR(linesFound);
00117 PR(errorsEncountered);
00118 #undef PR
00119 fputc('\n', log);
00120
00121 fclose(log);
00122 }
00123
00124 bool Logger::regularMsg(const Publisher<FoundMsg>& pub, const FoundMsg& msg)
00125 {
00126 linesFound++;
00127 fprintf(log, "FoundMsg: Publisher(%p) FindText(%p) fileName(%s) lineNum(%d) "
00128 "lineText(%s)\n", &pub, &msg.ft, msg.fileName.c_str(), msg.lineNum,
00129 msg.lineText.c_str());
00130
00131 return 1;
00132 }
00133
00134 bool Logger::regularMsg(const Publisher<ErrorMsg>& pub, const ErrorMsg& msg)
00135 {
00136 errorsEncountered++;
00137 fprintf(log, "ErrorMsg: Publisher(%p) FindText(%p) errMsg(%s)\n", &pub,
00138 &msg.ft, msg.errMsg.c_str());
00139
00140 return 1;
00141 }
00142
00143 bool Logger::regularMsg(const Publisher<InfoMsg>& pub, const InfoMsg& msg)
00144 {
00145 if (msg.type==InfoMsg::opened) filesOpened++;
00146 else filesClosed++;
00147
00148 fprintf(log, "InfoMsg : Publisher(%p) FindText(%p) type(%s) fileName(%s)\n",
00149 &pub, &msg.ft, (msg.type==InfoMsg::opened) ? "opened" : "closed",
00150 msg.fileName.c_str());
00151
00152 return 1;
00153 }
00154
00158 struct CmdLineParser {
00160 bool isL;
00162 string logName;
00164 bool isR;
00166 string dirName;
00168 string mask;
00170 string text;
00171
00175 CmdLineParser() : isL(0), isR(0) {}
00176
00183 bool parse(int argc, char** argv);
00184 };
00185
00186 bool CmdLineParser::parse(int argc, char** argv)
00187 {
00188 if (argc<4 || argc>7) return 0;
00189
00190 int curr=1;
00191 while (argv[curr][0]=='-') {
00192 string opt(argv[curr]);
00193
00194 if (opt=="-l") {
00195 if (isL) return 0;
00196
00197 isL=1;
00198 curr++;
00199
00200 logName=argv[curr++];
00201 }
00202 else if (opt=="-r") {
00203 if (isR) return 0;
00204
00205 isR=1;
00206 curr++;
00207 }
00208 else return 0;
00209 }
00210
00211 if (curr+3!=argc) return 0;
00212
00213 dirName=argv[curr++];
00214 mask=argv[curr++];
00215 text=argv[curr++];
00216
00217 return 1;
00218 }
00219
00223 void printUsage()
00224 {
00225 fprintf(stderr,
00226 "Usage:\n"
00227 " ftext [-l logname] [-r] dirname mask text\n"
00228 "For example:\n"
00229 " ftext -l ftext.log -r . *pp return\n"
00230 );
00231 }
00232
00233 int main(int argc, char** argv)
00234 {
00235 try {
00236 CmdLineParser clp;
00237 if (!clp.parse(argc, argv)) {
00238
00239
00240
00241
00242
00243 printf("Invalid command line:\n");
00244 for (int i=0; i<argc; i++)
00245 printf("%s%s", argv[i], (i!=argc-1)? " " : "\n\n");
00246
00247 printUsage();
00248 return 1;
00249 }
00250
00251 sh_ptr<FindText> ft=Factory::newFindText();
00252
00253 Finder f;
00254 ft->foundPub().subscribe(f);
00255 ft->errorPub().subscribe(f);
00256
00257 sh_ptr<Logger> l;
00258 if (clp.isL) {
00259 l.set(new Logger(clp.logName));
00260
00261 ft->foundPub().subscribe(*l);
00262 ft->errorPub().subscribe(*l);
00263 ft->infoPub().subscribe(*l);
00264 }
00265
00266 ft->search(clp.dirName, clp.isR, clp.mask, clp.text);
00267
00268 return 0;
00269 }
00270 catch (...) {
00271 fprintf(stderr, "Uncaught exception:\n%s",
00272 toCException(_FLINE_)->toStringAll().c_str());
00273 return 2;
00274 }
00275 }