The C Preprocessor (CPP) is often misunderstood as a simple text-to-text translator. In reality, the C standard defines it as a series of phases that transform source code into a stream of C tokens. While many implementations provide a text output for visibility, the underlying mechanism is designed to prepare a translation unit for the C parser. David Priver, while developing his own C2Y compiler and interpreter, implemented a custom CPP and introduced several extensions to make the preprocessor more expressive and easier to debug.
One of the primary goals of these extensions is to reduce the need for 'preprocessor abuse'—complex, nested macro definitions used to simulate functionality that the standard CPP lacks. For example, Priver introduced `__print(...)` and `__where()` as builtin debugging macros. `__print()` expands its arguments and writes them directly to stderr, allowing developers to see exactly what a macro expands to without dumping the entire translation unit. `__where()` identifies the specific file and line where a macro was defined, solving the common problem of tracing obscure expansions in large codebases.
To handle list transformations, Priver added a `__map(macro, ...)` builtin. In standard C, applying a transformation to every argument in a sequence typically requires recursive function-like macros, which the C standard restricts by suppressing expansion. While developers can 'fake' recursion by manually pumping iterations, it is often slow and visually cluttered. The `__map()` builtin simplifies this by performing a linear scan, applying the provided macro to each argument once. Additionally, he included a `__VA_COUNT__` builtin to simplify variadic macro handling, allowing developers to directly retrieve the number of arguments rather than relying on complex manual counting techniques. These additions aim to make the preprocessor a more powerful, readable tool by providing native support for common meta-programming patterns.
