Home | History | Annotate | Download | only in scripts
      1 # -*- coding: utf-8 -*-
      2 
      3 import os
      4 import sys
      5 from fnmatch import fnmatch
      6 from optparse import OptionParser
      7 
      8 HEADER_PATTERNS				= ["*.hpp", "*.h"]
      9 INDENTED_INCLUDE_PREFIX		= "#\tinclude "
     10 IFNDEF_PREFIX				= "#ifndef "
     11 
     12 def getIncludeGuardName (headerFile):
     13 	return '_' + os.path.basename(headerFile).upper().replace('.', '_')
     14 
     15 def getRedundantIncludeGuardErrors (fileName):
     16 	f		= open(fileName, 'rb')
     17 	errors	= []
     18 
     19 	lineNumber = 1
     20 	prevLine = None
     21 	for line in f:
     22 		if line.startswith(INDENTED_INCLUDE_PREFIX):
     23 			if prevLine is not None and prevLine.startswith(IFNDEF_PREFIX):
     24 				ifndefName		= prevLine[len(IFNDEF_PREFIX):-1]			# \note -1 to take out the newline.
     25 				includeName		= line[len(INDENTED_INCLUDE_PREFIX)+1:-2]	# \note +1 to take out the beginning quote, -2 to take out the newline and the ending quote.
     26 				if getIncludeGuardName(includeName) != ifndefName:
     27 					errors.append("Invalid redundant include guard around line %d:" % lineNumber)
     28 					errors.append("guard is %s but included file is %s" % (ifndefName, includeName))
     29 
     30 		prevLine = line
     31 		lineNumber += 1
     32 
     33 	f.close()
     34 	return errors
     35 
     36 def isHeader (filename):
     37 	for pattern in HEADER_PATTERNS:
     38 		if fnmatch(filename, pattern):
     39 			return True
     40 	return False
     41 
     42 def getFileList (path):
     43 	allFiles = []
     44 	if os.path.isfile(path):
     45 		if isHeader(path):
     46 			allFiles.append(path)
     47 	else:
     48 		for root, dirs, files in os.walk(path):
     49 			for file in files:
     50 				if isHeader(file):
     51 					allFiles.append(os.path.join(root, file))
     52 	return allFiles
     53 
     54 if __name__ == "__main__":
     55 	parser = OptionParser()
     56 	parser.add_option("-q", "--quiet", action="store_true", dest="quiet", default=False, help="only print files with errors")
     57 
     58 	(options, args)	= parser.parse_args()
     59 	quiet			= options.quiet
     60 	files			= []
     61 	invalidFiles	= []
     62 
     63 	for dir in args:
     64 		files += getFileList(os.path.normpath(dir))
     65 
     66 	print "Checking..."
     67 	for file in files:
     68 		if not quiet:
     69 			print "  %s" % file
     70 
     71 		errors = getRedundantIncludeGuardErrors(file)
     72 		if errors:
     73 			if quiet:
     74 				print "  %s" % file
     75 			for err in errors:
     76 				print "    %s" % err
     77 			invalidFiles.append(file)
     78 
     79 	print ""
     80 	if len(invalidFiles) > 0:
     81 		print "Found %d files with invalid redundant include guards:" % len(invalidFiles)
     82 
     83 		for file in invalidFiles:
     84 			print "  %s" % file
     85 
     86 		sys.exit(-1)
     87 	else:
     88 		print "All files have valid redundant include guards."
     89