header_guards.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import sys
  4. from pathlib import Path
  5. if len(sys.argv) < 2:
  6. print("Invalid usage of header_guards.py, it should be called with a path to one or multiple files.")
  7. sys.exit(1)
  8. HEADER_CHECK_OFFSET = 30
  9. HEADER_BEGIN_OFFSET = 31
  10. HEADER_END_OFFSET = -1
  11. changed = []
  12. invalid = []
  13. for file in sys.argv[1:]:
  14. with open(file, "rt", encoding="utf-8", newline="\n") as f:
  15. lines = f.readlines()
  16. if len(lines) <= HEADER_BEGIN_OFFSET:
  17. continue # Most likely a dummy file.
  18. if lines[HEADER_CHECK_OFFSET].startswith("#import"):
  19. continue # Early catch obj-c file.
  20. name = f"GODOT_{Path(file).name}".upper().replace(".", "_").replace("-", "_").replace(" ", "_")
  21. HEADER_CHECK = f"#ifndef {name}\n"
  22. HEADER_BEGIN = f"#define {name}\n"
  23. HEADER_END = f"#endif // {name}\n"
  24. if (
  25. lines[HEADER_CHECK_OFFSET] == HEADER_CHECK
  26. and lines[HEADER_BEGIN_OFFSET] == HEADER_BEGIN
  27. and lines[HEADER_END_OFFSET] == HEADER_END
  28. ):
  29. continue
  30. # Guards might exist but with the wrong names.
  31. if (
  32. lines[HEADER_CHECK_OFFSET].startswith("#ifndef")
  33. and lines[HEADER_BEGIN_OFFSET].startswith("#define")
  34. and lines[HEADER_END_OFFSET].startswith("#endif")
  35. ):
  36. lines[HEADER_CHECK_OFFSET] = HEADER_CHECK
  37. lines[HEADER_BEGIN_OFFSET] = HEADER_BEGIN
  38. lines[HEADER_END_OFFSET] = HEADER_END
  39. with open(file, "wt", encoding="utf-8", newline="\n") as f:
  40. f.writelines(lines)
  41. changed.append(file)
  42. continue
  43. header_check = -1
  44. header_begin = -1
  45. header_end = -1
  46. pragma_once = -1
  47. objc = False
  48. for idx, line in enumerate(lines):
  49. if not line.startswith("#"):
  50. continue
  51. elif line.startswith("#ifndef") and header_check == -1:
  52. header_check = idx
  53. elif line.startswith("#define") and header_begin == -1:
  54. header_begin = idx
  55. elif line.startswith("#endif") and header_end == -1:
  56. header_end = idx
  57. elif line.startswith("#pragma once"):
  58. pragma_once = idx
  59. break
  60. elif line.startswith("#import"):
  61. objc = True
  62. break
  63. if objc:
  64. continue
  65. if pragma_once != -1:
  66. lines.pop(pragma_once)
  67. lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
  68. lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
  69. lines.append("\n")
  70. lines.append(HEADER_END)
  71. with open(file, "wt", encoding="utf-8", newline="\n") as f:
  72. f.writelines(lines)
  73. changed.append(file)
  74. continue
  75. if header_check == -1 and header_begin == -1 and header_end == -1:
  76. # Guards simply didn't exist
  77. lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
  78. lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
  79. lines.append("\n")
  80. lines.append(HEADER_END)
  81. with open(file, "wt", encoding="utf-8", newline="\n") as f:
  82. f.writelines(lines)
  83. changed.append(file)
  84. continue
  85. if header_check != -1 and header_begin != -1 and header_end != -1:
  86. # All prepends "found", see if we can salvage this.
  87. if header_check == header_begin - 1 and header_begin < header_end:
  88. lines.pop(header_check)
  89. lines.pop(header_begin - 1)
  90. lines.pop(header_end - 2)
  91. if lines[header_end - 3] == "\n":
  92. lines.pop(header_end - 3)
  93. lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
  94. lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
  95. lines.append("\n")
  96. lines.append(HEADER_END)
  97. with open(file, "wt", encoding="utf-8", newline="\n") as f:
  98. f.writelines(lines)
  99. changed.append(file)
  100. continue
  101. invalid.append(file)
  102. if changed:
  103. for file in changed:
  104. print(f"FIXED: {file}")
  105. if invalid:
  106. for file in invalid:
  107. print(f"REQUIRES MANUAL CHANGES: {file}")
  108. sys.exit(1)