style.test 6.15 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#! /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.
17
18
19
20
21
22
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
23

24
25
26
27
28
29
30
# 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

31
32
tmp=incltest.tmp

33
34
for dir in "${INCDIR-..}" "${INCDIR-..}"/../iface; do

35
36
  find "$dir" \(    -name "${1-*}.hh" \
                 -o -name "${1-*}.hxx" \
37
38
                 -o -name "${1-*}.cc" \
                 -o -name "${1-*}.test" \) \
39
	      -a -type f -a -print |
40
  while read file; do
41

42
    if grep 'GNU Bison' "$file" >/dev/null ||
43
44
      grep 'generated by flex' "$file" >/dev/null ; then
      continue
45
    fi
46

47
48
49
50
51
    # Skip the files used by sanity.
    case $file in
	*incltest.cc) continue;;
    esac

52
    fail=false
53

54
55
56
57
    # Check this before stripping comments and strings.
    grep -i 'accepting cond' $file &&
      diag 'accepting -> acceptance'

58
59
60
    grep Copyright $file >/dev/null ||
      diag "missing copyright"

61
    # Strip comments and strings.
62
    sed 's,[	 ]*//.*,,;s,"[^"]*","",g' < $file > $tmp
63
64

    grep '[	 ]$' $tmp &&
65
      diag 'Trailing whitespace.'
66

67
68
69
    case $file in
    *.test);;
    *)
70
71
72
      grep -E '[^<]class[ \t]+[A-Z]' $tmp &&
        diag 'Use lower case class names.'

73
74
      grep '[	 ]if(' $tmp &&
	diag 'Missing space after "if"'
75

76
77
      grep '[	 ]if (.*).*{' $tmp &&
	diag 'Opening { should be on its own line.'
78

79
80
      grep '[	 ]if (.*).*;' $tmp &&
	diag 'if body should be on another line.'
81

82
83
      grep '[	 ]else.*;' $tmp &&
	diag 'else body should be on another line.'
84

85
86
      grep '[	 ]while(' $tmp &&
	diag 'Missing space after "while"'
87

88
89
      grep '[	 ]while (.*).*{' $tmp &&
	diag 'Opening { should be on its own line.'
90

91
92
      grep '[	 ]while (.*).*[^)];' $tmp &&
	diag 'while body should be on another line.'
93

94
95
      grep '[	 ]for(' $tmp &&
	diag 'Missing space after "for"'
96

97
98
      grep '[	 ]for (.*).*{' $tmp &&
	diag 'Opening { should be on its own line.'
99

100
101
      grep '[	 ]for (.*;.*;.*).*;' $tmp &&
	diag 'for body should be on another line.'
102

103
104
      grep '[	 ]switch(' $tmp &&
	diag 'Missing space after "switch"'
105

106
107
      grep '[	 ]switch (.*).*{' $tmp &&
	diag 'Opening { should be on its own line.'
108

109
110
      grep 'namespace .*{' $tmp &&
	diag 'Opening { should be on its own line.'
111

112
113
      grep 'class .*{' $tmp &&
	diag 'Opening { should be on its own line.'
114

115
116
      grep '( ' $tmp &&
	diag 'No space after opening (.'
117

118
119
      grep ' )' $tmp &&
	diag 'No space before closing ).'
120

121
122
      grep '! ' $tmp &&
	diag 'No space after unary operators (!).'
123

124
      grep ",[^ \"	%'\\\\]" $tmp &&
125
	diag 'Space after coma.'
126

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
127
128
      # The 'r' allows operator&&
      grep '[^	 r]&&[^	 ]' $tmp &&
129
	diag 'Space arround binary operators.'
130

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
131
132
133
134
135
136
      # The 'r' allows operator||
      grep '[^	 r]||[^	 ]' $tmp &&
	diag 'Space arround binary operators.'

      # The 'r' allows operator==
      grep '[^	 r][!<>=]=[^	 ]' $tmp &&
137
	diag 'Space arround binary operators.'
138

139
140
      grep '[	 ]default:[^:].*;' $tmp &&
	diag 'Label should be on their own line.'
141

142
143
      grep '[	 ]case.*:[^:].*;' $tmp &&
	diag 'Label should be on their own line.'
144

145
146
      grep '[	 ];' $tmp &&
	diag 'No space before semicolon.'
147

148
149
      grep -v 'for (.*;;)' $tmp | grep ';[^	 ")]' &&
	diag 'Must have space or newline after semicolon.'
150

151
152
      grep '}.*}' $tmp &&
	diag 'No two } on the same line.'
153

154
155
      grep '{.*{' $tmp &&
	diag 'No two { on the same line.'
156

157
158
      grep 'delete[	 ]*[(][^(]*[)];' $tmp &&
	diag 'No useless parentheses after delete.'
159

160
161
      grep 'return[	 ]*[(][^(]*[)];' $tmp &&
	diag 'No useless parentheses after return.'
162

163
164
      grep 'NULL' $tmp &&
	diag 'Use 0 instead of NULL.  NULL is not portable.'
165

166
167
168
169
      # 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.'
170

171
      egrep '^[^=*<]*([+][+]|--);' $tmp &&
172
	diag 'Take good habits: use ++i instead of i++ when you have the choice.'
173

174
175
      grep '[^a-zA-Z0-9_](\*[a-zA-Z0-9_]*)\.' $tmp &&
	diag 'Use "x->y", not "(*x).y"'
176

177
178
      grep 'std::hash' $tmp &&
	diag 'use Sgi:: for hash and hash_map'
179

180
181
      grep 'Sgi::[^h]' $tmp &&
	diag 'Sgi:: is for hash and hash_map only'
182

183
184
185
      egrep 'bdd_(false|true)[	]*\(' $tmp &&
	diag 'Use bddfalse and bddtrue instead of bdd_false() and bdd_true()'

186
187
188
189
190
191
192
      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
193

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
      case $file in
	*.hh | *.hxx)
	  if egrep '(cout|cerr|clog)' $tmp >/dev/null; then
	    :
	  else
	    grep '#.*include.*<iostream>' $tmp &&
	      diag 'Avoid <iostream> in headers, better use <iosfwd>.'
	  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
      ;;
214
215
    esac

216

217
    $fail && echo "$file" >>failures
218
219

  done || : # Make sure sh does not abort when read exits with false.
220
221
done

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

# 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

243
244
245
246
247
248
if test -f failures; then
   echo "The following files contain style errors:"
   cat failures
   rm failures
   exit 1;
fi
249
250

exit 0