1#!/usr/local/bin/bash
2
3# -----------------------------------------------------------------------------
4
5# Check source-tree for anomalies
6#
7# Copyright (C) 2005-2007 by Ivo van Poorten
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22#
23# Thanks to Melchior Franz of the FlightGear project for the original idea
24# of a source-tree checker and Torinthiel for the feedback along the way.
25
26# $Id: checktree.sh 31415 2010-06-14 15:17:48Z diego $
27
28# -----------------------------------------------------------------------------
29
30# All yes/no flags. Spaces around flagnames are important!
31
32testflags=" spaces extensions crlf tabs trailws rcsid oll charset stupid gnu \
33res depr "
34allflags="$testflags showcont color head svn "
35
36# -----------------------------------------------------------------------------
37
38# Avoid locale problems
39
40export LC_ALL=C
41
42# -----------------------------------------------------------------------------
43
44# Helper functions
45
46set_all_tests() {
47    for i in $testflags ; do
48        eval _$i=$1
49    done
50}
51
52printoption() {
53    test -n "$3" && def=$3 || eval def=\$_$1
54    echo "  -(no)$1  $2 [default: $def]"
55}
56
57printhead() {
58    test "$_head" = "yes" && echo -e "$COLB$1$COLE"
59}
60
61all_filenames() {
62    test "$_files" != "" && echo "$_files" && return
63
64    if [ "$_svn" = "no" ]; then
65        find . -type f \
66        | grep -v "\.\#\|\~$\|\.depend\|\/\.svn\/\|config.mak\|^\./config\.h" \
67        | grep -v "^\./version\.h\|\.o$\|\.a$\|config.log\|^\./help_mp.h"
68    else
69        for p in . libavcodec libavutil libavformat libpostproc ; do
70            svn info -R $p 2>/dev/null | sed -n \
71                '/Path:/bb; :a; d; b; :b; s/Path: /.\//; h; :c; n;
72                 /Node Kind:/bd; bc; :d; /directory/ba; g; p;'
73        done
74    fi
75}
76
77# -----------------------------------------------------------------------------
78
79# Default settings
80
81set_all_tests no
82_spaces=yes
83_extensions=yes
84_crlf=yes
85
86_showcont=no
87_color=yes
88_head=yes
89_svn=yes
90_files=
91
92# Parse command line
93
94for i in "$@"; do
95    case "$i" in
96    -help|--help|-h|-\?)
97        echo -e "\n$0 [options] [files]\n"
98        echo -e "options:\n"
99        printoption "spaces    " "test for spaces in filenames"
100        printoption "extensions" "test for uppercase extensions"
101        printoption "crlf      " "test for MSDOS line endings"
102        printoption "tabs      " "test for tab characters"
103        printoption "trailws   " "test for trailing whitespace"
104        printoption "rcsid     " "test for missing RCS Id's"
105        printoption "oll       " "test for overly long lines"
106        printoption "charset   " "test for wrong charset"
107        printoption "stupid    " "test for stupid code"
108        printoption "gnu       " "test for GNUisms"
109        printoption "res       " "test for reserved identifiers"
110        printoption "depr      " "test for deprecated function calls"
111        echo
112        printoption "all       " "enable all tests" "no"
113        echo  "                   (-noall can be specified as -none)"
114        echo
115        printoption "showcont  " "show offending content of file(s)"
116        echo
117        printoption "color     " "colored output"
118        printoption "head      " "print heading for each test"
119        printoption "svn       " \
120                    "use svn info to determine which files to check"
121        echo -e "\nIf no files are specified, the whole tree is traversed."
122        echo -e "If there are, -(no)svn has no effect.\n"
123        exit
124        ;;
125    -all)
126        set_all_tests yes
127        ;;
128    -noall)
129        set_all_tests no
130        ;;
131    -none)
132        set_all_tests no
133        ;;
134    -*)
135        var=`echo X$i | sed 's/^X-//'`
136        val=yes
137        case "$var" in
138            no*)
139                var=`echo "$var" | cut -c 3-`
140                val=no
141                ;;
142        esac
143        case "$allflags" in
144            *\ $var\ *)
145                eval _$var=$val
146                ;;
147            *)
148                echo "unknown option: $i" >&2
149                exit 0
150                ;;
151        esac
152        ;;
153    *)
154        _files="$_files $i"
155        ;;
156    esac
157done
158
159# -----------------------------------------------------------------------------
160
161# Set heading color
162
163if [ "$_color" = "yes" ]; then
164    COLB="\e[36m"
165    COLE="\e[m"
166else
167    COLB=""
168    COLE=""
169fi
170
171# Test presence of svn info
172
173if [ "$_svn" = "yes" -a ! -d .svn ] ; then
174    echo "No svn info available. Please use -nosvn." >&2
175    exit 1
176fi
177
178# Generate filelist once so -svn isn't _that_ much slower than -nosvn anymore
179
180filelist=`all_filenames`
181
182case "$_stupid$_res$_depr$_gnu" in
183    *yes*)
184    # generate 'shortlist' to avoid false positives in xpm files, docs, etc,
185    # when one only needs to check .c and .h files
186    chfilelist=`echo $filelist | tr ' ' '\n' | grep "[\.][ch]$"`
187    ;;
188esac
189
190if [ "$_showcont" = "yes" ]; then
191  _diffopts="-u"
192  _grepopts="-n -I"
193else
194  _diffopts="-q"
195  _grepopts="-l -I"
196fi
197
198TAB=`echo " " | tr ' ' '\011'`
199
200# -----------------------------------------------------------------------------
201
202# DO CHECKS
203
204# -----------------------------------------------------------------------------
205
206if [ "$_spaces" = "yes" ]; then
207    printhead "checking for spaces in filenames ..."
208    find . | grep " "
209fi
210
211# -----------------------------------------------------------------------------
212
213if [ "$_extensions" = "yes" ]; then
214    printhead "checking for uppercase extensions ..."
215    echo $filelist | grep "\.[[:upper:]]\+$" | grep -v "\.S$"
216fi
217
218# -----------------------------------------------------------------------------
219
220if [ "$_crlf" = "yes" ]; then
221    printhead "checking for MSDOS line endings ..."
222    CR=`echo " " | tr ' ' '\015'`
223    grep $_grepopts "$CR" $filelist
224fi
225
226# -----------------------------------------------------------------------------
227
228if [ "$_tabs" = "yes" ]; then
229    printhead "checking for TAB characters ..."
230    grep $_grepopts "$TAB" $filelist
231fi
232
233# -----------------------------------------------------------------------------
234
235if [ "$_trailws" = "yes" ]; then
236    printhead "checking for trailing whitespace ..."
237    grep $_grepopts "[[:space:]]\+$" $filelist
238fi
239
240# -----------------------------------------------------------------------------
241
242if [ "$_rcsid" = "yes" ]; then
243    printhead "checking for missing RCS \$Id\$ or \$Revision\$ tags ..."
244    grep -L -I "\$\(Id\|Revision\)[[:print:]]\+\$" $filelist
245fi
246
247# -----------------------------------------------------------------------------
248
249if [ "$_oll" = "yes" ]; then
250    printhead "checking for overly long lines (over 79 characters) ..."
251    grep $_grepopts "^[[:print:]]\{80,\}$" $filelist
252fi
253
254# -----------------------------------------------------------------------------
255
256if [ "$_gnu" = "yes" -a -n "$chfilelist" ]; then
257    printhead "checking for GNUisms ..."
258    grep $_grepopts "case.*\.\.\..*:" $chfilelist
259fi
260
261# -----------------------------------------------------------------------------
262
263if [ "$_res" = "yes" -a -n "$chfilelist" ]; then
264    printhead "checking for reserved identifiers ..."
265    grep $_grepopts "#[ $TAB]*define[ $TAB]\+_[[:upper:]].*" $chfilelist
266    grep $_grepopts "#[ $TAB]*define[ $TAB]\+__.*" $chfilelist
267fi
268
269# -----------------------------------------------------------------------------
270
271if [ "$_charset" = "yes" ]; then
272    printhead "checking bad charsets ..."
273    for I in $filelist ; do
274      case "$I" in
275        ./help/help_mp-*.h)
276          ;;
277        ./DOCS/*)
278          ;;
279        *.c|*.h)
280          iconv -c -f ascii -t ascii "$I" | diff $_diffopts "$I" -
281          ;;
282      esac
283    done
284fi
285
286# -----------------------------------------------------------------------------
287
288if [ "$_stupid" = "yes" -a -n "$chfilelist" ]; then
289    printhead "checking for stupid code ..."
290
291    for i in calloc malloc realloc memalign av_malloc av_mallocz faad_malloc \
292             lzo_malloc safe_malloc mpeg2_malloc _ogg_malloc; do
293        printhead "--> casting of void* $i()"
294        grep $_grepopts "([ $TAB]*[a-zA-Z_]\+[ $TAB]*\*.*)[ $TAB]*$i" \
295                                                                    $chfilelist
296    done
297
298    for i in "" signed unsigned; do
299        printhead "--> usage of sizeof($i char)"
300        grep $_grepopts "sizeof[ $TAB]*([ $TAB]*$i[ $TAB]*char[ $TAB]*)" \
301                                                                    $chfilelist
302    done
303
304    for i in int8_t uint8_t; do
305        printhead "--> usage of sizeof($i)"
306        grep $_grepopts "sizeof[ $TAB]*([ $TAB]*$i[ $TAB]*)" $chfilelist
307    done
308
309    printhead "--> usage of &&1"
310    grep $_grepopts "&&[ $TAB]*1" $chfilelist
311
312    printhead "--> usage of ||0"
313    grep $_grepopts "||[ $TAB]*0" $chfilelist
314
315    # added a-fA-F_ to eliminate some false positives
316    printhead "--> usage of *0"
317    grep $_grepopts "[a-zA-Z0-9)]\+[ $TAB]*\*[ $TAB]*0[^.0-9xa-fA-F_]" \
318                                                                    $chfilelist
319
320    printhead "--> usage of *1"
321    grep $_grepopts "[a-zA-Z0-9)]\+[ $TAB]*\*[ $TAB]*1[^.0-9ea-fA-F_]" \
322                                                                    $chfilelist
323
324    printhead "--> usage of +0"
325    grep $_grepopts "[a-zA-Z0-9)]\+[ $TAB]*+[ $TAB]*0[^.0-9xa-fA-F_]" \
326                                                                    $chfilelist
327
328    printhead "--> usage of -0"
329    grep $_grepopts "[a-zA-Z0-9)]\+[ $TAB]*-[ $TAB]*0[^.0-9xa-fA-F_]" \
330                                                                    $chfilelist
331fi
332
333# -----------------------------------------------------------------------------
334
335if [ "$_depr" = "yes" -a -n "$chfilelist" ]; then
336    printhead "checking for deprecated and obsolete function calls ..."
337
338    for i in bcmp bcopy bzero getcwd getipnodebyname inet_ntoa inet_addr \
339        atoq ecvt fcvt ecvt_r fcvt_r qecvt_r qfcvt_r finite ftime gcvt herror \
340        hstrerror getpass getpw getutent getutid getutline pututline setutent \
341        endutent utmpname gsignal ssignal gsignal_r ssignal_r infnan memalign \
342        valloc re_comp re_exec drem dremf dreml rexec svc_getreq sigset \
343        sighold sigrelse sigignore sigvec sigmask sigblock sigsetmask \
344        siggetmask ualarm ulimit usleep statfs fstatfs ustat get_kernel_syms \
345        query_module sbrk tempnam tmpnam mktemp mkstemp
346    do
347        printhead "--> $i()"
348        grep $_grepopts "[^a-zA-Z0-9]$i[ $TAB]*(" $chfilelist
349    done
350fi
351