home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume20 / cgrep2 / part01 / cgrep
Encoding:
Text File  |  1991-07-11  |  5.8 KB  |  230 lines

  1. #!/tools/bin/perl
  2. #
  3. #    Copyright (C) 1991 by Lutz Prechelt, Karlsruhe
  4. #
  5. #    This program is free software; you can redistribute it and/or modify
  6. #    it under the terms of the GNU General Public License as published by
  7. #    the Free Software Foundation; either version 1, or (at your option)
  8. #    any later version.
  9. #    This program is distributed in the hope that it will be useful,
  10. #    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. #    GNU General Public License for more details.
  13. #    If you don't have a copy of the GNU General Public License write to
  14. #    Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  
  16. # Version:     2,  Patchlevel 0
  17. # Author:      Lutz Prechelt (prechelt@ira.uka.de), 23.03.91
  18. # Correction   by Sridhar Vasudevan, 03.07.91
  19. # Last Change: Lutz Prechelt, 04.07.91
  20. #
  21. # Usage: see message at "die" below.
  22.  
  23. #---------- constants:
  24. $infinity         = 10000;
  25.  
  26. #---------- Variables:
  27. $delimiterstring  = "-----------\n";
  28. $matches          = 0;
  29. $precontext       = 2;
  30. $postcontext      = 2;
  31. $wrong_option     = 0;
  32.  
  33. #---------- boolean Options:
  34. $paragraphmode    = 0;
  35. $count_matches    = 0;
  36. $ignorecase       = 0;
  37. $withlinenumber   = 0;
  38. $withfilename     = 0;
  39. $reversemode      = 0;
  40.  
  41. # $endpara = '\S.*\n';
  42.  
  43. #---------- Subroutines:
  44.  
  45. sub match_found {
  46.   #bad style: uses the global variables $ignorecase, $reversemode, $cur, $pat
  47.   if ($ignorecase != 0) {
  48.     ($reversemode == 1 ? $cur !~ /$pat/io : $cur =~ /$pat/io);
  49.   }
  50.   else {
  51.     ($reversemode == 1 ? $cur !~ /$pat/o : $cur =~ /$pat/o);
  52.   }
  53. }
  54.  
  55. sub showline {
  56.   if ($withfilename != 0) {
  57.     printf ("\"%s\"", $ARGV);
  58.   }
  59.   if ($withfilename != 0 && $withlinenumber != 0) {
  60.     print ",";
  61.   }
  62.   if ($withlinenumber != 0) {
  63.     printf ("%4d", $_[1]);
  64.   }
  65.   if ($withfilename != 0 || $withlinenumber != 0) {
  66.     print ": ";
  67.   }
  68.   print ($_[0]);
  69. }
  70.  
  71.  
  72. #---------- Process the Options:
  73. do {
  74.   $something_done = 1;
  75.   if ($ARGV[0] =~ /^-(\d+)$/) {
  76.     $precontext = $postcontext = $1;
  77.     shift;
  78.   }
  79.   elsif ($ARGV[0] =~ /^-(\d+)[\,\+\/\;](\d+)$/) {
  80.     $precontext  = $1;
  81.     $postcontext = $2;
  82.     shift;
  83.   }
  84.   elsif ($ARGV[0] =~ /^-d$/ && $#ARGV > 0) {
  85.     $delimiterstring = $ARGV[1];
  86.     $delimiterstring =~ s/\\n/\n/o;
  87.     shift; shift;
  88.   }
  89.   elsif ($ARGV[0] =~ /^-d(.*)$/) {
  90.     $delimiterstring = $1;
  91.     $delimiterstring =~ s/\\n/\n/o;
  92.     shift;
  93.   }
  94.   elsif ($ARGV[0] =~ /^-c$/) {
  95.     $count_matches = 1;
  96.     shift;
  97.   }
  98.   elsif ($ARGV[0] =~ /^-h$/) {
  99.     $withfilename = 1;
  100.     shift;
  101.   }
  102.   elsif ($ARGV[0] =~ /^-i$/) {
  103.     $ignorecase = 1;
  104.     shift;
  105.   }
  106.   elsif ($ARGV[0] =~ /^-n$/) {
  107.     $withlinenumber = 1;
  108.     shift;
  109.   }
  110.   elsif ($ARGV[0] =~ /^-p$/) {
  111.     $paragraphmode = 1;
  112.     shift;
  113.   }
  114.   elsif ($ARGV[0] =~ /^-v$/) {
  115.     $reversemode = 1;
  116.     shift;
  117.   }
  118.   elsif ($ARGV[0] =~ /^-e$/) { # end options (for expressions starting
  119. with - )
  120.     $something_done = 0;
  121.     shift;
  122.   }
  123.   elsif ($ARGV[0] =~ /^-/) {
  124.     printf ("don't know option '%s'\n", $ARGV[0]);
  125.     $wrong_option = 1;
  126.     $something_done = 0;
  127.     shift;
  128.   }
  129.   else {
  130.     $something_done = 0;
  131.   }
  132. } while ($something_done);
  133.  
  134.  
  135. #---------- Usage message:
  136. if ($#ARGV == -1 || $wrong_option) {
  137.   die "
  138.    Usage: cgrep [-pre[,post]] [-p] [-v] [-c] [-h] [-n] [-d string] 
  139.                 [-e] pattern [file...]
  140.  
  141.    cgrep is a context grep. It displays more than the one matching line for
  142.    every match (2 before and 2 after as default).
  143.  
  144.    -3   means display 3 lines before and 3 lines after the match (e.g.)
  145.    -5,12  means display 5 lines before the match and 12 lines after (e.g.)
  146.    -p   means display only as much of the context as belongs to the
  147.         current paragraph. (paragraphs bounded by empty lines)
  148.    -v   means invert search (display nomatches)
  149.    -c   means display number of matching lines at the end of run
  150.    -h   means toggle display filename before every line
  151.    -i   means ignore case when matching the regexp
  152.    -n   means display line number before every line
  153.    -d string  means use string as the output delimiter string
  154.    -e   means end options (i.e. now comes the pattern, 
  155.                            for patterns starting with - )
  156.    pattern  is a Perl regular expression (you better quote it !)
  157. Exiting";
  158. }
  159.  
  160.  
  161. if (length (@ARGV) > 1) {
  162.   $withfilename = !$withfilename;
  163. }
  164.  
  165.  
  166. #---------- Get the pattern and protect the delimiter.
  167. $pat = shift;
  168. $pat =~ s#/#\\/#g;
  169.  
  170.  
  171. #---------- current line will always be at end of array, i.e.
  172. $ary[$currentpre]
  173. $_ = <>;
  174. push(@ary,$_);
  175. $currentpre = 0;
  176.  
  177. #---------- do the search
  178. # use @ary as a silo, shifting and pushing.
  179. # the length of the @ary at any time is $currentpre + 1
  180. # the current line is @ary[$currentpre], the postcontext is not held in @ary.
  181. $seq = 0;
  182. $lastoutput = $infinity;  #last output is infinitely many lines ago
  183. $cur = @ary[0];       #current line
  184. while ($cur) {  #as long as there is something to look at
  185.   if (&match_found()) {
  186.     $matches++;
  187.     if ($lastoutput <= $postcontext) {
  188.       &showline ($cur, $.);
  189.     }
  190.     else {
  191.       print $delimiterstring if ($seq++ && $precontext + $postcontext > 0);
  192.       $lineno = $. - $#ary;
  193.       foreach $line (@ary) {
  194.         &showline ($line, $lineno++);
  195.       }
  196.     }
  197.     $lastoutput = 0;
  198.   }
  199.   elsif (($cur !~ /\S.*\n/o && $paragraphmode == 1) || eof) {
  200. #paragraph/file end
  201.     for (; $currentpre >= 0; $currentpre--) {
  202.       shift (@ary);
  203.     }
  204.     $lastoutput = $infinity;
  205.     close (ARGV) if (eof);
  206.   }
  207.   elsif ($lastoutput <= $postcontext) {     #another line of postcontext
  208.     &showline ($cur, $.);
  209.   }
  210.   #goto next line of input:
  211.   $lastoutput++;
  212.   $_ = <> if $_;
  213.   push(@ary,$_); 
  214.   if ($currentpre < $precontext) {
  215.     $currentpre++;
  216.   }
  217.   else {
  218.     shift(@ary);
  219.   }
  220.   $cur = $ary[$currentpre];
  221. }
  222.  
  223.  
  224. #---------- perhaps display number of matches:
  225. if ($count_matches != 0) {
  226.   printf ("%d\n", $matches);
  227. }
  228.  
  229.  
  230.