#!/usr/bin/perl -w
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    if 0; #$running_under_some_shell

sub usage() {
    print "strip-guards /path/to/sources

Changes

#ifdef _BLAH_
#include <blah.hxx>
#endif

to simple

#include <blah.hxx>

in .c and .cxx files if the _BLAH_ guard exists in the .hxx file.\n";
    exit 1;
}

use File::Find();

%includes = ();

sub guard_name($)
{
    my ( $include_fname ) = @_;

    if ( !open( $IN, $include_fname ) ) {
        die "Couldn't open $include_fname";
    }
    while ( my $line = <$IN> ) {
        if ( $line =~ /^#\s*ifndef\s+([^\s\/]*)/ ||
			 $line =~ /^#if\s+!defined\s+([^\s\/]*)/ ) {
            my $guard = $1;
            if ( defined ( $line = <$IN> ) ) {
                if ( ( $line =~ /^#\s*define\s+([^\s\/]*)/ ) && ( $guard eq $1 ) )
                {
                    close $IN;
                    return $guard;
                }
                else {
                    last;
                }
            }
        }
    }
    close $IN;

    return "";
}

sub guards_include($$)
{
    my ( $guard, $include ) = @_;

    if ( $include =~ /\.hpp$/ ) {
        my $inc = "_" . $include . "_";
        $inc =~ tr(./a-z)(__A-Z/);
        if ( $inc eq $guard ) {
            return 1;
        }
    }

    my $should_be = $includes{$guard};
    if ( defined( $should_be ) ) {
        my $inc = $include;
        $inc =~ s/.*[\/\\]//;
        if ( $inc eq $should_be ) {
            return 1;
        }
    }

    return 0;
}

sub strip_file($$)
{
    my ( $in, $out ) = @_;
    if ( !open( $IN, $in ) ) {
        die "Couldn't open $in";
    }
    if ( !open( $OUT, '>', $out ) ) {
        die "Couldn't open $out";
    }

    my $first_include = 0;
    while ( my $line = <$IN> ) {
        my $buffer = $line;
        my $ok = 1;

        if ( $line =~ /^#\s*include/ ) {
            $first_include = 1;
        }
        if ( $first_include && ( $line =~ /^$/ ) ) {
            if ( defined( $line = <$IN> ) ) {
                $buffer .= $line;
            }
            else {
                $ok = 0;
            }
        }
        if ( $ok && ( $line =~ /^#\s*ifndef\s+([^\s\/]*)/ ) ) {
            if ( defined( $line = <$IN> ) ) {
                $buffer .= $line;
            }
            else {
                $ok = 0;
            }

            my $guard = $1;
            if ( $ok && ( $line =~ /^#\s*include\s+["<]([^">]*)/ ) ) {
                $first_include = 1;
                my $include_line = $line;
                my $include = $1;

                if ( defined( $line = <$IN> ) ) {
                    $buffer .= $line;
                }
                else {
                    $ok = 0;
                }

                if ( $ok && ( $line =~ /^#\s*endif/ ) && guards_include( $guard, $include ) ) {
                    print $OUT $include_line;
                }
                else {
                    $ok = 0;
                }
            }
            else {
                $ok = 0;
            }
        }
        else {
            $ok = 0;
        }

        if ( !$ok ) {
            print $OUT $buffer;
        }
    }

    close $OUT;
    close $IN;
}

sub find_guards
{
    if ( /^.*\.h\z/s || /^.*\.hxx\z/s ) {
        my $guard = guard_name( $_ );
        if ( $guard ne "" ) {
            my $inc = $_;
            $inc =~ s/.*\///;
            if ( defined( $includes{$guard} ) && ( $includes{$guard} ne $inc ) ) {
                print STDERR "Warning: Redefinition of guard '$guard' in '$_' (first definition in '$includes{$guard}'\n";
            }
            $includes{$guard} = $inc;
            print STDERR "guard: $guard ($inc)\n";
        }
    }
}

sub strip_guards
{
    if ( /^.*\.[ch]\z/s || /^.*\.[ch]xx\z/s ) {
        if ( rename( $_, "$_.strip-guards-orig" ) ) {
            print STDERR "stripping $_\n";
            strip_file( "$_.strip-guards-orig", $_ );
        }
    }
}

#
# main()
#
my $path = shift( @ARGV );
if ( !defined( $path ) ) {
    usage();
}

File::Find::find( {wanted => \&find_guards}, $path );

# add a few common typos
$includes{"_GEN_HXX"} = "gen.hxx";
$includes{"_TOOLS_GEN_HXX"} = "gen.hxx";
$includes{"_SV_H"} = "sv.h";
$includes{"_VCL_KEYCOD_HXX"} = "keycod.hxx";
$includes{"_VCL_FONT_HXX"} = "font.hxx";
$includes{"_VCL_FONT_HXX"} = "font.hxx";
$includes{"_SV_SALCTYPE_H"} = "salctype.hxx";
$includes{"_TIME_HXX"} = "time.hxx";
$includes{"_TIMER_HXX"} = "timer.hxx";
$includes{"_TOOLS_STRING_HXX"} = "string.hxx";
$includes{"_GFXLINK_HXX"} = "gfxlink.hxx";
$includes{"_COLOR_HXX"} = "color.hxx";
$includes{"_DEBUG_HXX"} = "debug.hxx";
$includes{"_SVX_ACCESSIBILITY_ACCESSIBLE_COMPONENT_BASE_HXX"} = "AccessibleComponentBase.hxx";
$includes{"_SD_ACCESSIBILITY_ACCESSIBLE_DOCUMENT_VIEW_BASE_HXX"} = "AccessibleDocumentViewBase.hxx";
$includes{"_SVX_ACCESSIBILITY_ACCESSIBLE_IVIEW_FORWARDER_HXX"} = "IAccessibleViewForwarder.hxx";
$includes{"_SVX_ACCESSIBILITY_ACCESSIBLE_IVIEW_FORWARDER_HXX"} = "IAccessibleViewForwarder.hxx";
$includes{"_SFX_HRC"} = "sfx.hrc";
$includes{"_SFXSIDS_HRC"} = "sfxsids.hrc";
$includes{"_RTL_USTRING_H"} = "ustring.h";
$includes{"_RTL_USTRING_"} = "ustring.hxx";
$includes{"_RTL_OUSTRING_HXX_"} = "ustring.hxx";
$includes{"_OSL_INTERLCK_H_"} = "interlck.h";

File::Find::find( {wanted => \&strip_guards}, $path );
