#*****************************************************************************
#
# StdLib.pm - Library Rules for autodep
# (c) 1998 Kriang Lerdsuwanakij
# License: GNU General Public License
#
#	This program is free software; you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation; either version 2 of the License, or
#	(at your option) any later version.
#
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#
#	You should have received a copy of the GNU General Public License
#	along with this program; if not, write to the Free Software
#	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# History:
#	For later history, see ChangeLog
#
#	1.0.0	(Jul 22, 1998)
#		- First version from StdStaticLib.pm and StdDynamicLib.pm.
#		- Fix a bug - missing scope for $::shCurTarget.
#		- Update to interface version 2.
#
#*****************************************************************************

package StdLib;
$pkgName = "StdLib";
die "$pkgName: this module must only be called by autodep\n" 
		if ($::shProgName !~ /^autodep/);

@source = ();			# List of source files and their parameters

@sourceSorted = ();		# Sorted version of @source with duplicate
				# entries removed

# Required subroutines
sub interface {
	return (2, "1.1.0");
}

sub queryoption {
	return ();
}

sub processoption {
	return;
}

sub new {
	my @parm = @_;			# Call by value
	my $class = shift @parm;	# Get the module name
	my $parm = shift @parm;		# Get the target info
				# $parm now contains a structure
				# described by $::shCurTarget in the next
				# section
	my $self = {};		# Data that will contain all information
				# specific to this target

	$self->{target} = $parm;
	push @{ $parm->{output} }, $self->{target}{name};
	push @{ $parm->{output2} }, { name => $self->{target}{name},
				      param => [],
				      depend => [] };
	push @::shGeneratedFile, $self->{target}{name};

	my $type = "Cobj";
	if ($self->{target}{type} =~ /C\+\+/) {
		$type = "C++obj";
	}

	if ($self->{target}{type} =~ /static/) {
		$self->{dynamic} = 0;
	}
	else {
		$self->{dynamic} = 1;
	}

					# Don't mess with shared
					# @::shTarget
	my $privateTarget = ::copystruct($parm);
	$privateTarget->{name} = "N/A";		# Dummy
	$privateTarget->{type} = $type;		# Cobj or C++obj type

	for $i (0 .. scalar(@{ $privateTarget->{source} })-1) {
		my $objName;
		my $j = ::isinlist("-o",
				@{ $privateTarget->{source}[$i]{param} });
		if ($j == 0) {
			$objName = $privateTarget->{source}[$i]{name};
			if ($self->{dynamic}) {
				$objName =~ s/\.(c|C|cc|cxx|cpp|c\+\+|i|ii|s|S)$/\.lo/;
				push @{ $privateTarget->{source}[$i]{param} },
					"-o", $objName;
			}
			else {
				$objName =~ s/\.(c|C|cc|cxx|cpp|c\+\+|i|ii|s|S)$/\.o/;
			}
		}
		else {
			$objName = $privateTarget->{source}[$j]{param};
		}
		$parm->{source}[$i]{output}{name} = $objName;

		if ($self->{dynamic}) {
			my $stdObjName = $privateTarget->{source}[$i]{name};
			$stdObjName =~ s/\.(c|C|cc|cxx|cpp|c\+\+|i|ii|s|S)$/\.o/;
			::adddepend($stdObjName, $objName);

			if (! ::isinlist("-fPIC", 
					@{ $privateTarget->{source}[$i]{param} })) {
				push @{ $privateTarget->{source}[$i]{param} }, "-fPIC";
			}
		}
	}

	::addtarget($privateTarget);

	$::shVariable{adLIBS} .= " " . $self->{target}{name};
	::appendunique $::shVariable{adOUTFILES}, "\$(adLIBS)";

	return bless $self, $class;	# Build an object for this target
}

sub output {
	my @parm = @_;			# Call by value
	my $self = shift @parm;		# The same data built by new
	my $handle = shift @parm;	# Output file handle

					# Emit link commands for this target
	$self->_OutputBuild($handle);
	return 1;		# Success
}

sub _OutputBuild {

	my @parm = @_;
	my $self = shift @parm;
	my $handle = shift @parm;

	print "Processing target: $self->{target}{name}\n";

	print $handle "# Building $self->{target}{name}\n\n";

	my ($i, $str, $strObj, $strOut);

	$str = "";
	if (! ::isinlist("Makefile",@{ $::shParameter{EXCLUDE} })) {
		$str = "Makefile ";
	}

	$strObj = "";
	my $options = "";
	for $i (0 .. scalar(@{ $self->{target}{source} })-1) {

					# Dependency list
		my $objFile = $self->{target}{source}[$i]{name};
		if (($self->{dynamic}
		     && $objFile =~ s/\.(c|C|cc|cxx|cpp|c\+\+|i|ii|s|S)$/\.lo/)
		    || (! $self->{dynamic}
		        && $objFile =~ s/\.(c|C|cc|cxx|cpp|c\+\+|i|ii|s|S)$/\.o/)) {
			$strObj .= "$objFile ";
		}
		else {
			$options .= "$objFile ";
			$options .= join ' ',
					$self->{target}{source}[$i]{param};
		}
	}

	$str .= $strObj;
	$strOut = ::indentstring("$self->{target}{name} : ", $str, 0);
	print $handle $strOut;

					# Command line
	if ($self->{dynamic}) {
		my $outCC = "\$(CC)";
		my $outCCFLAGS = "\$(CFLAGS)";
		if ($self->{target}{type} =~ /C\+\+/) {
			$outCC = "\$(CXX)";
			$outCCFLAGS = "\$(CXXFLAGS)";
		}
		$str = "$outCCFLAGS -shared -o $self->{target}{name} $strObj ";
		$str .= $options;
		$strOut = ::indentstring("$outCC ", $str, 1);
		print $handle $strOut, "\n";
	}
	else {
		$str = "rc $self->{target}{name} $strObj $options";
		$strOut = ::indentstring("\$(AR) ", $str, 1);
		print $handle $strOut;
		print $handle "\t\$(RANLIB) $self->{target}{name}\n\n";
	}
}

1;
