#!/usr/bin/perl -w use Data::Dumper; use File::Find; use Getopt::Std; use IO::File; use strict; my ($EXCLUDE, $HELP, $QUIET, $TEST); my $usage = <] [...] -e : Exclude paths matching case-insensitive. e.g. "(.gif|.jpg)$" -h: Display help message and exit -q: Quiet mode, do not report normal processing of files -t: Do not actually change files, just report what changes would be made EOF my $helpmsg = <comp, \$m->file, etc.) See Commands.pod for all the conversions to be performed. 2. References to request variable \$REQ are converted to \$m. All directories will be traversed recursively. We STRONGLY recommend that you backup your components, and/or use the -t flag to preview, before running this program for real. Files are modified destructively and no automatic backups are created. EOF my $warning = <) !~ /[Yy]/); } my $sub = sub { if (-f $_ && -s _) { return if defined($EXCLUDE) && "$File::Find::dir/$_" =~ /$EXCLUDE/i; convert($_,"$File::Find::dir/$_"); } }; find($sub,@dirs); } sub convert { my ($file,$path) = @_; my $buf; my $infh = new IO::File $file; if (!$infh) { warn "cannot read $path: $!"; return } { local $/ = undef; $buf = <$infh> } my $c = 0; my (@changes,@failures); my $report = sub { push(@changes,$_[1] ? "$_[0] --> $_[1]" : "removed $_[0]") }; my $report_failure = sub { push(@failures,$_[0]) }; # # Convert mc_ commands to $m-> method equivalents # # Easy substitutions # my $easy_cmds = join("|",qw(abort cache cache_self call_self comp comp_exists dhandler_arg file file_root out time)); if (!$TEST) { $c += ($buf =~ s{mc_($easy_cmds)(?![A-Za-z0-9 _])}{"\$m->$1"}geo); } else { while ($buf =~ m{(mc_($easy_cmds)(?![A-Za-z0-9 _]))}go) { $report->($1,"\$m->$2"); } } # Boilerplate substitutions for methods with no arguments my @subs = (['mc_auto_comp', '$m->fetch_next->path'], ['mc_caller', '$m->callers(1)->path'], ['mc_comp_source', '$m->current_comp->source_file'], ['mc_comp_stack', 'map($_->title,$m->callers)'], ); foreach my $sub (@subs) { my ($mc_cmd,$repl) = @$sub; if (!$TEST) { $c += ($buf =~ s{$mc_cmd(\s*\(\))?(?!\s*[\(])}{$repl}ge); } else { while ($buf =~ m{($mc_cmd(\s*\(\))?(?!\s*[\(]))}g) { $report->($1,$repl); } } } # Boilerplate substitutions for methods with arguments @subs = (['mc_auto_next', '$m->call_next'], ); foreach my $sub (@subs) { my ($mc_cmd,$repl) = @$sub; if (!$TEST) { $c += ($buf =~ s{$mc_cmd}{$repl}ge); } else { while ($buf =~ m{($mc_cmd)}g) { $report->($1,$repl); } } } # mc_comp_source with simple argument if (!$TEST) { $c += ($buf =~ s{mc_comp_source\s*\(([^\(\)]+)\)}{"\$m->fetch_comp($1)->source_file"}ge); } else { while ($buf =~ m{(mc_comp_source\s*\(([^\(\)]+)\))}g) { $report->($1,"\$m->fetch_comp($2)->source_file"); } } # mc_suppress_http_header with and without arguments if (!$TEST) { $c += ($buf =~ s{mc_suppress_http_header\s*(?!\s*\();?}{}g); $c += ($buf =~ s{mc_suppress_http_header\s*\([^\(\)]*\)\s*;?}{}g); } else { while ($buf =~ m{(mc_suppress_http_header\s*(?!\s*\();?)}g) { $report->($1,""); } while ($buf =~ m{(mc_suppress_http_header\s*\([^\(\)]*\)\s*;?)}g) { $report->($1,""); } } # # Convert $REQ to $m # if (!$TEST) { $c += ($buf =~ s{\$REQ(?![A-Za-z0-9_])}{\$m}go); } else { while ($buf =~ m{(\$REQ(?![A-Za-z0-9_]))}go) { $report->($1,"\$m"); } } # Report substitutions we can't handle foreach my $cmd (qw(mc_comp_source mc_suppress_http_header)) { if ($buf =~ m{$cmd\s*\([^\)]*\(}) { $report_failure->("Can't convert $cmd with complex arguments"); } } if ($buf =~ m{mc_date}) { $report_failure->("Can't convert mc_date"); } if ($TEST) { if (@changes) { print scalar(@changes)." substitutions in $path:\n"; print join("\n",@changes)."\n"; } } if ($c && !$TEST) { print "$c substitutions in $path\n" if !$QUIET; my $outfh = new IO::File ">$file"; if (!$outfh) { warn "cannot write $path: $!"; return } $outfh->print($buf); } foreach my $failure (@failures) { print "** Warning: $failure; must fix manually\n"; } print "\n" if (($TEST && @changes) || @failures); } main();