There are lots of ways to style check your C code. astyle does a pretty decent job. However, I prefer to use a modified version of the kernel scripts/ monstrosity. These 7500 lines of Perl does not simply check your style. It really also does the job of a static analyzer to a large extent. I really cannot begin to enumerate all the stuff that it checks, so you just have to try it out and modify it as you go.

There are obviously a lot of stuff in there which is highly kernel specific, so there are some basic patches that we have to apply to make this work on our project. First, we have to make it accept to actually run from a non-kernel top directory:

--- a/scripts/     2021-12-08 08:03:04.895068708 +0100
+++ b/scripts/     2021-12-01 20:36:32.959094794 +0100
@@ -418,20 +418,20 @@

 if ($tree) {
        if (defined $root) {
-               if (!top_of_kernel_tree($root)) {
+               if (!top_of_tree($root)) {
                        die "$P: $root: --root does not point at a valid tree\n";
        } else {
-               if (top_of_kernel_tree('.')) {
+               if (top_of_tree('.')) {
                        $root = '.';
                } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
-                                               top_of_kernel_tree($1)) {
+                                               top_of_tree($1)) {
                        $root = $1;

        if (!defined $root) {
-               print "Must be run from the top-level dir. of a kernel tree\n";
+               print "Must be run from the top-level dir\n";
@@ -1305,13 +1305,12 @@


-sub top_of_kernel_tree {
+sub top_of_tree {
        my ($root) = @_;

        my @tree_check = (
-               "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
-               "README", "Documentation", "arch", "include", "drivers",
-               "fs", "init", "ipc", "kernel", "lib", "scripts",
+               "",

        foreach my $check (@tree_check) {

Also, we probably have our include files in a different directory:

--- a/scripts/     2021-12-08 08:03:04.895068708 +0100
+++ b/scripts/     2021-12-01 20:36:32.959094794 +0100
@@ -6536,7 +6517,7 @@

 # Check for compiler attributes
-               if ($realfile !~ m@\binclude/uapi/@ &&
+               if ($realfile !~ m@\binclude/@ &&
                    $rawline =~ /\b__attribute__\s*\(\s*($balanced_parens)\s*\)/) {
                        my $attr = $1;
                        $attr =~ s/\s*\(\s*(.*)\)\s*/$1/;

When you run this against your patches for the first time, you'll notice that (obviously) it expects the Linux Kernel Coding Style. Now, I like that style, so I'm happy with using tabs over spaces, no braces on single line branches etc. If you are like me, applying this patch that contains the above diffs should get you started. However, this may not fit your project or your style, and neither does it for the QEMU folks, so they have some tips for you. The QEMU copy of scripts/ has diverged substantially from the upstream version in the kernel, so it was not trivial to grab the diff. However, I extracted the relevant stuff into this heretic patch which will convert for a style that uses spaces instead of tabs and requires braces for all branches. Like most sane projects these days.