diff options
| author | David Lamparter <equinox@opensourcerouting.org> | 2021-04-23 12:04:58 +0200 |
|---|---|---|
| committer | David Lamparter <equinox@opensourcerouting.org> | 2021-04-23 12:06:35 +0200 |
| commit | 1f8031f79a5f2af850d20dfff193e4d0571cb8d3 (patch) | |
| tree | fdd3c88e8182b136650977972f9e6a478fcca29e /python | |
| parent | b38f1fd03dacfcd2536d96379f575156d3844ee9 (diff) | |
*: make sure `config.h` or `zebra.h` is first
`config.h` has all the defines from autoconf, which may include things
that switch behavior of other included headers (e.g. _GNU_SOURCE
enabling prototypes for additional functions.)
So, the first include in any `.c` file must be either `config.h` (with
the appropriate guard) or `zebra.h` (which includes `config.h` first
thing.)
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'python')
| -rw-r--r-- | python/firstheader.py | 92 |
1 files changed, 76 insertions, 16 deletions
diff --git a/python/firstheader.py b/python/firstheader.py index bf50f33a33..892e9da8d6 100644 --- a/python/firstheader.py +++ b/python/firstheader.py @@ -1,30 +1,90 @@ -# # check that the first header included in C files is either # zebra.h or config.h # +# Copyright (C) 2020 David Lamparter for NetDEF, Inc. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; see the file COPYING; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import sys, os, re, subprocess +import sys +import os +import re +import subprocess +import argparse + +argp = argparse.ArgumentParser(description="include fixer") +argp.add_argument("--autofix", action="store_const", const=True) +argp.add_argument("--warn-empty", action="store_const", const=True) +argp.add_argument("--pipe", action="store_const", const=True) include_re = re.compile('^#\s*include\s+["<]([^ ">]+)[">]', re.M) -errors = 0 +ignore = [ + lambda fn: fn.startswith("tools/"), + lambda fn: fn + in [ + "lib/elf_py.c", + ], +] + + +def run(args): + out = [] + + files = subprocess.check_output(["git", "ls-files"]).decode("ASCII") + for fn in files.splitlines(): + if not fn.endswith(".c"): + continue + if max([i(fn) for i in ignore]): + continue + + with open(fn, "r") as fd: + data = fd.read() -files = subprocess.check_output(["git", "ls-files"]).decode("ASCII") -for fn in files.splitlines(): - if not fn.endswith(".c"): - continue - if fn.startswith("tools/"): - continue - with open(fn, "r") as fd: - data = fd.read() m = include_re.search(data) if m is None: - # sys.stderr.write('no #include in %s?\n' % (fn)) + if args.warn_empty: + sys.stderr.write("no #include in %s?\n" % (fn)) continue if m.group(1) in ["config.h", "zebra.h", "lib/zebra.h"]: continue - sys.stderr.write("%s: %s\n" % (fn, m.group(0))) - errors += 1 -if errors: - sys.exit(1) + if args.autofix: + sys.stderr.write("%s: %s - fixing\n" % (fn, m.group(0))) + if fn.startswith("pceplib/"): + insert = '#ifdef HAVE_CONFIG_H\n#include "config.h"\n#endif\n\n' + else: + insert = "#include <zebra.h>\n\n" + + pos = m.span()[0] + + data = data[:pos] + insert + data[pos:] + with open(fn + ".new", "w") as fd: + fd.write(data) + os.rename(fn + ".new", fn) + else: + sys.stderr.write("%s: %s\n" % (fn, m.group(0))) + out.append(fn) + + if len(out): + if args.pipe: + # for "vim `firstheader.py`" + print("\n".join(out)) + return 1 + return 0 + + +if __name__ == "__main__": + args = argp.parse_args() + sys.exit(run(args)) |
