aboutsummaryrefslogtreecommitdiff
path: root/scripts/sed-sources
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/sed-sources')
-rwxr-xr-xscripts/sed-sources251
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();