xref: /aosp_15_r20/external/pciutils/lib/ver2def.pl (revision c2e0c6b56a71da9abe8df5c8348fb3eb5c2c9251)
1#!/usr/bin/perl
2use strict;
3use warnings;
4die "Usage: $0 script.ver dllname build.def import.def\n" if @ARGV != 4;
5my ($verfile, $dllname, $builddef, $importdef) = @ARGV;
6open my $verfh, '<', $verfile or die "Cannot open input file $verfile: $!\n";
7my $input = join '', <$verfh>;
8close $verfh;
9my @syms;
10my (%cnt, %last, %ords);
11$input =~ s/\/\*.*?\*\///sg; # Remove C comments
12while ($input =~ m/(\S+)\s*\{((?:[^\{\}]|\{(?2)\})+)\}\s*;/sg) { # Split {...}
13	my ($ver, $block) = ($1, $2);
14	while ($block =~ s/(\S+)\s*:((?:[^\{\}:]|\{(?2)\})+)$//sg) { # Split section:
15		my ($section, $syms) = ($1, $2);
16		next if $section ne 'global';
17		$syms =~ s/\s+//g;
18		foreach (split /;\s*/, $syms) { # Split symbols
19			$cnt{$_}++;
20			$last{$_} = $ver;
21			push @syms, [$_, $ver];
22		}
23	}
24}
25open my $importfh, '>', $importdef or die "Cannot open output file $importdef: $!\n";
26open my $buildfh, '>', $builddef or die "Cannot open output file $builddef: $!\n";
27print $importfh "LIBRARY \"$dllname\"\n";
28print $importfh "EXPORTS\n";
29print $buildfh "EXPORTS\n";
30my $ord = 1;
31foreach (@syms) {
32	my ($sym, $ver) = @{$_};
33	print $importfh "\"$sym\@$ver\" \@$ord\n";
34	if ($last{$sym} ne $ver) {
35		print $buildfh "\"$sym\@$ver\" \@$ord\n";
36	} else {
37		$ords{$sym} = $ord;
38		print $buildfh "\"$sym\@$ver\" = " . (($cnt{$sym} > 1) ? "\"$sym\@\@$ver\"" : $sym) . " \@$ord\n"
39	}
40	$ord++;
41}
42# GNU dlltool has broken calculation of ordinals for aliased symbols, so specify ordinals explicitly
43# GNU LD prior 2.21 has broken handling of symbols with dot character
44# Operator == for defining symbol alias is supported since GNU dlltool 2.21
45print $importfh "$_ \@$ords{$_} == \"$_\@$last{$_}\"\n" foreach sort keys %last;
46close $importfh;
47close $buildfh;
48