@rem = '--*-PERL-*--';
@rem = '
@echo off
set PERL=perl
if "%OS%" == "Windows_NT" goto WinNT
%PERL% -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
:WinNT
%PERL% -x -S "%0" %*
if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
if %errorlevel% == 9009 echo Cannot run %PERL%
if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
goto endofperl
@rem ';
#!perl
#line 16

#!/usr/bin/env perl
#'
# Original author: W. Batelaan
# System Laboratory Southampton
# NXP Semiconductors

# Purpose
# =======
# A customizable script to morph a directory tree into a different one.
# Use this if you want to change the directory structure of a source tree
# but expect to get updates of your source tree, and you 
# still want to easily upgrade to these new releases.
# For example, you receive a source tree not conforming to MoReUse, and you want
# to change it to a MoReUse structure.
# Once you have customized this script for a particular source tree,
# you can use it again when you get an update of this tree.
# Then you can do your compare/import of your updated source tree.
# Having this script takes away at least one excuse for not using 
# the MoReUse directory structure!

# How it works
# ============
# This script is called with src tree and destination tree directory arguments.
# The script will cycle over all the files and directories of
# the src tree and call the Perl subroutine 'process'.
# The 'process' subroutine must be customized below with regular expressions
# which if matched cause a file to be skipped (ignored or deleted),
# or morphed (moved or copied to somewhere in the destination directory).
# The order in which 'process' is called is such that a directory
# always precedes the files it contains: 
# this allows you to move/copy a whole directory, without having to move/copy
# each individual file.

# Error Checks
# ============
# The script will complain if there is a file that does not match any
# of the skip of morph patterns. Either add a pattern for this file,
# of for its containing directory. This error reporting is important
# because we do not want to miss out any files from the original source
# tree that we are not aware of, e.g. because we get an update and something
# has changed.
# Directories that do not match are not reported as errors.

# Usage
# =====
# Runs this script with the -h option, or see the usage subroutine in this file.

################################################################################
# Customize this subroutine!
# There are two parts to be modified; they are both inbetween 
# START_CUSTOMISATION_HERE / END_CUSTOMISATION_HERE comment lines.
################################################################################

sub process {
  return if startOfFileCheck() == 1;

  # Below follow the skip patterns, which specify files/directories that should be skipped.
  # Format: 0 or more lines with:
  #   m!<regular_expression>! or
  # The regular expression is matched against the file path relative to <srcdir>.
  # E.G. m!/CVS/! or
  #      m!^(src/share/optional/filedialog/)! or

  if (
# **** START_CUSTOMISATION_HERE ****
      m!^([^/]+).(html|txt)! or
      m!^(files.pjava3.1.1.*|putback_history.html|README.html|build|install|src/solaris|src/win32)! or
      m!^(src/psos)! or
      m!/CVS/! or
      m!^(src/reference/)! or
      m!^(src/share/java/java/awt/)! or
      m!^(src/share/sun/awt/)! or
      m!^(src/share/sun/gif/)! or
      m!^(src/share/sun/images/)! or
      m!^(src/share/sun/jpeg/)! or
      m!^(src/share/sun/sun/awt/)! or
      m!^(src/share/com/com/sun/awt/)! or
      m!^(src/share/optional/filedialog/)! or
      m!^(src/share/native/sun/awt/)! or
      m!^(src/share/classes/sun/)! or
      m!^(src/share/native/sun/region/)! or
# **** END_CUSTOMISATION_HERE ****
      0
     ) {
    skipIt(); return;
  }



  # Below follow the morph rules, which specify how file/directory paths should be
  # translated from sitting below <srcdir> to <destdir>.
  # Format: 0 or more lines with:
  #   s!<from_regular_expression>!<replacement>! or
  # The regular expression is matched against the file path relative to <srcdir>.
  # E.G. s!^src/share/com/com/sun/(.*)!src/com/sun/$1! or
  #      s!^src/share/doc/(.*)!docs/$1! or

  if (
# **** START_CUSTOMISATION_HERE ****
      s!^src/share/com/com/sun/(.*)!src/com/sun/$1! or
      s!^src/share/doc/(.*)!docs/$1! or
      s!^src/share/java/include/((jni|jvmdi|jvmpi)\.h)$!inc/$1! or
      s!^src/share/java/include/((jni|jvmdi|jvmpi)\.h)$!inc/$1! or
      s!^src/share/native/sun/include/(.*)!inc/$1! or
      s!^src/share/java/runtime/(.*)!src/jvm/src/$1! or
      s!^src/share/java/java/(.*)!src/java/$1! or
      s!^src/share/java/io/(java_io_(File|RandomAccessFile)_.*\.c)!src/optional/javafile/java/io/$1! or
      s!^src/share/java/zip/(.*)!src/java/util/zip/$1! or
      s!^src/share/java/(.*)!src/java/$1! or
      s!^src/share/doc/javadoc_images/(.*)!docs/javadoc_images/$1! or
      s!^src/share/javadoc_images/(.*)!docs/javadoc_images/$1! or
      s!^src/share/jcc/(.*)!src/tools/javacompact/$1! or
      s!^src/share/lib/jvm.hprof.txt!src/tools/hprof/jvm.hprof.txt! or
      s!^src/share/lib/(.*)!src/properties/$1! or
      s!^src/share/optional/(.*)!src/optional/$1! or
      s!^src/share/sun/sun/security/([^/]+\.java)$!src/sun/security/$1! or
      s!^src/share/sun/debug/(.*)!src/tools/agent/$1 ! or
      s!^src/share/sun/jdc/(.*)!src/tools/javacompact/$1! or
      s!^src/share/sun/systemresource/(.*)!src/sun/net/www/protocol/systemresource/$1 ! or
      s!^src/share/sun/tools/(.*)!src/sun/$1! or
      s!^src/share/sun/sun/rmi/server/(MsgRMIClassLoader\.java)$!src/sun/rmi/server/resources/$1! or
      s!^src/share/sun/sun/(.*)!src/sun/$1! or
      s!^src/share/sun/(.*)!src/sun/$1! or
      s!^src/share/tools/(.*)!src/tools/$1! or
      s!^src/share/lib/(.*)properties!src/properties/$1! or
# **** END_CUSTOMISATION_HERE ****
      0
     ) {
    morphIt(); return;
  }

  fileNotMatchedError();
}

