build-aux:check-spacing: Add wrapper function of CheckWhiteSpaces

This patch adds CheckWhiteSpaces to simplify check-spacing.

Signed-off-by: Shi Lei <shi_lei@massclouds.com>
This commit is contained in:
Shi Lei 2018-09-19 16:38:17 +08:00 committed by Michal Privoznik
parent c3875129d9
commit 6225626b6f

View File

@ -96,6 +96,111 @@ sub KillComments {
return;
}
#
# CheckWhiteSpaces:
# $_[0]: $data(in)
# $_[1]: $location(in), which format is file-path:line-num:line-code
#
# Check whitespaces according to code spec of libvirt.
#
sub CheckWhiteSpaces {
my $ret = 0;
my ($data, $location) = @_;
# We need to match things like
#
# int foo (int bar, bool wizz);
# foo (bar, wizz);
#
# but not match things like:
#
# typedef int (*foo)(bar wizz)
#
# we can't do this (efficiently) without
# missing things like
#
# foo (*bar, wizz);
#
# We also don't want to spoil the $data so it can be used
# later on.
# For temporary modifications
my $tmpdata = $$data;
while ($tmpdata =~ /(\w+)\s\((?!\*)/) {
my $kw = $1;
# Allow space after keywords only
if ($kw =~ /^(?:if|for|while|switch|return)$/) {
$tmpdata =~ s/(?:$kw\s\()/XXX(/;
} else {
print "Whitespace after non-keyword:\n$$location";
$ret = 1;
last;
}
}
# Require whitespace immediately after keywords
if ($$data =~ /\b(?:if|for|while|switch|return)\(/) {
print "No whitespace after keyword:\n$$location";
$ret = 1;
}
# Forbid whitespace between )( of a function typedef
if ($$data =~ /\(\*\w+\)\s+\(/) {
print "Whitespace between ')' and '(':\n$$location";
$ret = 1;
}
# Forbid whitespace following ( or prior to )
# but allow whitespace before ) on a single line
# (optionally followed by a semicolon)
if (($$data =~ /\s\)/ && not $$data =~ /^\s+\);?$/) ||
$$data =~ /\((?!$)\s/) {
print "Whitespace after '(' or before ')':\n$$location";
$ret = 1;
}
# Forbid whitespace before ";" or ",". Things like below are allowed:
#
# 1) The expression is empty for "for" loop. E.g.
# for (i = 0; ; i++)
#
# 2) An empty statement. E.g.
# while (write(statuswrite, &status, 1) == -1 &&
# errno == EINTR)
# ;
#
if ($$data =~ /\s[;,]/) {
unless ($$data =~ /\S; ; / ||
$$data =~ /^\s+;/) {
print "Whitespace before semicolon or comma:\n$$location";
$ret = 1;
}
}
# Require EOL, macro line continuation, or whitespace after ";".
# Allow "for (;;)" as an exception.
if ($$data =~ /;[^ \\\n;)]/) {
print "Invalid character after semicolon:\n$$location";
$ret = 1;
}
# Require EOL, space, or enum/struct end after comma.
if ($$data =~ /,[^ \\\n)}]/) {
print "Invalid character after comma:\n$$location";
$ret = 1;
}
# Require spaces around assignment '=', compounds and '=='
if ($$data =~ /[^ ]\b[!<>&|\-+*\/%\^=]?=/ ||
$$data =~ /=[^= \\\n]/) {
print "Spacing around '=' or '==':\n$$location";
$ret = 1;
}
return $ret;
}
my $ret = 0;
foreach my $file (@ARGV) {
@ -111,8 +216,6 @@ foreach my $file (@ARGV) {
while (defined (my $line = <FILE>)) {
my $data = $line;
my $location = "$file:$.:\n$line";
# For temporary modifications
my $tmpdata;
# Kill any quoted , ; = or "
$data =~ s/'[";,=]'/'X'/g;
@ -129,102 +232,7 @@ foreach my $file (@ARGV) {
KillComments(\$data, \$incomment);
# We need to match things like
#
# int foo (int bar, bool wizz);
# foo (bar, wizz);
#
# but not match things like:
#
# typedef int (*foo)(bar wizz)
#
# we can't do this (efficiently) without
# missing things like
#
# foo (*bar, wizz);
#
# We also don't want to spoil the $data so it can be used
# later on.
$tmpdata = $data;
while ($tmpdata =~ /(\w+)\s\((?!\*)/) {
my $kw = $1;
# Allow space after keywords only
if ($kw =~ /^(?:if|for|while|switch|return)$/) {
$tmpdata =~ s/(?:$kw\s\()/XXX(/;
} else {
print "Whitespace after non-keyword:\n";
print "$file:$.: $line";
$ret = 1;
last;
}
}
# Require whitespace immediately after keywords
if ($data =~ /\b(?:if|for|while|switch|return)\(/) {
print "No whitespace after keyword:\n";
print "$file:$.: $line";
$ret = 1;
}
# Forbid whitespace between )( of a function typedef
if ($data =~ /\(\*\w+\)\s+\(/) {
print "Whitespace between ')' and '(':\n";
print "$file:$.: $line";
$ret = 1;
}
# Forbid whitespace following ( or prior to )
# but allow whitespace before ) on a single line
# (optionally followed by a semicolon)
if (($data =~ /\s\)/ && not $data =~ /^\s+\);?$/) ||
$data =~ /\((?!$)\s/) {
print "Whitespace after '(' or before ')':\n";
print "$file:$.: $line";
$ret = 1;
}
# Forbid whitespace before ";" or ",". Things like below are allowed:
#
# 1) The expression is empty for "for" loop. E.g.
# for (i = 0; ; i++)
#
# 2) An empty statement. E.g.
# while (write(statuswrite, &status, 1) == -1 &&
# errno == EINTR)
# ;
#
if ($data =~ /\s[;,]/) {
unless ($data =~ /\S; ; / ||
$data =~ /^\s+;/) {
print "Whitespace before semicolon or comma:\n";
print "$file:$.: $line";
$ret = 1;
}
}
# Require EOL, macro line continuation, or whitespace after ";".
# Allow "for (;;)" as an exception.
if ($data =~ /;[^ \\\n;)]/) {
print "Invalid character after semicolon:\n";
print "$file:$.: $line";
$ret = 1;
}
# Require EOL, space, or enum/struct end after comma.
if ($data =~ /,[^ \\\n)}]/) {
print "Invalid character after comma:\n";
print "$file:$.: $line";
$ret = 1;
}
# Require spaces around assignment '=', compounds and '=='
if ($data =~ /[^ ]\b[!<>&|\-+*\/%\^=]?=/ ||
$data =~ /=[^= \\\n]/) {
print "Spacing around '=' or '==':\n";
print "$file:$.: $line";
$ret = 1;
}
$ret = 1 if CheckWhiteSpaces(\$data, \$location);
# One line conditional statements with one line bodies should
# not use curly brackets.