eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
    & eval 'exec perl -S $0 $argv:q'
    if 0;

# $Id: ace_ld,v 4.4 1999/07/01 16:10:22 levine Exp $
#
# Drop-in replacement for "ld" that supports munching.
#
# The first three lines above let this script run without specifying the
# full path to perl, as long as it is in the user's PATH.
# Taken from perlrun man page.

$usage =
  "usage: $0 [-? | [[-C <compile> --] [-m <munch>] [-n <nm>]] [-f]]] " .
  "<ld command>\n";

#### To avoid quoting problems on the command line, all arguments
#### between -C and -- are combined into the single compile command.
$compile_option = 0;

####
#### process command line args
####
while ( $#ARGV >= 0  &&  $ARGV[0] =~ /^-/ ) {
    if ( $ARGV[0] eq '-C' ) {
        $compile_option = 1;
        if ( $ARGV[1] !~ /^[-].+$/ ) {
            $compile = $ARGV[1]; shift;
        } else {
            print STDERR "$0:  must provide argument for -c option\n";
            die $usage;
        }
    } elsif ( $ARGV[0] eq '--' ) {
        $compile_option = 0;
    } elsif ( $ARGV[0] eq '-m' ) {
        if ( $ARGV[1] !~ /^[-].+$/ ) {
            $munch = $ARGV[1]; shift;
        } else {
            print STDERR "$0:  must provide argument for -m option\n";
            die $usage;
        }
    } elsif ( $ARGV[0] eq '-n' ) {
        if ( $ARGV[1] !~ /^[-].+$/ ) {
            $nm = $ARGV[1]; shift;
        } else {
            print STDERR "$0:  must provide argument for -n option\n";
            die $usage;
        }
    } elsif ( $ARGV[0] eq '-?' ) {
        print "$usage";
        exit;
    } else {
        if ($compile_option) {
          $compile .= " $ARGV[0]";
        } else {
          warn "$0:  unknown option $ARGV[0]\n";
         die $usage;
        }
    }
    shift;
}


####
#### Save link command, i.e., current @ARGV, for use below.
####
@args = @ARGV;


####
#### Find full path to each library.
####
@libDirs = ();
$current_dir_in_libDirs = 0;
@libs = ();
@objs = '';

foreach $arg (@ARGV) {
  if ($arg =~ /^['"]?-L([\S]+)/) {
    ($dir = $1) =~ s%/+$%%;     #### trim any trailing slashes
    push (@libDirs, $dir);
    $current_dir_in_libDirs = 1 if $dir eq '.';
  } elsif ($arg =~ /^['"]?-l([\S]+)/) {
    push (@libs, $1);
  } elsif ($arg =~ /\.o$/) {
    push (@objs, $arg);
  }
}

#### Add . to libDirs if it doesn't already have it.
push (@libDirs, ".") unless $current_dir_in_libDirs;

foreach $lib (@libs) {
  foreach $libDir (@libDirs) {
    if (-e "$libDir/lib$lib.a") {
      $full_path{$lib} = "$libDir/lib$lib.a";
      last;
    }
  }
}


####
#### Set up signal handler.
####
$done = 0;
$SIG{'HUP'} = $SIG{'INT'} = $SIG{'QUIT'} = $SIG{'TERM'} = 'cleanup';


####
#### Munch, if $munch is non-null.
####
if ($munch) {
  $munch_objs = join (' ', @objs);
  $munch_libs = join (' ', values %full_path);

  open (MUNCH, "$nm $munch_objs $munch_libs | $munch |") ||
    &fail ("$0: unable to run \"$nm\" or \"$munch\"\n");

  open (CTORDTOR, "> __ctordtor.c") ||
    &fail ("$0: unable to open \"__ctordtor.c\"\n");

  while (<MUNCH>) {
    #### Filter out munch output that contains '.cpp'.  It results from
    #### .cpp files that have no text or data, e.g., .cpp files that
    #### only contain template instantiations.  These lines confuse g++.
    print CTORDTOR unless /\.cpp/;
  }

  close CTORDTOR || &fail ("$0: unable to write \"__ctordtor.c\"\n");
  close MUNCH;

  system ("$compile -o .obj/__ctordtor.o __ctordtor.c") &&
    &fail ("$0: \"$compile\" failed\n");
}


####
#### Construct the link command from @args and perform the link.
####
if ($munch) {
  #### Insert ctordtor object file before first library in link command.
  $arg_lib = 0;
  foreach $arg (@ARGV) {
    if ($arg =~ /^['"]?-l/) {
      last;
    }
    ++$arg_lib;
  }
  splice (@args, $arg_lib, 0, ".obj/__ctordtor.o");
}

$link_command = join (' ', @args);

system ("$link_command") && &fail ("$0: $link_command failed\n");


$done = 1;
&cleanup;


####
####
####
sub fail {
  local ($message) = @_;

  warn $message;
  &cleanup;
}


####
#### clean up when done or on signal
####
sub cleanup {
  unlink "__ctordtor.c", ".obj/__ctordtor.o";
  if ($done) {
    exit 0;
  } else {
    exit 1;
  }
}

#### EOF