################################################################################

use Getopt::Std;
use vars qw($opt_F $opt_h $opt_k $opt_n $opt_v);
use File::Find;
use Cwd;

$pgm = $0;
$errors = 0;

sub usage {
    print <<EOF;
$pgm [<options>] <srcdir> <destdir>
Rename or copies files from a source tree to a destination tree.
according to SLS DBS pjava source tree layout.

Options:
  -F		Force: ignore errors.
  -h		Help.
  -k		Keep going after an error.
  -n		Do Not change anything (only print what would be done).
  -m <regexp>	Only process src files matching <regexp>.
  -R		Rename/delete files from <srcdir> (default is to copy).
  -v		Verbose mode.
EOF
  exit($opt_h ? 0 : 1);
}

usage() if (!getopts("Fhknm:Rv") or $opt_h or @ARGV != 2);

$srcdir = shift @ARGV;
$srcdir =~ tr,\\,/,;
$destdir = shift @ARGV;
$destdir =~ tr,\\,/,;

$cwd = cwd();

if (!chdir $destdir) {
  fatal("$!: can't cd to $destdir\n");
}
$destdir = cwd();
print "Absolute destdir = '$destdir'\n";
chdir $cwd or fatal("Cant cd back to '$cwd'\n");

if (!chdir $srcdir) {
  fatal("$!: can't cd to $srcdir\n");
}
$srcdir = cwd();
print "Absolute srcdir = '$srcdir'\n";

find(\&process, ".");

unless ($errors && !$opt_F) {
  doCmds();
  print "No changes made (-n option in use).\n" if $opt_n;
}

#printf "Skipped: %4d files  %4d directories\n", $filesSkipped, $dirsSkipped;
#printf "Morphed: %4d files  %4d directories\n", $filesMorphed, $dirsMorphed;
print "$errors error", ($errors == 1 ? "" : "s"), " found.\n";
exit $errors ? 1 : 0;

################################################################################
# End of main program
################################################################################

# Sets up variables for processing a file:
# $_ and $srcfile: filename relative to <srcdir>
# $srcfilename: leaf of $srcfile
# $fullsrcfile: absolute pathname of srcfile
sub startOfFileCheck {
  $srcfile = $File::Find::name;
  $srcfilename = $_;
  $srcfile =~ s!^\Q$srcdir\E/!!o;
  $srcfile =~ s|^\./||; # remove starting ./
  $_ = $srcfile;
  $fullsrcfile = "$srcdir/$srcfile";
  print "srcfile = $srcfile srcfilename = $srcfilename\n" if $opt_v;

  # if -m option given, check it matches:
  if ($opt_m && $srcfile !~ m/$opt_m/) {
    print "ignored by -m option: $srcfile\n" if $opt_v;
  }

  # Ignore toplevel directory:
  return 1 if $srcfile eq '.';

  $fileIsDir = -d $fullsrcfile;

  $fileDone{$srcfile} = 0;
  return 0;
}

sub fileNotMatchedError {
  if ($fileDone{$srcfile} == 0 && !$fileIsDir) {
    error("No skip or morph expression match for '$srcfile'\n");
  }
}

sub morphIt {
  my $destfile = $_;
  print "morph '$srcfile' => '$destfile'\n" if $opt_v;
  my $fulldestfile = "$destdir/$destfile";
  my ($dir) = $fulldestfile =~ m!^(.*)/[^/]+$!;
  unless (exists $madeDir{$dir}) {
    storeCmd("mkdir", "-p", $dir);
    $madeDir{$dir} = 1;
  }

  if ($fileIsDir) {
    $File::Find::prune = 1;
    $dirsMorphed++;
  } else {
    $filesMorphed++;
  }
  my @options = $fileIsDir ? ("-r") : ();
  storeCmd($opt_R ? "mv" : "cp", @options, $fullsrcfile, $fulldestfile);
  $fileDone{$srcfile} = 0;
}

sub skipIt {
  
  if ($fileIsDir) {
    $File::Find::prune = 1;
    $dirsSkipped++;
  } else {
    $filesSkipped++;
  }
  $fileDone{$srcfile} = 1;
  if ($opt_R) {
    my @options = $fileIsDir ? ("-r") : ();
    storeCmd("rm", @options, $fullsrcfile);
  }
}

sub storeCmd {
  push @cmds, [@_];
}

sub doCmds {
  foreach $cmd (@cmds) {
    print "@$cmd\n";
    unless ($opt_n) {
      if (system(@$cmd) != 0) {
        error("Returns $?: @$cmd\n");
      }
    }
  }
}

sub msg {
  print "@_";
}

sub info {
  msg "(info)", @_;
}

sub warning {
  msg "**WARNING:", @_;
  $main::warnings++;
}

sub error {
  msg "**ERROR:", @_;
  exit 1 unless ($opt_k || $opt_F);
  $main::errors++;
}

sub fatal {
  msg "**FATAL:", @_;
  exit 1;
}
