SnowC is a simple variant of C designed to remove redundant syntax from the code of competent programmers. The other kind can't be helped.
SnowC stands for Semantic Non-Optional Whitespace C. The goal is to allow people who appreciate Python's semantic whitespace to enjoy the same code style in C.
The SnowC system is not a compiler but rather filters to convert the more structured SnowC to ordinary C which can then be read by a normal C compiler. This way no mental adjustments need to be made to fundamental expectations of the C language. SnowC simply uses software to automatically fill in the redundant syntax of C code.
This redundancy takes two forms.
1 In normal C programming a typical line ends with a semicolon and an end-of-line byte. Why both?
2 In normal C good programmers indent code to match the level of brace nesting. Why do both? This one is especially bad because mental energy is required to manually keep the indent levels accurately coordinated.
The reason for this redundancy is that there can be exceptions. SnowC takes the view that these are exceptional — doesn't it make sense to use awkward syntax for the exceptions rather than the typical code?
The complicated part of the SnowC project is that it is also capable of taking C as found in the wild and removing the redundancies automatically to create SnowC. This makes it possible to instantly convert any C codebase to SnowC so that you can easily explore the possible benefits.
The conversion from SnowC to C is designed to be very simple. This diagram describes the entire logic behind the project. If you can feed lines of text into this kind of a filter and they come out as valid C code, then you are starting with valid SnowC.
Generally this is a reasonable starting point to understand what to expect. In practice it can be a bit more complex. For example, when considering if the next line is indented, there is a distinction between semantic "lines" and EOL characters in the file. The former can be broken up with escapes to produce more of the latter. Also this completely ignores the thorny messes involving C comments and preprocessor directives. Ignoring them is also something SnowC attempts.
Here is an illustrative excerpt from page 148 of
this
online version of The C Programming Language by Brian Kernighan and
Dennis Ritchie. (Page 170 in my first edition paperback, page 184 in
my second edition paperback.) Original C on the left and SnowC
generated by c2snowc on the right.
#ifndef DIRSIZ | #ifndef DIRSIZ
#define DIRSIZ 14 | #define DIRSIZ 14
#endif | #endif
struct direct { /* directory entry */ | struct direct /* directory entry */
ino_t d_ino; /* inode number */ | ino_t d_ino /* inode number */
char d_name[DIRSIZ]; /* long name does not have '\0' */ | char d_name[DIRSIZ] /* long name does not have '\0' */
}; | ;
|
int fstat(int fd, struct stat *); | int fstat(int fd, struct stat *)
/* opendir: open a directory for readdir calls */ | /* opendir: open a directory for readdir calls */
DIR *opendir(char *dirname) | DIR *opendir(char *dirname)
{ | int fd
int fd; | struct stat stbuf
struct stat stbuf; | DIR *dp
DIR *dp; | if ((fd = open(dirname, O_RDONLY, 0)) == -1\
if ((fd = open(dirname, O_RDONLY, 0)) == -1 | || fstat(fd, &stbuf) == -1\
|| fstat(fd, &stbuf) == -1 | || (stbuf.st_mode & S_IFMT) != S_IFDIR\
|| (stbuf.st_mode & S_IFMT) != S_IFDIR | || (dp = (DIR *) malloc(sizeof(DIR))) == NULL)\
|| (dp = (DIR *) malloc(sizeof(DIR))) == NULL) | return NULL
return NULL; | dp->fd = fd
dp->fd = fd; | return dp
return dp; |
} | /* closedir: close directory opened by opendir */
| void closedir(DIR *dp)
/* closedir: close directory opened by opendir */ | if (dp)
void closedir(DIR *dp) | close(dp->fd)
{ | free(dp)
if (dp) { |
close(dp->fd); |
free(dp); |
} |
} |
My original 2015 blog post outlining the concept of a C where semantic whitespace replaces braces.
Here are some articles I wrote discussing aspects of the SnowC project in more detail.
When you first encounter the SnowC concept, I can assure you that it is natural to incorrectly think that it is trivial. Surely this can not be all that hard, right? The conversion from SnowC to compilable C was designed to be simple and that explains much of the illusion. Where things quickly descend into madness however is when dealing with C code in the wild and making the correct decisions during the conversion to SnowC.
Here is a series of articles I wrote detailing some of the difficult parts of this project.
Those should be helpful to anyone trying to make their own version.
You can download the entire source code and the test set I used. The
whole thing is only 48kB. There are no dependencies except a C
compiler. I used make which can be helpful but not strictly
necessary.
To run it, you'll need to have gcc handy or whatever you normally
use to compile C programs. You can download the directory ready to go
with these commands.
cd /tmp # Or whatever...
wget -qO- https://xed.ch/project/snowc/snowc.tgz | tar -xvzf -
cd snowc-???/
make
make test
If you saved your program as x.c you can now process it in a normal
sensible way.
./c2snowc x.c > x.cno
./snowc2c x.cno > X.c
In theory, the X.c should compile and run as well as the
original x.c. Sometimes it's fun to compare the before and after.
vimdiff x.c x.cno
vimdiff x.c X.c
It was originally written in pure C and performs like it. I did not use any external libraries. I did not even cheat by using regular expressions.
Here are some benchmark timings for the conversion of 36676 *.c files
(headers excluded) of the
7.1.5
Linux kernel.
cat > = 51s (1.4ms per file)
Are different indent levels allowed in the same SnowC file?
No. Python generously allows this questionable trick. SnowC does not. When converting from SnowC, the level indent spacing is auto-detected with the greatest common divisor of leading spaces. One reason the SnowC approach might be better for SnowC is that in C it is technically legal to have nonsense like this complete program:
void main() {{{return;}}}
Yes, that does compile! Might there ever be a sane need to have SnowC be able to produce something like that? Although SnowC can't do anything like that now, I think such things would require globally consistent indent spacing. This is why the Python flexibility was not explored or developed. I could change my mind though.
Does SnowC work with C++ or C# or any other language?
I don't know. Maybe. Maybe there are fundamental incompatibilities somehow. I guess for very limited subsets of those languages that are effectively basic C it should work, but I've not explored it. I have to imagine that the concept of using rigorously formatted whitespace to obviate C style syntax extends to other languages with free form whitespace and braces and semicolons.
There is CoffeeScript which appears to be similar to a SnowC concept for JavaScript. It looks they are removing the same redundancies but also trying to improve the base language in other ways. In contrast SnowC leaves C alone after the redundancies are cut.
Is SnowC capitalized? How exactly does one refer to it?
snowc*.cnosnowc2c & c2snowcCan I pipe to SnowC conversion programs?
Working on it. This should make automatic code formatting (e.g. adding braces to single statement control blocks) using a round trip conversion to SnowC and back slightly more satisfying.
Why should I not use SnowC?
Maybe you like curly braces. Maybe you like semicolons. Maybe you hate Python. Maybe your code breaks SnowC conversions. Maybe you want to fill your monitor up with extra unnecessary lines of code to make your colleagues think you're working. Maybe you're an IOCCC artiste. Maybe you've been doing this a while and are just used to normal C. It's all good. Remember, the reason we love C is that you've got choices.
Want to report a bug in SnowC? Want to tell me about some cool thing you made it do? Or wish you could make it do? You can send me an email!
My email address is: snowc at xed.ch
Software Freedom is very important to me. I wish to support the free software community which has supported me.
Copyright 2026 Chris X Edwards
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Yada YADA... You KNOW the DRILL.
The license should be available at https://www.gnu.org/licenses/gpl-3.0.txt. If for some reason it is not, a copy is distributed with this project at ./LICENSE.
Though your sins are like scarlet, they shall be as white as snow...