warn_summary 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #!/bin/sh
  2. #
  3. # This script parses the output of a gcc bootstrap when using warning
  4. # flags and determines various statistics.
  5. #
  6. # usage: warn_summary [-llf] [-s stage] [-nosub|-ch|-cp|-f|-fortran|-ada|-intl|-fixinc]
  7. # [-pass|-wpass] [file(s)]
  8. #
  9. # -llf
  10. # Filter out long lines from the bootstrap output before any other
  11. # action. This is useful for systems with broken awks/greps which choke
  12. # on long lines. It is not done by default as it sometimes slows things
  13. # down.
  14. #
  15. # -s number
  16. # Take warnings from stage "Number". Stage 0 means show warnings from
  17. # before and after the gcc bootstrap directory. E.g. libraries, etc.
  18. # This presupposes using "gcc -W*" for the stage1 compiler.
  19. #
  20. # -nosub
  21. # Only show warnings from the gcc top level directory.
  22. # -ch|-cp|-f|-fortran|-ada|-intl|-fixinc
  23. # Only show warnings from the specified gcc subdirectory.
  24. # These override each other so only the last one passed takes effect.
  25. #
  26. # -pass
  27. # Pass through the bootstrap output after filtering stage and subdir
  28. # (useful for manual inspection.) This is all lines, not just warnings.
  29. # -wpass
  30. # Pass through only warnings from the bootstrap output after filtering
  31. # stage and subdir.
  32. #
  33. # By Kaveh Ghazi (ghazi@caip.rutgers.edu) 12/13/97.
  34. # Some awks choke on long lines, sed seems to do a better job.
  35. # Truncate lines > 255 characters. RE '.\{255,\}' doesn't seem to work. :-(
  36. # Only do this if -llf was specified, because it can really slow things down.
  37. longLineFilter()
  38. {
  39. if test -z "$llf" ; then
  40. cat
  41. else
  42. sed 's/^\(...............................................................................................................................................................................................................................................................\).*/\1/'
  43. fi
  44. }
  45. # This function does one of three things. It either passes through
  46. # all warning data, or passes through gcc toplevel warnings, or passes
  47. # through a particular subdirectory set of warnings.
  48. subdirectoryFilter()
  49. {
  50. longLineFilter | (
  51. if test -z "$filter" ; then
  52. # Pass through all lines.
  53. cat
  54. else
  55. if test "$filter" = nosub ; then
  56. # Omit all subdirectories.
  57. egrep -v '/gcc/(ch|cp|f|fortran|ada|intl|fixinc)/'
  58. else
  59. # Pass through only subdir $filter.
  60. grep "/gcc/$filter/"
  61. fi
  62. fi )
  63. }
  64. # This function displays all lines from stageN of the bootstrap. If
  65. # stage==0, then show lines prior to stage1 and lines from after the last
  66. # stage. I.e. utilities, libraries, etc.
  67. stageNfilter()
  68. {
  69. if test "$stageN" -lt 1 ; then
  70. # stage "0" means check everything *but* gcc.
  71. $AWK "BEGIN{t=1} ; /^Bootstrapping the compiler/{t=0} ; /^Building runtime libraries/{t=1} ; {if(t==1)print}"
  72. else
  73. if test "$stageN" -eq 1 ; then
  74. $AWK "/^Bootstrapping the compiler|^Building the C and C\+\+ compiler/{t=1} ; /stage$stageN/{t=0} ; {if(t==1)print}"
  75. else
  76. stageNminus1=`expr $stageN - 1`
  77. $AWK "/stage${stageNminus1}\//{t=1} ; /stage$stageN/{t=0} ; {if(t==1)print}"
  78. fi
  79. fi
  80. }
  81. # This function displays lines containing warnings.
  82. warningFilter()
  83. {
  84. grep ' warning: '
  85. }
  86. # This function replaces `xxx' with `???', where xxx is usually some
  87. # variable or function name. This allows similar warnings to be
  88. # counted together when summarizing. However it avoids replacing
  89. # certain C keywords which are known appear in various messages.
  90. keywordFilter() {
  91. sed 's/.*warning: //;
  92. s/`\(int\)'"'"'/"\1"/g;
  93. s/`\(long\)'"'"'/"\1"/g;
  94. s/`\(char\)'"'"'/"\1"/g;
  95. s/`\(inline\)'"'"'/"\1"/g;
  96. s/`\(else\)'"'"'/"\1"/g;
  97. s/`\(return\)'"'"'/"\1"/g;
  98. s/`\(static\)'"'"'/"\1"/g;
  99. s/`\(extern\)'"'"'/"\1"/g;
  100. s/`\(const\)'"'"'/"\1"/g;
  101. s/`\(noreturn\)'"'"'/"\1"/g;
  102. s/`\(longjmp\)'"'"' or `\(vfork\)'"'"'/"\1" or "\2"/g;
  103. s/'"[\`'][^']*'/"'"???"/g;
  104. s/.*format, .* arg (arg [0-9][0-9]*)/??? format, ??? arg (arg ???)/;
  105. s/\([( ]\)arg [0-9][0-9]*\([) ]\)/\1arg ???\2/;
  106. s/"\([^"]*\)"/`\1'"'"'/g'
  107. }
  108. # This function strips out relative pathnames for source files printed
  109. # by the warningFilter function. This is done so that as the snapshot
  110. # directory name changes every week, the output of this program can be
  111. # compared to previous runs without spurious diffs caused by source
  112. # directory name changes.
  113. srcdirFilter()
  114. {
  115. sed '
  116. s%^[^ ]*/\(gcc/\)%\1%;
  117. s%^[^ ]*/\(include/\)%\1%;
  118. s%^[^ ]*/\(texinfo/\)%\1%;
  119. s%^[^ ]*/\(fastjar/\)%\1%;
  120. s%^[^ ]*/\(zlib/\)%\1%;
  121. s%^[^ ]*/\(fixincludes/\)%\1%;
  122. s%^[^ ]*/\(sim/\)%\1%;
  123. s%^[^ ]*/\(newlib/\)%\1%;
  124. s%^[^ ]*/\(mpfr/\)%\1%;
  125. s%^[^ ]*/\(lib[a-z23+-]*/\)%\1%;'
  126. }
  127. # Start the main section.
  128. usage="usage: `basename $0` [-llf] [-s stage] [-nosub|-ch|-cp|-f|-fortran|-ada|-intl|-fixinc] [-pass|-wpass] [file(s)]"
  129. stageN=3
  130. tmpfile=${TMPDIR:-/tmp}/tmp-warn.$$
  131. # Remove $tmpfile on exit and various signals.
  132. trap "rm -f $tmpfile" 0
  133. trap "rm -f $tmpfile ; exit 1" 1 2 3 5 9 13 15
  134. # Find a good awk.
  135. if test -z "$AWK" ; then
  136. for AWK in gawk nawk awk ; do
  137. if type $AWK 2>&1 | grep 'not found' > /dev/null 2>&1 ; then
  138. :
  139. else
  140. break
  141. fi
  142. done
  143. fi
  144. # Parse command line arguments.
  145. while test -n "$1" ; do
  146. case "$1" in
  147. -llf) llf=1 ; shift ;;
  148. -s) if test -z "$2"; then echo $usage 1>&2; exit 1; fi
  149. stageN="$2"; shift 2 ;;
  150. -s*) stageN="`expr $1 : '-s\(.*\)'`" ; shift ;;
  151. -nosub|-ch|-cp|-f|-fortran|-ada|-intl|-fixinc) filter="`expr $1 : '-\(.*\)'`" ; shift ;;
  152. -pass) pass=1 ; shift ;;
  153. -wpass) pass=w ; shift ;;
  154. -*) echo $usage 1>&2 ; exit 1 ;;
  155. *) break ;;
  156. esac
  157. done
  158. # Check for a valid value of $stageN.
  159. case "$stageN" in
  160. [0-9]) ;;
  161. *) echo "Stage <$stageN> must be in the range [0..9]." 1>&2 ; exit 1 ;;
  162. esac
  163. for file in "$@" ; do
  164. stageNfilter < $file | subdirectoryFilter > $tmpfile
  165. # (Just) show me the warnings.
  166. if test "$pass" != '' ; then
  167. if test "$pass" = w ; then
  168. warningFilter < $tmpfile
  169. else
  170. cat $tmpfile
  171. fi
  172. continue
  173. fi
  174. if test -z "$filter" ; then
  175. echo "Counting all warnings,"
  176. else
  177. if test "$filter" = nosub ; then
  178. echo "Counting non-subdirectory warnings,"
  179. else
  180. echo "Counting warnings in the gcc/$filter subdirectory,"
  181. fi
  182. fi
  183. count=`warningFilter < $tmpfile | wc -l`
  184. echo there are $count warnings in stage$stageN of this bootstrap.
  185. echo
  186. echo Number of warnings per file:
  187. warningFilter < $tmpfile | srcdirFilter | $AWK -F: '{print$1}' | sort | \
  188. uniq -c | sort -nr
  189. echo
  190. echo Number of warning types:
  191. warningFilter < $tmpfile | keywordFilter | sort | uniq -c | sort -nr
  192. done