#!/usr/bin/perl -w
# $Id: mklists.pl,v 1.3 1998/07/29 12:39:11 ray Exp $
#use strict;

my $C = $0; $C =~ s%.*/%%;

my $Mode = "create";
my $Append = "";
my $Help = 0;
my $OptErr = "";
my $debug = 0;
local $missed = "MISSED";

my %Default =
   ( 
    "dirs",
    [[ "^/(bin|dev|etc|lib|sbin|usr|var)/\$",		"IGNORED"],
     [ "^/usr/(bin|doc|etc|games|include|info)/\$",	"IGNORED"],
     [ "^/usr/(lib|man|sbin|share|src)/\$",		"IGNORED"],
     [ "^/usr/doc/",					"IGNORED"],
     [ "^/usr/man/man[123456789n]/\$",			"IGNORED"],
     [ "^/var/(lib|lock|log|run|spool|state|tmp)/\$",	"IGNORED"],
     [ ".*",						"base"],
    ],
    "files",
    [[ "/man/man[1456789n]/",				"base"],
     [ "/man/man[23]/", 				"devel"],
     [ "^/usr/include", 				"devel"],
     [ "^(/usr)?/lib/.*\.so\$", 			"devel"],
     [ "^(/usr)?/lib/.*\.a\$",				"devel-static"],
     [ "^\s*\$",					"IGNORED"],
     [ "^\#",						"IGNORED"],
     [ ".*",						"base"],
    ]
);

while ( $#ARGV >= $[ && ($_ = shift, /^-/ || (unshift(@ARGV,$_) && 0)) ) {
  last if /^--$/;
  (/^--create$/ || /^-c$/)		&& ($Mode = "create", next);
  (/^--dirs$/ || /^-d$/)		&& ($Mode = "dirs", next);
  (/^--files$/ || /^-f$/)		&& ($Mode = "files", next);
  (/^--append$/ || /^-a$/)		&& ($Append = ">", next);
  (/^--debug$/ || /^-D$/)		&& ($debug ++, next);
  (/^--?help/ || /^-h/)			&& ($Help = 1, next);
  (/^-/)				&& ($OptErr .= "$_ ", next);
}

if ( $OptErr ) {
  printf( STDERR "$C: unkown option: $OptErr\n");
}

my $Pkg = shift;


if ( $OptErr || $Help ) {
  die( "Usage: $C [-acdfh] pkg-name\n");
}

if ( "$Mode" eq "create" ) {
  my $D = $ENV{DESTDIR} || die( "$C: DESTDIR: no variable\n");
  system( "rm -f dirs-$Pkg files-$Pkg files-$Pkg-*" ) &&
     die( "$C: removing: $!\n");
  system( "find $D -type d -mindepth 1 -printf '/%P/\n' | sort > dirs-$Pkg") &&
     die( "$C: find dirs: $!\n");
  system( "find $D -not -type d -printf '/%P\n' | sort > files-$Pkg") &&
     die( "$C: find files: $!\n");
  exit( 0);
}

if ( ! -r "$Mode-$Pkg" ) {
  die( "$C: $Mode-$Pkg: $!\n");
}

my $i;
local @f2p = compilePattern($Mode, @{$Default{$Mode}});
my @subs = listSubs( @f2p);

open( IN, "< $Mode-$Pkg" ) || die( "open('$Pkg'): $!\n");
foreach $i ( @subs ) {
  printf( STDERR "open: >$Append files-$Pkg-$i\n") if ( $debug >= 2 );
  open( $i, ">$Append files-$Pkg-$i") || die( "open('$Pkg-$i'): $!\n");
}

while ( <IN> ) {
  my $out = match( $_);
  printf( STDERR "%-20s %s", "$out:", $_) if ( $debug >= 6 );
  print( $out $Prefix . $_);
}
close( IN);

foreach $i ( @subs ) {
  close( $i);
  if ( -z "files-$Pkg-$i" ) {
    printf( STDERR "removing empty '%s'\n", "files-$Pkg-$i")
       if ( $debug >= 1 );
    unlink( "files-$Pkg-$i");
  }
}

if ( -r "files-$Pkg-$missed" ) {
  printf( STDERR "$C: non-empty safety net: files-$Pkg-$missed\n");
  exit( 1);
}

exit( 0);

sub compilePattern($@) {
  my( $mode, @default) = @_;
  my( @p2p) = ();

  if ( $Mode eq "dirs" ) {
    $Prefix = "%dir ";
  } else {
    $Prefix = "";
  }

  unshift(@ARGV, '-') if $#ARGV < $[;
  while ( <> ) {
    next if ( m:^\s*$: || m:^\s*\#: );
    print( STDERR "processing") if ( $debug );
    if ( m:^\@default: ) {
      print( STDERR " defaults ") if ( $debug );
      for ( $i = 0 ; $i <= $#default ; $i ++ ) {
	print( STDERR ".") if ( $debug );
	push( @p2p, [ @{$default[$i]} ]);
      }
      print( STDERR "\n") if ( $debug );
    } else {
      print( STDERR " rule...\n") if ( $debug );
      push( @p2p, [ split ]);
    }    
  }
  # catch the rest...
  push( @p2p,     [ ".*", $missed]);

  return ( @p2p );
}

sub listSubs(@) {
  my( @f ) = @_;
  my( %s) = ();
  my( $i, $j) = ( "", "");
  my( @b) = ();

  for $i ( 0 .. $#f ) {
    printf( STDERR "pkg='%s' pattern='%s'\n", $f[$i][1], $f[$i][0])
       if ( $debug );
    $s{$f[$i][1]} ++;
  }

  foreach $i ( sort( keys( %s)) ) {
    printf( STDERR "sub='%s': %d\n", $i, $s{$i}) if ( $debug >= 2 );
    next unless ( defined( $s{$i}) && $s{$i} > 0 );
    push( @b, $i) unless ( $i eq $j );
    $j = $i;
  }
  printf( STDERR "subs: '%s'\n", join( ', ', @b)) if ( $debug >= 1 );
  return ( @b );
}

sub match($) {
  my ( $t) = @_;
  my ( $i) = 0;

  while ( $i <= $#f2p ) {
    my $p = $f2p[$i][0];
    printf( STDERR "testing(%d): '%s'\n", $i, $p) if ( $debug >= 99 );
    last if ( $t =~ m:$p: );
    $i ++;
  }
  printf( STDERR "Ouch: undefined: \$iff2p[$i]\n") 
     unless ( defined( $f2p[$i]) );
  return ( (defined( $f2p[$i])) ? $f2p[$i][1] : $missed );
}

