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@xxxxxxxxxx> --- Makefile.am | 2 +- build-aux/mock-noinline.pl | 75 -------------------------------- build-aux/mock-noinline.py | 88 ++++++++++++++++++++++++++++++++++++++ cfg.mk | 4 +- 4 files changed, 91 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..fdc60c5de9 --- /dev/null +++ b/build-aux/mock-noinline.py @@ -0,0 +1,88 @@ +#!/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: + func = None + lineno = 0 + for line in fh: + lineno = lineno + 1 + #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.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 4da3554b30..490e6b7f14 100644 --- a/cfg.mk +++ b/cfg.mk @@ -1156,8 +1156,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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list