diff --git a/dist/tools/headerguards/check.sh b/dist/tools/headerguards/check.sh new file mode 100755 index 0000000000000000000000000000000000000000..a3ba4f0d45a05cd7edff6aba7ad06ef62dfdcddf --- /dev/null +++ b/dist/tools/headerguards/check.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# Copyright 2017 Kaspar Schleiser <kaspar@schleiser.de> +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +: ${RIOTBASE:=$(pwd)} + +. ${RIOTBASE}/dist/tools/ci/changed_files.sh + +EXIT_CODE=0 + +filter() { + if [ $QUIET -eq 0 ]; then + cat + else + grep '^---' | cut -f 2 -d ' ' + fi +} + +_headercheck() { + OUT="$(${RIOTBASE}/dist/tools/headerguards/headerguards.py ${FILES} | filter)" + + if [ -n "$OUT" ]; then + EXIT_CODE=1 + echo "$OUT" + fi +} + +: ${FILES:=$(FILEREGEX='\.h$' changed_files)} + +if [ -z "${FILES}" ]; then + exit +fi + +: ${QUIET:=0} + +if [ -z "$*" ]; then + _headercheck +fi + +exit $EXIT_CODE diff --git a/dist/tools/headerguards/headerguards.py b/dist/tools/headerguards/headerguards.py new file mode 100755 index 0000000000000000000000000000000000000000..7affa3bd4fb2cb62c1738bcaaf4eb82fb284a910 --- /dev/null +++ b/dist/tools/headerguards/headerguards.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 + +import os, sys +import difflib +#from string import maketrans +from io import BytesIO, TextIOWrapper + +_in = "/-." +_out = "___" + +transtab = str.maketrans(_in, _out) + +def path_to_guardname(filepath): + res = filepath.upper().translate(transtab) + if res.startswith("_"): + res = "PRIV" + res + return res + +def get_guard_name(filepath): + parts = filepath.split(os.sep) + start = 0 + found = False + for i, part in enumerate(parts): + if part == "include": + found = True + start = i+1 + break + + if not found: + start = len(parts) -1 + + return path_to_guardname(os.path.join(*parts[start:])) + +def fix_headerguard(filename): + supposed = get_guard_name(filename) + with open(filename, "r",encoding='utf-8', errors='ignore') as f: + inlines = f.readlines() + + tmp = TextIOWrapper(BytesIO(), encoding="utf-8", errors="ignore") + tmp.seek(0) + + guard_found = 0 + guard_name = "" + ifstack = 0 + for n, line in enumerate(inlines): + if guard_found == 0: + if line.startswith("#ifndef"): + guard_found += 1 + guard_name = line[8:].rstrip() + line = "#ifndef %s\n" % (supposed) + elif guard_found == 1: + if line.startswith("#define") and line[8:].rstrip() == guard_name: + line = "#define %s\n" % (supposed) + guard_found += 1 + else: + break + elif guard_found == 2: + if line.startswith("#if"): + ifstack += 1 + elif line.startswith("#endif"): + if ifstack > 0: + ifstack -= 1 + else: + guard_found += 1 + line = "#endif /* %s */\n" % supposed + + tmp.write(line) + + tmp.seek(0) + if guard_found == 3: + for line in difflib.unified_diff(inlines, tmp.readlines(), "%s" % filename, "%s" % filename): + sys.stdout.write(line) + else: + print("%s: no / broken header guard" % filename, file=sys.stderr) + return False + +if __name__=="__main__": + error = False + for filename in sys.argv[1:]: + if fix_headerguard(filename) == False: + error = True + + if error: + sys.exit(1)