diff options
Diffstat (limited to 'scripts/sed-sources')
-rwxr-xr-x | scripts/sed-sources | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/scripts/sed-sources b/scripts/sed-sources new file mode 100755 index 000000000000..c67fb3319adb --- /dev/null +++ b/scripts/sed-sources @@ -0,0 +1,251 @@ +#!/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 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 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(); |