SBC - Slightly Better C
SBC is a C preprocessor that makes C slightly less annoying to program in. It takes in a C code file, imports other code files, and outputs a combined C code file which you can then compile with a compiler of your choice.
-
No header files. By organizing your code under
#sectiontags, it can be ordered in a way that doesn't require header files. SBC takes all the sections from all the files, and groups the sections of same name together from different files.#include <string.h> #section DEFINES; #define foo 1337 #section TYPEDEFS; enum { HI, HELLO, BYE }; typedef struct Thing Thing; #section STRUCTS; struct Thing { int x; }; #section FUNCTIONDEFS; static int do_the_thing (int y); #section GLOBALS; int state = HI; #section FUNCTIONS; static int do_the_thing (int y) { return y * y; }
Sections can be changed whenever and however you want, you can give them whatever names you want, and there's no restrictions about what goes where. The only section that exists by default is an empty section, everything goes there until the first section starts. Above are the sections that I've found to make most sense and solve all my problems. -
Easy imports. You can use
#importto directly import C files, SBC will load and parse the file once, and will ignore any subsequent imports of the same file. No fear of conflict.#import "hello_world.c" #import "zozzle.c"
-
Strings with length. Prefix your strings with
S, the string will get wrapped into a struct definition along with the string's length.char* foo = "Hello world!"; String bar = S"It is a good day.";
char* foo = "Hello world!"; String bar = ((String){.length=17,.data="It is a good day."});
-
Multi-character literals. The contents of character literals will be converted into hexadecimal values, allowing you to use multiple characters in them.
u32 value = 'X'; // 0x58
u32 value = 'Help'; // 0x706C6548
u32 value = '❤'; // 0xA49DE2
Current status
There's a lot of things I want in a language, but making a whole language is too much effort for me. However, making a preprocessor like this has some issues too, notably the fact that C macros can mangle the code. Unless SBC parses and processes macros completely (it doesn't), it's impossible to understand what types and functions exist in the program and what they look like.
Here's some ideas that I am considering.
- String macros. The 'S' string prefix should be replaced with something more customizable.
- Fixable section names. Currently if you typo a section name, it will just create a new section and probably put it after all the other sections. It should be possible to pre-define the sections and get an error if you use another one.
- "Here strings". Strings that use custom delimiters so it's easier to add quote marks and new lines inside it. The main reason I can't be bothered to do this is because my text editor doesn't understand them, I would have to start using .cpp files and use C++ raw string syntax
R"xxx(Hello world)xxx". - Better compile-time counters. C has
__COUNTER__which gives a unique number for every instance of it in your code. It would be easy to let you define different numbers with a name, so#counter(foo)will return a different counted value than#counter(bar). - Function metaprogramming tweaks. I really really want to be able to detect functions, list function names, give each function a unique ID that can be used from the function, and inject some code to the beginning/end/returns. It shouldn't be too difficult to do this.
- Manual function overloading, see
#overloadfrom the link above. It may be possible to generate a _Generic macro for all the defined overloads.
Things that might work at least partially, but may be messy because SBC would have to analyze the code a bit.
- Enums with bitfield values. Instead of 0,1,2,3,4,5... you get 0x1,0x2,0x4,0x8,0x16...
- Invert breaking from
switch, so it always breaks and you must usefallthroughto not break. - Inherited struct members. See
#inheriton the link above. This requires discovery of structs, so it may not fully work. - Defer. See
#on_leaveon the link above. - Breaking/continuing through multiple loops.
Notable things that I notably want but that are too difficult unless I come up with some genius trick.
- Automatic discovery of functions/structs, and automatic generation of their typedefs/definitions.
- Inferred enum members. You know, so you can just type
.FOOand.BARinstead ofSOME_KIND_OF_ENUM_FOOandSOME_KIND_OF_ENUM_BAR - Remove the god foraken
->and allow just.to access struct members. - Isolation of libraries into their own namespace. Sometimes you want to define some names, but an imported library also defines it so you can't use it.
- Nested functions. GCC already lets you use them so it's not a big deal, but I would like to reduce my dependency on GCC. Doing this may kind-of-sort-of be possible, but it may also be too messy to make it work.
- Struct literals without cast, so you could just do
{1,5}instead of(Some_fun_and_fancy_struct){1,5}.
Download
SBC comes with source code in case you'd like to tweak it for yourself, or port it to a different operating system or whatever.
Slightly Better C 0.1
Download Slightly_Better_C_0-1.zip - 74 KB