#!/usr/bin/perl package main ; use strict ; # # Perl script to beautify and enhance RTEMS automake Makefile.ams # # Reads from stdin and writes to stdout # # usage: # /ampolish Makefile.am~ # mv Makefile.am~ Makefile.am # my @vars ; my @conditions = ( "" ) ; my @buffer = (); my %var_ ; define_variable( "\$(AUTOMAKE_OPTIONS)", ( "foreign", "1.4" ) ); define_variable( "\$(VPATH)", ( "\@srcdir\@" ) ); # find relative up-path to configure.in my $rtems_cfg = find_file(".","configure.in"); # find relative up-path from configure.in to VERSION my $rtems_top = find_file("$rtems_cfg","VERSION"); if ( "$rtems_top" eq "." ) { $rtems_top = "" ; } else { $rtems_top .= "/" ; } { # PASS1: # read input file and concatenate multiple lines into single lines. my @ibuf = () ; while( ) { # consume header last if ( /^[^#].*$/ ) ; push @ibuf, "$_" ; } push @ibuf, "§header\n" ; do { if ( /^(#.*)$/o ) { # preserve comments push @ibuf, "$_" ; } elsif ( /^(\t.*)\\[\s]*$/o ) { # multilines for scripts my $line = "$1§" ; while( ) { if ( /^(.*)\\[\s]*$/o ) { $line .= "$1§" ; } else { $line .= "$_" ; push @ibuf, $line ; last ; } } } elsif ( /^(.*)\\[\s]*$/o ) { # multilines my $line = "$1" ; while( ) { if ( /^(.*)\\[\s]*$/o ) { $line .= "$1" ; } else { $line .= "$_" ; $line =~ s%[\s]+% %g ; push @ibuf, "$line\n" ; last ; } } } else { push @ibuf, "$_" ; } } while ( ) ; @buffer = @ibuf ; } { # PASS2: # fix obsolete constructs my @ibuf = () ; foreach ( @buffer ) { if ( /^(TMP|PRE)INSTALL_FILES[\s]*=(.*)$/o ) { # force "+=" push @ibuf, "$1INSTALL_FILES +=$2\n" ; } elsif ( /^(VPATH|EXTRA_DIST)[\s]*\+=(.*)$/o ) { # force "=" push @ibuf, "$1 = $2\n" ; } elsif ( /^[\s]*ACLOCAL[\s]*=[\s]*\@ACLOCAL\@.*$/o ) { # remove the line } elsif ( /^[\s]*(ACLOCAL_AMFLAGS)[\s\t]*[\+]*=[\s]*(.*)[\s]*$/o ) { # remove the line } elsif ( /^[\s]*(AM_CFLAGS)[\s\t]*[\+]*=[\s]*\$\(CFLAGS_OS_V\)[\s]*$/o ) { # remove the line } elsif ( /^[\s]*debug-am:.*$/o ) { # remove the line } elsif ( /^[\s]*all(\-am):(.*)$/o ) { # replace the line push @ibuf, "all-local:$2\n" ; } elsif ( /^[\s]*profile-am:.*$/o ) { # remove the line } elsif ( /^[\s]*include[\s\t]*\$\(RTEMS_ROOT\)\/make\/lib.cfg[\s]*$/o ) { push @ibuf, "include \$(top_srcdir)/${rtems_top}automake/lib.am\n" ; } elsif ( /^[\s]*include[\s\t]*.*compile.am[\s]*$/o ) { # remove the line } elsif ( /^(.*[^\s])[\s]*$/o ) { # remove trailing spaces push @ibuf, "$1\n" ; } else { push @ibuf, "$_" ; } } @buffer = @ibuf ; } { my @ibuf = () ; foreach ( @buffer ) { if ( /^#(.*)$/o ) { push @ibuf, "#$1\n" ; } elsif ( /^[\s]*if[\s\t]+([a-zA-Z0-9_]+)[\s\t]*$/o ) { push @conditions, "\@" . $1 . "_TRUE\@" ; push @ibuf, "if $1\n" ; } elsif ( /^[\s]*else[\s\t]*$/o ) { @conditions[$#conditions] =~ s/_TRUE\@$/_FALSE\@/; push @ibuf, "else\n" ; } elsif ( /^[\s]*endif[\s\t]*$/o ) { pop @conditions ; push @ibuf, "endif\n" ; } elsif ( /^§.*$/o ) { push @ibuf, "$_" ; } elsif ( /^[\s]*(VPATH)[\s\t]*([\+]*)=[\s]*(.*)[\s]*$/o ) { my $lh = "\$($1)" ; my @rh = split( /:/,"$3"); if ( $#conditions > 0 ) { print STDERR "WARNING: $1 must not be set inside of conditionals!\n" } define_variable( "$lh", @rh ); } elsif ( /^[\s]*(AUTOMAKE_OPTIONS)[\s\t]*([\+]*)=[\s]*(.*)$/o ) { my $lh = "\$($1)" ; my @rh = &split_vars("$3"); if ( $#conditions > 0 ) { print STDERR "WARNING: $1 must not be set inside of conditionals!\n" } define_variable( "$lh", @rh ); } elsif ( /^[\s]*([a-zA-Z0-9_]+)[\s\t]*([\+]*)=[\s]*(.*)$/o ) { my $lh = join ('',@conditions) . "\$($1)" ; my @rh = &split_vars("$3"); my $seen = variable_seen( "$lh" ) ; if ( $#conditions > 0 ) { define_variable( "\$($1)", () ); } define_variable( "$lh", @rh ); if ( not $seen ) { push @ibuf, "§$2var_$lh\n" ; } } elsif ( /^[\s]*include[\s\t]*\$\(top_srcdir\)[\.\/]*automake\/(.*)\.am$/o ) { if ( "$1" eq "lib" ) { push @ibuf, "include \$(top_srcdir)/${rtems_top}automake/compile.am\n" ; push @ibuf, "include \$(top_srcdir)/${rtems_top}automake/$1.am\n" ; } elsif ( "$1" eq "local" ) { $main::seen_local = 1 ; } elsif ( "$1" eq "host" ) { $main::seen_host = 1 ; } } elsif ( /^[\s]*include[\s\t]*\$\(RTEMS_ROOT\)\/make\/(.*)\.cfg$/o ) { if ( "$1" eq "leaf" ) { push @ibuf, "include \$(top_srcdir)/${rtems_top}automake/compile.am\n" ; push @ibuf, "include \$(RTEMS_ROOT)/make/$1.cfg\n" ; } else { push @ibuf, "include \$(RTEMS_ROOT)/make/$1.cfg\n" ; } } elsif ( /^[\s]*include[\s\t]*(.*)$/o ) { push @ibuf, "include $1\n" ; } elsif ( /^\t(.*)$/o ) { push @ibuf, "\t$1\n" ; } elsif ( /^(.*)\:(.*)$/o ) { push @ibuf, "$1:$2\n" ; } elsif ( /^[\s]*$/o ) { push @ibuf, "\n" ; } else { die "ERROR: Don't know how to handle <$_>" ; } } # for @buffer = @ibuf ; } # while die "Conditional stack corrupted" if ( $#conditions != 0 ); foreach( @vars ) { purge( \@{$var_{"$_"}} ); } # print STDERR "\n", @buffer, "\n" ; { my @ibuf = () ; foreach( @buffer ) { if ( /^#.*$/o ) { push @ibuf, "$_" ; } elsif( /^§header$/o ) { my $l = $var_{"\$(AUTOMAKE_OPTIONS)"} ; push @ibuf, "\nAUTOMAKE_OPTIONS = @{$l}\n" ; if ( "$rtems_cfg" eq "." ) { push @ibuf, "ACLOCAL_AMFLAGS = -I ${rtems_top}aclocal\n" ; } if ( defined( @{$var_{"\$(VPATH)"}} ) ) { if ( $#{$var_{"\$(VPATH)"}} > 0 ) { my $l = join (':',@{$var_{"\$(VPATH)"}}) ; push @ibuf, "\nVPATH = $l\n" ; } } push @ibuf, "\n" ; } elsif ( /^§(\+|)var_(.*)\$\((.*)\)$/o ) { print_var(\@ibuf, "$3 $1=", $var_{"$2\$($3)"}) ; } elsif ( /^\t.*$/o ) { &print_script(\@ibuf, "$_"); } elsif ( /^[\s]*if[\s]+([a-zA-Z0-9_]+)[\s\t]*$/o ) { push @conditions, "\@$1_TRUE\@" ; push @ibuf, "if $1\n" ; } elsif ( /^[\s]*else[\s]*$/o ) { @conditions[$#conditions] =~ s/_TRUE\@$/_FALSE\@/; push @ibuf, "else\n" ; } elsif ( /^[\s]*endif[\s]*$/o ) { pop @conditions ; push @ibuf, "endif\n" ; } else { print_line(\@ibuf,$_); } } if ( variable_seen("\$(SUBDIRS)") ) { push @ibuf, "include \$(top_srcdir)/${rtems_top}automake/subdirs.am\n" ; } if ( defined( $main::seen_host ) ) { push @ibuf, "include \$(top_srcdir)/${rtems_top}automake/host.am\n" ; } else { push @ibuf, "include \$(top_srcdir)/${rtems_top}automake/local.am\n" ; } @buffer = @ibuf ; } #print STDERR "\n", @buffer, "\n" ; { ## pretty print my $out = join ('',@buffer) ; $out =~ s/\s\#\n(\#\n)+/\n/g ; $out =~ s/\n\n\#\n\n/\n/g ; $out =~ s/\n\n[\n]*/\n\n/g ; print $out ; } exit 0; # find a relative up-path to a file $file, starting at directory $pre sub find_file($$) { my $pre = $_[0] ; my $file= $_[1] ; my $top = "." ; if (not "$pre") { $pre = "." ; } for ( my $str = "$pre" . "/" . "$top" ; ( -d "$str" ) ; $str = "$pre" . "/" . "$top" ) { if ( -f "${str}/${file}" ) { return $top ; } if ( "$top" eq "." ) { $top = ".." ; } else { $top .= "/.." ; } } ; die "Can't find file ${file}\n" ; } sub variable_seen($) { my $label = "$_[0]" ; my $res = defined $var_{"$label"}; #print STDERR "SEEN: $label ->$res<\n" ; return $res ; } sub define_variable($$) { my ($label,@value) = @_ ; if ( not variable_seen("$label") ) { #print STDERR "DEFINING: $label\n" ; push @vars, "$label" ; } foreach my $i ( @{value} ) { push @{$var_{"$label"}}, $i ; } } # Strip off duplicate entries from a list sub purge($) { my $list = $_[0] ; # Reference to list ! my (@tmp) = () ; foreach my $l ( @{$list} ) { my $i = 1 ; foreach my $t (@tmp) { if ( $t eq $l ) { $i = 0 ; last ; } } push @tmp,$l if ($i) ; } @{$list} = @tmp ; } # # Break the right hand side of a variable assignment into separate chunks # sub split_vars($) { my $line = $_[0] ; my (@buf) = split(//,"$line") ; my $begin = 0 ; my @res = () ; my $depth = 0 ; my $state = 0 ; my $len = $#buf + 1 ; for ( my $i = 0 ; $i < $len ; $i++ ) { my $c = @buf[$i] ; if ( $state == 0 ) { if ( "$c" ne " " ) { # token $begin = $i ; $state++ ; } if ( "$c" eq "\$" ) { # variable $depth++ ; } } elsif ( $state == 1 ) { if ( ( "$c" eq "\)" ) or ( "$c" eq "\}" ) ) { # variable $depth-- ; } elsif ( ("$c" eq " " ) and ( $depth == 0 ) ) { push @res, substr($line,$begin,$i-$begin); $state-- ; } elsif ( "$c" eq "\$" ) { # variable $depth++ ; } } else { die "split_vars: unknown mode\n" ; } } if ( $state > 0 ) { push @res, substr($line,$begin,$len-$begin); $state = 0 } return @res ; } sub print_var($$$) { my ($ibuf,$line,$l) = @_ ; # $l .. reference to list foreach (@{$l}) { if ( ( length($line) + length($_) ) < 76 ) { $line .= " $_"; } else { push @{$ibuf}, "$line \\\n"; $line = " $_" ; } } push @{$ibuf}, "$line\n" ; } sub print_line($$) { my ($ibuf,$input) = @_ ; my @l = split( / /, $input ); my $line = shift @l ; foreach my $i (@l) { if ( ( length($line) + length($i) ) < 76 ) { $line .= " $i"; } else { push @{$ibuf}, "$line \\\n"; $line = " $i" ; } } push @{$ibuf}, "$line" ; } sub print_script($$) { my ($ibuf,$input) = @_ ; $input =~ s%§%\\\n%g ; push @{$ibuf}, $input ; }