xref: /netbsd-src/external/gpl3/gcc/dist/contrib/check_GNU_style.sh (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1#!/bin/sh
2
3# Checks some of the GNU style formatting rules in a set of patches.
4# Copyright (C) 2010, 2012, 2016  Free Software Foundation, Inc.
5# Contributed by Sebastian Pop <sebastian.pop@amd.com>
6
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
11
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, see the file COPYING3.  If not,
19# see <http://www.gnu.org/licenses/>.
20
21# Set to empty in the environment to override.
22: ${color:---color=always}
23
24usage() {
25    cat <<EOF
26check_GNU_style.sh [patch]...
27
28    Checks the patches for some of the GNU style formatting problems.
29    When FILE is -, read standard input.
30
31    Please note that these checks are not always accurate, and
32    complete.  The reference documentation of the GNU Coding Standards
33    can be found here: http://www.gnu.org/prep/standards_toc.html
34    and there are also some additional coding conventions for GCC:
35    http://gcc.gnu.org/codingconventions.html
36
37EOF
38    exit 1
39}
40
41test $# -eq 0 && usage
42nfiles=$#
43files="$*"
44
45stdin=false
46stdin_tmp=""
47if [ $nfiles -eq 1 ] && [ "$files" = "-" ]; then
48    stdin=true
49
50    # By putting stdin into a temp file, we can handle it just like any other
51    # file.  F.i., we can cat it twice, which we can't do with stdin.
52    stdin_tmp=check_GNU_style.stdin
53    cat - > $stdin_tmp
54    files=$stdin_tmp
55else
56    for f in $files; do
57	if [ "$f" = "-" ]; then
58	    # Let's keep things simple.  Either we read from stdin, or we read
59	    # from files specified on the command line, not both.
60	    usage
61	fi
62	if [ ! -f "$f" ]; then
63	    echo "error: could not read file: $f"
64	    exit 1
65	fi
66    done
67fi
68
69inp=check_GNU_style.inp
70tmp=check_GNU_style.tmp
71tmp2=check_GNU_style.2.tmp
72tmp3=check_GNU_style.3.tmp
73
74# Remove $tmp on exit and various signals.
75trap "rm -f $inp $tmp $tmp2 $tmp3 $stdin_tmp" 0
76trap "rm -f $inp $tmp $tmp2 $tmp3 $stdin_tmp; exit 1" 1 2 3 5 9 13 15
77
78if [ $nfiles -eq 1 ]; then
79    # There's no need for the file prefix if we're dealing only with one file.
80    format="-n"
81else
82    format="-nH"
83fi
84grep $format '^+' $files \
85    | grep -v ':+++' \
86    > $inp
87
88cat_with_prefix ()
89{
90    local f="$1"
91
92    if [ "$prefix" = "" ]; then
93	cat "$f"
94    else
95	awk "{printf \"%s%s\n\", \"$prefix\", \$0}" $f
96    fi
97}
98
99# Grep
100g (){
101    local msg="$1"
102    local arg="$2"
103
104    local found=false
105    cat $inp \
106	| egrep $color -- "$arg" \
107	> "$tmp" && found=true
108
109    if $found; then
110	printf "\n$msg\n"
111	cat "$tmp"
112    fi
113}
114
115# And Grep
116ag (){
117    local msg="$1"
118    local arg1="$2"
119    local arg2="$3"
120
121    local found=false
122    cat $inp \
123	| egrep $color -- "$arg1" \
124	| egrep $color -- "$arg2" \
125	> "$tmp" && found=true
126
127    if $found; then
128	printf "\n$msg\n"
129	cat "$tmp"
130    fi
131}
132
133# reVerse Grep
134vg (){
135    local msg="$1"
136    local varg="$2"
137    local arg="$3"
138
139    local found=false
140    cat $inp \
141	| egrep -v -- "$varg" \
142	| egrep $color -- "$arg" \
143	> "$tmp" && found=true
144
145    if $found; then
146	printf "\n$msg\n"
147	cat "$tmp"
148    fi
149}
150
151col (){
152    local msg="$1"
153
154    local first=true
155    local f
156    for f in $files; do
157	prefix=""
158	if [ $nfiles -ne 1 ]; then
159	    prefix="$f:"
160	fi
161
162	# Don't reuse $inp, which may be generated using -H and thus contain a
163	# file prefix.
164	grep -n '^+' $f \
165	    | grep -v ':+++' \
166	    > $tmp
167
168	# Keep only line number prefix and patch modifier '+'.
169	cat "$tmp" \
170	    | sed 's/\(^[0-9][0-9]*:+\).*/\1/' \
171	    > "$tmp2"
172
173	# Remove line number prefix and patch modifier '+'.
174	# Expand tabs to spaces according to tab positions.
175	# Keep long lines, make short lines empty.  Print the part past 80 chars
176	# in red.
177        # Don't complain about dg-xxx directives in tests.
178	cat "$tmp" \
179	    | sed 's/^[0-9]*:+//' \
180	    | expand \
181	    | awk '$0 !~ /{[[:space:]]*dg-(error|warning|message)[[:space:]]/ { \
182		     if (length($0) > 80) \
183		       printf "%s\033[1;31m%s\033[0m\n", \
184			      substr($0,1,80), \
185			      substr($0,81); \
186		     else \
187		       print "" \
188		   }' \
189	    > "$tmp3"
190
191	# Combine prefix back with long lines.
192	# Filter out empty lines.
193	local found=false
194	paste -d '' "$tmp2" "$tmp3" \
195	    | grep -v '^[0-9][0-9]*:+$' \
196	    > "$tmp" && found=true
197
198	if $found; then
199	    if $first; then
200		printf "\n$msg\n"
201		first=false
202	    fi
203	    cat_with_prefix "$tmp"
204	fi
205    done
206}
207
208
209col 'Lines should not exceed 80 characters.'
210
211g 'Blocks of 8 spaces should be replaced with tabs.' \
212    ' {8}'
213
214g 'Trailing whitespace.' \
215    '[[:space:]]$'
216
217g 'Space before dot.' \
218    '[[:alnum:]][[:blank:]]+\.'
219
220g 'Dot, space, space, new sentence.' \
221    '[[:alnum:]]\.([[:blank:]]|[[:blank:]]{3,})[A-Z0-9]'
222
223g 'Dot, space, space, end of comment.' \
224    '[[:alnum:]]\.([[:blank:]]{0,1}|[[:blank:]]{3,})\*/'
225
226g 'Sentences should end with a dot.  Dot, space, space, end of the comment.' \
227    '[[:alnum:]][[:blank:]]*\*/'
228
229vg 'There should be exactly one space between function name and parenthesis.' \
230    '\#define' \
231    '[[:alnum:]]([[:blank:]]{2,})?\('
232
233g 'There should be no space before a left square bracket.' \
234   '[[:alnum:]][[:blank:]]+\['
235
236g 'There should be no space before closing parenthesis.' \
237    '[[:graph:]][[:blank:]]+\)'
238
239# This will give false positives for C99 compound literals.
240g 'Braces should be on a separate line.' \
241    '(\)|else)[[:blank:]]*{'
242
243# Does this apply to definitions of aggregate objects?
244ag 'Trailing operator.' \
245  '^[1-9][0-9]*:\+[[:space:]]' \
246  '(([^a-zA-Z_]\*)|([-%<=&|^?])|([^*]/)|([^:][+]))$'
247