#!/usr/bin/perl # use strict 'subs' ; # use strict 'vars' ; # use strict 'refs' ; # use strict ; # # Perl script to beautify and enhance RTEMS autoconf Makefile.ins # # Reads from stdin and writes to stdout # # usage: # acpolish Makefile.in~ # mv Makefile.in~ Makefile.in # # Note: This tool is not indented to be exported from the source-tree # if ( -f "Makefile.am" ) { # Refuse to work on Makefile.ins generated from automake; # redirecting STDOUT to Makefile.in will trash the Makefile.in ;- die "acpolish must not be run in automake directories" ; } my $experimental = 0 ; # enable experimental/unsafe features my $verbose = 0 ; my $build_pgms_seen = "" ; my $make_exe_seen = 0 ; my $install_seen = 0 ; my $top_builddir = ""; my $subdir = ""; my @installdirs = () ; my @pieces = () ; my @files = () ; my @variants = () ; my @vars = () ; sub print_macro($$) { my $line = $_[0] ; my $input = $_[1] ; $input =~ s/\\\\/ /g; my @l = split(' ',$input); foreach (@l) { if ( ( length($line) + length($_) ) < 76 ) { $line .= " $_"; } else { print "$line \\\n"; $line = " $_" ; } } print "$line\n" ; } # 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 ; } sub find_root { $top_builddir = "." ; $subdir=""; my $pwd = `pwd`; chomp $pwd; $pwd .= "/" ; my $len ; if ( -f "configure.in" ) { return $top_builddir ; } my $i = rindex($pwd,'/'); $len = $i; $pwd = substr($pwd,0,$len); $i = rindex($pwd,'/'); $subdir = substr($pwd,$i+1,$len - 1); $top_builddir = ".." ; while( -d "$top_builddir" ) { if ( -f "${top_builddir}/configure.in" ) { return $top_builddir ; } $len=$i; $pwd = substr($pwd,0,$len); $i = rindex($pwd,'/'); $subdir = substr($pwd,$i+1,$len - 1) . "/$subdir"; $top_builddir .= "/.." ; } ; die "Can't find configure.in\n" ; } find_root(); my @buffer = () ; sub subst_line { # substitute obsolete variables if ( /^([^\s]*)[\s]+$/o ) { # strip trailing spaces $_ = "$1\n"; } if ( /^(.*)MKLIB(.*)$/o ) { s/MKLIB/RANLIB/g ; } if ( /^(.*)\$\(INSTINCFLAGS\)(.*)$/o ) { s/\$\(INSTINCFLAGS\)/-m 644/g ; } if ( /^(.*)ASM(_FILES|_PIECES|_O_FILES)(.*)$/o ) { s/ASM_FILES/S_FILES/g ; s/ASM_PIECES/S_PIECES/g ; s/ASM_O_FILES/S_O_FILES/g ; print STDERR "ASM: $_" if ( $verbose > 0) ; } if ( /^(.*)MP_PIECES(.*)$/o ) { # HACK: this is not always correct s/MP_PIECES/MP_C_PIECES/g ; print STDERR "MP_PIECES: $_" if ( $verbose > 0 ); } if ( /^(.*)\$\(RTEMS_BSP\)(.*)$/o ) { s/\$\(RTEMS_BSP\)/\@RTEMS_BSP\@/g ; } if ( /^(.*)\$\(RTEMS_ROOT\)\/mkinstalldirs(.*)$/o ) { $_ = "$1\$\(mkinstalldirs\)$2\n" ; } if ( /^(.*)\$\{(.*)_FILES\}(.*)$/o ) { $_ = "$1\$\($2_FILES\)$3\n" ; } if ( /^(.*)\$\{(.*)_PIECES\}(.*)$/o ) { $_ = "$1\$\($2_PIECES\)$3\n" ; } if ( /^(.*)\$\(PROJECT_ROOT\)\/\@RTEMS_BSP\@\/lib\/include(.*)$/o ) { $_ = "$1\$\(PROJECT_INCLUDE\)$2\n" ; } if ( /^(.*)\$\{PROJECT_RELEASE\}(.*)$/o ) { $_ = "$1\$\(PROJECT_RELEASE\)$2\n" ; } if ( /^(.*\$\(INSTALL_[A-Z]+\))[\s]+-m[\s]+([54])([0-9][0-9].*)$/o ) { my $v = $2 + 2 ; $_ = "$1 -m $v$3\n" ; } if ( /^H_FILES[\s]*=[\s]*\$\(wildcard[\s]+\$\(srcdir\)\/\*\.h\)[\s]*$/o ) { my $files =`ls *.h 2>/dev/null`; print STDERR "WARNING: Replacing \"\(wildcard... in $_\n" ; $line = "H_FILES ="; @l = split(' ',$files) ; foreach(@l) { $line .= " \$\(srcdir\)/$_"; } $line .= "\n" ; $_ = "$line" ; } if ( /^.*\$\(make\-exe\).*$/o ) { $make_exe_seen = 1 ; } if ( /^.*\$\(INSTALL_(DATA|SCRIPT|PROGRAM)\)(.*)$/o ) { $install_seen = 1 ; } } { # 1st PASS: # * Read input file # * concatenate multiple lines # * Remove obsolete variables my @ibuf = () ; my $line = "" ; while ( <> ) { &subst_line ; if ( /^(#.*)$/o ) { # preserve comments $line = "$_" ; push @ibuf, $line ; $line = "" ; } elsif ( /^.*\\$/o ) { # multilines chop ; $line .= "$_\\" ; } else { $line .= "$_" ; push @ibuf, $line ; $line = "" ; } } @buffer = @ibuf; } { # 2nd PASS: # * remove automatically generated lines # * process some selected make rules my $line = "" ; my @tbuf = () ; foreach (@buffer) { if ( /^[\t](.*)$/o ) { # make rule production my $line = $1 ; tr/\\/ / ; my @l = split(/;/,$_); foreach (@l) { # try to get installation directories if ( /^.*\$\(mkinstalldirs\).*\s\$\(INSTALLDIRS\)$/o ) { } elsif ( /^.*\$\(mkinstalldirs\).*\s([^\s]+)$/o ) { push @installdirs, "$1" ; } elsif ( /^.*\$\(INSTALL_CHANGE\).*\s([^\s]+)$/o ) { push @installdirs, "$1" ; } } push @tbuf, "§3$line" } elsif ( /^[\s]*\#.*$/o ) { # comment push @tbuf, "$_" ; } elsif ( /^[\s]*([A-Z_]*)_FILES[\s]*\=[\s]*(.*)$/o ) { # *_FILES = ... Macros if ( /^[\s]*([A-Z_]*_|)(CC|C|EQ|H|I|O|S|X)_FILES[\s]*\=[\s]*(.*)$/o ) { # print STDERR "FILES: <$1>--<$2>--<$3>\n" ; my $f = "$1$2_FILES" ; ${"var_$f"}="$3" ; if ( ( $experimental > 0 ) and ( ( "$2" eq "C" ) or ( "$2" eq "CC" ) or ( "$2" eq "S" ) or ( "$2" eq "I" ) or ( "$2" eq "H" ) ) ) { my $p = "$1$2_PIECES" ; if ( not defined ${"var_$p"} ) { print STDERR "ADDING $p\n" ; ${"var_$p"} = "" ; push @tbuf, "§4$p\n" ; push @pieces, "$p" ; } } # place a marker push @tbuf, "§4$f\n" ; push @files, "$f" ; } else { # found a bug print STDERR "UNKNOWN _FILES: $_\n" ; my $f = "$1_FILES" ; ${"var_$f"}="$2" ; # place a marker push @tbuf, "§4$f\n" ; push @files, "$f" ; } } elsif ( /^[\s]*([A-Z_]*)_PIECES[\s]*\=[\s]*(.*)$/o ) { # *_PIECES = ... Macros if ( /^[\s]*([A-Z][A-Z0-9_]*_|)(CC|C|EQ|H|I|O|S|X|REL)_PIECES[\s]*\=[\s]*(.*)$/o ) { my $p = "$1$2_PIECES" ; if ( not defined ${"var_$p"} ) { ${"var_$p"} = "$3" ; push @tbuf, "§4$p\n" ; push @pieces, "$p" ; } else { ${"var_$p"} .= " $3" ; } } elsif ( /^[\s]*(BSP|CPU|GENERIC)_PIECES[\s]*\=[\s]*(.*)$/o ) { # Explicit exceptions from the *_PIECES naming conventions # They should better be replaced in future my $p = "$1_PIECES" ; ${"var_$p"}="$2" ; # place a marker push @tbuf, "§4$p\n" ; push @pieces, "$p" ; } else { # found a bug print STDERR "UNKNOWN _PIECES: $_\n" ; my $p = "$1_PIECES" ; ${"var_$p"}="$2" ; # place a marker push @tbuf, "§4$p\n" ; push @pieces, "$p" ; } } elsif ( /^[\s]*([A-Z_]+)_PIECES_([^\s]+)_V[\s]*\=[\s]*(.*)$/o ) { # *_PIECES_.._V = ... Macros if ( /^[\s]*([A-Z][A-Z0-9_]*_|)(CC|C|EQ|H|I|O|S|X|REL)_PIECES_([^\s]+)_V[\s]*\=[\s]*(.*)$/o ) { my @l = split(/_/,$3); my $v = "$1$2-$#l" ; if ( not defined @{"variants_$v"} ) { push @variants, "$v" ; } my $p = "$1$2_PIECES_$3_V" ; push @{"variants_${v}"}, "$p" ; ${"var_$p"}="$4" ; # place a marker push @tbuf, "§4$p\n" ; push @pieces, "$p" ; } else { # found a bug print STDERR "UNKNOWN _PIECES: $_\n" ; my $p = "$1_PIECES" ; ${"var_$p"}="$2" ; # place a marker push @tbuf, "§4$p\n" ; push @pieces, "$p" ; } } elsif ( /^[\s]*([^\s+=]+)[\s]*\=[\s]*(.*)$/o ) { # makefile variable if ( ( "$1" eq "subdir" ) or ( "$1" eq "top_srcdir" ) or ( "$1" eq "top_builddir" ) or ( "$1" eq "RTEMS_ROOT" ) or ( "$1" eq "PROJECT_ROOT" ) or ( "$1" eq "INSTALL" ) or ( "$1" eq "PACKHEX" ) or ( "$1" eq "INSTALL_CHANGE" ) or ( "$1" eq "mkinstalldirs" ) ) { print STDERR "REMOVE: $1\n" if $verbose ; } elsif ( "$1" eq "srcdir" ) { # place marker push @tbuf, "§0\n"; } elsif ( "$1" eq "INSTALLDIRS" ) { # process the block my $input = $2 ; $input =~ s/\\\\/ /g ; my @l = split(' ',$input); foreach (@l) { if ( /[\s]*([^\s]+)[\s]*$/o ) { push @installdirs, "$1" ; } } } else { # print STDERR "MACRO: <$1> = <$2>\n"; my $p = "$1" ; ${"var_$p"}="$2" ; # place a marker push @tbuf, "§4$p\n" ; push @vars, "$p" ; } } elsif ( /^[\s]*([^\s+=]+)[\s]*\+\=[\s]*(.*)$/o ) { # makefile variable addition # print STDERR "MACRO: <$1> += <$2>\n"; my $p = "$1" ; ${"var_$p+"}="$2" ; # place a marker push @tbuf, "§5$p\n" ; push @vars, "$p+" ; } elsif ( /^[\s]*(\@[^\s]+\@)$/o ) { # autoconf variable if ( "$1" eq "\@SET_MAKE\@" ) { } else { push @tbuf, "$1\n" ; } } elsif ( /^[\s]*include[\s]+(.*)$/o ) { # include line push @tbuf, "$_" ; if ( /^include[\s\t]*.*(directory|leaf|lib)\.cfg.*$/o ) { push @tbuf, "§1\n" ; push @tbuf, "PACKHEX = \@PACKHEX\@\n" if ( $make_exe_seen == 1 ) ; push @tbuf, "§2\n" ; } } elsif ( /^[\s]*(ifeq|ifneq|else|endif)[\s]+(.*)$/o ) { # gmake conditionals # Most of them are removed, but we still have some :- push @tbuf, "$1 $2\n" ; } elsif ( /^[\s]*([^:]+)[\s]*(:[:]*)[\s]*(.*)$/o ) { if ( "$2" eq "::" ) { # Warn about "::"-rules # Will be silently removed below. print STDERR "WARNING: Removing \"::\" in RULE $_\n" ; } if ( ( "$1" eq "Makefile" ) or ( "$1" eq "\$\(INSTALLDIRS\)" ) ) { # delete entry shift @buffer ; } elsif ( ( "$1" eq "all" ) or ( "$1" eq "preinstall" ) ) { # Note the dependencies # Not yet exploited, but could be useful for dependency # tracking in future if ( defined ${"var_$1"} ) { ${"var_$1"} .= " $3" ; } else { ${"var_$1"} = "$3" ; } push @tbuf, "$1: $3\n" ; } else { # make rule push @tbuf, "$1: $3\n" ; } } elsif ( /^[\s]*$/o ) { # empty line push @tbuf, "\n" ; } else { die "PASS 2: Unhandled $_" ; } } @buffer = @tbuf ; purge \@installdirs ; purge \@pieces ; } # A fragment to debug conditionals #foreach( @variants ) #{ # my $v = $_ ; # print STDERR "VARIANT: $v\n"; # foreach (@{"variants_${v}"}) # { # print STDERR "* $_\n;" ; # } #} # sanity check on *_FILES macros # too fragile for the time being, # therefore disabled by default if ( $experimental > 1 ) { foreach( @files ) { my $file = "$_" ; my $line = ${"var_$_"} ; $line =~ tr /\\/ /; my @l = split(' ',$line); my @o = () ; foreach (@l) { if ( /^([^\.]+)\.([a-z]+)$/o ) { print STDERR "$file: *.$2 in $_\n" ; } elsif ( /^\$\(.*\)$/o ) { print STDERR "$file: REF: $_\n" ; } else { print STDERR "$file: UNHANDLED: $_\n" ; } } } } # print STDERR "PASS 2: @buffer" ; { # PASS 3: # * output to new Makefile # * prettyprint newlines my $nl_seen = 0 ; foreach ( @buffer ) { if ( /^$/o ) { $nl_seen++ ; print "\n" if ( $nl_seen < 2 ); } elsif ( /^\§0$/o ) { print "\@SET_MAKE\@\n" ; print "srcdir = \@srcdir\@\n" ; print "top_srcdir = \@top_srcdir\@\n" ; print "top_builddir = $top_builddir\n" ; print "subdir = $subdir\n" if "$subdir" ; print "\nRTEMS_ROOT = \@RTEMS_ROOT\@\n" ; print "PROJECT_ROOT = \@PROJECT_ROOT\@\n\n" ; $nl_seen = 1 ; } elsif ( /^\§1$/o ) { print "\n" ; print "INSTALL = \@INSTALL\@\n" if ( $install_seen > 0 ); print "INSTALL_CHANGE = \@INSTALL_CHANGE\@\n" ; $nl_seen = 0 ; } elsif ( /^\§2$/o ) { # Handle installdirs related items if ( $#installdirs >= 0 ) { print "mkinstalldirs = \$(SHELL) \$(top_srcdir)/\@RTEMS_TOPdir\@/mkinstalldirs\n\n" ; my $line = join( ' ',@installdirs ); print_macro "INSTALLDIRS =", $line ; print "\n\$(INSTALLDIRS):\n\t\@\$(mkinstalldirs) \$(INSTALLDIRS)\n\n" ; $nl_seen = 1 ; } } elsif ( /^\§3(.*)$/o ) { # pretty print a shell script fragment/make production my @l = split(/\\\\/,$1); if ( $#l >= 0 ) { my $i = shift @l ; print "\t$i"; } foreach( @l ) { print "\\\n$_"; } print "\n" ; $nl_seen = 0 ; } elsif ( /^\§4(.*)$/o ) { # pretty print a make variable print_macro "$1 =", ${"var_$1"} ; $nl_seen = 0 ; } elsif ( /^\§5(.*)$/o ) { # pretty print an addition to a make variable print_macro "$1 +=", ${"var_$1+"} ; $nl_seen = 0 ; } else { $nl_seen = 0 ; print "$_" ; } } } # Add rules for config.status generated files if ( "$build_pgms_seen" ) { print "%: \$(srcdir)/%.in \$(top_builddir)/config.status\n" ; print " cd \$(top_builddir) \\\n" ; print " && CONFIG_FILES=" ; print "\$(subdir)/" if ( "$subdir" ); print "\$@ CONFIG_HEADERS= \$(SHELL) ./config.status\n"; } else { print "Makefile: \@MAINTAINER_MODE_TRUE\@ \$(srcdir)/Makefile.in \$(top_builddir)/config.status\n" ; print " cd \$(top_builddir) \\\n" ; print " && CONFIG_FILES=" ; print "\$(subdir)/" if ( "$subdir" ); print "\$@ CONFIG_HEADERS= \$(SHELL) ./config.status\n"; } ;1