1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- #!/usr/bin/python3
- # Copyright 2018 The Tor Project, Inc. See LICENSE file for licensing info.
- from __future__ import print_function
- import fnmatch
- import os
- import re
- import sys
- trouble = False
- def err(msg):
- global trouble
- trouble = True
- print(msg, file=sys.stderr)
- def fname_is_c(fname):
- return fname.endswith(".h") or fname.endswith(".c")
- INCLUDE_PATTERN = re.compile(r'\s*#\s*include\s+"([^"]*)"')
- RULES_FNAME = ".may_include"
- class Rules(object):
- def __init__(self, dirpath):
- self.dirpath = dirpath
- self.patterns = []
- self.usedPatterns = set()
- def addPattern(self, pattern):
- self.patterns.append(pattern)
- def includeOk(self, path):
- for pattern in self.patterns:
- if fnmatch.fnmatchcase(path, pattern):
- self.usedPatterns.add(pattern)
- return True
- return False
- def applyToLines(self, lines, context=""):
- lineno = 0
- for line in lines:
- lineno += 1
- m = INCLUDE_PATTERN.match(line)
- if m:
- include = m.group(1)
- if not self.includeOk(include):
- err("Forbidden include of {} on line {}{}".format(
- include, lineno, context))
- def applyToFile(self, fname):
- with open(fname, 'r') as f:
- #print(fname)
- self.applyToLines(iter(f), " of {}".format(fname))
- def noteUnusedRules(self):
- for p in self.patterns:
- if p not in self.usedPatterns:
- print("Pattern {} in {} was never used.".format(p, self.dirpath))
- def load_include_rules(fname):
- result = Rules(os.path.split(fname)[0])
- with open(fname, 'r') as f:
- for line in f:
- line = line.strip()
- if line.startswith("#") or not line:
- continue
- result.addPattern(line)
- return result
- list_unused = False
- for dirpath, dirnames, fnames in os.walk("src"):
- if ".may_include" in fnames:
- rules = load_include_rules(os.path.join(dirpath, RULES_FNAME))
- for fname in fnames:
- if fname_is_c(fname):
- rules.applyToFile(os.path.join(dirpath,fname))
- if list_unused:
- rules.noteUnusedRules()
- if trouble:
- err(
- """To change which includes are allowed in a C file, edit the {} files in its
- enclosing directory.""".format(RULES_FNAME))
- sys.exit(1)
|