#! /usr/bin/perl

# This Perl script buffs (removes trailing blanks from) and/or expands
# (converts tabs to spaces in) the files named on the command line.  It
# also ensures that each file (if not empty) ends in a proper "\n".  You
# do not need it to install, use, modify, develop, build, package or
# distribute `debram'.  The author uses it to tidy debram source files
# up before distribution.  Feel free to use it if you wish.
#
# Notice:  You normally do not want to expand Makefiles.  You only want
# to buff them.  Use the -X option with Makefiles.

use warnings;
use strict;
use integer;

our $tab   =  8;
our $usage = <<END;
usage: buff-expand [options] files
        -s      do not overwrite the files; output to stdout instead
        -B      do not buff
        -X      do not expand
        --      do not process further options
        -h      print this usage message

END

my $process_opts = 1;
my $stdout       = 0;
my $buff         = 1;
my $expand       = 1;
my $help         = 0;
my @file = map {
    eval {
        if ( $process_opts and my ( $opts ) = /^-(.*)/ ) {
            my @opts = split '', $opts;
            @opts or $process_opts = 0;
            for ( @opts ) {
                $process_opts or next;
                $_ eq '-' and $process_opts = 0, next;
                $_ eq 's' and $stdout       = 1, next;
                $_ eq 'B' and $buff         = 0, next;
                $_ eq 'X' and $expand       = 0, next;
                print $usage;
                exit 0;
            }
            return ();
        }
        else {
            return ( $_ );
        }
    }
} @ARGV;

sub buff_expand (\$@) {
    my $has_acted = shift;
    my @ret = map {
        chomp( my $a = $_ );
        if ( $expand ) {
            my $b = '';
            if ( my @b = split /\t/, $a ) {
                $b  = shift @b;
                $b .= ' ' x ( $tab - length( $b ) % $tab ) . $_ for @b;
            }
            $a = $b;
        }
        if ( $buff ) {
            $a =~ s/\s*$//;
        }
        "$a\n";
    } @_;
    if ( @ret != @_ ) { $$has_acted = 1 }
    else {
        for my $i ( 0 .. $#_ ) {
            $ret[$i] eq $_[$i] or $$has_acted = 1, last;
        }
    }
    return wantarray ? @ret : $ret[0];
}

if ( @file ) {
    for my $file ( @file ) {
        open  FILE, '<', $file
            or warn( "$0: cannot read $file\n" ), next;
        my @line          = <FILE>;
        close FILE;
        my $has_acted     = 0;
        my @buff_expanded = buff_expand $has_acted, @line;
        if    ( $stdout    ) {
            print @buff_expanded;
        }
        elsif ( $has_acted ) {
            open  FILE, '>', $file
                or warn( "$0: cannot write $file\n" ), next;
            print FILE @buff_expanded;
            close FILE;
        }
    }
}
else {
    my @line      = <>;
    my $has_acted = 0;
    print buff_expand $has_acted, @line;
}

