File: detect

package info (click to toggle)
widelands 1%3A17-3
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 332,404 kB
  • sloc: cpp: 104,978; python: 3,073; ada: 855; sh: 435; makefile: 225
file content (225 lines) | stat: -rwxr-xr-x 8,036 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#! /bin/sh
#
#  Detects style errors in the C++ source code. Run this from the top directory
#  (which has the subdirectories build, src and utils).
#
#  The output may include colour codes if and only if standard output is a
#  terminal.
#
#  Several check commands are used:
#  * grep with a set of regular expressions
#  * whitespace_checker (with detect_spurious_indentation.py as an inferior
#    fallback)
#  * krazy2 with a selected set of checks
#
#  Results are cached (there are separate caches for colour/nocolour). The
#  check commands do not write directly to a file at the cahce file location
#  because that could leave behind an incomplete cache file that is newer than
#  the source file in case that the check commands are interrupted. Instead
#  write the output from the check commands to a temporary file and when that
#  file is complete, move it to the cache file location.
#
#  Instead of storing empty cache files for source files that do not give any
#  errors, a per-directory timestamp file is stored. This drastically reduces
#  the number of cache files. The drawback is that if the script is interrupted
#  whilst checking a sequence of files with equal mtime, it will have to start
#  over with that sequence the next time it is executed. But reducing the
#  number of cache files is worth that minor inconvenience.
#
#  NOTE
#  This script uses [ FILE1 -nt FILE2 ] to test if FILE1 is newer than FILE2.
#  But it behaves differently in different shells. Bash behaves as the info
#  page for the test program from GNU Coreutils explains:
#    `FILE1 -nt FILE2'
#         True if FILE1 is newer (according to modification date) than
#         FILE2, or if FILE1 exists and FILE2 does not.
#
#  But zsh and dash behave differently in the case when FILE1 exits and FILE2
#  does not. Therefore the FILE1 -nt FILE2 tests in this script are followed by
#  || [ ! -e FILE2 ].
#
#  So if you are reading this script, only know bash and wonder about the
#  reduanancy; this is the reason for it.

CHECKER=utils/spurious_source_code/whitespace_checker
if [ ! -f $CHECKER ]; then
	echo "WARNING: $CHECKER does not exist!"
	echo "WARNING:    Go to utils/spurious_source_code and build it with make!"
	echo "WARNING:    Else many checks will be done much slower or not at all!"
	unset CHECKER
elif [ $CHECKER.adb -nt $CHECKER ]; then
	echo "ERROR: $CHECKER is out of date!!!"
	echo "ERROR:    Go to utils/spurious_source_code and rebuild it with make!"
	exit
fi

KRAZY2=$(which krazy2 2>/dev/null)
if [ -z $KRAZY2 ]; then
	KRAZY2=/usr/local/Krazy2/bin/krazy2
	if [ ! -f $KRAZY2 ]; then
		echo "WARNING: krazy2 does not exist!"
		echo "WARNING:    Get it from:"
		echo "WARNING:       svn://anonsvn.kde.org/home/kde/trunk/quality/krazy2"
		echo "WARNING:    Else you will submit code with i. a. spelling errors!"
		unset KRAZY2
	fi
fi

# Which C++ checks from krazy2 should we use?
#       captruefalse: use (fallback: regexps/using_macro_TRUE_FALSE)
#           constref: undecided
#          copyright: use
#                cpp: undecided (complains about __APPLE__ and __GNUC__)
#  doublequote_chars: only for Qt
#           doxytags: undecided
#           dpointer: only for shared libraries with binary compatibility reqs
#    emptystrcompare: only for Qt
#    endswithnewline: taken care of by whitespace_checker
#           explicit: use
#            foreach: undecided
#       i18ncheckarg: only for Qt
#          iconnames: only for KDE
#           includes: use
#             inline: use
#            license: use
#      nullstrassign: only for Qt
#     nullstrcompare: only for Qt
#          operators: use
#        passbyvalue: use
#          postfixop: use
#         qbytearray: only for Qt
#           qclasses: only for Qt
#           qconnect: only for Qt
#           qmethods: only for Qt
#            qminmax: only for Qt
#            qobject: only for Qt
#       sigsandslots: only for Qt
#           spelling: use
#            strings: use
#           syscalls: only for Qt
#           typedefs: only for Qt
#          camelcase: undecided
#       contractions: use
#            defines: undecided
#             kdebug: only for KDE
#       multiclasses: undecided
#               null: use
#             qenums: only for Qt
#              style: gives false positives
#        tipsandthis: only for Qt
KRAZY2CHECKS=captruefalse,copyright,explicit,includes,inline,license,operators,passbyvalue,postfixop,spelling,strings,contractions,null

