changeset 0:d72d5d73b93a

Added Autopoop and mkchangelog.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 22 Apr 2008 14:31:44 +0300
parents
children 2375efb3340d
files autopoop mkchangelog
diffstat 2 files changed, 377 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/autopoop	Tue Apr 22 14:31:44 2008 +0300
@@ -0,0 +1,257 @@
+#!/usr/bin/perl -w
+# autopoop v0.57 (C) 2008 Matti 'ccr' Hamalainen
+#
+# Tries to generate extra.mk.in from known configure.ac and other
+# autoconf m4-macros, scanning against Makefiles. Also checks for
+# missing / unsubstituted symbols, etc.
+#
+# Requirements:
+# - Recent enough GNU Autoconf (and requirements for that)
+# - Perl 5
+#
+# TODO:
+# - see fixmes
+# - document this
+# - find bugs
+# - ???
+# - profit
+#
+use strict;
+use Cwd qw(getcwd realpath);
+
+# List of subdirectories to check for additional Autoconf m4 macros
+my @m4testdirs = ("m4", "unix");
+
+# Misc. settings
+my $makefile = "Makefile";
+my $extrasys = "extra.mk";
+my $buildsys = "buildsys.mk";
+my $tmpfile = "autopoop.tmp";
+my $autom4te = "autom4te";
+
+# Things that may be set by user
+my %bsdefines = (
+  "DESTDIR" => 1,
+);
+
+# Special substitutions
+my %confdefines = (
+#  "VPATH" => "srcdir",
+#  "SET_MAKE" => "",
+);
+
+
+### Function prototypes
+sub shortpath($);
+sub scanfile($$$$$$$$);
+
+
+### Argument handling
+my $pcwd = getcwd();
+my $argc = ($#ARGV + 1);
+print "Autopoop v0.57 (C) 2008 Matti 'ccr' Hamalainen\n";
+die("Usage: autopoop <configurefile> <outfile> [autom4te options]\n".
+"Example: autopoop configure.ac extra.mk.in\n\n".
+"NOTICE! Assumes following files are used:\n".
+"$buildsys\[.in\], $extrasys, $makefile\n\n") unless ($argc >= 2);
+my $configure = shift;
+my $outfile = shift;
+
+
+### Execute Autoconf 'autom4te' ...
+my @args = (@ARGV);
+foreach my $dir (@m4testdirs) {
+  if (-d $dir) { push(@args, ("-I", $dir)); }
+}
+
+push(@args, (
+  "--force", "--no-cache", "--melt", "--language=autoconf",
+  "--trace=AC_SUBST", "-o", $tmpfile, $configure));
+
+print "- Running $autom4te ".join(" ", @args)." ...\n";
+system($autom4te, @args) == 0 or die("Failed to execute $autom4te: $?\n");
+
+
+### Paf files
+$buildsys = realpath($buildsys);
+$extrasys = realpath($extrasys);
+$outfile = realpath($outfile);
+
+
+### Process results
+open(INFILE,"<".$tmpfile) or die("Could not open '$tmpfile'!\n");
+while (<INFILE>) {
+  chop;
+  my @entries = split(/:/);
+  my $key = $entries[3];
+  unless ($key =~ /_(FALSE|TRUE)$/) { $confdefines{$key} = $key; }
+}
+close INFILE;
+unlink($tmpfile);
+
+
+### Scan Makefiles and depencies
+my %makesubsts = ();
+my %confsubsts = ();
+my %makedefines = ();
+my %scanned = ($outfile => 1, $extrasys => 1);
+scanfile(".", $makefile, \%scanned, \%makesubsts, \%confsubsts, \%makedefines, 1, 1);
+scanfile("", $buildsys, \%scanned, \%makesubsts, \%confsubsts, \%makedefines, 1, 0);
+
+
+### Scan buildsys.mk.in
+my %bssubsts = ();
+scanfile("", $buildsys.".in", \%scanned, \%bssubsts, \%bssubsts, \%bsdefines, 0, 0);
+
+
+my %globdefs = ();
+foreach my $file (keys %makedefines) {
+  foreach my $s (keys %{$makedefines{$file}}) {
+    $globdefs{$s} = 1;
+  }
+}
+
+
+### Compare results
+print "- Checking for used, but possibly undefined Make variables:\n";
+foreach my $file (keys %makesubsts) {
+  foreach my $s (sort { $a cmp $b } keys %{$makesubsts{$file}}) {
+    if (!defined($confdefines{$s}) && !defined($makedefines{$file}{$s}) && !defined($bsdefines{$s})) {
+      my $err = 0;
+      if (!defined($globdefs{$s})) {
+        $err = 1;
+      } elsif ($file ne $buildsys && $file ne $outfile) {
+        $err = 2;
+      }
+      if ($err) {
+        printf "  %-20s", "'$s'";
+        print  " in ".shortpath($file).":".$makesubsts{$file}{$s}." ($err)\n";
+      }
+    }
+  }
+}
+print qq|Legend:
+  (1) = Not defined anywhere (or misdetected).
+  (2) = Defined 'somewhere', but unsure if symbol is propagated.
+
+|;
+
+
+print "- Checking for used, but possibly undefined substitutions:\n";
+foreach my $file (keys %confsubsts) {
+  foreach my $s (keys %{$confsubsts{$file}}) {
+    if (!defined($confdefines{$s})) {
+        printf "  %-20s", "'$s'";
+        print  " in ".shortpath($file).":".$confsubsts{$file}{$s}."\n";
+    }
+  }
+}
+print "\n";
+
+
+### Output stuff
+print "- Outputting '$outfile'\n";
+open(OUTFILE, ">", $outfile) or die("Could not open '$outfile'!\n");
+foreach my $s (keys %confdefines) {
+  if ($confdefines{$s} ne "") {
+    print OUTFILE "$s ?= \@".$confdefines{$s}."\@\n";
+  } else {
+    print OUTFILE "\@".$s."\@\n";
+  }
+}
+close OUTFILE;
+
+print "- Done.\n";
+
+
+###
+### Functions
+###
+sub shortpath($) {
+  if (index($_[0], $pcwd) == 0) {
+    return substr($_[0], length($pcwd) + 1);
+  } else {
+    return $_[0];
+  }  
+}
+
+sub addhash($$$$$)
+{
+# if ($usenames) { $substs->{$filename}{$1} = $line; } else { $substs->{$1} = $line; }
+  if ($_[0]) {
+    $_[1]->{$_[2]}{$_[3]} = $_[4];
+  } else {
+    $_[1]->{$_[3]} = $_[4];
+  }
+}
+
+sub scanfile($$$$$$$$) {
+  my $mypath = $_[0];
+  my $myfile = $_[1];
+  
+  my $scanned = $_[2];
+  my $substs = $_[3];
+  my $confsubsts = $_[4];
+  my $defines = $_[5];
+  
+  my $usenames = $_[6];
+  my $recurse = $_[7];
+
+  # Form real path and check if we have already scanned the file
+  my $filename = realpath($mypath."/".$myfile);
+  if (defined($filename)) {
+    if (defined($scanned->{$filename})) {
+      $scanned->{$filename}++;
+      return;
+    }
+    $scanned->{$filename} = 1;
+  } else {
+    $filename = $mypath."/".$myfile;
+  }
+
+#print "ASDF: $filename\n";
+
+  # Scan file, if found
+  if (open(my $SCANFILE, "<", $filename)) {
+    print "- Scanning ".shortpath($filename)." ...\n";
+    my $line = 0;
+    while (<$SCANFILE>) {
+      $line++;
+      chop;
+      if (/^#/) {
+        # ignore comment lines
+      } else {
+      
+      while (/[^\$]\$\{([A-Za-z0-9_]+)\}/g) {
+        addhash($usenames, $substs, $filename, $1, $line);
+      }
+      while (/[^\$]\$\(([A-Za-z0-9_]+)\)/g) {
+        addhash($usenames, $substs, $filename, $1, $line);
+      }
+      while (/\@([A-Za-z0-9_]+)\@/g) {
+        addhash($usenames, $confsubsts, $filename, $1, $line);
+      }
+      
+      if (/^ifdef\s+([A-Za-z0-9_]+)/g) {
+        addhash($usenames, $substs, $filename, $1, $line);
+      } elsif (/^([A-Za-z][A-Za-z0-9_]+)\s*[\+]?=/) {
+        addhash($usenames, $defines, $filename, $1, $line);
+      }
+      elsif (/^include (\S+)/) {
+        scanfile($mypath, "$1", $scanned, $substs, $confsubsts, $defines, $usenames, $recurse);
+      }
+      }
+    }
+    close $SCANFILE;
+  }
+  
+  # Recurse into subdirectories
+  if ($recurse) {
+    opendir(DIR, $mypath) || return;
+    my @dirs = grep { /^[^\.]/ && -d "$mypath/$_" } readdir(DIR);
+    closedir(DIR);
+    foreach my $dir (@dirs) {
+      scanfile($mypath."/".$dir, $myfile, $scanned, $substs, $confsubsts, $defines, $usenames, $recurse);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mkchangelog	Tue Apr 22 14:31:44 2008 +0300
@@ -0,0 +1,120 @@
+#!/usr/bin/perl -w
+use strict;
+my $HG = "hg";
+
+my $argc = ($#ARGV + 1);
+print STDERR "mkchangelog v0.1 (C) 2008 Matti 'ccr' Hamalainen\n";
+die("Usage: mkchangelog [revision]\n".
+"Assumes latest tagged revision if no revision given."
+) unless ($argc <= 1);
+my $startrev = "";
+if ($argc >= 1) { $startrev = shift; }
+
+
+### Parse tag information
+my $hgcmd = "$HG tags";
+open(PIIPPU, '-|', $hgcmd) or die("Cannot execute $hgcmd\n");
+my %tags = ();
+my $gottags = 0;
+while (<PIIPPU>) {
+  chop;
+  if (/^(\S+)\s+(\d+):(.+)$/) {
+    $tags{$2} = $1;
+    $gottags = 1;
+  }
+}
+close PIIPPU;
+
+die("No Mercurial tags data found, quitting.\n") unless ($gottags);
+
+### Do shit
+if ($startrev eq "") {
+  foreach my $i (sort { $a <=> $b } keys %tags) {
+    if ($tags{$i} ne "tip") { $startrev = $i; }
+  }
+}
+
+my $revcmd;
+my $therevs = "tip:$startrev";
+if ($startrev ne "") {
+  $revcmd = "-r $therevs";
+  print STDERR "Getting log for revisions $therevs ...\n";
+} else {
+  $revcmd = "";
+  $therevs = "ALL";
+  print STDERR "Getting log for all revisions ...\n";
+}
+
+### Parse log
+$hgcmd = "$HG log -M -v -f $revcmd --template '\@\$REV:#rev#:#node|short#:#files#\$\@\n#desc#\n\@\$END\$\@\n'";
+open(PIIPPU, '-|', $hgcmd) or die("Cannot execute $hgcmd\n");
+my %log = ();
+my %loghash = ();
+my %revhash = ();
+my %filehash = ();
+my %rmref = ();
+my $isdesc = 0;
+my $rev = -1;
+my $hash = "";
+my $text = "";
+my $gotrevs = 0;
+my $files = "";
+while (<PIIPPU>) {
+  chop;
+  if (/^\@\$REV:(\d+):([0-9a-f]{12}):(.*)\$\@$/) {
+    $rev = $1;
+    $hash = $2;
+    $files = $3;
+    $text = "";
+    $isdesc = 1;
+    $gotrevs = 1;
+  } elsif (/^\@\$END\$\@$/) {
+    die("lol\n") unless ($isdesc);
+    $isdesc = 0;
+    $filehash{$rev} = $files;
+    $log{$rev} = $text;
+    $loghash{$hash} = $rev;
+    $revhash{$rev} = $hash;
+  } elsif ($isdesc) {
+    $text .= $_." ";
+  } else {
+    print STDERR "? $_\n";
+  }
+}
+close PIIPPU;
+
+die("No Mercurial revision data found? How odd... quitting.\n") unless ($gotrevs);
+
+###
+my %hide = ();
+foreach my $i (sort { $a <=> $b } keys %log) {
+  if ($log{$i} =~ /Backed out changeset ([0-9a-f]{12})/) {
+    my $href = $1;
+    if (defined($loghash{$href})) {
+      $hide{$i} = 1;
+      $rmref{$href} = $revhash{$i};
+    }
+  }
+}
+
+my $s = "ChangeLog between revisions $therevs";
+print "$s\n";
+print "=" x length($s) . "\n\n";
+
+foreach my $i (sort { $a <=> $b } keys %log) {
+  my $href = $revhash{$i};
+  if (!defined($rmref{$href}) && !defined($hide{$i})) {
+    my @foo = split(/\s+/,$filehash{$i});
+    my $n = $#foo + 1;
+    if ($n > 3) { $n = 3; }
+    
+    print "- $log{$i} [".($#foo + 1).": ";
+    for (my $k = 0; $k < $n; $k++) {
+      print $foo[$k];
+      print " " unless ($k+1 == $n);
+    }
+    print " ..." unless ($#foo <= $n);
+    print "]\n";
+  }
+}
+