diff --git a/.clang-format b/.clang-format
index 6b47069ca..30cf41020 100644
--- a/.clang-format
+++ b/.clang-format
@@ -24,6 +24,7 @@ AttributeMacros:
 BinPackArguments: false
 BinPackParameters: false
 BitFieldColonSpacing: Both
+BreakAfterAttributes: Always
 BreakBeforeBinaryOperators: NonAssignment
 BreakBeforeBraces: Attach
 BreakBeforeConceptDeclarations: true
@@ -60,6 +61,8 @@ IndentPPDirectives: BeforeHash
 IndentRequires: true
 IndentWidth: 4
 IndentWrappedFunctionNames: true
+InsertBraces: true
+InsertNewlineAtEOF: true
 # Only support for Javascript as of clang-format 14...
 # InsertTrailingCommas: Wrapped
 KeepEmptyLinesAtTheStartOfBlocks: false
@@ -71,6 +74,8 @@ PPIndentWidth: -1
 PointerAlignment: Right
 QualifierAlignment: Right
 ReflowComments: true
+RemoveParentheses: ReturnStatement
+RemoveSemicolon: true
 SortIncludes: CaseSensitive
 SortUsingDeclarations: true
 SpaceAfterCStyleCast: false
diff --git a/include/asm/charmap.hpp b/include/asm/charmap.hpp
index 975ee8265..8c0415cff 100644
--- a/include/asm/charmap.hpp
+++ b/include/asm/charmap.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_CHARMAP_HPP
 #define RGBDS_ASM_CHARMAP_HPP
diff --git a/include/asm/fixpoint.hpp b/include/asm/fixpoint.hpp
index 7a1374f70..5fbd90850 100644
--- a/include/asm/fixpoint.hpp
+++ b/include/asm/fixpoint.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_FIXPOINT_HPP
 #define RGBDS_ASM_FIXPOINT_HPP
diff --git a/include/asm/format.hpp b/include/asm/format.hpp
index 2431b9238..9909aeb0e 100644
--- a/include/asm/format.hpp
+++ b/include/asm/format.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_FORMAT_HPP
 #define RGBDS_ASM_FORMAT_HPP
diff --git a/include/asm/fstack.hpp b/include/asm/fstack.hpp
index 53eba43fd..7b4befa9f 100644
--- a/include/asm/fstack.hpp
+++ b/include/asm/fstack.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 // Contains some assembler-wide defines and externs
 
diff --git a/include/asm/lexer.hpp b/include/asm/lexer.hpp
index 9ca6cfa5e..0052cab10 100644
--- a/include/asm/lexer.hpp
+++ b/include/asm/lexer.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_LEXER_HPP
 #define RGBDS_ASM_LEXER_HPP
diff --git a/include/asm/macro.hpp b/include/asm/macro.hpp
index a9c74437f..fb8041763 100644
--- a/include/asm/macro.hpp
+++ b/include/asm/macro.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_MACRO_HPP
 #define RGBDS_ASM_MACRO_HPP
diff --git a/include/asm/main.hpp b/include/asm/main.hpp
index 6521a7af8..0c29c5ece 100644
--- a/include/asm/main.hpp
+++ b/include/asm/main.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_MAIN_HPP
 #define RGBDS_ASM_MAIN_HPP
diff --git a/include/asm/opt.hpp b/include/asm/opt.hpp
index 1f81a63f7..a4f9f8e18 100644
--- a/include/asm/opt.hpp
+++ b/include/asm/opt.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_OPT_HPP
 #define RGBDS_ASM_OPT_HPP
diff --git a/include/asm/output.hpp b/include/asm/output.hpp
index 490f4448a..0112e1e7a 100644
--- a/include/asm/output.hpp
+++ b/include/asm/output.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_OUTPUT_HPP
 #define RGBDS_ASM_OUTPUT_HPP
@@ -14,14 +14,7 @@
 struct Expression;
 struct FileStackNode;
 
-enum StateFeature {
-    STATE_EQU,
-    STATE_VAR,
-    STATE_EQUS,
-    STATE_CHAR,
-    STATE_MACRO,
-    NB_STATE_FEATURES
-};
+enum StateFeature { STATE_EQU, STATE_VAR, STATE_EQUS, STATE_CHAR, STATE_MACRO, NB_STATE_FEATURES };
 
 extern std::string objectFileName;
 
diff --git a/include/asm/rpn.hpp b/include/asm/rpn.hpp
index 69d7700c3..28f2fb6c4 100644
--- a/include/asm/rpn.hpp
+++ b/include/asm/rpn.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_RPN_HPP
 #define RGBDS_ASM_RPN_HPP
@@ -31,12 +31,8 @@ struct Expression {
 
 	Expression &operator=(Expression &&) = default;
 
-	bool isKnown() const {
-		return data.holds<int32_t>();
-	}
-	int32_t value() const {
-		return data.get<int32_t>();
-	}
+	bool isKnown() const { return data.holds<int32_t>(); }
+	int32_t value() const { return data.get<int32_t>(); }
 
 	int32_t getConstVal() const;
 	Symbol const *symbolOf() const;
diff --git a/include/asm/section.hpp b/include/asm/section.hpp
index a89a4b0cf..a776bcc49 100644
--- a/include/asm/section.hpp
+++ b/include/asm/section.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_SECTION_HPP
 #define RGBDS_ASM_SECTION_HPP
diff --git a/include/asm/symbol.hpp b/include/asm/symbol.hpp
index 9aec71959..fc27e6b8a 100644
--- a/include/asm/symbol.hpp
+++ b/include/asm/symbol.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_SYMBOL_HPP
 #define RGBDS_ASM_SYMBOL_HPP
diff --git a/include/asm/warning.hpp b/include/asm/warning.hpp
index e2ca7d344..0bbc927a9 100644
--- a/include/asm/warning.hpp
+++ b/include/asm/warning.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ASM_WARNING_HPP
 #define RGBDS_ASM_WARNING_HPP
@@ -62,27 +62,24 @@ extern bool warningsAreErrors;
 
 void processWarningFlag(char const *flag);
 
-/*
- * Used to warn the user about problems that don't prevent the generation of
- * valid code.
- */
-[[gnu::format(printf, 2, 3)]] void warning(WarningID id, char const *fmt, ...);
-
-/*
- * Used for errors that compromise the whole assembly process by affecting the
- * following code, potencially making the assembler generate errors caused by
- * the first one and unrelated to the code that the assembler complains about.
- * It is also used when the assembler goes into an invalid state (for example,
- * when it fails to allocate memory).
- */
-[[gnu::format(printf, 1, 2), noreturn]] void fatalerror(char const *fmt, ...);
-
-/*
- * Used for errors that make it impossible to assemble correctly, but don't
- * affect the following code. The code will fail to assemble but the user will
- * get a list of all errors at the end, making it easier to fix all of them at
- * once.
- */
-[[gnu::format(printf, 1, 2)]] void error(char const *fmt, ...);
+// Used to warn the user about problems that don't prevent the generation of
+// valid code.
+[[gnu::format(printf, 2, 3)]]
+void warning(WarningID id, char const *fmt, ...);
+
+// Used for errors that compromise the whole assembly process by affecting the
+// following code, potencially making the assembler generate errors caused by
+// the first one and unrelated to the code that the assembler complains about.
+// It is also used when the assembler goes into an invalid state (for example,
+// when it fails to allocate memory).
+[[gnu::format(printf, 1, 2), noreturn]]
+void fatalerror(char const *fmt, ...);
+
+// Used for errors that make it impossible to assemble correctly, but don't
+// affect the following code. The code will fail to assemble but the user will
+// get a list of all errors at the end, making it easier to fix all of them at
+// once.
+[[gnu::format(printf, 1, 2)]]
+void error(char const *fmt, ...);
 
 #endif // RGBDS_ASM_WARNING_HPP
diff --git a/include/defaultinitvec.hpp b/include/defaultinitvec.hpp
index a656b68cb..949b243ff 100644
--- a/include/defaultinitvec.hpp
+++ b/include/defaultinitvec.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_DEFAULT_INIT_ALLOC_HPP
 #define RGBDS_DEFAULT_INIT_ALLOC_HPP
@@ -6,14 +6,11 @@
 #include <memory>
 #include <vector>
 
-/*
- * Allocator adaptor that interposes construct() calls to convert value-initialization
- * (which is what you get with e.g. `vector::resize`) into default-initialization (which does not
- * zero out non-class types).
- * From
- * https://stackoverflow.com/questions/21028299/is-this-behavior-of-vectorresizesize-type-n-under-c11-and-boost-container/21028912#21028912
- */
-
+// Allocator adaptor that interposes construct() calls to convert value-initialization
+// (which is what you get with e.g. `vector::resize`) into default-initialization (which does not
+// zero out non-class types).
+// From
+// https://stackoverflow.com/questions/21028299/is-this-behavior-of-vectorresizesize-type-n-under-c11-and-boost-container/21028912#21028912
 template<typename T, typename A = std::allocator<T>>
 class default_init_allocator : public A {
 	using a_t = std::allocator_traits<A>;
diff --git a/include/either.hpp b/include/either.hpp
index 54eae2c8f..06634c12b 100644
--- a/include/either.hpp
+++ b/include/either.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_EITHER_HPP
 #define RGBDS_EITHER_HPP
diff --git a/include/error.hpp b/include/error.hpp
index 5f8476d85..b353fd545 100644
--- a/include/error.hpp
+++ b/include/error.hpp
@@ -1,15 +1,18 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ERROR_HPP
 #define RGBDS_ERROR_HPP
 
 extern "C" {
+	[[gnu::format(printf, 1, 2)]]
+	void warn(char const *fmt...);
+	[[gnu::format(printf, 1, 2)]]
+	void warnx(char const *fmt, ...);
 
-[[gnu::format(printf, 1, 2)]] void warn(char const *fmt...);
-[[gnu::format(printf, 1, 2)]] void warnx(char const *fmt, ...);
-
-[[gnu::format(printf, 1, 2), noreturn]] void err(char const *fmt, ...);
-[[gnu::format(printf, 1, 2), noreturn]] void errx(char const *fmt, ...);
+	[[gnu::format(printf, 1, 2), noreturn]]
+	void err(char const *fmt, ...);
+	[[gnu::format(printf, 1, 2), noreturn]]
+	void errx(char const *fmt, ...);
 }
 
 #endif // RGBDS_ERROR_HPP
diff --git a/include/extern/getopt.hpp b/include/extern/getopt.hpp
index 68bda496a..ec9fa4f7a 100644
--- a/include/extern/getopt.hpp
+++ b/include/extern/getopt.hpp
@@ -1,11 +1,15 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
-/* This implementation was taken from musl and modified for RGBDS */
+// This implementation was taken from musl and modified for RGBDS
 
 #ifndef RGBDS_EXTERN_GETOPT_HPP
 #define RGBDS_EXTERN_GETOPT_HPP
 
-extern "C" {
+// clang-format off: vertically align values
+static constexpr int no_argument       = 0;
+static constexpr int required_argument = 1;
+static constexpr int optional_argument = 2;
+// clang-format on
 
 extern char *musl_optarg;
 extern int musl_optind, musl_opterr, musl_optopt, musl_optreset;
@@ -21,10 +25,4 @@ int musl_getopt_long_only(
     int argc, char **argv, char const *optstring, option const *longopts, int *idx
 );
 
-#define no_argument       0
-#define required_argument 1
-#define optional_argument 2
-
-} // extern "C"
-
 #endif // RGBDS_EXTERN_GETOPT_HPP
diff --git a/include/extern/utf8decoder.hpp b/include/extern/utf8decoder.hpp
index 499201736..66bdc2661 100644
--- a/include/extern/utf8decoder.hpp
+++ b/include/extern/utf8decoder.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_EXTERN_UTF8DECODER_HPP
 #define RGBDS_EXTERN_UTF8DECODER_HPP
diff --git a/include/file.hpp b/include/file.hpp
index 63f528ff7..57a007570 100644
--- a/include/file.hpp
+++ b/include/file.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_FILE_HPP
 #define RGBDS_FILE_HPP
@@ -25,10 +25,8 @@ class File {
 	File() {}
 	~File() { close(); }
 
-	/**
-	 * This should only be called once, and before doing any `->` operations.
-	 * Returns `nullptr` on error, and a non-null pointer otherwise.
-	 */
+	// This should only be called once, and before doing any `->` operations.
+	// Returns `nullptr` on error, and a non-null pointer otherwise.
 	File *open(std::string const &path, std::ios_base::openmode mode) {
 		if (path != "-") {
 			_file.emplace<std::filebuf>();
diff --git a/include/gfx/main.hpp b/include/gfx/main.hpp
index c3c7af6f1..28435b49b 100644
--- a/include/gfx/main.hpp
+++ b/include/gfx/main.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_GFX_MAIN_HPP
 #define RGBDS_GFX_MAIN_HPP
@@ -48,6 +48,7 @@ struct Options {
 
 	std::string input{}; // positional arg
 
+	// clang-format off: vertically align values
 	static constexpr uint8_t VERB_NONE    = 0; // Normal, no extra output
 	static constexpr uint8_t VERB_CFG     = 1; // Print configuration after parsing options
 	static constexpr uint8_t VERB_LOG_ACT = 2; // Log actions before doing them
@@ -55,7 +56,9 @@ struct Options {
 	static constexpr uint8_t VERB_DEBUG   = 4; // Internals are logged
 	static constexpr uint8_t VERB_TRACE   = 5; // Step-by-step algorithm details
 	static constexpr uint8_t VERB_VVVVVV  = 6; // What, can't I have a little fun?
-	[[gnu::format(printf, 3, 4)]] void verbosePrint(uint8_t level, char const *fmt, ...) const;
+	// clang-format on
+	[[gnu::format(printf, 3, 4)]]
+	void verbosePrint(uint8_t level, char const *fmt, ...) const;
 
 	mutable bool hasTransparentPixels = false;
 	uint8_t maxOpaqueColors() const { return nbColorsPerPal - hasTransparentPixels; }
@@ -63,32 +66,24 @@ struct Options {
 
 extern Options options;
 
-/*
- * Prints the error count, and exits with failure
- */
-[[noreturn]] void giveUp();
-/*
- * If any error has been emitted thus far, calls `giveUp()`.
- */
+// Prints the error count, and exits with failure
+[[noreturn]]
+void giveUp();
+// If any error has been emitted thus far, calls `giveUp()`.
 void requireZeroErrors();
-/*
- * Prints a warning, and does not change the error count
- */
-[[gnu::format(printf, 1, 2)]] void warning(char const *fmt, ...);
-/*
- * Prints an error, and increments the error count
- */
-[[gnu::format(printf, 1, 2)]] void error(char const *fmt, ...);
-/*
- * Prints an error, and increments the error count
- * Does not take format arguments so `format_` and `-Wformat-security` won't complain about
- * calling `errorMessage(msg)`.
- */
+// Prints a warning, and does not change the error count
+[[gnu::format(printf, 1, 2)]]
+void warning(char const *fmt, ...);
+// Prints an error, and increments the error count
+[[gnu::format(printf, 1, 2)]]
+void error(char const *fmt, ...);
+// Prints an error, and increments the error count
+// Does not take format arguments so `format_` and `-Wformat-security` won't complain about
+// calling `errorMessage(msg)`.
 void errorMessage(char const *msg);
-/*
- * Prints a fatal error, increments the error count, and gives up
- */
-[[gnu::format(printf, 1, 2), noreturn]] void fatal(char const *fmt, ...);
+// Prints a fatal error, increments the error count, and gives up
+[[gnu::format(printf, 1, 2), noreturn]]
+void fatal(char const *fmt, ...);
 
 struct Palette {
 	// An array of 4 GBC-native (RGB555) colors
diff --git a/include/gfx/pal_packing.hpp b/include/gfx/pal_packing.hpp
index 9f5693860..7b1aefd9d 100644
--- a/include/gfx/pal_packing.hpp
+++ b/include/gfx/pal_packing.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_GFX_PAL_PACKING_HPP
 #define RGBDS_GFX_PAL_PACKING_HPP
@@ -11,9 +11,7 @@
 struct Palette;
 class ProtoPalette;
 
-/*
- * Returns which palette each proto-palette maps to, and how many palettes are necessary
- */
+// Returns which palette each proto-palette maps to, and how many palettes are necessary
 std::tuple<DefaultInitVec<size_t>, size_t>
     overloadAndRemove(std::vector<ProtoPalette> const &protoPalettes);
 
diff --git a/include/gfx/pal_sorting.hpp b/include/gfx/pal_sorting.hpp
index 4d1015d36..a068efcc2 100644
--- a/include/gfx/pal_sorting.hpp
+++ b/include/gfx/pal_sorting.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_GFX_PAL_SORTING_HPP
 #define RGBDS_GFX_PAL_SORTING_HPP
diff --git a/include/gfx/pal_spec.hpp b/include/gfx/pal_spec.hpp
index b5f96953c..0b3abd4fa 100644
--- a/include/gfx/pal_spec.hpp
+++ b/include/gfx/pal_spec.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_GFX_PAL_SPEC_HPP
 #define RGBDS_GFX_PAL_SPEC_HPP
diff --git a/include/gfx/process.hpp b/include/gfx/process.hpp
index 9bff8f282..d0105ff2f 100644
--- a/include/gfx/process.hpp
+++ b/include/gfx/process.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_GFX_PROCESS_HPP
 #define RGBDS_GFX_PROCESS_HPP
diff --git a/include/gfx/proto_palette.hpp b/include/gfx/proto_palette.hpp
index 88f5476e9..7557ad695 100644
--- a/include/gfx/proto_palette.hpp
+++ b/include/gfx/proto_palette.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_GFX_PROTO_PALETTE_HPP
 #define RGBDS_GFX_PROTO_PALETTE_HPP
diff --git a/include/gfx/reverse.hpp b/include/gfx/reverse.hpp
index bc1fea5a9..d2aeb1226 100644
--- a/include/gfx/reverse.hpp
+++ b/include/gfx/reverse.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_GFX_REVERSE_HPP
 #define RGBDS_GFX_REVERSE_HPP
diff --git a/include/gfx/rgba.hpp b/include/gfx/rgba.hpp
index 9e2dcc5c4..be0ea510e 100644
--- a/include/gfx/rgba.hpp
+++ b/include/gfx/rgba.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_GFX_RGBA_HPP
 #define RGBDS_GFX_RGBA_HPP
@@ -13,9 +13,7 @@ struct Rgba {
 
 	constexpr Rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
 	    : red(r), green(g), blue(b), alpha(a) {}
-	/*
-	 * Constructs the color from a "packed" RGBA representation (0xRRGGBBAA)
-	 */
+	// Constructs the color from a "packed" RGBA representation (0xRRGGBBAA)
 	explicit constexpr Rgba(uint32_t rgba = 0)
 	    : red(rgba >> 24), green(rgba >> 16), blue(rgba >> 8), alpha(rgba) {}
 
@@ -32,10 +30,8 @@ struct Rgba {
 		};
 	}
 
-	/*
-	 * Returns this RGBA as a 32-bit number that can be printed in hex (`%08x`) to yield its CSS
-	 * representation
-	 */
+	// Returns this RGBA as a 32-bit number that can be printed in hex (`%08x`) to yield its CSS
+	// representation
 	uint32_t toCSS() const {
 		auto shl = [](uint8_t val, unsigned shift) { return static_cast<uint32_t>(val) << shift; };
 		return shl(red, 24) | shl(green, 16) | shl(blue, 8) | shl(alpha, 0);
@@ -43,19 +39,15 @@ struct Rgba {
 	bool operator==(Rgba const &rhs) const { return toCSS() == rhs.toCSS(); }
 	bool operator!=(Rgba const &rhs) const { return toCSS() != rhs.toCSS(); }
 
-	/*
-	 * CGB colors are RGB555, so we use bit 15 to signify that the color is transparent instead
-	 * Since the rest of the bits don't matter then, we return 0x8000 exactly.
-	 */
+	// CGB colors are RGB555, so we use bit 15 to signify that the color is transparent instead
+	// Since the rest of the bits don't matter then, we return 0x8000 exactly.
 	static constexpr uint16_t transparent = 0b1'00000'00000'00000;
 
 	static constexpr uint8_t transparency_threshold = 0x10;
 	bool isTransparent() const { return alpha < transparency_threshold; }
 	static constexpr uint8_t opacity_threshold = 0xF0;
 	bool isOpaque() const { return alpha >= opacity_threshold; }
-	/*
-	 * Computes the equivalent CGB color, respects the color curve depending on options
-	 */
+	// Computes the equivalent CGB color, respects the color curve depending on options
 	uint16_t cgbColor() const;
 
 	bool isGray() const { return red == green && green == blue; }
diff --git a/include/helpers.hpp b/include/helpers.hpp
index 55b406406..1fc732ccd 100644
--- a/include/helpers.hpp
+++ b/include/helpers.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_HELPERS_HPP
 #define RGBDS_HELPERS_HPP
@@ -14,7 +14,8 @@
 #else
 // This seems to generate similar code to __builtin_unreachable, despite different semantics
 // Note that executing this is undefined behavior (declared [[noreturn]], but does return)
-[[noreturn]] static inline void unreachable_() {
+[[noreturn]]
+static inline void unreachable_() {
 }
 #endif
 
@@ -26,8 +27,9 @@
 		//  `[[gnu::assume()]]` for GCC or compatible also has insufficient support (GCC 13+ only)
 		#define assume(x) \
 			do { \
-				if (!(x)) \
+				if (!(x)) { \
 					unreachable_(); \
+				} \
 			} while (0)
 	#endif
 #else
diff --git a/include/itertools.hpp b/include/itertools.hpp
index 09e2cba6b..4629b5216 100644
--- a/include/itertools.hpp
+++ b/include/itertools.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_ITERTOOLS_HPP
 #define RGBDS_ITERTOOLS_HPP
@@ -25,7 +25,7 @@ class EnumSeq {
 		auto operator*() const { return _value; }
 
 		bool operator==(Iterator const &rhs) const { return _value == rhs._value; }
-		bool operator!=(Iterator const &rhs) const  { return _value != rhs._value; }
+		bool operator!=(Iterator const &rhs) const { return _value != rhs._value; }
 	};
 
 public:
diff --git a/include/link/assign.hpp b/include/link/assign.hpp
index a64bb28fe..42fdbaded 100644
--- a/include/link/assign.hpp
+++ b/include/link/assign.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_LINK_ASSIGN_HPP
 #define RGBDS_LINK_ASSIGN_HPP
diff --git a/include/link/main.hpp b/include/link/main.hpp
index 99327cc12..4634f9b35 100644
--- a/include/link/main.hpp
+++ b/include/link/main.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_LINK_MAIN_HPP
 #define RGBDS_LINK_MAIN_HPP
@@ -32,8 +32,9 @@ extern bool disablePadding;
 // Helper macro for printing verbose-mode messages
 #define verbosePrint(...) \
 	do { \
-		if (beVerbose) \
+		if (beVerbose) { \
 			fprintf(stderr, __VA_ARGS__); \
+		} \
 	} while (0)
 
 struct FileStackNode {
@@ -58,11 +59,11 @@ struct FileStackNode {
 	std::string const &dump(uint32_t curLineNo) const;
 };
 
-[[gnu::format(printf, 3, 4)]] void
-    warning(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...);
-[[gnu::format(printf, 3, 4)]] void
-    error(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...);
-[[gnu::format(printf, 3, 4), noreturn]] void
-    fatal(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...);
+[[gnu::format(printf, 3, 4)]]
+void warning(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...);
+[[gnu::format(printf, 3, 4)]]
+void error(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...);
+[[gnu::format(printf, 3, 4), noreturn]]
+void fatal(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...);
 
 #endif // RGBDS_LINK_MAIN_HPP
diff --git a/include/link/object.hpp b/include/link/object.hpp
index 1b08cda98..1bb9270f8 100644
--- a/include/link/object.hpp
+++ b/include/link/object.hpp
@@ -1,19 +1,15 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_LINK_OBJECT_HPP
 #define RGBDS_LINK_OBJECT_HPP
 
-/*
- * Read an object (.o) file, and add its info to the data structures.
- * @param fileName A path to the object file to be read
- * @param i The ID of the file
- */
+// Read an object (.o) file, and add its info to the data structures.
+// @param fileName A path to the object file to be read
+// @param i The ID of the file
 void obj_ReadFile(char const *fileName, unsigned int i);
 
-/*
- * Sets up object file reading
- * @param nbFiles The number of object files that will be read
- */
+// Sets up object file reading
+// @param nbFiles The number of object files that will be read
 void obj_Setup(unsigned int nbFiles);
 
 #endif // RGBDS_LINK_OBJECT_HPP
diff --git a/include/link/output.hpp b/include/link/output.hpp
index 2a9af0ea2..e456632e2 100644
--- a/include/link/output.hpp
+++ b/include/link/output.hpp
@@ -1,26 +1,20 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_LINK_OUTPUT_HPP
 #define RGBDS_LINK_OUTPUT_HPP
 
 struct Section;
 
-/*
- * Registers a section for output.
- * @param section The section to add
- */
+// Registers a section for output.
+// @param section The section to add
 void out_AddSection(Section const &section);
 
-/*
- * Finds an assigned section overlapping another one.
- * @param section The section that is being overlapped
- * @return A section overlapping it
- */
+// Finds an assigned section overlapping another one.
+// @param section The section that is being overlapped
+// @return A section overlapping it
 Section const *out_OverlappingSection(Section const &section);
 
-/*
- * Writes all output (bin, sym, map) files.
- */
+// Writes all output (bin, sym, map) files.
 void out_WriteFiles();
 
 #endif // RGBDS_LINK_OUTPUT_HPP
diff --git a/include/link/patch.hpp b/include/link/patch.hpp
index 532ba50c8..240cfa5e3 100644
--- a/include/link/patch.hpp
+++ b/include/link/patch.hpp
@@ -1,17 +1,13 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_LINK_PATCH_HPP
 #define RGBDS_LINK_PATCH_HPP
 
-/*
- * Checks all assertions
- * @return true if assertion failed
- */
+// Checks all assertions
+// @return true if assertion failed
 void patch_CheckAssertions();
 
-/*
- * Applies all SECTIONs' patches to them
- */
+// Applies all SECTIONs' patches to them
 void patch_ApplyPatches();
 
 #endif // RGBDS_LINK_PATCH_HPP
diff --git a/include/link/sdas_obj.hpp b/include/link/sdas_obj.hpp
index c8b8cdf52..8acc5aa8b 100644
--- a/include/link/sdas_obj.hpp
+++ b/include/link/sdas_obj.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_LINK_SDAS_OBJ_HPP
 #define RGBDS_LINK_SDAS_OBJ_HPP
diff --git a/include/link/section.hpp b/include/link/section.hpp
index 09f7a4e34..b21f32d24 100644
--- a/include/link/section.hpp
+++ b/include/link/section.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_LINK_SECTION_HPP
 #define RGBDS_LINK_SECTION_HPP
@@ -65,29 +65,21 @@ struct Assertion {
 
 extern std::deque<Assertion> assertions;
 
-/*
- * Execute a callback for each section currently registered.
- * This is to avoid exposing the data structure in which sections are stored.
- * @param callback The function to call for each structure.
- */
+// Execute a callback for each section currently registered.
+// This is to avoid exposing the data structure in which sections are stored.
+// @param callback The function to call for each structure.
 void sect_ForEach(void (*callback)(Section &));
 
-/*
- * Registers a section to be processed.
- * @param section The section to register.
- */
+// Registers a section to be processed.
+// @param section The section to register.
 void sect_AddSection(std::unique_ptr<Section> &&section);
 
-/*
- * Finds a section by its name.
- * @param name The name of the section to look for
- * @return A pointer to the section, or `nullptr` if it wasn't found
- */
+// Finds a section by its name.
+// @param name The name of the section to look for
+// @return A pointer to the section, or `nullptr` if it wasn't found
 Section *sect_GetSection(std::string const &name);
 
-/*
- * Checks if all sections meet reasonable criteria, such as max size
- */
+// Checks if all sections meet reasonable criteria, such as max size
 void sect_DoSanityChecks();
 
 #endif // RGBDS_LINK_SECTION_HPP
diff --git a/include/link/symbol.hpp b/include/link/symbol.hpp
index f84d69744..4335c3bbc 100644
--- a/include/link/symbol.hpp
+++ b/include/link/symbol.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_LINK_SYMBOL_HPP
 #define RGBDS_LINK_SYMBOL_HPP
@@ -41,11 +41,9 @@ void sym_ForEach(void (*callback)(Symbol &));
 
 void sym_AddSymbol(Symbol &symbol);
 
-/*
- * Finds a symbol in all the defined symbols.
- * @param name The name of the symbol to look for
- * @return A pointer to the symbol, or `nullptr` if not found.
- */
+// Finds a symbol in all the defined symbols.
+// @param name The name of the symbol to look for
+// @return A pointer to the symbol, or `nullptr` if not found.
 Symbol *sym_GetSymbol(std::string const &name);
 
 void sym_DumpLocalAliasedSymbols(std::string const &name);
diff --git a/include/linkdefs.hpp b/include/linkdefs.hpp
index 2a18c6f43..4ac52ab14 100644
--- a/include/linkdefs.hpp
+++ b/include/linkdefs.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_LINKDEFS_HPP
 #define RGBDS_LINKDEFS_HPP
@@ -92,29 +92,23 @@ extern struct SectionTypeInfo {
 	uint32_t lastBank;
 } sectionTypeInfo[SECTTYPE_INVALID];
 
-/*
- * Tells whether a section has data in its object file definition,
- * depending on type.
- * @param type The section's type
- * @return `true` if the section's definition includes data
- */
+// Tells whether a section has data in its object file definition,
+// depending on type.
+// @param type The section's type
+// @return `true` if the section's definition includes data
 static inline bool sect_HasData(SectionType type) {
 	assume(type != SECTTYPE_INVALID);
 	return type == SECTTYPE_ROM0 || type == SECTTYPE_ROMX;
 }
 
-/*
- * Computes a memory region's end address (last byte), eg. 0x7FFF
- * @return The address of the last byte in that memory region
- */
+// Computes a memory region's end address (last byte), eg. 0x7FFF
+// @return The address of the last byte in that memory region
 static inline uint16_t endaddr(SectionType type) {
 	return sectionTypeInfo[type].startAddr + sectionTypeInfo[type].size - 1;
 }
 
-/*
- * Computes a memory region's number of banks
- * @return The number of banks, 1 for regions without banking
- */
+// Computes a memory region's number of banks
+// @return The number of banks, 1 for regions without banking
 static inline uint32_t nbbanks(SectionType type) {
 	return sectionTypeInfo[type].lastBank - sectionTypeInfo[type].firstBank + 1;
 }
diff --git a/include/opmath.hpp b/include/opmath.hpp
index e7df512f8..2c1433ca8 100644
--- a/include/opmath.hpp
+++ b/include/opmath.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_OP_MATH_HPP
 #define RGBDS_OP_MATH_HPP
diff --git a/include/platform.hpp b/include/platform.hpp
index ea0d65c23..8e71e71d1 100644
--- a/include/platform.hpp
+++ b/include/platform.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 // platform-specific hacks
 
diff --git a/include/util.hpp b/include/util.hpp
index b08edc538..a45de124f 100644
--- a/include/util.hpp
+++ b/include/util.hpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_UTIL_HPP
 #define RGBDS_UTIL_HPP
@@ -9,9 +9,7 @@
 
 char const *printChar(int c);
 
-/*
- * @return The number of bytes read, or 0 if invalid data was found
- */
+// @return The number of bytes read, or 0 if invalid data was found
 size_t readUTF8Char(std::vector<int32_t> *dest, char const *src);
 
 #endif // RGBDS_UTIL_HPP
diff --git a/include/version.hpp b/include/version.hpp
index f27d46af5..774f52df0 100644
--- a/include/version.hpp
+++ b/include/version.hpp
@@ -1,15 +1,12 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #ifndef RGBDS_VERSION_HPP
 #define RGBDS_VERSION_HPP
 
-extern "C" {
-
 #define PACKAGE_VERSION_MAJOR 0
 #define PACKAGE_VERSION_MINOR 9
 #define PACKAGE_VERSION_PATCH 0
 
 char const *get_package_version_string();
-}
 
 #endif // RGBDS_VERSION_H
diff --git a/src/asm/charmap.cpp b/src/asm/charmap.cpp
index 84678b87c..b5875ee1d 100644
--- a/src/asm/charmap.cpp
+++ b/src/asm/charmap.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/charmap.hpp"
 
@@ -45,20 +45,26 @@ bool charmap_ForEach(
 	for (Charmap const &charmap : charmapList) {
 		// Traverse the trie depth-first to derive the character mappings in definition order
 		std::map<size_t, std::string> mappings;
-		for (std::stack<std::pair<size_t, std::string>> prefixes({{0, ""}}); !prefixes.empty();) {
+		// clang-format off: nested initializers
+		for (std::stack<std::pair<size_t, std::string>> prefixes({{0, ""}});
+		     !prefixes.empty();) {
+			// clang-format on
 			auto [nodeIdx, mapping] = std::move(prefixes.top());
 			prefixes.pop();
 			CharmapNode const &node = charmap.nodes[nodeIdx];
-			if (node.isTerminal())
+			if (node.isTerminal()) {
 				mappings[nodeIdx] = mapping;
+			}
 			for (unsigned c = 0; c < 256; c++) {
-				if (size_t nextIdx = node.next[c]; nextIdx)
+				if (size_t nextIdx = node.next[c]; nextIdx) {
 					prefixes.push({nextIdx, mapping + static_cast<char>(c)});
+				}
 			}
 		}
 		mapFunc(charmap.name);
-		for (auto [nodeIdx, mapping] : mappings)
+		for (auto [nodeIdx, mapping] : mappings) {
 			charFunc(mapping, charmap.nodes[nodeIdx].value);
+		}
 	}
 	return !charmapList.empty();
 }
@@ -67,10 +73,11 @@ void charmap_New(std::string const &name, std::string const *baseName) {
 	size_t baseIdx = SIZE_MAX;
 
 	if (baseName != nullptr) {
-		if (auto search = charmapMap.find(*baseName); search == charmapMap.end())
+		if (auto search = charmapMap.find(*baseName); search == charmapMap.end()) {
 			error("Base charmap '%s' doesn't exist\n", baseName->c_str());
-		else
+		} else {
 			baseIdx = search->second;
+		}
 	}
 
 	if (charmapMap.find(name) != charmapMap.end()) {
@@ -82,10 +89,11 @@ void charmap_New(std::string const &name, std::string const *baseName) {
 	charmapMap[name] = charmapList.size();
 	Charmap &charmap = charmapList.emplace_back();
 
-	if (baseIdx != SIZE_MAX)
+	if (baseIdx != SIZE_MAX) {
 		charmap.nodes = charmapList[baseIdx].nodes; // Copies `charmapList[baseIdx].nodes`
-	else
+	} else {
 		charmap.nodes.emplace_back(); // Zero-init the root node
+	}
 
 	charmap.name = name;
 
@@ -93,10 +101,11 @@ void charmap_New(std::string const &name, std::string const *baseName) {
 }
 
 void charmap_Set(std::string const &name) {
-	if (auto search = charmapMap.find(name); search == charmapMap.end())
+	if (auto search = charmapMap.find(name); search == charmapMap.end()) {
 		error("Charmap '%s' doesn't exist\n", name.c_str());
-	else
+	} else {
 		currentCharmap = &charmapList[search->second];
+	}
 }
 
 void charmap_Push() {
@@ -146,8 +155,9 @@ void charmap_Add(std::string const &mapping, std::vector<int32_t> &&value) {
 
 	CharmapNode &node = charmap.nodes[nodeIdx];
 
-	if (node.isTerminal())
+	if (node.isTerminal()) {
 		warning(WARNING_CHARMAP_REDEF, "Overriding charmap mapping\n");
+	}
 
 	std::swap(node.value, value);
 }
@@ -159,8 +169,9 @@ bool charmap_HasChar(std::string const &input) {
 	for (char c : input) {
 		nodeIdx = charmap.nodes[nodeIdx].next[static_cast<uint8_t>(c)];
 
-		if (!nodeIdx)
+		if (!nodeIdx) {
 			return false;
+		}
 	}
 
 	return charmap.nodes[nodeIdx].isTerminal();
@@ -185,8 +196,9 @@ size_t charmap_ConvertNext(std::string_view &input, std::vector<int32_t> *output
 	for (size_t nodeIdx = 0; inputIdx < input.length();) {
 		nodeIdx = charmap.nodes[nodeIdx].next[static_cast<uint8_t>(input[inputIdx])];
 
-		if (!nodeIdx)
+		if (!nodeIdx) {
 			break;
+		}
 
 		inputIdx++; // Consume that char
 
@@ -206,8 +218,9 @@ size_t charmap_ConvertNext(std::string_view &input, std::vector<int32_t> *output
 	if (matchIdx) { // A match was found, use it
 		std::vector<int32_t> const &value = charmap.nodes[matchIdx].value;
 
-		if (output)
+		if (output) {
 			output->insert(output->end(), RANGE(value));
+		}
 
 		matchLen = value.size();
 	} else if (inputIdx < input.length()) { // No match found, but there is some input left
@@ -215,18 +228,20 @@ size_t charmap_ConvertNext(std::string_view &input, std::vector<int32_t> *output
 		// This will write the codepoint's value to `output`, little-endian
 		size_t codepointLen = readUTF8Char(output, input.data() + inputIdx);
 
-		if (codepointLen == 0)
+		if (codepointLen == 0) {
 			error("Input string is not valid UTF-8\n");
+		}
 
 		// Warn if this character is not mapped but any others are
-		if (charmap.nodes.size() > 1)
+		if (charmap.nodes.size() > 1) {
 			warning(WARNING_UNMAPPED_CHAR_1, "Unmapped character %s\n", printChar(firstChar));
-		else if (charmap.name != DEFAULT_CHARMAP_NAME)
+		} else if (charmap.name != DEFAULT_CHARMAP_NAME) {
 			warning(
 			    WARNING_UNMAPPED_CHAR_2,
 			    "Unmapped character %s not in " DEFAULT_CHARMAP_NAME " charmap\n",
 			    printChar(firstChar)
 			);
+		}
 
 		inputIdx += codepointLen;
 		matchLen = codepointLen;
diff --git a/src/asm/fixpoint.cpp b/src/asm/fixpoint.cpp
index a87a82ebf..d34a03a8d 100644
--- a/src/asm/fixpoint.cpp
+++ b/src/asm/fixpoint.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 // Fixed-point math routines
 
@@ -25,10 +25,12 @@ static double fix2double(int32_t i, int32_t q) {
 }
 
 static int32_t double2fix(double d, int32_t q) {
-	if (isnan(d))
+	if (isnan(d)) {
 		return 0;
-	if (isinf(d))
+	}
+	if (isinf(d)) {
 		return d < 0 ? INT32_MIN : INT32_MAX;
+	}
 	return static_cast<int32_t>(round(d * pow(2.0, q)));
 }
 
@@ -75,8 +77,9 @@ int32_t fix_Mul(int32_t i, int32_t j, int32_t q) {
 int32_t fix_Div(int32_t i, int32_t j, int32_t q) {
 	double dividend = fix2double(i, q);
 	double divisor = fix2double(j, q);
-	if (fpclassify(divisor) == FP_ZERO)
+	if (fpclassify(divisor) == FP_ZERO) {
 		return dividend < 0 ? INT32_MIN : dividend > 0 ? INT32_MAX : 0;
+	}
 	return double2fix(dividend / divisor, q);
 }
 
@@ -90,8 +93,9 @@ int32_t fix_Pow(int32_t i, int32_t j, int32_t q) {
 
 int32_t fix_Log(int32_t i, int32_t j, int32_t q) {
 	double divisor = log(fix2double(j, q));
-	if (fpclassify(divisor) == FP_ZERO)
+	if (fpclassify(divisor) == FP_ZERO) {
 		return INT32_MAX;
+	}
 	return double2fix(log(fix2double(i, q)) / divisor, q);
 }
 
diff --git a/src/asm/format.cpp b/src/asm/format.cpp
index 41457b594..f9ba9fe3f 100644
--- a/src/asm/format.cpp
+++ b/src/asm/format.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/format.hpp"
 
@@ -13,39 +13,44 @@
 #include "asm/warning.hpp"
 
 void FormatSpec::useCharacter(int c) {
-	if (state == FORMAT_INVALID)
+	if (state == FORMAT_INVALID) {
 		return;
+	}
 
 	switch (c) {
 	// sign
 	case ' ':
 	case '+':
-		if (state > FORMAT_SIGN)
+		if (state > FORMAT_SIGN) {
 			goto invalid;
+		}
 		state = FORMAT_EXACT;
 		sign = c;
 		break;
 
 	// exact
 	case '#':
-		if (state > FORMAT_EXACT)
+		if (state > FORMAT_EXACT) {
 			goto invalid;
+		}
 		state = FORMAT_ALIGN;
 		exact = true;
 		break;
 
 	// align
 	case '-':
-		if (state > FORMAT_ALIGN)
+		if (state > FORMAT_ALIGN) {
 			goto invalid;
+		}
 		state = FORMAT_WIDTH;
 		alignLeft = true;
 		break;
 
 	// pad, width, and prec values
 	case '0':
-		if (state < FORMAT_WIDTH)
+		if (state < FORMAT_WIDTH) {
 			padZero = true;
+		}
 		[[fallthrough]];
 	case '1':
 	case '2':
@@ -72,16 +77,18 @@ void FormatSpec::useCharacter(int c) {
 
 	// width
 	case '.':
-		if (state > FORMAT_WIDTH)
+		if (state > FORMAT_WIDTH) {
 			goto invalid;
+		}
 		state = FORMAT_FRAC;
 		hasFrac = true;
 		break;
 
 	// prec
 	case 'q':
-		if (state > FORMAT_PREC)
+		if (state > FORMAT_PREC) {
 			goto invalid;
+		}
 		state = FORMAT_PREC;
 		hasPrec = true;
 		break;
@@ -95,8 +102,9 @@ void FormatSpec::useCharacter(int c) {
 	case 'o':
 	case 'f':
 	case 's':
-		if (state >= FORMAT_DONE)
+		if (state >= FORMAT_DONE) {
 			goto invalid;
+		}
 		state = FORMAT_DONE;
 		valid = true;
 		type = c;
@@ -110,8 +118,9 @@ void FormatSpec::useCharacter(int c) {
 }
 
 void FormatSpec::finishCharacters() {
-	if (!isValid())
+	if (!isValid()) {
 		state = FORMAT_INVALID;
+	}
 }
 
 static std::string escapeString(std::string const &str) {
@@ -151,16 +160,21 @@ void FormatSpec::appendString(std::string &str, std::string const &value) const
 		useType = 's';
 	}
 
-	if (sign)
+	if (sign) {
 		error("Formatting string with sign flag '%c'\n", sign);
-	if (padZero)
+	}
+	if (padZero) {
 		error("Formatting string with padding flag '0'\n");
-	if (hasFrac)
+	}
+	if (hasFrac) {
 		error("Formatting string with fractional width\n");
-	if (hasPrec)
+	}
+	if (hasPrec) {
 		error("Formatting string with fractional precision\n");
-	if (useType != 's')
+	}
+	if (useType != 's') {
 		error("Formatting string as type '%c'\n", useType);
+	}
 
 	std::string useValue = exact ? escapeString(value) : value;
 	size_t valueLen = useValue.length();
@@ -187,22 +201,27 @@ void FormatSpec::appendNumber(std::string &str, uint32_t value) const {
 	}
 
 	if (useType != 'X' && useType != 'x' && useType != 'b' && useType != 'o' && useType != 'f'
-	    && useExact)
+	    && useExact) {
 		error("Formatting type '%c' with exact flag '#'\n", useType);
-	if (useType != 'f' && hasFrac)
+	}
+	if (useType != 'f' && hasFrac) {
 		error("Formatting type '%c' with fractional width\n", useType);
-	if (useType != 'f' && hasPrec)
+	}
+	if (useType != 'f' && hasPrec) {
 		error("Formatting type '%c' with fractional precision\n", useType);
-	if (useType == 's')
+	}
+	if (useType == 's') {
 		error("Formatting number as type 's'\n");
+	}
 
 	char signChar = sign; // 0 or ' ' or '+'
 
 	if (useType == 'd' || useType == 'f') {
 		if (int32_t v = value; v < 0) {
 			signChar = '-';
-			if (v != INT32_MIN)
+			if (v != INT32_MIN) {
 				value = -v;
+			}
 		}
 	}
 
@@ -250,10 +269,11 @@ void FormatSpec::appendNumber(std::string &str, uint32_t value) const {
 		}
 
 		double fval = fabs(value / pow(2.0, usePrec));
-		if (int fracWidthArg = static_cast<int>(useFracWidth); useExact)
+		if (int fracWidthArg = static_cast<int>(useFracWidth); useExact) {
 			snprintf(valueBuf, sizeof(valueBuf), "%.*fq%zu", fracWidthArg, fval, usePrec);
-		else
+		} else {
 			snprintf(valueBuf, sizeof(valueBuf), "%.*f", fracWidthArg, fval);
+		}
 	} else if (useType == 'd') {
 		// Decimal numbers may be formatted with a '-' sign by `snprintf`, so `abs` prevents that,
 		// with a special case for `INT32_MIN` since `labs(INT32_MIN)` is UB. The sign will be
@@ -278,27 +298,33 @@ void FormatSpec::appendNumber(std::string &str, uint32_t value) const {
 
 	str.reserve(str.length() + totalLen);
 	if (alignLeft) {
-		if (signChar)
+		if (signChar) {
 			str += signChar;
-		if (prefixChar)
+		}
+		if (prefixChar) {
 			str += prefixChar;
+		}
 		str.append(valueBuf);
 		str.append(padLen, ' ');
 	} else {
 		if (padZero) {
 			// sign, then prefix, then zero padding
-			if (signChar)
+			if (signChar) {
 				str += signChar;
-			if (prefixChar)
+			}
+			if (prefixChar) {
 				str += prefixChar;
+			}
 			str.append(padLen, '0');
 		} else {
 			// space padding, then sign, then prefix
 			str.append(padLen, ' ');
-			if (signChar)
+			if (signChar) {
 				str += signChar;
-			if (prefixChar)
+			}
+			if (prefixChar) {
 				str += prefixChar;
+			}
 		}
 		str.append(valueBuf);
 	}
diff --git a/src/asm/fstack.cpp b/src/asm/fstack.cpp
index ffca0e821..87bb85896 100644
--- a/src/asm/fstack.cpp
+++ b/src/asm/fstack.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/fstack.hpp"
 #include <sys/stat.h>
@@ -90,8 +90,9 @@ std::shared_ptr<std::string> fstk_GetUniqueIDStr() {
 	std::shared_ptr<std::string> &str = contextStack.top().uniqueIDStr;
 
 	// If a unique ID is allowed but has not been generated yet, generate one now.
-	if (str && str->empty())
+	if (str && str->empty()) {
 		*str = "_u"s + std::to_string(nextUniqueID++);
+	}
 
 	return str;
 }
@@ -103,27 +104,32 @@ MacroArgs *fstk_GetCurrentMacroArgs() {
 }
 
 void fstk_AddIncludePath(std::string const &path) {
-	if (path.empty())
+	if (path.empty()) {
 		return;
+	}
 
 	std::string &includePath = includePaths.emplace_back(path);
-	if (includePath.back() != '/')
+	if (includePath.back() != '/') {
 		includePath += '/';
+	}
 }
 
 void fstk_SetPreIncludeFile(std::string const &path) {
-	if (!preIncludeName.empty())
+	if (!preIncludeName.empty()) {
 		warnx("Overriding pre-included filename %s", preIncludeName.c_str());
+	}
 	preIncludeName = path;
-	if (verbose)
+	if (verbose) {
 		printf("Pre-included filename %s\n", preIncludeName.c_str());
+	}
 }
 
 static void printDep(std::string const &path) {
 	if (dependFile) {
 		fprintf(dependFile, "%s: %s\n", targetFileName.c_str(), path.c_str());
-		if (generatePhonyDeps)
+		if (generatePhonyDeps) {
 			fprintf(dependFile, "%s:\n", path.c_str());
+		}
 	}
 }
 
@@ -141,20 +147,22 @@ std::optional<std::string> fstk_FindFile(std::string const &path) {
 	}
 
 	errno = ENOENT;
-	if (generatedMissingIncludes)
+	if (generatedMissingIncludes) {
 		printDep(path);
+	}
 	return std::nullopt;
 }
 
 bool yywrap() {
 	uint32_t ifDepth = lexer_GetIFDepth();
 
-	if (ifDepth != 0)
+	if (ifDepth != 0) {
 		fatalerror(
 		    "Ended block with %" PRIu32 " unterminated IF construct%s\n",
 		    ifDepth,
 		    ifDepth == 1 ? "" : "s"
 		);
+	}
 
 	if (Context &context = contextStack.top(); context.fileInfo->type == NODE_REPT) {
 		// The context is a REPT or FOR block, which may loop
@@ -177,8 +185,9 @@ bool yywrap() {
 			Symbol *sym = sym_AddVar(context.forName, context.forValue);
 
 			// This error message will refer to the current iteration
-			if (sym->type != SYM_VAR)
+			if (sym->type != SYM_VAR) {
 				fatalerror("Failed to update FOR symbol value\n");
+			}
 		}
 		// Advance to the next iteration
 		fileInfoIters.front()++;
@@ -199,8 +208,9 @@ bool yywrap() {
 }
 
 static void checkRecursionDepth() {
-	if (contextStack.size() > maxRecursionDepth)
+	if (contextStack.size() > maxRecursionDepth) {
 		fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
+	}
 }
 
 static bool newFileContext(std::string const &filePath, bool updateStateNow) {
@@ -298,8 +308,9 @@ void fstk_RunInclude(std::string const &path, bool preInclude) {
 
 	if (!fullPath) {
 		if (generatedMissingIncludes && !preInclude) {
-			if (verbose)
+			if (verbose) {
 				printf("Aborting (-MG) on INCLUDE file '%s' (%s)\n", path.c_str(), strerror(errno));
+			}
 			failedOnMissingInclude = true;
 		} else {
 			error("Unable to open included file '%s': %s\n", path.c_str(), strerror(errno));
@@ -307,18 +318,20 @@ void fstk_RunInclude(std::string const &path, bool preInclude) {
 		return;
 	}
 
-	if (!newFileContext(*fullPath, false))
+	if (!newFileContext(*fullPath, false)) {
 		fatalerror("Failed to set up lexer for file include\n");
+	}
 }
 
 void fstk_RunMacro(std::string const &macroName, std::shared_ptr<MacroArgs> macroArgs) {
 	Symbol *macro = sym_FindExactSymbol(macroName);
 
 	if (!macro) {
-		if (sym_IsPurgedExact(macroName))
+		if (sym_IsPurgedExact(macroName)) {
 			error("Macro \"%s\" not defined; it was purged\n", macroName.c_str());
-		else
+		} else {
 			error("Macro \"%s\" not defined\n", macroName.c_str());
+		}
 		return;
 	}
 	if (macro->type != SYM_MACRO) {
@@ -330,8 +343,9 @@ void fstk_RunMacro(std::string const &macroName, std::shared_ptr<MacroArgs> macr
 }
 
 void fstk_RunRept(uint32_t count, int32_t reptLineNo, ContentSpan const &span) {
-	if (count == 0)
+	if (count == 0) {
 		return;
+	}
 
 	newReptContext(reptLineNo, span, count);
 }
@@ -344,24 +358,28 @@ void fstk_RunFor(
     int32_t reptLineNo,
     ContentSpan const &span
 ) {
-	if (Symbol *sym = sym_AddVar(symName, start); sym->type != SYM_VAR)
+	if (Symbol *sym = sym_AddVar(symName, start); sym->type != SYM_VAR) {
 		return;
+	}
 
 	uint32_t count = 0;
-	if (step > 0 && start < stop)
+	if (step > 0 && start < stop) {
 		count = (static_cast<int64_t>(stop) - start - 1) / step + 1;
-	else if (step < 0 && stop < start)
+	} else if (step < 0 && stop < start) {
 		count = (static_cast<int64_t>(start) - stop - 1) / -static_cast<int64_t>(step) + 1;
-	else if (step == 0)
+	} else if (step == 0) {
 		error("FOR cannot have a step value of 0\n");
+	}
 
-	if ((step > 0 && start > stop) || (step < 0 && start < stop))
+	if ((step > 0 && start > stop) || (step < 0 && start < stop)) {
 		warning(
 		    WARNING_BACKWARDS_FOR, "FOR goes backwards from %d to %d by %d\n", start, stop, step
 		);
+	}
 
-	if (count == 0)
+	if (count == 0) {
 		return;
+	}
 
 	Context &context = newReptContext(reptLineNo, span, count);
 	context.isForLoop = true;
@@ -385,17 +403,20 @@ bool fstk_Break() {
 }
 
 void fstk_NewRecursionDepth(size_t newDepth) {
-	if (contextStack.size() > newDepth + 1)
+	if (contextStack.size() > newDepth + 1) {
 		fatalerror("Recursion limit (%zu) exceeded\n", newDepth);
+	}
 	maxRecursionDepth = newDepth;
 }
 
 void fstk_Init(std::string const &mainPath, size_t maxDepth) {
-	if (!newFileContext(mainPath, true))
+	if (!newFileContext(mainPath, true)) {
 		fatalerror("Failed to open main file\n");
+	}
 
 	maxRecursionDepth = maxDepth;
 
-	if (!preIncludeName.empty())
+	if (!preIncludeName.empty()) {
 		fstk_RunInclude(preIncludeName, true);
+	}
 }
diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp
index 9bcbcd1cd..d27364bc9 100644
--- a/src/asm/lexer.cpp
+++ b/src/asm/lexer.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/lexer.hpp"
 #include <sys/stat.h>
@@ -35,15 +35,14 @@
 
 // Neither MSVC nor MinGW provide `mmap`
 #if defined(_MSC_VER) || defined(__MINGW32__)
-// clang-format off
-	// (we need these `include`s in this order)
-	#define WIN32_LEAN_AND_MEAN // include less from windows.h
+// clang-format off: maintain `include` order
+	#define WIN32_LEAN_AND_MEAN // Include less from `windows.h`
 	#include <windows.h>   // target architecture
+// clang-format on
 	#include <fileapi.h>   // CreateFileA
-	#include <winbase.h>   // CreateFileMappingA
-	#include <memoryapi.h> // MapViewOfFile
 	#include <handleapi.h> // CloseHandle
-// clang-format on
+	#include <memoryapi.h> // MapViewOfFile
+	#include <winbase.h>   // CreateFileMappingA
 
 static char *mapFile(int fd, std::string const &path, size_t) {
 	void *mappingAddr = nullptr;
@@ -82,8 +81,9 @@ static char *mapFile(int fd, std::string const &path, size_t size) {
 		// The implementation may not support MAP_PRIVATE; try again with MAP_SHARED
 		// instead, offering, I believe, weaker guarantees about external modifications to
 		// the file while reading it. That's still better than not opening it at all, though.
-		if (verbose)
+		if (verbose) {
 			printf("mmap(%s, MAP_PRIVATE) failed, retrying with MAP_SHARED\n", path.c_str());
+		}
 		mappingAddr = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0);
 	}
 	return mappingAddr != MAP_FAILED ? static_cast<char *>(mappingAddr) : nullptr;
@@ -120,8 +120,9 @@ struct CaseInsensitive {
 	size_t operator()(std::string const &str) const {
 		size_t hash = 0x811C9DC5;
 
-		for (char const &c : str)
+		for (char const &c : str) {
 			hash = (hash ^ toupper(c)) * 16777619;
+		}
 		return hash;
 	}
 
@@ -190,7 +191,7 @@ static std::unordered_map<std::string, int, CaseInsensitive, CaseInsensitive> ke
     {"NZ",            T_(CC_NZ)            },
     {"Z",             T_(CC_Z)             },
     {"NC",            T_(CC_NC)            },
- // There is no `T_(CC_C)`; it's handled before as `T_(TOKEN_C)`
+    // There is no `T_(CC_C)`; it's handled before as `T_(TOKEN_C)`
 
     {"AF",            T_(MODE_AF)          },
     {"BC",            T_(MODE_BC)          },
@@ -315,7 +316,7 @@ static std::unordered_map<std::string, int, CaseInsensitive, CaseInsensitive> ke
 
     {"RB",            T_(POP_RB)           },
     {"RW",            T_(POP_RW)           },
- // There is no `T_(POP_RL)`; it's handled before as `T_(SM83_RL)`
+    // There is no `T_(POP_RL)`; it's handled before as `T_(SM83_RL)`
 
     {"EQU",           T_(POP_EQU)          },
     {"EQUS",          T_(POP_EQUS)         },
@@ -376,8 +377,9 @@ void lexer_IncIFDepth() {
 }
 
 void lexer_DecIFDepth() {
-	if (lexerState->ifStack.empty())
+	if (lexerState->ifStack.empty()) {
 		fatalerror("Found ENDC outside of an IF construct\n");
+	}
 
 	lexerState->ifStack.pop_front();
 }
@@ -406,8 +408,9 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
 	if (filePath == "-") {
 		path = "<stdin>";
 		content.emplace<BufferedContent>(STDIN_FILENO);
-		if (verbose)
+		if (verbose) {
 			printf("Opening stdin\n");
+		}
 	} else {
 		struct stat statBuf;
 		if (stat(filePath.c_str(), &statBuf) != 0) {
@@ -431,8 +434,9 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
 				content.emplace<ViewedContent>(
 				    std::shared_ptr<char[]>(mappingAddr, FileUnmapDeleter(size)), size
 				);
-				if (verbose)
+				if (verbose) {
 					printf("File \"%s\" is mmap()ped\n", path.c_str());
+				}
 				isMmapped = true;
 			}
 		}
@@ -453,10 +457,11 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
 	}
 
 	clear(0);
-	if (updateStateNow)
+	if (updateStateNow) {
 		lexerState = this;
-	else
+	} else {
 		lexerStateEOL = this;
+	}
 	return true;
 }
 
@@ -502,8 +507,9 @@ BufferedContent::~BufferedContent() {
 void BufferedContent::advance() {
 	assume(offset < std::size(buf));
 	offset++;
-	if (offset == std::size(buf))
+	if (offset == std::size(buf)) {
 		offset = 0; // Wrap around if necessary
+	}
 	assume(size > 0);
 	size--;
 }
@@ -520,16 +526,19 @@ void BufferedContent::refill() {
 		size_t nbReadChars = readMore(startIndex, nbExpectedChars);
 
 		startIndex += nbReadChars;
-		if (startIndex == std::size(buf))
+		if (startIndex == std::size(buf)) {
 			startIndex = 0;
+		}
 
 		// If the read was incomplete, don't perform a second read
 		target -= nbReadChars;
-		if (nbReadChars < nbExpectedChars)
+		if (nbReadChars < nbExpectedChars) {
 			target = 0;
+		}
 	}
-	if (target != 0)
+	if (target != 0) {
 		readMore(startIndex, target);
+	}
 }
 
 size_t BufferedContent::readMore(size_t startIndex, size_t nbChars) {
@@ -537,8 +546,9 @@ size_t BufferedContent::readMore(size_t startIndex, size_t nbChars) {
 	assume(startIndex + nbChars <= std::size(buf));
 	ssize_t nbReadChars = read(fd, &buf[startIndex], nbChars);
 
-	if (nbReadChars == -1)
+	if (nbReadChars == -1) {
 		fatalerror("Error while reading \"%s\": %s\n", lexerState->path.c_str(), strerror(errno));
+	}
 
 	size += nbReadChars;
 
@@ -557,19 +567,22 @@ void lexer_ToggleStringExpansion(bool enable) {
 // Functions for the actual lexer to obtain characters
 
 static void beginExpansion(std::shared_ptr<std::string> str, std::optional<std::string> name) {
-	if (name)
+	if (name) {
 		lexer_CheckRecursionDepth();
+	}
 
 	// Do not expand empty strings
-	if (str->empty())
+	if (str->empty()) {
 		return;
+	}
 
 	lexerState->expansions.push_front({.name = name, .contents = str, .offset = 0});
 }
 
 void lexer_CheckRecursionDepth() {
-	if (lexerState->expansions.size() > maxRecursionDepth + 1)
+	if (lexerState->expansions.size() > maxRecursionDepth + 1) {
 		fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
+	}
 }
 
 static bool isMacroChar(char c) {
@@ -620,10 +633,11 @@ static uint32_t readBracketedMacroArgNum() {
 		Symbol const *sym = sym_FindScopedValidSymbol(symName);
 
 		if (!sym) {
-			if (sym_IsPurgedScoped(symName))
+			if (sym_IsPurgedScoped(symName)) {
 				error("Bracketed symbol \"%s\" does not exist; it was purged\n", symName.c_str());
-			else
+			} else {
 				error("Bracketed symbol \"%s\" does not exist\n", symName.c_str());
+			}
 			num = 0;
 			symbolError = true;
 		} else if (!sym->isNumeric()) {
@@ -708,21 +722,25 @@ static std::shared_ptr<std::string> readMacroArg(char name) {
 int LexerState::peekChar() {
 	// This is `.peekCharAhead()` modified for zero lookahead distance
 	for (Expansion &exp : expansions) {
-		if (exp.offset < exp.size())
+		if (exp.offset < exp.size()) {
 			return static_cast<uint8_t>((*exp.contents)[exp.offset]);
+		}
 	}
 
 	if (content.holds<ViewedContent>()) {
 		auto &view = content.get<ViewedContent>();
-		if (view.offset < view.span.size)
+		if (view.offset < view.span.size) {
 			return static_cast<uint8_t>(view.span.ptr[view.offset]);
+		}
 	} else {
 		auto &cbuf = content.get<BufferedContent>();
-		if (cbuf.size == 0)
+		if (cbuf.size == 0) {
 			cbuf.refill();
+		}
 		assume(cbuf.offset < std::size(cbuf.buf));
-		if (cbuf.size > 0)
+		if (cbuf.size > 0) {
 			return static_cast<uint8_t>(cbuf.buf[cbuf.offset]);
+		}
 	}
 
 	// If there aren't enough chars, give up
@@ -737,22 +755,26 @@ int LexerState::peekCharAhead() {
 		// An expansion that has reached its end will have `exp.offset` == `exp.size()`,
 		// and `.peekCharAhead()` will continue with its parent
 		assume(exp.offset <= exp.size());
-		if (exp.offset + distance < exp.size())
+		if (exp.offset + distance < exp.size()) {
 			return static_cast<uint8_t>((*exp.contents)[exp.offset + distance]);
+		}
 		distance -= exp.size() - exp.offset;
 	}
 
 	if (content.holds<ViewedContent>()) {
 		auto &view = content.get<ViewedContent>();
-		if (view.offset + distance < view.span.size)
+		if (view.offset + distance < view.span.size) {
 			return static_cast<uint8_t>(view.span.ptr[view.offset + distance]);
+		}
 	} else {
 		auto &cbuf = content.get<BufferedContent>();
 		assume(distance < std::size(cbuf.buf));
-		if (cbuf.size <= distance)
+		if (cbuf.size <= distance) {
 			cbuf.refill();
-		if (cbuf.size > distance)
+		}
+		if (cbuf.size > distance) {
 			return static_cast<uint8_t>(cbuf.buf[(cbuf.offset + distance) % std::size(cbuf.buf)]);
+		}
 	}
 
 	// If there aren't enough chars, give up
@@ -766,8 +788,9 @@ static std::shared_ptr<std::string> readInterpolation(size_t depth);
 static int peek() {
 	int c = lexerState->peekChar();
 
-	if (lexerState->macroArgScanDistance > 0)
+	if (lexerState->macroArgScanDistance > 0) {
 		return c;
+	}
 
 	lexerState->macroArgScanDistance++; // Do not consider again
 
@@ -810,8 +833,9 @@ static int peek() {
 
 static void shiftChar() {
 	if (lexerState->capturing) {
-		if (lexerState->captureBuf)
+		if (lexerState->captureBuf) {
 			lexerState->captureBuf->push_back(peek());
+		}
 		lexerState->captureSize++;
 	}
 
@@ -841,14 +865,16 @@ static int nextChar() {
 	int c = peek();
 
 	// If not at EOF, advance read position
-	if (c != EOF)
+	if (c != EOF) {
 		shiftChar();
+	}
 	return c;
 }
 
 static void handleCRLF(int c) {
-	if (c == '\r' && peek() == '\n')
+	if (c == '\r' && peek() == '\n') {
 		shiftChar();
+	}
 }
 
 static auto scopedDisableExpansions() {
@@ -871,13 +897,15 @@ uint32_t lexer_GetColNo() {
 }
 
 void lexer_DumpStringExpansions() {
-	if (!lexerState)
+	if (!lexerState) {
 		return;
+	}
 
 	for (Expansion &exp : lexerState->expansions) {
 		// Only register EQUS expansions, not string args
-		if (exp.name)
+		if (exp.name) {
 			fprintf(stderr, "while expanding symbol \"%s\"\n", exp.name->c_str());
+		}
 	}
 }
 
@@ -897,8 +925,9 @@ static void discardBlockComment() {
 			handleCRLF(c);
 			[[fallthrough]];
 		case '\n':
-			if (lexerState->expansions.empty())
+			if (lexerState->expansions.empty()) {
 				nextLine();
+			}
 			continue;
 		case '/':
 			if (peek() == '*') {
@@ -922,8 +951,9 @@ static void discardComment() {
 	for (;; shiftChar()) {
 		int c = peek();
 
-		if (c == EOF || c == '\r' || c == '\n')
+		if (c == EOF || c == '\r' || c == '\n') {
 			break;
+		}
 	}
 }
 
@@ -937,8 +967,9 @@ static void discardLineContinuation() {
 			shiftChar();
 			// Handle CRLF before nextLine() since shiftChar updates colNo
 			handleCRLF(c);
-			if (lexerState->expansions.empty())
+			if (lexerState->expansions.empty()) {
 				nextLine();
+			}
 			break;
 		} else if (c == ';') {
 			discardComment();
@@ -969,12 +1000,14 @@ static uint32_t readNumber(int radix, uint32_t baseValue) {
 	for (;; shiftChar()) {
 		int c = peek();
 
-		if (c == '_')
+		if (c == '_') {
 			continue;
-		else if (c < '0' || c > '0' + radix - 1)
+		} else if (c < '0' || c > '0' + radix - 1) {
 			break;
-		if (value > (UINT32_MAX - (c - '0')) / radix)
+		}
+		if (value > (UINT32_MAX - (c - '0')) / radix) {
 			warning(WARNING_LARGE_CONSTANT, "Integer constant is too large\n");
+		}
 		value = value * radix + (c - '0');
 	}
 
@@ -1006,8 +1039,9 @@ static uint32_t readFractionalPart(uint32_t integer) {
 				warning(WARNING_LARGE_CONSTANT, "Precision of fixed-point constant is too large\n");
 				// Discard any additional digits
 				shiftChar();
-				while (c = peek(), (c >= '0' && c <= '9') || c == '_')
+				while (c = peek(), (c >= '0' && c <= '9') || c == '_') {
 					shiftChar();
+				}
 				break;
 			}
 			value = value * 10 + (c - '0');
@@ -1024,16 +1058,18 @@ static uint32_t readFractionalPart(uint32_t integer) {
 	}
 
 	if (precision == 0) {
-		if (state >= READFRACTIONALPART_PRECISION)
+		if (state >= READFRACTIONALPART_PRECISION) {
 			error("Invalid fixed-point constant, no significant digits after 'q'\n");
+		}
 		precision = fixPrecision;
 	} else if (precision > 31) {
 		error("Fixed-point constant precision must be between 1 and 31\n");
 		precision = fixPrecision;
 	}
 
-	if (integer >= (1ULL << (32 - precision)))
+	if (integer >= (1ULL << (32 - precision))) {
 		warning(WARNING_LARGE_CONSTANT, "Magnitude of fixed-point constant is too large\n");
+	}
 
 	// Cast to unsigned avoids undefined overflow behavior
 	uint32_t fractional =
@@ -1052,16 +1088,18 @@ static uint32_t readBinaryNumber() {
 		int bit;
 
 		// Check for '_' after digits in case one of the digits is '_'
-		if (c == binDigits[0])
+		if (c == binDigits[0]) {
 			bit = 0;
-		else if (c == binDigits[1])
+		} else if (c == binDigits[1]) {
 			bit = 1;
-		else if (c == '_')
+		} else if (c == '_') {
 			continue;
-		else
+		} else {
 			break;
-		if (value > (UINT32_MAX - bit) / 2)
+		}
+		if (value > (UINT32_MAX - bit) / 2) {
 			warning(WARNING_LARGE_CONSTANT, "Integer constant is too large\n");
+		}
 		value = value * 2 + bit;
 	}
 
@@ -1075,26 +1113,29 @@ static uint32_t readHexNumber() {
 	for (;; shiftChar()) {
 		int c = peek();
 
-		if (c >= 'a' && c <= 'f')
+		if (c >= 'a' && c <= 'f') {
 			c = c - 'a' + 10;
-		else if (c >= 'A' && c <= 'F')
+		} else if (c >= 'A' && c <= 'F') {
 			c = c - 'A' + 10;
-		else if (c >= '0' && c <= '9')
+		} else if (c >= '0' && c <= '9') {
 			c = c - '0';
-		else if (c == '_' && !empty)
+		} else if (c == '_' && !empty) {
 			continue;
-		else
+		} else {
 			break;
+		}
 
-		if (value > (UINT32_MAX - c) / 16)
+		if (value > (UINT32_MAX - c) / 16) {
 			warning(WARNING_LARGE_CONSTANT, "Integer constant is too large\n");
+		}
 		value = value * 16 + c;
 
 		empty = false;
 	}
 
-	if (empty)
+	if (empty) {
 		error("Invalid integer constant, no digits after '$'\n");
+	}
 
 	return value;
 }
@@ -1110,34 +1151,37 @@ static uint32_t readGfxConstant() {
 		uint32_t pixel;
 
 		// Check for '_' after digits in case one of the digits is '_'
-		if (c == gfxDigits[0])
+		if (c == gfxDigits[0]) {
 			pixel = 0;
-		else if (c == gfxDigits[1])
+		} else if (c == gfxDigits[1]) {
 			pixel = 1;
-		else if (c == gfxDigits[2])
+		} else if (c == gfxDigits[2]) {
 			pixel = 2;
-		else if (c == gfxDigits[3])
+		} else if (c == gfxDigits[3]) {
 			pixel = 3;
-		else if (c == '_' && width > 0)
+		} else if (c == '_' && width > 0) {
 			continue;
-		else
+		} else {
 			break;
+		}
 
 		if (width < 8) {
 			bitPlaneLower = bitPlaneLower << 1 | (pixel & 1);
 			bitPlaneUpper = bitPlaneUpper << 1 | (pixel >> 1);
 		}
-		if (width < 9)
+		if (width < 9) {
 			width++;
+		}
 	}
 
-	if (width == 0)
+	if (width == 0) {
 		error("Invalid graphics constant, no digits after '`'\n");
-	else if (width == 9)
+	} else if (width == 9) {
 		warning(
 		    WARNING_LARGE_CONSTANT,
 		    "Graphics constant is too long, only first 8 pixels considered\n"
 		);
+	}
 
 	return bitPlaneUpper << 8 | bitPlaneLower;
 }
@@ -1165,8 +1209,9 @@ static Token readIdentifier(char firstChar, bool raw) {
 		identifier += c;
 
 		// If the char was a dot, mark the identifier as local
-		if (c == '.')
+		if (c == '.') {
 			tokenType = T_(LOCAL_ID);
+		}
 	}
 
 	// Attempt to check for a keyword if the identifier is not raw
@@ -1180,8 +1225,9 @@ static Token readIdentifier(char firstChar, bool raw) {
 	}
 
 	// Label scopes `.` and `..` are the only nonlocal identifiers that start with a dot
-	if (identifier.find_first_not_of('.') == identifier.npos)
+	if (identifier.find_first_not_of('.') == identifier.npos) {
 		tokenType = T_(ID);
+	}
 
 	return Token(tokenType, identifier);
 }
@@ -1189,8 +1235,9 @@ static Token readIdentifier(char firstChar, bool raw) {
 // Functions to read strings
 
 static std::shared_ptr<std::string> readInterpolation(size_t depth) {
-	if (depth > maxRecursionDepth)
+	if (depth > maxRecursionDepth) {
 		fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
+	}
 
 	std::string fmtBuf;
 	FormatSpec fmt{};
@@ -1218,11 +1265,13 @@ static std::shared_ptr<std::string> readInterpolation(size_t depth) {
 			break;
 		} else if (c == ':' && !fmt.isFinished()) { // Format spec, only once
 			shiftChar();
-			for (char f : fmtBuf)
+			for (char f : fmtBuf) {
 				fmt.useCharacter(f);
+			}
 			fmt.finishCharacters();
-			if (!fmt.isValid())
+			if (!fmt.isValid()) {
 				error("Invalid format spec '%s'\n", fmtBuf.c_str());
+			}
 			fmtBuf.clear(); // Now that format has been set, restart at beginning of string
 		} else {
 			shiftChar();
@@ -1249,10 +1298,11 @@ static std::shared_ptr<std::string> readInterpolation(size_t depth) {
 	Symbol const *sym = sym_FindScopedValidSymbol(fmtBuf);
 
 	if (!sym || !sym->isDefined()) {
-		if (sym_IsPurgedScoped(fmtBuf))
+		if (sym_IsPurgedScoped(fmtBuf)) {
 			error("Interpolated symbol \"%s\" does not exist; it was purged\n", fmtBuf.c_str());
-		else
+		} else {
 			error("Interpolated symbol \"%s\" does not exist\n", fmtBuf.c_str());
+		}
 	} else if (sym->type == SYM_EQUS) {
 		auto buf = std::make_shared<std::string>();
 		fmt.appendString(*buf, *sym->getEqus());
@@ -1336,8 +1386,9 @@ static std::string readString(bool raw) {
 		case '"':
 			if (multiline) {
 				// Only """ ends a multi-line string
-				if (peek() != '"')
+				if (peek() != '"') {
 					break;
+				}
 				shiftChar();
 				if (peek() != '"') {
 					str += '"';
@@ -1348,8 +1399,9 @@ static std::string readString(bool raw) {
 			return str;
 
 		case '\\': // Character escape or macro arg
-			if (raw)
+			if (raw) {
 				break;
+			}
 			c = peek();
 			switch (c) {
 			case '\\':
@@ -1416,8 +1468,9 @@ static std::string readString(bool raw) {
 			break;
 
 		case '{': // Symbol interpolation
-			if (raw)
+			if (raw) {
 				break;
+			}
 			// We'll be exiting the string scope, so re-enable expansions
 			// (Not interpolations, since they're handled by the function itself...)
 			lexerState->disableMacroArgs = false;
@@ -1478,12 +1531,14 @@ static void appendStringLiteral(std::string &str, bool raw) {
 		case '"':
 			if (multiline) {
 				// Only """ ends a multi-line string
-				if (peek() != '"')
+				if (peek() != '"') {
 					break;
+				}
 				str += '"';
 				shiftChar();
-				if (peek() != '"')
+				if (peek() != '"') {
 					break;
+				}
 				str += '"';
 				shiftChar();
 			}
@@ -1491,8 +1546,9 @@ static void appendStringLiteral(std::string &str, bool raw) {
 			return;
 
 		case '\\': // Character escape or macro arg
-			if (raw)
+			if (raw) {
 				break;
+			}
 			c = peek();
 			switch (c) {
 			// Character escape
@@ -1550,8 +1606,9 @@ static void appendStringLiteral(std::string &str, bool raw) {
 			break;
 
 		case '{': // Symbol interpolation
-			if (raw)
+			if (raw) {
 				break;
+			}
 			// We'll be exiting the string scope, so re-enable expansions
 			// (Not interpolations, since they're handled by the function itself...)
 			lexerState->disableMacroArgs = false;
@@ -1850,12 +1907,14 @@ static Token yylex_NORMAL() {
 
 				// An ELIF after a taken IF needs to not evaluate its condition
 				if (token.type == T_(POP_ELIF) && lexerState->lastToken == T_(NEWLINE)
-				    && lexer_GetIFDepth() > 0 && lexer_RanIFBlock() && !lexer_ReachedELSEBlock())
+				    && lexer_GetIFDepth() > 0 && lexer_RanIFBlock() && !lexer_ReachedELSEBlock()) {
 					return yylex_SKIP_TO_ENDC();
+				}
 
 				// If a keyword, don't try to expand
-				if (token.type != T_(ID) && token.type != T_(LOCAL_ID))
+				if (token.type != T_(ID) && token.type != T_(LOCAL_ID)) {
 					return token;
+				}
 
 				// `token` is either an `ID` or a `LOCAL_ID`, and both have a `std::string` value.
 				assume(token.value.holds<std::string>());
@@ -1886,8 +1945,9 @@ static Token yylex_NORMAL() {
 				// character *immediately* follows the identifier. Thus, at the beginning of a line,
 				// "Label:" and "mac:" are treated as label definitions, but "Label :" and "mac :"
 				// are treated as macro invocations.
-				if (token.type == T_(ID) && peek() == ':')
+				if (token.type == T_(ID) && peek() == ':') {
 					token.type = T_(LABEL);
+				}
 
 				return token;
 			}
@@ -1917,8 +1977,9 @@ static Token yylex_RAW() {
 			shiftChar();
 			c = peek();
 			// If not a line continuation, handle as a normal char
-			if (!isWhitespace(c) && c != '\n' && c != '\r')
+			if (!isWhitespace(c) && c != '\n' && c != '\r') {
 				goto backslash;
+			}
 			// Line continuations count as "whitespace"
 			discardLineContinuation();
 		} else {
@@ -1964,18 +2025,21 @@ static Token yylex_RAW() {
 			break;
 
 		case ',': // End of macro arg
-			if (parenDepth == 0)
+			if (parenDepth == 0) {
 				goto finish;
+			}
 			goto append;
 
 		case '(': // Open parentheses inside macro args
-			if (parenDepth < UINT_MAX)
+			if (parenDepth < UINT_MAX) {
 				parenDepth++;
+			}
 			goto append;
 
 		case ')': // Close parentheses inside macro args
-			if (parenDepth > 0)
+			if (parenDepth > 0) {
 				parenDepth--;
+			}
 			goto append;
 
 		case '\\': // Character escape
@@ -2055,8 +2119,9 @@ static Token yylex_RAW() {
 	// an empty raw string before it). This will not be treated as a
 	// macro argument. To pass an empty last argument, use a second
 	// trailing comma.
-	if (!str.empty())
+	if (!str.empty()) {
 		return Token(T_(STRING), str);
+	}
 	lexer_SetMode(LEXER_NORMAL);
 
 	if (c == '\r' || c == '\n') {
@@ -2088,8 +2153,9 @@ static Token skipIfBlock(bool toEndc) {
 
 			for (;; shiftChar()) {
 				c = peek();
-				if (!isWhitespace(c))
+				if (!isWhitespace(c)) {
 					break;
+				}
 			}
 
 			if (startsIdentifier(c)) {
@@ -2100,23 +2166,28 @@ static Token skipIfBlock(bool toEndc) {
 					break;
 
 				case T_(POP_ELIF):
-					if (lexer_ReachedELSEBlock())
+					if (lexer_ReachedELSEBlock()) {
 						fatalerror("Found ELIF after an ELSE block\n");
-					if (!toEndc && lexer_GetIFDepth() == startingDepth)
+					}
+					if (!toEndc && lexer_GetIFDepth() == startingDepth) {
 						return token;
+					}
 					break;
 
 				case T_(POP_ELSE):
-					if (lexer_ReachedELSEBlock())
+					if (lexer_ReachedELSEBlock()) {
 						fatalerror("Found ELSE after an ELSE block\n");
+					}
 					lexer_ReachELSEBlock();
-					if (!toEndc && lexer_GetIFDepth() == startingDepth)
+					if (!toEndc && lexer_GetIFDepth() == startingDepth) {
 						return token;
+					}
 					break;
 
 				case T_(POP_ENDC):
-					if (lexer_GetIFDepth() == startingDepth)
+					if (lexer_GetIFDepth() == startingDepth) {
 						return token;
+					}
 					lexer_DecIFDepth();
 					break;
 
@@ -2173,8 +2244,9 @@ static Token yylex_SKIP_TO_ENDR() {
 
 			for (;;) {
 				c = peek();
-				if (!isWhitespace(c))
+				if (!isWhitespace(c)) {
 					break;
+				}
 				shiftChar();
 			}
 
@@ -2188,8 +2260,9 @@ static Token yylex_SKIP_TO_ENDR() {
 
 				case T_(POP_ENDR):
 					depth--;
-					if (!depth)
+					if (!depth) {
 						return Token(T_(YYEOF)); // yywrap() will finish the REPT/FOR loop
+					}
 					break;
 
 				case T_(POP_IF):
@@ -2235,11 +2308,13 @@ yy::parser::symbol_type yylex() {
 		lexerState = lexerStateEOL;
 		lexerStateEOL = nullptr;
 	}
-	if (lexerState->lastToken == T_(EOB) && yywrap())
+	if (lexerState->lastToken == T_(EOB) && yywrap()) {
 		return yy::parser::make_YYEOF();
+	}
 	// Newlines read within an expansion should not increase the line count
-	if (lexerState->atLineStart && lexerState->expansions.empty())
+	if (lexerState->atLineStart && lexerState->expansions.empty()) {
 		nextLine();
+	}
 
 	static Token (* const lexerModeFuncs[NB_LEXER_MODES])() = {
 	    yylex_NORMAL,
@@ -2286,22 +2361,23 @@ static Capture startCapture() {
 		auto &view = lexerState->content.get<ViewedContent>();
 		return {
 		    .lineNo = lineNo, .span = {.ptr = view.makeSharedContentPtr(), .size = 0}
-        };
+		};
 	} else {
 		assume(lexerState->captureBuf == nullptr);
 		lexerState->captureBuf = std::make_shared<std::vector<char>>();
 		// `.span.ptr == nullptr`; indicates to retrieve the capture buffer when done capturing
 		return {
 		    .lineNo = lineNo, .span = {.ptr = nullptr, .size = 0}
-        };
+		};
 	}
 }
 
 static void endCapture(Capture &capture) {
 	// This being `nullptr` means we're capturing from the capture buffer, which is reallocated
 	// during the whole capture process, and so MUST be retrieved at the end
-	if (!capture.span.ptr)
+	if (!capture.span.ptr) {
 		capture.span.ptr = lexerState->makeSharedCaptureBufPtr();
+	}
 	capture.span.size = lexerState->captureSize;
 
 	// ENDR/ENDM or EOF puts us past the start of the line
diff --git a/src/asm/macro.cpp b/src/asm/macro.cpp
index e3d3e95c2..dc5f3a465 100644
--- a/src/asm/macro.cpp
+++ b/src/asm/macro.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/macro.hpp"
 
@@ -17,13 +17,15 @@ std::shared_ptr<std::string> MacroArgs::getArg(uint32_t i) const {
 std::shared_ptr<std::string> MacroArgs::getAllArgs() const {
 	size_t nbArgs = args.size();
 
-	if (shift >= nbArgs)
+	if (shift >= nbArgs) {
 		return std::make_shared<std::string>("");
+	}
 
 	size_t len = 0;
 
-	for (uint32_t i = shift; i < nbArgs; i++)
+	for (uint32_t i = shift; i < nbArgs; i++) {
 		len += args[i]->length() + 1; // 1 for comma
+	}
 
 	auto str = std::make_shared<std::string>();
 	str->reserve(len + 1); // 1 for comma
@@ -34,16 +36,18 @@ std::shared_ptr<std::string> MacroArgs::getAllArgs() const {
 		str->append(*arg);
 
 		// Commas go between args and after a last empty arg
-		if (i < nbArgs - 1 || arg->empty())
+		if (i < nbArgs - 1 || arg->empty()) {
 			str->push_back(','); // no space after comma
+		}
 	}
 
 	return str;
 }
 
 void MacroArgs::appendArg(std::shared_ptr<std::string> arg) {
-	if (arg->empty())
+	if (arg->empty()) {
 		warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n");
+	}
 	args.push_back(arg);
 }
 
diff --git a/src/asm/main.cpp b/src/asm/main.cpp
index 2be5ab743..2da5e28a5 100644
--- a/src/asm/main.cpp
+++ b/src/asm/main.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/main.hpp"
 
@@ -37,8 +37,9 @@ static std::string make_escape(std::string &str) {
 	for (;;) {
 		// All dollars needs to be doubled
 		size_t nextPos = str.find("$", pos);
-		if (nextPos == std::string::npos)
+		if (nextPos == std::string::npos) {
 			break;
+		}
 		escaped.append(str, pos, nextPos - pos);
 		escaped.append("$$");
 		pos = nextPos + literal_strlen("$");
@@ -54,13 +55,12 @@ static char const *optstring = "b:D:Eg:hI:M:o:P:p:Q:r:s:VvW:wX:";
 static int depType; // Variants of `-M`
 
 // Equivalent long options
-// Please keep in the same order as short opts
-//
+// Please keep in the same order as short opts.
 // Also, make sure long opts don't create ambiguity:
 // A long opt's name should start with the same letter as its short opt,
 // except if it doesn't create any ambiguity (`verbose` versus `version`).
 // This is because long opt matching, even to a single char, is prioritized
-// over short opt matching
+// over short opt matching.
 static option const longopts[] = {
     {"binary-digits",   required_argument, nullptr,  'b'},
     {"define",          required_argument, nullptr,  'D'},
@@ -112,12 +112,14 @@ int main(int argc, char *argv[]) {
 	time_t now = time(nullptr);
 	// Support SOURCE_DATE_EPOCH for reproducible builds
 	// https://reproducible-builds.org/docs/source-date-epoch/
-	if (char const *sourceDateEpoch = getenv("SOURCE_DATE_EPOCH"); sourceDateEpoch)
+	if (char const *sourceDateEpoch = getenv("SOURCE_DATE_EPOCH"); sourceDateEpoch) {
 		now = static_cast<time_t>(strtoul(sourceDateEpoch, nullptr, 0));
+	}
 
 	Defer closeDependFile{[&] {
-		if (dependFile)
+		if (dependFile) {
 			fclose(dependFile);
+		}
 	}};
 
 	// Perform some init for below
@@ -134,18 +136,20 @@ int main(int argc, char *argv[]) {
 	std::unordered_map<std::string, std::vector<StateFeature>> stateFileSpecs;
 	std::string newTarget;
 	// Maximum of 100 errors only applies if rgbasm is printing errors to a terminal.
-	if (isatty(STDERR_FILENO))
+	if (isatty(STDERR_FILENO)) {
 		maxErrors = 100;
+	}
 
 	for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, nullptr)) != -1;) {
 		switch (ch) {
 			char *endptr;
 
 		case 'b':
-			if (strlen(musl_optarg) == 2)
+			if (strlen(musl_optarg) == 2) {
 				opt_B(musl_optarg);
-			else
+			} else {
 				errx("Must specify exactly 2 characters for option 'b'");
+			}
 			break;
 
 			char *equals;
@@ -164,10 +168,11 @@ int main(int argc, char *argv[]) {
 			break;
 
 		case 'g':
-			if (strlen(musl_optarg) == 4)
+			if (strlen(musl_optarg) == 4) {
 				opt_G(musl_optarg);
-			else
+			} else {
 				errx("Must specify exactly 4 characters for option 'g'");
+			}
 			break;
 
 		case 'h':
@@ -179,8 +184,9 @@ int main(int argc, char *argv[]) {
 			break;
 
 		case 'M':
-			if (dependFile)
+			if (dependFile) {
 				warnx("Overriding dependfile %s", dependFileName);
+			}
 			if (strcmp("-", musl_optarg)) {
 				dependFile = fopen(musl_optarg, "w");
 				dependFileName = musl_optarg;
@@ -188,8 +194,9 @@ int main(int argc, char *argv[]) {
 				dependFile = stdout;
 				dependFileName = "<stdout>";
 			}
-			if (dependFile == nullptr)
+			if (dependFile == nullptr) {
 				err("Failed to open dependfile \"%s\"", dependFileName);
+			}
 			break;
 
 		case 'o':
@@ -204,11 +211,13 @@ int main(int argc, char *argv[]) {
 		case 'p':
 			padByte = strtoul(musl_optarg, &endptr, 0);
 
-			if (musl_optarg[0] == '\0' || *endptr != '\0')
+			if (musl_optarg[0] == '\0' || *endptr != '\0') {
 				errx("Invalid argument for option 'p'");
+			}
 
-			if (padByte > 0xFF)
+			if (padByte > 0xFF) {
 				errx("Argument for option 'p' must be between 0 and 0xFF");
+			}
 
 			opt_P(padByte);
 			break;
@@ -217,15 +226,18 @@ int main(int argc, char *argv[]) {
 			char const *precisionArg;
 		case 'Q':
 			precisionArg = musl_optarg;
-			if (precisionArg[0] == '.')
+			if (precisionArg[0] == '.') {
 				precisionArg++;
+			}
 			precision = strtoul(precisionArg, &endptr, 0);
 
-			if (musl_optarg[0] == '\0' || *endptr != '\0')
+			if (musl_optarg[0] == '\0' || *endptr != '\0') {
 				errx("Invalid argument for option 'Q'");
+			}
 
-			if (precision < 1 || precision > 31)
+			if (precision < 1 || precision > 31) {
 				errx("Argument for option 'Q' must be between 1 and 31");
+			}
 
 			opt_Q(precision);
 			break;
@@ -233,35 +245,41 @@ int main(int argc, char *argv[]) {
 		case 'r':
 			maxDepth = strtoul(musl_optarg, &endptr, 0);
 
-			if (musl_optarg[0] == '\0' || *endptr != '\0')
+			if (musl_optarg[0] == '\0' || *endptr != '\0') {
 				errx("Invalid argument for option 'r'");
+			}
 			break;
 
 		case 's': {
 			// Split "<features>:<name>" so `musl_optarg` is "<features>" and `name` is "<name>"
 			char *name = strchr(musl_optarg, ':');
-			if (!name)
+			if (!name) {
 				errx("Invalid argument for option 's'");
+			}
 			*name++ = '\0';
 
 			std::vector<StateFeature> features;
 			for (char *feature = musl_optarg; feature;) {
 				// Split "<feature>,<rest>" so `feature` is "<feature>" and `next` is "<rest>"
 				char *next = strchr(feature, ',');
-				if (next)
+				if (next) {
 					*next++ = '\0';
+				}
 				// Trim whitespace from the beginning of `feature`...
 				feature += strspn(feature, " \t");
 				// ...and from the end
-				if (char *end = strpbrk(feature, " \t"); end)
+				if (char *end = strpbrk(feature, " \t"); end) {
 					*end = '\0';
+				}
 				// A feature must be specified
-				if (*feature == '\0')
+				if (*feature == '\0') {
 					errx("Empty feature for option 's'");
+				}
 				// Parse the `feature` and update the `features` list
 				if (!strcasecmp(feature, "all")) {
-					if (!features.empty())
+					if (!features.empty()) {
 						warnx("Redundant feature before \"%s\" for option 's'", feature);
+					}
 					features.assign({STATE_EQU, STATE_VAR, STATE_EQUS, STATE_CHAR, STATE_MACRO});
 				} else {
 					StateFeature value = !strcasecmp(feature, "equ")     ? STATE_EQU
@@ -281,10 +299,12 @@ int main(int argc, char *argv[]) {
 				feature = next;
 			}
 
-			if (stateFileSpecs.find(name) != stateFileSpecs.end())
+			if (stateFileSpecs.find(name) != stateFileSpecs.end()) {
 				warnx("Overriding state filename %s", name);
-			if (verbose)
+			}
+			if (verbose) {
 				printf("State filename %s\n", name);
+			}
 			stateFileSpecs.emplace(name, std::move(features));
 			break;
 		}
@@ -309,11 +329,13 @@ int main(int argc, char *argv[]) {
 		case 'X':
 			maxValue = strtoul(musl_optarg, &endptr, 0);
 
-			if (musl_optarg[0] == '\0' || *endptr != '\0')
+			if (musl_optarg[0] == '\0' || *endptr != '\0') {
 				errx("Invalid argument for option 'X'");
+			}
 
-			if (maxValue > UINT_MAX)
+			if (maxValue > UINT_MAX) {
 				errx("Argument for option 'X' must be between 0 and %u", UINT_MAX);
+			}
 
 			maxErrors = maxValue;
 			break;
@@ -332,10 +354,12 @@ int main(int argc, char *argv[]) {
 			case 'Q':
 			case 'T':
 				newTarget = musl_optarg;
-				if (depType == 'Q')
+				if (depType == 'Q') {
 					newTarget = make_escape(newTarget);
-				if (!targetFileName.empty())
+				}
+				if (!targetFileName.empty()) {
 					targetFileName += ' ';
+				}
 				targetFileName += newTarget;
 				break;
 			}
@@ -348,8 +372,9 @@ int main(int argc, char *argv[]) {
 		}
 	}
 
-	if (targetFileName.empty() && !objectFileName.empty())
+	if (targetFileName.empty() && !objectFileName.empty()) {
 		targetFileName = objectFileName;
+	}
 
 	if (argc == musl_optind) {
 		fputs(
@@ -365,13 +390,15 @@ int main(int argc, char *argv[]) {
 
 	std::string mainFileName = argv[musl_optind];
 
-	if (verbose)
+	if (verbose) {
 		printf("Assembling %s\n", mainFileName.c_str());
+	}
 
 	if (dependFile) {
-		if (targetFileName.empty())
+		if (targetFileName.empty()) {
 			errx("Dependency files can only be created if a target file is specified with either "
 			     "-o, -MQ or -MT");
+		}
 
 		fprintf(dependFile, "%s: %s\n", targetFileName.c_str(), mainFileName.c_str());
 	}
@@ -382,8 +409,9 @@ int main(int argc, char *argv[]) {
 	fstk_Init(mainFileName, maxDepth);
 
 	// Perform parse (`yy::parser` is auto-generated from `parser.y`)
-	if (yy::parser parser; parser.parse() != 0 && nbErrors == 0)
+	if (yy::parser parser; parser.parse() != 0 && nbErrors == 0) {
 		nbErrors = 1;
+	}
 
 	if (!failedOnMissingInclude) {
 		sect_CheckUnionClosed();
@@ -395,17 +423,20 @@ int main(int argc, char *argv[]) {
 		sect_CheckStack();
 	}
 
-	if (nbErrors != 0)
+	if (nbErrors != 0) {
 		errx("Assembly aborted (%u error%s)!", nbErrors, nbErrors == 1 ? "" : "s");
+	}
 
 	// If parse aborted due to missing an include, and `-MG` was given, exit normally
-	if (failedOnMissingInclude)
+	if (failedOnMissingInclude) {
 		return 0;
+	}
 
 	out_WriteObject();
 
-	for (auto [name, features] : stateFileSpecs)
+	for (auto [name, features] : stateFileSpecs) {
 		out_WriteState(name, features);
+	}
 
 	return 0;
 }
diff --git a/src/asm/opt.cpp b/src/asm/opt.cpp
index ac5442ccc..e678a97df 100644
--- a/src/asm/opt.cpp
+++ b/src/asm/opt.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include <ctype.h>
 #include <errno.h>
@@ -53,17 +53,19 @@ void opt_W(char const *flag) {
 void opt_Parse(char const *s) {
 	switch (s[0]) {
 	case 'b':
-		if (strlen(&s[1]) == 2)
+		if (strlen(&s[1]) == 2) {
 			opt_B(&s[1]);
-		else
+		} else {
 			error("Must specify exactly 2 characters for option 'b'\n");
+		}
 		break;
 
 	case 'g':
-		if (strlen(&s[1]) == 4)
+		if (strlen(&s[1]) == 4) {
 			opt_G(&s[1]);
-		else
+		} else {
 			error("Must specify exactly 4 characters for option 'g'\n");
+		}
 		break;
 
 	case 'p':
@@ -72,12 +74,13 @@ void opt_Parse(char const *s) {
 			unsigned int padByte;
 
 			result = sscanf(&s[1], "%x", &padByte);
-			if (result != 1)
+			if (result != 1) {
 				error("Invalid argument for option 'p'\n");
-			else if (padByte > 0xFF)
+			} else if (padByte > 0xFF) {
 				error("Argument for option 'p' must be between 0 and 0xFF\n");
-			else
+			} else {
 				opt_P(padByte);
+			}
 		} else {
 			error("Invalid argument for option 'p'\n");
 		}
@@ -86,19 +89,21 @@ void opt_Parse(char const *s) {
 		char const *precisionArg;
 	case 'Q':
 		precisionArg = &s[1];
-		if (precisionArg[0] == '.')
+		if (precisionArg[0] == '.') {
 			precisionArg++;
+		}
 		if (strlen(precisionArg) <= 2) {
 			int result;
 			unsigned int precision;
 
 			result = sscanf(precisionArg, "%u", &precision);
-			if (result != 1)
+			if (result != 1) {
 				error("Invalid argument for option 'Q'\n");
-			else if (precision < 1 || precision > 31)
+			} else if (precision < 1 || precision > 31) {
 				error("Argument for option 'Q' must be between 1 and 31\n");
-			else
+			} else {
 				opt_Q(precision);
+			}
 		} else {
 			error("Invalid argument for option 'Q'\n");
 		}
@@ -106,8 +111,9 @@ void opt_Parse(char const *s) {
 
 	case 'r': {
 		++s; // Skip 'r'
-		while (isblank(*s))
+		while (isblank(*s)) {
 			++s; // Skip leading whitespace
+		}
 
 		if (s[0] == '\0') {
 			error("Missing argument to option 'r'\n");
@@ -128,10 +134,11 @@ void opt_Parse(char const *s) {
 	}
 
 	case 'W':
-		if (strlen(&s[1]) > 0)
+		if (strlen(&s[1]) > 0) {
 			opt_W(&s[1]);
-		else
+		} else {
 			error("Must specify an argument for option 'W'\n");
+		}
 		break;
 
 	default:
diff --git a/src/asm/output.cpp b/src/asm/output.cpp
index 57c359e21..e65b03f06 100644
--- a/src/asm/output.cpp
+++ b/src/asm/output.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/output.hpp"
 
@@ -63,11 +63,13 @@ void out_RegisterNode(std::shared_ptr<FileStackNode> node) {
 
 // Return a section's ID, or UINT32_MAX if the section is not in the list
 static uint32_t getSectIDIfAny(Section *sect) {
-	if (!sect)
+	if (!sect) {
 		return UINT32_MAX;
+	}
 
-	if (auto search = sectionMap.find(sect->name); search != sectionMap.end())
+	if (auto search = sectionMap.find(sect->name); search != sectionMap.end()) {
 		return static_cast<uint32_t>(search->second);
+	}
 
 	fatalerror("Unknown section '%s'\n", sect->name.c_str());
 }
@@ -109,8 +111,9 @@ static void writeSection(Section const &sect, FILE *file) {
 		fwrite(sect.data.data(), 1, sect.size, file);
 		putLong(sect.patches.size(), file);
 
-		for (Patch const &patch : sect.patches)
+		for (Patch const &patch : sect.patches) {
 			writePatch(patch, file);
+		}
 	}
 }
 
@@ -162,8 +165,9 @@ static void writeRpn(std::vector<uint8_t> &rpnexpr, std::vector<uint8_t> const &
 			symName.clear();
 			for (;;) {
 				uint8_t c = rpn[offset++];
-				if (c == 0)
+				if (c == 0) {
 					break;
+				}
 				symName += c;
 			}
 
@@ -188,8 +192,9 @@ static void writeRpn(std::vector<uint8_t> &rpnexpr, std::vector<uint8_t> const &
 			symName.clear();
 			for (;;) {
 				uint8_t c = rpn[offset++];
-				if (c == 0)
+				if (c == 0) {
 					break;
+				}
 				symName += c;
 			}
 
@@ -298,14 +303,16 @@ static void writeFileStackNode(FileStackNode const &node, FILE *file) {
 
 		putLong(nodeIters.size(), file);
 		// Iters are stored by decreasing depth, so reverse the order for output
-		for (uint32_t i = nodeIters.size(); i--;)
+		for (uint32_t i = nodeIters.size(); i--;) {
 			putLong(nodeIters[i], file);
+		}
 	}
 }
 
 void out_WriteObject() {
-	if (objectFileName.empty())
+	if (objectFileName.empty()) {
 		return;
+	}
 
 	FILE *file;
 	if (objectFileName != "-") {
@@ -315,8 +322,9 @@ void out_WriteObject() {
 		(void)setmode(STDOUT_FILENO, O_BINARY);
 		file = stdout;
 	}
-	if (!file)
+	if (!file) {
 		err("Failed to open object file '%s'", objectFileName.c_str());
+	}
 	Defer closeFile{[&] { fclose(file); }};
 
 	// Also write symbols that weren't written above
@@ -335,33 +343,39 @@ void out_WriteObject() {
 		writeFileStackNode(node, file);
 
 		// The list is supposed to have decrementing IDs
-		if (it + 1 != fileStackNodes.end() && it[1]->ID != node.ID - 1)
+		if (it + 1 != fileStackNodes.end() && it[1]->ID != node.ID - 1) {
 			fatalerror(
 			    "Internal error: fstack node #%" PRIu32 " follows #%" PRIu32
 			    ". Please report this to the developers!\n",
 			    it[1]->ID,
 			    node.ID
 			);
+		}
 	}
 
-	for (Symbol const *sym : objectSymbols)
+	for (Symbol const *sym : objectSymbols) {
 		writeSymbol(*sym, file);
+	}
 
-	for (Section const &sect : sectionList)
+	for (Section const &sect : sectionList) {
 		writeSection(sect, file);
+	}
 
 	putLong(assertions.size(), file);
 
-	for (Assertion const &assert : assertions)
+	for (Assertion const &assert : assertions) {
 		writeAssert(assert, file);
+	}
 }
 
 void out_SetFileName(std::string const &name) {
-	if (!objectFileName.empty())
+	if (!objectFileName.empty()) {
 		warnx("Overriding output filename %s", objectFileName.c_str());
+	}
 	objectFileName = name;
-	if (verbose)
+	if (verbose) {
 		printf("Output filename %s\n", objectFileName.c_str());
+	}
 }
 
 static void dumpString(std::string const &escape, FILE *file) {
@@ -397,8 +411,9 @@ static bool dumpEquConstants(FILE *file) {
 	equConstants.clear();
 
 	sym_ForEach([](Symbol &sym) {
-		if (!sym.isBuiltin && sym.type == SYM_EQU)
+		if (!sym.isBuiltin && sym.type == SYM_EQU) {
 			equConstants.push_back(&sym);
+		}
 	});
 	// Constants are ordered by file, then by definition order
 	std::sort(RANGE(equConstants), [](Symbol *sym1, Symbol *sym2) -> bool {
@@ -418,8 +433,9 @@ static bool dumpVariables(FILE *file) {
 	variables.clear();
 
 	sym_ForEach([](Symbol &sym) {
-		if (!sym.isBuiltin && sym.type == SYM_VAR)
+		if (!sym.isBuiltin && sym.type == SYM_VAR) {
 			variables.push_back(&sym);
+		}
 	});
 	// Variables are ordered by file, then by definition order
 	std::sort(RANGE(variables), [](Symbol *sym1, Symbol *sym2) -> bool {
@@ -439,8 +455,9 @@ static bool dumpEqusConstants(FILE *file) {
 	equsConstants.clear();
 
 	sym_ForEach([](Symbol &sym) {
-		if (!sym.isBuiltin && sym.type == SYM_EQUS)
+		if (!sym.isBuiltin && sym.type == SYM_EQUS) {
 			equsConstants.push_back(&sym);
+		}
 	});
 	// Constants are ordered by file, then by definition order
 	std::sort(RANGE(equsConstants), [](Symbol *sym1, Symbol *sym2) -> bool {
@@ -467,8 +484,9 @@ static bool dumpCharmaps(FILE *file) {
 		    fputs("charmap \"", charmapFile);
 		    dumpString(mapping, charmapFile);
 		    putc('"', charmapFile);
-		    for (int32_t v : value)
+		    for (int32_t v : value) {
 			    fprintf(charmapFile, ", $%" PRIx32, v);
+		    }
 		    putc('\n', charmapFile);
 	    }
 	);
@@ -479,8 +497,9 @@ static bool dumpMacros(FILE *file) {
 	macros.clear();
 
 	sym_ForEach([](Symbol &sym) {
-		if (!sym.isBuiltin && sym.type == SYM_MACRO)
+		if (!sym.isBuiltin && sym.type == SYM_MACRO) {
 			macros.push_back(&sym);
+		}
 	});
 	// Macros are ordered by file, then by definition order
 	std::sort(RANGE(macros), [](Symbol *sym1, Symbol *sym2) -> bool {
@@ -508,8 +527,9 @@ void out_WriteState(std::string name, std::vector<StateFeature> const &features)
 		(void)setmode(STDOUT_FILENO, O_BINARY);
 		file = stdout;
 	}
-	if (!file)
+	if (!file) {
 		err("Failed to open state file '%s'", name.c_str());
+	}
 	Defer closeFile{[&] { fclose(file); }};
 
 	static char const *dumpHeadings[NB_STATE_FEATURES] = {
@@ -530,7 +550,8 @@ void out_WriteState(std::string name, std::vector<StateFeature> const &features)
 	fputs("; File generated by rgbasm\n", file);
 	for (StateFeature feature : features) {
 		fprintf(file, "\n; %s\n", dumpHeadings[feature]);
-		if (!dumpFuncs[feature](file))
+		if (!dumpFuncs[feature](file)) {
 			fprintf(file, "; No values\n");
+		}
 	}
 }
diff --git a/src/asm/parser.y b/src/asm/parser.y
index a2b97b376..4150ed41c 100644
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 %language "c++"
 %define api.value.type variant
@@ -9,14 +9,14 @@
 	#include <string>
 	#include <vector>
 
+	#include "either.hpp"
+	#include "linkdefs.hpp"
+
 	#include "asm/lexer.hpp"
 	#include "asm/macro.hpp"
 	#include "asm/rpn.hpp"
 	#include "asm/section.hpp"
 
-	#include "either.hpp"
-	#include "linkdefs.hpp"
-
 	struct AlignmentSpec {
 		uint8_t alignment;
 		uint16_t alignOfs;
@@ -42,6 +42,7 @@
 		StrFmtArgList &operator=(StrFmtArgList &&) = default;
 	};
 }
+
 %code {
 	#include <algorithm>
 	#include <ctype.h>
@@ -51,6 +52,9 @@
 	#include <string.h>
 	#include <string_view>
 
+	#include "extern/utf8decoder.hpp"
+	#include "helpers.hpp"
+
 	#include "asm/charmap.hpp"
 	#include "asm/fixpoint.hpp"
 	#include "asm/format.hpp"
@@ -62,10 +66,6 @@
 	#include "asm/symbol.hpp"
 	#include "asm/warning.hpp"
 
-	#include "extern/utf8decoder.hpp"
-
-	#include "helpers.hpp"
-
 	using namespace std::literals;
 
 	yy::parser::symbol_type yylex(); // Provided by lexer.cpp
@@ -77,9 +77,7 @@
 	static size_t charlenUTF8(std::string const &str);
 	static std::string charsubUTF8(std::string const &str, uint32_t pos);
 	static uint32_t adjustNegativePos(int32_t pos, size_t len, char const *functionName);
-	static std::string strrpl(
-	    std::string_view str, std::string const &old, std::string const &rep
-	);
+	static std::string strrpl(std::string_view str, std::string const &old, std::string const &rep);
 	static std::string strfmt(
 	    std::string const &spec, std::vector<Either<uint32_t, std::string>> const &args
 	);
@@ -457,22 +455,23 @@ if:
 	POP_IF iconst NEWLINE {
 		lexer_IncIFDepth();
 
-		if ($2)
+		if ($2) {
 			lexer_RunIFBlock();
-		else
+		} else {
 			lexer_SetMode(LEXER_SKIP_TO_ELIF);
+		}
 	}
 ;
 
 elif:
 	POP_ELIF iconst NEWLINE {
-		if (lexer_GetIFDepth() == 0)
+		if (lexer_GetIFDepth() == 0) {
 			fatalerror("Found ELIF outside of an IF construct\n");
-
+		}
 		if (lexer_RanIFBlock()) {
-			if (lexer_ReachedELSEBlock())
+			if (lexer_ReachedELSEBlock()) {
 				fatalerror("Found ELIF after an ELSE block\n");
-
+			}
 			lexer_SetMode(LEXER_SKIP_TO_ENDC);
 		} else if ($2) {
 			lexer_RunIFBlock();
@@ -484,13 +483,13 @@ elif:
 
 else:
 	POP_ELSE NEWLINE {
-		if (lexer_GetIFDepth() == 0)
+		if (lexer_GetIFDepth() == 0) {
 			fatalerror("Found ELSE outside of an IF construct\n");
-
+		}
 		if (lexer_RanIFBlock()) {
-			if (lexer_ReachedELSEBlock())
+			if (lexer_ReachedELSEBlock()) {
 				fatalerror("Found ELSE after an ELSE block\n");
-
+			}
 			lexer_SetMode(LEXER_SKIP_TO_ENDC);
 		} else {
 			lexer_RunIFBlock();
@@ -818,12 +817,14 @@ assert:
 		}
 	}
 	| POP_STATIC_ASSERT assert_type iconst {
-		if ($3 == 0)
+		if ($3 == 0) {
 			failAssert($2);
+		}
 	}
 	| POP_STATIC_ASSERT assert_type iconst COMMA string {
-		if ($3 == 0)
+		if ($3 == 0) {
 			failAssertMsg($2, $5);
+		}
 	}
 ;
 
@@ -855,8 +856,9 @@ load:
 
 rept:
 	POP_REPT uconst NEWLINE capture_rept endofline {
-		if ($4.span.ptr)
+		if ($4.span.ptr) {
 			fstk_RunRept($2, $4.lineNo, $4.span);
+		}
 	}
 ;
 
@@ -866,8 +868,9 @@ for:
 	} ID {
 		lexer_ToggleStringExpansion(true);
 	} COMMA for_args NEWLINE capture_rept endofline {
-		if ($8.span.ptr)
+		if ($8.span.ptr) {
 			fstk_RunFor($3, $6.start, $6.stop, $6.step, $8.lineNo, $8.span);
+		}
 	}
 ;
 
@@ -897,8 +900,9 @@ for_args:
 
 break:
 	label POP_BREAK endofline {
-		if (fstk_Break())
+		if (fstk_Break()) {
 			lexer_SetMode(LEXER_SKIP_TO_ENDR);
+		}
 	}
 ;
 
@@ -908,8 +912,9 @@ def_macro:
 	} ID {
 		lexer_ToggleStringExpansion(true);
 	} NEWLINE capture_macro endofline {
-		if ($6.span.ptr)
+		if ($6.span.ptr) {
 			sym_AddMacro($3, $6.lineNo, $6.span);
+		}
 	}
 ;
 
@@ -1086,8 +1091,9 @@ purge:
 	POP_PURGE {
 		lexer_ToggleStringExpansion(false);
 	} purge_args trailing_comma {
-		for (std::string &arg : $3)
+		for (std::string &arg : $3) {
 			sym_Purge(arg);
+		}
 		lexer_ToggleStringExpansion(true);
 	}
 ;
@@ -1124,26 +1130,30 @@ export_def:
 include:
 	label POP_INCLUDE string endofline {
 		fstk_RunInclude($3, false);
-		if (failedOnMissingInclude)
+		if (failedOnMissingInclude) {
 			YYACCEPT;
+		}
 	}
 ;
 
 incbin:
 	POP_INCBIN string {
 		sect_BinaryFile($2, 0);
-		if (failedOnMissingInclude)
+		if (failedOnMissingInclude) {
 			YYACCEPT;
+		}
 	}
 	| POP_INCBIN string COMMA iconst {
 		sect_BinaryFile($2, $4);
-		if (failedOnMissingInclude)
+		if (failedOnMissingInclude) {
 			YYACCEPT;
+		}
 	}
 	| POP_INCBIN string COMMA iconst COMMA iconst {
 		sect_BinaryFileSlice($2, $4, $6);
-		if (failedOnMissingInclude)
+		if (failedOnMissingInclude) {
 			YYACCEPT;
+		}
 	}
 ;
 
@@ -1523,8 +1533,9 @@ relocexpr_no_str:
 uconst:
 	iconst {
 		$$ = $1;
-		if ($$ < 0)
+		if ($$ < 0) {
 			fatalerror("Constant must not be negative: %d\n", $$);
+		}
 	}
 ;
 
@@ -1599,15 +1610,17 @@ string:
 		Symbol *sym = sym_FindScopedValidSymbol($3);
 
 		if (!sym) {
-			if (sym_IsPurgedScoped($3))
+			if (sym_IsPurgedScoped($3)) {
 				fatalerror("Unknown symbol \"%s\"; it was purged\n", $3.c_str());
-			else
+			} else {
 				fatalerror("Unknown symbol \"%s\"\n", $3.c_str());
+			}
 		}
 		Section const *section = sym->getSection();
 
-		if (!section)
+		if (!section) {
 			fatalerror("\"%s\" does not belong to any section\n", sym->name.c_str());
+		}
 		// Section names are capped by rgbasm's maximum string length,
 		// so this currently can't overflow.
 		$$ = section->name;
@@ -1989,8 +2002,9 @@ c_ind: LBRACK MODE_C RBRACK;
 ff00_c_ind:
 	LBRACK relocexpr OP_ADD MODE_C RBRACK {
 		// This has to use `relocexpr`, not `iconst`, to avoid a shift/reduce conflict
-		if ($2.getConstVal() != 0xFF00)
+		if ($2.getConstVal() != 0xFF00) {
 			::error("Base value must be equal to $FF00 for $FF00+C\n");
+		}
 	}
 ;
 
@@ -2059,10 +2073,11 @@ sm83_ld_r_no_a:
 		sect_RelByte($4, 1);
 	}
 	| SM83_LD reg_r_no_a COMMA reg_r {
-		if ($2 == REG_HL_IND && $4 == REG_HL_IND)
+		if ($2 == REG_HL_IND && $4 == REG_HL_IND) {
 			::error("LD [HL], [HL] is not a valid instruction\n");
-		else
+		} else {
 			sect_ConstByte(0x40 | ($2 << 3) | $4);
+		}
 	}
 ;
 
@@ -2208,10 +2223,11 @@ sm83_rrca:
 sm83_rst:
 	SM83_RST reloc_8bit {
 		$2.makeCheckRST();
-		if (!$2.isKnown())
+		if (!$2.isKnown()) {
 			sect_RelByte($2, 0);
-		else
+		} else {
 			sect_ConstByte(0xC7 | $2.value());
+		}
 	}
 ;
 
@@ -2487,8 +2503,9 @@ static uint32_t strToNum(std::vector<int32_t> const &s) {
 	warning(WARNING_OBSOLETE, "Treating multi-unit strings as numbers is deprecated\n");
 
 	for (int32_t v : s) {
-		if (!checkNBit(v, 8, "All character units"))
+		if (!checkNBit(v, 8, "All character units")) {
 			break;
+		}
 	}
 
 	uint32_t r = 0;
@@ -2525,8 +2542,9 @@ static size_t strlenUTF8(std::string const &str) {
 	}
 
 	// Check for partial code point.
-	if (state != 0)
+	if (state != 0) {
 		error("STRLEN: Incomplete UTF-8 character\n");
+	}
 
 	return len;
 }
@@ -2554,10 +2572,11 @@ static std::string strsubUTF8(std::string const &str, uint32_t pos, uint32_t len
 
 	// A position 1 past the end of the string is allowed, but will trigger the
 	// "Length too big" warning below if the length is nonzero.
-	if (!ptr[index] && pos > curPos)
+	if (!ptr[index] && pos > curPos) {
 		warning(
 		    WARNING_BUILTIN_ARG, "STRSUB: Position %" PRIu32 " is past the end of the string\n", pos
 		);
+	}
 
 	size_t startIndex = index;
 	uint32_t curLen = 0;
@@ -2576,12 +2595,14 @@ static std::string strsubUTF8(std::string const &str, uint32_t pos, uint32_t len
 		index++;
 	}
 
-	if (curLen < len)
+	if (curLen < len) {
 		warning(WARNING_BUILTIN_ARG, "STRSUB: Length too big: %" PRIu32 "\n", len);
+	}
 
 	// Check for partial code point.
-	if (state != 0)
+	if (state != 0) {
 		error("STRSUB: Incomplete UTF-8 character\n");
+	}
 
 	return std::string(ptr + startIndex, ptr + index);
 }
@@ -2600,17 +2621,19 @@ static std::string charsubUTF8(std::string const &str, uint32_t pos) {
 	size_t charLen = 1;
 
 	// Advance to starting position in source string.
-	for (uint32_t curPos = 1; charLen && curPos < pos; curPos++)
+	for (uint32_t curPos = 1; charLen && curPos < pos; curPos++) {
 		charLen = charmap_ConvertNext(view, nullptr);
+	}
 
 	std::string_view start = view;
 
-	if (!charmap_ConvertNext(view, nullptr))
+	if (!charmap_ConvertNext(view, nullptr)) {
 		warning(
 		    WARNING_BUILTIN_ARG,
 		    "CHARSUB: Position %" PRIu32 " is past the end of the string\n",
 		    pos
 		);
+	}
 
 	start = start.substr(0, start.length() - view.length());
 	return std::string(start);
@@ -2619,8 +2642,9 @@ static std::string charsubUTF8(std::string const &str, uint32_t pos) {
 static uint32_t adjustNegativePos(int32_t pos, size_t len, char const *functionName) {
 	// STRSUB and CHARSUB adjust negative `pos` arguments the same way,
 	// such that position -1 is the last character of a string.
-	if (pos < 0)
+	if (pos < 0) {
 		pos += len + 1;
+	}
 	if (pos < 1) {
 		warning(WARNING_BUILTIN_ARG, "%s: Position starts at 1\n", functionName);
 		pos = 1;
@@ -2650,9 +2674,8 @@ static std::string strrpl(std::string_view str, std::string const &old, std::str
 	return rpl;
 }
 
-static std::string strfmt(
-    std::string const &spec, std::vector<Either<uint32_t, std::string>> const &args
-) {
+static std::string
+    strfmt(std::string const &spec, std::vector<Either<uint32_t, std::string>> const &args) {
 	std::string str;
 	size_t argIndex = 0;
 
@@ -2675,8 +2698,9 @@ static std::string strfmt(
 
 		while (c != '\0') {
 			fmt.useCharacter(c);
-			if (fmt.isFinished())
+			if (fmt.isFinished()) {
 				break;
+			}
 			c = spec[++i];
 		}
 
@@ -2701,14 +2725,15 @@ static std::string strfmt(
 		argIndex++;
 	}
 
-	if (argIndex < args.size())
+	if (argIndex < args.size()) {
 		error("STRFMT: %zu unformatted argument(s)\n", args.size() - argIndex);
-	else if (argIndex > args.size())
+	} else if (argIndex > args.size()) {
 		error(
 		    "STRFMT: Not enough arguments for format spec, got: %zu, need: %zu\n",
 		    args.size(),
 		    argIndex
 		);
+	}
 
 	return str;
 }
diff --git a/src/asm/rpn.cpp b/src/asm/rpn.cpp
index fb71cec6b..903002a68 100644
--- a/src/asm/rpn.cpp
+++ b/src/asm/rpn.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/rpn.hpp"
 
@@ -46,8 +46,9 @@ int32_t Expression::getConstVal() const {
 }
 
 Symbol const *Expression::symbolOf() const {
-	if (!isSymbol)
+	if (!isSymbol) {
 		return nullptr;
+	}
 	return sym_FindScopedSymbol(reinterpret_cast<char const *>(&rpn[1]));
 }
 
@@ -55,8 +56,9 @@ bool Expression::isDiffConstant(Symbol const *sym) const {
 	// Check if both expressions only refer to a single symbol
 	Symbol const *sym1 = symbolOf();
 
-	if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL)
+	if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL) {
 		return false;
+	}
 
 	Section const *sect1 = sym1->getSection();
 	Section const *sect2 = sym->getSection();
@@ -77,9 +79,9 @@ void Expression::makeSymbol(std::string const &symName) {
 		isSymbol = true;
 
 		data = sym_IsPC(sym) ? "PC is not constant at assembly time"
-		                     : sym_IsPurgedScoped(symName)
-		                     ? "'"s + symName + "' is not constant at assembly time; it was purged"
-		                     : "'"s + symName + "' is not constant at assembly time";
+		       : sym_IsPurgedScoped(symName)
+		           ? "'"s + symName + "' is not constant at assembly time; it was purged"
+		           : "'"s + symName + "' is not constant at assembly time";
 		sym = sym_Ref(symName);
 
 		size_t nameLen = sym->name.length() + 1; // Don't forget NUL!
@@ -120,8 +122,8 @@ void Expression::makeBankSymbol(std::string const &symName) {
 			data = static_cast<int32_t>(sym->getSection()->bank);
 		} else {
 			data = sym_IsPurgedScoped(symName)
-			       ? "\""s + symName + "\"'s bank is not known; it was purged"
-			       : "\""s + symName + "\"'s bank is not known";
+			           ? "\""s + symName + "\"'s bank is not known; it was purged"
+			           : "\""s + symName + "\"'s bank is not known";
 
 			size_t nameLen = sym->name.length() + 1; // Room for NUL!
 
@@ -208,8 +210,9 @@ static bool tryConstNonzero(Expression const &lhs, Expression const &rhs) {
 
 static bool tryConstLogNot(Expression const &expr) {
 	Symbol const *sym = expr.symbolOf();
-	if (!sym || !sym->getSection() || !sym->isDefined())
+	if (!sym || !sym->getSection() || !sym->isDefined()) {
 		return false;
+	}
 
 	assume(sym->isNumeric());
 
@@ -225,23 +228,22 @@ static bool tryConstLogNot(Expression const &expr) {
 	return knownBits != 0;
 }
 
-/*
- * Attempts to compute a constant LOW() from non-constant argument
- * This is possible if the argument is a symbol belonging to an `ALIGN[8]` section.
- *
- * @return The constant `LOW(expr)` result if it can be computed, or -1 otherwise.
- */
+// Attempts to compute a constant LOW() from non-constant argument
+// This is possible if the argument is a symbol belonging to an `ALIGN[8]` section.
+// @return The constant `LOW(expr)` result if it can be computed, or -1 otherwise.
 static int32_t tryConstLow(Expression const &expr) {
 	Symbol const *sym = expr.symbolOf();
-	if (!sym || !sym->getSection() || !sym->isDefined())
+	if (!sym || !sym->getSection() || !sym->isDefined()) {
 		return -1;
+	}
 
 	assume(sym->isNumeric());
 
 	// The low byte must not cover any unknown bits
 	Section const &sect = *sym->getSection();
-	if (sect.align < 8)
+	if (sect.align < 8) {
 		return -1;
+	}
 
 	// `sym->getValue()` attempts to add the section's address, but that's `UINT32_MAX`
 	// because the section is floating (otherwise we wouldn't be here)
@@ -251,28 +253,27 @@ static int32_t tryConstLow(Expression const &expr) {
 	return (symbolOfs + sect.alignOfs) & 0xFF;
 }
 
-/*
- * Attempts to compute a constant binary AND with one non-constant operands
- * This is possible if one operand is a symbol belonging to an `ALIGN[N]` section, and the other is
- * a constant that only keeps (some of) the lower N bits.
- *
- * @return The constant `lhs & rhs` result if it can be computed, or -1 otherwise.
- */
+// Attempts to compute a constant binary AND with one non-constant operands
+// This is possible if one operand is a symbol belonging to an `ALIGN[N]` section, and the other is
+// a constant that only keeps (some of) the lower N bits.
+// @return The constant `lhs & rhs` result if it can be computed, or -1 otherwise.
 static int32_t tryConstMask(Expression const &lhs, Expression const &rhs) {
 	Symbol const *lhsSymbol = lhs.symbolOf();
 	Symbol const *rhsSymbol = lhsSymbol ? nullptr : rhs.symbolOf();
 	bool lhsIsSymbol = lhsSymbol && lhsSymbol->getSection();
 	bool rhsIsSymbol = rhsSymbol && rhsSymbol->getSection();
 
-	if (!lhsIsSymbol && !rhsIsSymbol)
+	if (!lhsIsSymbol && !rhsIsSymbol) {
 		return -1;
+	}
 
 	// If the lhs isn't a symbol, try again the other way around
 	Symbol const &sym = lhsIsSymbol ? *lhsSymbol : *rhsSymbol;
 	Expression const &expr = lhsIsSymbol ? rhs : lhs; // Opposite side of `sym`
 
-	if (!sym.isDefined() || !expr.isKnown())
+	if (!sym.isDefined() || !expr.isKnown()) {
 		return -1;
+	}
 
 	assume(sym.isNumeric());
 
@@ -281,8 +282,9 @@ static int32_t tryConstMask(Expression const &lhs, Expression const &rhs) {
 
 	// The mask must not cover any unknown bits
 	Section const &sect = *sym.getSection();
-	if (int32_t unknownBits = (1 << 16) - (1 << sect.align); (unknownBits & mask) != 0)
+	if (int32_t unknownBits = (1 << 16) - (1 << sect.align); (unknownBits & mask) != 0) {
 		return -1;
+	}
 
 	// `sym.getValue()` attempts to add the section's address, but that's `UINT32_MAX`
 	// because the section is floating (otherwise we wouldn't be here)
@@ -418,38 +420,45 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
 			data = lval & rval;
 			break;
 		case RPN_SHL:
-			if (rval < 0)
+			if (rval < 0) {
 				warning(
 				    WARNING_SHIFT_AMOUNT, "Shifting left by negative amount %" PRId32 "\n", rval
 				);
+			}
 
-			if (rval >= 32)
+			if (rval >= 32) {
 				warning(WARNING_SHIFT_AMOUNT, "Shifting left by large amount %" PRId32 "\n", rval);
+			}
 
 			data = op_shift_left(lval, rval);
 			break;
 		case RPN_SHR:
-			if (lval < 0)
+			if (lval < 0) {
 				warning(WARNING_SHIFT, "Shifting right negative value %" PRId32 "\n", lval);
+			}
 
-			if (rval < 0)
+			if (rval < 0) {
 				warning(
 				    WARNING_SHIFT_AMOUNT, "Shifting right by negative amount %" PRId32 "\n", rval
 				);
+			}
 
-			if (rval >= 32)
+			if (rval >= 32) {
 				warning(WARNING_SHIFT_AMOUNT, "Shifting right by large amount %" PRId32 "\n", rval);
+			}
 
 			data = op_shift_right(lval, rval);
 			break;
 		case RPN_USHR:
-			if (rval < 0)
+			if (rval < 0) {
 				warning(
 				    WARNING_SHIFT_AMOUNT, "Shifting right by negative amount %" PRId32 "\n", rval
 				);
+			}
 
-			if (rval >= 32)
+			if (rval >= 32) {
 				warning(WARNING_SHIFT_AMOUNT, "Shifting right by large amount %" PRId32 "\n", rval);
+			}
 
 			data = op_shift_right_unsigned(lval, rval);
 			break;
@@ -457,8 +466,9 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
 			data = static_cast<int32_t>(ulval * urval);
 			break;
 		case RPN_DIV:
-			if (rval == 0)
+			if (rval == 0) {
 				fatalerror("Division by zero\n");
+			}
 
 			if (lval == INT32_MIN && rval == -1) {
 				warning(
@@ -473,17 +483,20 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
 			}
 			break;
 		case RPN_MOD:
-			if (rval == 0)
+			if (rval == 0) {
 				fatalerror("Modulo by zero\n");
+			}
 
-			if (lval == INT32_MIN && rval == -1)
+			if (lval == INT32_MIN && rval == -1) {
 				data = 0;
-			else
+			} else {
 				data = op_modulo(lval, rval);
+			}
 			break;
 		case RPN_EXP:
-			if (rval < 0)
+			if (rval < 0) {
 				fatalerror("Exponentiation by negative power\n");
+			}
 
 			data = op_exponent(lval, rval);
 			break;
@@ -560,9 +573,10 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
 			// Copy the right RPN and append the operator
 			uint32_t rightRpnSize = src2.rpn.size();
 			uint8_t *ptr = reserveSpace(rightRpnSize + 1, src2.rpnPatchSize + 1);
-			if (rightRpnSize > 0)
+			if (rightRpnSize > 0) {
 				// If `rightRpnSize == 0`, then `memcpy(ptr, nullptr, rightRpnSize)` would be UB
 				memcpy(ptr, src2.rpn.data(), rightRpnSize);
+			}
 			ptr[rightRpnSize] = op;
 		}
 	}
@@ -595,8 +609,9 @@ void Expression::makeCheckRST() {
 
 // Checks that an RPN expression's value fits within N bits (signed or unsigned)
 void Expression::checkNBit(uint8_t n) const {
-	if (isKnown())
+	if (isKnown()) {
 		::checkNBit(value(), n, "Expression");
+	}
 }
 
 bool checkNBit(int32_t v, uint8_t n, char const *name) {
diff --git a/src/asm/section.cpp b/src/asm/section.cpp
index 25553888a..ba518ccfb 100644
--- a/src/asm/section.cpp
+++ b/src/asm/section.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/section.hpp"
 
@@ -49,9 +49,11 @@ static std::pair<Symbol const *, Symbol const *> currentLoadLabelScopes = {nullp
 int32_t loadOffset; // Offset into the LOAD section's parent (see sect_GetOutputOffset)
 
 // A quick check to see if we have an initialized section
-[[nodiscard]] static bool requireSection() {
-	if (currentSection)
+[[nodiscard]]
+static bool requireSection() {
+	if (currentSection) {
 		return true;
+	}
 
 	error("Cannot output data outside of a SECTION\n");
 	return false;
@@ -59,12 +61,15 @@ int32_t loadOffset; // Offset into the LOAD section's parent (see sect_GetOutput
 
 // A quick check to see if we have an initialized section that can contain
 // this much initialized data
-[[nodiscard]] static bool requireCodeSection() {
-	if (!requireSection())
+[[nodiscard]]
+static bool requireCodeSection() {
+	if (!requireSection()) {
 		return false;
+	}
 
-	if (sect_HasData(currentSection->type))
+	if (sect_HasData(currentSection->type)) {
 		return true;
+	}
 
 	error(
 	    "Section '%s' cannot contain code or data (not ROM0 or ROMX)\n",
@@ -75,7 +80,7 @@ int32_t loadOffset; // Offset into the LOAD section's parent (see sect_GetOutput
 
 void sect_CheckSizes() {
 	for (Section const &sect : sectionList) {
-		if (uint32_t maxSize = sectionTypeInfo[sect.type].size; sect.size > maxSize)
+		if (uint32_t maxSize = sectionTypeInfo[sect.type].size; sect.size > maxSize) {
 			error(
 			    "Section '%s' grew too big (max size = 0x%" PRIX32 " bytes, reached 0x%" PRIX32
 			    ").\n",
@@ -83,6 +88,7 @@ void sect_CheckSizes() {
 			    maxSize,
 			    sect.size
 			);
+		}
 	}
 }
 
@@ -106,33 +112,36 @@ static unsigned int mergeSectUnion(
 
 	// Unionized sections only need "compatible" constraints, and they end up with the strictest
 	// combination of both.
-	if (sect_HasData(type))
+	if (sect_HasData(type)) {
 		sectError("Cannot declare ROM sections as UNION\n");
+	}
 
 	if (org != UINT32_MAX) {
 		// If both are fixed, they must be the same
-		if (sect.org != UINT32_MAX && sect.org != org)
+		if (sect.org != UINT32_MAX && sect.org != org) {
 			sectError(
 			    "Section already declared as fixed at different address $%04" PRIx32 "\n", sect.org
 			);
-		else if (sect.align != 0 && (mask(sect.align) & (org - sect.alignOfs)))
+		} else if (sect.align != 0 && (mask(sect.align) & (org - sect.alignOfs))) {
 			sectError(
 			    "Section already declared as aligned to %u bytes (offset %" PRIu16 ")\n",
 			    1U << sect.align,
 			    sect.alignOfs
 			);
-		else
+		} else {
 			// Otherwise, just override
 			sect.org = org;
+		}
 
 	} else if (alignment != 0) {
 		// Make sure any fixed address given is compatible
 		if (sect.org != UINT32_MAX) {
-			if ((sect.org - alignOffset) & mask(alignment))
+			if ((sect.org - alignOffset) & mask(alignment)) {
 				sectError(
 				    "Section already declared as fixed at incompatible address $%04" PRIx32 "\n",
 				    sect.org
 				);
+			}
 			// Check if alignment offsets are compatible
 		} else if ((alignOffset & mask(sect.align)) != (sect.alignOfs & mask(alignment))) {
 			sectError(
@@ -163,34 +172,37 @@ static unsigned int
 		uint16_t curOrg = org - sect.size;
 
 		// If both are fixed, they must be the same
-		if (sect.org != UINT32_MAX && sect.org != curOrg)
+		if (sect.org != UINT32_MAX && sect.org != curOrg) {
 			sectError(
 			    "Section already declared as fixed at incompatible address $%04" PRIx32 "\n",
 			    sect.org
 			);
-		else if (sect.align != 0 && (mask(sect.align) & (curOrg - sect.alignOfs)))
+		} else if (sect.align != 0 && (mask(sect.align) & (curOrg - sect.alignOfs))) {
 			sectError(
 			    "Section already declared as aligned to %u bytes (offset %" PRIu16 ")\n",
 			    1U << sect.align,
 			    sect.alignOfs
 			);
-		else
+		} else {
 			// Otherwise, just override
 			sect.org = curOrg;
+		}
 
 	} else if (alignment != 0) {
 		int32_t curOfs = (alignOffset - sect.size) % (1U << alignment);
 
-		if (curOfs < 0)
+		if (curOfs < 0) {
 			curOfs += 1U << alignment;
+		}
 
 		// Make sure any fixed address given is compatible
 		if (sect.org != UINT32_MAX) {
-			if ((sect.org - curOfs) & mask(alignment))
+			if ((sect.org - curOfs) & mask(alignment)) {
 				sectError(
 				    "Section already declared as fixed at incompatible address $%04" PRIx32 "\n",
 				    sect.org
 				);
+			}
 			// Check if alignment offsets are compatible
 		} else if ((curOfs & mask(sect.align)) != (sect.alignOfs & mask(alignment))) {
 			sectError(
@@ -220,10 +232,11 @@ static void mergeSections(
 ) {
 	unsigned int nbSectErrors = 0;
 
-	if (type != sect.type)
+	if (type != sect.type) {
 		sectError(
 		    "Section already exists but with type %s\n", sectionTypeInfo[sect.type].name.c_str()
 		);
+	}
 
 	if (sect.modifier != mod) {
 		sectError("Section already declared as %s section\n", sectionModNames[sect.modifier]);
@@ -238,11 +251,13 @@ static void mergeSections(
 			// Common checks
 
 			// If the section's bank is unspecified, override it
-			if (sect.bank == UINT32_MAX)
+			if (sect.bank == UINT32_MAX) {
 				sect.bank = bank;
+			}
 			// If both specify a bank, it must be the same one
-			else if (bank != UINT32_MAX && sect.bank != bank)
+			else if (bank != UINT32_MAX && sect.bank != bank) {
 				sectError("Section already declared with different bank %" PRIu32 "\n", sect.bank);
+			}
 			break;
 
 		case SECTION_NORMAL:
@@ -253,13 +268,14 @@ static void mergeSections(
 		}
 	}
 
-	if (nbSectErrors)
+	if (nbSectErrors) {
 		fatalerror(
 		    "Cannot create section \"%s\" (%u error%s)\n",
 		    sect.name.c_str(),
 		    nbSectErrors,
 		    nbSectErrors == 1 ? "" : "s"
 		);
+	}
 }
 
 #undef sectError
@@ -292,8 +308,9 @@ static Section *createSection(
 	out_RegisterNode(sect.src);
 
 	// It is only needed to allocate memory for ROM sections.
-	if (sect_HasData(type))
+	if (sect_HasData(type)) {
 		sect.data.resize(sectionTypeInfo[type].size);
+	}
 
 	return &sect;
 }
@@ -314,9 +331,10 @@ static Section *getSection(
 
 	if (bank != UINT32_MAX) {
 		if (type != SECTTYPE_ROMX && type != SECTTYPE_VRAM && type != SECTTYPE_SRAM
-		    && type != SECTTYPE_WRAMX)
+		    && type != SECTTYPE_WRAMX) {
 			error("BANK only allowed for ROMX, WRAMX, SRAM, or VRAM sections\n");
-		else if (bank < sectionTypeInfo[type].firstBank || bank > sectionTypeInfo[type].lastBank)
+		} else if (bank < sectionTypeInfo[type].firstBank
+		           || bank > sectionTypeInfo[type].lastBank) {
 			error(
 			    "%s bank value $%04" PRIx32 " out of range ($%04" PRIx32 " to $%04" PRIx32 ")\n",
 			    sectionTypeInfo[type].name.c_str(),
@@ -324,6 +342,7 @@ static Section *getSection(
 			    sectionTypeInfo[type].firstBank,
 			    sectionTypeInfo[type].lastBank
 			);
+		}
 	} else if (nbbanks(type) == 1) {
 		// If the section type only has a single bank, implicitly force it
 		bank = sectionTypeInfo[type].firstBank;
@@ -339,7 +358,7 @@ static Section *getSection(
 	}
 
 	if (org != UINT32_MAX) {
-		if (org < sectionTypeInfo[type].startAddr || org > endaddr(type))
+		if (org < sectionTypeInfo[type].startAddr || org > endaddr(type)) {
 			error(
 			    "Section \"%s\"'s fixed address $%04" PRIx32 " is outside of range [$%04" PRIx16
 			    "; $%04" PRIx16 "]\n",
@@ -348,6 +367,7 @@ static Section *getSection(
 			    sectionTypeInfo[type].startAddr,
 			    endaddr(type)
 			);
+		}
 	}
 
 	if (alignment != 0) {
@@ -359,8 +379,9 @@ static Section *getSection(
 		uint32_t mask = mask(alignment);
 
 		if (org != UINT32_MAX) {
-			if ((org - alignOffset) & mask)
+			if ((org - alignOffset) & mask) {
 				error("Section \"%s\"'s fixed address doesn't match its alignment\n", name.c_str());
+			}
 			alignment = 0; // Ignore it if it's satisfied
 		} else if (sectionTypeInfo[type].startAddr & mask) {
 			error(
@@ -393,25 +414,29 @@ static Section *getSection(
 
 // Set the current section
 static void changeSection() {
-	if (!currentUnionStack.empty())
+	if (!currentUnionStack.empty()) {
 		fatalerror("Cannot change the section within a UNION\n");
+	}
 
 	sym_ResetCurrentLabelScopes();
 }
 
 bool Section::isSizeKnown() const {
 	// SECTION UNION and SECTION FRAGMENT can still grow
-	if (modifier != SECTION_NORMAL)
+	if (modifier != SECTION_NORMAL) {
 		return false;
+	}
 
 	// The current section (or current load section if within one) is still growing
-	if (this == currentSection || this == currentLoadSection)
+	if (this == currentSection || this == currentLoadSection) {
 		return false;
+	}
 
 	// Any section on the stack is still growing
 	for (SectionStackEntry &entry : sectionStack) {
-		if (entry.section && entry.section->name == name)
+		if (entry.section && entry.section->name == name) {
 			return false;
+		}
 	}
 
 	return true;
@@ -426,12 +451,14 @@ void sect_NewSection(
     SectionModifier mod
 ) {
 	for (SectionStackEntry &entry : sectionStack) {
-		if (entry.section && entry.section->name == name)
+		if (entry.section && entry.section->name == name) {
 			fatalerror("Section '%s' is already on the stack\n", name.c_str());
+		}
 	}
 
-	if (currentLoadSection)
+	if (currentLoadSection) {
 		sect_EndLoadSection("SECTION");
+	}
 
 	Section *sect = getSection(name, type, org, attrs, mod);
 
@@ -454,16 +481,18 @@ void sect_SetLoadSection(
 	// Therefore, any interactions are NOT TESTED, so lift either of those restrictions at
 	// your own peril! ^^
 
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
 	if (sect_HasData(type)) {
 		error("`LOAD` blocks cannot create a ROM section\n");
 		return;
 	}
 
-	if (currentLoadSection)
+	if (currentLoadSection) {
 		sect_EndLoadSection("LOAD");
+	}
 
 	Section *sect = getSection(name, type, org, attrs, mod);
 
@@ -475,12 +504,11 @@ void sect_SetLoadSection(
 }
 
 void sect_EndLoadSection(char const *cause) {
-	if (cause)
+	if (cause) {
 		warning(
-		    WARNING_UNTERMINATED_LOAD,
-		    "`LOAD` block without `ENDL` terminated by `%s`\n",
-		    cause
+		    WARNING_UNTERMINATED_LOAD, "`LOAD` block without `ENDL` terminated by `%s`\n", cause
 		);
+	}
 
 	if (!currentLoadSection) {
 		error("Found `ENDL` outside of a `LOAD` block\n");
@@ -495,8 +523,9 @@ void sect_EndLoadSection(char const *cause) {
 }
 
 void sect_CheckLoadClosed() {
-	if (currentLoadSection)
+	if (currentLoadSection) {
 		warning(WARNING_UNTERMINATED_LOAD, "`LOAD` block without `ENDL` terminated by EOF\n");
+	}
 }
 
 Section *sect_GetSymbolSection() {
@@ -515,16 +544,18 @@ uint32_t sect_GetOutputOffset() {
 // Returns how many bytes need outputting for the specified alignment and offset to succeed
 uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset) {
 	Section *sect = sect_GetSymbolSection();
-	if (!sect)
+	if (!sect) {
 		return 0;
+	}
 
 	bool isFixed = sect->org != UINT32_MAX;
 
 	// If the section is not aligned, no bytes are needed
 	// (fixed sections count as being maximally aligned for this purpose)
 	uint8_t curAlignment = isFixed ? 16 : sect->align;
-	if (curAlignment == 0)
+	if (curAlignment == 0) {
 		return 0;
+	}
 
 	// We need `(pcValue + curOffset + return value) % (1 << alignment) == offset`
 	uint16_t pcValue = isFixed ? sect->org : sect->alignOfs;
@@ -533,18 +564,20 @@ uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset) {
 }
 
 void sect_AlignPC(uint8_t alignment, uint16_t offset) {
-	if (!requireSection())
+	if (!requireSection()) {
 		return;
+	}
 
 	Section *sect = sect_GetSymbolSection();
 	uint32_t alignSize = 1 << alignment; // Size of an aligned "block"
 
 	if (sect->org != UINT32_MAX) {
-		if ((sect->org + curOffset - offset) % alignSize)
+		if ((sect->org + curOffset - offset) % alignSize) {
 			error(
 			    "Section's fixed address fails required alignment (PC = $%04" PRIx32 ")\n",
 			    sect->org + curOffset
 			);
+		}
 	} else if (sect->align != 0
 	           && (((sect->alignOfs + curOffset) % (1u << sect->align)) - offset) % alignSize) {
 		error(
@@ -568,18 +601,22 @@ void sect_AlignPC(uint8_t alignment, uint16_t offset) {
 }
 
 static void growSection(uint32_t growth) {
-	if (growth > 0 && curOffset > UINT32_MAX - growth)
+	if (growth > 0 && curOffset > UINT32_MAX - growth) {
 		fatalerror("Section size would overflow internal counter\n");
+	}
 	curOffset += growth;
-	if (uint32_t outOffset = sect_GetOutputOffset(); outOffset > currentSection->size)
+	if (uint32_t outOffset = sect_GetOutputOffset(); outOffset > currentSection->size) {
 		currentSection->size = outOffset;
-	if (currentLoadSection && curOffset > currentLoadSection->size)
+	}
+	if (currentLoadSection && curOffset > currentLoadSection->size) {
 		currentLoadSection->size = curOffset;
+	}
 }
 
 static void writeByte(uint8_t byte) {
-	if (uint32_t index = sect_GetOutputOffset(); index < currentSection->data.size())
+	if (uint32_t index = sect_GetOutputOffset(); index < currentSection->data.size()) {
 		currentSection->data[index] = byte;
+	}
 	growSection(1);
 }
 
@@ -621,8 +658,9 @@ static void endUnionMember() {
 	UnionStackEntry &member = currentUnionStack.top();
 	uint32_t memberSize = curOffset - member.start;
 
-	if (memberSize > member.size)
+	if (memberSize > member.size) {
 		member.size = memberSize;
+	}
 	curOffset = member.start;
 }
 
@@ -645,64 +683,75 @@ void sect_EndUnion() {
 }
 
 void sect_CheckUnionClosed() {
-	if (!currentUnionStack.empty())
+	if (!currentUnionStack.empty()) {
 		error("Unterminated UNION construct\n");
+	}
 }
 
 // Output a constant byte
 void sect_ConstByte(uint8_t byte) {
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
 	writeByte(byte);
 }
 
 // Output a string's character units as bytes
 void sect_ByteString(std::vector<int32_t> const &string) {
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
 	for (int32_t unit : string) {
-		if (!checkNBit(unit, 8, "All character units"))
+		if (!checkNBit(unit, 8, "All character units")) {
 			break;
+		}
 	}
 
-	for (int32_t unit : string)
+	for (int32_t unit : string) {
 		writeByte(static_cast<uint8_t>(unit));
+	}
 }
 
 // Output a string's character units as words
 void sect_WordString(std::vector<int32_t> const &string) {
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
 	for (int32_t unit : string) {
-		if (!checkNBit(unit, 16, "All character units"))
+		if (!checkNBit(unit, 16, "All character units")) {
 			break;
+		}
 	}
 
-	for (int32_t unit : string)
+	for (int32_t unit : string) {
 		writeWord(static_cast<uint16_t>(unit));
+	}
 }
 
 // Output a string's character units as longs
 void sect_LongString(std::vector<int32_t> const &string) {
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
-	for (int32_t unit : string)
+	for (int32_t unit : string) {
 		writeLong(static_cast<uint32_t>(unit));
+	}
 }
 
 // Skip this many bytes
 void sect_Skip(uint32_t skip, bool ds) {
-	if (!requireSection())
+	if (!requireSection()) {
 		return;
+	}
 
 	if (!sect_HasData(currentSection->type)) {
 		growSection(skip);
 	} else {
-		if (!ds)
+		if (!ds) {
 			warning(
 			    WARNING_EMPTY_DATA_DIRECTIVE,
 			    "%s directive without data in ROM\n",
@@ -710,16 +759,19 @@ void sect_Skip(uint32_t skip, bool ds) {
 			    : (skip == 2) ? "DW"
 			                  : "DB"
 			);
+		}
 		// We know we're in a code SECTION
-		while (skip--)
+		while (skip--) {
 			writeByte(fillByte);
+		}
 	}
 }
 
 // Output a byte that can be relocatable or constant
 void sect_RelByte(Expression &expr, uint32_t pcShift) {
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
 	if (!expr.isKnown()) {
 		createPatch(PATCHTYPE_BYTE, expr, pcShift);
@@ -731,8 +783,9 @@ void sect_RelByte(Expression &expr, uint32_t pcShift) {
 
 // Output several bytes that can be relocatable or constant
 void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs) {
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
 	for (uint32_t i = 0; i < n; i++) {
 		Expression &expr = exprs[i % exprs.size()];
@@ -748,8 +801,9 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs) {
 
 // Output a word that can be relocatable or constant
 void sect_RelWord(Expression &expr, uint32_t pcShift) {
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
 	if (!expr.isKnown()) {
 		createPatch(PATCHTYPE_WORD, expr, pcShift);
@@ -761,8 +815,9 @@ void sect_RelWord(Expression &expr, uint32_t pcShift) {
 
 // Output a long that can be relocatable or constant
 void sect_RelLong(Expression &expr, uint32_t pcShift) {
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
 	if (!expr.isKnown()) {
 		createPatch(PATCHTYPE_LONG, expr, pcShift);
@@ -774,8 +829,9 @@ void sect_RelLong(Expression &expr, uint32_t pcShift) {
 
 // Output a PC-relative byte that can be relocatable or constant
 void sect_PCRelByte(Expression &expr, uint32_t pcShift) {
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
 	if (Symbol const *pc = sym_GetPC(); !expr.isDiffConstant(pc)) {
 		createPatch(PATCHTYPE_JR, expr, pcShift);
@@ -786,10 +842,11 @@ void sect_PCRelByte(Expression &expr, uint32_t pcShift) {
 		int16_t offset;
 
 		// Offset is relative to the byte *after* the operand
-		if (sym == pc)
+		if (sym == pc) {
 			offset = -2; // PC as operand to `jr` is lower than reference PC by 2
-		else
+		} else {
 			offset = sym->getValue() - (pc->getValue() + 1);
+		}
 
 		if (offset < -128 || offset > 127) {
 			error(
@@ -810,16 +867,19 @@ void sect_BinaryFile(std::string const &name, int32_t startPos) {
 		error("Start position cannot be negative (%" PRId32 ")\n", startPos);
 		startPos = 0;
 	}
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
+	}
 
 	FILE *file = nullptr;
-	if (std::optional<std::string> fullPath = fstk_FindFile(name); fullPath)
+	if (std::optional<std::string> fullPath = fstk_FindFile(name); fullPath) {
 		file = fopen(fullPath->c_str(), "rb");
+	}
 	if (!file) {
 		if (generatedMissingIncludes) {
-			if (verbose)
+			if (verbose) {
 				printf("Aborting (-MG) on INCBIN file '%s' (%s)\n", name.c_str(), strerror(errno));
+			}
 			failedOnMissingInclude = true;
 		} else {
 			error("Error opening INCBIN file '%s': %s\n", name.c_str(), strerror(errno));
@@ -836,10 +896,11 @@ void sect_BinaryFile(std::string const &name, int32_t startPos) {
 		// The file is seekable; skip to the specified start position
 		fseek(file, startPos, SEEK_SET);
 	} else {
-		if (errno != ESPIPE)
+		if (errno != ESPIPE) {
 			error(
 			    "Error determining size of INCBIN file '%s': %s\n", name.c_str(), strerror(errno)
 			);
+		}
 		// The file isn't seekable, so we'll just skip bytes one at a time
 		while (startPos--) {
 			if (fgetc(file) == EOF) {
@@ -851,11 +912,13 @@ void sect_BinaryFile(std::string const &name, int32_t startPos) {
 		}
 	}
 
-	for (int byte; (byte = fgetc(file)) != EOF;)
+	for (int byte; (byte = fgetc(file)) != EOF;) {
 		writeByte(byte);
+	}
 
-	if (ferror(file))
+	if (ferror(file)) {
 		error("Error reading INCBIN file '%s': %s\n", name.c_str(), strerror(errno));
+	}
 }
 
 // Output a slice of a binary file
@@ -868,18 +931,22 @@ void sect_BinaryFileSlice(std::string const &name, int32_t startPos, int32_t len
 		error("Number of bytes to read cannot be negative (%" PRId32 ")\n", length);
 		length = 0;
 	}
-	if (!requireCodeSection())
+	if (!requireCodeSection()) {
 		return;
-	if (length == 0) // Don't even bother with 0-byte slices
+	}
+	if (length == 0) { // Don't even bother with 0-byte slices
 		return;
+	}
 
 	FILE *file = nullptr;
-	if (std::optional<std::string> fullPath = fstk_FindFile(name); fullPath)
+	if (std::optional<std::string> fullPath = fstk_FindFile(name); fullPath) {
 		file = fopen(fullPath->c_str(), "rb");
+	}
 	if (!file) {
 		if (generatedMissingIncludes) {
-			if (verbose)
+			if (verbose) {
 				printf("Aborting (-MG) on INCBIN file '%s' (%s)\n", name.c_str(), strerror(errno));
+			}
 			failedOnMissingInclude = true;
 		} else {
 			error("Error opening INCBIN file '%s': %s\n", name.c_str(), strerror(errno));
@@ -906,10 +973,11 @@ void sect_BinaryFileSlice(std::string const &name, int32_t startPos, int32_t len
 		// The file is seekable; skip to the specified start position
 		fseek(file, startPos, SEEK_SET);
 	} else {
-		if (errno != ESPIPE)
+		if (errno != ESPIPE) {
 			error(
 			    "Error determining size of INCBIN file '%s': %s\n", name.c_str(), strerror(errno)
 			);
+		}
 		// The file isn't seekable, so we'll just skip bytes one at a time
 		while (startPos--) {
 			if (fgetc(file) == EOF) {
@@ -955,11 +1023,13 @@ void sect_PushSection() {
 }
 
 void sect_PopSection() {
-	if (sectionStack.empty())
+	if (sectionStack.empty()) {
 		fatalerror("No entries in the section stack\n");
+	}
 
-	if (currentLoadSection)
+	if (currentLoadSection) {
 		sect_EndLoadSection("POPS");
+	}
 
 	SectionStackEntry entry = sectionStack.front();
 	sectionStack.pop_front();
@@ -980,14 +1050,17 @@ void sect_CheckStack() {
 }
 
 void sect_EndSection() {
-	if (!currentSection)
+	if (!currentSection) {
 		fatalerror("Cannot end the section outside of a SECTION\n");
+	}
 
-	if (!currentUnionStack.empty())
+	if (!currentUnionStack.empty()) {
 		fatalerror("Cannot end the section within a UNION\n");
+	}
 
-	if (currentLoadSection)
+	if (currentLoadSection) {
 		sect_EndLoadSection("ENDSECTION");
+	}
 
 	// Reset the section scope
 	currentSection = nullptr;
diff --git a/src/asm/symbol.cpp b/src/asm/symbol.cpp
index 1ae86aba5..0d81f3312 100644
--- a/src/asm/symbol.cpp
+++ b/src/asm/symbol.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/symbol.hpp"
 
@@ -40,8 +40,9 @@ bool sym_IsPC(Symbol const *sym) {
 }
 
 void sym_ForEach(void (*callback)(Symbol &)) {
-	for (auto &it : symbols)
+	for (auto &it : symbols) {
 		callback(it.second);
+	}
 }
 
 static int32_t NARGCallback() {
@@ -92,7 +93,7 @@ int32_t Symbol::getOutputValue() const {
 }
 
 ContentSpan const &Symbol::getMacro() const {
-	assume((std::holds_alternative<ContentSpan>(data)));
+	assume(std::holds_alternative<ContentSpan>(data));
 	return std::get<ContentSpan>(data);
 }
 
@@ -101,8 +102,9 @@ std::shared_ptr<std::string> Symbol::getEqus() const {
 	    std::holds_alternative<std::shared_ptr<std::string>>(data)
 	    || std::holds_alternative<std::shared_ptr<std::string> (*)()>(data)
 	);
-	if (auto *callback = std::get_if<std::shared_ptr<std::string> (*)()>(&data); callback)
+	if (auto *callback = std::get_if<std::shared_ptr<std::string> (*)()>(&data); callback) {
 		return (*callback)();
+	}
 	return std::get<std::shared_ptr<std::string>>(data);
 }
 
@@ -123,8 +125,9 @@ static void updateSymbolFilename(Symbol &sym) {
 	sym.fileLine = sym.src ? lexer_GetLineNo() : 0;
 
 	// If the old node was registered, ensure the new one is too
-	if (oldSrc && oldSrc->ID != UINT32_MAX)
+	if (oldSrc && oldSrc->ID != UINT32_MAX) {
 		out_RegisterNode(sym.src);
+	}
 }
 
 static void alreadyDefinedError(Symbol const &sym, char const *asType) {
@@ -133,8 +136,9 @@ static void alreadyDefinedError(Symbol const &sym, char const *asType) {
 		error("'%s' is reserved for a built-in symbol\n", sym.name.c_str());
 	} else {
 		error("'%s' already defined", sym.name.c_str());
-		if (asType)
+		if (asType) {
 			fprintf(stderr, " as %s", asType);
+		}
 		fputs(" at ", stderr);
 		dumpFilename(sym);
 	}
@@ -184,28 +188,34 @@ static bool isAutoScoped(std::string const &symName) {
 	size_t dotPos = symName.find('.');
 
 	// If there are no dots, it's not a local label
-	if (dotPos == std::string::npos)
+	if (dotPos == std::string::npos) {
 		return false;
+	}
 
 	// Label scopes `.` and `..` are the only nonlocal identifiers that start with a dot
-	if (dotPos == 0 && symName.find_first_not_of('.') == symName.npos)
+	if (dotPos == 0 && symName.find_first_not_of('.') == symName.npos) {
 		return false;
+	}
 
 	// Check for nothing after the dot
-	if (dotPos == symName.length() - 1)
+	if (dotPos == symName.length() - 1) {
 		fatalerror("'%s' is a nonsensical reference to an empty local label\n", symName.c_str());
+	}
 
 	// Check for more than one dot
-	if (symName.find('.', dotPos + 1) != std::string::npos)
+	if (symName.find('.', dotPos + 1) != std::string::npos) {
 		fatalerror("'%s' is a nonsensical reference to a nested local label\n", symName.c_str());
+	}
 
 	// Check for already-qualified local label
-	if (dotPos > 0)
+	if (dotPos > 0) {
 		return false;
+	}
 
 	// Check for unqualifiable local label
-	if (!globalScope)
+	if (!globalScope) {
 		fatalerror("Unqualified local label '%s' in main scope\n", symName.c_str());
+	}
 
 	return true;
 }
@@ -252,24 +262,28 @@ void sym_Purge(std::string const &symName) {
 	Symbol *sym = sym_FindScopedValidSymbol(symName);
 
 	if (!sym) {
-		if (sym_IsPurgedScoped(symName))
+		if (sym_IsPurgedScoped(symName)) {
 			error("'%s' was already purged\n", symName.c_str());
-		else
+		} else {
 			error("'%s' not defined\n", symName.c_str());
+		}
 	} else if (sym->isBuiltin) {
 		error("Built-in symbol '%s' cannot be purged\n", symName.c_str());
 	} else if (sym->ID != UINT32_MAX) {
 		error("Symbol \"%s\" is referenced and thus cannot be purged\n", symName.c_str());
 	} else {
-		if (sym->isExported)
+		if (sym->isExported) {
 			warning(WARNING_PURGE_1, "Purging an exported symbol \"%s\"\n", symName.c_str());
-		else if (sym->isLabel())
+		} else if (sym->isLabel()) {
 			warning(WARNING_PURGE_2, "Purging a label \"%s\"\n", symName.c_str());
+		}
 		// Do not keep a reference to the label after purging it
-		if (sym == globalScope)
+		if (sym == globalScope) {
 			globalScope = nullptr;
-		if (sym == localScope)
+		}
+		if (sym == localScope) {
 			localScope = nullptr;
+		}
 		purgedSymbols.emplace(sym->name);
 		symbols.erase(sym->name);
 	}
@@ -295,14 +309,16 @@ void sym_SetRSValue(int32_t value) {
 }
 
 uint32_t Symbol::getConstantValue() const {
-	if (isConstant())
+	if (isConstant()) {
 		return getValue();
+	}
 
 	if (sym_IsPC(this)) {
-		if (!getSection())
+		if (!getSection()) {
 			error("PC has no value outside of a section\n");
-		else
+		} else {
 			error("PC does not have a constant value; the current section is not fixed\n");
+		}
 	} else {
 		error("\"%s\" does not have a constant value\n", name.c_str());
 	}
@@ -310,13 +326,15 @@ uint32_t Symbol::getConstantValue() const {
 }
 
 uint32_t sym_GetConstantValue(std::string const &symName) {
-	if (Symbol const *sym = sym_FindScopedSymbol(symName); sym)
+	if (Symbol const *sym = sym_FindScopedSymbol(symName); sym) {
 		return sym->getConstantValue();
+	}
 
-	if (sym_IsPurgedScoped(symName))
+	if (sym_IsPurgedScoped(symName)) {
 		error("'%s' not defined; it was purged\n", symName.c_str());
-	else
+	} else {
 		error("'%s' not defined\n", symName.c_str());
+	}
 	return 0;
 }
 
@@ -361,8 +379,9 @@ static Symbol *createNonrelocSymbol(std::string const &symName, bool numeric) {
 Symbol *sym_AddEqu(std::string const &symName, int32_t value) {
 	Symbol *sym = createNonrelocSymbol(symName, true);
 
-	if (!sym)
+	if (!sym) {
 		return nullptr;
+	}
 
 	sym->type = SYM_EQU;
 	sym->data = value;
@@ -373,8 +392,9 @@ Symbol *sym_AddEqu(std::string const &symName, int32_t value) {
 Symbol *sym_RedefEqu(std::string const &symName, int32_t value) {
 	Symbol *sym = sym_FindExactSymbol(symName);
 
-	if (!sym)
+	if (!sym) {
 		return sym_AddEqu(symName, value);
+	}
 
 	if (sym->isDefined() && sym->type != SYM_EQU) {
 		alreadyDefinedError(*sym, "non-EQU");
@@ -394,8 +414,9 @@ Symbol *sym_RedefEqu(std::string const &symName, int32_t value) {
 Symbol *sym_AddString(std::string const &symName, std::shared_ptr<std::string> str) {
 	Symbol *sym = createNonrelocSymbol(symName, false);
 
-	if (!sym)
+	if (!sym) {
 		return nullptr;
+	}
 
 	sym->type = SYM_EQUS;
 	sym->data = str;
@@ -405,8 +426,9 @@ Symbol *sym_AddString(std::string const &symName, std::shared_ptr<std::string> s
 Symbol *sym_RedefString(std::string const &symName, std::shared_ptr<std::string> str) {
 	Symbol *sym = sym_FindExactSymbol(symName);
 
-	if (!sym)
+	if (!sym) {
 		return sym_AddString(symName, str);
+	}
 
 	if (sym->type != SYM_EQUS) {
 		if (sym->isDefined()) {
@@ -462,12 +484,14 @@ static Symbol *addLabel(std::string const &symName) {
 	sym->type = SYM_LABEL;
 	sym->data = static_cast<int32_t>(sect_GetSymbolOffset());
 	// Don't export anonymous labels
-	if (exportAll && !symName.starts_with('!'))
+	if (exportAll && !symName.starts_with('!')) {
 		sym->isExported = true;
+	}
 	sym->section = sect_GetSymbolSection();
 
-	if (sym && !sym->section)
+	if (sym && !sym->section) {
 		error("Label \"%s\" created outside of a SECTION\n", symName.c_str());
+	}
 
 	return sym;
 }
@@ -478,8 +502,9 @@ Symbol *sym_AddLocalLabel(std::string const &symName) {
 
 	Symbol *sym = addLabel(isAutoScoped(symName) ? globalScope->name + symName : symName);
 
-	if (sym)
+	if (sym) {
 		localScope = sym;
+	}
 
 	return sym;
 }
@@ -516,7 +541,7 @@ std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg) {
 	uint32_t id = 0;
 
 	if (neg) {
-		if (ofs > anonLabelID)
+		if (ofs > anonLabelID) {
 			error(
 			    "Reference to anonymous label %" PRIu32 " before, when only %" PRIu32
 			    " ha%s been created so far\n",
@@ -524,19 +549,21 @@ std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg) {
 			    anonLabelID,
 			    anonLabelID == 1 ? "s" : "ve"
 			);
-		else
+		} else {
 			id = anonLabelID - ofs;
+		}
 	} else {
 		ofs--; // We're referencing symbols that haven't been created yet...
-		if (ofs > UINT32_MAX - anonLabelID)
+		if (ofs > UINT32_MAX - anonLabelID) {
 			error(
 			    "Reference to anonymous label %" PRIu32 " after, when only %" PRIu32
 			    " may still be created\n",
 			    ofs + 1,
 			    UINT32_MAX - anonLabelID
 			);
-		else
+		} else {
 			id = anonLabelID + ofs;
+		}
 	}
 
 	std::string anon("!");
@@ -553,16 +580,18 @@ void sym_Export(std::string const &symName) {
 	Symbol *sym = sym_FindScopedSymbol(symName);
 
 	// If the symbol doesn't exist, create a ref that can be purged
-	if (!sym)
+	if (!sym) {
 		sym = sym_Ref(symName);
+	}
 	sym->isExported = true;
 }
 
 Symbol *sym_AddMacro(std::string const &symName, int32_t defLineNo, ContentSpan const &span) {
 	Symbol *sym = createNonrelocSymbol(symName, false);
 
-	if (!sym)
+	if (!sym) {
 		return nullptr;
+	}
 
 	sym->type = SYM_MACRO;
 	sym->data = span;
diff --git a/src/asm/warning.cpp b/src/asm/warning.cpp
index 2288c1067..39a670267 100644
--- a/src/asm/warning.cpp
+++ b/src/asm/warning.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "asm/warning.hpp"
 
@@ -35,13 +35,13 @@ struct WarningFlag {
 	WarningLevel level;
 };
 
-static const WarningFlag metaWarnings[] = {
+static WarningFlag const metaWarnings[] = {
     {"all",        LEVEL_ALL       },
     {"extra",      LEVEL_EXTRA     },
     {"everything", LEVEL_EVERYTHING},
 };
 
-static const WarningFlag warningFlags[NB_WARNINGS] = {
+static WarningFlag const warningFlags[NB_WARNINGS] = {
     {"assert",               LEVEL_DEFAULT   },
     {"backwards-for",        LEVEL_ALL       },
     {"builtin-args",         LEVEL_ALL       },
@@ -85,8 +85,9 @@ enum WarningBehavior { DISABLED, ENABLED, ERROR };
 
 static WarningBehavior getWarningBehavior(WarningID id) {
 	// Check if warnings are globally disabled
-	if (!warnings)
+	if (!warnings) {
 		return WarningBehavior::DISABLED;
+	}
 
 	// Get the state of this warning flag
 	WarningState const &flagState = warningStates.flagStates[id];
@@ -100,34 +101,43 @@ static WarningBehavior getWarningBehavior(WarningID id) {
 	    warningIsError ? WarningBehavior::ERROR : WarningBehavior::ENABLED;
 
 	// First, check the state of the specific warning flag
-	if (flagState.state == WARNING_DISABLED) // -Wno-<flag>
+	if (flagState.state == WARNING_DISABLED) { // -Wno-<flag>
 		return WarningBehavior::DISABLED;
-	if (flagState.error == WARNING_ENABLED) // -Werror=<flag>
+	}
+	if (flagState.error == WARNING_ENABLED) { // -Werror=<flag>
 		return WarningBehavior::ERROR;
-	if (flagState.state == WARNING_ENABLED) // -W<flag>
+	}
+	if (flagState.state == WARNING_ENABLED) { // -W<flag>
 		return enabledBehavior;
+	}
 
 	// If no flag is specified, check the state of the "meta" flags that affect this warning flag
-	if (metaState.state == WARNING_DISABLED) // -Wno-<meta>
+	if (metaState.state == WARNING_DISABLED) { // -Wno-<meta>
 		return WarningBehavior::DISABLED;
-	if (metaState.error == WARNING_ENABLED) // -Werror=<meta>
+	}
+	if (metaState.error == WARNING_ENABLED) { // -Werror=<meta>
 		return WarningBehavior::ERROR;
-	if (metaState.state == WARNING_ENABLED) // -W<meta>
+	}
+	if (metaState.state == WARNING_ENABLED) { // -W<meta>
 		return enabledBehavior;
+	}
 
 	// If no meta flag is specified, check the default state of this warning flag
-	if (warningFlags[id].level == LEVEL_DEFAULT) // enabled by default
+	if (warningFlags[id].level == LEVEL_DEFAULT) { // enabled by default
 		return enabledBehavior;
+	}
 
 	// No flag enables this warning, explicitly or implicitly
 	return WarningBehavior::DISABLED;
 }
 
 void WarningState::update(WarningState other) {
-	if (other.state != WARNING_DEFAULT)
+	if (other.state != WARNING_DEFAULT) {
 		state = other.state;
-	if (other.error != WARNING_DEFAULT)
+	}
+	if (other.error != WARNING_DEFAULT) {
 		error = other.error;
+	}
 }
 
 void processWarningFlag(char const *flag) {
@@ -184,12 +194,14 @@ void processWarningFlag(char const *flag) {
 			// The `if`'s condition above ensures that this will run at least once
 			do {
 				// If we don't have a digit, bail
-				if (*ptr < '0' || *ptr > '9')
+				if (*ptr < '0' || *ptr > '9') {
 					break;
+				}
 				// Avoid overflowing!
 				if (param > UINT8_MAX - (*ptr - '0')) {
-					if (!warned)
+					if (!warned) {
 						warnx("Invalid warning flag \"%s\": capping parameter at 255", flag);
+					}
 					warned = true; // Only warn once, cap always
 					param = 255;
 					continue;
@@ -203,8 +215,9 @@ void processWarningFlag(char const *flag) {
 			if (*ptr == '\0') {
 				rootFlag.resize(equals);
 				// `-W<flag>=0` is equivalent to `-Wno-<flag>`
-				if (param == 0)
+				if (param == 0) {
 					state.state = WARNING_DISABLED;
+				}
 			}
 		}
 	}
@@ -218,8 +231,9 @@ void processWarningFlag(char const *flag) {
 		assume(paramWarning.defaultLevel <= maxParam);
 
 		if (rootFlag == warningFlags[baseID].name) { // Match!
-			if (rootFlag == "numeric-string")
+			if (rootFlag == "numeric-string") {
 				warning(WARNING_OBSOLETE, "Warning flag \"numeric-string\" is deprecated\n");
+			}
 
 			// If making the warning an error but param is 0, set to the maximum
 			// This accommodates `-Werror=<flag>`, but also `-Werror=<flag>=0`, which is
@@ -229,7 +243,7 @@ void processWarningFlag(char const *flag) {
 			if (param == 0) {
 				param = paramWarning.defaultLevel;
 			} else if (param > maxParam) {
-				if (param != 255) // Don't warn if already capped
+				if (param != 255) { // Don't warn if already capped
 					warnx(
 					    "Invalid parameter %" PRIu8
 					    " for warning flag \"%s\"; capping at maximum %" PRIu8,
@@ -237,16 +251,18 @@ void processWarningFlag(char const *flag) {
 					    rootFlag.c_str(),
 					    maxParam
 					);
+				}
 				param = maxParam;
 			}
 
 			// Set the first <param> to enabled/error, and disable the rest
 			for (uint8_t ofs = 0; ofs < maxParam; ofs++) {
 				WarningState &warning = warningStates.flagStates[baseID + ofs];
-				if (ofs < param)
+				if (ofs < param) {
 					warning.update(state);
-				else
+				} else {
 					warning.state = WARNING_DISABLED;
+				}
 			}
 			return;
 		}
@@ -259,8 +275,9 @@ void processWarningFlag(char const *flag) {
 			if (rootFlag == metaWarning.name) {
 				// Set each of the warning flags that meets this level
 				for (WarningID id : EnumSeq(NB_WARNINGS)) {
-					if (metaWarning.level >= warningFlags[id].level)
+					if (metaWarning.level >= warningFlags[id].level) {
 						warningStates.metaStates[id].update(state);
+					}
 				}
 				return;
 			}
@@ -299,16 +316,18 @@ void error(char const *fmt, ...) {
 
 	// This intentionally makes 0 act as "unlimited" (or at least "limited to sizeof(unsigned)")
 	nbErrors++;
-	if (nbErrors == maxErrors)
+	if (nbErrors == maxErrors) {
 		errx(
 		    "The maximum of %u error%s was reached (configure with \"-X/--max-errors\"); assembly "
 		    "aborted!",
 		    maxErrors,
 		    maxErrors == 1 ? "" : "s"
 		);
+	}
 }
 
-[[noreturn]] void fatalerror(char const *fmt, ...) {
+[[noreturn]]
+void fatalerror(char const *fmt, ...) {
 	va_list args;
 
 	va_start(args, fmt);
diff --git a/src/error.cpp b/src/error.cpp
index 1550d3c17..99add990a 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "error.hpp"
 
@@ -22,7 +22,8 @@ static void vwarnx(char const *fmt, va_list ap) {
 	putc('\n', stderr);
 }
 
-[[noreturn]] static void verr(char const *fmt, va_list ap) {
+[[noreturn]]
+static void verr(char const *fmt, va_list ap) {
 	char const *error = strerror(errno);
 
 	fprintf(stderr, "error: ");
@@ -32,7 +33,8 @@ static void vwarnx(char const *fmt, va_list ap) {
 	exit(1);
 }
 
-[[noreturn]] static void verrx(char const *fmt, va_list ap) {
+[[noreturn]]
+static void verrx(char const *fmt, va_list ap) {
 	fprintf(stderr, "error: ");
 	vfprintf(stderr, fmt, ap);
 	putc('\n', stderr);
@@ -56,14 +58,16 @@ void warnx(char const *fmt, ...) {
 	va_end(ap);
 }
 
-[[noreturn]] void err(char const *fmt, ...) {
+[[noreturn]]
+void err(char const *fmt, ...) {
 	va_list ap;
 
 	va_start(ap, fmt);
 	verr(fmt, ap);
 }
 
-[[noreturn]] void errx(char const *fmt, ...) {
+[[noreturn]]
+void errx(char const *fmt, ...) {
 	va_list ap;
 
 	va_start(ap, fmt);
diff --git a/src/extern/getopt.cpp b/src/extern/getopt.cpp
index db798d51e..d8bf383b6 100644
--- a/src/extern/getopt.cpp
+++ b/src/extern/getopt.cpp
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
-/* This implementation was taken from musl and modified for RGBDS */
+// This implementation was taken from musl and modified for RGBDS
 
 #include "extern/getopt.hpp"
 
@@ -19,8 +19,9 @@ static int musl_optpos;
 static void musl_getopt_msg(char const *a, char const *b, char const *c, size_t l) {
 	FILE *f = stderr;
 
-	if (fputs(a, f) >= 0 && fwrite(b, strlen(b), 1, f) && fwrite(c, 1, l, f) == l)
+	if (fputs(a, f) >= 0 && fwrite(b, strlen(b), 1, f) && fwrite(c, 1, l, f) == l) {
 		putc('\n', f);
+	}
 }
 
 static int getopt(int argc, char *argv[], char const *optstring) {
@@ -35,8 +36,9 @@ static int getopt(int argc, char *argv[], char const *optstring) {
 		musl_optind = 1;
 	}
 
-	if (musl_optind >= argc || !argv[musl_optind])
+	if (musl_optind >= argc || !argv[musl_optind]) {
 		return -1;
+	}
 
 	if (argv[musl_optind][0] != '-') {
 		if (optstring[0] == '-') {
@@ -46,18 +48,21 @@ static int getopt(int argc, char *argv[], char const *optstring) {
 		return -1;
 	}
 
-	if (!argv[musl_optind][1])
+	if (!argv[musl_optind][1]) {
 		return -1;
+	}
 
-	if (argv[musl_optind][1] == '-' && !argv[musl_optind][2])
+	if (argv[musl_optind][1] == '-' && !argv[musl_optind][2]) {
 		return musl_optind++, -1;
+	}
 
-	if (!musl_optpos)
+	if (!musl_optpos) {
 		musl_optpos++;
+	}
 	k = mbtowc(&c, argv[musl_optind] + musl_optpos, MB_LEN_MAX);
 	if (k < 0) {
 		k = 1;
-		c = 0xFFFD; /* replacement char */
+		c = 0xFFFD; // replacement char
 	}
 	optchar = argv[musl_optind] + musl_optpos;
 	musl_optpos += k;
@@ -67,23 +72,26 @@ static int getopt(int argc, char *argv[], char const *optstring) {
 		musl_optpos = 0;
 	}
 
-	if (optstring[0] == '-' || optstring[0] == '+')
+	if (optstring[0] == '-' || optstring[0] == '+') {
 		optstring++;
+	}
 
 	i = 0;
 	d = 0;
 	do {
 		l = mbtowc(&d, optstring + i, MB_LEN_MAX);
-		if (l > 0)
+		if (l > 0) {
 			i += l;
-		else
+		} else {
 			i++;
+		}
 	} while (l && d != c);
 
 	if (d != c || c == ':') {
 		musl_optopt = c;
-		if (optstring[0] != ':' && musl_opterr)
+		if (optstring[0] != ':' && musl_opterr) {
 			musl_getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
+		}
 		return '?';
 	}
 	if (optstring[i] == ':') {
@@ -94,10 +102,12 @@ static int getopt(int argc, char *argv[], char const *optstring) {
 		}
 		if (musl_optind > argc) {
 			musl_optopt = c;
-			if (optstring[0] == ':')
+			if (optstring[0] == ':') {
 				return ':';
-			if (musl_opterr)
+			}
+			if (musl_opterr) {
 				musl_getopt_msg(argv[0], ": option requires an argument: ", optchar, k);
+			}
 			return '?';
 		}
 	}
@@ -108,8 +118,9 @@ static void permute(char **argv, int dest, int src) {
 	char *tmp = argv[src];
 	int i;
 
-	for (i = src; i > dest; i--)
+	for (i = src; i > dest; i--) {
 		argv[i] = argv[i - 1];
+	}
 	argv[dest] = tmp;
 }
 
@@ -128,17 +139,20 @@ static int musl_getopt_long(
 		musl_optind = 1;
 	}
 
-	if (musl_optind >= argc || !argv[musl_optind])
+	if (musl_optind >= argc || !argv[musl_optind]) {
 		return -1;
+	}
 
 	skipped = musl_optind;
 	if (optstring[0] != '+' && optstring[0] != '-') {
 		int i;
 		for (i = musl_optind;; i++) {
-			if (i >= argc || !argv[i])
+			if (i >= argc || !argv[i]) {
 				return -1;
-			if (argv[i][0] == '-' && argv[i][1])
+			}
+			if (argv[i][0] == '-' && argv[i][1]) {
 				break;
+			}
 		}
 		musl_optind = i;
 	}
@@ -147,8 +161,9 @@ static int musl_getopt_long(
 	if (resumed > skipped) {
 		int i, cnt = musl_optind - resumed;
 
-		for (i = 0; i < cnt; i++)
+		for (i = 0; i < cnt; i++) {
 			permute(argv, skipped, musl_optind - 1);
+		}
 		musl_optind = skipped + cnt;
 	}
 	return ret;
@@ -169,14 +184,16 @@ static int musl_getopt_long_core(
 			char const *name = longopts[i].name;
 
 			opt = start;
-			if (*opt == '-')
+			if (*opt == '-') {
 				opt++;
+			}
 			while (*opt && *opt != '=' && *opt == *name) {
 				name++;
 				opt++;
 			}
-			if (*opt && *opt != '=')
+			if (*opt && *opt != '=') {
 				continue;
+			}
 			arg = opt;
 			match = i;
 			if (!*name) {
@@ -191,8 +208,9 @@ static int musl_getopt_long_core(
 			for (i = 0; optstring[i]; i++) {
 				int j = 0;
 
-				while (j < l && start[j] == optstring[i + j])
+				while (j < l && start[j] == optstring[i + j]) {
 					j++;
+				}
 				if (j == l) {
 					cnt++;
 					break;
@@ -206,8 +224,9 @@ static int musl_getopt_long_core(
 			if (*opt == '=') {
 				if (!longopts[i].has_arg) {
 					musl_optopt = longopts[i].val;
-					if (colon || !musl_opterr)
+					if (colon || !musl_opterr) {
 						return '?';
+					}
 					musl_getopt_msg(
 					    argv[0],
 					    ": option does not take an argument: ",
@@ -221,10 +240,12 @@ static int musl_getopt_long_core(
 				musl_optarg = argv[musl_optind];
 				if (!musl_optarg) {
 					musl_optopt = longopts[i].val;
-					if (colon)
+					if (colon) {
 						return ':';
-					if (!musl_opterr)
+					}
+					if (!musl_opterr) {
 						return '?';
+					}
 					musl_getopt_msg(
 					    argv[0],
 					    ": option requires an argument: ",
@@ -235,8 +256,9 @@ static int musl_getopt_long_core(
 				}
 				musl_optind++;
 			}
-			if (idx)
+			if (idx) {
 				*idx = i;
+			}
 			if (longopts[i].flag) {
 				*longopts[i].flag = longopts[i].val;
 				return 0;
@@ -245,13 +267,14 @@ static int musl_getopt_long_core(
 		}
 		if (argv[musl_optind][1] == '-') {
 			musl_optopt = 0;
-			if (!colon && musl_opterr)
+			if (!colon && musl_opterr) {
 				musl_getopt_msg(
 				    argv[0],
 				    cnt ? ": option is ambiguous: " : ": unrecognized option: ",
 				    argv[musl_optind] + 2,
 				    strlen(argv[musl_optind] + 2)
 				);
+			}
 			musl_optind++;
 			return '?';
 		}
diff --git a/src/extern/utf8decoder.cpp b/src/extern/utf8decoder.cpp
index c20511c59..b6b45f6b4 100644
--- a/src/extern/utf8decoder.cpp
+++ b/src/extern/utf8decoder.cpp
@@ -1,35 +1,35 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
-/* UTF-8 decoder: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ */
+// UTF-8 decoder: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
 
 #include "extern/utf8decoder.hpp"
 
 static uint8_t const utf8d[] = {
-    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00..0f */
-    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10..1f */
-    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20..2f */
-    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 30..3f */
-    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40..4f */
-    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50..5f */
-    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60..6f */
-    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70..7f */
-    1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80..8f */
-    9,  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, /* 90..9f */
-    7,  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* a0..af */
-    7,  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* b0..bf */
-    8,  8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* c0..cf */
-    2,  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* d0..df */
-    10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, /* e0..ef */
-    11, 6, 6, 6, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* f0..ff */
-    0,  1, 2, 3, 5, 8, 7, 1, 1, 1, 4, 6, 1, 1, 1, 1, /* s0 */
-    1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* s1 */
-    1,  0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, /* s1 */
-    1,  2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, /* s3 */
-    1,  1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, /* s4 */
-    1,  2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, /* s5 */
-    1,  1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, /* s6 */
-    1,  3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, /* s7 */
-    1,  3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* s8 */
+    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..0f
+    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10..1f
+    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..2f
+    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30..3f
+    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..4f
+    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 50..5f
+    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..6f
+    0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 70..7f
+    1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80..8f
+    9,  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 90..9f
+    7,  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..af
+    7,  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // b0..bf
+    8,  8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..cf
+    2,  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // d0..df
+    10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, // e0..ef
+    11, 6, 6, 6, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // f0..ff
+    0,  1, 2, 3, 5, 8, 7, 1, 1, 1, 4, 6, 1, 1, 1, 1, // s0
+    1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s1
+    1,  0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1
+    1,  2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, // s3
+    1,  1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s4
+    1,  2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, // s5
+    1,  1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s6
+    1,  3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s7
+    1,  3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s8
 };
 
 uint32_t decode(uint32_t *state, uint32_t *codep, uint8_t byte) {
diff --git a/src/fix/main.cpp b/src/fix/main.cpp
index 7849672a4..ccdcaef52 100644
--- a/src/fix/main.cpp
+++ b/src/fix/main.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -25,16 +25,13 @@ static constexpr off_t BANK_SIZE = 0x4000;
 // Short options
 static char const *optstring = "Ccf:hi:jk:L:l:m:n:Op:r:st:Vv";
 
-/*
- * Equivalent long options
- * Please keep in the same order as short opts
- *
- * Also, make sure long opts don't create ambiguity:
- * A long opt's name should start with the same letter as its short opt,
- * except if it doesn't create any ambiguity (`verbose` versus `version`).
- * This is because long opt matching, even to a single char, is prioritized
- * over short opt matching
- */
+// Equivalent long options
+// Please keep in the same order as short opts.
+// Also, make sure long opts don't create ambiguity:
+// A long opt's name should start with the same letter as its short opt,
+// except if it doesn't create any ambiguity (`verbose` versus `version`).
+// This is because long opt matching, even to a single char, is prioritized
+// over short opt matching.
 static option const longopts[] = {
     {"color-only",       no_argument,       nullptr, 'C'},
     {"color-compatible", no_argument,       nullptr, 'c'},
@@ -78,15 +75,17 @@ static void printUsage() {
 
 static uint8_t nbErrors;
 
-[[gnu::format(printf, 1, 2)]] static void report(char const *fmt, ...) {
+[[gnu::format(printf, 1, 2)]]
+static void report(char const *fmt, ...) {
 	va_list ap;
 
 	va_start(ap, fmt);
 	vfprintf(stderr, fmt, ap);
 	va_end(ap);
 
-	if (nbErrors != UINT8_MAX)
+	if (nbErrors != UINT8_MAX) {
 		nbErrors++;
+	}
 }
 
 enum MbcType {
@@ -186,23 +185,24 @@ static void printAcceptedMBCNames() {
 
 static uint8_t tpp1Rev[2];
 
-/*
- * @return False on failure
- */
+// @return False on failure
 static bool readMBCSlice(char const *&name, char const *expected) {
 	while (*expected) {
 		char c = *name++;
 
-		if (c == '\0') // Name too short
+		if (c == '\0') { // Name too short
 			return false;
+		}
 
-		if (c >= 'a' && c <= 'z') // Perform the comparison case-insensitive
+		if (c >= 'a' && c <= 'z') { // Perform the comparison case-insensitive
 			c = c - 'a' + 'A';
-		else if (c == '_') // Treat underscores as spaces
+		} else if (c == '_') { // Treat underscores as spaces
 			c = ' ';
+		}
 
-		if (c != *expected++)
+		if (c != *expected++) {
 			return false;
+		}
 	}
 	return true;
 }
@@ -225,10 +225,12 @@ static MbcType parseMBC(char const *name) {
 		char *endptr;
 		unsigned long mbc = strtoul(name, &endptr, base);
 
-		if (*endptr)
+		if (*endptr) {
 			return MBC_BAD;
-		if (mbc > 0xFF)
+		}
+		if (mbc > 0xFF) {
 			return MBC_BAD_RANGE;
+		}
 		return static_cast<MbcType>(mbc);
 
 	} else {
@@ -237,13 +239,15 @@ static MbcType parseMBC(char const *name) {
 		char const *ptr = name;
 
 		// Trim off leading whitespace
-		while (*ptr == ' ' || *ptr == '\t')
+		while (*ptr == ' ' || *ptr == '\t') {
 			ptr++;
+		}
 
 #define tryReadSlice(expected) \
 	do { \
-		if (!readMBCSlice(ptr, expected)) \
+		if (!readMBCSlice(ptr, expected)) { \
 			return MBC_BAD; \
+		} \
 	} while (0)
 
 		switch (*ptr++) {
@@ -251,8 +255,9 @@ static MbcType parseMBC(char const *name) {
 		case 'r':
 			tryReadSlice("OM");
 			// Handle optional " ONLY"
-			while (*ptr == ' ' || *ptr == '\t' || *ptr == '_')
+			while (*ptr == ' ' || *ptr == '\t' || *ptr == '_') {
 				ptr++;
+			}
 			if (*ptr == 'O' || *ptr == 'o') {
 				ptr++;
 				tryReadSlice("NLY");
@@ -327,8 +332,9 @@ static MbcType parseMBC(char const *name) {
 			case 'P': {
 				tryReadSlice("P1");
 				// Parse version
-				while (*ptr == ' ' || *ptr == '_')
+				while (*ptr == ' ' || *ptr == '_') {
 					ptr++;
+				}
 				// Major
 				char *endptr;
 				unsigned long val = strtoul(ptr, &endptr, 10);
@@ -385,27 +391,33 @@ static MbcType parseMBC(char const *name) {
 
 		// Read "additional features"
 		uint8_t features = 0;
+		// clang-format off: vertically align values
 		static constexpr uint8_t RAM         = 1 << 7;
 		static constexpr uint8_t BATTERY     = 1 << 6;
 		static constexpr uint8_t TIMER       = 1 << 5;
 		static constexpr uint8_t RUMBLE      = 1 << 4;
 		static constexpr uint8_t SENSOR      = 1 << 3;
 		static constexpr uint8_t MULTIRUMBLE = 1 << 2;
+		// clang-format on
 
 		for (;;) {
 			// Trim off trailing whitespace
-			while (*ptr == ' ' || *ptr == '\t' || *ptr == '_')
+			while (*ptr == ' ' || *ptr == '\t' || *ptr == '_') {
 				ptr++;
+			}
 
 			// If done, start processing "features"
-			if (!*ptr)
+			if (!*ptr) {
 				break;
+			}
 			// We expect a '+' at this point
-			if (*ptr++ != '+')
+			if (*ptr++ != '+') {
 				return MBC_BAD;
+			}
 			// Trim off leading whitespace
-			while (*ptr == ' ' || *ptr == '\t' || *ptr == '_')
+			while (*ptr == ' ' || *ptr == '\t' || *ptr == '_') {
 				ptr++;
+			}
 
 			switch (*ptr++) {
 			case 'B': // BATTERY
@@ -430,8 +442,9 @@ static MbcType parseMBC(char const *name) {
 					break;
 				case 'A':
 				case 'a':
-					if (*ptr != 'M' && *ptr != 'm')
+					if (*ptr != 'M' && *ptr != 'm') {
 						return MBC_BAD;
+					}
 					ptr++;
 					features |= RAM;
 					break;
@@ -460,8 +473,9 @@ static MbcType parseMBC(char const *name) {
 
 		switch (mbc) {
 		case ROM:
-			if (!features)
+			if (!features) {
 				break;
+			}
 			mbc = ROM_RAM - 1;
 			static_assert(ROM_RAM + 1 == ROM_RAM_BATTERY, "Enum sanity check failed!");
 			static_assert(MBC1 + 1 == MBC1_RAM, "Enum sanity check failed!");
@@ -471,26 +485,29 @@ static MbcType parseMBC(char const *name) {
 			[[fallthrough]];
 		case MBC1:
 		case MMM01:
-			if (features == RAM)
+			if (features == RAM) {
 				mbc++;
-			else if (features == (RAM | BATTERY))
+			} else if (features == (RAM | BATTERY)) {
 				mbc += 2;
-			else if (features)
+			} else if (features) {
 				return MBC_WRONG_FEATURES;
+			}
 			break;
 
 		case MBC2:
-			if (features == BATTERY)
+			if (features == BATTERY) {
 				mbc = MBC2_BATTERY;
-			else if (features)
+			} else if (features) {
 				return MBC_WRONG_FEATURES;
+			}
 			break;
 
 		case MBC3:
 			// Handle timer, which also requires battery
 			if (features & TIMER) {
-				if (!(features & BATTERY))
+				if (!(features & BATTERY)) {
 					fprintf(stderr, "warning: MBC3+TIMER implies BATTERY\n");
+				}
 				features &= ~(TIMER | BATTERY); // Reset those bits
 				mbc = MBC3_TIMER_BATTERY;
 				// RAM is handled below
@@ -500,12 +517,13 @@ static MbcType parseMBC(char const *name) {
 			static_assert(
 			    MBC3_TIMER_BATTERY + 1 == MBC3_TIMER_RAM_BATTERY, "Enum sanity check failed!"
 			);
-			if (features == RAM)
+			if (features == RAM) {
 				mbc++;
-			else if (features == (RAM | BATTERY))
+			} else if (features == (RAM | BATTERY)) {
 				mbc += 2;
-			else if (features)
+			} else if (features) {
 				return MBC_WRONG_FEATURES;
+			}
 			break;
 
 		case MBC5:
@@ -517,12 +535,13 @@ static MbcType parseMBC(char const *name) {
 			static_assert(MBC5 + 2 == MBC5_RAM_BATTERY, "Enum sanity check failed!");
 			static_assert(MBC5_RUMBLE + 1 == MBC5_RUMBLE_RAM, "Enum sanity check failed!");
 			static_assert(MBC5_RUMBLE + 2 == MBC5_RUMBLE_RAM_BATTERY, "Enum sanity check failed!");
-			if (features == RAM)
+			if (features == RAM) {
 				mbc++;
-			else if (features == (RAM | BATTERY))
+			} else if (features == (RAM | BATTERY)) {
 				mbc += 2;
-			else if (features)
+			} else if (features) {
 				return MBC_WRONG_FEATURES;
+			}
 			break;
 
 		case MBC6:
@@ -530,45 +549,56 @@ static MbcType parseMBC(char const *name) {
 		case BANDAI_TAMA5:
 		case HUC3:
 			// No extra features accepted
-			if (features)
+			if (features) {
 				return MBC_WRONG_FEATURES;
+			}
 			break;
 
 		case MBC7_SENSOR_RUMBLE_RAM_BATTERY:
-			if (features != (SENSOR | RUMBLE | RAM | BATTERY))
+			if (features != (SENSOR | RUMBLE | RAM | BATTERY)) {
 				return MBC_WRONG_FEATURES;
+			}
 			break;
 
 		case HUC1_RAM_BATTERY:
-			if (features != (RAM | BATTERY)) // HuC1 expects RAM+BATTERY
+			if (features != (RAM | BATTERY)) { // HuC1 expects RAM+BATTERY
 				return MBC_WRONG_FEATURES;
+			}
 			break;
 
 		case TPP1:
-			if (features & RAM)
+			if (features & RAM) {
 				fprintf(
 				    stderr, "warning: TPP1 requests RAM implicitly if given a non-zero RAM size"
 				);
-			if (features & BATTERY)
+			}
+			if (features & BATTERY) {
 				mbc |= 0x08;
-			if (features & TIMER)
+			}
+			if (features & TIMER) {
 				mbc |= 0x04;
-			if (features & MULTIRUMBLE)
+			}
+			if (features & MULTIRUMBLE) {
 				mbc |= 0x03; // Also set the rumble flag
-			if (features & RUMBLE)
+			}
+			if (features & RUMBLE) {
 				mbc |= 0x01;
-			if (features & SENSOR)
+			}
+			if (features & SENSOR) {
 				return MBC_WRONG_FEATURES;
+			}
 			break;
 		}
 
 		// Trim off trailing whitespace
-		while (*ptr == ' ' || *ptr == '\t')
+		while (*ptr == ' ' || *ptr == '\t') {
 			ptr++;
+		}
 
 		// If there is still something past the whitespace, error out
-		if (*ptr)
+		if (*ptr) {
 			return MBC_BAD;
+		}
 
 		return static_cast<MbcType>(mbc);
 	}
@@ -742,12 +772,14 @@ static uint8_t const nintendoLogo[] = {
 };
 
 static uint8_t fixSpec = 0;
+// clang-format off: vertically align values
 static constexpr uint8_t FIX_LOGO         = 1 << 7;
 static constexpr uint8_t TRASH_LOGO       = 1 << 6;
 static constexpr uint8_t FIX_HEADER_SUM   = 1 << 5;
 static constexpr uint8_t TRASH_HEADER_SUM = 1 << 4;
 static constexpr uint8_t FIX_GLOBAL_SUM   = 1 << 3;
 static constexpr uint8_t TRASH_GLOBAL_SUM = 1 << 2;
+// clang-format on
 
 static enum { DMG, BOTH, CGB } model = DMG; // If DMG, byte is left alone
 static char const *gameID = nullptr;
@@ -780,11 +812,13 @@ static ssize_t readBytes(int fd, uint8_t *buf, size_t len) {
 	while (len) {
 		ssize_t ret = read(fd, buf, len);
 
-		if (ret == -1 && errno != EINTR) // Return errors, unless we only were interrupted
+		if (ret == -1 && errno != EINTR) { // Return errors, unless we only were interrupted
 			return -1;
+		}
 		// EOF reached
-		if (ret == 0)
+		if (ret == 0) {
 			return total;
+		}
 		// If anything was read, accumulate it, and continue
 		if (ret != -1) {
 			total += ret;
@@ -805,8 +839,9 @@ static ssize_t writeBytes(int fd, uint8_t *buf, size_t len) {
 	while (len) {
 		ssize_t ret = write(fd, buf, len);
 
-		if (ret == -1 && errno != EINTR) // Return errors, unless we only were interrupted
+		if (ret == -1 && errno != EINTR) { // Return errors, unless we only were interrupted
 			return -1;
+		}
 		// If anything was written, accumulate it, and continue
 		if (ret != -1) {
 			total += ret;
@@ -818,28 +853,25 @@ static ssize_t writeBytes(int fd, uint8_t *buf, size_t len) {
 	return total;
 }
 
-/*
- * @param rom0 A pointer to rom0
- * @param addr What address to check
- * @param fixedByte The fixed byte at the address
- * @param areaName Name to be displayed in the warning message
- */
+// @param rom0 A pointer to rom0
+// @param addr What address to check
+// @param fixedByte The fixed byte at the address
+// @param areaName Name to be displayed in the warning message
 static void overwriteByte(uint8_t *rom0, uint16_t addr, uint8_t fixedByte, char const *areaName) {
 	uint8_t origByte = rom0[addr];
 
-	if (!overwriteRom && origByte != 0 && origByte != fixedByte)
+	if (!overwriteRom && origByte != 0 && origByte != fixedByte) {
 		fprintf(stderr, "warning: Overwrote a non-zero byte in the %s\n", areaName);
+	}
 
 	rom0[addr] = fixedByte;
 }
 
-/*
- * @param rom0 A pointer to rom0
- * @param startAddr What address to begin checking from
- * @param fixed The fixed bytes at the address
- * @param size How many bytes to check
- * @param areaName Name to be displayed in the warning message
- */
+// @param rom0 A pointer to rom0
+// @param startAddr What address to begin checking from
+// @param fixed The fixed bytes at the address
+// @param size How many bytes to check
+// @param areaName Name to be displayed in the warning message
 static void overwriteBytes(
     uint8_t *rom0, uint16_t startAddr, uint8_t const *fixed, uint8_t size, char const *areaName
 ) {
@@ -857,18 +889,17 @@ static void overwriteBytes(
 	memcpy(&rom0[startAddr], fixed, size);
 }
 
-/*
- * @param input File descriptor to be used for reading
- * @param output File descriptor to be used for writing, may be equal to `input`
- * @param name The file's name, to be displayed for error output
- * @param fileSize The file's size if known, 0 if not.
- */
+// @param input File descriptor to be used for reading
+// @param output File descriptor to be used for writing, may be equal to `input`
+// @param name The file's name, to be displayed for error output
+// @param fileSize The file's size if known, 0 if not.
 static void processFile(int input, int output, char const *name, off_t fileSize) {
 	// Both of these should be true for seekable files, and neither otherwise
-	if (input == output)
+	if (input == output) {
 		assume(fileSize != 0);
-	else
+	} else {
 		assume(fileSize == 0);
+	}
 
 	uint8_t rom0[BANK_SIZE];
 	ssize_t rom0Len = readBytes(input, rom0, sizeof(rom0));
@@ -890,21 +921,25 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
 	}
 	// Accept partial reads if the file contains at least the header
 
-	if (fixSpec & (FIX_LOGO | TRASH_LOGO))
+	if (fixSpec & (FIX_LOGO | TRASH_LOGO)) {
 		overwriteBytes(rom0, 0x0104, logo, sizeof(logo), logoFilename ? "logo" : "Nintendo logo");
+	}
 
-	if (title)
+	if (title) {
 		overwriteBytes(rom0, 0x134, reinterpret_cast<uint8_t const *>(title), titleLen, "title");
+	}
 
-	if (gameID)
+	if (gameID) {
 		overwriteBytes(
 		    rom0, 0x13F, reinterpret_cast<uint8_t const *>(gameID), gameIDLen, "manufacturer code"
 		);
+	}
 
-	if (model != DMG)
+	if (model != DMG) {
 		overwriteByte(rom0, 0x143, model == BOTH ? 0x80 : 0xC0, "CGB flag");
+	}
 
-	if (newLicensee)
+	if (newLicensee) {
 		overwriteBytes(
 		    rom0,
 		    0x144,
@@ -912,9 +947,11 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
 		    newLicenseeLen,
 		    "new licensee code"
 		);
+	}
 
-	if (sgb)
+	if (sgb) {
 		overwriteByte(rom0, 0x146, 0x03, "SGB flag");
+	}
 
 	// If a valid MBC was specified...
 	if (cartridgeType < MBC_NONE) {
@@ -937,31 +974,36 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
 
 		overwriteBytes(rom0, 0x150, tpp1Rev, sizeof(tpp1Rev), "TPP1 revision number");
 
-		if (ramSize != UNSPECIFIED)
+		if (ramSize != UNSPECIFIED) {
 			overwriteByte(rom0, 0x152, ramSize, "RAM size");
+		}
 
 		overwriteByte(rom0, 0x153, cartridgeType & 0xFF, "TPP1 feature flags");
 	} else {
 		// Regular mappers
 
-		if (ramSize != UNSPECIFIED)
+		if (ramSize != UNSPECIFIED) {
 			overwriteByte(rom0, 0x149, ramSize, "RAM size");
+		}
 
-		if (!japanese)
+		if (!japanese) {
 			overwriteByte(rom0, 0x14A, 0x01, "destination code");
+		}
 	}
 
-	if (oldLicensee != UNSPECIFIED)
+	if (oldLicensee != UNSPECIFIED) {
 		overwriteByte(rom0, 0x14B, oldLicensee, "old licensee code");
-	else if (sgb && rom0[0x14B] != 0x33)
+	} else if (sgb && rom0[0x14B] != 0x33) {
 		fprintf(
 		    stderr,
 		    "warning: SGB compatibility enabled, but old licensee was 0x%02x, not 0x33\n",
 		    rom0[0x14B]
 		);
+	}
 
-	if (romVersion != UNSPECIFIED)
+	if (romVersion != UNSPECIFIED) {
 		overwriteByte(rom0, 0x14C, romVersion, "mask ROM version number");
+	}
 
 	// Remain to be handled the ROM size, and header checksum.
 	// The latter depends on the former, and so will be handled after it.
@@ -1009,13 +1051,15 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
 				nbBanks++;
 
 				// Update global checksum, too
-				for (uint16_t i = 0; i < bankLen; i++)
+				for (uint16_t i = 0; i < bankLen; i++) {
 					globalSum += romx[totalRomxLen + i];
+				}
 				totalRomxLen += bankLen;
 			}
 			// Stop when an incomplete bank has been read
-			if (bankLen != BANK_SIZE)
+			if (bankLen != BANK_SIZE) {
 				break;
+			}
 		}
 	}
 
@@ -1042,8 +1086,9 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
 		// Alter number of banks to reflect required value
 		// x&(x-1) is zero iff x is a power of 2, or 0; we know for sure it's non-zero,
 		// so this is true (non-zero) when we don't have a power of 2
-		if (nbBanks & (nbBanks - 1))
+		if (nbBanks & (nbBanks - 1)) {
 			nbBanks = 1 << (CHAR_BIT * sizeof(nbBanks) - clz(nbBanks));
+		}
 		// Write final ROM size
 		rom0[0x148] = ctz(nbBanks / 2);
 		// Alter global checksum based on how many bytes will be added (not counting ROM0)
@@ -1054,8 +1099,9 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
 	if (fixSpec & (FIX_HEADER_SUM | TRASH_HEADER_SUM)) {
 		uint8_t sum = 0;
 
-		for (uint16_t i = 0x134; i < 0x14D; i++)
+		for (uint16_t i = 0x134; i < 0x14D; i++) {
 			sum -= rom0[i] + 1;
+		}
 
 		overwriteByte(rom0, 0x14D, fixSpec & TRASH_HEADER_SUM ? ~sum : sum, "header checksum");
 	}
@@ -1063,28 +1109,32 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
 	if (fixSpec & (FIX_GLOBAL_SUM | TRASH_GLOBAL_SUM)) {
 		// Computation of the global checksum does not include the checksum bytes
 		assume(rom0Len >= 0x14E);
-		for (uint16_t i = 0; i < 0x14E; i++)
+		for (uint16_t i = 0; i < 0x14E; i++) {
 			globalSum += rom0[i];
-		for (uint16_t i = 0x150; i < rom0Len; i++)
+		}
+		for (uint16_t i = 0x150; i < rom0Len; i++) {
 			globalSum += rom0[i];
+		}
 		// Pipes have already read ROMX and updated globalSum, but not regular files
 		if (input == output) {
 			for (;;) {
 				ssize_t bankLen = readBytes(input, bank, sizeof(bank));
 
-				for (uint16_t i = 0; i < bankLen; i++)
+				for (uint16_t i = 0; i < bankLen; i++) {
 					globalSum += bank[i];
-				if (bankLen != sizeof(bank))
+				}
+				if (bankLen != sizeof(bank)) {
 					break;
+				}
 			}
 		}
 
-		if (fixSpec & TRASH_GLOBAL_SUM)
+		if (fixSpec & TRASH_GLOBAL_SUM) {
 			globalSum = ~globalSum;
+		}
 
 		uint8_t bytes[2] = {
-		    static_cast<uint8_t>(globalSum >> 8),
-		    static_cast<uint8_t>(globalSum & 0xFF)
+		    static_cast<uint8_t>(globalSum >> 8), static_cast<uint8_t>(globalSum & 0xFF)
 		};
 
 		overwriteBytes(rom0, 0x14E, bytes, sizeof(bytes), "global checksum");
@@ -1101,8 +1151,9 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
 		}
 		// If modifying the file in-place, we only need to edit the header
 		// However, padding may have modified ROM0 (added padding), so don't in that case
-		if (padValue == UNSPECIFIED)
+		if (padValue == UNSPECIFIED) {
 			rom0Len = headerSize;
+		}
 	}
 	writeLen = writeBytes(output, rom0, rom0Len);
 
@@ -1205,7 +1256,7 @@ static bool processFilename(char const *name) {
 		}
 	}
 
-	if (nbErrors)
+	if (nbErrors) {
 		fprintf(
 		    stderr,
 		    "Fixing \"%s\" failed with %u error%s\n",
@@ -1213,6 +1264,7 @@ static bool processFilename(char const *name) {
 		    nbErrors,
 		    nbErrors == 1 ? "" : "s"
 		);
+	}
 	return nbErrors;
 }
 
@@ -1262,16 +1314,17 @@ int main(int argc, char *argv[]) {
 				switch (*musl_optarg) {
 #define OVERRIDE_SPEC(cur, bad, curFlag, badFlag) \
 	case STR(cur)[0]: \
-		if (fixSpec & badFlag) \
+		if (fixSpec & badFlag) { \
 			fprintf(stderr, "warning: '" STR(cur) "' overriding '" STR(bad) "' in fix spec\n"); \
+		} \
 		fixSpec = (fixSpec & ~badFlag) | curFlag; \
 		break
 #define overrideSpecs(fix, fixFlag, trash, trashFlag) \
 	OVERRIDE_SPEC(fix, trash, fixFlag, trashFlag); \
 	OVERRIDE_SPEC(trash, fix, trashFlag, fixFlag)
-				overrideSpecs(l, FIX_LOGO,       L, TRASH_LOGO);
-				overrideSpecs(h, FIX_HEADER_SUM, H, TRASH_HEADER_SUM);
-				overrideSpecs(g, FIX_GLOBAL_SUM, G, TRASH_GLOBAL_SUM);
+					overrideSpecs(l, FIX_LOGO, L, TRASH_LOGO);
+					overrideSpecs(h, FIX_HEADER_SUM, H, TRASH_HEADER_SUM);
+					overrideSpecs(g, FIX_GLOBAL_SUM, G, TRASH_GLOBAL_SUM);
 #undef OVERRIDE_SPEC
 #undef overrideSpecs
 
@@ -1393,21 +1446,23 @@ int main(int argc, char *argv[]) {
 		}
 	}
 
-	if ((cartridgeType & 0xFF00) == TPP1 && !japanese)
+	if ((cartridgeType & 0xFF00) == TPP1 && !japanese) {
 		fprintf(
 		    stderr,
 		    "warning: TPP1 overwrites region flag for its identification code, ignoring `-j`\n"
 		);
+	}
 
 	// Check that RAM size is correct for "standard" mappers
 	if (ramSize != UNSPECIFIED && (cartridgeType & 0xFF00) == 0) {
 		if (cartridgeType == ROM_RAM || cartridgeType == ROM_RAM_BATTERY) {
-			if (ramSize != 1)
+			if (ramSize != 1) {
 				fprintf(
 				    stderr,
 				    "warning: MBC \"%s\" should have 2 KiB of RAM (-r 1)\n",
 				    mbcName(cartridgeType)
 				);
+			}
 		} else if (hasRAM(cartridgeType)) {
 			if (!ramSize) {
 				fprintf(
@@ -1432,12 +1487,13 @@ int main(int argc, char *argv[]) {
 		}
 	}
 
-	if (sgb && oldLicensee != UNSPECIFIED && oldLicensee != 0x33)
+	if (sgb && oldLicensee != UNSPECIFIED && oldLicensee != 0x33) {
 		fprintf(
 		    stderr,
 		    "warning: SGB compatibility enabled, but old licensee is 0x%02x, not 0x33\n",
 		    oldLicensee
 		);
+	}
 
 	argv += musl_optind;
 	bool failed = nbErrors;
@@ -1488,8 +1544,9 @@ int main(int argc, char *argv[]) {
 		memcpy(logo, nintendoLogo, sizeof(nintendoLogo));
 	}
 	if (fixSpec & TRASH_LOGO) {
-		for (uint16_t i = 0; i < sizeof(logo); i++)
+		for (uint16_t i = 0; i < sizeof(logo); i++) {
 			logo[i] = 0xFF ^ logo[i];
+		}
 	}
 
 	if (!*argv) {
diff --git a/src/gfx/main.cpp b/src/gfx/main.cpp
index c8fd4fe18..c78983096 100644
--- a/src/gfx/main.cpp
+++ b/src/gfx/main.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "gfx/main.hpp"
 
@@ -41,7 +41,8 @@ static struct LocalOptions {
 
 static uintmax_t nbErrors;
 
-[[noreturn]] void giveUp() {
+[[noreturn]]
+void giveUp() {
 	fprintf(stderr, "Conversion aborted after %ju error%s\n", nbErrors, nbErrors == 1 ? "" : "s");
 	exit(1);
 }
@@ -71,18 +72,21 @@ void error(char const *fmt, ...) {
 	va_end(ap);
 	putc('\n', stderr);
 
-	if (nbErrors != std::numeric_limits<decltype(nbErrors)>::max())
+	if (nbErrors != std::numeric_limits<decltype(nbErrors)>::max()) {
 		nbErrors++;
+	}
 }
 
 void errorMessage(char const *msg) {
 	fprintf(stderr, "error: %s\n", msg);
 
-	if (nbErrors != std::numeric_limits<decltype(nbErrors)>::max())
+	if (nbErrors != std::numeric_limits<decltype(nbErrors)>::max()) {
 		nbErrors++;
+	}
 }
 
-[[noreturn]] void fatal(char const *fmt, ...) {
+[[noreturn]]
+void fatal(char const *fmt, ...) {
 	va_list ap;
 
 	fputs("FATAL: ", stderr);
@@ -91,8 +95,9 @@ void errorMessage(char const *msg) {
 	va_end(ap);
 	putc('\n', stderr);
 
-	if (nbErrors != std::numeric_limits<decltype(nbErrors)>::max())
+	if (nbErrors != std::numeric_limits<decltype(nbErrors)>::max()) {
 		nbErrors++;
+	}
 
 	giveUp();
 }
@@ -110,16 +115,13 @@ void Options::verbosePrint(uint8_t level, char const *fmt, ...) const {
 // Short options
 static char const *optstring = "-Aa:b:Cc:d:hi:L:mN:n:Oo:Pp:Qq:r:s:Tt:U:uVvXx:YZ";
 
-/*
- * Equivalent long options
- * Please keep in the same order as short opts
- *
- * Also, make sure long opts don't create ambiguity:
- * A long opt's name should start with the same letter as its short opt,
- * except if it doesn't create any ambiguity (`verbose` versus `version`).
- * This is because long opt matching, even to a single char, is prioritized
- * over short opt matching
- */
+// Equivalent long options
+// Please keep in the same order as short opts.
+// Also, make sure long opts don't create ambiguity:
+// A long opt's name should start with the same letter as its short opt,
+// except if it doesn't create any ambiguity (`verbose` versus `version`).
+// This is because long opt matching, even to a single char, is prioritized
+// over short opt matching.
 static option const longopts[] = {
     {"auto-attr-map",    no_argument,       nullptr, 'A'},
     {"attr-map",         required_argument, nullptr, 'a'},
@@ -173,10 +175,8 @@ static void printUsage() {
 	);
 }
 
-/*
- * Parses a number at the beginning of a string, moving the pointer to skip the parsed characters
- * Returns the provided errVal on error
- */
+// Parses a number at the beginning of a string, moving the pointer to skip the parsed characters.
+// Returns the provided errVal on error.
 static uint16_t parseNumber(char *&string, char const *errPrefix, uint16_t errVal = UINT16_MAX) {
 	uint8_t base = 10;
 	if (*string == '\0') {
@@ -199,12 +199,10 @@ static uint16_t parseNumber(char *&string, char const *errPrefix, uint16_t errVa
 		}
 	}
 
-	/*
-	 * Turns a digit into its numeric value in the current base, if it has one.
-	 * Maximum is inclusive. The string_view is modified to "consume" all digits.
-	 * Returns 255 on parse failure (including wrong char for base), in which case
-	 * the string_view may be pointing on garbage.
-	 */
+	// Turns a digit into its numeric value in the current base, if it has one.
+	// Maximum is inclusive. The string_view is modified to "consume" all digits.
+	// Returns 255 on parse failure (including wrong char for base), in which case
+	// the string_view may be pointing on garbage.
 	auto charIndex = [&base](unsigned char c) -> uint8_t {
 		unsigned char index = c - '0'; // Use wrapping semantics
 		if (base == 2 && index >= 2) {
@@ -272,10 +270,8 @@ static void registerInput(char const *arg) {
 	}
 }
 
-/*
- * Turn an "at-file"'s contents into an argv that `getopt` can handle
- * @param argPool Argument characters will be appended to this vector, for storage purposes.
- */
+// Turn an "at-file"'s contents into an argv that `getopt` can handle
+// @param argPool Argument characters will be appended to this vector, for storage purposes.
 static std::vector<size_t> readAtFile(std::string const &path, std::vector<char> &argPool) {
 	File file;
 	if (!file.open(path, std::ios_base::in)) {
@@ -347,13 +343,10 @@ static std::vector<size_t> readAtFile(std::string const &path, std::vector<char>
 	}
 }
 
-/*
- * Parses an arg vector, modifying `options` and `localOptions` as options are read.
- * The `localOptions` struct is for flags which must be processed after the option parsing finishes.
- *
- * Returns `nullptr` if the vector was fully parsed, or a pointer (which is part of the arg vector)
- * to an "at-file" path if one is encountered.
- */
+// Parses an arg vector, modifying `options` and `localOptions` as options are read.
+// The `localOptions` struct is for flags which must be processed after the option parsing finishes.
+// Returns `nullptr` if the vector was fully parsed, or a pointer (which is part of the arg vector)
+// to an "at-file" path if one is encountered.
 static char *parseArgv(int argc, char *argv[]) {
 	for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, nullptr)) != -1;) {
 		char *arg = musl_optarg; // Make a copy for scanning
@@ -364,8 +357,9 @@ static char *parseArgv(int argc, char *argv[]) {
 			break;
 		case 'a':
 			localOptions.autoAttrmap = false;
-			if (!options.attrmap.empty())
+			if (!options.attrmap.empty()) {
 				warning("Overriding attrmap file %s", options.attrmap.c_str());
+			}
 			options.attrmap = musl_optarg;
 			break;
 		case 'b':
@@ -435,8 +429,9 @@ static char *parseArgv(int argc, char *argv[]) {
 			printUsage();
 			exit(0);
 		case 'i':
-			if (!options.inputTileset.empty())
+			if (!options.inputTileset.empty()) {
 				warning("Overriding input tileset file %s", options.inputTileset.c_str());
+			}
 			options.inputTileset = musl_optarg;
 			break;
 		case 'L':
@@ -534,8 +529,9 @@ static char *parseArgv(int argc, char *argv[]) {
 			localOptions.groupOutputs = true;
 			break;
 		case 'o':
-			if (!options.output.empty())
+			if (!options.output.empty()) {
 				warning("Overriding tile data file %s", options.output.c_str());
+			}
 			options.output = musl_optarg;
 			break;
 		case 'P':
@@ -543,8 +539,9 @@ static char *parseArgv(int argc, char *argv[]) {
 			break;
 		case 'p':
 			localOptions.autoPalettes = false;
-			if (!options.palettes.empty())
+			if (!options.palettes.empty()) {
 				warning("Overriding palettes file %s", options.palettes.c_str());
+			}
 			options.palettes = musl_optarg;
 			break;
 		case 'Q':
@@ -552,8 +549,9 @@ static char *parseArgv(int argc, char *argv[]) {
 			break;
 		case 'q':
 			localOptions.autoPalmap = false;
-			if (!options.palmap.empty())
+			if (!options.palmap.empty()) {
 				warning("Overriding palette map file %s", options.palmap.c_str());
+			}
 			options.palmap = musl_optarg;
 			break;
 		case 'r':
@@ -579,8 +577,9 @@ static char *parseArgv(int argc, char *argv[]) {
 			break;
 		case 't':
 			localOptions.autoTilemap = false;
-			if (!options.tilemap.empty())
+			if (!options.tilemap.empty()) {
 				warning("Overriding tilemap file %s", options.tilemap.c_str());
+			}
 			options.tilemap = musl_optarg;
 			break;
 		case 'V':
@@ -778,19 +777,25 @@ int main(int argc, char *argv[]) {
 		}
 
 		fputs("Options:\n", stderr);
-		if (options.columnMajor)
+		if (options.columnMajor) {
 			fputs("\tVisit image in column-major order\n", stderr);
-		if (options.allowDedup)
+		}
+		if (options.allowDedup) {
 			fputs("\tAllow deduplicating tiles\n", stderr);
-		if (options.allowMirroringX)
+		}
+		if (options.allowMirroringX) {
 			fputs("\tAllow deduplicating horizontally mirrored tiles\n", stderr);
-		if (options.allowMirroringY)
+		}
+		if (options.allowMirroringY) {
 			fputs("\tAllow deduplicating vertically mirrored tiles\n", stderr);
-		if (options.useColorCurve)
+		}
+		if (options.useColorCurve) {
 			fputs("\tUse color curve\n", stderr);
+		}
 		fprintf(stderr, "\tBit depth: %" PRIu8 "bpp\n", options.bitDepth);
-		if (options.trim != 0)
+		if (options.trim != 0) {
 			fprintf(stderr, "\tTrim the last %" PRIu64 " tiles\n", options.trim);
+		}
 		fprintf(stderr, "\tMaximum %" PRIu16 " palettes\n", options.nbPalettes);
 		fprintf(stderr, "\tPalettes contain %" PRIu8 " colors\n", options.nbColorsPerPal);
 		fprintf(stderr, "\t%s palette spec\n", [] {
@@ -887,9 +892,7 @@ void Palette::addColor(uint16_t color) {
 	}
 }
 
-/*
- * Returns the ID of the color in the palette, or `size()` if the color is not in
- */
+// Returns the ID of the color in the palette, or `size()` if the color is not in
 uint8_t Palette::indexOf(uint16_t color) const {
 	return color == Rgba::transparent
 	           ? 0
diff --git a/src/gfx/pal_packing.cpp b/src/gfx/pal_packing.cpp
index 6e712e2d8..869299c22 100644
--- a/src/gfx/pal_packing.cpp
+++ b/src/gfx/pal_packing.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "gfx/pal_packing.hpp"
 
@@ -27,15 +27,11 @@
 //  Tile | Proto-palette
 //  Page | Palette
 
-/*
- * A reference to a proto-palette, and attached attributes for sorting purposes
- */
+// A reference to a proto-palette, and attached attributes for sorting purposes
 struct ProtoPalAttrs {
 	size_t protoPalIndex;
-	/*
-	 * Pages from which we are banned (to prevent infinite loops)
-	 * This is dynamic because we wish not to hard-cap the amount of palettes
-	 */
+	// Pages from which we are banned (to prevent infinite loops)
+	// This is dynamic because we wish not to hard-cap the amount of palettes
 	std::vector<bool> bannedPages;
 
 	explicit ProtoPalAttrs(size_t index) : protoPalIndex(index) {}
@@ -50,10 +46,8 @@ struct ProtoPalAttrs {
 	}
 };
 
-/*
- * A collection of proto-palettes assigned to a palette
- * Does not contain the actual color indices because we need to be able to remove elements
- */
+// A collection of proto-palettes assigned to a palette
+// Does not contain the actual color indices because we need to be able to remove elements
 class AssignedProtos {
 	// We leave room for emptied slots to avoid copying the structs around on removal
 	std::vector<std::optional<ProtoPalAttrs>> _assigned;
@@ -127,10 +121,8 @@ class AssignedProtos {
 	}
 	const_iterator end() const { return const_iterator{&_assigned, _assigned.end()}; }
 
-	/*
-	 * Assigns a new ProtoPalAttrs in a free slot, assuming there is one
-	 * Args are passed to the `ProtoPalAttrs`'s constructor
-	 */
+	// Assigns a new ProtoPalAttrs in a free slot, assuming there is one
+	// Args are passed to the `ProtoPalAttrs`'s constructor
 	template<typename... Ts>
 	void assign(Ts &&...args) {
 		auto freeSlot =
@@ -192,9 +184,7 @@ class AssignedProtos {
 		return colors;
 	}
 public:
-	/*
-	 * Returns the number of distinct colors
-	 */
+	// Returns the number of distinct colors
 	size_t volume() const { return uniqueColors().size(); }
 	bool canFit(ProtoPalette const &protoPal) const {
 		auto &colors = uniqueColors();
@@ -218,10 +208,8 @@ class AssignedProtos {
 		return factor;
 	}();
 
-	/*
-	 * Computes the "relative size" of a proto-palette on this palette;
-	 * it's a measure of how much this proto-palette would "cost" to introduce.
-	 */
+	// Computes the "relative size" of a proto-palette on this palette;
+	// it's a measure of how much this proto-palette would "cost" to introduce.
 	uint32_t relSizeOf(ProtoPalette const &protoPal) const {
 		// NOTE: this function must not call `uniqueColors`, or one of its callers will break!
 
@@ -244,9 +232,7 @@ class AssignedProtos {
 		return relSize;
 	}
 
-	/*
-	 * Computes the "relative size" of a set of proto-palettes on this palette
-	 */
+	// Computes the "relative size" of a set of proto-palettes on this palette
 	template<typename Iter>
 	auto combinedVolume(Iter &&begin, Iter const &end, std::vector<ProtoPalette> const &protoPals)
 	    const {
@@ -254,9 +240,7 @@ class AssignedProtos {
 		addUniqueColors(colors, std::forward<Iter>(begin), end, protoPals);
 		return colors.size();
 	}
-	/*
-	 * Computes the "relative size" of a set of colors on this palette
-	 */
+	// Computes the "relative size" of a set of colors on this palette
 	template<typename Iter>
 	auto combinedVolume(Iter &&begin, Iter &&end) const {
 		auto &colors = uniqueColors();
diff --git a/src/gfx/pal_sorting.cpp b/src/gfx/pal_sorting.cpp
index 0cfde25a3..991f45a7f 100644
--- a/src/gfx/pal_sorting.cpp
+++ b/src/gfx/pal_sorting.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "gfx/pal_sorting.hpp"
 
diff --git a/src/gfx/pal_spec.cpp b/src/gfx/pal_spec.cpp
index f1e1400d4..4e2b3db91 100644
--- a/src/gfx/pal_spec.cpp
+++ b/src/gfx/pal_spec.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "gfx/pal_spec.hpp"
 
@@ -189,12 +189,9 @@ static T readLE(U const *bytes) {
 	return val;
 }
 
-/*
- * **Appends** the first line read from `file` to the end of the provided `buffer`.
- *
- * @return true if a line was read.
- */
-[[gnu::warn_unused_result]] // Ignoring EOF is a bad idea.
+// **Appends** the first line read from `file` to the end of the provided `buffer`.
+// @return true if a line was read.
+[[gnu::warn_unused_result]]
 static bool readLine(std::filebuf &file, std::string &buffer) {
 	assume(buffer.empty());
 	// TODO: maybe this can be optimized to bulk reads?
@@ -223,9 +220,7 @@ static bool readLine(std::filebuf &file, std::string &buffer) {
 		} \
 	} while (0)
 
-/*
- * Parses the initial part of a string_view, advancing the "read index" as it does
- */
+// Parses the initial part of a string_view, advancing the "read index" as it does
 template<typename U> // Should be uint*_t
 static std::optional<U> parseDec(std::string const &str, std::string::size_type &n) {
 	uintmax_t value = 0;
diff --git a/src/gfx/process.cpp b/src/gfx/process.cpp
index 9aeeb6e65..646a49f9c 100644
--- a/src/gfx/process.cpp
+++ b/src/gfx/process.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "gfx/process.hpp"
 
@@ -31,12 +31,11 @@ class ImagePalette {
 public:
 	ImagePalette() = default;
 
-	/*
-	 * Registers a color in the palette.
-	 * If the newly inserted color "conflicts" with another one (different color, but same CGB
-	 * color), then the other color is returned. Otherwise, `nullptr` is returned.
-	 */
-	[[nodiscard]] Rgba const *registerColor(Rgba const &rgba) {
+	// Registers a color in the palette.
+	// If the newly inserted color "conflicts" with another one (different color, but same CGB
+	// color), then the other color is returned. Otherwise, `nullptr` is returned.
+	[[nodiscard]]
+	Rgba const *registerColor(Rgba const &rgba) {
 		decltype(_colors)::value_type &slot = _colors[rgba.cgbColor()];
 
 		if (rgba.cgbColor() == Rgba::transparent) {
@@ -79,7 +78,8 @@ class Png {
 	int nbTransparentEntries;
 	png_bytep transparencyPal = nullptr;
 
-	[[noreturn]] static void handleError(png_structp png, char const *msg) {
+	[[noreturn]]
+	static void handleError(png_structp png, char const *msg) {
 		Png *self = reinterpret_cast<Png *>(png_get_error_ptr(png));
 
 		fatal("Error reading input image (\"%s\"): %s", self->c_str(), msg);
@@ -165,15 +165,13 @@ class Png {
 		return true;
 	}
 
-	/*
-	 * Reads a PNG and notes all of its colors
-	 *
-	 * This code is more complicated than strictly necessary, but that's because of the API
-	 * being used: the "high-level" interface doesn't provide all the transformations we need,
-	 * so we use the "lower-level" one instead.
-	 * We also use that occasion to only read the PNG one line at a time, since we store all of
-	 * the pixel data in `pixels`, which saves on memory allocations.
-	 */
+	// Reads a PNG and notes all of its colors
+	//
+	// This code is more complicated than strictly necessary, but that's because of the API
+	// being used: the "high-level" interface doesn't provide all the transformations we need,
+	// so we use the "lower-level" one instead.
+	// We also use that occasion to only read the PNG one line at a time, since we store all of
+	// the pixel data in `pixels`, which saves on memory allocations.
 	explicit Png(std::string const &filePath) : path(filePath), colors() {
 		if (file.open(path, std::ios_base::in | std::ios_base::binary) == nullptr) {
 			fatal("Failed to open input image (\"%s\"): %s", file.c_str(path), strerror(errno));
@@ -490,9 +488,7 @@ class Png {
 };
 
 class RawTiles {
-	/*
-	 * A tile which only contains indices into the image's global palette
-	 */
+	// A tile which only contains indices into the image's global palette
 	class RawTile {
 		std::array<std::array<size_t, 8>, 8> _pixelIndices{};
 
@@ -505,9 +501,7 @@ class RawTiles {
 	std::vector<RawTile> _tiles;
 
 public:
-	/*
-	 * Creates a new raw tile, and returns a reference to it so it can be filled in
-	 */
+	// Creates a new raw tile, and returns a reference to it so it can be filled in
 	RawTile &newTile() {
 		_tiles.emplace_back();
 		return _tiles.back();
@@ -515,11 +509,9 @@ class RawTiles {
 };
 
 struct AttrmapEntry {
-	/*
-	 * This field can either be a proto-palette ID, or `transparent` to indicate that the
-	 * corresponding tile is fully transparent. If you are looking to get the palette ID for this
-	 * attrmap entry while correctly handling the above, use `getPalID`.
-	 */
+	// This field can either be a proto-palette ID, or `transparent` to indicate that the
+	// corresponding tile is fully transparent. If you are looking to get the palette ID for this
+	// attrmap entry while correctly handling the above, use `getPalID`.
 	size_t protoPaletteID; // Only this field is used when outputting "unoptimized" data
 	uint8_t tileID;        // This is the ID as it will be output to the tilemap
 	bool bank;
@@ -712,8 +704,9 @@ static void hashBitplanes(uint16_t bitplanes, uint16_t &hash) {
 
 class TileData {
 	// Importantly, `TileData` is **always** 2bpp.
-	// If the active bit depth is 1bpp, all tiles are processed as 2bpp nonetheless, but emitted as 1bpp.
-	// This massively simplifies internal processing, since bit depth is always identical outside of I/O / serialization boundaries.
+	// If the active bit depth is 1bpp, all tiles are processed as 2bpp nonetheless, but emitted as
+	// 1bpp. This massively simplifies internal processing, since bit depth is always identical
+	// outside of I/O / serialization boundaries.
 	std::array<uint8_t, 16> _data;
 	// The hash is a bit lax: it's the XOR of all lines, and every other nibble is identical
 	// if horizontal mirroring is in effect. It should still be a reasonable tie-breaker in
@@ -917,9 +910,7 @@ struct UniqueTiles {
 	UniqueTiles(UniqueTiles const &) = delete;
 	UniqueTiles(UniqueTiles &&) = default;
 
-	/*
-	 * Adds a tile to the collection, and returns its ID
-	 */
+	// Adds a tile to the collection, and returns its ID
 	std::tuple<uint16_t, TileData::MatchType> addTile(TileData newTile) {
 		auto [tileData, inserted] = tileset.insert(newTile);
 
@@ -941,12 +932,10 @@ struct UniqueTiles {
 	auto end() const { return tiles.end(); }
 };
 
-/*
- * Generate tile data while deduplicating unique tiles (via mirroring if enabled)
- * Additionally, while we have the info handy, convert from the 16-bit "global" tile IDs to
- * 8-bit tile IDs + the bank bit; this will save the work when we output the data later (potentially
- * twice)
- */
+// Generate tile data while deduplicating unique tiles (via mirroring if enabled)
+// Additionally, while we have the info handy, convert from the 16-bit "global" tile IDs to
+// 8-bit tile IDs + the bank bit; this will save the work when we output the data later (potentially
+// twice)
 static UniqueTiles dedupTiles(
     Png const &png,
     DefaultInitVec<AttrmapEntry> &attrmap,
@@ -1163,18 +1152,17 @@ void process() {
 				protoPalettes[n] = protoPalette; // Override them
 				// Remove any other proto-palettes that we encompass
 				// (Example [(0, 1), (0, 2)], inserting (0, 1, 2))
-				/*
-				 * The following code does its job, except that references to the removed
-				 * proto-palettes are not updated, causing issues.
-				 * TODO: overlap might not be detrimental to the packing algorithm.
-				 * Investigation is necessary, especially if pathological cases are found.
-				 *
-				 * for (size_t i = protoPalettes.size(); --i != n;) {
-				 *     if (protoPalette.compare(protoPalettes[i]) == ProtoPalette::WE_BIGGER) {
-				 *         protoPalettes.erase(protoPalettes.begin() + i);
-				 *     }
-				 * }
-				 */
+				//
+				// The following code does its job, except that references to the removed
+				// proto-palettes are not updated, causing issues.
+				// TODO: overlap might not be detrimental to the packing algorithm.
+				// Investigation is necessary, especially if pathological cases are found.
+				//
+				// for (size_t i = protoPalettes.size(); --i != n;) {
+				//     if (protoPalette.compare(protoPalettes[i]) == ProtoPalette::WE_BIGGER) {
+				//         protoPalettes.erase(protoPalettes.begin() + i);
+				//     }
+				// }
 				[[fallthrough]];
 
 			case ProtoPalette::THEY_BIGGER:
diff --git a/src/gfx/proto_palette.cpp b/src/gfx/proto_palette.cpp
index be845bd01..7a7a532c5 100644
--- a/src/gfx/proto_palette.cpp
+++ b/src/gfx/proto_palette.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "gfx/proto_palette.hpp"
 
diff --git a/src/gfx/reverse.cpp b/src/gfx/reverse.cpp
index 82904156d..d2dbd1890 100644
--- a/src/gfx/reverse.cpp
+++ b/src/gfx/reverse.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "gfx/reverse.hpp"
 
@@ -49,7 +49,8 @@ static DefaultInitVec<uint8_t> readInto(std::string const &path) {
 	return data;
 }
 
-[[noreturn]] static void pngError(png_structp png, char const *msg) {
+[[noreturn]]
+static void pngError(png_structp png, char const *msg) {
 	fatal(
 	    "Error writing reversed image (\"%s\"): %s",
 	    static_cast<char const *>(png_get_error_ptr(png)),
@@ -166,8 +167,9 @@ void reverse() {
 		// This avoids redundancy with `-r 1` which results in a vertical column.
 		width = static_cast<size_t>(ceil(sqrt(mapSize)));
 		for (; width < mapSize; ++width) {
-			if (mapSize % width == 0)
+			if (mapSize % width == 0) {
 				break;
+			}
 		}
 		options.verbosePrint(Options::VERB_INTERM, "Picked reversing width of %zu tiles\n", width);
 	}
@@ -467,24 +469,7 @@ void reverse() {
 			assume(palID < palettes.size()); // Should be ensured on data read
 
 			// We do not have data for tiles trimmed with `-x`, so assume they are "blank"
-			static std::array<uint8_t, 16> const trimmedTile{
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			    0x00,
-			};
+			static std::array<uint8_t, 16> const trimmedTile{0x00};
 			uint8_t const *tileData =
 			    tileOfs >= nbTiles ? trimmedTile.data() : &tiles[tileOfs * tileSize];
 			auto const &palette = palettes[palID];
diff --git a/src/gfx/rgba.cpp b/src/gfx/rgba.cpp
index e2ae941d6..0e0677efd 100644
--- a/src/gfx/rgba.cpp
+++ b/src/gfx/rgba.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "gfx/rgba.hpp"
 
@@ -10,29 +10,29 @@
 
 #include "gfx/main.hpp" // options
 
-/*
- * Based on inverting the "Modern - Accurate" formula used by SameBoy
- * since commit b5a611c5db46d6a0649d04d24d8d6339200f9ca1 (Dec 2020),
- * with gaps in the scale curve filled by polynomial interpolation.
- */
+// Based on inverting the "Modern - Accurate" formula used by SameBoy
+// since commit b5a611c5db46d6a0649d04d24d8d6339200f9ca1 (Dec 2020),
+// with gaps in the scale curve filled by polynomial interpolation.
+// clang-format off: vertically align columns of values
 static std::array<uint8_t, 256> reverse_curve{
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  // These
-    1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  // comments
-    3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  // prevent
-    5,  5,  5,  6,  6,  6,  6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  // clang-format
-    7,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  10, 10, 10, 10, // from
-    10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, // reflowing
-    13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, // these
-    16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 19, 19, // sixteen
-    19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 22, // 16-item
-    22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, // lines,
-    24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, // which,
-    26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, // in
-    28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, // my
-    29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, // opinion,
-    31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, // help
-    31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, // visualization!
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,
+    1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,
+    3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,
+    5,  5,  5,  6,  6,  6,  6,  6,  6,  7,  7,  7,  7,  7,  7,  7,
+    7,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  10, 10, 10, 10,
+    10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13,
+    13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16,
+    16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 19, 19,
+    19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 22,
+    22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24,
+    24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26,
+    26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28,
+    28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+    29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+    31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+    31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
 };
+// clang-format on
 
 uint16_t Rgba::cgbColor() const {
 	if (isTransparent()) {
diff --git a/src/link/assign.cpp b/src/link/assign.cpp
index 35810c24f..b0220b527 100644
--- a/src/link/assign.cpp
+++ b/src/link/assign.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "link/assign.hpp"
 
@@ -48,11 +48,9 @@ static void initFreeSpace() {
 	}
 }
 
-/*
- * Assigns a section to a given memory location
- * @param section The section to assign
- * @param location The location to assign the section to
- */
+// Assigns a section to a given memory location
+// @param section The section to assign
+// @param location The location to assign the section to
 static void assignSection(Section &section, MemoryLocation const &location) {
 	// Propagate the assigned location to all UNIONs/FRAGMENTs
 	// so `jr` patches in them will have the correct offset
@@ -66,37 +64,36 @@ static void assignSection(Section &section, MemoryLocation const &location) {
 	out_AddSection(section);
 }
 
-/*
- * Checks whether a given location is suitable for placing a given section
- * This checks not only that the location has enough room for the section, but
- * also that the constraints (alignment...) are respected.
- * @param section The section to be placed
- * @param freeSpace The candidate free space to place the section into
- * @param location The location to attempt placing the section at
- * @return True if the location is suitable, false otherwise.
- */
+// Checks whether a given location is suitable for placing a given section
+// This checks not only that the location has enough room for the section, but
+// also that the constraints (alignment...) are respected.
+// @param section The section to be placed
+// @param freeSpace The candidate free space to place the section into
+// @param location The location to attempt placing the section at
+// @return True if the location is suitable, false otherwise.
 static bool isLocationSuitable(
     Section const &section, FreeSpace const &freeSpace, MemoryLocation const &location
 ) {
-	if (section.isAddressFixed && section.org != location.address)
+	if (section.isAddressFixed && section.org != location.address) {
 		return false;
+	}
 
-	if (section.isAlignFixed && ((location.address - section.alignOfs) & section.alignMask))
+	if (section.isAlignFixed && ((location.address - section.alignOfs) & section.alignMask)) {
 		return false;
+	}
 
-	if (location.address < freeSpace.address)
+	if (location.address < freeSpace.address) {
 		return false;
+	}
 
 	return location.address + section.size <= freeSpace.address + freeSpace.size;
 }
 
-/*
- * Finds a suitable location to place a section at.
- * @param section The section to be placed
- * @param location A pointer to a memory location that will be filled
- * @return The index into `memory[section->type]` of the free space encompassing the location,
- *         or -1 if none was found
- */
+// Finds a suitable location to place a section at.
+// @param section The section to be placed
+// @param location A pointer to a memory location that will be filled
+// @return The index into `memory[section->type]` of the free space encompassing the location,
+//         or -1 if none was found
 static ssize_t getPlacement(Section const &section, MemoryLocation &location) {
 	SectionTypeInfo const &typeInfo = sectionTypeInfo[section.type];
 
@@ -108,16 +105,19 @@ static ssize_t getPlacement(Section const &section, MemoryLocation &location) {
 	if (section.isBankFixed) {
 		location.bank = section.bank;
 	} else if (scrambleROMX && section.type == SECTTYPE_ROMX) {
-		if (curScrambleROM < 1)
+		if (curScrambleROM < 1) {
 			curScrambleROM = scrambleROMX;
+		}
 		location.bank = curScrambleROM--;
 	} else if (scrambleWRAMX && section.type == SECTTYPE_WRAMX) {
-		if (curScrambleWRAM < 1)
+		if (curScrambleWRAM < 1) {
 			curScrambleWRAM = scrambleWRAMX;
+		}
 		location.bank = curScrambleWRAM--;
 	} else if (scrambleSRAM && section.type == SECTTYPE_SRAM) {
-		if (curScrambleSRAM < 0)
+		if (curScrambleSRAM < 0) {
 			curScrambleSRAM = scrambleSRAM;
+		}
 		location.bank = curScrambleSRAM--;
 	} else {
 		location.bank = typeInfo.firstBank;
@@ -134,18 +134,20 @@ static ssize_t getPlacement(Section const &section, MemoryLocation &location) {
 			// Process locations in that bank
 			while (spaceIdx < bankMem.size()) {
 				// If that location is OK, return it
-				if (isLocationSuitable(section, bankMem[spaceIdx], location))
+				if (isLocationSuitable(section, bankMem[spaceIdx], location)) {
 					return spaceIdx;
+				}
 
 				// Go to the next *possible* location
 				if (section.isAddressFixed) {
 					// If the address is fixed, there can be only
 					// one candidate block per bank; if we already
 					// reached it, give up.
-					if (location.address < section.org)
+					if (location.address < section.org) {
 						location.address = section.org;
-					else
+					} else {
 						break; // Try again in next bank
+					}
 				} else if (section.isAlignFixed) {
 					// Move to next aligned location
 					// Move back to alignment boundary
@@ -157,15 +159,17 @@ static ssize_t getPlacement(Section const &section, MemoryLocation &location) {
 				} else {
 					// Any location is fine, so, next free block
 					spaceIdx++;
-					if (spaceIdx < bankMem.size())
+					if (spaceIdx < bankMem.size()) {
 						location.address = bankMem[spaceIdx].address;
+					}
 				}
 
 				// If that location is past the current block's end,
 				// go forwards until that is no longer the case.
 				while (spaceIdx < bankMem.size()
-				       && location.address >= bankMem[spaceIdx].address + bankMem[spaceIdx].size)
+				       && location.address >= bankMem[spaceIdx].address + bankMem[spaceIdx].size) {
 					spaceIdx++;
+				}
 
 				// Try again with the new location/free space combo
 			}
@@ -177,26 +181,30 @@ static ssize_t getPlacement(Section const &section, MemoryLocation &location) {
 		if (section.isBankFixed) {
 			return -1;
 		} else if (scrambleROMX && section.type == SECTTYPE_ROMX && location.bank <= scrambleROMX) {
-			if (location.bank > typeInfo.firstBank)
+			if (location.bank > typeInfo.firstBank) {
 				location.bank--;
-			else if (scrambleROMX < typeInfo.lastBank)
+			} else if (scrambleROMX < typeInfo.lastBank) {
 				location.bank = scrambleROMX + 1;
-			else
+			} else {
 				return -1;
-		} else if (scrambleWRAMX && section.type == SECTTYPE_WRAMX && location.bank <= scrambleWRAMX) {
-			if (location.bank > typeInfo.firstBank)
+			}
+		} else if (scrambleWRAMX && section.type == SECTTYPE_WRAMX
+		           && location.bank <= scrambleWRAMX) {
+			if (location.bank > typeInfo.firstBank) {
 				location.bank--;
-			else if (scrambleWRAMX < typeInfo.lastBank)
+			} else if (scrambleWRAMX < typeInfo.lastBank) {
 				location.bank = scrambleWRAMX + 1;
-			else
+			} else {
 				return -1;
+			}
 		} else if (scrambleSRAM && section.type == SECTTYPE_SRAM && location.bank <= scrambleSRAM) {
-			if (location.bank > typeInfo.firstBank)
+			if (location.bank > typeInfo.firstBank) {
 				location.bank--;
-			else if (scrambleSRAM < typeInfo.lastBank)
+			} else if (scrambleSRAM < typeInfo.lastBank) {
 				location.bank = scrambleSRAM + 1;
-			else
+			} else {
 				return -1;
+			}
 		} else if (location.bank < typeInfo.lastBank) {
 			location.bank++;
 		} else {
@@ -205,12 +213,10 @@ static ssize_t getPlacement(Section const &section, MemoryLocation &location) {
 	}
 }
 
-/*
- * Places a section in a suitable location, or error out if it fails to.
- * @warning Due to the implemented algorithm, this should be called with
- *          sections of decreasing size.
- * @param section The section to place
- */
+// Places a section in a suitable location, or error out if it fails to.
+// @warning Due to the implemented algorithm, this should be called with
+//          sections of decreasing size.
+// @param section The section to place
 static void placeSection(Section &section) {
 	MemoryLocation location;
 
@@ -258,9 +264,10 @@ static void placeSection(Section &section) {
 		} else {
 			// The amount of free spaces doesn't change: resize!
 			freeSpace.size -= section.size;
-			if (noLeftSpace)
+			if (noLeftSpace) {
 				// The free space is moved *and* resized
 				freeSpace.address += section.size;
+			}
 		}
 		return;
 	}
@@ -269,11 +276,11 @@ static void placeSection(Section &section) {
 	char where[64];
 
 	if (section.isBankFixed && nbbanks(section.type) != 1) {
-		if (section.isAddressFixed)
+		if (section.isAddressFixed) {
 			snprintf(
 			    where, sizeof(where), "at $%02" PRIx32 ":%04" PRIx16, section.bank, section.org
 			);
-		else if (section.isAlignFixed)
+		} else if (section.isAlignFixed) {
 			snprintf(
 			    where,
 			    sizeof(where),
@@ -281,12 +288,13 @@ static void placeSection(Section &section) {
 			    section.bank,
 			    static_cast<uint16_t>(~section.alignMask)
 			);
-		else
+		} else {
 			snprintf(where, sizeof(where), "in bank $%02" PRIx32, section.bank);
+		}
 	} else {
-		if (section.isAddressFixed)
+		if (section.isAddressFixed) {
 			snprintf(where, sizeof(where), "at address $%04" PRIx16, section.org);
-		else if (section.isAlignFixed)
+		} else if (section.isAlignFixed) {
 			snprintf(
 			    where,
 			    sizeof(where),
@@ -294,20 +302,22 @@ static void placeSection(Section &section) {
 			    static_cast<uint16_t>(~section.alignMask),
 			    section.alignOfs
 			);
-		else
+		} else {
 			strcpy(where, "anywhere");
+		}
 	}
 
 	// If a section failed to go to several places, nothing we can report
-	if (!section.isBankFixed || !section.isAddressFixed)
+	if (!section.isBankFixed || !section.isAddressFixed) {
 		errx(
 		    "Unable to place \"%s\" (%s section) %s",
 		    section.name.c_str(),
 		    sectionTypeInfo[section.type].name.c_str(),
 		    where
 		);
+	}
 	// If the section just can't fit the bank, report that
-	else if (section.org + section.size > endaddr(section.type) + 1)
+	else if (section.org + section.size > endaddr(section.type) + 1) {
 		errx(
 		    "Unable to place \"%s\" (%s section) %s: section runs past end of region ($%04x > "
 		    "$%04x)",
@@ -317,8 +327,9 @@ static void placeSection(Section &section) {
 		    section.org + section.size,
 		    endaddr(section.type) + 1
 		);
+	}
 	// Otherwise there is overlap with another section
-	else
+	else {
 		errx(
 		    "Unable to place \"%s\" (%s section) %s: section overlaps with \"%s\"",
 		    section.name.c_str(),
@@ -326,35 +337,40 @@ static void placeSection(Section &section) {
 		    where,
 		    out_OverlappingSection(section)->name.c_str()
 		);
+	}
 }
 
+// clang-format off: vertically align values
 static constexpr uint8_t BANK_CONSTRAINED  = 1 << 2;
 static constexpr uint8_t ORG_CONSTRAINED   = 1 << 1;
 static constexpr uint8_t ALIGN_CONSTRAINED = 1 << 0;
+// clang-format on
 static std::deque<Section *> unassignedSections[1 << 3];
 
-/*
- * Categorize a section depending on how constrained it is
- * This is so the most-constrained sections are placed first
- * @param section The section to categorize
- */
+// Categorize a section depending on how constrained it is
+// This is so the most-constrained sections are placed first
+// @param section The section to categorize
 static void categorizeSection(Section &section) {
 	uint8_t constraints = 0;
 
-	if (section.isBankFixed)
+	if (section.isBankFixed) {
 		constraints |= BANK_CONSTRAINED;
-	if (section.isAddressFixed)
+	}
+	if (section.isAddressFixed) {
 		constraints |= ORG_CONSTRAINED;
+	}
 	// Can't have both!
-	else if (section.isAlignFixed)
+	else if (section.isAlignFixed) {
 		constraints |= ALIGN_CONSTRAINED;
+	}
 
 	std::deque<Section *> &sections = unassignedSections[constraints];
 	auto pos = sections.begin();
 
 	// Insert section while keeping the list sorted by decreasing size
-	while (pos != sections.end() && (*pos)->size > section.size)
+	while (pos != sections.end() && (*pos)->size > section.size) {
 		pos++;
+	}
 	sections.insert(pos, &section);
 
 	nbSectionsToAssign++;
@@ -375,12 +391,14 @@ void assign_AssignSections() {
 
 	// Specially process fully-constrained sections because of overlaying
 	verbosePrint("Assigning bank+org-constrained...\n");
-	for (Section *section : unassignedSections[BANK_CONSTRAINED | ORG_CONSTRAINED])
+	for (Section *section : unassignedSections[BANK_CONSTRAINED | ORG_CONSTRAINED]) {
 		placeSection(*section);
+	}
 
 	// If all sections were fully constrained, we have nothing left to do
-	if (!nbSectionsToAssign)
+	if (!nbSectionsToAssign) {
 		return;
+	}
 
 	// Overlaying requires only fully-constrained sections
 	verbosePrint("Assigning other sections...\n");
@@ -392,14 +410,16 @@ void assign_AssignSections() {
 			for (Section *section : unassignedSections[constraints]) {
 				fprintf(stderr, "%c \"%s\"", nbSections == 0 ? ';' : ',', section->name.c_str());
 				nbSections++;
-				if (nbSections == 10)
+				if (nbSections == 10) {
 					goto max_out; // Can't `break` out of a nested loop
+				}
 			}
 		}
 
 max_out:
-		if (nbSectionsToAssign != nbSections)
+		if (nbSectionsToAssign != nbSections) {
 			fprintf(stderr, " and %" PRIu64 " more", nbSectionsToAssign - nbSections);
+		}
 		fprintf(stderr, " %sn't\n", nbSectionsToAssign == 1 ? "is" : "are");
 		exit(1);
 	}
@@ -407,11 +427,13 @@ void assign_AssignSections() {
 	// Assign all remaining sections by decreasing constraint order
 	for (int8_t constraints = BANK_CONSTRAINED | ALIGN_CONSTRAINED; constraints >= 0;
 	     constraints--) {
-		for (Section *section : unassignedSections[constraints])
+		for (Section *section : unassignedSections[constraints]) {
 			placeSection(*section);
+		}
 
-		if (!nbSectionsToAssign)
+		if (!nbSectionsToAssign) {
 			return;
+		}
 	}
 
 	unreachable_();
diff --git a/src/link/main.cpp b/src/link/main.cpp
index 7e4c1d0d5..0fd54eca9 100644
--- a/src/link/main.cpp
+++ b/src/link/main.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -52,8 +52,9 @@ std::string const &FileStackNode::dump(uint32_t curLineNo) const {
 		std::string const &lastName = parent->dump(lineNo);
 		fputs(" -> ", stderr);
 		fputs(lastName.c_str(), stderr);
-		for (uint32_t iter : iters())
+		for (uint32_t iter : iters()) {
 			fprintf(stderr, "::REPT~%" PRIu32, iter);
+		}
 		fprintf(stderr, "(%" PRIu32 ")", curLineNo);
 		return lastName;
 	} else {
@@ -96,8 +97,9 @@ void error(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) {
 	printDiag(fmt, args, "error", where, lineNo);
 	va_end(args);
 
-	if (nbErrors != UINT32_MAX)
+	if (nbErrors != UINT32_MAX) {
 		nbErrors++;
+	}
 }
 
 void argErr(char flag, char const *fmt, ...) {
@@ -109,19 +111,22 @@ void argErr(char flag, char const *fmt, ...) {
 	va_end(args);
 	putc('\n', stderr);
 
-	if (nbErrors != UINT32_MAX)
+	if (nbErrors != UINT32_MAX) {
 		nbErrors++;
+	}
 }
 
-[[noreturn]] void fatal(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) {
+[[noreturn]]
+void fatal(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) {
 	va_list args;
 
 	va_start(args, fmt);
 	printDiag(fmt, args, "FATAL", where, lineNo);
 	va_end(args);
 
-	if (nbErrors != UINT32_MAX)
+	if (nbErrors != UINT32_MAX) {
 		nbErrors++;
+	}
 
 	fprintf(
 	    stderr, "Linking aborted after %" PRIu32 " error%s\n", nbErrors, nbErrors == 1 ? "" : "s"
@@ -132,16 +137,13 @@ void argErr(char flag, char const *fmt, ...) {
 // Short options
 static char const *optstring = "dhl:m:Mn:O:o:p:S:tVvWwx";
 
-/*
- * Equivalent long options
- * Please keep in the same order as short opts
- *
- * Also, make sure long opts don't create ambiguity:
- * A long opt's name should start with the same letter as its short opt,
- * except if it doesn't create any ambiguity (`verbose` versus `version`).
- * This is because long opt matching, even to a single char, is prioritized
- * over short opt matching
- */
+// Equivalent long options
+// Please keep in the same order as short opts.
+// Also, make sure long opts don't create ambiguity:
+// A long opt's name should start with the same letter as its short opt,
+// except if it doesn't create any ambiguity (`verbose` versus `version`).
+// This is because long opt matching, even to a single char, is prioritized
+// over short opt matching.
 static option const longopts[] = {
     {"dmg",           no_argument,       nullptr, 'd'},
     {"help",          no_argument,       nullptr, 'h'},
@@ -218,19 +220,19 @@ static void parseScrambleSpec(char const *spec) {
 		if (regionNameLen == 0) {
 			argErr('S', "Missing region name");
 
-			if (*spec == '\0')
+			if (*spec == '\0') {
 				break;
-			if (*spec == '=')                 // Skip the limit, too
+			}
+			if (*spec == '=') {               // Skip the limit, too
 				spec = strchr(&spec[1], ','); // Skip to next comma, if any
+			}
 			goto next;
 		}
 
 		// Find the next non-blank char after the region name's end
 		spec += regionNameLen + strspn(&spec[regionNameLen], " \t");
 		if (*spec != '\0' && *spec != ',' && *spec != '=') {
-			argErr(
-			    'S', "Unexpected '%c' after region name \"%.*s\"", regionNameFmtLen, regionName
-			);
+			argErr('S', "Unexpected '%c' after region name \"%.*s\"", regionNameFmtLen, regionName);
 			// Skip to next ',' or '=' (or NUL) and keep parsing
 			spec += 1 + strcspn(&spec[1], ",=");
 		}
@@ -246,8 +248,9 @@ static void parseScrambleSpec(char const *spec) {
 			}
 		}
 
-		if (region == SCRAMBLE_UNK)
+		if (region == SCRAMBLE_UNK) {
 			argErr('S', "Unknown region \"%.*s\"", regionNameFmtLen, regionName);
+		}
 
 		if (*spec == '=') {
 			spec++; // `strtoul` will skip the whitespace on its own
@@ -305,15 +308,18 @@ static void parseScrambleSpec(char const *spec) {
 next: // Can't `continue` a `for` loop with this nontrivial iteration logic
 		if (spec) {
 			assume(*spec == ',' || *spec == '\0');
-			if (*spec == ',')
+			if (*spec == ',') {
 				spec += 1 + strspn(&spec[1], " \t");
-			if (*spec == '\0')
+			}
+			if (*spec == '\0') {
 				break;
+			}
 		}
 	}
 }
 
-[[noreturn]] void reportErrors() {
+[[noreturn]]
+void reportErrors() {
 	fprintf(
 	    stderr, "Linking failed with %" PRIu32 " error%s\n", nbErrors, nbErrors == 1 ? "" : "s"
 	);
@@ -332,31 +338,36 @@ int main(int argc, char *argv[]) {
 			printUsage();
 			exit(0);
 		case 'l':
-			if (linkerScriptName)
+			if (linkerScriptName) {
 				warnx("Overriding linker script %s", linkerScriptName);
+			}
 			linkerScriptName = musl_optarg;
 			break;
 		case 'M':
 			noSymInMap = true;
 			break;
 		case 'm':
-			if (mapFileName)
+			if (mapFileName) {
 				warnx("Overriding map file %s", mapFileName);
+			}
 			mapFileName = musl_optarg;
 			break;
 		case 'n':
-			if (symFileName)
+			if (symFileName) {
 				warnx("Overriding sym file %s", symFileName);
+			}
 			symFileName = musl_optarg;
 			break;
 		case 'O':
-			if (overlayFileName)
+			if (overlayFileName) {
 				warnx("Overriding overlay file %s", overlayFileName);
+			}
 			overlayFileName = musl_optarg;
 			break;
 		case 'o':
-			if (outputFileName)
+			if (outputFileName) {
 				warnx("Overriding output file %s", outputFileName);
+			}
 			outputFileName = musl_optarg;
 			break;
 		case 'p': {
@@ -413,18 +424,22 @@ int main(int argc, char *argv[]) {
 	}
 
 	// Patch the size array depending on command-line options
-	if (!is32kMode)
+	if (!is32kMode) {
 		sectionTypeInfo[SECTTYPE_ROM0].size = 0x4000;
-	if (!isWRAM0Mode)
+	}
+	if (!isWRAM0Mode) {
 		sectionTypeInfo[SECTTYPE_WRAM0].size = 0x1000;
+	}
 
 	// Patch the bank ranges array depending on command-line options
-	if (isDmgMode)
+	if (isDmgMode) {
 		sectionTypeInfo[SECTTYPE_VRAM].lastBank = 0;
+	}
 
 	// Read all object files first,
-	for (obj_Setup(argc - curArgIndex); curArgIndex < argc; curArgIndex++)
+	for (obj_Setup(argc - curArgIndex); curArgIndex < argc; curArgIndex++) {
 		obj_ReadFile(argv[curArgIndex], argc - curArgIndex - 1);
+	}
 
 	// apply the linker script's modifications,
 	if (linkerScriptName) {
@@ -433,20 +448,23 @@ int main(int argc, char *argv[]) {
 		script_ProcessScript(linkerScriptName);
 
 		// If the linker script produced any errors, some sections may be in an invalid state
-		if (nbErrors != 0)
+		if (nbErrors != 0) {
 			reportErrors();
+		}
 	}
 
 	// then process them,
 	sect_DoSanityChecks();
-	if (nbErrors != 0)
+	if (nbErrors != 0) {
 		reportErrors();
+	}
 	assign_AssignSections();
 	patch_CheckAssertions();
 
 	// and finally output the result.
 	patch_ApplyPatches();
-	if (nbErrors != 0)
+	if (nbErrors != 0) {
 		reportErrors();
+	}
 	out_WriteFiles();
 }
diff --git a/src/link/object.cpp b/src/link/object.cpp
index 4253d30dd..7a77b345f 100644
--- a/src/link/object.cpp
+++ b/src/link/object.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "link/object.hpp"
 
@@ -41,11 +41,9 @@ static std::vector<std::vector<FileStackNode>> nodes;
 		var = static_cast<vartype>(tmpVal); \
 	} while (0)
 
-/*
- * Reads an unsigned long (32-bit) value from a file.
- * @param file The file to read from. This will read 4 bytes from the file.
- * @return The value read, cast to a int64_t, or `INT64_MAX` on failure.
- */
+// Reads an unsigned long (32-bit) value from a file.
+// @param file The file to read from. This will read 4 bytes from the file.
+// @return The value read, cast to a int64_t, or `INT64_MAX` on failure.
 static int64_t readLong(FILE *file) {
 	uint32_t value = 0;
 
@@ -53,8 +51,9 @@ static int64_t readLong(FILE *file) {
 	for (uint8_t shift = 0; shift < sizeof(value) * CHAR_BIT; shift += 8) {
 		int byte = getc(file);
 
-		if (byte == EOF)
+		if (byte == EOF) {
 			return INT64_MAX;
+		}
 		// This must be casted to `unsigned`, not `uint8_t`. Rationale:
 		// the type of the shift is the type of `byte` after undergoing
 		// integer promotion, which would be `int` if this was casted to
@@ -66,37 +65,31 @@ static int64_t readLong(FILE *file) {
 	return value;
 }
 
-/*
- * Helper macro for reading longs from a file, and errors out if it fails to.
- * Not as a function to avoid overhead in the general case.
- * @param var The variable to stash the number into
- * @param file The file to read from. Its position will be advanced
- * @param ... A format string and related arguments; note that an extra string
- *            argument is provided, the reason for failure
- */
+// Helper macro for reading longs from a file, and errors out if it fails to.
+// Not as a function to avoid overhead in the general case.
+// @param var The variable to stash the number into
+// @param file The file to read from. Its position will be advanced
+// @param ... A format string and related arguments; note that an extra string
+//            argument is provided, the reason for failure
 #define tryReadLong(var, file, ...) \
 	tryRead(readLong, int64_t, INT64_MAX, long, var, file, __VA_ARGS__)
 
-// There is no `readbyte`, just use `fgetc` or `getc`.
+// There is no `readByte`, just use `fgetc` or `getc`.
 
-/*
- * Helper macro for reading bytes from a file, and errors out if it fails to.
- * Not as a function to avoid overhead in the general case.
- * @param var The variable to stash the number into
- * @param file The file to read from. Its position will be advanced
- * @param ... A format string and related arguments; note that an extra string
- *            argument is provided, the reason for failure
- */
+// Helper macro for reading bytes from a file, and errors out if it fails to.
+// Not as a function to avoid overhead in the general case.
+// @param var The variable to stash the number into
+// @param file The file to read from. Its position will be advanced
+// @param ... A format string and related arguments; note that an extra string
+//            argument is provided, the reason for failure
 #define tryGetc(type, var, file, ...) tryRead(getc, int, EOF, type, var, file, __VA_ARGS__)
 
-/*
- * Helper macro for readings '\0'-terminated strings from a file, and errors out if it fails to.
- * Not as a function to avoid overhead in the general case.
- * @param var The variable to stash the string into
- * @param file The file to read from. Its position will be advanced
- * @param ... A format string and related arguments; note that an extra string
- *            argument is provided, the reason for failure
- */
+// Helper macro for readings '\0'-terminated strings from a file, and errors out if it fails to.
+// Not as a function to avoid overhead in the general case.
+// @param var The variable to stash the string into
+// @param file The file to read from. Its position will be advanced
+// @param ... A format string and related arguments; note that an extra string
+//            argument is provided, the reason for failure
 #define tryReadString(var, file, ...) \
 	do { \
 		FILE *tmpFile = file; \
@@ -112,13 +105,11 @@ static int64_t readLong(FILE *file) {
 
 // Functions to parse object files
 
-/*
- * Reads a file stack node form a file.
- * @param file The file to read from
- * @param nodes The file's array of nodes
- * @param i The ID of the node in the array
- * @param fileName The filename to report in errors
- */
+// Reads a file stack node form a file.
+// @param file The file to read from
+// @param nodes The file's array of nodes
+// @param i The ID of the node in the array
+// @param fileName The filename to report in errors
 static void readFileStackNode(
     FILE *file, std::vector<FileStackNode> &fileNodes, uint32_t i, char const *fileName
 ) {
@@ -151,7 +142,7 @@ static void readFileStackNode(
 	case NODE_REPT:
 		tryReadLong(depth, file, "%s: Cannot read node #%" PRIu32 "'s rept depth: %s", fileName, i);
 		node.data = std::vector<uint32_t>(depth);
-		for (uint32_t k = 0; k < depth; k++)
+		for (uint32_t k = 0; k < depth; k++) {
 			tryReadLong(
 			    node.iters()[k],
 			    file,
@@ -160,7 +151,8 @@ static void readFileStackNode(
 			    i,
 			    k
 			);
-		if (!node.parent)
+		}
+		if (!node.parent) {
 			fatal(
 			    nullptr,
 			    0,
@@ -168,15 +160,14 @@ static void readFileStackNode(
 			    fileName,
 			    i
 			);
+		}
 	}
 }
 
-/*
- * Reads a symbol from a file.
- * @param file The file to read from
- * @param symbol The symbol to fill
- * @param fileName The filename to report in errors
- */
+// Reads a symbol from a file.
+// @param file The file to read from
+// @param symbol The symbol to fill
+// @param fileName The filename to report in errors
 static void readSymbol(
     FILE *file, Symbol &symbol, char const *fileName, std::vector<FileStackNode> const &fileNodes
 ) {
@@ -229,13 +220,11 @@ static void readSymbol(
 	}
 }
 
-/*
- * Reads a patch from a file.
- * @param file The file to read from
- * @param patch The patch to fill
- * @param fileName The filename to report in errors
- * @param i The number of the patch to report in errors
- */
+// Reads a patch from a file.
+// @param file The file to read from
+// @param patch The patch to fill
+// @param fileName The filename to report in errors
+// @param i The number of the patch to report in errors
 static void readPatch(
     FILE *file,
     Patch &patch,
@@ -310,7 +299,7 @@ static void readPatch(
 	patch.rpnExpression.resize(rpnSize);
 	size_t nbElementsRead = fread(patch.rpnExpression.data(), 1, rpnSize, file);
 
-	if (nbElementsRead != rpnSize)
+	if (nbElementsRead != rpnSize) {
 		errx(
 		    "%s: Cannot read \"%s\"'s patch #%" PRIu32 "'s RPN expression: %s",
 		    fileName,
@@ -318,24 +307,21 @@ static void readPatch(
 		    i,
 		    feof(file) ? "Unexpected end of file" : strerror(errno)
 		);
+	}
 }
 
-/*
- * Sets a patch's pcSection from its pcSectionID.
- * @param patch The patch to fix
- */
+// Sets a patch's pcSection from its pcSectionID.
+// @param patch The patch to fix
 static void
     linkPatchToPCSect(Patch &patch, std::vector<std::unique_ptr<Section>> const &fileSections) {
 	patch.pcSection =
 	    patch.pcSectionID != UINT32_MAX ? fileSections[patch.pcSectionID].get() : nullptr;
 }
 
-/*
- * Reads a section from a file.
- * @param file The file to read from
- * @param section The section to fill
- * @param fileName The filename to report in errors
- */
+// Reads a section from a file.
+// @param file The file to read from
+// @param section The section to fill
+// @param fileName The filename to report in errors
 static void readSection(
     FILE *file, Section &section, char const *fileName, std::vector<FileStackNode> const &fileNodes
 ) {
@@ -356,8 +342,9 @@ static void readSection(
 	    section.name.c_str()
 	);
 	tryReadLong(tmp, file, "%s: Cannot read \"%s\"'s' size: %s", fileName, section.name.c_str());
-	if (tmp < 0 || tmp > UINT16_MAX)
+	if (tmp < 0 || tmp > UINT16_MAX) {
 		errx("\"%s\"'s section size ($%" PRIx32 ") is invalid", section.name.c_str(), tmp);
+	}
 	section.size = tmp;
 	section.offset = 0;
 	tryGetc(
@@ -368,12 +355,13 @@ static void readSection(
 	} else {
 		section.type = SectionType(type);
 	}
-	if (byte >> 7)
+	if (byte >> 7) {
 		section.modifier = SECTION_UNION;
-	else if (byte >> 6)
+	} else if (byte >> 6) {
 		section.modifier = SECTION_FRAGMENT;
-	else
+	} else {
 		section.modifier = SECTION_NORMAL;
+	}
 	tryReadLong(tmp, file, "%s: Cannot read \"%s\"'s org: %s", fileName, section.name.c_str());
 	section.isAddressFixed = tmp >= 0;
 	if (tmp > UINT16_MAX) {
@@ -392,8 +380,9 @@ static void readSection(
 	    fileName,
 	    section.name.c_str()
 	);
-	if (byte > 16)
+	if (byte > 16) {
 		byte = 16;
+	}
 	section.isAlignFixed = byte != 0;
 	section.alignMask = (1 << byte) - 1;
 	tryReadLong(
@@ -415,13 +404,14 @@ static void readSection(
 		if (section.size) {
 			section.data.resize(section.size);
 			if (size_t nbRead = fread(section.data.data(), 1, section.size, file);
-			    nbRead != section.size)
+			    nbRead != section.size) {
 				errx(
 				    "%s: Cannot read \"%s\"'s data: %s",
 				    fileName,
 				    section.name.c_str(),
 				    feof(file) ? "Unexpected end of file" : strerror(errno)
 				);
+			}
 		}
 
 		uint32_t nbPatches;
@@ -435,16 +425,15 @@ static void readSection(
 		);
 
 		section.patches.resize(nbPatches);
-		for (uint32_t i = 0; i < nbPatches; i++)
+		for (uint32_t i = 0; i < nbPatches; i++) {
 			readPatch(file, section.patches[i], fileName, section.name, i, fileNodes);
+		}
 	}
 }
 
-/*
- * Links a symbol to a section, keeping the section's symbol list sorted.
- * @param symbol The symbol to link
- * @param section The section to link
- */
+// Links a symbol to a section, keeping the section's symbol list sorted.
+// @param symbol The symbol to link
+// @param section The section to link
 static void linkSymToSect(Symbol &symbol, Section &section) {
 	uint32_t a = 0, b = section.symbols.size();
 	int32_t symbolOffset = symbol.label().offset;
@@ -453,21 +442,20 @@ static void linkSymToSect(Symbol &symbol, Section &section) {
 		uint32_t c = (a + b) / 2;
 		int32_t otherOffset = section.symbols[c]->label().offset;
 
-		if (otherOffset > symbolOffset)
+		if (otherOffset > symbolOffset) {
 			b = c;
-		else
+		} else {
 			a = c + 1;
+		}
 	}
 
 	section.symbols.insert(section.symbols.begin() + a, &symbol);
 }
 
-/*
- * Reads an assertion from a file
- * @param file The file to read from
- * @param assert The assertion to fill
- * @param fileName The filename to report in errors
- */
+// Reads an assertion from a file
+// @param file The file to read from
+// @param assert The assertion to fill
+// @param fileName The filename to report in errors
 static void readAssertion(
     FILE *file,
     Assertion &assert,
@@ -491,8 +479,9 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
 		(void)setmode(STDIN_FILENO, O_BINARY);
 		file = stdin;
 	}
-	if (!file)
+	if (!file) {
 		err("Failed to open file \"%s\"", fileName);
+	}
 	Defer closeFile{[&] { fclose(file); }};
 
 	// First, check if the object is a RGBDS object or a SDCC one. If the first byte is 'R',
@@ -528,15 +517,16 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
 	int matchedElems;
 
 	if (fscanf(file, RGBDS_OBJECT_VERSION_STRING "%n", &matchedElems) == 1
-	    && matchedElems != literal_strlen(RGBDS_OBJECT_VERSION_STRING))
+	    && matchedElems != literal_strlen(RGBDS_OBJECT_VERSION_STRING)) {
 		errx("%s: Not a RGBDS object file", fileName);
+	}
 
 	verbosePrint("Reading object file %s\n", fileName);
 
 	uint32_t revNum;
 
 	tryReadLong(revNum, file, "%s: Cannot read revision number: %s", fileName);
-	if (revNum != RGBDS_OBJECT_REV)
+	if (revNum != RGBDS_OBJECT_REV) {
 		errx(
 		    "%s: Unsupported object file for rgblink %s; try rebuilding \"%s\"%s"
 		    " (expected revision %d, got %d)",
@@ -547,6 +537,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
 		    RGBDS_OBJECT_REV,
 		    revNum
 		);
+	}
 
 	uint32_t nbNodes;
 	uint32_t nbSymbols;
@@ -560,8 +551,9 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
 	tryReadLong(nbNodes, file, "%s: Cannot read number of nodes: %s", fileName);
 	nodes[fileID].resize(nbNodes);
 	verbosePrint("Reading %u nodes...\n", nbNodes);
-	for (uint32_t i = nbNodes; i--;)
+	for (uint32_t i = nbNodes; i--;) {
 		readFileStackNode(file, nodes[fileID], i, fileName);
+	}
 
 	// This file's symbols, kept to link sections to them
 	std::vector<Symbol> &fileSymbols = symbolLists.emplace_front(nbSymbols);
@@ -575,8 +567,9 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
 		readSymbol(file, symbol, fileName, nodes[fileID]);
 
 		sym_AddSymbol(symbol);
-		if (symbol.data.holds<Label>())
+		if (symbol.data.holds<Label>()) {
 			nbSymPerSect[symbol.data.get<Label>().sectionID]++;
+		}
 	}
 
 	// This file's sections, stored in a table to link symbols to them
@@ -607,8 +600,9 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
 	// Give patches' PC section pointers to their sections
 	for (uint32_t i = 0; i < nbSections; i++) {
 		if (sect_HasData(fileSections[i]->type)) {
-			for (Patch &patch : fileSections[i]->patches)
+			for (Patch &patch : fileSections[i]->patches) {
 				linkPatchToPCSect(patch, fileSections);
+			}
 		}
 	}
 
@@ -623,8 +617,9 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
 	}
 
 	// Calling `sect_AddSection` invalidates the contents of `fileSections`!
-	for (uint32_t i = 0; i < nbSections; i++)
+	for (uint32_t i = 0; i < nbSections; i++) {
 		sect_AddSection(std::move(fileSections[i]));
+	}
 
 	// Fix symbols' section pointers to component sections
 	// This has to run **after** all the `sect_AddSection()` calls,
diff --git a/src/link/output.cpp b/src/link/output.cpp
index 45bb93e25..66f52389a 100644
--- a/src/link/output.cpp
+++ b/src/link/output.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "link/output.hpp"
 
@@ -66,24 +66,27 @@ void out_AddSection(Section const &section) {
 	uint32_t targetBank = section.bank - sectionTypeInfo[section.type].firstBank;
 	uint32_t minNbBanks = targetBank + 1;
 
-	if (minNbBanks > maxNbBanks[section.type])
+	if (minNbBanks > maxNbBanks[section.type]) {
 		errx(
 		    "Section \"%s\" has an invalid bank range (%" PRIu32 " > %" PRIu32 ")",
 		    section.name.c_str(),
 		    section.bank,
 		    maxNbBanks[section.type] - 1
 		);
+	}
 
-	for (uint32_t i = sections[section.type].size(); i < minNbBanks; i++)
+	for (uint32_t i = sections[section.type].size(); i < minNbBanks; i++) {
 		sections[section.type].emplace_back();
+	}
 
 	std::deque<Section const *> &bankSections =
 	    section.size ? sections[section.type][targetBank].sections
 	                 : sections[section.type][targetBank].zeroLenSections;
 	auto pos = bankSections.begin();
 
-	while (pos != bankSections.end() && (*pos)->org < section.org)
+	while (pos != bankSections.end() && (*pos)->org < section.org) {
 		pos++;
+	}
 
 	bankSections.insert(pos, &section);
 }
@@ -92,19 +95,19 @@ Section const *out_OverlappingSection(Section const &section) {
 	uint32_t bank = section.bank - sectionTypeInfo[section.type].firstBank;
 
 	for (Section const *ptr : sections[section.type][bank].sections) {
-		if (ptr->org < section.org + section.size && section.org < ptr->org + ptr->size)
+		if (ptr->org < section.org + section.size && section.org < ptr->org + ptr->size) {
 			return ptr;
+		}
 	}
 	return nullptr;
 }
 
-/*
- * Performs sanity checks on the overlay file.
- * @return The number of ROM banks in the overlay file
- */
+// Performs sanity checks on the overlay file.
+// @return The number of ROM banks in the overlay file
 static uint32_t checkOverlaySize() {
-	if (!overlayFile)
+	if (!overlayFile) {
 		return 0;
+	}
 
 	if (fseek(overlayFile, 0, SEEK_END) != 0) {
 		warnx("Overlay file is not seekable, cannot check if properly formed");
@@ -116,22 +119,21 @@ static uint32_t checkOverlaySize() {
 	// Reset back to beginning
 	fseek(overlayFile, 0, SEEK_SET);
 
-	if (overlaySize % BANK_SIZE)
+	if (overlaySize % BANK_SIZE) {
 		warnx("Overlay file does not have a size multiple of 0x4000");
-	else if (is32kMode && overlaySize != 0x8000)
+	} else if (is32kMode && overlaySize != 0x8000) {
 		warnx("Overlay is not exactly 0x8000 bytes large");
-	else if (overlaySize < 0x8000)
+	} else if (overlaySize < 0x8000) {
 		warnx("Overlay is less than 0x8000 bytes large");
+	}
 
 	return (overlaySize + BANK_SIZE - 1) / BANK_SIZE;
 }
 
-/*
- * Expand `sections[SECTTYPE_ROMX]` to cover all the overlay banks.
- * This ensures that `writeROM` will output each bank, even if some are not
- * covered by any sections.
- * @param nbOverlayBanks The number of banks in the overlay file
- */
+// Expand `sections[SECTTYPE_ROMX]` to cover all the overlay banks.
+// This ensures that `writeROM` will output each bank, even if some are not
+// covered by any sections.
+// @param nbOverlayBanks The number of banks in the overlay file
 static void coverOverlayBanks(uint32_t nbOverlayBanks) {
 	// 2 if is32kMode, 1 otherwise
 	uint32_t nbRom0Banks = sectionTypeInfo[SECTTYPE_ROM0].size / BANK_SIZE;
@@ -141,8 +143,9 @@ static void coverOverlayBanks(uint32_t nbOverlayBanks) {
 	                                : 0;
 
 	if (nbUncoveredBanks > sections[SECTTYPE_ROMX].size()) {
-		for (uint32_t i = sections[SECTTYPE_ROMX].size(); i < nbUncoveredBanks; i++)
+		for (uint32_t i = sections[SECTTYPE_ROMX].size(); i < nbUncoveredBanks; i++) {
 			sections[SECTTYPE_ROMX].emplace_back();
+		}
 	}
 }
 
@@ -162,12 +165,10 @@ static uint8_t getNextFillByte() {
 	return padValue;
 }
 
-/*
- * Write a ROM bank's sections to the output file.
- * @param bankSections The bank's sections, ordered by increasing address
- * @param baseOffset The address of the bank's first byte in GB address space
- * @param size The size of the bank
- */
+// Write a ROM bank's sections to the output file.
+// @param bankSections The bank's sections, ordered by increasing address
+// @param baseOffset The address of the bank's first byte in GB address space
+// @param size The size of the bank
 static void
     writeBank(std::deque<Section const *> *bankSections, uint16_t baseOffset, uint16_t size) {
 	uint16_t offset = 0;
@@ -185,8 +186,9 @@ static void
 			fwrite(section->data.data(), 1, section->size, outputFile);
 			if (overlayFile) {
 				// Skip bytes even with pipes
-				for (uint16_t i = 0; i < section->size; i++)
+				for (uint16_t i = 0; i < section->size; i++) {
 					getc(overlayFile);
+				}
 			}
 			offset += section->size;
 		}
@@ -210,12 +212,14 @@ static void writeROM() {
 			(void)setmode(STDOUT_FILENO, O_BINARY);
 			outputFile = stdout;
 		}
-		if (!outputFile)
+		if (!outputFile) {
 			err("Failed to open output file \"%s\"", outputFileName);
+		}
 	}
 	Defer closeOutputFile{[&] {
-		if (outputFile)
+		if (outputFile) {
 			fclose(outputFile);
+		}
 	}};
 
 	if (overlayFileName) {
@@ -226,18 +230,21 @@ static void writeROM() {
 			(void)setmode(STDIN_FILENO, O_BINARY);
 			overlayFile = stdin;
 		}
-		if (!overlayFile)
+		if (!overlayFile) {
 			err("Failed to open overlay file \"%s\"", overlayFileName);
+		}
 	}
 	Defer closeOverlayFile{[&] {
-		if (overlayFile)
+		if (overlayFile) {
 			fclose(overlayFile);
+		}
 	}};
 
 	uint32_t nbOverlayBanks = checkOverlaySize();
 
-	if (nbOverlayBanks > 0)
+	if (nbOverlayBanks > 0) {
 		coverOverlayBanks(nbOverlayBanks);
+	}
 
 	if (outputFile) {
 		writeBank(
@@ -246,12 +253,13 @@ static void writeROM() {
 		    sectionTypeInfo[SECTTYPE_ROM0].size
 		);
 
-		for (uint32_t i = 0; i < sections[SECTTYPE_ROMX].size(); i++)
+		for (uint32_t i = 0; i < sections[SECTTYPE_ROMX].size(); i++) {
 			writeBank(
 			    &sections[SECTTYPE_ROMX][i].sections,
 			    sectionTypeInfo[SECTTYPE_ROMX].startAddr,
 			    sectionTypeInfo[SECTTYPE_ROMX].size
 			);
+		}
 	}
 }
 
@@ -288,8 +296,9 @@ static void printSymName(std::string const &name, FILE *file) {
 					codepoint = 0xFFFD;
 					// Skip continuation bytes
 					// A NUL byte does not qualify, so we're good
-					while ((*ptr & 0xC0) == 0x80)
+					while ((*ptr & 0xC0) == 0x80) {
 						++ptr;
+					}
 					break;
 				}
 				++ptr;
@@ -303,8 +312,9 @@ static void printSymName(std::string const &name, FILE *file) {
 // Comparator function for `std::stable_sort` to sort symbols
 // Symbols are ordered by address, then by parentage
 static bool compareSymbols(SortedSymbol const &sym1, SortedSymbol const &sym2) {
-	if (sym1.addr != sym2.addr)
+	if (sym1.addr != sym2.addr) {
 		return sym1.addr < sym2.addr;
+	}
 
 	std::string const &sym1_name = sym1.sym->name;
 	std::string const &sym2_name = sym2.sym->name;
@@ -316,10 +326,12 @@ static bool compareSymbols(SortedSymbol const &sym1, SortedSymbol const &sym2) {
 		size_t sym2_len = sym2_name.length();
 
 		// Sort parent labels before their child local labels
-		if (sym2_name.starts_with(sym1_name) && sym2_name[sym1_len] == '.')
+		if (sym2_name.starts_with(sym1_name) && sym2_name[sym1_len] == '.') {
 			return true;
-		if (sym1_name.starts_with(sym2_name) && sym1_name[sym2_len] == '.')
+		}
+		if (sym1_name.starts_with(sym2_name) && sym1_name[sym2_len] == '.') {
 			return false;
+		}
 		// Sort local labels before unrelated global labels
 		return sym1_local;
 	}
@@ -327,22 +339,22 @@ static bool compareSymbols(SortedSymbol const &sym1, SortedSymbol const &sym2) {
 	return false;
 }
 
-/*
- * Write a bank's contents to the sym file
- * @param bankSections The bank's sections
- */
+// Write a bank's contents to the sym file
+// @param bankSections The bank's sections
 static void writeSymBank(SortedSections const &bankSections, SectionType type, uint32_t bank) {
 #define forEachSortedSection(sect, ...) \
 	do { \
 		for (auto it = bankSections.zeroLenSections.begin(); \
 		     it != bankSections.zeroLenSections.end(); \
 		     it++) { \
-			for (Section const *sect = *it; sect; sect = sect->nextu.get()) \
+			for (Section const *sect = *it; sect; sect = sect->nextu.get()) { \
 				__VA_ARGS__ \
+			} \
 		} \
 		for (auto it = bankSections.sections.begin(); it != bankSections.sections.end(); it++) { \
-			for (Section const *sect = *it; sect; sect = sect->nextu.get()) \
+			for (Section const *sect = *it; sect; sect = sect->nextu.get()) { \
 				__VA_ARGS__ \
+			} \
 		} \
 	} while (0)
 
@@ -350,8 +362,9 @@ static void writeSymBank(SortedSections const &bankSections, SectionType type, u
 
 	forEachSortedSection(sect, { nbSymbols += sect->symbols.size(); });
 
-	if (!nbSymbols)
+	if (!nbSymbols) {
 		return;
+	}
 
 	std::vector<SortedSymbol> symList;
 
@@ -360,11 +373,12 @@ static void writeSymBank(SortedSections const &bankSections, SectionType type, u
 	forEachSortedSection(sect, {
 		for (Symbol const *sym : sect->symbols) {
 			// Don't output symbols that begin with an illegal character
-			if (!sym->name.empty() && canStartSymName(sym->name[0]))
+			if (!sym->name.empty() && canStartSymName(sym->name[0])) {
 				symList.push_back({
 				    .sym = sym,
 				    .addr = static_cast<uint16_t>(sym->label().offset + sect->org),
 				});
+			}
 		}
 	});
 
@@ -421,9 +435,7 @@ static void printSectionName(std::string const &name, FILE *file) {
 	}
 }
 
-/*
- * Write a bank's contents to the map file
- */
+// Write a bank's contents to the map file
 static void writeMapBank(SortedSections const &sectList, SectionType type, uint32_t bank) {
 	fprintf(
 	    mapFile,
@@ -453,8 +465,9 @@ static void writeMapBank(SortedSections const &sectList, SectionType type, uint3
 		prevEndAddr = sect->org + sect->size;
 
 		fprintf(mapFile, "\tSECTION: $%04" PRIx16, sect->org);
-		if (sect->size != 0)
+		if (sect->size != 0) {
 			fprintf(mapFile, "-$%04x", prevEndAddr - 1);
+		}
 		fprintf(mapFile, " ($%04" PRIx16 " byte%s) [\"", sect->size, sect->size == 1 ? "" : "s");
 		printSectionName(sect->name, mapFile);
 		fputs("\"]\n", mapFile);
@@ -471,10 +484,11 @@ static void writeMapBank(SortedSections const &sectList, SectionType type, uint3
 
 				if (sect->nextu) {
 					// Announce the following "piece"
-					if (sect->nextu->modifier == SECTION_UNION)
+					if (sect->nextu->modifier == SECTION_UNION) {
 						fprintf(mapFile, "\t         ; Next union\n");
-					else if (sect->nextu->modifier == SECTION_FRAGMENT)
+					} else if (sect->nextu->modifier == SECTION_FRAGMENT) {
 						fprintf(mapFile, "\t         ; Next fragment\n");
+					}
 				}
 			}
 		}
@@ -495,9 +509,7 @@ static void writeMapBank(SortedSections const &sectList, SectionType type, uint3
 	}
 }
 
-/*
- * Write the total used and free space by section type to the map file
- */
+// Write the total used and free space by section type to the map file
 static void writeMapSummary() {
 	fputs("SUMMARY:\n", mapFile);
 
@@ -506,12 +518,14 @@ static void writeMapSummary() {
 		uint32_t nbBanks = sections[type].size();
 
 		// Do not output used space for VRAM or OAM
-		if (type == SECTTYPE_VRAM || type == SECTTYPE_OAM)
+		if (type == SECTTYPE_VRAM || type == SECTTYPE_OAM) {
 			continue;
+		}
 
 		// Do not output unused section types
-		if (nbBanks == 0)
+		if (nbBanks == 0) {
 			continue;
+		}
 
 		uint32_t usedTotal = 0;
 
@@ -544,16 +558,18 @@ static void writeMapSummary() {
 		    usedTotal == 1 ? "" : "s",
 		    nbBanks * sectionTypeInfo[type].size - usedTotal
 		);
-		if (sectionTypeInfo[type].firstBank != sectionTypeInfo[type].lastBank || nbBanks > 1)
+		if (sectionTypeInfo[type].firstBank != sectionTypeInfo[type].lastBank || nbBanks > 1) {
 			fprintf(mapFile, " in %u bank%s", nbBanks, nbBanks == 1 ? "" : "s");
+		}
 		putc('\n', mapFile);
 	}
 }
 
 // Writes the sym file, if applicable.
 static void writeSym() {
-	if (!symFileName)
+	if (!symFileName) {
 		return;
+	}
 
 	if (strcmp(symFileName, "-")) {
 		symFile = fopen(symFileName, "w");
@@ -562,8 +578,9 @@ static void writeSym() {
 		(void)setmode(STDOUT_FILENO, O_TEXT); // May have been set to O_BINARY previously
 		symFile = stdout;
 	}
-	if (!symFile)
+	if (!symFile) {
 		err("Failed to open sym file \"%s\"", symFileName);
+	}
 	Defer closeSymFile{[&] { fclose(symFile); }};
 
 	fputs("; File generated by rgblink\n", symFile);
@@ -571,8 +588,9 @@ static void writeSym() {
 	for (uint8_t i = 0; i < SECTTYPE_INVALID; i++) {
 		SectionType type = typeMap[i];
 
-		for (uint32_t bank = 0; bank < sections[type].size(); bank++)
+		for (uint32_t bank = 0; bank < sections[type].size(); bank++) {
 			writeSymBank(sections[type][bank], type, bank);
+		}
 	}
 
 	// Output the exported numeric constants
@@ -580,8 +598,9 @@ static void writeSym() {
 	constants.clear();
 	sym_ForEach([](Symbol &sym) {
 		// Symbols are already limited to the exported ones
-		if (sym.data.holds<int32_t>())
+		if (sym.data.holds<int32_t>()) {
 			constants.push_back(&sym);
+		}
 	});
 	// Numeric constants are ordered by value, then by name
 	std::sort(RANGE(constants), [](Symbol *sym1, Symbol *sym2) -> bool {
@@ -599,8 +618,9 @@ static void writeSym() {
 
 // Writes the map file, if applicable.
 static void writeMap() {
-	if (!mapFileName)
+	if (!mapFileName) {
 		return;
+	}
 
 	if (strcmp(mapFileName, "-")) {
 		mapFile = fopen(mapFileName, "w");
@@ -609,8 +629,9 @@ static void writeMap() {
 		(void)setmode(STDOUT_FILENO, O_TEXT); // May have been set to O_BINARY previously
 		mapFile = stdout;
 	}
-	if (!mapFile)
+	if (!mapFile) {
 		err("Failed to open map file \"%s\"", mapFileName);
+	}
 	Defer closeMapFile{[&] { fclose(mapFile); }};
 
 	writeMapSummary();
@@ -618,8 +639,9 @@ static void writeMap() {
 	for (uint8_t i = 0; i < SECTTYPE_INVALID; i++) {
 		SectionType type = typeMap[i];
 
-		for (uint32_t bank = 0; bank < sections[type].size(); bank++)
+		for (uint32_t bank = 0; bank < sections[type].size(); bank++) {
 			writeMapBank(sections[type][bank], type, bank);
+		}
 	}
 }
 
diff --git a/src/link/patch.cpp b/src/link/patch.cpp
index e12e767b7..c474e4518 100644
--- a/src/link/patch.cpp
+++ b/src/link/patch.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "link/patch.hpp"
 
@@ -33,8 +33,9 @@ static void pushRPN(int32_t value, bool comesFromError) {
 static bool isError = false;
 
 static int32_t popRPN(Patch const &patch) {
-	if (rpnStack.empty())
+	if (rpnStack.empty()) {
 		fatal(patch.src, patch.lineNo, "Internal error, RPN stack empty");
+	}
 
 	RPNStackEntry entry = rpnStack.front();
 
@@ -46,8 +47,9 @@ static int32_t popRPN(Patch const &patch) {
 // RPN operators
 
 static uint32_t getRPNByte(uint8_t const *&expression, int32_t &size, Patch const &patch) {
-	if (!size--)
+	if (!size--) {
 		fatal(patch.src, patch.lineNo, "Internal error, RPN expression overread");
+	}
 
 	return *expression++;
 }
@@ -57,20 +59,19 @@ static Symbol const *getSymbol(std::vector<Symbol> const &symbolList, uint32_t i
 	Symbol const &symbol = symbolList[index];
 
 	// If the symbol is defined elsewhere...
-	if (symbol.type == SYMTYPE_IMPORT)
+	if (symbol.type == SYMTYPE_IMPORT) {
 		return sym_GetSymbol(symbol.name);
+	}
 
 	return &symbol;
 }
 
-/*
- * Compute a patch's value from its RPN string.
- * @param patch The patch to compute the value of
- * @param section The section the patch is contained in
- * @return The patch's value
- * @return isError Set if an error occurred during evaluation, and further
- *                 errors caused by the value should be suppressed.
- */
+// Compute a patch's value from its RPN string.
+// @param patch The patch to compute the value of
+// @param section The section the patch is contained in
+// @return The patch's value
+// @return isError Set if an error occurred during evaluation, and further
+//                 errors caused by the value should be suppressed.
 static int32_t computeRPNExpr(Patch const &patch, std::vector<Symbol> const &fileSymbols) {
 	uint8_t const *expression = patch.rpnExpression.data();
 	int32_t size = static_cast<int32_t>(patch.rpnExpression.size());
@@ -220,8 +221,9 @@ static int32_t computeRPNExpr(Patch const &patch, std::vector<Symbol> const &fil
 
 		case RPN_BANK_SYM:
 			value = 0;
-			for (uint8_t shift = 0; shift < 32; shift += 8)
+			for (uint8_t shift = 0; shift < 32; shift += 8) {
 				value |= getRPNByte(expression, size, patch) << shift;
+			}
 
 			if (Symbol const *symbol = getSymbol(fileSymbols, value); !symbol) {
 				error(
@@ -379,14 +381,16 @@ static int32_t computeRPNExpr(Patch const &patch, std::vector<Symbol> const &fil
 
 		case RPN_CONST:
 			value = 0;
-			for (uint8_t shift = 0; shift < 32; shift += 8)
+			for (uint8_t shift = 0; shift < 32; shift += 8) {
 				value |= getRPNByte(expression, size, patch) << shift;
+			}
 			break;
 
 		case RPN_SYM:
 			value = 0;
-			for (uint8_t shift = 0; shift < 32; shift += 8)
+			for (uint8_t shift = 0; shift < 32; shift += 8) {
 				value |= getRPNByte(expression, size, patch) << shift;
+			}
 
 			if (value == -1) { // PC
 				if (!patch.pcSection) {
@@ -419,8 +423,9 @@ static int32_t computeRPNExpr(Patch const &patch, std::vector<Symbol> const &fil
 		pushRPN(value, isError);
 	}
 
-	if (rpnStack.size() > 1)
+	if (rpnStack.size() > 1) {
 		error(patch.src, patch.lineNo, "RPN stack has %zu entries on exit, not 1", rpnStack.size());
+	}
 
 	isError = false;
 	return popRPN(patch);
@@ -471,11 +476,9 @@ void patch_CheckAssertions() {
 	}
 }
 
-/*
- * Applies all of a section's patches
- * @param section The section component to patch
- * @param dataSection The section to patch
- */
+// Applies all of a section's patches
+// @param section The section component to patch
+// @param dataSection The section to patch
 static void applyFilePatches(Section &section, Section &dataSection) {
 	verbosePrint("Patching section \"%s\"...\n", section.name.c_str());
 	for (Patch &patch : section.patches) {
@@ -509,7 +512,7 @@ static void applyFilePatches(Section &section, Section &dataSection) {
 			uint16_t address = patch.pcSection->org + patch.pcOffset + 2;
 			int16_t jumpOffset = value - address;
 
-			if (!isError && (jumpOffset < -128 || jumpOffset > 127))
+			if (!isError && (jumpOffset < -128 || jumpOffset > 127)) {
 				error(
 				    patch.src,
 				    patch.lineNo,
@@ -517,10 +520,11 @@ static void applyFilePatches(Section &section, Section &dataSection) {
 				    "; use jp instead\n",
 				    jumpOffset
 				);
+			}
 			dataSection.data[offset] = jumpOffset & 0xFF;
 		} else {
 			// Patch a certain number of bytes
-			if (!isError && (value < type.min || value > type.max))
+			if (!isError && (value < type.min || value > type.max)) {
 				error(
 				    patch.src,
 				    patch.lineNo,
@@ -529,6 +533,7 @@ static void applyFilePatches(Section &section, Section &dataSection) {
 				    value < 0 ? " (maybe negative?)" : "",
 				    type.size * 8U
 				);
+			}
 			for (uint8_t i = 0; i < type.size; i++) {
 				dataSection.data[offset + i] = value & 0xFF;
 				value >>= 8;
@@ -537,16 +542,16 @@ static void applyFilePatches(Section &section, Section &dataSection) {
 	}
 }
 
-/*
- * Applies all of a section's patches, iterating over "components" of unionized sections
- * @param section The section to patch
- */
+// Applies all of a section's patches, iterating over "components" of unionized sections
+// @param section The section to patch
 static void applyPatches(Section &section) {
-	if (!sect_HasData(section.type))
+	if (!sect_HasData(section.type)) {
 		return;
+	}
 
-	for (Section *component = &section; component; component = component->nextu.get())
+	for (Section *component = &section; component; component = component->nextu.get()) {
 		applyFilePatches(*component, section);
+	}
 }
 
 void patch_ApplyPatches() {
diff --git a/src/link/script.y b/src/link/script.y
index a534877fc..a33ccf3ca 100644
--- a/src/link/script.y
+++ b/src/link/script.y
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 %language "c++"
 %define api.value.type variant
@@ -12,6 +12,7 @@
 
 	void script_ProcessScript(char const *path);
 }
+
 %code {
 	#include <algorithm>
 	#include <array>
@@ -394,7 +395,8 @@ static void setActiveTypeAndIdx(SectionType type, uint32_t idx) {
 
 static void setFloatingSectionType(SectionType type) {
 	if (nbbanks(type) == 1) {
-		setActiveTypeAndIdx(type, 0); // There is only a single bank anyway, so just set the index to 0.
+		// There is only a single bank anyway, so just set the index to 0.
+		setActiveTypeAndIdx(type, 0);
 	} else {
 		activeType = type;
 		activeBankIdx = UINT32_MAX;
@@ -634,7 +636,8 @@ static void placeSection(std::string const &name, bool isOptional) {
 			    typeInfo.name.c_str()
 			);
 		} else {
-			// SDCC areas don't have a type assigned yet, so the linker script is used to give them one.
+			// SDCC areas don't have a type assigned yet, so the linker script is used to give them
+			// one.
 			for (Section *fragment = section; fragment; fragment = fragment->nextu.get()) {
 				fragment->type = activeType;
 			}
diff --git a/src/link/sdas_obj.cpp b/src/link/sdas_obj.cpp
index b8f6c15fd..e0620f8e7 100644
--- a/src/link/sdas_obj.cpp
+++ b/src/link/sdas_obj.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "link/sdas_obj.hpp"
 
@@ -25,8 +25,9 @@ enum NumberType {
 };
 
 static void consumeLF(FileStackNode const &where, uint32_t lineNo, FILE *file) {
-	if (getc(file) != '\n')
+	if (getc(file) != '\n') {
 		fatal(&where, lineNo, "Bad line ending (CR without LF)");
+	}
 }
 
 static char const *delim = " \f\n\r\t\v"; // Whitespace according to the C and POSIX locales
@@ -49,8 +50,9 @@ static int
 		} while (firstChar != EOF && firstChar != '\r' && firstChar != '\n');
 		[[fallthrough]];
 	case '\r':
-		if (firstChar == '\r' && getc(file) != '\n')
+		if (firstChar == '\r' && getc(file) != '\n') {
 			consumeLF(where, lineNo, file);
+		}
 		[[fallthrough]];
 	case '\n':
 		goto retry;
@@ -90,14 +92,16 @@ static uint32_t readNumber(char const *str, char const *&endptr, NumberType base
 
 static uint32_t
     parseNumber(FileStackNode const &where, uint32_t lineNo, char const *str, NumberType base) {
-	if (str[0] == '\0')
+	if (str[0] == '\0') {
 		fatal(&where, lineNo, "Expected number, got empty string");
+	}
 
 	char const *endptr;
 	uint32_t res = readNumber(str, endptr, base);
 
-	if (*endptr != '\0')
+	if (*endptr != '\0') {
 		fatal(&where, lineNo, "Expected number, got \"%s\"", str);
+	}
 	return res;
 }
 
@@ -105,8 +109,9 @@ static uint8_t
     parseByte(FileStackNode const &where, uint32_t lineNo, char const *str, NumberType base) {
 	uint32_t num = parseNumber(where, lineNo, str, base);
 
-	if (num > UINT8_MAX)
+	if (num > UINT8_MAX) {
 		fatal(&where, lineNo, "\"%s\" is not a byte", str);
+	}
 	return num;
 }
 
@@ -143,19 +148,21 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 #define getToken(ptr, ...) \
 	do { \
 		token = strtok((ptr), delim); \
-		if (!token) \
+		if (!token) { \
 			fatal(&where, lineNo, __VA_ARGS__); \
+		} \
 	} while (0)
 #define expectEol(...) \
 	do { \
 		token = strtok(nullptr, delim); \
-		if (token) \
+		if (token) { \
 			fatal(&where, lineNo, __VA_ARGS__); \
+		} \
 	} while (0)
 #define expectToken(expected, lineType) \
 	do { \
 		getToken(nullptr, "'%c' line is too short", (lineType)); \
-		if (strcasecmp(token, (expected)) != 0) \
+		if (strcasecmp(token, (expected)) != 0) { \
 			fatal( \
 			    &where, \
 			    lineNo, \
@@ -164,6 +171,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 			    (expected), \
 			    token \
 			); \
+		} \
 	} while (0)
 
 	uint32_t lineNo = 0;
@@ -203,17 +211,20 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 
 	static constexpr uint8_t ADDR_SIZE = 3;
 
-	if (line[1] != '0' + ADDR_SIZE)
+	if (line[1] != '0' + ADDR_SIZE) {
 		fatal(&where, lineNo, "Unknown or unsupported address size '%c'", line[1]);
+	}
 
-	if (line[2] != '\0')
+	if (line[2] != '\0') {
 		warning(&where, lineNo, "Ignoring unknown characters (\"%s\") in first line", &line[2]);
+	}
 
 	// Header line
 
 	lineType = nextLine(line, lineNo, where, file);
-	if (lineType != 'H')
+	if (lineType != 'H') {
 		fatal(&where, lineNo, "Expected header line, got '%c' line", lineType);
+	}
 	// Expected format: "A areas S global symbols"
 
 	getToken(line.data(), "Empty 'H' line");
@@ -242,8 +253,9 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 
 	for (;;) {
 		lineType = nextLine(line, lineNo, where, file);
-		if (lineType == EOF)
+		if (lineType == EOF) {
 			break;
+		}
 		switch (lineType) {
 		case 'M': // Module name
 		case 'O': // Assembler flags
@@ -251,10 +263,11 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 			break;
 
 		case 'A': {
-			if (fileSections.size() == expectedNbAreas)
+			if (fileSections.size() == expectedNbAreas) {
 				warning(
 				    &where, lineNo, "Got more 'A' lines than the expected %" PRIu32, expectedNbAreas
 				);
+			}
 			std::unique_ptr<Section> curSection = std::make_unique<Section>();
 
 			curSection->src = &where;
@@ -264,8 +277,9 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 			assume(strlen(token) != 0); // This should be impossible, tokens are non-empty
 			// The following is required for fragment offsets to be reliably predicted
 			for (FileSection &entry : fileSections) {
-				if (!strcmp(token, entry.section->name.c_str()))
+				if (!strcmp(token, entry.section->name.c_str())) {
 					fatal(&where, lineNo, "Area \"%s\" already defined earlier", token);
+				}
 			}
 			char const *sectName = token; // We'll deal with the section's name depending on type
 
@@ -275,21 +289,23 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 
 			uint32_t tmp = parseNumber(where, lineNo, token, numberType);
 
-			if (tmp > UINT16_MAX)
+			if (tmp > UINT16_MAX) {
 				fatal(
 				    &where,
 				    lineNo,
 				    "Area \"%s\" is larger than the GB address space!?",
 				    curSection->name.c_str()
 				);
+			}
 			curSection->size = tmp;
 
 			expectToken("flags", 'A');
 
 			getToken(nullptr, "'A' line is too short");
 			tmp = parseNumber(where, lineNo, token, numberType);
-			if (tmp & (1 << AREA_PAGING))
+			if (tmp & (1 << AREA_PAGING)) {
 				fatal(&where, lineNo, "Internal error: paging is not supported");
+			}
 			curSection->isAddressFixed = tmp & (1 << AREA_ISABS);
 			curSection->isBankFixed = curSection->isAddressFixed;
 			curSection->modifier = curSection->isAddressFixed || (tmp & (1 << AREA_TYPE))
@@ -430,11 +446,13 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 				// It's fine to keep modifying the symbol after `AddSymbol`, only
 				// the name must not be modified
 			}
-			if (strncasecmp(&token[1], "ef", 2) != 0)
+			if (strncasecmp(&token[1], "ef", 2) != 0) {
 				fatal(&where, lineNo, "'S' line is neither \"Def\" nor \"Ref\"");
+			}
 
-			if (!fileSections.empty())
+			if (!fileSections.empty()) {
 				fileSections.back().section->symbols.push_back(&symbol);
+			}
 
 			expectEol("'S' line is too long");
 			break;
@@ -442,15 +460,18 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 
 		case 'T':
 			// Now, time to parse the data!
-			if (!data.empty())
+			if (!data.empty()) {
 				warning(&where, lineNo, "Previous 'T' line had no 'R' line (ignored)");
+			}
 
 			data.clear();
-			for (token = strtok(line.data(), delim); token; token = strtok(nullptr, delim))
+			for (token = strtok(line.data(), delim); token; token = strtok(nullptr, delim)) {
 				data.push_back(parseByte(where, lineNo, token, numberType));
+			}
 
-			if (data.size() < ADDR_SIZE)
+			if (data.size() < ADDR_SIZE) {
 				fatal(&where, lineNo, "'T' line is too short");
+			}
 			// Importantly, now we know that there is "pending data" in `data`
 			break;
 
@@ -470,7 +491,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 			areaIdx = parseByte(where, lineNo, token, numberType);
 			getToken(nullptr, "'R' line is too short");
 			areaIdx |= static_cast<uint16_t>(parseByte(where, lineNo, token, numberType)) << 8;
-			if (areaIdx >= fileSections.size())
+			if (areaIdx >= fileSections.size()) {
 				fatal(
 				    &where,
 				    lineNo,
@@ -478,6 +499,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 				    areaIdx,
 				    fileSections.size()
 				);
+			}
 			assume(!fileSections.empty()); // There should be at least one, from the above check
 			Section *section = fileSections[areaIdx].section.get();
 			uint16_t *writeIndex = &fileSections[areaIdx].writeIndex;
@@ -485,7 +507,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 			uint16_t addr = data[0] | data[1] << 8;
 
 			if (section->isAddressFixed) {
-				if (addr < section->org)
+				if (addr < section->org) {
 					fatal(
 					    &where,
 					    lineNo,
@@ -495,12 +517,13 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 					    section->name.c_str(),
 					    section->org
 					);
+				}
 				addr -= section->org;
 			}
 			// Lines are emitted that violate this check but contain no "payload";
 			// ignore those. "Empty" lines shouldn't trigger allocation, either.
 			if (data.size() != ADDR_SIZE) {
-				if (addr != *writeIndex)
+				if (addr != *writeIndex) {
 					fatal(
 					    &where,
 					    lineNo,
@@ -509,6 +532,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 					    addr,
 					    *writeIndex
 					);
+				}
 				if (section->data.empty()) {
 					assume(section->size != 0);
 					section->data.resize(section->size);
@@ -541,7 +565,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 				getToken(nullptr, "Incomplete relocation");
 				uint8_t offset = parseByte(where, lineNo, token, numberType);
 
-				if (offset < ADDR_SIZE)
+				if (offset < ADDR_SIZE) {
 					fatal(
 					    &where,
 					    lineNo,
@@ -549,7 +573,8 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 					    offset,
 					    ADDR_SIZE
 					);
-				if (offset >= data.size())
+				}
+				if (offset >= data.size()) {
 					fatal(
 					    &where,
 					    lineNo,
@@ -557,6 +582,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 					    offset,
 					    data.size()
 					);
+				}
 
 				getToken(nullptr, "Incomplete relocation");
 				uint16_t idx = parseByte(where, lineNo, token, numberType);
@@ -565,10 +591,12 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 				idx |= static_cast<uint16_t>(parseByte(where, lineNo, token, numberType));
 
 				// Loudly fail on unknown flags
-				if (flags & (1 << RELOC_ZPAGE | 1 << RELOC_NPAGE))
+				if (flags & (1 << RELOC_ZPAGE | 1 << RELOC_NPAGE)) {
 					fatal(&where, lineNo, "Paging flags are not supported");
-				if (flags & ~RELOC_ALL_FLAGS)
+				}
+				if (flags & ~RELOC_ALL_FLAGS) {
 					warning(&where, lineNo, "Unknown reloc flags 0x%x", flags & ~RELOC_ALL_FLAGS);
+				}
 
 				// Turn this into a Patch
 				Patch &patch = section->patches.emplace_back();
@@ -578,7 +606,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 				patch.offset = offset - writtenOfs + *writeIndex;
 				if (section->patches.size() > 1) {
 					uint32_t prevOffset = section->patches[section->patches.size() - 2].offset;
-					if (prevOffset >= patch.offset)
+					if (prevOffset >= patch.offset) {
 						fatal(
 						    &where,
 						    lineNo,
@@ -587,6 +615,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 						    prevOffset,
 						    patch.offset
 						);
+					}
 				}
 				patch.pcSection = section;         // No need to fill `pcSectionID`, then
 				patch.pcOffset = patch.offset - 1; // For `jr`s
@@ -596,7 +625,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 				uint32_t baseValue = 0;
 
 				assume(offset < data.size());
-				if (data.size() - offset < nbBaseBytes)
+				if (data.size() - offset < nbBaseBytes) {
 					fatal(
 					    &where,
 					    lineNo,
@@ -604,13 +633,15 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 					    nbBaseBytes,
 					    data.size() - offset
 					);
-				for (uint8_t i = 0; i < nbBaseBytes; ++i)
+				}
+				for (uint8_t i = 0; i < nbBaseBytes; ++i) {
 					baseValue = baseValue | data[offset + i] << (8 * i);
+				}
 
 				// Bit 4 specifies signedness, but I don't think that matters?
 				// Generate a RPN expression from the info and flags
 				if (flags & 1 << RELOC_ISSYM) {
-					if (idx >= fileSymbols.size())
+					if (idx >= fileSymbols.size()) {
 						fatal(
 						    &where,
 						    lineNo,
@@ -618,6 +649,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 						    idx,
 						    fileSymbols.size()
 						);
+					}
 					Symbol const &sym = fileSymbols[idx];
 
 					// SDCC has a bunch of "magic symbols" that start with a
@@ -627,10 +659,11 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 						// Look for the symbol being referenced, and use its index instead
 						for (idx = 0; idx < fileSymbols.size(); ++idx) {
 							if (sym.name.ends_with(fileSymbols[idx].name)
-							    && 1 + sym.name.length() == fileSymbols[idx].name.length())
+							    && 1 + sym.name.length() == fileSymbols[idx].name.length()) {
 								break;
+							}
 						}
-						if (idx == fileSymbols.size())
+						if (idx == fileSymbols.size()) {
 							fatal(
 							    &where,
 							    lineNo,
@@ -638,6 +671,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 							    sym.name.c_str(),
 							    &sym.name.c_str()[1]
 							);
+						}
 						patch.rpnExpression.resize(5);
 						patch.rpnExpression[0] = RPN_BANK_SYM;
 						patch.rpnExpression[1] = idx;
@@ -669,7 +703,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 						patch.rpnExpression[4] = idx >> 24;
 					}
 				} else {
-					if (idx >= fileSections.size())
+					if (idx >= fileSections.size()) {
 						fatal(
 						    &where,
 						    lineNo,
@@ -677,6 +711,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 						    idx,
 						    fileSections.size()
 						);
+					}
 					// It gets funky. If the area is absolute, *actually*, we
 					// must not add its base address, as the assembler will
 					// already have added it in `baseValue`.
@@ -684,8 +719,9 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 					// address from `baseValue`, undoing what the assembler did;
 					// this allows the relocation to still be correct, even if
 					// the section gets moved for any reason.
-					if (fileSections[idx].section->isAddressFixed)
+					if (fileSections[idx].section->isAddressFixed) {
 						baseValue -= fileSections[idx].section->org;
+					}
 					std::string const &name = fileSections[idx].section->name;
 					Section const *other = sect_GetSection(name);
 
@@ -697,8 +733,9 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 					// so this fragment will be appended to the existing section
 					// *if any*, and thus its offset will be the section's
 					// current size.
-					if (other)
+					if (other) {
 						baseValue += other->size;
+					}
 					patch.rpnExpression.resize(1 + name.length() + 1);
 					patch.rpnExpression[0] = RPN_STARTOF_SECT;
 					// The cast is fine, it's just different signedness
@@ -720,7 +757,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 					// Despite the flag's name, as soon as it is set, 3 bytes
 					// are present, so we must skip two of them
 					if (flags & 1 << RELOC_EXPR16) {
-						if (*writeIndex + (offset - writtenOfs) > section->size)
+						if (*writeIndex + (offset - writtenOfs) > section->size) {
 							fatal(
 							    &where,
 							    lineNo,
@@ -729,6 +766,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 							    *writeIndex + (offset - writtenOfs),
 							    section->size
 							);
+						}
 						// Copy all bytes up to those (plus the byte that we'll overwrite)
 						memcpy(
 						    &section->data[*writeIndex], &data[writtenOfs], offset - writtenOfs + 1
@@ -785,7 +823,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 			// If there is some data left to append, do so
 			if (writtenOfs != data.size()) {
 				assume(data.size() > writtenOfs);
-				if (*writeIndex + (data.size() - writtenOfs) > section->size)
+				if (*writeIndex + (data.size() - writtenOfs) > section->size) {
 					fatal(
 					    &where,
 					    lineNo,
@@ -794,6 +832,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 					    *writeIndex + (data.size() - writtenOfs),
 					    section->size
 					);
+				}
 				memcpy(&section->data[*writeIndex], &data[writtenOfs], data.size() - writtenOfs);
 				*writeIndex += data.size() - writtenOfs;
 			}
@@ -813,9 +852,10 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 #undef expectToken
 #undef getToken
 
-	if (!data.empty())
+	if (!data.empty()) {
 		warning(&where, lineNo, "Last 'T' line had no 'R' line (ignored)");
-	if (fileSections.size() < expectedNbAreas)
+	}
+	if (fileSections.size() < expectedNbAreas) {
 		warning(
 		    &where,
 		    lineNo,
@@ -823,7 +863,8 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 		    expectedNbAreas,
 		    fileSections.size()
 		);
-	if (fileSymbols.size() < expectedNbSymbols)
+	}
+	if (fileSymbols.size() < expectedNbSymbols) {
 		warning(
 		    &where,
 		    lineNo,
@@ -831,6 +872,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
 		    expectedNbSymbols,
 		    fileSymbols.size()
 		);
+	}
 
 	nbSectionsToAssign += fileSections.size();
 
diff --git a/src/link/section.cpp b/src/link/section.cpp
index 4c084b85c..189726a6f 100644
--- a/src/link/section.cpp
+++ b/src/link/section.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "link/section.hpp"
 
@@ -14,8 +14,9 @@ std::vector<std::unique_ptr<Section>> sectionList;
 std::unordered_map<std::string, size_t> sectionMap; // Indexes into `sectionList`
 
 void sect_ForEach(void (*callback)(Section &)) {
-	for (auto &ptr : sectionList)
+	for (auto &ptr : sectionList) {
 		callback(*ptr);
+	}
 }
 
 static void checkAgainstFixedAddress(Section const &target, Section const &other, uint16_t org) {
@@ -117,8 +118,9 @@ static void checkFragmentCompat(Section &target, Section &other) {
 		target.org = org;
 	} else if (other.isAlignFixed) {
 		int32_t ofs = (other.alignOfs - target.size) % (other.alignMask + 1);
-		if (ofs < 0)
+		if (ofs < 0) {
 			ofs += other.alignMask + 1;
+		}
 		if (checkAgainstFixedAlign(target, other, ofs)) {
 			target.isAlignFixed = true;
 			target.alignMask = other.alignMask;
@@ -183,8 +185,9 @@ static void mergeSections(Section &target, std::unique_ptr<Section> &&other) {
 	switch (other->modifier) {
 	case SECTION_UNION:
 		checkSectUnionCompat(target, *other);
-		if (other->size > target.size)
+		if (other->size > target.size) {
 			target.size = other->size;
+		}
 		break;
 
 	case SECTION_FRAGMENT:
@@ -196,8 +199,9 @@ static void mergeSections(Section &target, std::unique_ptr<Section> &&other) {
 		if (!other->data.empty()) {
 			target.data.insert(target.data.end(), RANGE(other->data));
 			// Adjust patches' PC offsets
-			for (Patch &patch : other->patches)
+			for (Patch &patch : other->patches) {
 				patch.pcOffset += other->offset;
+			}
 		} else if (!target.data.empty()) {
 			assume(other->size == 0);
 		}
@@ -250,37 +254,41 @@ static void doSanityChecks(Section &section) {
 	}
 
 	if (is32kMode && section.type == SECTTYPE_ROMX) {
-		if (section.isBankFixed && section.bank != 1)
+		if (section.isBankFixed && section.bank != 1) {
 			error(
 			    nullptr,
 			    0,
 			    "%s: ROMX sections must be in bank 1 (if any) with option -t",
 			    section.name.c_str()
 			);
-		else
+		} else {
 			section.type = SECTTYPE_ROM0;
+		}
 	}
 	if (isWRAM0Mode && section.type == SECTTYPE_WRAMX) {
-		if (section.isBankFixed && section.bank != 1)
+		if (section.isBankFixed && section.bank != 1) {
 			error(
 			    nullptr,
 			    0,
 			    "%s: WRAMX sections must be in bank 1 with options -w or -d",
 			    section.name.c_str()
 			);
-		else
+		} else {
 			section.type = SECTTYPE_WRAM0;
+		}
 	}
-	if (isDmgMode && section.type == SECTTYPE_VRAM && section.bank == 1)
+	if (isDmgMode && section.type == SECTTYPE_VRAM && section.bank == 1) {
 		error(nullptr, 0, "%s: VRAM bank 1 can't be used with option -d", section.name.c_str());
+	}
 
 	// Check if alignment is reasonable, this is important to avoid UB
 	// An alignment of zero is equivalent to no alignment, basically
-	if (section.isAlignFixed && section.alignMask == 0)
+	if (section.isAlignFixed && section.alignMask == 0) {
 		section.isAlignFixed = false;
+	}
 
 	// Too large an alignment may not be satisfiable
-	if (section.isAlignFixed && (section.alignMask & sectionTypeInfo[section.type].startAddr))
+	if (section.isAlignFixed && (section.alignMask & sectionTypeInfo[section.type].startAddr)) {
 		error(
 		    nullptr,
 		    0,
@@ -289,11 +297,12 @@ static void doSanityChecks(Section &section) {
 		    sectionTypeInfo[section.type].name.c_str(),
 		    section.alignMask + 1
 		);
+	}
 
 	uint32_t minbank = sectionTypeInfo[section.type].firstBank,
 	         maxbank = sectionTypeInfo[section.type].lastBank;
 
-	if (section.isBankFixed && section.bank < minbank && section.bank > maxbank)
+	if (section.isBankFixed && section.bank < minbank && section.bank > maxbank) {
 		error(
 		    nullptr,
 		    0,
@@ -306,9 +315,10 @@ static void doSanityChecks(Section &section) {
 		    minbank,
 		    maxbank
 		);
+	}
 
 	// Check if section has a chance to be placed
-	if (section.size > sectionTypeInfo[section.type].size)
+	if (section.size > sectionTypeInfo[section.type].size) {
 		error(
 		    nullptr,
 		    0,
@@ -317,6 +327,7 @@ static void doSanityChecks(Section &section) {
 		    section.size,
 		    sectionTypeInfo[section.type].size
 		);
+	}
 
 	// Translate loose constraints to strong ones when they're equivalent
 
@@ -328,19 +339,20 @@ static void doSanityChecks(Section &section) {
 	if (section.isAddressFixed) {
 		// It doesn't make sense to have both org and alignment set
 		if (section.isAlignFixed) {
-			if ((section.org & section.alignMask) != section.alignOfs)
+			if ((section.org & section.alignMask) != section.alignOfs) {
 				error(
 				    nullptr,
 				    0,
 				    "Section \"%s\"'s fixed address doesn't match its alignment",
 				    section.name.c_str()
 				);
+			}
 			section.isAlignFixed = false;
 		}
 
 		// Ensure the target address is valid
 		if (section.org < sectionTypeInfo[section.type].startAddr
-		    || section.org > endaddr(section.type))
+		    || section.org > endaddr(section.type)) {
 			error(
 			    nullptr,
 			    0,
@@ -351,8 +363,9 @@ static void doSanityChecks(Section &section) {
 			    sectionTypeInfo[section.type].startAddr,
 			    endaddr(section.type)
 			);
+		}
 
-		if (section.org + section.size > endaddr(section.type) + 1)
+		if (section.org + section.size > endaddr(section.type) + 1) {
 			error(
 			    nullptr,
 			    0,
@@ -361,6 +374,7 @@ static void doSanityChecks(Section &section) {
 			    section.org + section.size,
 			    endaddr(section.type) + 1
 			);
+		}
 	}
 }
 
diff --git a/src/link/symbol.cpp b/src/link/symbol.cpp
index d5a639119..88adaead9 100644
--- a/src/link/symbol.cpp
+++ b/src/link/symbol.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "link/symbol.hpp"
 
@@ -16,14 +16,16 @@ std::unordered_map<std::string, Symbol *> symbols;
 std::unordered_map<std::string, std::vector<Symbol *>> localSymbols;
 
 void sym_ForEach(void (*callback)(Symbol &)) {
-	for (auto &it : symbols)
+	for (auto &it : symbols) {
 		callback(*it.second);
+	}
 }
 
 void sym_AddSymbol(Symbol &symbol) {
 	if (symbol.type != SYMTYPE_EXPORT) {
-		if (symbol.type != SYMTYPE_IMPORT)
+		if (symbol.type != SYMTYPE_IMPORT) {
 			localSymbols[symbol.name].push_back(&symbol);
+		}
 		return;
 	}
 
@@ -35,17 +37,19 @@ void sym_AddSymbol(Symbol &symbol) {
 	// Check if the symbol already exists with a different value
 	if (other && !(symValue && otherValue && *symValue == *otherValue)) {
 		fprintf(stderr, "error: \"%s\" is defined as ", symbol.name.c_str());
-		if (symValue)
+		if (symValue) {
 			fprintf(stderr, "%" PRId32, *symValue);
-		else
+		} else {
 			fputs("a label", stderr);
+		}
 		fputs(" at ", stderr);
 		symbol.src->dump(symbol.lineNo);
 		fputs(", but as ", stderr);
-		if (otherValue)
+		if (otherValue) {
 			fprintf(stderr, "%" PRId32, *otherValue);
-		else
+		} else {
 			fputs("another label", stderr);
+		}
 		fputs(" at ", stderr);
 		other->src->dump(other->lineNo);
 		putc('\n', stderr);
diff --git a/src/linkdefs.cpp b/src/linkdefs.cpp
index fcb7b04a3..6e00b01b1 100644
--- a/src/linkdefs.cpp
+++ b/src/linkdefs.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "linkdefs.hpp"
 
@@ -6,64 +6,66 @@ using namespace std::literals;
 
 // The default values are the most lax, as they are used as-is by RGBASM; only RGBLINK has the full
 // info, so RGBASM's job is only to catch unconditional errors earlier.
+// clang-format off: nested initializers
 SectionTypeInfo sectionTypeInfo[SECTTYPE_INVALID] = {
     {
-     .name = "WRAM0"s,
-     .startAddr = 0xC000,
-     .size = 0x2000 /* Patched to 0x1000 if !isWRAM0Mode */,
-     .firstBank = 0,
-     .lastBank = 0,
+        .name = "WRAM0"s,
+        .startAddr = 0xC000,
+        .size = 0x2000, // Patched to 0x1000 if !isWRAM0Mode
+        .firstBank = 0,
+        .lastBank = 0,
      },
     {
-     .name = "VRAM"s,
-     .startAddr = 0x8000,
-     .size = 0x2000,
-     .firstBank = 0,
-     .lastBank = 1 /* Patched to 0 if isDmgMode */,
-     },
+        .name = "VRAM"s,
+        .startAddr = 0x8000,
+        .size = 0x2000,
+        .firstBank = 0,
+        .lastBank = 1, // Patched to 0 if isDmgMode
+    },
     {
-     .name = "ROMX"s,
-     .startAddr = 0x4000,
-     .size = 0x4000,
-     .firstBank = 1,
-     .lastBank = 65535,
+        .name = "ROMX"s,
+        .startAddr = 0x4000,
+        .size = 0x4000,
+        .firstBank = 1,
+        .lastBank = 65535,
      },
     {
-     .name = "ROM0"s,
-     .startAddr = 0x0000,
-     .size = 0x8000 /* Patched to 0x4000 if !is32kMode */,
-     .firstBank = 0,
-     .lastBank = 0,
+        .name = "ROM0"s,
+        .startAddr = 0x0000,
+        .size = 0x8000, // Patched to 0x4000 if !is32kMode
+        .firstBank = 0,
+        .lastBank = 0,
      },
     {
-     .name = "HRAM"s,
-     .startAddr = 0xFF80,
-     .size = 0x007F,
-     .firstBank = 0,
-     .lastBank = 0,
+        .name = "HRAM"s,
+        .startAddr = 0xFF80,
+        .size = 0x007F,
+        .firstBank = 0,
+        .lastBank = 0,
      },
     {
-     .name = "WRAMX"s,
-     .startAddr = 0xD000,
-     .size = 0x1000,
-     .firstBank = 1,
-     .lastBank = 7,
+        .name = "WRAMX"s,
+        .startAddr = 0xD000,
+        .size = 0x1000,
+        .firstBank = 1,
+        .lastBank = 7,
      },
     {
-     .name = "SRAM"s,
-     .startAddr = 0xA000,
-     .size = 0x2000,
-     .firstBank = 0,
-     .lastBank = 255,
+        .name = "SRAM"s,
+        .startAddr = 0xA000,
+        .size = 0x2000,
+        .firstBank = 0,
+        .lastBank = 255,
      },
     {
-     .name = "OAM"s,
-     .startAddr = 0xFE00,
-     .size = 0x00A0,
-     .firstBank = 0,
-     .lastBank = 0,
+        .name = "OAM"s,
+        .startAddr = 0xFE00,
+        .size = 0x00A0,
+        .firstBank = 0,
+        .lastBank = 0,
      },
 };
+// clang-format on
 
 char const * const sectionModNames[] = {
     "regular",  // SECTION_NORMAL
diff --git a/src/opmath.cpp b/src/opmath.cpp
index 619b3536e..d9df2fc50 100644
--- a/src/opmath.cpp
+++ b/src/opmath.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 // Mathematical operators that don't reuse C++'s behavior
 
@@ -24,11 +24,13 @@ int32_t op_exponent(int32_t base, uint32_t power) {
 	int32_t result = 1;
 
 	for (;;) {
-		if (power % 2)
+		if (power % 2) {
 			result *= base;
+		}
 		power /= 2;
-		if (!power)
+		if (!power) {
 			break;
+		}
 		base *= base;
 	}
 
@@ -37,14 +39,18 @@ int32_t op_exponent(int32_t base, uint32_t power) {
 
 int32_t op_shift_left(int32_t value, int32_t amount) {
 	// Get the easy cases out of the way
-	if (amount == 0)
+	if (amount == 0) {
 		return value;
-	if (value == 0 || amount >= 32)
+	}
+	if (value == 0 || amount >= 32) {
 		return 0;
-	if (amount < -31)
+	}
+	if (amount < -31) {
 		return (value < 0) ? -1 : 0;
-	if (amount < 0)
+	}
+	if (amount < 0) {
 		return op_shift_right(value, -amount);
+	}
 
 	// Use unsigned to force a bitwise shift
 	// Casting back is OK because the types implement two's complement behavior
@@ -53,17 +59,22 @@ int32_t op_shift_left(int32_t value, int32_t amount) {
 
 int32_t op_shift_right(int32_t value, int32_t amount) {
 	// Repeat the easy cases here to avoid INT_MIN funny business
-	if (amount == 0)
+	if (amount == 0) {
 		return value;
-	if (value == 0 || amount < -31)
+	}
+	if (value == 0 || amount < -31) {
 		return 0;
-	if (amount > 31)
+	}
+	if (amount > 31) {
 		return (value < 0) ? -1 : 0;
-	if (amount < 0)
+	}
+	if (amount < 0) {
 		return op_shift_left(value, -amount);
+	}
 
-	if (value > 0)
+	if (value > 0) {
 		return static_cast<uint32_t>(value) >> amount;
+	}
 
 	// Calculate an OR mask for sign extension
 	// 1->0x80000000, 2->0xC0000000, ..., 31->0xFFFFFFFE
@@ -76,12 +87,15 @@ int32_t op_shift_right(int32_t value, int32_t amount) {
 
 int32_t op_shift_right_unsigned(int32_t value, int32_t amount) {
 	// Repeat the easy cases here to avoid INT_MIN funny business
-	if (amount == 0)
+	if (amount == 0) {
 		return value;
-	if (value == 0 || amount < -31 || amount > 31)
+	}
+	if (value == 0 || amount < -31 || amount > 31) {
 		return 0;
-	if (amount < 0)
+	}
+	if (amount < 0) {
 		return op_shift_left(value, -amount);
+	}
 
 	return static_cast<uint32_t>(value) >> amount;
 }
diff --git a/src/util.cpp b/src/util.cpp
index 60db9a383..67f776fc9 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "util.hpp"
 
@@ -15,8 +15,9 @@ char const *printChar(int c) {
 	// "0xFF" + '\0': 5 bytes
 	static char buf[5];
 
-	if (c == EOF)
+	if (c == EOF) {
 		return "EOF";
+	}
 
 	if (isprint(c)) {
 		buf[0] = '\'';
@@ -58,14 +59,17 @@ size_t readUTF8Char(std::vector<int32_t> *dest, char const *src) {
 	size_t i = 0;
 
 	for (;;) {
-		if (decode(&state, &codepoint, src[i]) == 1)
+		if (decode(&state, &codepoint, src[i]) == 1) {
 			return 0;
+		}
 
-		if (dest)
+		if (dest) {
 			dest->push_back(src[i]);
+		}
 		i++;
 
-		if (state == 0)
+		if (state == 0) {
 			return i;
+		}
 	}
 }
diff --git a/src/version.cpp b/src/version.cpp
index 1b3466776..8f69e6a5e 100644
--- a/src/version.cpp
+++ b/src/version.cpp
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
 
 #include "version.hpp"
 
diff --git a/test/gfx/rgbgfx_test.cpp b/test/gfx/rgbgfx_test.cpp
index 59578922b..51b697f35 100644
--- a/test/gfx/rgbgfx_test.cpp
+++ b/test/gfx/rgbgfx_test.cpp
@@ -27,10 +27,13 @@
 	#include <spawn.h>
 	#include <unistd.h>
 #else
-	#define WIN32_LEAN_AND_MEAN // Include less from `windows.h` to avoid conflicts
+// clang-format off: maintain `include` order
+	#define WIN32_LEAN_AND_MEAN // Include less from `windows.h`
 	#include <windows.h>
+// clang-format on
 	#include <errhandlingapi.h>
 	#include <processthreadsapi.h>
+
 	#undef max // This macro conflicts with `std::numeric_limits<...>::max()`
 #endif
 
@@ -60,7 +63,8 @@ static void error(char const *fmt, ...) {
 	}
 }
 
-[[noreturn]] static void fatal(char const *fmt, ...) {
+[[noreturn]]
+static void fatal(char const *fmt, ...) {
 	va_list ap;
 
 	fputs("FATAL: ", stderr);
@@ -93,7 +97,8 @@ class Png {
 	int nbTransparentEntries;
 	png_bytep transparencyPal = nullptr;
 
-	[[noreturn]] static void handleError(png_structp png, char const *msg) {
+	[[noreturn]]
+	static void handleError(png_structp png, char const *msg) {
 		Png *self = reinterpret_cast<Png *>(png_get_error_ptr(png));
 
 		fatal("Error reading input image (\"%s\"): %s", self->path.c_str(), msg);
@@ -311,12 +316,7 @@ static char *execProg(char const *name, char * const *argv) {
 	if (int info; waitpid(pid, &info, 0) == -1 || !WIFEXITED(info)) {
 		fatal("Error waiting for %s: %s", name, strerror(errno));
 	} else if (int status = WEXITSTATUS(info); status != 0) {
-		fatal(
-		    "%s returned with status %d\n\tThe command was: [%s]",
-		    name,
-		    status,
-		    formatArgv()
-		);
+		fatal("%s returned with status %d\n\tThe command was: [%s]", name, status, formatArgv());
 	}
 
 #else // defined(_MSC_VER) || defined(__MINGW32__)
@@ -341,8 +341,9 @@ static char *execProg(char const *name, char * const *argv) {
 
 	std::vector<char> cmdLine;
 	for (size_t i = 0; argv[i]; ++i) {
-		if (i > 0)
+		if (i > 0) {
 			cmdLine.push_back(' ');
+		}
 		cmdLine.insert(cmdLine.end(), argv[i], argv[i] + strlen(argv[i]));
 	}
 	cmdLine.push_back('\0');