]> xenbits.xensource.com Git - libvirt.git/commitdiff
build-aux: rewrite mock inline checker in Python
authorDaniel P. Berrangé <berrange@redhat.com>
Fri, 30 Aug 2019 12:22:54 +0000 (13:22 +0100)
committerDaniel P. Berrangé <berrange@redhat.com>
Wed, 20 Nov 2019 14:45:25 +0000 (14:45 +0000)
As part of a goal to eliminate Perl from libvirt build tools,
rewrite the mock-noinline.pl tool in Python.

This was a straight conversion, manually going line-by-line to
change the syntax from Perl to Python. Thus the overall structure
of the file and approach is the same.

Tested-by: Cole Robinson <crobinso@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Makefile.am
build-aux/mock-noinline.pl [deleted file]
build-aux/syntax-check.mk
scripts/mock-noinline.py [new file with mode: 0644]

index 9471cf7117860494ecc200acd1d756b1e8faf30d..9fe24fb65baeb22f34aa4398c80d8a227ca71357 100644 (file)
@@ -49,7 +49,7 @@ EXTRA_DIST = \
   build-aux/check-spacing.pl \
   build-aux/header-ifdef.pl \
   scripts/minimize-po.py \
-  build-aux/mock-noinline.pl \
+  scripts/mock-noinline.py \
   scripts/prohibit-duplicate-header.py \
   build-aux/syntax-check.mk \
   build-aux/useless-if-before-free \
diff --git a/build-aux/mock-noinline.pl b/build-aux/mock-noinline.pl
deleted file mode 100644 (file)
index b005b8d..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/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
-}
index f1e976ec769712dcd5ccd3c20fc3ce0e1abea3e1..7112f8235d1cd79961d69bb235fb088edf4c2b20 100644 (file)
@@ -2180,8 +2180,8 @@ spacing-check:
          { echo '$(ME): incorrect formatting' 1>&2; exit 1; }
 
 mock-noinline:
-       $(AM_V_GEN)$(VC_LIST) | $(GREP) '\.[ch]$$' | xargs \
-       $(PERL) $(top_srcdir)/build-aux/mock-noinline.pl
+       $(AM_V_GEN)$(VC_LIST) | $(GREP) '\.[ch]$$' | $(RUNUTF8) xargs \
+       $(PYTHON) $(top_srcdir)/scripts/mock-noinline.py
 
 header-ifdef:
        $(AM_V_GEN)$(VC_LIST) | $(GREP) '\.[h]$$' | xargs \
diff --git a/scripts/mock-noinline.py b/scripts/mock-noinline.py
new file mode 100644 (file)
index 0000000..b338c5f
--- /dev/null
@@ -0,0 +1,84 @@
+#!/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)