#!/usr/bin/perl -w

# $OpenBSD: check-libs-elf,v 1.11 2004/11/23 11:54:55 espie Exp $

#  Copyright (c) 2001 Marc Espie
# 
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#  SUCH DAMAGE.
# 

# Check that all libraries are mentioned in lib depends.

use strict;
use OpenBSD::PackageInfo;
use OpenBSD::PackingList;
use OpenBSD::SharedLibs;

sub find_library
{
	my $spec = shift;
	my @r;
	OpenBSD::SharedLibs::add_system_libs('/');
	@r = OpenBSD::SharedLibs::lookup_libspec('/usr', $spec);
	unless (@r) {
		@r = OpenBSD::SharedLibs::lookup_libspec('/usr/X11R6', $spec);
	}
	unless (@r) {
		for my $pkg (installed_packages()) {
		    OpenBSD::SharedLibs::add_package_libs($pkg, 1);
		}
		@r = OpenBSD::SharedLibs::lookup_libspec('/usr/local', $spec);
	}
	return join(',', @r);
}

my $error = 0;
my %registered;
my %used;

if (defined $ENV{'LIB_DEPENDS'}) {
	for my $d (split(/[ ,\n]+/, $ENV{'LIB_DEPENDS'})) {
		$d =~ s/.*\///;
		$d =~ s/\.$//;
		$d =~ s/(?:\.\d+){1,2}$//;
		$registered{$d} = 1;
		$used{$d} = 0;
	}
}

if (defined $ENV{'WANTLIB'}) {
	for my $r (split(/\s+/, $ENV{'WANTLIB'})) {
		$r =~ s/(?:\.\d+){1,2}$//;
		$registered{$r} = 1;
		$used{$r} = 0;
	}
}

open(my $libs, '<', shift) or die;
open(my $builds, '<', shift) or die;
while (<$builds>) {
	chomp;
	if (m/^.*\/lib(.*?)\.so((?:\.\d+)*)$/) {
		$registered{$1} = $2;
    	}
}

close($builds);

while (<$libs>) {
	my ($path, $name, $major, $minor);
	chomp;
	# older a.out
	if (m/^\tlibrary: (\S+)\s(\d+)\s(\-?\d+)$/) {
		($name, $major, $minor) = ($1, $2, $3);
	} elsif (m/^\t\-l(.*?)(\.\d+)?(\.\d+)?(?: \=\> .*)?$/) {
		($name, $major, $minor) = ($1, $2, $3);
	# newer elf
	} elsif (m/^lib(\S+)\s+(\d+)\s+(\d+)$/) {
		($name, $major, $minor) = ($1, $2, $3);
	} elsif (m/^(.*)\/lib(\S+)\s+(\d+)\s+(\d+)$/) {
		($path, $name, $major, $minor) = ($1, $2, $3, $4);
	} elsif (m/^lib(\S+)$/) {
		$name = $1;
	} elsif (m/^(.*)\/lib(\S+)$/) {
		($path, $name) = ($1, $2);
	} else {
		next;
	}
	if (exists $registered{$name}) {
		$used{$name} = 1;
	} else {
		my $spec="$name.$major.$minor";
		if (defined $path && $path ne '/usr/local/lib') {
			$spec="$path/$spec";
		}
		print "lib-depends-check: no mention of $spec (".find_library($spec).")\n";
		$error = 1;
	}
}
close($libs);

while (my ($k, $v) = each %used) {
	next if $v == 1;
	print "lib-depends-check: unused library $k\n";
}

exit($error);
