1*10355SAli.Bahrami@Sun.COM#!/usr/bin/perl -w
2*10355SAli.Bahrami@Sun.COM#
3*10355SAli.Bahrami@Sun.COM# CDDL HEADER START
4*10355SAli.Bahrami@Sun.COM#
5*10355SAli.Bahrami@Sun.COM# The contents of this file are subject to the terms of the
6*10355SAli.Bahrami@Sun.COM# Common Development and Distribution License (the "License").
7*10355SAli.Bahrami@Sun.COM# You may not use this file except in compliance with the License.
8*10355SAli.Bahrami@Sun.COM#
9*10355SAli.Bahrami@Sun.COM# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*10355SAli.Bahrami@Sun.COM# or http://www.opensolaris.org/os/licensing.
11*10355SAli.Bahrami@Sun.COM# See the License for the specific language governing permissions
12*10355SAli.Bahrami@Sun.COM# and limitations under the License.
13*10355SAli.Bahrami@Sun.COM#
14*10355SAli.Bahrami@Sun.COM# When distributing Covered Code, include this CDDL HEADER in each
15*10355SAli.Bahrami@Sun.COM# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*10355SAli.Bahrami@Sun.COM# If applicable, add the following below this CDDL HEADER, with the
17*10355SAli.Bahrami@Sun.COM# fields enclosed by brackets "[]" replaced with your own identifying
18*10355SAli.Bahrami@Sun.COM# information: Portions Copyright [yyyy] [name of copyright owner]
19*10355SAli.Bahrami@Sun.COM#
20*10355SAli.Bahrami@Sun.COM# CDDL HEADER END
21*10355SAli.Bahrami@Sun.COM#
22*10355SAli.Bahrami@Sun.COM
23*10355SAli.Bahrami@Sun.COM#
24*10355SAli.Bahrami@Sun.COM# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25*10355SAli.Bahrami@Sun.COM# Use is subject to license terms.
26*10355SAli.Bahrami@Sun.COM#
27*10355SAli.Bahrami@Sun.COM
28*10355SAli.Bahrami@Sun.COM#
29*10355SAli.Bahrami@Sun.COM# interface_cmp audits two interface definition files (as created by
30*10355SAli.Bahrami@Sun.COM# interface_check) against one another, and confirms that:
31*10355SAli.Bahrami@Sun.COM#
32*10355SAli.Bahrami@Sun.COM#  o	All versioned libraries that were present in the previous interface
33*10355SAli.Bahrami@Sun.COM#	are present in the new interface
34*10355SAli.Bahrami@Sun.COM#
35*10355SAli.Bahrami@Sun.COM#  o	for each non-private interface in a library confirm that no symbols
36*10355SAli.Bahrami@Sun.COM#	have been removed and that no symbols have been added to it between
37*10355SAli.Bahrami@Sun.COM#	the two revisions
38*10355SAli.Bahrami@Sun.COM#
39*10355SAli.Bahrami@Sun.COM# Return codes:
40*10355SAli.Bahrami@Sun.COM#
41*10355SAli.Bahrami@Sun.COM#  0	All interfaces in the new release are identical in old release.
42*10355SAli.Bahrami@Sun.COM#  1	Something is different refer to the error messages.
43*10355SAli.Bahrami@Sun.COM
44*10355SAli.Bahrami@Sun.COM
45*10355SAli.Bahrami@Sun.COMuse strict;
46*10355SAli.Bahrami@Sun.COM
47*10355SAli.Bahrami@Sun.COMuse POSIX qw(getenv);
48*10355SAli.Bahrami@Sun.COMuse Getopt::Std;
49*10355SAli.Bahrami@Sun.COMuse File::Basename;
50*10355SAli.Bahrami@Sun.COM
51*10355SAli.Bahrami@Sun.COM#### Define all global variables (required for strict)
52*10355SAli.Bahrami@Sun.COMuse vars  qw($Prog);
53*10355SAli.Bahrami@Sun.COMuse vars  qw(%opt);
54*10355SAli.Bahrami@Sun.COMuse vars  qw(%old_hash %old_alias %new_hash %new_alias);
55*10355SAli.Bahrami@Sun.COM
56*10355SAli.Bahrami@Sun.COM# Exception Arrays:
57*10355SAli.Bahrami@Sun.COM#
58*10355SAli.Bahrami@Sun.COM# The ADDSYM and DELSYM exceptions are maintained on the @AddSymList
59*10355SAli.Bahrami@Sun.COM# and @DelSymList arrays, respectively. Each array element is a reference
60*10355SAli.Bahrami@Sun.COM# to a subarray of triples:
61*10355SAli.Bahrami@Sun.COM#	(sym_re, ver_re, obj_re)
62*10355SAli.Bahrami@Sun.COM# where each item in the tripple is a regular expression, used to
63*10355SAli.Bahrami@Sun.COM# match a particular symbol/version/object combination.
64*10355SAli.Bahrami@Sun.COM#
65*10355SAli.Bahrami@Sun.COM# The EMPTY_TOPVERSION exceptions are maintained on the @EmptyTopVerList
66*10355SAli.Bahrami@Sun.COM# array. Each array element is a reference to a subarray of pairs:
67*10355SAli.Bahrami@Sun.COM#	(ver_re, obj_re)
68*10355SAli.Bahrami@Sun.COM# where each item in the pair is a regular expression, used to
69*10355SAli.Bahrami@Sun.COM# match a particular version/object combination.
70*10355SAli.Bahrami@Sun.COM#
71*10355SAli.Bahrami@Sun.COMuse vars  qw(@AddSymList @DelSymList @EmptyTopVerList);
72*10355SAli.Bahrami@Sun.COM
73*10355SAli.Bahrami@Sun.COM
74*10355SAli.Bahrami@Sun.COM## LoadExceptions
75*10355SAli.Bahrami@Sun.COM#
76*10355SAli.Bahrami@Sun.COM# Locate the exceptions file and process its contents. We can't use
77*10355SAli.Bahrami@Sun.COM# onbld_elfmod::LoadExceptionsToEXRE() for this, because our exceptions
78*10355SAli.Bahrami@Sun.COM# need to support more than a single regular expression.
79*10355SAli.Bahrami@Sun.COM#
80*10355SAli.Bahrami@Sun.COM# exit:
81*10355SAli.Bahrami@Sun.COM#	@AddSymList, @DelSymList, and @EmptyTopVerList have been updated
82*10355SAli.Bahrami@Sun.COM#
83*10355SAli.Bahrami@Sun.COM# note:
84*10355SAli.Bahrami@Sun.COM#	We expand strings of the form MACH(dir) to match the given
85*10355SAli.Bahrami@Sun.COM#	directory as well as any 64-bit architecture subdirectory that
86*10355SAli.Bahrami@Sun.COM#	might be present (i.e. amd64, sparcv9).
87*10355SAli.Bahrami@Sun.COM#
88*10355SAli.Bahrami@Sun.COMsub LoadExceptions {
89*10355SAli.Bahrami@Sun.COM	my $file;
90*10355SAli.Bahrami@Sun.COM	my $Line;
91*10355SAli.Bahrami@Sun.COM	my $LineNum = 0;
92*10355SAli.Bahrami@Sun.COM	my $err = 0;
93*10355SAli.Bahrami@Sun.COM
94*10355SAli.Bahrami@Sun.COM	# Locate the exception file
95*10355SAli.Bahrami@Sun.COM	FILE: {
96*10355SAli.Bahrami@Sun.COM		# If -e is specified, that file must be used
97*10355SAli.Bahrami@Sun.COM		if ($opt{e}) {
98*10355SAli.Bahrami@Sun.COM			$file = $opt{e};
99*10355SAli.Bahrami@Sun.COM			last FILE;
100*10355SAli.Bahrami@Sun.COM		}
101*10355SAli.Bahrami@Sun.COM
102*10355SAli.Bahrami@Sun.COM		# If this is an activated workspace, use the exception
103*10355SAli.Bahrami@Sun.COM		# file found in the exceptions_list directory.
104*10355SAli.Bahrami@Sun.COM		if (defined($ENV{CODEMGR_WS})) {
105*10355SAli.Bahrami@Sun.COM			$file = "$ENV{CODEMGR_WS}/exception_lists/interface_cmp";
106*10355SAli.Bahrami@Sun.COM			last FILE if (-f $file);
107*10355SAli.Bahrami@Sun.COM		}
108*10355SAli.Bahrami@Sun.COM
109*10355SAli.Bahrami@Sun.COM		# As a final backstop, the SUNWonbld package provides a
110*10355SAli.Bahrami@Sun.COM		# copy of the exception file. This can be useful if we
111*10355SAli.Bahrami@Sun.COM		# are being used with an older workspace.
112*10355SAli.Bahrami@Sun.COM		#
113*10355SAli.Bahrami@Sun.COM		# This script is installed in the SUNWonbld bin directory,
114*10355SAli.Bahrami@Sun.COM		# while the exception file is in etc/exception_lists. Find
115*10355SAli.Bahrami@Sun.COM		# it relative to the script location given by $0.
116*10355SAli.Bahrami@Sun.COM		$file = dirname($0) . "/../etc/exception_lists/interface_cmp";
117*10355SAli.Bahrami@Sun.COM		last FILE if (-f $file);
118*10355SAli.Bahrami@Sun.COM
119*10355SAli.Bahrami@Sun.COM		# No exception file was found.
120*10355SAli.Bahrami@Sun.COM		return;
121*10355SAli.Bahrami@Sun.COM	}
122*10355SAli.Bahrami@Sun.COM
123*10355SAli.Bahrami@Sun.COM	open (EFILE, $file) ||
124*10355SAli.Bahrami@Sun.COM		die "$Prog: unable to open exceptions file: $file";
125*10355SAli.Bahrami@Sun.COM	while ($Line = onbld_elfmod::GetLine(\*EFILE, \$LineNum)) {
126*10355SAli.Bahrami@Sun.COM
127*10355SAli.Bahrami@Sun.COM		# Expand MACH()
128*10355SAli.Bahrami@Sun.COM		$Line =~ s/MACH\(([^)]+)\)/$1(\/amd64|\/sparcv9)?/g;
129*10355SAli.Bahrami@Sun.COM
130*10355SAli.Bahrami@Sun.COM		if ($Line =~ /^DELSYM\s+/) {
131*10355SAli.Bahrami@Sun.COM		    my ($item, $sym_re, $ver_re, $obj_re) =
132*10355SAli.Bahrami@Sun.COM			split(/\s+/, $Line, 4);
133*10355SAli.Bahrami@Sun.COM		    push @DelSymList, [ $sym_re, $ver_re, $obj_re ];
134*10355SAli.Bahrami@Sun.COM		    next;
135*10355SAli.Bahrami@Sun.COM		}
136*10355SAli.Bahrami@Sun.COM
137*10355SAli.Bahrami@Sun.COM		if ($Line =~ /^ADDSYM\s+/) {
138*10355SAli.Bahrami@Sun.COM		    my ($item, $sym_re, $ver_re, $obj_re) =
139*10355SAli.Bahrami@Sun.COM			split(/\s+/, $Line, 4);
140*10355SAli.Bahrami@Sun.COM		    push @AddSymList, [ $sym_re, $ver_re, $obj_re ];
141*10355SAli.Bahrami@Sun.COM		    next;
142*10355SAli.Bahrami@Sun.COM		}
143*10355SAli.Bahrami@Sun.COM
144*10355SAli.Bahrami@Sun.COM		if ($Line =~ /^EMPTY_TOPVERSION\s+/) {
145*10355SAli.Bahrami@Sun.COM		    my ($item, $ver_re, $obj_re) = split(/\s+/, $Line, 3);
146*10355SAli.Bahrami@Sun.COM		    push @EmptyTopVerList, [ $ver_re, $obj_re ];
147*10355SAli.Bahrami@Sun.COM		    next;
148*10355SAli.Bahrami@Sun.COM		}
149*10355SAli.Bahrami@Sun.COM
150*10355SAli.Bahrami@Sun.COM		$err++;
151*10355SAli.Bahrami@Sun.COM		printf(STDERR "$file: Unrecognized option: ".
152*10355SAli.Bahrami@Sun.COM		    "line $LineNum: $Line\n");
153*10355SAli.Bahrami@Sun.COM	}
154*10355SAli.Bahrami@Sun.COM	close EFILE;
155*10355SAli.Bahrami@Sun.COM
156*10355SAli.Bahrami@Sun.COM	exit 1 if ($err != 0);
157*10355SAli.Bahrami@Sun.COM}
158*10355SAli.Bahrami@Sun.COM
159*10355SAli.Bahrami@Sun.COM## ExSym(SymList, sym, ver, obj)
160*10355SAli.Bahrami@Sun.COM#
161*10355SAli.Bahrami@Sun.COM# Compare a given symbol/version/object combination against the
162*10355SAli.Bahrami@Sun.COM# exceptions found in the given list.
163*10355SAli.Bahrami@Sun.COM#
164*10355SAli.Bahrami@Sun.COM# entry:
165*10355SAli.Bahrami@Sun.COM#	SymList - Reference to @AddSymList, or @DelSymList.
166*10355SAli.Bahrami@Sun.COM#	sym, ver, obj - Combination to be compared against exception list
167*10355SAli.Bahrami@Sun.COM#
168*10355SAli.Bahrami@Sun.COM# exit:
169*10355SAli.Bahrami@Sun.COM#	Returns True (1) if there is a match, and False (0) otherwise.
170*10355SAli.Bahrami@Sun.COM#
171*10355SAli.Bahrami@Sun.COMsub ExSym {
172*10355SAli.Bahrami@Sun.COM	my ($SymList, $sym, $ver, $obj) = @_;
173*10355SAli.Bahrami@Sun.COM
174*10355SAli.Bahrami@Sun.COM	foreach my $ex (@$SymList) {
175*10355SAli.Bahrami@Sun.COM		return 1 if ($obj =~ /$$ex[2]/) && ($ver =~ /$$ex[1]/) &&
176*10355SAli.Bahrami@Sun.COM		    ($sym =~ /$$ex[0]/);
177*10355SAli.Bahrami@Sun.COM	}
178*10355SAli.Bahrami@Sun.COM
179*10355SAli.Bahrami@Sun.COM	return 0;
180*10355SAli.Bahrami@Sun.COM}
181*10355SAli.Bahrami@Sun.COM
182*10355SAli.Bahrami@Sun.COM## ExTopVer(ver, obj)
183*10355SAli.Bahrami@Sun.COM#
184*10355SAli.Bahrami@Sun.COM# Compare a given version/object combination against the pairs found
185*10355SAli.Bahrami@Sun.COM# in @EmptyTopVerList.
186*10355SAli.Bahrami@Sun.COM#
187*10355SAli.Bahrami@Sun.COM# entry:
188*10355SAli.Bahrami@Sun.COM#	ver, obj - Combination to be compared against empty top version list
189*10355SAli.Bahrami@Sun.COM#
190*10355SAli.Bahrami@Sun.COM# exit:
191*10355SAli.Bahrami@Sun.COM#	Returns True (1) if there is a match, and False (0) otherwise.
192*10355SAli.Bahrami@Sun.COM#
193*10355SAli.Bahrami@Sun.COMsub ExTopVer {
194*10355SAli.Bahrami@Sun.COM	my ($ver, $obj) = @_;
195*10355SAli.Bahrami@Sun.COM
196*10355SAli.Bahrami@Sun.COM	foreach my $ex (@EmptyTopVerList) {
197*10355SAli.Bahrami@Sun.COM		return 1 if ($obj =~ /$$ex[1]/) && ($ver =~ /$$ex[0]/);
198*10355SAli.Bahrami@Sun.COM	}
199*10355SAli.Bahrami@Sun.COM
200*10355SAli.Bahrami@Sun.COM	return 0;
201*10355SAli.Bahrami@Sun.COM}
202*10355SAli.Bahrami@Sun.COM
203*10355SAli.Bahrami@Sun.COM## ExpandInheritance(objhashref)
204*10355SAli.Bahrami@Sun.COM#
205*10355SAli.Bahrami@Sun.COM# For each version contained in the specified object hash reference,
206*10355SAli.Bahrami@Sun.COM# add the inherited symbols.
207*10355SAli.Bahrami@Sun.COM#
208*10355SAli.Bahrami@Sun.COMsub ExpandInheritance {
209*10355SAli.Bahrami@Sun.COM	my $obj = $_[0];
210*10355SAli.Bahrami@Sun.COM
211*10355SAli.Bahrami@Sun.COM	# Versions to process. Typically, inheriting versions come before
212*10355SAli.Bahrami@Sun.COM	# the versions they inherit. Processing the list in reverse order
213*10355SAli.Bahrami@Sun.COM	# maximizes the odds that a needed sub-version will have already
214*10355SAli.Bahrami@Sun.COM	# have been processed.
215*10355SAli.Bahrami@Sun.COM	my @vers = reverse(@{$obj->{'VERSION_NAMES'}});
216*10355SAli.Bahrami@Sun.COM
217*10355SAli.Bahrami@Sun.COM	# Versions to process in the next pass
218*10355SAli.Bahrami@Sun.COM	my @next_vers = ();
219*10355SAli.Bahrami@Sun.COM
220*10355SAli.Bahrami@Sun.COM	# Hash, indexed by version name, that reflects whether the version
221*10355SAli.Bahrami@Sun.COM	# has been expanded yet or not.
222*10355SAli.Bahrami@Sun.COM	my %done = ();
223*10355SAli.Bahrami@Sun.COM
224*10355SAli.Bahrami@Sun.COM	while (scalar(@vers) > 0) {
225*10355SAli.Bahrami@Sun.COM		foreach my $name (@vers) {
226*10355SAli.Bahrami@Sun.COM			my $i;
227*10355SAli.Bahrami@Sun.COM			my $defer = 0;
228*10355SAli.Bahrami@Sun.COM			my $cur_version = $obj->{'VERSION_INFO'}{$name};
229*10355SAli.Bahrami@Sun.COM			my ($top, $direct, $total, $symhash, $inheritarr) =
230*10355SAli.Bahrami@Sun.COM			    @{$cur_version};
231*10355SAli.Bahrami@Sun.COM
232*10355SAli.Bahrami@Sun.COM			# In order to expand this version, all the inherited
233*10355SAli.Bahrami@Sun.COM			# versions must already have been done. If not, put
234*10355SAli.Bahrami@Sun.COM			# this version on @next_vers for the next pass.
235*10355SAli.Bahrami@Sun.COM			my $num = scalar(@$inheritarr);
236*10355SAli.Bahrami@Sun.COM			for ($i = 0; $i < $num; $i++) {
237*10355SAli.Bahrami@Sun.COM			    if (!$done{$inheritarr->[$i]}) {
238*10355SAli.Bahrami@Sun.COM				$defer = 1;
239*10355SAli.Bahrami@Sun.COM				push @next_vers, $name;
240*10355SAli.Bahrami@Sun.COM				last;
241*10355SAli.Bahrami@Sun.COM			    }
242*10355SAli.Bahrami@Sun.COM			}
243*10355SAli.Bahrami@Sun.COM			next if ($defer);
244*10355SAli.Bahrami@Sun.COM
245*10355SAli.Bahrami@Sun.COM			# Add all the symbols from the inherited versions
246*10355SAli.Bahrami@Sun.COM			# to this one.
247*10355SAli.Bahrami@Sun.COM			for ($i = 0; $i < $num; $i++) {
248*10355SAli.Bahrami@Sun.COM				my $i_version =
249*10355SAli.Bahrami@Sun.COM				    $obj->{'VERSION_INFO'}{$inheritarr->[$i]};
250*10355SAli.Bahrami@Sun.COM				my $i_symhash = $i_version->[3];
251*10355SAli.Bahrami@Sun.COM
252*10355SAli.Bahrami@Sun.COM				foreach my $sym (keys %$i_symhash) {
253*10355SAli.Bahrami@Sun.COM				    if (!defined($cur_version->[3]{$sym})) {
254*10355SAli.Bahrami@Sun.COM					    $cur_version->[2]++;
255*10355SAli.Bahrami@Sun.COM					    $cur_version->[3]{$sym} = 'INHERIT';
256*10355SAli.Bahrami@Sun.COM				    }
257*10355SAli.Bahrami@Sun.COM				}
258*10355SAli.Bahrami@Sun.COM			}
259*10355SAli.Bahrami@Sun.COM
260*10355SAli.Bahrami@Sun.COM			$done{$name} = 1;
261*10355SAli.Bahrami@Sun.COM		}
262*10355SAli.Bahrami@Sun.COM
263*10355SAli.Bahrami@Sun.COM		@vers = @next_vers;
264*10355SAli.Bahrami@Sun.COM		@next_vers = ();
265*10355SAli.Bahrami@Sun.COM	}
266*10355SAli.Bahrami@Sun.COM}
267*10355SAli.Bahrami@Sun.COM
268*10355SAli.Bahrami@Sun.COM## ReadInterface(file, alias)
269*10355SAli.Bahrami@Sun.COM#
270*10355SAli.Bahrami@Sun.COM# Read the interface description file, as produced by interface_check, and
271*10355SAli.Bahrami@Sun.COM# return a hash describing it.
272*10355SAli.Bahrami@Sun.COM#
273*10355SAli.Bahrami@Sun.COM# entry:
274*10355SAli.Bahrami@Sun.COM#	file - Interface file to read.
275*10355SAli.Bahrami@Sun.COM#	alias - Refence to hash to be filled in with any aliases
276*10355SAli.Bahrami@Sun.COM#		that are seen in the file. The alias name is the key,
277*10355SAli.Bahrami@Sun.COM#		and the object is the value.
278*10355SAli.Bahrami@Sun.COM#
279*10355SAli.Bahrami@Sun.COM# exit:
280*10355SAli.Bahrami@Sun.COM#	The hash referenced by alias has been updated.
281*10355SAli.Bahrami@Sun.COM#
282*10355SAli.Bahrami@Sun.COM#	The return value is a hash that encapsulates the interface
283*10355SAli.Bahrami@Sun.COM#	information. This hash returned uses the object names as the
284*10355SAli.Bahrami@Sun.COM#	key. Each key references a sub-hash that contains information
285*10355SAli.Bahrami@Sun.COM#	for that object:
286*10355SAli.Bahrami@Sun.COM#
287*10355SAli.Bahrami@Sun.COM#	CLASS		-> ELFCLASS
288*10355SAli.Bahrami@Sun.COM#	TYPE		-> ELF type
289*10355SAli.Bahrami@Sun.COM#	VERSION_NAMES	-> Reference to array [1..n] of version names, in the
290*10355SAli.Bahrami@Sun.COM#			   order they come from the input file.
291*10355SAli.Bahrami@Sun.COM#	VERSION_INFO	-> Reference to hash indexed by version name, yielding
292*10355SAli.Bahrami@Sun.COM#			   a reference to an array containing information about
293*10355SAli.Bahrami@Sun.COM#			   that version.
294*10355SAli.Bahrami@Sun.COM#
295*10355SAli.Bahrami@Sun.COM#	The arrays referenced via VERSION_INFO are of the form:
296*10355SAli.Bahrami@Sun.COM#
297*10355SAli.Bahrami@Sun.COM#		(top, new, total, symhashref, inheritarrref)
298*10355SAli.Bahrami@Sun.COM#
299*10355SAli.Bahrami@Sun.COM#	where:
300*10355SAli.Bahrami@Sun.COM#		top - 1 if version is a TOP_VERSION, 0 for a regular VERSION
301*10355SAli.Bahrami@Sun.COM#		new - Number of symbols defined explicitly by version
302*10355SAli.Bahrami@Sun.COM#		total - Number of symbols included in version, both new,
303*10355SAli.Bahrami@Sun.COM#			and via inheritance.
304*10355SAli.Bahrami@Sun.COM#		symhashref - Reference to hash indexed by symbol names, and
305*10355SAli.Bahrami@Sun.COM#			yielding true (1).
306*10355SAli.Bahrami@Sun.COM#		inheritarrref - Reference to array of names of versions
307*10355SAli.Bahrami@Sun.COM#			inherited by this one.
308*10355SAli.Bahrami@Sun.COM#
309*10355SAli.Bahrami@Sun.COMsub ReadInterface {
310*10355SAli.Bahrami@Sun.COM	my ($file, $alias) = @_;
311*10355SAli.Bahrami@Sun.COM	my %main_hash = ();
312*10355SAli.Bahrami@Sun.COM	my $Line;
313*10355SAli.Bahrami@Sun.COM	my $LineNum = 0;
314*10355SAli.Bahrami@Sun.COM	my $obj_name;
315*10355SAli.Bahrami@Sun.COM	my $obj_hash;
316*10355SAli.Bahrami@Sun.COM	my $sym_ok = 0;
317*10355SAli.Bahrami@Sun.COM	my $cur_version;
318*10355SAli.Bahrami@Sun.COM
319*10355SAli.Bahrami@Sun.COM	open(FILE, $file) || die "$Prog: Unable to open: $file";
320*10355SAli.Bahrami@Sun.COM
321*10355SAli.Bahrami@Sun.COM	# Until we see an OBJECT line, nothing else is valid. To
322*10355SAli.Bahrami@Sun.COM	# simplify the error handling, use a simple initial loop to
323*10355SAli.Bahrami@Sun.COM	# read the file up to that point
324*10355SAli.Bahrami@Sun.COM	while ($Line = onbld_elfmod::GetLine(\*FILE, \$LineNum)) {
325*10355SAli.Bahrami@Sun.COM		if ($Line =~ s/^OBJECT\s+//i) {
326*10355SAli.Bahrami@Sun.COM		    $obj_name = $Line;
327*10355SAli.Bahrami@Sun.COM		    $main_hash{$obj_name} = {};
328*10355SAli.Bahrami@Sun.COM		    $obj_hash = $main_hash{$obj_name};
329*10355SAli.Bahrami@Sun.COM		    last;
330*10355SAli.Bahrami@Sun.COM		}
331*10355SAli.Bahrami@Sun.COM		die "$file: OBJECT expected on line $LineNum: $Line\n";
332*10355SAli.Bahrami@Sun.COM	}
333*10355SAli.Bahrami@Sun.COM
334*10355SAli.Bahrami@Sun.COM	# Read the remainder of the file
335*10355SAli.Bahrami@Sun.COM	while ($Line = onbld_elfmod::GetLine(\*FILE, \$LineNum)) {
336*10355SAli.Bahrami@Sun.COM		# Items are parsed in order of decreasing frequency
337*10355SAli.Bahrami@Sun.COM
338*10355SAli.Bahrami@Sun.COM		if ($Line =~
339*10355SAli.Bahrami@Sun.COM		    /^SYMBOL\s+([^\s]+)$/i) {
340*10355SAli.Bahrami@Sun.COM			my $sym = $1;
341*10355SAli.Bahrami@Sun.COM
342*10355SAli.Bahrami@Sun.COM			die "$file: SYMBOL not expected on line $LineNum: $Line\n"
343*10355SAli.Bahrami@Sun.COM			    if !$sym_ok;
344*10355SAli.Bahrami@Sun.COM
345*10355SAli.Bahrami@Sun.COM			$cur_version->[1]++;
346*10355SAli.Bahrami@Sun.COM			$cur_version->[2]++;
347*10355SAli.Bahrami@Sun.COM			$cur_version->[3]{$sym} = 'NEW';
348*10355SAli.Bahrami@Sun.COM			next;
349*10355SAli.Bahrami@Sun.COM		}
350*10355SAli.Bahrami@Sun.COM
351*10355SAli.Bahrami@Sun.COM		if ($Line =~ /^((TOP_)?VERSION)\s+([^\s]+)(\s+\{(.*)\})?\s*$/i) {
352*10355SAli.Bahrami@Sun.COM			my ($top, $name, $inherit) = ($2, $3, $5);
353*10355SAli.Bahrami@Sun.COM
354*10355SAli.Bahrami@Sun.COM			$top = defined($top) ? 1 : 0;
355*10355SAli.Bahrami@Sun.COM
356*10355SAli.Bahrami@Sun.COM			my @inheritarr = defined($inherit) ?
357*10355SAli.Bahrami@Sun.COM			    split /[,{\s]+/, $inherit : ();
358*10355SAli.Bahrami@Sun.COM
359*10355SAli.Bahrami@Sun.COM			$cur_version = [ $top, 0, 0, {}, \@inheritarr ];
360*10355SAli.Bahrami@Sun.COM			$obj_hash->{'VERSION_INFO'}{$name} = $cur_version;
361*10355SAli.Bahrami@Sun.COM
362*10355SAli.Bahrami@Sun.COM			push @{$obj_hash->{'VERSION_NAMES'}}, $name;
363*10355SAli.Bahrami@Sun.COM			$sym_ok = 1;
364*10355SAli.Bahrami@Sun.COM			next;
365*10355SAli.Bahrami@Sun.COM		}
366*10355SAli.Bahrami@Sun.COM
367*10355SAli.Bahrami@Sun.COM		if ($Line =~ /^OBJECT\s+([^\s]+)$/i) {
368*10355SAli.Bahrami@Sun.COM		    my $prev_obj_hash = $obj_hash;
369*10355SAli.Bahrami@Sun.COM		    $obj_name = $1;
370*10355SAli.Bahrami@Sun.COM		    $main_hash{$obj_name} = {};
371*10355SAli.Bahrami@Sun.COM		    $obj_hash = $main_hash{$obj_name};
372*10355SAli.Bahrami@Sun.COM
373*10355SAli.Bahrami@Sun.COM		    # Expand the versions for the object just processed
374*10355SAli.Bahrami@Sun.COM		    ExpandInheritance($prev_obj_hash);
375*10355SAli.Bahrami@Sun.COM		    next;
376*10355SAli.Bahrami@Sun.COM		}
377*10355SAli.Bahrami@Sun.COM
378*10355SAli.Bahrami@Sun.COM		if ($Line =~ /^CLASS\s+([^\s]+)$/i) {
379*10355SAli.Bahrami@Sun.COM			$obj_hash->{'CLASS'} = $1;
380*10355SAli.Bahrami@Sun.COM			next;
381*10355SAli.Bahrami@Sun.COM		}
382*10355SAli.Bahrami@Sun.COM
383*10355SAli.Bahrami@Sun.COM		if ($Line =~ /^TYPE\s+([^\s]+)$/i) {
384*10355SAli.Bahrami@Sun.COM			$obj_hash->{'TYPE'} = $1;
385*10355SAli.Bahrami@Sun.COM			next;
386*10355SAli.Bahrami@Sun.COM		}
387*10355SAli.Bahrami@Sun.COM
388*10355SAli.Bahrami@Sun.COM		if ($Line =~ /^ALIAS\s+([^\s]+)$/i) {
389*10355SAli.Bahrami@Sun.COM			$$alias{$1} = $obj_name;
390*10355SAli.Bahrami@Sun.COM			next;
391*10355SAli.Bahrami@Sun.COM		}
392*10355SAli.Bahrami@Sun.COM
393*10355SAli.Bahrami@Sun.COM		die "$file: unrecognized item on line $LineNum: $Line\n";
394*10355SAli.Bahrami@Sun.COM	}
395*10355SAli.Bahrami@Sun.COM	close FILE;
396*10355SAli.Bahrami@Sun.COM
397*10355SAli.Bahrami@Sun.COM	# Expand the versions for the final object from the file
398*10355SAli.Bahrami@Sun.COM	ExpandInheritance($obj_hash);
399*10355SAli.Bahrami@Sun.COM
400*10355SAli.Bahrami@Sun.COM	return %main_hash;
401*10355SAli.Bahrami@Sun.COM}
402*10355SAli.Bahrami@Sun.COM
403*10355SAli.Bahrami@Sun.COM## PrintInterface(main_hash, alias)
404*10355SAli.Bahrami@Sun.COM#
405*10355SAli.Bahrami@Sun.COM# Dump the contents of main_hash and alias to stdout in the same format
406*10355SAli.Bahrami@Sun.COM# used by interface_check to produce the input interface file. This output
407*10355SAli.Bahrami@Sun.COM# should diff cleanly against the original (ignoring the header comments).
408*10355SAli.Bahrami@Sun.COM#
409*10355SAli.Bahrami@Sun.COMsub PrintInterface {
410*10355SAli.Bahrami@Sun.COM	my ($main_hash, $alias_hash) = @_;
411*10355SAli.Bahrami@Sun.COM
412*10355SAli.Bahrami@Sun.COM	foreach my $obj (sort keys %$main_hash) {
413*10355SAli.Bahrami@Sun.COM		print "OBJECT\t$obj\n";
414*10355SAli.Bahrami@Sun.COM		print "CLASS\t$main_hash->{$obj}{'CLASS'}\n";
415*10355SAli.Bahrami@Sun.COM		print "TYPE\t$main_hash->{$obj}{'TYPE'}\n";
416*10355SAli.Bahrami@Sun.COM
417*10355SAli.Bahrami@Sun.COM		# This is inefficient, but good enough for debugging
418*10355SAli.Bahrami@Sun.COM		# Look at all the aliases and print those that belong
419*10355SAli.Bahrami@Sun.COM		# to this object.
420*10355SAli.Bahrami@Sun.COM		foreach my $alias (sort keys %$alias_hash) {
421*10355SAli.Bahrami@Sun.COM			print "ALIAS\t$alias\n"
422*10355SAli.Bahrami@Sun.COM			    if ($obj eq $alias_hash->{$alias});
423*10355SAli.Bahrami@Sun.COM		}
424*10355SAli.Bahrami@Sun.COM
425*10355SAli.Bahrami@Sun.COM		next if !defined($main_hash->{$obj}{'VERSION_NAMES'});
426*10355SAli.Bahrami@Sun.COM
427*10355SAli.Bahrami@Sun.COM		my $num = scalar(@{$main_hash->{$obj}{'VERSION_NAMES'}});
428*10355SAli.Bahrami@Sun.COM		my $i;
429*10355SAli.Bahrami@Sun.COM		for ($i = 0; $i < $num; $i++) {
430*10355SAli.Bahrami@Sun.COM			my $name = $main_hash->{$obj}{'VERSION_NAMES'}[$i];
431*10355SAli.Bahrami@Sun.COM			my ($top, $direct, $total, $symhash, $inheritarr) =
432*10355SAli.Bahrami@Sun.COM			    @{$main_hash->{$obj}{'VERSION_INFO'}{$name}};
433*10355SAli.Bahrami@Sun.COM
434*10355SAli.Bahrami@Sun.COM			$top = $top ? "TOP_" : '';
435*10355SAli.Bahrami@Sun.COM
436*10355SAli.Bahrami@Sun.COM			my $inherit = (scalar(@$inheritarr) > 0) ?
437*10355SAli.Bahrami@Sun.COM			    "\t{" . join(', ', @{$inheritarr}) . "}" : '';
438*10355SAli.Bahrami@Sun.COM
439*10355SAli.Bahrami@Sun.COM			print "${top}VERSION\t$name$inherit\n";
440*10355SAli.Bahrami@Sun.COM
441*10355SAli.Bahrami@Sun.COM			foreach my $sym (sort keys %$symhash) {
442*10355SAli.Bahrami@Sun.COM				print "\t$symhash->{$sym}\t$sym\n";
443*10355SAli.Bahrami@Sun.COM			}
444*10355SAli.Bahrami@Sun.COM		}
445*10355SAli.Bahrami@Sun.COM	}
446*10355SAli.Bahrami@Sun.COM}
447*10355SAli.Bahrami@Sun.COM
448*10355SAli.Bahrami@Sun.COM## compare()
449*10355SAli.Bahrami@Sun.COM#
450*10355SAli.Bahrami@Sun.COM# Compare the old interface definition contained in (%old_hash, %old_alias)
451*10355SAli.Bahrami@Sun.COM# with the new interface contained in (%new_hash, %new_alias).
452*10355SAli.Bahrami@Sun.COM#
453*10355SAli.Bahrami@Sun.COMsub compare {
454*10355SAli.Bahrami@Sun.COM	foreach my $old_obj (sort keys %old_hash) {
455*10355SAli.Bahrami@Sun.COM		my $new_obj = $old_obj;
456*10355SAli.Bahrami@Sun.COM		my $Ttl = 0;
457*10355SAli.Bahrami@Sun.COM
458*10355SAli.Bahrami@Sun.COM		# If the object does not exist in the new interface,
459*10355SAli.Bahrami@Sun.COM		# then see if there's an alias for it. Failing that,
460*10355SAli.Bahrami@Sun.COM		# we simply ignore the object.
461*10355SAli.Bahrami@Sun.COM		if (!defined($new_hash{$new_obj})) {
462*10355SAli.Bahrami@Sun.COM			next if !defined($new_alias{$new_obj});
463*10355SAli.Bahrami@Sun.COM			$new_obj = $new_alias{$new_obj};
464*10355SAli.Bahrami@Sun.COM		}
465*10355SAli.Bahrami@Sun.COM
466*10355SAli.Bahrami@Sun.COM		my $old = $old_hash{$old_obj};
467*10355SAli.Bahrami@Sun.COM		my $new = $new_hash{$new_obj};
468*10355SAli.Bahrami@Sun.COM
469*10355SAli.Bahrami@Sun.COM		# Every version in the old object must exist in the new object,
470*10355SAli.Bahrami@Sun.COM		# and there must be exactly the same symbols in each.
471*10355SAli.Bahrami@Sun.COM		my $num = scalar(@{$old->{'VERSION_NAMES'}});
472*10355SAli.Bahrami@Sun.COM		for (my $i = 0; $i < $num; $i++) {
473*10355SAli.Bahrami@Sun.COM			my $name = $old->{'VERSION_NAMES'}[$i];
474*10355SAli.Bahrami@Sun.COM
475*10355SAli.Bahrami@Sun.COM			# New object must have this version
476*10355SAli.Bahrami@Sun.COM			if (!defined($new->{'VERSION_INFO'}{$name})) {
477*10355SAli.Bahrami@Sun.COM				onbld_elfmod::OutMsg2(\*STDOUT, \$Ttl, $old_obj,
478*10355SAli.Bahrami@Sun.COM				    $new_obj, "$name: deleted version");
479*10355SAli.Bahrami@Sun.COM				next;
480*10355SAli.Bahrami@Sun.COM			}
481*10355SAli.Bahrami@Sun.COM
482*10355SAli.Bahrami@Sun.COM			my ($old_top, $old_direct, $old_total, $old_symhash) =
483*10355SAli.Bahrami@Sun.COM			    @{$old->{'VERSION_INFO'}{$name}};
484*10355SAli.Bahrami@Sun.COM			my ($new_top, $new_direct, $new_total, $new_symhash) =
485*10355SAli.Bahrami@Sun.COM			    @{$new->{'VERSION_INFO'}{$name}};
486*10355SAli.Bahrami@Sun.COM
487*10355SAli.Bahrami@Sun.COM			# If this is an empty top version, and the old object
488*10355SAli.Bahrami@Sun.COM			# has the EMPTY_TOPVERSION exception set, then we
489*10355SAli.Bahrami@Sun.COM			# skip it as if it were not present.
490*10355SAli.Bahrami@Sun.COM			next if $old_top && ($old_direct == 0) &&
491*10355SAli.Bahrami@Sun.COM			    ExTopVer($name, $old_obj);
492*10355SAli.Bahrami@Sun.COM
493*10355SAli.Bahrami@Sun.COM			# We check that every symbol in the old object is
494*10355SAli.Bahrami@Sun.COM			# in the new one to detect deleted symbols. We then
495*10355SAli.Bahrami@Sun.COM			# check that every symbol in the new object is also
496*10355SAli.Bahrami@Sun.COM			# in the old object, to find added symbols. If the
497*10355SAli.Bahrami@Sun.COM			# "deleted" check is clean, and the two objects have
498*10355SAli.Bahrami@Sun.COM			# the same number of symbols in their versions, then we
499*10355SAli.Bahrami@Sun.COM			# can skip the "added" test, because we know that
500*10355SAli.Bahrami@Sun.COM			# there is no room for an addition to have happened.
501*10355SAli.Bahrami@Sun.COM			# Since most objects satisfy these constraints, we
502*10355SAli.Bahrami@Sun.COM			# end up doing roughly half the number of comparisons
503*10355SAli.Bahrami@Sun.COM			# that would otherwise be needed.
504*10355SAli.Bahrami@Sun.COM			my $check_added_syms =
505*10355SAli.Bahrami@Sun.COM			    ($old_total == $new_total) ? 0: 1;
506*10355SAli.Bahrami@Sun.COM
507*10355SAli.Bahrami@Sun.COM			# Every symbol in the old version must be in the new one
508*10355SAli.Bahrami@Sun.COM			foreach my $sym (sort keys %$old_symhash) {
509*10355SAli.Bahrami@Sun.COM				if (!defined($new_symhash->{$sym})) {
510*10355SAli.Bahrami@Sun.COM					onbld_elfmod::OutMsg2(\*STDOUT,
511*10355SAli.Bahrami@Sun.COM					   \$Ttl, $old_obj, $new_obj,
512*10355SAli.Bahrami@Sun.COM					   "$name: deleted interface: $sym")
513*10355SAli.Bahrami@Sun.COM					    if !ExSym(\@DelSymList,
514*10355SAli.Bahrami@Sun.COM						      $sym, $name, $new_obj);
515*10355SAli.Bahrami@Sun.COM					$check_added_syms = 1;
516*10355SAli.Bahrami@Sun.COM				}
517*10355SAli.Bahrami@Sun.COM			}
518*10355SAli.Bahrami@Sun.COM
519*10355SAli.Bahrami@Sun.COM			# Do the "added" check, unless we can optimize it away.
520*10355SAli.Bahrami@Sun.COM			# Every symbol in the new version must be in the old one.
521*10355SAli.Bahrami@Sun.COM			if ($check_added_syms) {
522*10355SAli.Bahrami@Sun.COM				foreach my $sym (sort keys %$new_symhash) {
523*10355SAli.Bahrami@Sun.COM				    if (!defined($old_symhash->{$sym})) {
524*10355SAli.Bahrami@Sun.COM					next if ExSym(\@AddSymList,
525*10355SAli.Bahrami@Sun.COM					    $sym, $name, $new_obj);
526*10355SAli.Bahrami@Sun.COM					onbld_elfmod::OutMsg2(\*STDOUT,
527*10355SAli.Bahrami@Sun.COM					       \$Ttl, $old_obj, $new_obj,
528*10355SAli.Bahrami@Sun.COM					       "$name: added interface: $sym");
529*10355SAli.Bahrami@Sun.COM				    }
530*10355SAli.Bahrami@Sun.COM				}
531*10355SAli.Bahrami@Sun.COM			}
532*10355SAli.Bahrami@Sun.COM
533*10355SAli.Bahrami@Sun.COM			# We want to ensure that version numbers in an
534*10355SAli.Bahrami@Sun.COM			# inheritance chain don't go up by more than 1 in
535*10355SAli.Bahrami@Sun.COM			# any given release. If the version names are in the
536*10355SAli.Bahrami@Sun.COM			# standard SUNW_x.y[.z] format, we can compare the
537*10355SAli.Bahrami@Sun.COM			# two top versions and see if this has happened.
538*10355SAli.Bahrami@Sun.COM			#
539*10355SAli.Bahrami@Sun.COM			# For a given SUNW_x.y[.z], valid sucessors would
540*10355SAli.Bahrami@Sun.COM			# be SUNW_x.(y+1) or SUNW_x.y.(z+1), where z is
541*10355SAli.Bahrami@Sun.COM			# assumed to be 0 if not present.
542*10355SAli.Bahrami@Sun.COM			#
543*10355SAli.Bahrami@Sun.COM			# This check only makes sense when the new interface
544*10355SAli.Bahrami@Sun.COM			# is a direct decendent of the old one, as specified
545*10355SAli.Bahrami@Sun.COM			# via the -d option. If the two interfaces are more
546*10355SAli.Bahrami@Sun.COM			# than one release apart, we should not do this test.
547*10355SAli.Bahrami@Sun.COM			if ($opt{d} && $old_top && !$new_top &&
548*10355SAli.Bahrami@Sun.COM			    ($name =~ /^SUNW_(\d+)\.(\d+)(\.(\d+))?/)) {
549*10355SAli.Bahrami@Sun.COM				my $iname1 = "SUNW_$1." . ($2 + 1);
550*10355SAli.Bahrami@Sun.COM				my $iname2;
551*10355SAli.Bahrami@Sun.COM				if (defined($4)) {
552*10355SAli.Bahrami@Sun.COM			    		$iname2 = "SUNW_$1.$2." . ($4 + 1);
553*10355SAli.Bahrami@Sun.COM				} else {
554*10355SAli.Bahrami@Sun.COM			    		$iname2 = "SUNW_$1.$2.1";
555*10355SAli.Bahrami@Sun.COM				}
556*10355SAli.Bahrami@Sun.COM
557*10355SAli.Bahrami@Sun.COM				if (defined($new->{'VERSION_INFO'}{$iname1}) ||
558*10355SAli.Bahrami@Sun.COM				    defined($new->{'VERSION_INFO'}{$iname2})) {
559*10355SAli.Bahrami@Sun.COM					my $i_top =
560*10355SAli.Bahrami@Sun.COM					    $new->{'VERSION_INFO'}{$iname1}[0] ||
561*10355SAli.Bahrami@Sun.COM					    $new->{'VERSION_INFO'}{$iname2}[0];
562*10355SAli.Bahrami@Sun.COM					if (!$i_top) {
563*10355SAli.Bahrami@Sun.COM						onbld_elfmod::OutMsg2(\*STDOUT,
564*10355SAli.Bahrami@Sun.COM						    \$Ttl, $old_obj, $new_obj,
565*10355SAli.Bahrami@Sun.COM						    "$name: inconsistant " .
566*10355SAli.Bahrami@Sun.COM						    "version increment: " .
567*10355SAli.Bahrami@Sun.COM						    "expect $iname1 or $iname2 ".
568*10355SAli.Bahrami@Sun.COM						    "to replace top version");
569*10355SAli.Bahrami@Sun.COM					}
570*10355SAli.Bahrami@Sun.COM				} else {
571*10355SAli.Bahrami@Sun.COM 					onbld_elfmod::OutMsg2(\*STDOUT,
572*10355SAli.Bahrami@Sun.COM					    \$Ttl, $old_obj, $new_obj,
573*10355SAli.Bahrami@Sun.COM				            "$name: expected superseding " .
574*10355SAli.Bahrami@Sun.COM					    "top version to $name not " .
575*10355SAli.Bahrami@Sun.COM					    "present: $iname1 or $iname2");
576*10355SAli.Bahrami@Sun.COM				}
577*10355SAli.Bahrami@Sun.COM			}
578*10355SAli.Bahrami@Sun.COM		}
579*10355SAli.Bahrami@Sun.COM
580*10355SAli.Bahrami@Sun.COM
581*10355SAli.Bahrami@Sun.COM		# Empty versions in the established interface description
582*10355SAli.Bahrami@Sun.COM		# are usually the result of fixing a versioning mistake
583*10355SAli.Bahrami@Sun.COM		# at some point in the past. These versions are part of
584*10355SAli.Bahrami@Sun.COM		# the public record, and cannot be changed now. However, if
585*10355SAli.Bahrami@Sun.COM		# comparing two interface descriptions from the same gate,
586*10355SAli.Bahrami@Sun.COM		# flag any empty versions in the new interface description
587*10355SAli.Bahrami@Sun.COM		# that are not present in the old one. These have yet to
588*10355SAli.Bahrami@Sun.COM		# become part of the official interface, and should be removed
589*10355SAli.Bahrami@Sun.COM		# before they do.
590*10355SAli.Bahrami@Sun.COM		next if !$opt{d};
591*10355SAli.Bahrami@Sun.COM
592*10355SAli.Bahrami@Sun.COM		$num = scalar(@{$new->{'VERSION_NAMES'}});
593*10355SAli.Bahrami@Sun.COM		for (my $i = 0; $i < $num; $i++) {
594*10355SAli.Bahrami@Sun.COM			my $name = $new->{'VERSION_NAMES'}[$i];
595*10355SAli.Bahrami@Sun.COM
596*10355SAli.Bahrami@Sun.COM			# If old object has this version, skip it
597*10355SAli.Bahrami@Sun.COM			next if defined($old->{'VERSION_INFO'}{$name});
598*10355SAli.Bahrami@Sun.COM
599*10355SAli.Bahrami@Sun.COM			# If explicitly whitelisted, skip it
600*10355SAli.Bahrami@Sun.COM			next if ExTopVer($name, $new_obj);
601*10355SAli.Bahrami@Sun.COM
602*10355SAli.Bahrami@Sun.COM			my ($new_top, $new_direct, $new_total, $new_symhash) =
603*10355SAli.Bahrami@Sun.COM			    @{$new->{'VERSION_INFO'}{$name}};
604*10355SAli.Bahrami@Sun.COM
605*10355SAli.Bahrami@Sun.COM			if ($new_direct == 0) {
606*10355SAli.Bahrami@Sun.COM				onbld_elfmod::OutMsg2(\*STDOUT,
607*10355SAli.Bahrami@Sun.COM				    \$Ttl, $old_obj, $new_obj,
608*10355SAli.Bahrami@Sun.COM				    "$name: invalid empty new version");
609*10355SAli.Bahrami@Sun.COM			}
610*10355SAli.Bahrami@Sun.COM		}
611*10355SAli.Bahrami@Sun.COM	}
612*10355SAli.Bahrami@Sun.COM
613*10355SAli.Bahrami@Sun.COM}
614*10355SAli.Bahrami@Sun.COM
615*10355SAli.Bahrami@Sun.COM
616*10355SAli.Bahrami@Sun.COM
617*10355SAli.Bahrami@Sun.COM# -----------------------------------------------------------------------------
618*10355SAli.Bahrami@Sun.COM
619*10355SAli.Bahrami@Sun.COM# Establish a program name for any error diagnostics.
620*10355SAli.Bahrami@Sun.COMchomp($Prog = `basename $0`);
621*10355SAli.Bahrami@Sun.COM
622*10355SAli.Bahrami@Sun.COM# The onbld_elfmod package is maintained in the same directory as this
623*10355SAli.Bahrami@Sun.COM# script, and is installed in ../lib/perl. Use the local one if present,
624*10355SAli.Bahrami@Sun.COM# and the installed one otherwise.
625*10355SAli.Bahrami@Sun.COMmy $moddir = dirname($0);
626*10355SAli.Bahrami@Sun.COM$moddir = "$moddir/../lib/perl" if ! -f "$moddir/onbld_elfmod.pm";
627*10355SAli.Bahrami@Sun.COMrequire "$moddir/onbld_elfmod.pm";
628*10355SAli.Bahrami@Sun.COM
629*10355SAli.Bahrami@Sun.COM# Check that we have arguments. Normally, 2 plain arguments are required,
630*10355SAli.Bahrami@Sun.COM# but if -t is present, only one is allowed.
631*10355SAli.Bahrami@Sun.COMif ((getopts('de:ot', \%opt) == 0) || (scalar(@ARGV) != ($opt{t} ? 1 : 2))) {
632*10355SAli.Bahrami@Sun.COM	print "usage: $Prog [-dot] [-e exfile] old new\n";
633*10355SAli.Bahrami@Sun.COM	print "\t[-d]\t\tnew is a direct decendent of old\n";
634*10355SAli.Bahrami@Sun.COM	print "\t[-e exfile]\texceptions file\n";
635*10355SAli.Bahrami@Sun.COM	print "\t[-o]\t\tproduce one-liner output (prefixed with pathname)\n";
636*10355SAli.Bahrami@Sun.COM	print "\t[-t]\tParse old, and recreate to stdout\n";
637*10355SAli.Bahrami@Sun.COM	exit 1;
638*10355SAli.Bahrami@Sun.COM}
639*10355SAli.Bahrami@Sun.COM
640*10355SAli.Bahrami@Sun.COM# Locate and process the exceptions file
641*10355SAli.Bahrami@Sun.COMLoadExceptions();
642*10355SAli.Bahrami@Sun.COM
643*10355SAli.Bahrami@Sun.COM%old_alias = ();
644*10355SAli.Bahrami@Sun.COM%old_hash = ReadInterface($ARGV[0], \%old_alias);
645*10355SAli.Bahrami@Sun.COM
646*10355SAli.Bahrami@Sun.COM# If -t is present, only one argument is allowed --- we parse it, and then
647*10355SAli.Bahrami@Sun.COM# print the same information back to stderr in the same format as the original.
648*10355SAli.Bahrami@Sun.COM# This is useful for debugging, to verify that the parsing is correct.
649*10355SAli.Bahrami@Sun.COMif ($opt{t}) {
650*10355SAli.Bahrami@Sun.COM	PrintInterface(\%old_hash, \%old_alias);
651*10355SAli.Bahrami@Sun.COM	exit 0;
652*10355SAli.Bahrami@Sun.COM}
653*10355SAli.Bahrami@Sun.COM
654*10355SAli.Bahrami@Sun.COM%new_alias = ();
655*10355SAli.Bahrami@Sun.COM%new_hash = ReadInterface($ARGV[1], \%new_alias);
656*10355SAli.Bahrami@Sun.COM
657*10355SAli.Bahrami@Sun.COMcompare();
658*10355SAli.Bahrami@Sun.COM
659*10355SAli.Bahrami@Sun.COMexit 0;
660