123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- #!/usr/bin/perl -w
-
- use File::Spec::Functions qw ( :ALL );
- use File::stat;
- use strict;
- use warnings;
-
- my $cfgdir = "config";
- my $config_h = shift || "config.h";
-
- # Read in a whole file
- #
- sub read_file {
- my $file = shift;
-
- open my $fh, "<$file" or die "Could not open file $file: $!\n";
- local $/;
- my $data = <$fh>;
- close $fh;
- return $data;
- }
-
- # Write out a whole file
- #
- sub write_file {
- my $file = shift;
- my $data = shift;
-
- open my $fh, ">$file" or die "Could not write $file: $!\n";
- print $fh $data;
- close $fh;
- }
-
- # Delete a file
- #
- sub delete_file {
- my $file = shift;
-
- unlink $file or die "Could not delete $file: $!\n";
- }
-
- # Get a file modification time
- #
- sub file_mtime {
- my $file = shift;
-
- my $stat = stat ( $file ) or die "Could not stat $file: $!\n";
- return $stat->mtime;
- }
-
- # Read all the .h files in a directory
- #
- sub read_dir {
- my $dir = shift;
-
- opendir my $dh, $dir or die "Could not open directory $dir: $!\n";
- my @entries = grep { /\.h$/ } readdir $dh;
- closedir $dh;
- return @entries;
- }
-
- # Get the current configuration by reading the configuration file
- # fragments
- #
- sub current_config {
- my $dir = shift;
-
- my $cfg = {};
- foreach my $file ( read_dir ( $dir ) ) {
- $cfg->{$file} = read_file ( catfile ( $dir, $file ) );
- }
- return $cfg;
- }
-
- # Calculate guard name for a header file
- #
- sub guard {
- my $name = shift;
-
- $name =~ s/\W/_/g;
- return "CONFIG_".( uc $name );
- }
-
- # Calculate preamble for a header file
- #
- sub preamble {
- my $name = shift;
- my $master = shift;
-
- my $guard = guard ( $name );
- my $preamble = <<"EOF";
- /*
- * This file is automatically generated from $master. Do not edit this
- * file; edit $master instead.
- *
- */
-
- #ifndef $guard
- #define $guard
- EOF
- return $preamble;
- }
-
- # Calculate postamble for a header file
- #
- sub postamble {
- my $name = shift;
-
- my $guard = guard ( $name );
- return "\n#endif /* $guard */\n";
- }
-
- # Get the new configuration by splitting config.h file using the
- # @BEGIN/@END tags
- #
- sub new_config {
- my $file = shift;
-
- my $cfg = {};
- my $cursor = "";
-
- open my $fh, "<$file" or die "Could not open $file: $!\n";
- while ( <$fh> ) {
- if ( ( my $newcursor, my $suffix ) = /\@BEGIN\s+(\w+\.h)(.*)$/ ) {
- die "Missing \"\@END $cursor\" before \"\@BEGIN $1\""
- ." at $file line $.\n" if $cursor;
- $cursor = $newcursor;
- $cfg->{$cursor} = preamble ( $cursor, $file )
- unless exists $cfg->{$cursor};
- $cfg->{$cursor} .= "\n/*".$suffix."\n";
- } elsif ( ( my $prefix, my $oldcursor ) = /^(.*)\@END\s+(\w+\.h)/ ) {
- die "Missing \"\@BEGIN $oldcursor\" before \"\@END $oldcursor\""
- ." at $file line $.\n" unless $cursor eq $oldcursor;
- $cfg->{$cursor} .= $prefix."*/\n";
- $cursor = "";
- } else {
- $cfg->{$cursor} .= $_ if $cursor;
- }
- }
- close $fh;
- die "Missing \"\@END $cursor\" in $file\n" if $cursor;
-
- foreach $cursor ( keys %$cfg ) {
- $cfg->{$cursor} .= postamble ( $cursor );
- }
-
- return $cfg;
- }
-
- #############################################################################
- #
- # Main program
-
- # Read in current config file fragments
- #
- my $current = current_config ( $cfgdir );
-
- # Read in config.h and split it into fragments
- #
- my $new = new_config ( $config_h );
-
- # Delete any no-longer-wanted config file fragments
- #
- foreach my $file ( keys %$current ) {
- unlink catfile ( $cfgdir, $file ) unless exists $new->{$file};
- }
-
- # Write out any modified fragments, and find the oldest timestamp of
- # any unmodified fragments.
- #
- my $oldest = time ();
- foreach my $file ( keys %$new ) {
- if ( $current->{$file} && $new->{$file} eq $current->{$file} ) {
- # Unmodified
- my $time = file_mtime ( catfile ( $cfgdir, $file ) );
- $oldest = $time if $time < $oldest;
- } else {
- write_file ( catfile ( $cfgdir, $file ), $new->{$file} );
- }
- }
-
- # If we now have fragments that are older than config.h, set the
- # timestamp on config.h to match the oldest fragment, to prevent make
- # from always attempting to rebuild the fragments.
- #
- if ( $oldest < file_mtime ( $config_h ) ) {
- utime time(), $oldest, $config_h or die "Could not touch $config_h: $!\n";
- }
|