diff --git a/scripts/process-text-files.py b/scripts/process-text-files.py index 6eba642..82b4343 100644 --- a/scripts/process-text-files.py +++ b/scripts/process-text-files.py @@ -12,9 +12,12 @@ import subprocess import jwutils from jwutils.log import * -_exts_h = set([ '.h', '.H', '.hxx', '.HXX']) -_exts_cpp = set([ '.cpp', '.CPP', '.c', '.C', '.cxx', '.CXX' ]) -_exts_h_cpp = _exts_h | _exts_cpp +def _regexify(l): + return '|'.join(x.replace('.', '\.') + '$' for x in l) + +_exts_h = set([ '.h', '.H', '.hxx', '.HXX', '.hpp']) +_exts_cpp = set([ '.cpp', '.CPP', '.c', '.C', '.cxx', '.CXX' ]) +_exts_h_cpp = _exts_h | _exts_cpp # ----------------------------------------------------------------------------------- Base class @@ -252,45 +255,68 @@ class Cmd(jwutils.Cmd): if ext not in _exts_h: return False tok = re.sub('([A-Z])', '_\\1', name) - tok = re.sub('\.', '_', tok) + tok = re.sub('[.-]', '_', tok) ig = prefix + '_' + tok ig = re.sub('__', '_', ig) ig = ig.upper() # find first old ig + with open(path, 'r') as f: - data = f.read() - lines = data.splitlines() + odata = f.read() + lines = odata.splitlines() old = None + cand = None for line in iter(lines): - old = re.sub('^ *#[ \t]*ifndef[\t ]+([^ ]+)($|[ \t/;])', '\\1', line) - if old == line: - continue - #slog(NOTICE, "found MIP", old, "in", line) - break + if old is None: + if cand is None: + m = re.match('^\s*#\s*ifndef\s+(\w+)', line) + if m is not None: + cand = m.group(1) + else: + m = re.match('^\s*#\s*define\s+(\w+).*', line) + if m is None: + cand = None + continue + cand = None + old = m.group(1) + break if old is None: # TODO: add anyway at beginning and end raise Exception('No multiple inclusion preventer found in', path, ', not implemented') - data = '' + ndata = '' level = 0 + found = -1 + num=0 for line in iter(lines): - if re.match('^ *#[ \t]*if.?def[\t ]', line): + num += 1 + if re.match('^\s*#\s*(ifdef|ifndef|if)\s+[a-zA-Z0-9_(]', line): level += 1 - if re.match('^ *#[ \t]*ifndef[\t ]+' + old + '($|[ \t/;])', line): - data += '#ifndef ' + ig + '\n' + if found >= 0 or re.match('^\s*#\s*ifndef\s+(\w+)', line) is None: + ndata += line + '\n' continue - elif re.match('^ *#[ \t]*define[\t ]+' + old + '($|[ \t/;])', line): - data += '#define ' + ig + '\n' + found = level + ndata += '#ifndef ' + ig + '\n' continue - elif re.match('^ *#[ \t]*endif($|[ \t/;])', line): - level -= 1 - if level == 0: - data += '#endif /* ' + ig + ' */' + '\n' + elif re.match('^\s*#\s*define\s+' + old + '($|\s+)', line): + if found != level: + ndata += line + '\n' continue - data += line + '\n' - tmp = path + '.ig' - with open(tmp, 'w') as f: - f.write(data) - os.rename(tmp, path) + ndata += '#define ' + ig + '\n' + continue + elif re.match('^\s*#\s*endif($|\s.*)', line): + level -= 1 + if found != level + 1: + ndata += line + '\n' + continue + ndata += '#endif // ' + ig + '\n' + continue + ndata += line + '\n' + if odata != ndata: + slog(NOTICE, "+ fix include guards in", path) + tmp = path + '.ig' + with open(tmp, 'w') as f: + f.write(ndata) + os.rename(tmp, path) def add_parser(self, parsers): p = super(Cmd, self).add_parser(parsers) @@ -387,6 +413,23 @@ class CmdMkIndentEquals(Cmd): if self._replace_in_file(path, replacements, func=self._indent_pattern, context=context): slog(NOTICE, "+ aligned equals :", path) +class CmdCppFixIncludeGuard(Cmd): + + def __init__(self): + super(CmdCppFixIncludeGuard, self).__init__("cpp-fix-include-guard", "Standardize include guard in header files") + + def add_parser(self, parsers): + p = super(CmdCppFixIncludeGuard, self).add_parser(parsers) + p.add_argument('-P', '--ig-prefix', help="Prefix to include guard", default='') + p.set_defaults(name_regex=_regexify(_exts_h)) + return p + + def process(self, args, files): + slog(NOTICE, "Fixing include guard in", len(files), "header files:") + for dir, name in files: + path = dir + '/' + name + self._fix_include_guard(args.ig_prefix, path) + class CmdCppReplaceSymbols(Cmd): def __init__(self): @@ -454,7 +497,7 @@ class CmdCppIndentMacros(Cmd): p = super(CmdCppIndentMacros, self).add_parser(parsers) p.add_argument('-w', "--spaces", help="Number of spaces per indentation level", type=int, default=2) p.add_argument('-s', "--skip-outer", help="Skip the outmost macro (read multiple-inclusion guards)", action='store_true', default=True) - p.add_argument('-S', "--skip-outer-name-regex", help="Regex for file names that --skip-outer should be applied to", default="\.h$|\.H$|\.hpp$") + p.add_argument('-S', "--skip-outer-name-regex", help="Regex for file names that --skip-outer should be applied to", default=_regexify(_exts_h)) return p def process(self, args, files):