From 1f8031f79a5f2af850d20dfff193e4d0571cb8d3 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 23 Apr 2021 12:04:58 +0200 Subject: *: 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 --- python/firstheader.py | 92 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 16 deletions(-) (limited to 'python') 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 \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)) -- cgit v1.2.3