mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
build-aux: rewrite header ifdef checker in Python
As part of a 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. Tested-by: Cole Robinson <crobinso@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
b7d00249ea
commit
2d6f543b06
@ -47,7 +47,7 @@ EXTRA_DIST = \
|
||||
AUTHORS.in \
|
||||
scripts/augeas-gentest.py \
|
||||
build-aux/check-spacing.pl \
|
||||
build-aux/header-ifdef.pl \
|
||||
scripts/header-ifdef.py \
|
||||
scripts/minimize-po.py \
|
||||
scripts/mock-noinline.py \
|
||||
scripts/prohibit-duplicate-header.py \
|
||||
|
@ -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;
|
@ -2184,8 +2184,8 @@ mock-noinline:
|
||||
$(PYTHON) $(top_srcdir)/scripts/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)/scripts/header-ifdef.py
|
||||
|
||||
test-wrap-argv:
|
||||
$(AM_V_GEN)$(VC_LIST) | $(GREP) -E '\.(ldargs|args)' | xargs \
|
||||
|
230
scripts/header-ifdef.py
Normal file
230
scripts/header-ifdef.py
Normal file
@ -0,0 +1,230 @@
|
||||
#!/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
|
||||
"libvirt_internal.h" in filename):
|
||||
ifdef = "LIBVIRT_" + ifdef
|
||||
|
||||
ifdefpriv = ifdef + "_ALLOW"
|
||||
|
||||
state = STATE_COPYRIGHT_COMMENT
|
||||
publicheader = False
|
||||
if "include/" in filename:
|
||||
publicheader = True
|
||||
|
||||
with open(filename, "r") as fh:
|
||||
for line in fh:
|
||||
if state == STATE_COPYRIGHT_COMMENT:
|
||||
if "*/" in line:
|
||||
state = STATE_COPYRIGHT_BLANK
|
||||
elif state == STATE_COPYRIGHT_BLANK:
|
||||
if not line.isspace():
|
||||
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.isspace():
|
||||
print("%s: too many blank lines after copyright header" %
|
||||
filename, file=sys.stderr)
|
||||
return True
|
||||
elif re.search(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.search(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.search(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 not line.isspace():
|
||||
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.isspace():
|
||||
print("%s: too many blank lines after copyright header" %
|
||||
filename, file=sys.stderr)
|
||||
return True
|
||||
if publicheader:
|
||||
if re.search(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.search(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.search(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.search(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 "config-post.h" in filename:
|
||||
continue
|
||||
if "vbox_CAPI" in filename:
|
||||
continue
|
||||
if "vbox_XPCOM" in filename:
|
||||
continue
|
||||
if check_header(filename):
|
||||
ret = 1
|
||||
|
||||
sys.exit(ret)
|
Loading…
Reference in New Issue
Block a user