#!/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] ''' % 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)