#  Make sure that several instances of this script running concurrently each
#  have a separate temporary directory.
TMP_DIR=/tmp/spurious_source_code_detect.$PPID
rm -fr $TMP_DIR
mkdir $TMP_DIR || { echo "ERROR: could not create $TMP_DIR"; exit; }


REGEXPS_FILE=$TMP_DIR/regexps
for r in utils/spurious_source_code/regexps/*; do
	if
		[ -d $r ]                                                              &&
		[ ! -f $r/disabled ]                                                   &&
		( [ ! $CHECKER ]  || [ ! -f $r/redundant_with_whitespace_checker ] )   &&
		( [ ! $KRAZY2  ]  || [ ! -f $r/redundant_with_krazy2             ] )
	then
		cat $r/regexps >> $REGEXPS_FILE
	fi
done


[ -t 1 ] && COLOUR=.colourized || unset COLOUR


RESULT_FILE=$TMP_DIR/result

#  Runs all checks on single source file. The result is written to
#  $RESULT_FILE.
#
#  Requirements on the result:
#  * Error message lines must begin with <filename>:<linenumber> so that they
#    can be parsed by tools like KDevelop.
#  * Any colour codes produced by commands like "grep --colour" must be
#    included if and only if $COLOUR is set.
#
#  Parameters:
#    $1
#      The name of the source file to be checked.
check () {
	egrep --with-filename --line-number $([ $COLOUR ] && echo --colour=always) -f $REGEXPS_FILE $1 >  $RESULT_FILE
	if [ $CHECKER ]; then
		$CHECKER $1                                                                                 >> $RESULT_FILE
	else
		utils/detect_spurious_indentation.py $1                                                     >> $RESULT_FILE
	fi
	[ $KRAZY2 ] && $KRAZY2 --brief --export=textedit --check=$KRAZY2CHECKS $1                      >> $RESULT_FILE
}


CACHE_DIR="build/stylecheck"

#  Detects errors recursively and stores the result in a cache. The cache
#  content (if any) is echoed to standard output.
#
#  If a cached entry exists and is not older than the source file, no checks
#  are done on that source file.
#
#  Calls itself recursively for each subdirectory. Then checks all the source
#  files in the current directory that are newer than the timestamp file there.
#  Files are checked in mtime order, oldest first. After checking group of
#  files that have the same mtime, the timestamp is is set to that mtime.
#
#  Parameters:
#    $1
#      The name of the directory to start the search and check in.
detect () {
	for d in $1/*; do
		[ -d $d ] && detect $d
	done
	TIMESTAMP=$CACHE_DIR/$1/timestamp
	PREVIOUS_FILE=$1
	FILES=$(find $1 -maxdepth 1 -name "*.h" -or -name "*.cc")
	if [ -n "$FILES" ]; then
		FILES=$(ls -tr $FILES)
		mkdir -p $CACHE_DIR/$1
		for f in $(echo $FILES); do
			CACHE_BASE=$CACHE_DIR/$f.stylecheck
			CACHE_COLOUR=$CACHE_BASE.colourized
			CACHE=$CACHE_BASE$COLOUR
			if
				[ $f -nt $TIMESTAMP ] || [ ! -e $TIMESTAMP ]                     ||
				[ -s $CACHE_BASE ] || [ -s $CACHE_COLOUR ]
			then
				if [ $f -nt $CACHE ] || [ ! -e $CACHE ]; then
					echo "Checking for errors in $f ..."
					check $f
					if [ -s $RESULT_FILE ]; then
						mv $RESULT_FILE $CACHE
						cat $CACHE
					else
						rm -f $CACHE_BASE $CACHE_COLOUR
					fi
					if
						[ $f -nt $PREVIOUS_FILE ] &&
						( [ $PREVIOUS_FILE -nt $TIMESTAMP ] || [ ! -e $TIMESTAMP ] )
					then
						touch --reference=$PREVIOUS_FILE $TIMESTAMP
					fi
				else
					echo "Showing cached errors in $f ..."
					cat $CACHE
				fi
			fi
			PREVIOUS_FILE=$f
		done
		if [ $PREVIOUS_FILE -nt $TIMESTAMP ] || [ ! -e $TIMESTAMP ]; then
			touch --reference=$PREVIOUS_FILE $TIMESTAMP
		fi
	fi
}


detect src

rm -fr $TMP_DIR