|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# VirtualGL Style Checker, or |
| 4 | +# How I Learned to Stop Worrying and Love Regular Expressions |
| 5 | +# |
| 6 | +# Copyright (C)2018 D. R. Commander. All Rights Reserved. |
| 7 | +# |
| 8 | +# Redistribution and use in source and binary forms, with or without |
| 9 | +# modification, are permitted provided that the following conditions are met: |
| 10 | +# |
| 11 | +# - Redistributions of source code must retain the above copyright notice, |
| 12 | +# this list of conditions and the following disclaimer. |
| 13 | +# - Redistributions in binary form must reproduce the above copyright notice, |
| 14 | +# this list of conditions and the following disclaimer in the documentation |
| 15 | +# and/or other materials provided with the distribution. |
| 16 | +# - Neither the name of The VirtualGL Project nor the names of its |
| 17 | +# contributors may be used to endorse or promote products derived from this |
| 18 | +# software without specific prior written permission. |
| 19 | +# |
| 20 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", |
| 21 | +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 22 | +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 23 | +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
| 24 | +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 25 | +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 26 | +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 27 | +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 28 | +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 29 | +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 30 | +# POSSIBILITY OF SUCH DAMAGE. |
| 31 | + |
| 32 | +SCRIPTDIR=`dirname $0` |
| 33 | + |
| 34 | +set -f |
| 35 | + |
| 36 | +# Move along. Nothing to format here. |
| 37 | +FORMATTED="$(git ls-files -- glxdemos ':!glxdemos/glxspheres.c' ':!*CMakeLists.txt') diags/dsimple.c diags/dsimple.h include/boost/endian.hpp util/md5*.c include/md5.h server/xfonts.c" |
| 38 | +NFORMATTED=$(for i in $FORMATTED; do echo :!$i; done) |
| 39 | +EXCLFILES=':!.gitattributes :!ci/ :!doc/ :!common/glx*.h :!server/fltk/ :!server/xcb_headers/ :!*.rtf' |
| 40 | +FILES="./* $EXCLFILES" |
| 41 | + |
| 42 | +# C and C++ files |
| 43 | +CFILES='*.c *.cpp *.h *.h.in '$EXCLFILES |
| 44 | +NCFILES=':!*.c :!*.cpp :!*.h :!*.h.in' |
| 45 | + |
| 46 | +filter_quotes() |
| 47 | +{ |
| 48 | + pcregrep -v ':.*\"[^\"]*'"$EXPR"'[^\"]*\"' |
| 49 | +} |
| 50 | + |
| 51 | +grep_without_c_comments() |
| 52 | +{ |
| 53 | + git ls-files -- ${2+"$@"} | while read file; do |
| 54 | + "$SCRIPTDIR/remcomms.sh" $file | pcregrep "$1" | sed -E 's@^@'$file':@' |
| 55 | + done |
| 56 | +} |
| 57 | + |
| 58 | + |
| 59 | +echo |
| 60 | + |
| 61 | +echo '********** DETECTING WHITESPACE ERRORS **********' |
| 62 | + |
| 63 | +echo '---------- Stray tab characters ----------' |
| 64 | +echo |
| 65 | +git grep -P '[^^\n\t]\t' -- $FILES $NFORMATTED ':!common/rr.h' ':!server/rrtransport.h' |
| 66 | +git grep -E $'\t' -- $FORMATTED 'common/rr.h' 'server/rrtransport.h' |
| 67 | +echo |
| 68 | + |
| 69 | +echo '---------- Detecting spaces used for indentation ----------' |
| 70 | +echo |
| 71 | +EXPR='^ +' |
| 72 | +git grep -E "$EXPR" -- $FILES $NCFILES ':!*.md' ':!*.yml' ':!LGPL.txt' ':!LICENSE.txt' ':!cmakescripts/GNUInstallDirs.cmake' ':!cmakescripts/cmake_uninstall.cmake.in' ':!release/deb-control.in' |
| 73 | +# Process C[++] files separately, so we can parse out the comments |
| 74 | +grep_without_c_comments "$EXPR" $CFILES $NFORMATTED ':!common/rr.h' ':!server/rrtransport.h' |
| 75 | +unset EXPR |
| 76 | +echo |
| 77 | + |
| 78 | +echo '---------- Alt-Space ----------' |
| 79 | +echo |
| 80 | +git grep ' ' -- $FILES |
| 81 | +echo |
| 82 | + |
| 83 | +echo '---------- Blank line(s) at top of file ----------' |
| 84 | +echo |
| 85 | +git ls-files -- $FILES | while read file; do |
| 86 | + MATCH=`head -n1 $file | grep -E '^[ '$'\t]*$'` |
| 87 | + if [ $? = 0 ]; then |
| 88 | + echo $file:$MATCH |
| 89 | + fi |
| 90 | +done |
| 91 | +echo |
| 92 | + |
| 93 | +echo '---------- No blank line at end of file ----------' |
| 94 | +echo |
| 95 | +git ls-files -- $FILES | while read file; do |
| 96 | + pcregrep -ML '\n\Z$' $file |
| 97 | +done |
| 98 | +echo |
| 99 | + |
| 100 | +echo '---------- General whitespace errors ----------' |
| 101 | +echo |
| 102 | +git diff --check $(git rev-list HEAD | tail -n 1) -- $FILES |
| 103 | +echo |
| 104 | + |
| 105 | +echo # ************************************************************************ |
| 106 | + |
| 107 | + |
| 108 | +echo '********** DETECTING BAD LINE CONTINUATION SPACING **********' |
| 109 | + |
| 110 | +echo '---------- More than one space, no spaces ----------' |
| 111 | +echo |
| 112 | +git grep -P '[^ \t]+(\\| {2,}\\)$' -- $FILES |
| 113 | +echo |
| 114 | + |
| 115 | +echo '---------- Blank line using spaces instead of tabs ----------' |
| 116 | +echo |
| 117 | +git grep -P '^[\t]* +[\t]*\\' -- $FILES |
| 118 | +echo |
| 119 | + |
| 120 | +echo # ************************************************************************ |
| 121 | + |
| 122 | + |
| 123 | +echo '********** DETECTING ATTACHED else/catch **********' |
| 124 | +echo |
| 125 | +git grep -E '}.*(else|catch)[^}]+$' -- $FILES $NFORMATTED |
| 126 | +echo |
| 127 | + |
| 128 | +echo # ************************************************************************ |
| 129 | + |
| 130 | + |
| 131 | +echo '********** DETECTING INCORRECT BRACKET SPACING **********' |
| 132 | + |
| 133 | +echo '---------- Attached bracket ----------' |
| 134 | +echo |
| 135 | +EXCLEXPR='(?!extern \"C\" {)(?!namespace)(?!enum)(?!#define TRY\(\) try {)' |
| 136 | +git grep -P '^'"$EXCLEXPR"'.*[^ \t]+ *(?<!= )\{[^}]*$' -- $FILES $NFORMATTED |
| 137 | +unset EXCLEXPR |
| 138 | +echo |
| 139 | + |
| 140 | +echo '---------- {something ----------' |
| 141 | +echo |
| 142 | +git grep -E '\{[^ }]' -- $FILES $NFORMATTED ':!*.md' ':!*CMakeLists.txt' ':!cmakescripts/' ':!client/vglconnect.in' ':!release/*.in' ':!server/vglgenkey' ':!server/vglrun.in' ':!server/vglserver_config' | |
| 143 | + filter_quotes |
| 144 | +echo |
| 145 | + |
| 146 | +echo '---------- { something ... ----------' |
| 147 | +echo |
| 148 | +EXCLEXPR='(?!{ \"Anaglyphic \(Green)' |
| 149 | +git grep -P '^[ \t]*'"$EXCLEXPR"'\{ [^\}\\]*$' -- $FILES |
| 150 | +unset EXCLEXPR |
| 151 | +echo |
| 152 | + |
| 153 | +echo '---------- something} ----------' |
| 154 | +echo |
| 155 | +git grep -P '[^ \{\t]}' -- $FILES $NFORMATTED ':!*.md' ':!*CMakeLists.txt' ':!cmakescripts/' ':!client/vglconnect.in' ':!release/*.in' ':!server/vglgenkey' ':!server/vglrun.in' ':!server/vglserver_config' | |
| 156 | + filter_quotes |
| 157 | +echo |
| 158 | + |
| 159 | +echo '---------- }something ----------' |
| 160 | +echo |
| 161 | +git grep -E '}[^ ;,\"]' -- $FILES ':!*.md' ':!*CMakeLists.txt' ':!cmakescripts/' ':!release/*.in' ':!server/vglgenkey' ':!server/vglserver_config' |
| 162 | +echo |
| 163 | + |
| 164 | +echo # ************************************************************************ |
| 165 | + |
| 166 | + |
| 167 | +echo '********** DETECTING INCORRECT STATEMENT SPACING **********' |
| 168 | + |
| 169 | +for statement in if for catch while do switch; do |
| 170 | + echo '---------- '$statement' ( ----------' |
| 171 | + echo |
| 172 | + git grep -E $statement' \(' -- $FILES $NFORMATTED ':!cmakescripts/GNUInstallDirs.cmake' ':!cmakescripts/cmake_uninstall.cmake.in' |
| 173 | + echo |
| 174 | +done |
| 175 | + |
| 176 | +echo '---------- Semicolon spacing in one-liners ----------' |
| 177 | +echo |
| 178 | +EXPR='; [^ \\}]' |
| 179 | +EXCLEXPR='(?!\t*for\()(?!\t*if\(.*\) for\()(?!\t*dstbptr = \&dstptr\[bindex\];)' |
| 180 | +grep_without_c_comments '^'"$EXCLEXPR"'.*'"$EXPR" $FILES $NFORMATTED ':!.travis.yml' ':!/*.txt' ':!client/vglconnect.in' ':!cmakescripts/' ':!release/*.in' ':!server/servertest.in' ':!server/vglgenkey' ':!server/vgllogin' ':!server/vglrun.in' ':!server/vglrun.vars.in' ':!server/vglserver_config' ':!util/utiltest*.in' |
| 181 | +unset EXPR |
| 182 | +unset EXCLEXPR |
| 183 | +echo |
| 184 | + |
| 185 | +echo # ************************************************************************ |
| 186 | + |
| 187 | + |
| 188 | +echo '********** DETECTING INCORRECT FUNCTION/TYPE CAST SPACING **********' |
| 189 | + |
| 190 | +echo '---------- (type*) ----------' |
| 191 | +echo |
| 192 | +git grep -E '[^ \(\*]\*\)' -- $FILES $NFORMATTED ':!client/vglconnect.in' ':!server/vglrun.in' ':!server/vglserver_config' |
| 193 | +echo |
| 194 | + |
| 195 | +echo '---------- (type**) ----------' |
| 196 | +echo |
| 197 | +git grep -E '[^ \*]\*\*\)' -- $FILES ':!BUILDING.md' |
| 198 | +echo |
| 199 | + |
| 200 | +echo '---------- (type) var ----------' |
| 201 | +echo |
| 202 | +grep_without_c_comments '(^|[\t ])\([^\*][^\)\> ]*\) [A-Za-z0-9_\(]' $FILES $NFORMATTED ':!*.md' ':!/L*.txt' ':!cmakescripts/' ':!release/' | |
| 203 | + filter_quotes |
| 204 | +echo |
| 205 | + |
| 206 | +echo # ************************************************************************ |
| 207 | + |
| 208 | + |
| 209 | +echo '********** DETECTING INCORRECT MACRO SPACING **********' |
| 210 | +echo |
| 211 | +EXCLEXPR='(?!#define LOAD_XCB_SYMBOL\()(?!#define VGL_THREAD_LOCAL\()' |
| 212 | +git ls-files -- $FILES $NFORMATTED | while read file; do |
| 213 | + pcregrep -H -M "$EXCLEXPR"'#define.*\\\n[^{\t]' $file |
| 214 | +done |
| 215 | +# #define something |
| 216 | +git grep -E '^#define {2,}' -- $FILES |
| 217 | +# #define something(...) something |
| 218 | +git grep -E '^#define [A-Za-z0-9_]+\([^\(\)]+\) [^ \(\\]' -- $FILES $NFORMATTED |
| 219 | +# #define something(...) something |
| 220 | +git grep -E '^#define [A-Za-z0-9_]+\([^\(\)]+\) {3,}[^ ]' -- $FILES $NFORMATTED |
| 221 | +# #define something something |
| 222 | +git grep -E '^#define [^\(\) ]+ [^ \\]' -- $FILES $NFORMATTED |
| 223 | +# #define something something |
| 224 | +git grep -E '^#define [^\(\) ]+ {3,}[^ \\]' -- $FILES $NFORMATTED |
| 225 | +unset EXCLEXPR |
| 226 | +echo |
| 227 | + |
| 228 | +echo # ************************************************************************ |
| 229 | + |
| 230 | + |
| 231 | +echo '********** DETECTING INCORRECT COMMA SPACING **********' |
| 232 | + |
| 233 | +echo '---------- [ ], ----------' |
| 234 | +echo |
| 235 | +git grep -E ' ,' -- $FILES |
| 236 | +echo |
| 237 | + |
| 238 | +echo '---------- ,something ----------' |
| 239 | +echo |
| 240 | +git grep -E ',[^ \"'\''\)]' -- $FILES $NFORMATTED ':!*CMakeLists.txt' ':!ChangeLog.md' ':!release/rpm.spec.in' ':!server/vglserver_config' |
| 241 | +echo |
| 242 | + |
| 243 | +echo # ************************************************************************ |
| 244 | + |
| 245 | + |
| 246 | +echo '********** DETECTING INCORRECT OPERATOR SPACING **********' |
| 247 | + |
| 248 | +echo '---------- Incorrect pointer operator spacing ----------' |
| 249 | +echo |
| 250 | +grep_without_c_comments '[^ /\*}\t]\* [^&]' -- $FILES $NFORMATTED ':!cmakescripts/' ':!release/*.in' ':!server/vglserver_config' |
| 251 | +echo |
| 252 | + |
| 253 | +echo '---------- Incorrect address operator spacing ----------' |
| 254 | +echo |
| 255 | +git grep -E '[^ \&]\&[ ]' -- $FILES |
| 256 | +echo |
| 257 | + |
| 258 | +# OPERATORS: |
| 259 | +# Assignment: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= |
| 260 | +# Arithmetic: +, -, *, /, % |
| 261 | +# Unary: +something, -something |
| 262 | +# Increment/decrement: ++something, something++, --something, something-- |
| 263 | +# Comparison: ==, !=, >, <, >=, <= |
| 264 | +# Logical: !, &&, || |
| 265 | +# Bitwise: ~, &, |, ^, <<, >> |
| 266 | + |
| 267 | +echo '---------- No space before other operators ----------' |
| 268 | +echo |
| 269 | +OP='(?!\-\>)(?!\+\+)(?!\-\-)(?!\*\*)([=\+\-\*/%&\|\^\!\<\>]*=|[\+\*/%]|\-(?![0-9])|\>+|\<+|&+|\|+|\^)' |
| 270 | +EXPR='[^ ]\b[\)\]]*'"$OP" |
| 271 | +EXCLEXPR='(?<!::operator=)(?<!&operator=)(?<!\VirtualWin\*)' |
| 272 | +grep_without_c_comments "$EXPR""$EXCLEXPR"'[^\)]' $FILES $NFORMATTED ':!*.md' ':!*CMakeLists.txt' ':!/L*.txt' ':!*.yml' ':!client/vglconnect.in' ':!cmakescripts/' ':!release/' ':!server/servertest.in' ':!server/vglgenkey' ':!server/vgllogin' ':!server/vglrun.in' ':!server/vglrun.vars.in' ':!server/vglserver_config' ':!util/*.in' | |
| 273 | + filter_quotes | |
| 274 | + pcregrep -v ':\t*#include \<.*\>' | |
| 275 | + pcregrep -v ':\t*template \<.*\>' | |
| 276 | + pcregrep -v ':#define HASH Hash\<' |
| 277 | + |
| 278 | +# Process ternary conditional operators separately, so we can filter out |
| 279 | +# cases and labels. |
| 280 | +EXPR='[^ ]\b[\)\]]*[?:]' |
| 281 | +grep_without_c_comments "$EXPR"'[^:]' $FILES $NFORMATTED ':!*.yml' ':!*.md' ':!*CMakeLists.txt' ':!/L*.txt' ':!client/vglconnect.in' ':!cmakescripts/' ':!release/*.in' ':!server/vgllogin' ':!server/vglrun.in' ':!server/vglrun.vars.in' ':!server/vglserver_config' | |
| 282 | + filter_quotes | |
| 283 | + grep -vE '(\.c|\.cpp|\.h):.*(case [A-Za-z0-9_]+|default):' |
| 284 | + |
| 285 | +unset EXPR |
| 286 | +unset EXCLEXPR |
| 287 | +echo |
| 288 | + |
| 289 | +echo '---------- No space after other operators ----------' |
| 290 | +echo |
| 291 | +# NOTE: We can't check for *something or &something effectively, because |
| 292 | +# there's no way to distinguish those errors from valid pointer/address |
| 293 | +# operators. We also can't check for -something effectively, because there's |
| 294 | +# no way to distinguish those errors from valid unary operators. We have to |
| 295 | +# hope that, if such errors exist, they will be caught by the something{op} |
| 296 | +# check. We also have to hope that someone will eventually write a decent |
| 297 | +# open source C style checker! |
| 298 | +OP='([=\+\-\*/%&\|\^\!\<\>]*=|[\+/%]|\>+|\<+|&&|\|+|\^)(?<!\-\>)(?<!\+\+)(?<!\-\-)' |
| 299 | +EXPR="$OP"'[\(]*\b[^ ]' |
| 300 | +grep_without_c_comments "$EXPR" $FILES $NFORMATTED ':!*.md' ':!*CMakeLists.txt' ':!/L*.txt' ':!*.yml' ':!client/vglconnect.in' ':!cmakescripts/' ':!release/' ':!server/servertest.in' ':!server/vglgenkey' ':!server/vgllogin' ':!server/vglrun.in' ':!server/vglrun.vars.in' ':!server/vglserver_config' ':!util/*.in' | |
| 301 | + filter_quotes | |
| 302 | + pcregrep -v ':\t*#include \<.*\>' | |
| 303 | + pcregrep -v ':\t*template \<.*\>' | |
| 304 | + pcregrep -v ':#define HASH Hash\<' |
| 305 | + |
| 306 | +# Process ternary conditional operators separately |
| 307 | +EXPR='[?:][\(]*\b[^ ]' |
| 308 | +grep_without_c_comments '[^:]'"$EXPR" $FILES ':!*.yml' ':!*.md' ':!client/vglconnect.in' ':!cmakescripts/' ':!release/*.in' ':!server/servertest.in' ':!server/vglrun.in' ':!util/utiltest.in' | |
| 309 | + filter_quotes |
| 310 | + |
| 311 | +unset EXPR |
| 312 | +echo |
| 313 | + |
| 314 | +echo '---------- [!|~] something ----------' |
| 315 | +echo |
| 316 | +git grep -E '[!~] \b' -- $FILES $NFORMATTED ':!server/vglserver_config' |
| 317 | +echo |
| 318 | + |
| 319 | +echo # ************************************************************************ |
| 320 | + |
| 321 | + |
| 322 | +echo '********** DETECTING INCORRECT OPERATOR CONTINUANCE **********' |
| 323 | +echo |
| 324 | + |
| 325 | +# In general, trailing operators are preferred, but those create readability |
| 326 | +# problems in continued expressions unless the continued expressions are |
| 327 | +# aligned under the open parenthesis, and aligning under the open parenthesis |
| 328 | +# creates problems unless you use spaces for indentation and aligning, and |
| 329 | +# using spaces for indentation and aligning creates wrist strain. The |
| 330 | +# VirtualGL formatting style attempts to balance the (sometimes competing) |
| 331 | +# goals of readability and ease of maintenance. |
| 332 | + |
| 333 | +OP='([\+\-\*/%&\|\^]*=|\>\>=|\<\<=|\?|\:)' |
| 334 | +EXPR='^ *'"$OP"' +' |
| 335 | +git grep -P "$EXPR" -- $FILES |
| 336 | + |
| 337 | +OP='([=\!\<\>]=|[\+\-\*/%]|\>+|\<+|&+|\|+|\^)' |
| 338 | +EXPR=' '"$OP"'($| \\$)' |
| 339 | +EXCLEXPR='(?<!xcb_glx_query_version_reply_t \*)(?<!xcb_query_extension_reply_t \*)' |
| 340 | +grep_without_c_comments "$EXPR""$EXCLEXPR" $FILES $NFORMATTED ':!*.yml' ':!*.md' ':!cmakescripts/' ':!include/vglutil.h' ':!release/*.in' ':!server/vglgenkey' ':!server/vglrun.vars.in' ':!util/utiltest*.in' |
| 341 | + |
| 342 | +unset EXPR |
| 343 | +unset EXCLEXPR |
| 344 | +echo |
| 345 | + |
| 346 | +echo # ************************************************************************ |
| 347 | + |
| 348 | + |
| 349 | +echo '********** DETECTING INCORRECT FUNCTION SPACING **********' |
| 350 | +echo |
| 351 | +EXPR='\b \(' |
| 352 | +EXCLEXPR='(?<!if \()(?<!delete \()(?<!else \()(?<!return \()' |
| 353 | +grep_without_c_comments "$EXPR""$EXCLEXPR"'[^\*]' $FILES $NFORMATTED ':!*.md' ':!*CMakeLists.txt' ':!/L*.txt' ':!*.yml' ':!client/vglconnect.in' ':!cmakescripts/' ':!release/' ':!server/vgllogin' ':!server/vglrun.in' ':!server/vglrun.vars.in' ':!server/vglserver_config' | |
| 354 | + filter_quotes |
| 355 | +unset EXPR |
| 356 | +unset EXCLEXPR |
| 357 | +echo |
| 358 | + |
| 359 | +echo # ************************************************************************ |
0 commit comments