#!Perl
# macperl_grep.pl     1998-04-10 Sean M. Burke (sburke@netadventure.net)
#
# Search given MacPerl files for lines matching a given regexp.
#
# A "MacPerl file" is very loosely defined as anything that
#  is a TEXT file, or is owned by (AKA was created by) MacPerl.
#
# Drop files or folders on this script (which you should resave as
#  a droplet).
#
# If you drop any folders on this script, their contents
#  will be recursed and only filenames matching a (second) given
#  regexp (if they are also TEXTs or created by MacPerl) will be
#  searched.
#
#! This is different from, say, the Multi-File Search in BBEdit in
#!  that this will search text resource #128 (where droplets et al.
#!  keep their source) in addition to data forks.
#
# I'm not calling this a general grepper for the Mac, because for
#  that I'd want to grep other kinds of resources besides just
#  TEXT resources (much less just TEXT #128)

use Mac::Memory;
use Mac::Resources;
use File::Find;

$debug = 0; # 0 = normal output, 1 = verbose, 2 = really verbose

#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

exit unless @ARGV;

@files = ();
@directories = ();
foreach(@ARGV) {
  if(-f $_) { push(@files, $_) } else { push(@directories, $_) } 
}

$regexp = MacPerl::Ask('Regexp to search for in file content', '');
exit if $regexp eq '';

if(@directories) {
  $filename_regexp = MacPerl::Ask(
   'Regexp to match filenames against', '.');
  exit if $filename_regexp eq '';
}

print "Starting to search for /$regexp/...\n";

# first, search specified files
foreach(@files) { &grep_perl($_) }

# recurse directories
find(sub {
        unless($_ ne "Icon\cm"
               and ! /\.(txt|s?html?)$/si # TEXTs that are non-Perly
               and /$filename_regexp/oi
               and -f $File::Find::name) {
          print "Not looking at $File::Find::name\n" if $debug > 1;
          return;
        } # otherwise...
        &grep_perl($File::Find::name);
     } ,
     @directories) if @directories;
print "Done.\n\n";
exit;

#--------------------------------------------------------------------------

sub grep_perl {
  my $SPEC = $_[0];
  my $handle_128 = undef;

  print "Looking at $SPEC\n" if $debug;
  my($creator, $type) = MacPerl::GetFileInfo($SPEC);

  unless( $creator eq 'MrPL' or $creator eq 'McPL' or
   $type eq 'TEXT') {
    print "  bad owner/creator; skipping.\n" if $debug;
    return;
  }

  my $refnum = FSpOpenResFile($SPEC, 1);
 Reslook:
  if(defined($refnum)) {
    $handle_128 = Get1Resource('TEXT', 128);# Look for a TEXT #128
    if( $handle_128 ) {
      my @lines = split("\cm", $handle_128->get);
      CloseResFile $refnum;

      print scalar(@lines), " lines in $SPEC TEXT #128\n" if $debug;

      for (my $line_number = 0; $line_number < @lines; $line_number++) {
        next unless $lines[$line_number] =~ /$regexp/oi;
        chomp($lines[$line_number]); # may or may not be necessary
        print "$SPEC\xC5", 1 + $line_number, "\xC5$lines[$line_number]\n";
      }  # \xC5 = the MacAscii swoosh-equals
      return; # don't look in the data fork
    } else { # resource, but no TEXT #128
      print "  no text #128...\n" if $debug;
      CloseResFile $refnum;
    }
  }

  return unless -s $SPEC;

  # if we get this far, look in the data fork
  print "  looking at $SPEC\'s data fork...\n" if $debug;
  if(open(IN, "$SPEC")) {
    local($_);

    # If you want to add heuristics to isolate just Perl scripts
    #  and not other text files, do so here, then seek() back
    #  to the start of the file.
    # Also maybe do newline conversion (by setting $/) if you're
    #  net sure all your Perl files are in Mac newline (CR) format
    while(<IN>){
      next unless /$regexp/oi;
      chomp($_);
      print "$_[0]\xC5$.\xC5$_\n";
    }  # \xC5 = the MacAscii swoosh-equals
  }
  close(IN);
  print "  moving on...\n" if $debug;

}

__END__
