#!/usr/bin/perl -Tw
#
# phpglobals.pl
#
# detect and fix unused globals in a php file
# assumes consistently indented code!

my $fn='', $indent='', %globals=(),  %linenos=(), $re='', $lineno=0;
my $lastPrintedLine=0;
my @lines;

use Getopt::Std;

sub usage() {
  print STDERR << "EOF";

Usage: $0 [-r] [-f] < file.php
Find and optionally fix unused global variables in PHP code read 
from standard input.

 -r\tgenerate a report of unused globals (default)
 -f\tattempt to fix unused globals

EOF
  exit;
}

my %opt;
getopts( "frh", \%opt ) or usage();
usage() if $opt{h};

my $mode='report';
if ($opt{f}) {
  $mode='fix';
}

while(<>) {
  push @lines, $_;

  # attempt to normalize leading whitespace
  s/^(\s*) {8}/$1\t/g;

  if ($fn eq '') {
    # look for a function
    if (!/^(\s*)function\s+(\w*)/) {
      next;
    }
    ($indent, $fn, $lineno) = ( $1, $2, $. );
    %globals=%linenos=();
  } elsif ( /^$indent}/ ) {
    # end of function
    foreach my $g ( keys %globals ) {
      if ( $globals{$g} == 0 ) {
	if ( $mode eq 'report' ) {
	  print "$linenos{$g}: $fn \$$g\n";
	} elsif ( $mode eq 'fix' ) {
	  my $l = $lines[$linenos{$g} - $lastPrintedLine - 1];
	  $l =~ s!(,?\s*)\$$g!!;
	  $l =~ s!^(\s*global),!$1!;
	  if ($l =~ /^[^\$]*$/) { $l=''; }
	  $lines[$linenos{$g} - $lastPrintedLine - 1] = $l;
	}
      }
    }
    $fn='';
    if ( $mode eq 'fix' ) {
      print @lines;
      $lastPrintedLine=$.;
    }
    @lines=();
  }

  if (s/^\s*global\b//) {
    foreach my $g (split /\b[,;\s]*/) {
      if ($g =~ /^\w+$/) {
	$globals{$g}=0;
	$linenos{$g}=$.;
      }
    }
    $re = join '|', keys %globals;
  } elsif ($re ne '') {
    while ( /\$($re)\b/g ) {
      #print "$.: $1\n";
      $globals{$1}++;
    }
  }
}
if ($mode eq 'fix') { print  @lines; }
