mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com> Acked-by: Andrew Cooper <Andrew.Cooper3@citrix.com> Acked-by: Christian Lindig <christian.lindig@citrix.com>
108 lines
3.0 KiB
Perl
Executable File
108 lines
3.0 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
|
|
use strict;
|
|
use Data::Dumper;
|
|
|
|
our %enums;
|
|
|
|
# Usage: abi-check C-file Ocaml-file
|
|
# Writes out a BUILD_BUG_ON() list to be included back into C.
|
|
#
|
|
# Ocaml-file should be the .ml file. The ocaml compiler will check
|
|
# that any declarations in a .mli correspond. We check the .ml
|
|
# rather than the .mli in case there are private types in future.
|
|
|
|
@ARGV == 2 or die;
|
|
our ($c, $o) = @ARGV;
|
|
|
|
open C_FILE, "<", $c or die $!;
|
|
|
|
our $cline = -1;
|
|
our $ei;
|
|
|
|
# Parse the C file looking for calls to:
|
|
# c_bitmap_to_ocaml_list()
|
|
# ocaml_list_to_c_bitmap()
|
|
#
|
|
# followed by anotations of the following form:
|
|
# /* ! OType OPrefix Mangle */
|
|
# /* ! CPrefix CFinal CFinalHow */
|
|
# or, for subsequent invocations for the same OType, just
|
|
# /* ! OType */
|
|
#
|
|
# The function definitions use /* ! */ which simply skips that instance.
|
|
while (<C_FILE>) {
|
|
if ($cline == -1) {
|
|
if (m/c_bitmap_to_ocaml_list|ocaml_list_to_c_bitmap/) {
|
|
$cline = 0;
|
|
$ei = { };
|
|
}
|
|
} else {
|
|
$cline++;
|
|
m{^\s+/\* \s+ ! \s+ (.*?) \s* \*/\s*$}x or
|
|
die "at line $cline of annotation, did not expect $_ ?";
|
|
my @vals = split /\s+/, $1;
|
|
if ($cline == 1 && !@vals) {
|
|
$cline = -1;
|
|
} elsif ($cline == 1 && @vals == 1) {
|
|
my ($otype) = @vals;
|
|
die "reference to undefined OType $otype" unless $enums{$otype};
|
|
} elsif ($cline == 1 && @vals == 3) {
|
|
$ei->{$_} = shift @vals foreach qw(OType OPrefix Mangle);
|
|
} elsif ($cline == 2 && @vals == 3) {
|
|
$ei->{$_} = shift @vals foreach qw(CPrefix CFinal CFinalHow);
|
|
die "redefining OType $ei->{OType}" if $enums{ $ei->{OType} };
|
|
$enums{ $ei->{OType} } = $ei;
|
|
$cline = -1;
|
|
} else {
|
|
die "$_ ?";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub expect ($$) {
|
|
printf "BUILD_BUG_ON( %-30s != %-10s );\n", @_ or die $!;
|
|
}
|
|
|
|
open OCAML_FILE, "<", $o or die $!;
|
|
my $cval;
|
|
$ei = undef;
|
|
my $bitnum = 0;
|
|
while (<OCAML_FILE>) {
|
|
if (!$ei) {
|
|
if (m{^type \s+ (\w+) \s* \= \s* $/}x && $enums{$1}) {
|
|
print "// found ocaml type $1 at $o:$.\n" or die $!;
|
|
$ei = $enums{$1};
|
|
$cval = '';
|
|
$bitnum = 0;
|
|
}
|
|
} else {
|
|
if (m{^\s+ \| \s* $ei->{OPrefix} (\w+) \s*$}x) {
|
|
$cval = $1;
|
|
if ($ei->{Mangle} eq 'lc') {
|
|
$cval = lc $cval;
|
|
} elsif ($ei->{Mangle} eq 'none') {
|
|
} else {
|
|
die;
|
|
}
|
|
$cval = $ei->{CPrefix}.$cval;
|
|
expect($cval, "(1u << $bitnum)");
|
|
$bitnum++;
|
|
} elsif (m/^\w|\{/) {
|
|
if ($ei->{CFinalHow} eq 'max') {
|
|
expect($ei->{CFinal}, "(1u << ".($bitnum-1).")");
|
|
} elsif ($ei->{CFinalHow} eq 'all') {
|
|
expect($ei->{CFinal}, "(1u << $bitnum)-1u");
|
|
} else {
|
|
die Dumper($ei)." ?";
|
|
}
|
|
$ei = undef;
|
|
} elsif (!m{\S}) {
|
|
} else {
|
|
die "$_ ?";
|
|
}
|
|
}
|
|
}
|
|
|
|
close STDOUT or die $!;
|