00001 static char Module[] = "$Header: /TDS Product Cycle/0 Development/Software/MiscTools/NewGrep/NewGrep.cpp 2 00-10-31 14:48 Vwagner $";
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "stdafx.h"
00038 #include "pattern.hpp"
00039 #include <io.h>
00040 using namespace std;
00041
00042 void log_on(char *name, char *version, char *dates)
00043 {
00044 clog << name << " - Version " << version
00045 << "\nCopyright (C) 1986,7, 1991,3,6-9 Victor A. Wagner, Jr. and Kenneth T. Spoor All Rights Reserved\n"
00046 << "Copyright (C) " << dates <<" Victor A. Wagner Jr. All Rights Reserved\n";
00047 }
00048 typedef struct
00049 {
00050 long handle;
00051 struct _finddata_t data;
00052 } FileData;
00053
00054 int find_files (string OriginalPattern,
00055 void ( *dest_process ) ( char *FoundFileName,
00056 char *path,
00057 FileData *FileInfo ),
00058 int how_deep )
00059 {
00060 return 20;
00061 }
00062
00063 bool Read_a_Line(istream_iterator<char>& Stream, istream_iterator<char>& End_of_Stream, string& towhere)
00064 {
00065 towhere.clear();
00066 char ch;
00067 while (('\n' != (ch = *Stream++)) && (Stream != End_of_Stream))
00068 towhere += ch;
00069 return (Stream != End_of_Stream) || !towhere.empty();
00070 }
00071
00072 void grep (string patt, istream& input, string log_message)
00073 {
00074 Pattern magic(patt);
00075 string Line;
00076 unsigned long Line_Number = 0;
00077
00078 input.unsetf(ios::skipws);
00079 istream_iterator<char> End_of_Stream;
00080 istream_iterator<char> Stream(input);
00081 while(Read_a_Line(Stream, End_of_Stream, Line))
00082 {
00083 ++Line_Number;
00084 if (magic(Line))
00085 cout << Line_Number << '\t' << Line << endl;
00086 }
00087 }
00088
00089 void pre_grep(char* name, char* path, FileData* FileInfo)
00090 {
00091 }
00092
00093 const int MaxLines = 64;
00094
00095 int aflag = 0;
00096 int cflag = 0;
00097 int dflag = 0;
00098 int fflag = 1;
00099 int kflag = 0;
00100 int lflag = 0;
00101 int nflag = 0;
00102 int qflag = 0;
00103 int tflag = 0;
00104 int vflag = 0;
00105 int zflag = 0;
00106 int files;
00107
00108 int TotalFileMatches = 0;
00109
00110 int LeadingLines = 0;
00111 int TrailingLines = 0;
00112 int LastMatchLine = 0;
00113 int MarkLineCount = 0;
00114
00115 string pattern;
00116
00117 void help(void)
00118 {
00119 cout << "\nUsage:\n";
00120 cout << " grep [options] pattern file1 [file2...filen] [>output]\n";
00121 cout << "\n";
00122 cout << "options:\n";
00123 cout << " -a[+x-y] +x = # of trailing lines, -y = # of leading lines \n"
00124 " largest combined lines is " << MaxLines << '\n';
00125 cout << " -c print only a count of matching lines.\n";
00126 cout << " -f don't print file names.\n";
00127 cout << " -lxxxx only search the first xxxx lines of a file.\n";
00128 cout << " -n print line number of matching lines.\n";
00129 cout << " -q quit searching the current file after the first match.\n";
00130 cout << " -tnn tree walk from the given node (nn = depth, 99 if no nn).\n";
00131 cout << " -v print non matching lines only.\n";
00132 cout << "\n";
00133 cout << "pattern:\n";
00134 cout << " ^ = matches beginning of line\n";
00135 cout << " ? = matches any single character except newline\n";
00136 cout << " # = zero or more occurrances of follow character\n";
00137 cout << " %% = matches the null string\n";
00138 cout << " \'a = any alphabetic character\n";
00139 cout << " \'d = any digit\n";
00140 cout << " \'n = any alphanumeric\n";
00141 cout << " \'s = any white space character\n";
00142 cout << " \' = escape (match following metacharacter literally, \'? = ?)\n";
00143 cout << " ` or | = or, (a`b) = a or b, (mother|father) = mother or father\n";
00144 cout << "\n";
00145 cout << " note : Using the \"|\" requires the pattern to be in quotes.\n";
00146 cout << " example: grep \"(mother|father)\" #?.txt\n";
00147 }
00148
00149 string StarConvert (char *input)
00150 {
00151 string output;
00152 char PreviousCharacter = '\0';
00153
00154 if (input)
00155 {
00156 while (*input)
00157 {
00158 if ((*input == '*') && (PreviousCharacter != '\''))
00159 {
00160 output += "#?";
00161 }
00162 else
00163 {
00164 output += *input;
00165 }
00166
00167 PreviousCharacter = *input++;
00168 }
00169 }
00170
00171 return (output);
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 int GetIntegerParameter (char **ParameterString)
00188 {
00189 int IntegerValue = 0;
00190
00191 while (isdigit (**ParameterString))
00192 {
00193 IntegerValue = (IntegerValue * 10) + (**ParameterString - '0');
00194 (*ParameterString)++;
00195 }
00196
00197 return (IntegerValue);
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 char *GetStringParameter (char **ParameterString, char *StringParameter)
00213 {
00214 while (isdigit (**ParameterString))
00215 {
00216 *StringParameter++ = **ParameterString;
00217 (*ParameterString)++;
00218 }
00219
00220 return (StringParameter);
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230 char *AdjoiningLinesOptionProcessing (char *opt)
00231 {
00232 bool more = true;
00233
00234 opt++;
00235 aflag = GetIntegerParameter (&opt);
00236 LeadingLines = aflag;
00237 TrailingLines = aflag;
00238
00239 while (more)
00240 {
00241 if (*opt == '-')
00242 {
00243 ++opt;
00244 LeadingLines = GetIntegerParameter (&opt);
00245 }
00246 else if (*opt == '+')
00247 {
00248 ++opt;
00249 TrailingLines = GetIntegerParameter (&opt);
00250 }
00251 else
00252 {
00253 more = false;
00254 }
00255 }
00256
00257 if (dflag)
00258 {
00259 cout << "adjoining lines = " << aflag;
00260 cout << "\nleading lines = " << LeadingLines;
00261 cout << "\ntrailing lines = " << TrailingLines << '\n';
00262 }
00263
00264 if (aflag == 0)
00265 {
00266 aflag = 1;
00267 }
00268
00269 if ((LeadingLines == 0) && (TrailingLines == 0))
00270 {
00271 LeadingLines = TrailingLines = 1;
00272 }
00273
00274 if (aflag > (MaxLines >> 1))
00275 {
00276 aflag = (MaxLines >> 1) - 1;
00277 LeadingLines = aflag;
00278 TrailingLines = aflag;
00279 }
00280
00281 if ((LeadingLines + TrailingLines + 1) >= MaxLines)
00282 {
00283 LeadingLines = (MaxLines - 1) * LeadingLines / (LeadingLines + TrailingLines) ;
00284 TrailingLines = (MaxLines - 1) - LeadingLines;
00285 }
00286
00287 return (--opt);
00288 }
00289
00290 int main(int argc, char* argv[])
00291 {
00292 static char myrev[] = "$Revision: 2 $";
00293 char *opt;
00294 int i;
00295 int j;
00296 int status;
00297 int got_pattern = 0;
00298
00299 string prefix, suffix;
00300
00301 myrev [strlen (myrev) - 1] = '\0';
00302 #define CopyrightDates "2000;"
00303 if (argc < 2)
00304 {
00305 log_on ("Grep", &myrev [11], CopyrightDates);
00306 help();
00307 return 2;
00308 }
00309 files = argc - 1;
00310
00311 for (i = 1; i < argc; ++i)
00312 {
00313 opt = argv[i];
00314
00315 if (*opt == '-')
00316 {
00317 ++opt;
00318
00319 while (*opt != '\0')
00320 {
00321 switch (tolower(*opt))
00322 {
00323 case 'a':
00324 opt = AdjoiningLinesOptionProcessing (opt);
00325 break;
00326 case 'c':
00327 ++cflag;
00328 break;
00329 case 'd':
00330 ++dflag;
00331 break;
00332 case 'f':
00333 fflag = 0;
00334 break;
00335 case 'k':
00336 ++kflag;
00337 break;
00338 case 'l':
00339 while (isdigit (*(++opt)))
00340 {
00341 lflag = (lflag * 10) + (*opt - '0');
00342 }
00343
00344 if (dflag)
00345 {
00346 cout << "line count = " << lflag << '\n';
00347 }
00348
00349 opt--;
00350 break;
00351 case 'n':
00352 ++nflag;
00353 break;
00354 case 'q':
00355 ++qflag;
00356 break;
00357 case 't':
00358 while (isdigit (*(++opt)))
00359 {
00360 tflag = (tflag * 10) + (*opt - '0');
00361 }
00362
00363 if (tflag == 0)
00364 {
00365 tflag = 99;
00366 }
00367
00368 opt--;
00369 break;
00370 case 'v':
00371 ++vflag;
00372 break;
00373 case 'z':
00374 ++zflag;
00375 break;
00376 default:
00377 log_on ("Grep", &myrev [11], CopyrightDates);
00378 cout << "Unknown Switch\n" << *opt;
00379 return 3;
00380 }
00381 opt++;
00382 }
00383 argv[i] = 0;
00384 files--;
00385 }
00386
00387 else
00388 if (got_pattern == 0)
00389 {
00390 pattern = StarConvert(argv[i]);
00391 j = pattern.size();
00392 suffix = "#?";
00393
00394 if (pattern[0] == '^')
00395 {
00396 pattern.erase(0,1);
00397 }
00398 else
00399 {
00400 if ((pattern[0] == '#') && (pattern[1] == '?'))
00401 {
00402 if (j == 2)
00403 suffix.erase();
00404 }
00405 else prefix = "#?";
00406 }
00407
00408 j = pattern.size();
00409 if ((j > 2) && (pattern[j-3] != '\''))
00410 if (pattern[j-2] == '#')
00411 if(pattern[j-1] == '?')
00412 suffix.erase();
00413 if((j > 2) && (pattern[j-1] == '^'))
00414 {
00415 pattern.erase(j-1);
00416 suffix.erase();
00417 }
00418
00419 pattern = prefix + pattern + suffix;
00420
00421 try
00422 {
00423 Pattern test_for_error(pattern);
00424 }
00425 catch (runtime_error& x)
00426 {
00427 log_on ("Grep", &myrev [11], CopyrightDates);
00428 cerr << "error in compiling pattern \"" << x.what() << "\"\nattempting to compile: " << pattern << '\n';
00429 return 4;
00430 }
00431
00432 got_pattern++;
00433 argv[i] = 0;
00434 files--;
00435 }
00436 }
00437
00438 if (!zflag)
00439 {
00440 log_on ("Grep", &myrev [11], CopyrightDates);
00441 }
00442
00443 if (dflag)
00444 {
00445 cout << "\nSearch pattern = " << pattern;
00446 }
00447
00448 if (!got_pattern)
00449 {
00450 log_on ("Grep", &myrev [11], CopyrightDates);
00451 cerr << "no pattern given\n";
00452 return 5;
00453 }
00454
00455 if (files == 0)
00456 {
00457 if (Pattern("#?test#?")("This is a test, isn't it?"))
00458 cout << "Yes, and successful at that!\n";
00459 grep(pattern, cin, "<Standard In>");
00460 clog << "\n";
00461 }
00462 else
00463 {
00464 for (i = 1; i < argc; i++)
00465 {
00466 if (argv[i])
00467 {
00468 string FilePattern = StarConvert(argv [i]);
00469
00470 if (dflag)
00471 {
00472 cout << "File pattern = " << FilePattern << '\n';
00473 }
00474
00475 status = find_files (FilePattern, pre_grep, tflag);
00476 printf ("\n");
00477 }
00478 }
00479 }
00480
00481 return (TotalFileMatches == 0);
00482 }