#!/usr/bin/env python # -*- coding: utf-8 -*- import sys if len(sys.argv) < 2: print("Invalid usage of header_guards.py, it should be called with a path to one or multiple files.") sys.exit(1) changed = [] invalid = [] for file in sys.argv[1:]: header_start = -1 header_end = -1 with open(file.strip(), "rt", encoding="utf-8", newline="\n") as f: lines = f.readlines() for idx, line in enumerate(lines): sline = line.strip() if header_start < 0: if sline == "": # Skip empty lines at the top. continue if sline.startswith("/**********"): # Godot header starts this way. header_start = idx else: header_end = 0 # There is no Godot header. break else: if not sline.startswith(("*", "/*")): # Not in the Godot header anymore. header_end = idx + 1 # The guard should be two lines below the Godot header. break if (HEADER_CHECK_OFFSET := header_end) < 0 or HEADER_CHECK_OFFSET >= len(lines): invalid.append(file) continue if lines[HEADER_CHECK_OFFSET].startswith("#pragma once"): continue # Might be using legacy header guards. HEADER_BEGIN_OFFSET = HEADER_CHECK_OFFSET + 1 HEADER_END_OFFSET = len(lines) - 1 if HEADER_BEGIN_OFFSET >= HEADER_END_OFFSET: invalid.append(file) continue if ( lines[HEADER_CHECK_OFFSET].startswith("#ifndef") and lines[HEADER_BEGIN_OFFSET].startswith("#define") and lines[HEADER_END_OFFSET].startswith("#endif") ): lines[HEADER_CHECK_OFFSET] = "#pragma once" lines[HEADER_BEGIN_OFFSET] = "\n" lines.pop() with open(file, "wt", encoding="utf-8", newline="\n") as f: f.writelines(lines) changed.append(file) continue # Verify `#pragma once` doesn't exist at invalid location. misplaced = False for line in lines: if line.startswith("#pragma once"): misplaced = True break if misplaced: invalid.append(file) continue # Assume that we're simply missing a guard entirely. lines.insert(HEADER_CHECK_OFFSET, "#pragma once\n\n") with open(file, "wt", encoding="utf-8", newline="\n") as f: f.writelines(lines) changed.append(file) if changed: for file in changed: print(f"FIXED: {file}") if invalid: for file in invalid: print(f"REQUIRES MANUAL CHANGES: {file}") sys.exit(1)