summaryrefslogtreecommitdiffstats
path: root/python/firstheader.py
blob: 892e9da8d650ffb7b3d97fdf17162e044686f5a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
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)

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

        m = include_re.search(data)
        if m is None:
            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

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