+++ /dev/null
-#!/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 (<FH>) {
- 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 (<FH>) {
- if (/^(\w+)\(/ || /^\w+\s*(?:\*\s*)?(\w+)\(/) {
- my $name = $1;
- if ($name =~ /^vir/) {
- $mocked{$name} = "$file:$.";
- }
- }
- }
-
- close FH
-}
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright (C) 2017-2019 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from __future__ import print_function
+
+import re
+import sys
+
+noninlined = {}
+mocked = {}
+
+# Functions in public header don't get the noinline annotation
+# so whitelist them here
+noninlined["virEventAddTimeout"] = True
+# This one confuses the script as its defined in the mock file
+# but is actually just a local helper
+noninlined["virMockStatRedirect"] = True
+
+
+def scan_annotations(filename):
+ with open(filename, "r") as fh:
+ func = None
+ for line in fh:
+ m = re.search(r'''^\s*(\w+)\(''', line)
+ if m is None:
+ m = re.search(r'''^(?:\w+\*?\s+)+(?:\*\s*)?(\w+)\(''', line)
+ if m is not None:
+ name = m.group(1)
+ if "ATTRIBUTE" not in name and "G_GNUC_" not in name:
+ func = name
+ elif line.isspace():
+ func = None
+
+ if "G_GNUC_NO_INLINE" in line:
+ if func is not None:
+ noninlined[func] = True
+
+
+def scan_overrides(filename):
+ with open(filename, "r") as fh:
+ lineno = 0
+ for line in fh:
+ lineno = lineno + 1
+
+ m = re.search(r'''^(\w+)\(''', line)
+ if m is None:
+ m = re.search(r'''^\w+\s*(?:\*\s*)?(\w+)\(''', line)
+ if m is not None:
+ name = m.group(1)
+ if name.startswith("vir"):
+ mocked[name] = "%s:%d" % (filename, lineno)
+
+
+for filename in sys.argv[1:]:
+ if filename.endswith(".h"):
+ scan_annotations(filename)
+ elif filename.endswith("mock.c"):
+ scan_overrides(filename)
+
+warned = False
+for func in mocked.keys():
+ if func not in noninlined:
+ warned = True
+ print("%s is mocked at %s but missing noinline annotation" %
+ (func, mocked[func]), file=sys.stderr)
+
+if warned:
+ sys.exit(1)
+sys.exit(0)