Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

G:/NewGrep/NewGrep.cpp

Go to the documentation of this file.
00001 static char Module[] = "$Header: /TDS Product Cycle/0 Development/Software/MiscTools/NewGrep/NewGrep.cpp 2     00-10-31 14:48 Vwagner $";
00002 // NewGrep.cpp : Defines the entry point for the console application.
00003 //
00004 /************************************************************************/
00005 /*                                                                      */
00006 /*                          G R E P                                     */
00007 /*                                                                      */
00008 /************************************************************************/
00009 /*                                                                      */
00010 /*                                                                      */
00011 /* Usage:                                                               */
00012 /*    grep [>output] [options] pattern file1 [file2...filen]            */
00013 /*                                                                      */
00014 /* options:                                                             */
00015 /*    -a   print adjoining lines.                                       */
00016 /*    -c   print only a count of matching lines.                        */
00017 /*    -f   don't print file names.                                      */
00018 /*    -lxxxx  only search the first xxxx lines of a file.               */
00019 /*    -n   print line number of matching lines.                         */
00020 /*    -q   quit searching the current after the first match.            */
00021 /*    -tnn tree walk from the given node (nn = depth, 99 if no nn).     */
00022 /*    -v   print non matching lines only.                               */
00023 /*                                                                      */
00024 /* pattern:                                                             */
00025 /*   ?  = matches any single character except newline                   */
00026 /*   #  = zero or more occurrances of following character               */
00027 /*   %  = Matches the null string                                       */
00028 /*   'a = any alphabetic character                                      */
00029 /*   'd = any digit                                                     */
00030 /*   'n = any alphanumeric                                              */
00031 /*   's = any white space character                                     */
00032 /*   '  = escape (match following metacharacter literally, \'$ = $)     */
00033 /*   `  = or (a`b) = a or b                                             */
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);                        //!< holds the pattern
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;                          /* adjoining lines                 */
00096 int cflag = 0;                          /* print count only option flag    */
00097 int dflag = 0;                          /* debug flag                      */
00098 int fflag = 1;                          /* no file names option flag       */
00099 int kflag = 0;                          /* quiet mode, minimum output      */
00100 int lflag = 0;                          /* line number limit option flag   */
00101 int nflag = 0;                          /* line number option flag         */
00102 int qflag = 0;                          /* quit on first match option flag */
00103 int tflag = 0;                          /* tree walk depth option flag     */
00104 int vflag = 0;                          /* print non-matching option flag  */
00105 int zflag = 0;                          /* inhibit the logging on message  */
00106 int files;                              /* number of input 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 /*      GetIntegerParameter (char **ParameterString)                      */
00179 /*                                                                        */
00180 /*        char **ParameterString // input string                          */
00181 /*                                                                        */
00182 /*   This function returns the integer value of a numeric (sub)string     */
00183 /*   and updates the pointer to the first non nummeric character.         */
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 /*      GetStringParameter (char **ParameterString)                       */
00204 /*                                                                        */
00205 /*        char **ParameterString // input string                          */
00206 /*                                                                        */
00207 /*   This function returns the integer value of a numeric (sub)string     */
00208 /*   and updates the pointer to the first non nummeric character.         */
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';   // take out the trailing $ and ' '
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':   // adjoining lines
00324             opt = AdjoiningLinesOptionProcessing (opt);
00325             break;
00326           case 'c':   // match count
00327             ++cflag;
00328             break;
00329           case 'd':   // debug
00330             ++dflag;
00331             break;
00332           case 'f':   // no file name
00333             fflag = 0;
00334             break;
00335           case 'k':   // quiet mode
00336             ++kflag;
00337             break;
00338           case 'l':   // lines per file to search
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':   // line numbers
00352             ++nflag;
00353             break;
00354           case 'q':   // quit on match
00355             ++qflag;
00356             break;
00357           case 't':   // tree walk
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':   // print non-matching lines
00371             ++vflag;
00372             break;
00373           case 'z':     // inhibit logon
00374             ++zflag;
00375             break;
00376           default:
00377             log_on ("Grep", &myrev [11], CopyrightDates);
00378             cout << "Unknown Switch\n" << *opt;
00379             return 3;
00380           }  /* end of switch */
00381         opt++;
00382         }  /* end of while (*opt != '\0')  */
00383       argv[i] = 0;
00384       files--;
00385     }  /* end of if (*opt == '-')  */
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   }  /* end of for (i = 1; i < argc; i++)  */
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 }

Generated at Wed Dec 6 21:25:04 2000 for NewGrep by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000