As part of an goal to eliminate Perl from libvirt build tools,
rewrite the header-ifdef.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/header-ifdef.pl | 182 ------------------------------
build-aux/header-ifdef.py | 231 ++++++++++++++++++++++++++++++++++++++
cfg.mk | 4 +-
4 files changed, 234 insertions(+), 185 deletions(-)
delete mode 100644 build-aux/header-ifdef.pl
create mode 100644 build-aux/header-ifdef.py
diff --git a/Makefile.am b/Makefile.am
index db77da890c..4ba729d3f7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -44,7 +44,7 @@ EXTRA_DIST = \
build-aux/augeas-gentest.py \
build-aux/check-spacing.py \
build-aux/gitlog-to-changelog \
- build-aux/header-ifdef.pl \
+ build-aux/header-ifdef.py \
build-aux/minimize-po.py \
build-aux/mock-noinline.py \
build-aux/prohibit-duplicate-header.py \
diff --git a/build-aux/header-ifdef.pl b/build-aux/header-ifdef.pl
deleted file mode 100644
index dba3dbcbdc..0000000000
--- a/build-aux/header-ifdef.pl
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/usr/bin/perl
-#
-# Validate that header files follow a standard layout:
-#
-# /*
-# ...copyright header...
-# */
-# <one blank line>
-# #pragma once
-# ....content....
-#
-#---
-#
-# For any file ending priv.h, before the #pragma once
-# We will have a further section
-#
-# #ifndef SYMBOL_ALLOW
-# # error ....
-# #endif /* SYMBOL_ALLOW */
-# <one blank line>
-#
-#---
-#
-# For public headers (files in include/), use the standard header guard instead of
#pragma once:
-# #ifndef SYMBOL
-# # define SYMBOL
-# ....content....
-# #endif /* SYMBOL */
-
-use strict;
-use warnings;
-
-my $STATE_COPYRIGHT_COMMENT = 0;
-my $STATE_COPYRIGHT_BLANK = 1;
-my $STATE_PRIV_START = 2;
-my $STATE_PRIV_ERROR = 3;
-my $STATE_PRIV_END = 4;
-my $STATE_PRIV_BLANK = 5;
-my $STATE_GUARD_START = 6;
-my $STATE_GUARD_DEFINE = 7;
-my $STATE_GUARD_END = 8;
-my $STATE_EOF = 9;
-my $STATE_PRAGMA = 10;
-
-my $file = " ";
-my $ret = 0;
-my $ifdef = "";
-my $ifdefpriv = "";
-my $publicheader = 0;
-
-my $state = $STATE_EOF;
-my $mistake = 0;
-
-sub mistake {
- my $msg = shift;
- warn $msg;
- $mistake = 1;
- $ret = 1;
-}
-
-while (<>) {
- if (not $file eq $ARGV) {
- if ($state == $STATE_COPYRIGHT_COMMENT) {
- &mistake("$file: missing copyright comment");
- } elsif ($state == $STATE_COPYRIGHT_BLANK) {
- &mistake("$file: missing blank line after copyright header");
- } elsif ($state == $STATE_PRIV_START) {
- &mistake("$file: missing '#ifndef $ifdefpriv'");
- } elsif ($state == $STATE_PRIV_ERROR) {
- &mistake("$file: missing '# error ...priv allow...'");
- } elsif ($state == $STATE_PRIV_END) {
- &mistake("$file: missing '#endif /* $ifdefpriv */'");
- } elsif ($state == $STATE_PRIV_BLANK) {
- &mistake("$file: missing blank line after priv header check");
- } elsif ($state == $STATE_GUARD_START) {
- if ($publicheader) {
- &mistake("$file: missing '#ifndef $ifdef'");
- } else {
- &mistake("$file: missing '#pragma once' header
guard");
- }
- } elsif ($state == $STATE_GUARD_DEFINE) {
- &mistake("$file: missing '# define $ifdef'");
- } elsif ($state == $STATE_GUARD_END) {
- &mistake("$file: missing '#endif /* $ifdef */'");
- }
-
- $ifdef = uc $ARGV;
- $ifdef =~ s,.*/,,;
- $ifdef =~ s,[^A-Z0-9],_,g;
- $ifdef =~ s,__+,_,g;
- unless ($ifdef =~ /^LIBVIRT_/ && $ARGV !~ /libvirt_internal.h/) {
- $ifdef = "LIBVIRT_" . $ifdef;
- }
- $ifdefpriv = $ifdef . "_ALLOW";
-
- $file = $ARGV;
- $state = $STATE_COPYRIGHT_COMMENT;
- $mistake = 0;
- $publicheader = ($ARGV =~ /include\//);
- }
-
- if ($mistake ||
- $ARGV =~ /config-post\.h$/ ||
- $ARGV =~ /vbox_(CAPI|XPCOM)/) {
- $state = $STATE_EOF;
- next;
- }
-
- if ($state == $STATE_COPYRIGHT_COMMENT) {
- if (m,\*/,) {
- $state = $STATE_COPYRIGHT_BLANK;
- }
- } elsif ($state == $STATE_COPYRIGHT_BLANK) {
- if (! /^$/) {
- &mistake("$file: missing blank line after copyright header");
- }
- if ($ARGV =~ /priv\.h$/) {
- $state = $STATE_PRIV_START;
- } else {
- $state = $STATE_GUARD_START;
- }
- } elsif ($state == $STATE_PRIV_START) {
- if (/^$/) {
- &mistake("$file: too many blank lines after copyright
header");
- } elsif (/#ifndef $ifdefpriv$/) {
- $state = $STATE_PRIV_ERROR;
- } else {
- &mistake("$file: missing '#ifndef $ifdefpriv'");
- }
- } elsif ($state == $STATE_PRIV_ERROR) {
- if (/# error ".*"$/) {
- $state = $STATE_PRIV_END;
- } else {
- &mistake("$file: missing '# error ...priv allow...'");
- }
- } elsif ($state == $STATE_PRIV_END) {
- if (m,#endif /\* $ifdefpriv \*/,) {
- $state = $STATE_PRIV_BLANK;
- } else {
- &mistake("$file: missing '#endif /* $ifdefpriv */'");
- }
- } elsif ($state == $STATE_PRIV_BLANK) {
- if (! /^$/) {
- &mistake("$file: missing blank line after priv guard");
- }
- $state = $STATE_GUARD_START;
- } elsif ($state == $STATE_GUARD_START) {
- if (/^$/) {
- &mistake("$file: too many blank lines after copyright
header");
- }
- if ($publicheader) {
- if (/#ifndef $ifdef$/) {
- $state = $STATE_GUARD_DEFINE;
- } else {
- &mistake("$file: missing '#ifndef $ifdef'");
- }
- } else {
- if (/#pragma once/) {
- $state = $STATE_PRAGMA;
- } else {
- &mistake("$file: missing '#pragma once' header
guard");
- }
- }
- } elsif ($state == $STATE_GUARD_DEFINE) {
- if (/# define $ifdef$/) {
- $state = $STATE_GUARD_END;
- } else {
- &mistake("$file: missing '# define $ifdef'");
- }
- } elsif ($state == $STATE_GUARD_END) {
- if (m,#endif /\* $ifdef \*/$,) {
- $state = $STATE_EOF;
- }
- } elsif ($state == $STATE_PRAGMA) {
- next;
- } elsif ($state == $STATE_EOF) {
- die "$file: unexpected content after '#endif /* $ifdef */'";
- } else {
- die "$file: unexpected state $state";
- }
-}
-exit $ret;
diff --git a/build-aux/header-ifdef.py b/build-aux/header-ifdef.py
new file mode 100644
index 0000000000..a192e01bc4
--- /dev/null
+++ b/build-aux/header-ifdef.py
@@ -0,0 +1,231 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018-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/>.
+#
+# Validate that header files follow a standard layout:
+#
+# /*
+# ...copyright header...
+# */
+# <one blank line>
+# #pragma once
+# ....content....
+#
+# ---
+#
+# For any file ending priv.h, before the #pragma once
+# We will have a further section
+#
+# #ifndef SYMBOL_ALLOW
+# # error ....
+# #endif /* SYMBOL_ALLOW */
+# <one blank line>
+#
+# ---
+#
+# For public headers (files in include/), use the standard
+# header guard instead of #pragma once:
+# #ifndef SYMBOL
+# # define SYMBOL
+# ....content....
+# #endif /* SYMBOL */
+
+from __future__ import print_function
+
+import os.path
+import re
+import sys
+
+STATE_COPYRIGHT_COMMENT = 0
+STATE_COPYRIGHT_BLANK = 1
+STATE_PRIV_START = 2
+STATE_PRIV_ERROR = 3
+STATE_PRIV_END = 4
+STATE_PRIV_BLANK = 5
+STATE_GUARD_START = 6
+STATE_GUARD_DEFINE = 7
+STATE_GUARD_END = 8
+STATE_EOF = 9
+STATE_PRAGMA = 10
+
+
+def check_header(filename):
+ ifdef = ""
+ ifdefpriv = ""
+
+ state = STATE_EOF
+
+ ifdef = os.path.basename(filename).upper()
+ ifdef = re.sub(r"""[^A-Z0-9]""", "_", ifdef)
+ ifdef = re.sub(r"""__+""", "_", ifdef)
+
+ if (not ifdef.startswith("LIBVIRT_") or
+ filename.find("libvirt_internal.h") != -1):
+ ifdef = "LIBVIRT_" + ifdef
+
+ ifdefpriv = ifdef + "_ALLOW"
+
+ state = STATE_COPYRIGHT_COMMENT
+ publicheader = False
+ if filename.find("include/") != -1:
+ publicheader = True
+
+ with open(filename, "r") as fh:
+ for line in fh:
+ line = line.rstrip("\n")
+ if state == STATE_COPYRIGHT_COMMENT:
+ if line.find("*/") != -1:
+ state = STATE_COPYRIGHT_BLANK
+ elif state == STATE_COPYRIGHT_BLANK:
+ if line != "":
+ print("%s: missing blank line after copyright header" %
+ filename, file=sys.stderr)
+ return True
+
+ if filename.endswith("priv.h"):
+ state = STATE_PRIV_START
+ else:
+ state = STATE_GUARD_START
+ elif state == STATE_PRIV_START:
+ if line == "":
+ print("%s: too many blank lines after copyright header" %
+ filename, file=sys.stderr)
+ return True
+ elif re.match(r"""#ifndef %s$""" %
ifdefpriv, line):
+ state = STATE_PRIV_ERROR
+ else:
+ print("%s: missing '#ifndef %s'" % (filename,
ifdefpriv),
+ file=sys.stderr)
+ return True
+ elif state == STATE_PRIV_ERROR:
+ if re.match(r"""# error ".*"$""",
line):
+ state = STATE_PRIV_END
+ else:
+ print("%s: missing '# error ...priv allow...'" %
+ filename, file=sys.stderr)
+ return True
+ elif state == STATE_PRIV_END:
+ if re.match(r"""#endif /\* %s \*/""" %
ifdefpriv, line):
+ state = STATE_PRIV_BLANK
+ else:
+ print("%s: missing '#endif /* %s */'" %
+ (filename, ifdefpriv), file=sys.stderr)
+ return True
+ elif state == STATE_PRIV_BLANK:
+ if line != "":
+ print("%s: missing blank line after priv guard" %
+ filename, file=sys.stderr)
+ return True
+ state = STATE_GUARD_START
+ elif state == STATE_GUARD_START:
+ if line == "":
+ print("%s: too many blank lines after copyright header" %
+ filename, file=sys.stderr)
+ return True
+ if publicheader:
+ if re.match(r"""#ifndef %s$""" % ifdef,
line):
+ state = STATE_GUARD_DEFINE
+ else:
+ print("%s: missing '#ifndef %s'" %
+ (filename, ifdef), file=sys.stderr)
+ return True
+ else:
+ if re.match(r"""#pragma once""",
line):
+ state = STATE_PRAGMA
+ else:
+ print("%s: missing '#pragma once' header guard"
%
+ filename, file=sys.stderr)
+ return True
+ elif state == STATE_GUARD_DEFINE:
+ if re.match(r"""# define %s$""" % ifdef,
line):
+ state = STATE_GUARD_END
+ else:
+ print("%s: missing '# define %s'" %
+ (filename, ifdef), file=sys.stderr)
+ return True
+ elif state == STATE_GUARD_END:
+ if re.match(r"""#endif /\* %s \*/$""" %
ifdef, line):
+ state = STATE_EOF
+ elif state == STATE_PRAGMA:
+ next
+ elif state == STATE_EOF:
+ print("%s: unexpected content after '#endif /* %s */'"
%
+ (filename, ifdef), file=sys.stderr)
+ return True
+ else:
+ print("%s: unexpected state $state" %
+ filename, file=sys.stderr)
+ return True
+
+ if state == STATE_COPYRIGHT_COMMENT:
+ print("%s: missing copyright comment" %
+ filename, file=sys.stderr)
+ return True
+ elif state == STATE_COPYRIGHT_BLANK:
+ print("%s: missing blank line after copyright header" %
+ filename, file=sys.stderr)
+ return True
+ elif state == STATE_PRIV_START:
+ print("%s: missing '#ifndef %s'" %
+ (filename, ifdefpriv), file=sys.stderr)
+ return True
+ elif state == STATE_PRIV_ERROR:
+ print("%s: missing '# error ...priv allow...'" %
+ filename, file=sys.stderr)
+ return True
+ elif state == STATE_PRIV_END:
+ print("%s: missing '#endif /* %s */'" %
+ (filename, ifdefpriv), file=sys.stderr)
+ return True
+ elif state == STATE_PRIV_BLANK:
+ print("%s: missing blank line after priv header check" %
+ filename, file=sys.stderr)
+ return True
+ elif state == STATE_GUARD_START:
+ if publicheader:
+ print("%s: missing '#ifndef %s'" %
+ (filename, ifdef), file=sys.stderr)
+ return True
+ else:
+ print("%s: missing '#pragma once' header guard" %
+ filename, file=sys.stderr)
+ return True
+ elif state == STATE_GUARD_DEFINE:
+ print("%s: missing '# define %s'" %
+ (filename, ifdef), file=sys.stderr)
+ return True
+ elif state == STATE_GUARD_END:
+ print("%s: missing '#endif /* %s */'" %
+ (filename, ifdef), file=sys.stderr)
+ return True
+
+ return False
+
+
+ret = 0
+
+for filename in sys.argv[1:]:
+ if filename.find("config-post.h") != -1:
+ continue
+ if filename.find("vbox_CAPI") != -1:
+ continue
+ if filename.find("vbox_XPCOM") != -1:
+ continue
+ if check_header(filename):
+ ret = 1
+
+sys.exit(ret)
diff --git a/cfg.mk b/cfg.mk
index b73d3ae1bf..f0aed0365a 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -1165,8 +1165,8 @@ mock-noinline:
$(PYTHON) $(top_srcdir)/build-aux/mock-noinline.py
header-ifdef:
- $(AM_V_GEN)$(VC_LIST) | $(GREP) '\.[h]$$' | xargs \
- $(PERL) $(top_srcdir)/build-aux/header-ifdef.pl
+ $(AM_V_GEN)$(VC_LIST) | $(GREP) '\.[h]$$' | $(RUNUTF8) xargs \
+ $(PYTHON) $(top_srcdir)/build-aux/header-ifdef.py
test-wrap-argv:
$(AM_V_GEN)$(VC_LIST) | $(GREP) -E '\.(ldargs|args)' | xargs \
--
2.21.0