#!/usr/bin/env perl my %noninlined; my %mocked; # Functions in public header don't get the noinline annotation # so whitelist them here $noninlined{"virEventAddTimeout"} = 1; # This one confuses the script as its defined in the mock file # but is actually just a local helper $noninlined{"virMockStatRedirect"} = 1; foreach my $arg (@ARGV) { if ($arg =~ /\.h$/) { #print "Scan header $arg\n"; &scan_annotations($arg); } elsif ($arg =~ /mock\.c$/) { #print "Scan mock $arg\n"; &scan_overrides($arg); } } my $warned = 0; foreach my $func (keys %mocked) { next if exists $noninlined{$func}; $warned++; print STDERR "$func is mocked at $mocked{$func} but missing noinline annotation\n"; } exit $warned ? 1 : 0; sub scan_annotations { my $file = shift; open FH, $file or die "cannot read $file: $!"; my $func; while () { if (/^\s*(\w+)\(/ || /^(?:\w+\*?\s+)+(?:\*\s*)?(\w+)\(/) { my $name = $1; if ($name !~ /(?:G_GNUC|ATTRIBUTE)/) { $func = $name; } } elsif (/^\s*$/) { $func = undef; } if (/G_GNUC_NO_INLINE/) { if (defined $func) { $noninlined{$func} = 1; } } } close FH } sub scan_overrides { my $file = shift; open FH, $file or die "cannot read $file: $!"; my $func; while () { if (/^(\w+)\(/ || /^\w+\s*(?:\*\s*)?(\w+)\(/) { my $name = $1; if ($name =~ /^vir/) { $mocked{$name} = "$file:$."; } } } close FH }