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(a)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