forked from OSchip/llvm-project
251 lines
5.7 KiB
Perl
Executable File
251 lines
5.7 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
|
|
use strict;
|
|
use File::Find;
|
|
use File::Temp qw/ tempfile tempdir /;
|
|
use Getopt::Std;
|
|
use Pod::Usage;
|
|
use Text::Tabs;
|
|
|
|
=head1 NAME
|
|
|
|
B<sed-sources> -- Performs multiple sed commands on files with the ability to expand or unexpand tabs.
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
B<sed-sources> [options] [file dir ...]
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
Performs multiple sed commands (modify builtin %seds hash) on source files
|
|
or any sources in directories. If no arguments are given, STDIN will be used
|
|
as the source. If source files or directories are specified as arguments,
|
|
all files will be transformed and overwritten with new versions. Use the B<-p>
|
|
option to preview changes to STDOUT, or use the B<-b> option to make a backup
|
|
or the original files.
|
|
|
|
=head1 OPTIONS
|
|
|
|
=over
|
|
|
|
=item B<-b>
|
|
|
|
Backup original source file by appending ".bak" before overwriting with the
|
|
newly transformed file.
|
|
|
|
=item B<-g>
|
|
|
|
Display verbose debug logging.
|
|
|
|
=item B<-e>
|
|
|
|
Expand tabs to spaces (in addition to doing sed substitutions).
|
|
|
|
=item B<-u>
|
|
|
|
Unexpand spaces to tabs (in addition to doing sed substitutions).
|
|
|
|
=item B<-p>
|
|
|
|
Preview changes to STDOUT without modifying original source files.
|
|
|
|
=item B<-r>
|
|
|
|
Skip variants when doing multiple files (no _profile or _debug variants).
|
|
|
|
=item B<-t N>
|
|
|
|
Set the number of spaces per tab (default is 4) to use when expanding or
|
|
unexpanding.
|
|
|
|
=back
|
|
|
|
=head1 EXAMPLES
|
|
|
|
# Recursively process all source files in the current working directory
|
|
# and and subdirectories and also expand tabs to spaces. All source files
|
|
# will be overwritten with the newly transformed source files.
|
|
|
|
% sed-sources -e $cwd
|
|
|
|
# Recursively process all source files in the current working directory
|
|
# and and subdirectories and also unexpand spaces to tabs and preview the
|
|
# results to STDOUT
|
|
|
|
% sed-sources -p -u $cwd
|
|
|
|
# Same as above except use 8 spaces per tab.
|
|
|
|
% sed-sources -p -u -t8 $cwd
|
|
|
|
=cut
|
|
|
|
|
|
our $opt_b = 0; # Backup original file?
|
|
our $opt_g = 0; # Verbose debug output?
|
|
our $opt_e = 0; # Expand tabs to spaces?
|
|
our $opt_h = 0; # Show help?
|
|
our $opt_m = 0; # Show help manpage style?
|
|
our $opt_p = 0; # Preview changes to STDOUT?
|
|
our $opt_t = 4; # Number of spaces per tab?
|
|
our $opt_u = 0; # Unexpand spaces to tabs?
|
|
getopts('eghmpt:u');
|
|
|
|
$opt_m and show_manpage();
|
|
$opt_h and help();
|
|
|
|
our %seds = (
|
|
'\s+$' => "\n", # Get rid of spaces at the end of a line
|
|
'^\s+$' => "\n", # Get rid spaces on lines that are all spaces
|
|
);
|
|
|
|
|
|
sub show_manpage { exit pod2usage( verbose => 2 ); };
|
|
sub help { exit pod2usage( verbose => 3, noperldoc => 1 ); };
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
# process_opened_file_handle
|
|
#----------------------------------------------------------------------
|
|
sub process_opened_file_handle
|
|
{
|
|
my $in_fh = shift;
|
|
my $out_fh = shift;
|
|
|
|
# Set the number of spaces per tab for expand/unexpand
|
|
$tabstop = $opt_t;
|
|
|
|
while (my $line = <$in_fh>)
|
|
{
|
|
foreach my $key (keys %seds)
|
|
{
|
|
my $value = $seds{"$key"};
|
|
$line =~ s/$key/$value/g;
|
|
}
|
|
if ($opt_e) {
|
|
print $out_fh expand $line;
|
|
} elsif ($opt_u) {
|
|
print $out_fh unexpand $line;
|
|
} else {
|
|
print $out_fh $line;
|
|
}
|
|
}
|
|
}
|
|
|
|
#----------------------------------------------------------------------
|
|
# process_file
|
|
#----------------------------------------------------------------------
|
|
sub process_file
|
|
{
|
|
my $in_path = shift;
|
|
if (-T $in_path)
|
|
{
|
|
my $out_fh;
|
|
my $out_path;
|
|
if ($opt_p)
|
|
{
|
|
# Preview to STDOUT
|
|
$out_fh = *STDOUT;
|
|
print "#---------------------------------------------------------------------- \n";
|
|
print "# BEGIN: '$in_path'\n";
|
|
print "#---------------------------------------------------------------------- \n";
|
|
}
|
|
else
|
|
{
|
|
($out_fh, $out_path) = tempfile();
|
|
$opt_g and print "temporary for '$in_path' is '$out_path'\n";
|
|
}
|
|
open (IN, "<$in_path") or die "error: can't open '$in_path' for reading: $!";
|
|
process_opened_file_handle (*IN, $out_fh);
|
|
|
|
|
|
# Close our input file
|
|
close (IN);
|
|
|
|
if ($opt_p)
|
|
{
|
|
print "#---------------------------------------------------------------------- \n";
|
|
print "# END: '$in_path'\n";
|
|
print "#---------------------------------------------------------------------- \n";
|
|
print "\n\n";
|
|
}
|
|
else
|
|
{
|
|
# Close the output file if it wasn't STDOUT
|
|
close ($out_fh);
|
|
|
|
# Backup file if requested
|
|
if ($opt_b)
|
|
{
|
|
my $backup_command = "cp '$in_path' '$in_path.bak'";
|
|
$opt_g and print "\% $backup_command\n";
|
|
system ($backup_command);
|
|
}
|
|
|
|
# Copy temp file over original
|
|
my $copy_command = "cp '$out_path' '$in_path'";
|
|
$opt_g and print "\% $copy_command\n";
|
|
system ($copy_command);
|
|
}
|
|
}
|
|
}
|
|
|
|
our @valid_extensions = ( "h", "cpp", "c", "m", "mm" );
|
|
|
|
#----------------------------------------------------------------------
|
|
# find_callback
|
|
#----------------------------------------------------------------------
|
|
sub find_callback
|
|
{
|
|
my $file = $_;
|
|
my $fullpath = $File::Find::name;
|
|
|
|
foreach my $ext (@valid_extensions)
|
|
{
|
|
my $ext_regex = "\\.$ext\$";
|
|
if ($fullpath =~ /$ext_regex/i)
|
|
{
|
|
print "processing: '$fullpath'\n";
|
|
process_file ($fullpath);
|
|
return;
|
|
}
|
|
}
|
|
print " ignoring: '$fullpath'\n";
|
|
}
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
# main
|
|
#----------------------------------------------------------------------
|
|
sub main
|
|
{
|
|
if (@ARGV == 0)
|
|
{
|
|
# no args, take from STDIN and put to STDOUT
|
|
process_opened_file_handle (*STDIN, *STDOUT);
|
|
}
|
|
else
|
|
{
|
|
# Got args, any files we run into parse them, any directories
|
|
# we run into, search them for files
|
|
my $path;
|
|
foreach $path (@ARGV)
|
|
{
|
|
if (-f $path)
|
|
{
|
|
print "processing: '$path'\n";
|
|
process_file ($path);
|
|
}
|
|
else
|
|
{
|
|
print " searching: '$path'\n";
|
|
find(\&find_callback, $path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
# call the main function
|
|
main(); |