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))  | 
