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 84 85# Remove the testsuite part of the diff. We don't care about GNU style 86# in testcases and the dg-* directives give too many false positives. 87remove_testsuite () 88{ 89 awk 'BEGIN{testsuite=0} /^(.*:)?([1-9][0-9]*:)?\+\+\+ / && ! /testsuite\//{testsuite=0} \ 90 {if (!testsuite) print} /^(.*:)?([1-9][0-9]*:)?\+\+\+ (.*\/)?testsuite\//{testsuite=1}' 91} 92 93grep $format '^+' $files \ 94 | remove_testsuite \ 95 | grep -v ':+++' \ 96 > $inp 97 98cat_with_prefix () 99{ 100 local f="$1" 101 102 if [ "$prefix" = "" ]; then 103 cat "$f" 104 else 105 awk "{printf \"%s%s\n\", \"$prefix\", \$0}" $f 106 fi 107} 108 109# Grep 110g (){ 111 local msg="$1" 112 local arg="$2" 113 114 local found=false 115 cat $inp \ 116 | egrep $color -- "$arg" \ 117 > "$tmp" && found=true 118 119 if $found; then 120 printf "\n$msg\n" 121 cat "$tmp" 122 fi 123} 124 125# And Grep 126ag (){ 127 local msg="$1" 128 local arg1="$2" 129 local arg2="$3" 130 131 local found=false 132 cat $inp \ 133 | egrep $color -- "$arg1" \ 134 | egrep $color -- "$arg2" \ 135 > "$tmp" && found=true 136 137 if $found; then 138 printf "\n$msg\n" 139 cat "$tmp" 140 fi 141} 142 143# reVerse Grep 144vg (){ 145 local msg="$1" 146 local varg="$2" 147 local arg="$3" 148 149 local found=false 150 cat $inp \ 151 | egrep -v -- "$varg" \ 152 | egrep $color -- "$arg" \ 153 > "$tmp" && found=true 154 155 if $found; then 156 printf "\n$msg\n" 157 cat "$tmp" 158 fi 159} 160 161col (){ 162 local msg="$1" 163 164 local first=true 165 local f 166 for f in $files; do 167 prefix="" 168 if [ $nfiles -ne 1 ]; then 169 prefix="$f:" 170 fi 171 172 # Don't reuse $inp, which may be generated using -H and thus contain a 173 # file prefix. Re-remove the testsuite since we're not using $inp. 174 cat $f | remove_testsuite \ 175 | grep -n '^+' \ 176 | grep -v ':+++' \ 177 > $tmp 178 179 # Keep only line number prefix and patch modifier '+'. 180 cat "$tmp" \ 181 | sed 's/\(^[0-9][0-9]*:+\).*/\1/' \ 182 > "$tmp2" 183 184 # Remove line number prefix and patch modifier '+'. 185 # Expand tabs to spaces according to tab positions. 186 # Keep long lines, make short lines empty. Print the part past 80 chars 187 # in red. 188 cat "$tmp" \ 189 | sed 's/^[0-9]*:+//' \ 190 | expand \ 191 | awk '{ \ 192 if (length($0) > 80) \ 193 printf "%s\033[1;31m%s\033[0m\n", \ 194 substr($0,1,80), \ 195 substr($0,81); \ 196 else \ 197 print "" \ 198 }' \ 199 > "$tmp3" 200 201 # Combine prefix back with long lines. 202 # Filter out empty lines. 203 local found=false 204 paste -d '\0' "$tmp2" "$tmp3" \ 205 | grep -v '^[0-9][0-9]*:+$' \ 206 > "$tmp" && found=true 207 208 if $found; then 209 if $first; then 210 printf "\n$msg\n" 211 first=false 212 fi 213 cat_with_prefix "$tmp" 214 fi 215 done 216} 217 218 219col 'Lines should not exceed 80 characters.' 220 221g 'Blocks of 8 spaces should be replaced with tabs.' \ 222 ' {8}' 223 224g 'Trailing whitespace.' \ 225 '[[:space:]]$' 226 227g 'Space before dot.' \ 228 '[[:alnum:]][[:blank:]]+\.' 229 230g 'Dot, space, space, new sentence.' \ 231 '[[:alnum:]]\.([[:blank:]]|[[:blank:]]{3,})[A-Z0-9]' 232 233g 'Dot, space, space, end of comment.' \ 234 '[[:alnum:]]\.([[:blank:]]{0,1}|[[:blank:]]{3,})\*/' 235 236g 'Sentences should end with a dot. Dot, space, space, end of the comment.' \ 237 '[[:alnum:]][[:blank:]]*\*/' 238 239vg 'There should be exactly one space between function name and parenthesis.' \ 240 '\#define' \ 241 '[[:alnum:]]([[:blank:]]{2,})?\(' 242 243g 'There should be no space before a left square bracket.' \ 244 '[[:alnum:]][[:blank:]]+\[' 245 246g 'There should be no space before closing parenthesis.' \ 247 '[[:graph:]][[:blank:]]+\)' 248 249# This will give false positives for C99 compound literals. 250g 'Braces should be on a separate line.' \ 251 '(\)|else)[[:blank:]]*{' 252 253# Does this apply to definitions of aggregate objects? 254ag 'Trailing operator.' \ 255 '^[1-9][0-9]*:\+[[:space:]]' \ 256 '(([^a-zA-Z_]\*)|([-%<=&|^?])|([^*]/)|([^:][+]))$' 257