linux-yocto/scripts/cleanfile
H. Peter Anvin 12b315603a cleanfile: a script to clean up stealth whitespace
This script cleans up various classes of stealth whitespace.  In
particular, it cleans up:

- Whitespace (spaces or tabs)before newline;
- DOS line endings (CR before LF);
- Space before tab (spaces are deleted or converted to tabs);
- Empty lines at end of file.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
2007-05-02 20:58:08 +02:00

2.5 KiB
Executable File

#!/usr/bin/perl -w

Clean a text file -- or directory of text files -- of stealth whitespace.

WARNING: this can be a highly destructive operation. Use with caution.

use bytes; use File::Basename;

Clean up space-tab sequences, either by removing spaces or

replacing them with tabs.

sub clean_space_tabs($) { no bytes; # Tab alignment depends on characters

my($li) = @_;
my($lo) = '';
my $pos = 0;
my $nsp = 0;
my($i, $c);

for ($i = 0; $i < length($li); $i++) {
$c = substr($li, $i, 1);
if ($c eq "\t") {
    my $npos = ($pos+$nsp+8) & ~7;
    my $ntab = ($npos >> 3) - ($pos >> 3);
    $lo .= "\t" x $ntab;
    $pos = $npos;
    $nsp = 0;
} elsif ($c eq "\n" || $c eq "\r") {
    $lo .= " " x $nsp;
    $pos += $nsp;
    $nsp = 0;
    $lo .= $c;
    $pos = 0;
} elsif ($c eq " ") {
    $nsp++;
} else {
    $lo .= " " x $nsp;
    $pos += $nsp;
    $nsp = 0;
    $lo .= $c;
    $pos++;
}
}
$lo .= " " x $nsp;
return $lo;

}

$name = basename($0);

foreach $f ( @ARGV ) { print STDERR "$name: $f\n";

if (! -f $f) {
print STDERR "$f: not a file\n";
next;
}

if (!open(FILE, '+<', $f)) {
print STDERR "$name: Cannot open file: $f: $!\n";
next;
}

binmode FILE;

# First, verify that it is not a binary file; consider any file
# with a zero byte to be a binary file.  Is there any better, or
# additional, heuristic that should be applied?
$is_binary = 0;

while (read(FILE, $data, 65536) > 0) {
if ($data =~ /\0/) {
    $is_binary = 1;
    last;
}
}

if ($is_binary) {
print STDERR "$name: $f: binary file\n";
next;
}

seek(FILE, 0, 0);

$in_bytes = 0;
$out_bytes = 0;
$blank_bytes = 0;

@blanks = ();
@lines  = ();

while ( defined($line = <FILE>) ) {
$in_bytes += length($line);
$line =~ s/[ \t\r]*$//;		# Remove trailing spaces
$line = clean_space_tabs($line);

if ( $line eq "\n" ) {
    push(@blanks, $line);
    $blank_bytes += length($line);
} else {
    push(@lines, @blanks);
    $out_bytes += $blank_bytes;
    push(@lines, $line);
    $out_bytes += length($line);
    @blanks = ();
    $blank_bytes = 0;
}
}

# Any blanks at the end of the file are discarded

if ($in_bytes != $out_bytes) {
# Only write to the file if changed
seek(FILE, 0, 0);
print FILE @lines;

if ( !defined($where = tell(FILE)) ||
     !truncate(FILE, $where) ) {
    die "$name: Failed to truncate modified file: $f: $!\n";
}
}

close(FILE);

}