* src/sanity/80columns.test, src/sanity/includes.test, src/sanity/private.test, src/sanity/style.test: Here.
320 lines
8.7 KiB
Bash
Executable file
320 lines
8.7 KiB
Bash
Executable file
#! /bin/sh
|
|
# -*- coding: utf-8 -*-
|
|
# Copyright (C) 2009, 2010, 2011, 2012, 2013 Laboratoire de Recherche
|
|
# et Développement de l'Epita (LRDE).
|
|
# Copyright (C) 2004, 2005 Laboratoire d'Informatique de Paris 6
|
|
# (LIP6), département Systèmes Répartis Coopératifs (SRC), Université
|
|
# Pierre et Marie Curie.
|
|
#
|
|
# This file is part of Spot, a model checking library.
|
|
#
|
|
# Spot is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Spot 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 General Public
|
|
# License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# Ensure consistent style by catching common improper constructs.
|
|
|
|
set -e
|
|
|
|
diag()
|
|
{
|
|
fail=:
|
|
echo "$file:" "$@"
|
|
echo ============================================================
|
|
}
|
|
|
|
rm -f failures
|
|
|
|
# Get some help from GNU grep.
|
|
if (grep --color=auto -n --version)>/dev/null 2>&1; then
|
|
GREP_OPTIONS='--color=auto -n'
|
|
GREP_COLOR='1;31'
|
|
export GREP_OPTIONS
|
|
export GREP_COLOR
|
|
fi
|
|
|
|
# Reset the locale, so for instance we don't get bugs because sed is
|
|
# expecting utf-8 and we feed him latin-1. The C locale should be OK,
|
|
# because we do not treat extended characters specifically in the
|
|
# following style rules.
|
|
LC_ALL=C
|
|
export LC_ALL
|
|
|
|
tmp=incltest.tmp
|
|
|
|
for dir in "${INCDIR-..}" "${INCDIR-..}"/../iface; do
|
|
|
|
find "$dir" \( -name "${1-*}.hh" \
|
|
-o -name "${1-*}.hxx" \
|
|
-o -name "${1-*}.cc" \
|
|
-o -name "${1-*}.test" \) \
|
|
-a -type f -a -print |
|
|
while read file; do
|
|
|
|
if grep 'GNU Bison' "$file" >/dev/null ||
|
|
grep 'generated by flex' "$file" >/dev/null ; then
|
|
continue
|
|
fi
|
|
|
|
# Skip the files used by sanity.
|
|
case $file in
|
|
*incltest.cc) continue;;
|
|
esac
|
|
|
|
fail=false
|
|
|
|
# Check this before stripping comments and strings.
|
|
grep -i 'accepting cond' $file &&
|
|
diag 'accepting -> acceptance'
|
|
|
|
grep -i 'version 2 of the License' $file &&
|
|
diag 'license text should refer to version 2'
|
|
grep -i 'Temple Place' $file &&
|
|
diag 'license text should give a url instead of an address'
|
|
|
|
grep Copyright $file >/dev/null ||
|
|
diag "missing copyright"
|
|
|
|
# A doxygen comments such as
|
|
#
|
|
# | \brief foo
|
|
# | \ingroup bar
|
|
# |
|
|
# | baz
|
|
#
|
|
# will be output as "foobaz." But if the first two lines
|
|
# are reversed, it's output correctly.
|
|
perl -ne '/(.*\\brief.*\n.*\\ingroup.*)/ && print("$1\n") && exit(1)' \
|
|
-0777 $file || diag "always put 'ingroup' before 'brief'"
|
|
|
|
# Strip comments and strings.
|
|
#
|
|
# Multi-line comments of the form
|
|
# /* Line 1
|
|
# Line 2
|
|
# Line 3 */
|
|
# are replaced by
|
|
# //
|
|
# //
|
|
# //
|
|
# to keep the line numbers correct in the diagnostics.
|
|
#
|
|
# Also get read of the SPOT_API tags.
|
|
perl -pe 'sub f {my $a = shift; $a =~ s:[^\n]*://:g; return "$a"}
|
|
s,/\*(.*?)\*/,f($1),sge;
|
|
s,//.*?\n,//\n,g;
|
|
s,"[^"\n]*","",g;
|
|
s,SPOT_API ,,g' -0777 <$file >$tmp
|
|
|
|
grep '[ ]$' $tmp &&
|
|
diag 'Trailing whitespace.'
|
|
|
|
case $file in
|
|
*.test);;
|
|
*)
|
|
grep -E '[^<]class[ \t]+[A-Z]' $tmp &&
|
|
diag 'Use lower case class names.'
|
|
|
|
grep '[ ]if(' $tmp &&
|
|
diag 'Missing space after "if"'
|
|
|
|
grep '[ ]if (.*).*{' $tmp &&
|
|
diag 'Opening { should be on its own line.'
|
|
|
|
grep '[ ]if (.*).*;' $tmp &&
|
|
diag 'if body should be on another line.'
|
|
|
|
grep '[ ]else.*;' $tmp &&
|
|
diag 'else body should be on another line.'
|
|
|
|
grep '[ ]while(' $tmp &&
|
|
diag 'Missing space after "while"'
|
|
|
|
grep '[ ]while (.*).*{' $tmp &&
|
|
diag 'Opening { should be on its own line.'
|
|
|
|
grep '[ ]while (.*).*[^)];' $tmp &&
|
|
diag 'while body should be on another line.'
|
|
|
|
grep '[ ]for(' $tmp &&
|
|
diag 'Missing space after "for"'
|
|
|
|
grep '[ ]for (.*).*{' $tmp &&
|
|
diag 'Opening { should be on its own line.'
|
|
|
|
grep '[ ]for (.*;.*;.*).*;' $tmp &&
|
|
diag 'for body should be on another line.'
|
|
|
|
grep '[ ]switch(' $tmp &&
|
|
diag 'Missing space after "switch"'
|
|
|
|
grep '[ ]switch (.*).*{' $tmp &&
|
|
diag 'Opening { should be on its own line.'
|
|
|
|
grep 'namespace .*{' $tmp &&
|
|
diag 'Opening { should be on its own line.'
|
|
|
|
grep 'class .*{' $tmp &&
|
|
diag 'Opening { should be on its own line.'
|
|
|
|
grep '( ' $tmp &&
|
|
diag 'No space after opening (.'
|
|
|
|
grep ' )' $tmp &&
|
|
diag 'No space before closing ).'
|
|
|
|
grep '! ' $tmp &&
|
|
diag 'No space after unary operators (!).'
|
|
|
|
grep ",[^ \" %'\\\\]" $tmp &&
|
|
diag 'Space after coma.'
|
|
|
|
# The 'r' allows operator&&
|
|
grep '[^ r]&&[^ ]' $tmp &&
|
|
diag 'Space around binary operators.'
|
|
|
|
# The 'r' allows operator||
|
|
grep '[^ r]||[^ ]' $tmp &&
|
|
diag 'Space around binary operators.'
|
|
|
|
# The 'r' allows operator==
|
|
grep '[^ r<>][!<>=]=[^ ]' $tmp &&
|
|
diag 'Space around binary operators.'
|
|
|
|
# The 'r' allows operator<<=
|
|
grep '[^ r][<>][<>]=[^ ]' $tmp &&
|
|
diag 'Space around binary operators.'
|
|
|
|
grep 'operator[^a-zA-Z0-9_(]*[ ][^a-zA-Z0-9_(]*(' $tmp &&
|
|
diag 'Write operatorXX(...) without spaces around XX.'
|
|
|
|
grep 'operator[^(]* (' $tmp &&
|
|
diag 'No space before ('
|
|
|
|
grep '[ ]default:[^:].*;' $tmp &&
|
|
diag 'Label should be on their own line.'
|
|
|
|
grep '[ ]case.*:[^:].*;' $tmp &&
|
|
diag 'Label should be on their own line.'
|
|
|
|
grep '[ ];' $tmp &&
|
|
diag 'No space before semicolon.'
|
|
|
|
grep -v 'for (.*;;)' $tmp | grep ';[^ ")]' &&
|
|
diag 'Must have space or newline after semicolon.'
|
|
|
|
grep '}.*}' $tmp &&
|
|
diag 'No two } on the same line.'
|
|
|
|
grep '{.*{' $tmp &&
|
|
diag 'No two { on the same line.'
|
|
|
|
grep 'delete[ ]*[(][^(]*[)];' $tmp &&
|
|
diag 'No useless parentheses after delete.'
|
|
|
|
grep 'return[ ]*[(][^(]*[)];' $tmp &&
|
|
diag 'No useless parentheses after return.'
|
|
|
|
grep 'NULL' $tmp &&
|
|
diag 'Use 0 instead of NULL. NULL is not portable.'
|
|
|
|
# std::list::size() can be O(n). Better use empty() whenever
|
|
# possible, even for other containers.
|
|
egrep '(->|[.])size\(\) [=!]= 0|![a-zA-Z0-9_]*(->|[.])size\(\)|(if |while |assert)\([a-zA-Z0-9_]*(->|[.])size\(\)\)' $tmp &&
|
|
diag 'Prefer empty() to check emptiness.'
|
|
|
|
egrep '^[^=*<]*([+][+]|--);' $tmp &&
|
|
diag 'Take good habits: use ++i instead of i++ when you have the choice.'
|
|
|
|
grep '[^a-zA-Z0-9_](\*[a-zA-Z0-9_]*)\.' $tmp &&
|
|
diag 'Use "x->y", not "(*x).y"'
|
|
|
|
grep 'std::hash' $tmp &&
|
|
diag 'use Sgi:: for hash and hash_map'
|
|
|
|
grep 'Sgi::[^h]' $tmp &&
|
|
diag 'Sgi:: is for hash and hash_map only'
|
|
|
|
egrep 'bdd_(false|true)[ ]*\(' $tmp &&
|
|
diag 'Use bddfalse and bddtrue instead of bdd_false() and bdd_true()'
|
|
|
|
res=`perl -ne '$/ = undef;
|
|
print "$&\n"
|
|
while /if \((.*)(\s*==\s*0)?\)\s*delete(\[\])?\s+\1;(?!\s+else)/g' $tmp`
|
|
if test -n "$res"; then
|
|
echo "$res"
|
|
diag 'No "if (x)" required before "delete x;".'
|
|
fi
|
|
|
|
case $file in
|
|
*.hh | *.hxx)
|
|
if egrep '(<<|>>)' $tmp >/dev/null; then
|
|
:
|
|
else
|
|
grep '#.*include.*<iostream>' $tmp &&
|
|
diag 'Avoid <iostream> in headers, better use <iosfwd>.'
|
|
fi
|
|
# Headers from src/priv/ are not installed, so may only be
|
|
# included from *.cc files or from other src/priv/ headers
|
|
# (in the latter case they do not have to specify the priv/
|
|
# directory, so they will not match this regex).
|
|
grep '#.*include.*priv/' $tmp &&
|
|
diag 'Do not include private headers in public headers.'
|
|
;;
|
|
*.cc)
|
|
if grep 'namespace$' $tmp >/dev/null; then
|
|
:
|
|
else
|
|
# We only check classes, but the rule should apply to functions too
|
|
grep '^[ ]*class[ ]' $tmp &&
|
|
diag 'Private definitions must be in anonymous namespace.'
|
|
fi
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
|
|
|
|
$fail && echo "$file" >>failures
|
|
|
|
done || : # Make sure sh does not abort when read exits with false.
|
|
done
|
|
|
|
|
|
# Rules for Makefiles.
|
|
for dir in "${INCDIR-..}" "${INCDIR-..}"/../iface; do
|
|
|
|
find "$dir" -name "Makefile.am" -a -type f -a -print |
|
|
while read file; do
|
|
fail=false
|
|
|
|
# Strip comments.
|
|
sed 's,#.*,,' < $file > $tmp
|
|
|
|
grep '[ ]$' $tmp &&
|
|
diag 'Trailing whitespace.'
|
|
|
|
grep '\.libs/' $tmp &&
|
|
diag "Don't reference files in .libs/, use Libtool instead."
|
|
|
|
$fail && echo "$file" >>failures
|
|
done || : # Make sure sh does not abort when read exits with false.
|
|
done
|
|
|
|
if test -f failures; then
|
|
echo "The following files contain style errors:"
|
|
cat failures
|
|
rm failures
|
|
exit 1;
|
|
fi
|
|
|
|
exit 0
|