Add command cpp-fix-include-guard

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2019-03-16 11:37:20 +01:00
commit 7ac9cd7a69

View file

@ -12,7 +12,10 @@ import subprocess
import jwutils import jwutils
from jwutils.log import * from jwutils.log import *
_exts_h = set([ '.h', '.H', '.hxx', '.HXX']) 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_cpp = set([ '.cpp', '.CPP', '.c', '.C', '.cxx', '.CXX' ])
_exts_h_cpp = _exts_h | _exts_cpp _exts_h_cpp = _exts_h | _exts_cpp
@ -252,44 +255,67 @@ class Cmd(jwutils.Cmd):
if ext not in _exts_h: if ext not in _exts_h:
return False return False
tok = re.sub('([A-Z])', '_\\1', name) tok = re.sub('([A-Z])', '_\\1', name)
tok = re.sub('\.', '_', tok) tok = re.sub('[.-]', '_', tok)
ig = prefix + '_' + tok ig = prefix + '_' + tok
ig = re.sub('__', '_', ig) ig = re.sub('__', '_', ig)
ig = ig.upper() ig = ig.upper()
# find first old ig # find first old ig
with open(path, 'r') as f: with open(path, 'r') as f:
data = f.read() odata = f.read()
lines = data.splitlines() lines = odata.splitlines()
old = None old = None
cand = None
for line in iter(lines): for line in iter(lines):
old = re.sub('^ *#[ \t]*ifndef[\t ]+([^ ]+)($|[ \t/;])', '\\1', line) if old is None:
if old == line: 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 continue
#slog(NOTICE, "found MIP", old, "in", line) cand = None
old = m.group(1)
break break
if old is None: if old is None:
# TODO: add anyway at beginning and end # TODO: add anyway at beginning and end
raise Exception('No multiple inclusion preventer found in', path, ', not implemented') raise Exception('No multiple inclusion preventer found in', path, ', not implemented')
data = '' ndata = ''
level = 0 level = 0
found = -1
num=0
for line in iter(lines): 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 level += 1
if re.match('^ *#[ \t]*ifndef[\t ]+' + old + '($|[ \t/;])', line): if found >= 0 or re.match('^\s*#\s*ifndef\s+(\w+)', line) is None:
data += '#ifndef ' + ig + '\n' ndata += line + '\n'
continue continue
elif re.match('^ *#[ \t]*define[\t ]+' + old + '($|[ \t/;])', line): found = level
data += '#define ' + ig + '\n' ndata += '#ifndef ' + ig + '\n'
continue continue
elif re.match('^ *#[ \t]*endif($|[ \t/;])', line): elif re.match('^\s*#\s*define\s+' + old + '($|\s+)', line):
if found != level:
ndata += line + '\n'
continue
ndata += '#define ' + ig + '\n'
continue
elif re.match('^\s*#\s*endif($|\s.*)', line):
level -= 1 level -= 1
if level == 0: if found != level + 1:
data += '#endif /* ' + ig + ' */' + '\n' ndata += line + '\n'
continue continue
data += line + '\n' ndata += '#endif // ' + ig + '\n'
continue
ndata += line + '\n'
if odata != ndata:
slog(NOTICE, "+ fix include guards in", path)
tmp = path + '.ig' tmp = path + '.ig'
with open(tmp, 'w') as f: with open(tmp, 'w') as f:
f.write(data) f.write(ndata)
os.rename(tmp, path) os.rename(tmp, path)
def add_parser(self, parsers): def add_parser(self, parsers):
@ -387,6 +413,23 @@ class CmdMkIndentEquals(Cmd):
if self._replace_in_file(path, replacements, func=self._indent_pattern, context=context): if self._replace_in_file(path, replacements, func=self._indent_pattern, context=context):
slog(NOTICE, "+ aligned equals :", path) 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): class CmdCppReplaceSymbols(Cmd):
def __init__(self): def __init__(self):
@ -454,7 +497,7 @@ class CmdCppIndentMacros(Cmd):
p = super(CmdCppIndentMacros, self).add_parser(parsers) 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('-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", 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 return p
def process(self, args, files): def process(self, args, files):