| #!/usr/bin/env python | |
| # Copyright (c) 2006 The Regents of The University of Michigan | |
| # All rights reserved. | |
| # | |
| # Redistribution and use in source and binary forms, with or without | |
| # modification, are permitted provided that the following conditions are | |
| # met: redistributions of source code must retain the above copyright | |
| # notice, this list of conditions and the following disclaimer; | |
| # redistributions in binary form must reproduce the above copyright | |
| # notice, this list of conditions and the following disclaimer in the | |
| # documentation and/or other materials provided with the distribution; | |
| # neither the name of the copyright holders nor the names of its | |
| # contributors may be used to endorse or promote products derived from | |
| # this software without specific prior written permission. | |
| # | |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| # | |
| # Authors: Nathan Binkert | |
| from getopt import getopt, GetoptError | |
| import re | |
| import sys | |
| tabsize = 8 | |
| lead = re.compile(r'^([ \t])+') | |
| trail = re.compile(r'[ \t]+$') | |
| any_control = re.compile(r'\b(if|while|for)[ \t]*[(]') | |
| good_control = re.compile(r'\b(if|while|for) [(]') | |
| def linelen(line): | |
| tabs = line.count('\t') | |
| if not tabs: | |
| return len(line) | |
| count = 0 | |
| for c in line: | |
| if c == '\t': | |
| count += tabsize - count % tabsize | |
| else: | |
| count += 1 | |
| return count | |
| toolong = 0 | |
| toolong80 = 0 | |
| leadtabs = 0 | |
| trailwhite = 0 | |
| badcontrol = 0 | |
| cret = 0 | |
| def validate(filename, verbose, code): | |
| global toolong, toolong80, leadtabs, trailwhite, badcontrol, cret | |
| def msg(lineno, line, message): | |
| print '%s:%d>' % (filename, lineno + 1), message | |
| if verbose > 2: | |
| print line | |
| def bad(): | |
| if code is not None: | |
| sys.exit(code) | |
| cpp = filename.endswith('.cc') or filename.endswith('.hh') | |
| py = filename.endswith('.py') | |
| if py + cpp != 1: | |
| raise AttributeError, \ | |
| "I don't know how to deal with the file %s" % filename | |
| try: | |
| f = file(filename, 'r') | |
| except OSError: | |
| if verbose > 0: | |
| print 'could not open file %s' % filename | |
| bad() | |
| return | |
| for i,line in enumerate(f): | |
| line = line.rstrip('\n') | |
| # no carriage returns | |
| if line.find('\r') != -1: | |
| cret += 1 | |
| if verbose > 1: | |
| msg(i, line, 'carriage return found') | |
| bad() | |
| # lines max out at 79 chars | |
| llen = linelen(line) | |
| if llen > 79: | |
| toolong += 1 | |
| if llen == 80: | |
| toolong80 += 1 | |
| if verbose > 1: | |
| msg(i, line, 'line too long (%d chars)' % llen) | |
| bad() | |
| # no tabs used to indent | |
| match = lead.search(line) | |
| if match and match.group(1).find('\t') != -1: | |
| leadtabs += 1 | |
| if verbose > 1: | |
| msg(i, line, 'using tabs to indent') | |
| bad() | |
| # no trailing whitespace | |
| if trail.search(line): | |
| trailwhite +=1 | |
| if verbose > 1: | |
| msg(i, line, 'trailing whitespace') | |
| bad() | |
| # for c++, exactly one space betwen if/while/for and ( | |
| if cpp: | |
| match = any_control.search(line) | |
| if match and not good_control.search(line): | |
| badcontrol += 1 | |
| if verbose > 1: | |
| msg(i, line, 'improper spacing after %s' % match.group(1)) | |
| bad() | |
| if __name__ == '__main__': | |
| progname = sys.argv[0] | |
| def usage(code=None): | |
| print >>sys.stderr, '''%s [-n] [-q] [-v] <filenames>''' % progname | |
| if code is not None: | |
| sys.exit(code) | |
| try: | |
| opts, args = getopt(sys.argv[1:], '-nv') | |
| except GetoptError: | |
| usage(2) | |
| code = 1 | |
| verbose = 1 | |
| for opt,arg in opts: | |
| if opt == '-n': | |
| code = None | |
| if opt == '-q': | |
| verbose -= 1 | |
| if opt == '-v': | |
| verbose += 1 | |
| for filename in args: | |
| validate(filename, verbose=verbose, code=code) | |
| if verbose > 0: | |
| print '''\ | |
| %d violations of lines over 79 chars. %d of which are 80 chars exactly. | |
| %d cases of whitespace at the end of a line. | |
| %d cases of tabs to indent. | |
| %d bad parens after if/while/for. | |
| %d carriage returns found. | |
| ''' % (toolong, toolong80, trailwhite, leadtabs, badcontrol, cret) | |