#! /bin/sh # Ensure consistent style by catching common improper constructs. set -e diag() { fail=: echo "$file:" "$@" echo ============================================================ } rm -f failures # Get some help from GNU grep. GREP_OPTIONS='--color=auto -n' GREP_COLOR='1;31' export GREP_OPTIONS export GREP_COLOR tmp=incltest.tmp for dir in "${INCDIR-..}" "${INCDIR-..}"/../iface; do find "$dir" \( -name "${1-*}.hh" -o -name "${1-*}.cc" \) \ -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 fail=false sed 's,[ ]*//.*,,' < $file > $tmp grep '[ ]$' $tmp && diag 'Trailing whitespace.' 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.' grep '[^ ]&&[^ ]' $tmp && diag 'Space arround binary operators.' grep '[^ ]||[^ ]' $tmp && diag 'Space arround binary operators.' 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"' 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 '(cout|cerr|clog)' $tmp >/dev/null; then : else grep '#.*include.*' $tmp && diag 'Avoid in headers, better use .' fi ;; *.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 $fail && echo "$file" >>failures done done if test -f failures; then echo "The following files contain style errors:" cat failures rm failures exit 1; fi