home *** CD-ROM | disk | FTP | other *** search
- #!/tools/bin/perl
- #
- # Copyright (C) 1991 by Lutz Prechelt, Karlsruhe
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 1, or (at your option)
- # any later version.
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- # If you don't have a copy of the GNU General Public License write to
- # Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- # Version: 2, Patchlevel 0
- # Author: Lutz Prechelt (prechelt@ira.uka.de), 23.03.91
- # Correction by Sridhar Vasudevan, 03.07.91
- # Last Change: Lutz Prechelt, 04.07.91
- #
- # Usage: see message at "die" below.
-
- #---------- constants:
- $infinity = 10000;
-
- #---------- Variables:
- $delimiterstring = "-----------\n";
- $matches = 0;
- $precontext = 2;
- $postcontext = 2;
- $wrong_option = 0;
-
- #---------- boolean Options:
- $paragraphmode = 0;
- $count_matches = 0;
- $ignorecase = 0;
- $withlinenumber = 0;
- $withfilename = 0;
- $reversemode = 0;
-
- # $endpara = '\S.*\n';
-
- #---------- Subroutines:
-
- sub match_found {
- #bad style: uses the global variables $ignorecase, $reversemode, $cur, $pat
- if ($ignorecase != 0) {
- ($reversemode == 1 ? $cur !~ /$pat/io : $cur =~ /$pat/io);
- }
- else {
- ($reversemode == 1 ? $cur !~ /$pat/o : $cur =~ /$pat/o);
- }
- }
-
- sub showline {
- if ($withfilename != 0) {
- printf ("\"%s\"", $ARGV);
- }
- if ($withfilename != 0 && $withlinenumber != 0) {
- print ",";
- }
- if ($withlinenumber != 0) {
- printf ("%4d", $_[1]);
- }
- if ($withfilename != 0 || $withlinenumber != 0) {
- print ": ";
- }
- print ($_[0]);
- }
-
-
- #---------- Process the Options:
- do {
- $something_done = 1;
- if ($ARGV[0] =~ /^-(\d+)$/) {
- $precontext = $postcontext = $1;
- shift;
- }
- elsif ($ARGV[0] =~ /^-(\d+)[\,\+\/\;](\d+)$/) {
- $precontext = $1;
- $postcontext = $2;
- shift;
- }
- elsif ($ARGV[0] =~ /^-d$/ && $#ARGV > 0) {
- $delimiterstring = $ARGV[1];
- $delimiterstring =~ s/\\n/\n/o;
- shift; shift;
- }
- elsif ($ARGV[0] =~ /^-d(.*)$/) {
- $delimiterstring = $1;
- $delimiterstring =~ s/\\n/\n/o;
- shift;
- }
- elsif ($ARGV[0] =~ /^-c$/) {
- $count_matches = 1;
- shift;
- }
- elsif ($ARGV[0] =~ /^-h$/) {
- $withfilename = 1;
- shift;
- }
- elsif ($ARGV[0] =~ /^-i$/) {
- $ignorecase = 1;
- shift;
- }
- elsif ($ARGV[0] =~ /^-n$/) {
- $withlinenumber = 1;
- shift;
- }
- elsif ($ARGV[0] =~ /^-p$/) {
- $paragraphmode = 1;
- shift;
- }
- elsif ($ARGV[0] =~ /^-v$/) {
- $reversemode = 1;
- shift;
- }
- elsif ($ARGV[0] =~ /^-e$/) { # end options (for expressions starting
- with - )
- $something_done = 0;
- shift;
- }
- elsif ($ARGV[0] =~ /^-/) {
- printf ("don't know option '%s'\n", $ARGV[0]);
- $wrong_option = 1;
- $something_done = 0;
- shift;
- }
- else {
- $something_done = 0;
- }
- } while ($something_done);
-
-
- #---------- Usage message:
- if ($#ARGV == -1 || $wrong_option) {
- die "
- Usage: cgrep [-pre[,post]] [-p] [-v] [-c] [-h] [-n] [-d string]
- [-e] pattern [file...]
-
- cgrep is a context grep. It displays more than the one matching line for
- every match (2 before and 2 after as default).
-
- -3 means display 3 lines before and 3 lines after the match (e.g.)
- -5,12 means display 5 lines before the match and 12 lines after (e.g.)
- -p means display only as much of the context as belongs to the
- current paragraph. (paragraphs bounded by empty lines)
- -v means invert search (display nomatches)
- -c means display number of matching lines at the end of run
- -h means toggle display filename before every line
- -i means ignore case when matching the regexp
- -n means display line number before every line
- -d string means use string as the output delimiter string
- -e means end options (i.e. now comes the pattern,
- for patterns starting with - )
- pattern is a Perl regular expression (you better quote it !)
- Exiting";
- }
-
-
- if (length (@ARGV) > 1) {
- $withfilename = !$withfilename;
- }
-
-
- #---------- Get the pattern and protect the delimiter.
- $pat = shift;
- $pat =~ s#/#\\/#g;
-
-
- #---------- current line will always be at end of array, i.e.
- $ary[$currentpre]
- $_ = <>;
- push(@ary,$_);
- $currentpre = 0;
-
- #---------- do the search
- # use @ary as a silo, shifting and pushing.
- # the length of the @ary at any time is $currentpre + 1
- # the current line is @ary[$currentpre], the postcontext is not held in @ary.
- $seq = 0;
- $lastoutput = $infinity; #last output is infinitely many lines ago
- $cur = @ary[0]; #current line
- while ($cur) { #as long as there is something to look at
- if (&match_found()) {
- $matches++;
- if ($lastoutput <= $postcontext) {
- &showline ($cur, $.);
- }
- else {
- print $delimiterstring if ($seq++ && $precontext + $postcontext > 0);
- $lineno = $. - $#ary;
- foreach $line (@ary) {
- &showline ($line, $lineno++);
- }
- }
- $lastoutput = 0;
- }
- elsif (($cur !~ /\S.*\n/o && $paragraphmode == 1) || eof) {
- #paragraph/file end
- for (; $currentpre >= 0; $currentpre--) {
- shift (@ary);
- }
- $lastoutput = $infinity;
- close (ARGV) if (eof);
- }
- elsif ($lastoutput <= $postcontext) { #another line of postcontext
- &showline ($cur, $.);
- }
- #goto next line of input:
- $lastoutput++;
- $_ = <> if $_;
- push(@ary,$_);
- if ($currentpre < $precontext) {
- $currentpre++;
- }
- else {
- shift(@ary);
- }
- $cur = $ary[$currentpre];
- }
-
-
- #---------- perhaps display number of matches:
- if ($count_matches != 0) {
- printf ("%d\n", $matches);
- }
-
-
-