[libvirt] [PATCH v3 06/22] build-aux: rewrite mock inline checker in Python

Daniel P. Berrangé berrange at redhat.com
Tue Sep 24 14:58:47 UTC 2019


As part of an 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.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 Makefile.am                |  2 +-
 build-aux/mock-noinline.pl | 75 --------------------------------
 build-aux/mock-noinline.py | 89 ++++++++++++++++++++++++++++++++++++++
 cfg.mk                     |  4 +-
 4 files changed, 92 insertions(+), 78 deletions(-)
 delete mode 100644 build-aux/mock-noinline.pl
 create mode 100644 build-aux/mock-noinline.py

diff --git a/Makefile.am b/Makefile.am
index 03bf1beb78..db77da890c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -46,7 +46,7 @@ EXTRA_DIST = \
   build-aux/gitlog-to-changelog \
   build-aux/header-ifdef.pl \
   build-aux/minimize-po.py \
-  build-aux/mock-noinline.pl \
+  build-aux/mock-noinline.py \
   build-aux/prohibit-duplicate-header.py \
   build-aux/useless-if-before-free \
   build-aux/vc-list-files \
diff --git a/build-aux/mock-noinline.pl b/build-aux/mock-noinline.pl
deleted file mode 100644
index 958e133885..0000000000
--- a/build-aux/mock-noinline.pl
+++ /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 !~ /ATTRIBUTE/) {
-                $func = $name;
-            }
-        } elsif (/^\s*$/) {
-            $func = undef;
-        }
-        if (/ATTRIBUTE_NOINLINE/) {
-            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
-}
diff --git a/build-aux/mock-noinline.py b/build-aux/mock-noinline.py
new file mode 100644
index 0000000000..53aeeb429c
--- /dev/null
+++ b/build-aux/mock-noinline.py
@@ -0,0 +1,89 @@
+#!/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):
+    funcprog1 = re.compile(r'''^\s*(\w+)\(.*''')
+    funcprog2 = re.compile(r'''^(?:\w+\*?\s+)+(?:\*\s*)?(\w+)\(.*''')
+    with open(filename, "r") as fh:
+        func = None
+        for line in fh:
+            line = line.strip()
+            m = funcprog1.match(line)
+            if m is None:
+                m = funcprog2.match(line)
+            if m is not None:
+                name = m.group(1)
+                if name.find("ATTRIBUTE") == -1:
+                    func = name
+            elif line == "":
+                func = None
+
+            if line.find("ATTRIBUTE_NOINLINE") != -1:
+                if func is not None:
+                    noninlined[func] = True
+
+
+def scan_overrides(filename):
+    funcprog1 = re.compile(r'''^(\w+)\(.*''')
+    funcprog2 = re.compile(r'''^\w+\s*(?:\*\s*)?(\w+)\(.*''')
+    with open(filename, "r") as fh:
+        lineno = 0
+        for line in fh:
+            lineno = lineno + 1
+
+            m = funcprog1.match(line)
+            if m is None:
+                m = funcprog2.match(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)
diff --git a/cfg.mk b/cfg.mk
index d52d42c06c..b73d3ae1bf 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -1161,8 +1161,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)/build-aux/mock-noinline.py
 
 header-ifdef:
 	$(AM_V_GEN)$(VC_LIST) | $(GREP) '\.[h]$$' | xargs \
-- 
2.21.0




More information about the libvir-list mailing list