diff --git a/build-aux/check-spacing.pl b/build-aux/check-spacing.pl index 75bcfd9a5c..cdd991bd6e 100755 --- a/build-aux/check-spacing.pl +++ b/build-aux/check-spacing.pl @@ -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 = )) { 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.