check_GNU_style.sh 6.1 KB

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