Skip to content

Preprocessor

Derek Snider edited this page May 19, 2026 · 1 revision

Preprocessor

madc implements C preprocessor directives at the lexer level.

#define / #undef

#define MAX 100
#define PI 3.14159
#define MSG "hello"

cout << MAX << endl;    // 100
cout << PI << endl;     // 3.14159

#undef MAX
// MAX is no longer defined

Defines expand by pushing the value back into the source stream for re-tokenization — they can expand to any valid token sequence.

Conditional compilation

#ifdef FEATURE_X
    // compiled only if FEATURE_X is defined
#endif

#ifndef FEATURE_Y
    // compiled only if FEATURE_Y is NOT defined
#endif

#if defined(FEATURE_X) && !defined(FEATURE_Y)
    // boolean expressions supported
#endif

#if 1
    // always compiled
#endif

#if 0
    // never compiled (useful for commenting out blocks)
#endif

#elif / #else

#ifdef LINUX
    // Linux-specific code
#elif defined(MACOS)
    // macOS-specific code
#else
    // fallback code
#endif

Nested conditionals are fully supported.

#include

#include "myfile.mad"      // quotes: filesystem (relative to current file)
#include <stdio.h>         // angle brackets: embedded headers first, then filesystem

See Multi-file Projects and Embedded Headers.

#load

Load a shared library as a namespace:

#load "libfoo.so" as foo;

Opens the library via dlopen with RTLD_LAZY | RTLD_GLOBAL. Functions become available as foo::function_name() via dlsym on first use.

RTLD_GLOBAL makes loaded symbols globally visible, so functions can also be called without the namespace prefix via the dlsym fallback.

#pragma

#pragma pack

Controls struct field alignment:

#pragma pack(push, 1)
struct packed_header {
    char magic;
    int32_t size;
};  // 5 bytes, no padding
#pragma pack(pop)

#pragma prefer

Sets namespace precedence:

#pragma prefer rust, php, c

#pragma push_macro / pop_macro

Save and restore macro definitions:

#define FOO 42
#pragma push_macro("FOO")
#undef FOO
// FOO is undefined here
#pragma pop_macro("FOO")
// FOO is 42 again

Predefined macros

Macro Value
__FILE__ Current source filename
__LINE__ Current line number

These work inside function-like macros too.

What's next?

Clone this wiki locally