diff options
Diffstat (limited to 'lib/ver2def.pl')
-rwxr-xr-x | lib/ver2def.pl | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/ver2def.pl b/lib/ver2def.pl new file mode 100755 index 0000000..18231bc --- /dev/null +++ b/lib/ver2def.pl @@ -0,0 +1,47 @@ +#!/usr/bin/perl +use strict; +use warnings; +die "Usage: $0 script.ver dllname build.def import.def\n" if @ARGV != 4; +my ($verfile, $dllname, $builddef, $importdef) = @ARGV; +open my $verfh, '<', $verfile or die "Cannot open input file $verfile: $!\n"; +my $input = join '', <$verfh>; +close $verfh; +my @syms; +my (%cnt, %last, %ords); +$input =~ s/\/\*.*?\*\///sg; # Remove C comments +while ($input =~ m/(\S+)\s*\{((?:[^\{\}]|\{(?2)\})+)\}\s*;/sg) { # Split {...} + my ($ver, $block) = ($1, $2); + while ($block =~ s/(\S+)\s*:((?:[^\{\}:]|\{(?2)\})+)$//sg) { # Split section: + my ($section, $syms) = ($1, $2); + next if $section ne 'global'; + $syms =~ s/\s+//g; + foreach (split /;\s*/, $syms) { # Split symbols + $cnt{$_}++; + $last{$_} = $ver; + push @syms, [$_, $ver]; + } + } +} +open my $importfh, '>', $importdef or die "Cannot open output file $importdef: $!\n"; +open my $buildfh, '>', $builddef or die "Cannot open output file $builddef: $!\n"; +print $importfh "LIBRARY \"$dllname\"\n"; +print $importfh "EXPORTS\n"; +print $buildfh "EXPORTS\n"; +my $ord = 1; +foreach (@syms) { + my ($sym, $ver) = @{$_}; + print $importfh "\"$sym\@$ver\" \@$ord\n"; + if ($last{$sym} ne $ver) { + print $buildfh "\"$sym\@$ver\" \@$ord\n"; + } else { + $ords{$sym} = $ord; + print $buildfh "\"$sym\@$ver\" = " . (($cnt{$sym} > 1) ? "\"$sym\@\@$ver\"" : $sym) . " \@$ord\n" + } + $ord++; +} +# GNU dlltool has broken calculation of ordinals for aliased symbols, so specify ordinals explicitly +# GNU LD prior 2.21 has broken handling of symbols with dot character +# Operator == for defining symbol alias is supported since GNU dlltool 2.21 +print $importfh "$_ \@$ords{$_} == \"$_\@$last{$_}\"\n" foreach sort keys %last; +close $importfh; +close $buildfh; |