M4m4 is a powerful (Turing-equivalent, unlike CPP) macro-expansion program designed as a preprocessor to more stubborn programming languages. It's ugly, but it's fairly standard, and available on most platforms, including a fine GNU version.
The semantics of m4 are bad. it uses back-door evaluation in a dynamically-bound global environment as the only way to program, without any way to safely quote text (not to speak about quasiquotation). Thus, users who want to do complex things often find they must compile manually to continuation passing style with manual fluid-bindings. Avoid m4 but for quick hacks, and when the environment has already been setup for it (e.g. FvwmM4, sendmail configuration, etc).