CPPHS(1)
π CPPHS π
okay bestie, pull up a chair, we're talking about cpphs β the liberalised cpp-a-like preprocessor for Haskell π¦
β¨ SYNOPSIS β¨
cpphs [FILENAME|OPTION]...
πΈ DESCRIPTION πΈ
So cpphs is a liberalised re-implementation of cpp(1), the C pre-processor, written in and for Haskell. no cap π
Why would anyone re-implement cpp?? Great question, bestie. Rightly or wrongly, the C pre-processor is widely used in Haskell source code. It enables conditional compilation for different compilers, for different versions of the same compiler, and for different OS platforms. It's also occasionally used for its macro language, which can enable certain forms of platform-specific detail-filling, like the tedious boilerplate generation of instance definitions and FFI declarations. iconic behaviour tbh.
BUT β and this is the tea π΅ β there are two problems with cpp, aside from the obvious aesthetic ones:
- For some Haskell systems, notably Hugs on Windows, a true
cppis not available by default. π - Even for the other Haskell systems, the common
cppprovided by thegcc3.x series is changing subtly in ways that are incompatible with Haskell's syntax. There have always been problems with, for instance, string gaps, and prime characters in identifiers. And these problems are only going to get worse. π
So, it seemed right to attempt to provide an alternative to cpp, both more compatible with Haskell, and itself written in Haskell so that it can be distributed with compilers. main character energy fr fr β¨
cpphs is pretty-much feature-complete, and compatible with the -traditional style of cpp. It has two modes:
- conditional compilation only (
--nomacro), and - full macro-expansion (default).
In --nomacro mode, cpphs performs only conditional compilation actions, i.e. #include's, #if's, and #ifdef's are processed according to text-replacement definitions (both command-line and internal), but no parameterised macro expansion is performed. In full compatibility mode (the default), textual replacements and macro expansions are also processed in the remaining body of non-cpp text. slay π
π Working Features π
#ifdefβ simple conditional compilation#ifβ the full boolean language ofdefined(),&&,||,==, etc.#elifβ chained conditionals#defineβ in-line definitions (text replacements and macros)#undefβ in-line revocation of definitions#includeβ file inclusion#lineβ line number directives\nβ line continuations within all#directives/**/β token catenation within a macro definition##β ANSI-style token catenation#β ANSI-style token stringisation__FILE__β special text replacement for DIY error messages__LINE__β special text replacement for DIY error messages__DATE__β special text replacement__TIME__β special text replacement
Macro expansion is recursive. Redefinition of a macro name does not generate a warning (we're chill like that π). Macros can be defined on the command-line with -D just like textual replacements. Macro names are permitted to be Haskell identifiers e.g. with the prime ` and backtick Β΄ characters, which is slightly looser than in C, but they still may not include operator symbols.
Numbering of lines in the output is preserved so that any later processor can give meaningful error messages. When a file is #include'd, cpphs inserts #line directives for the same reason. Numbering should be correct even in the presence of line continuations. If you don't want #line directives in the final output, use the --noline option. π
Any syntax errors in cpp directives gives a message to stderr and halts the program. Failure to find a #include'd file produces a warning to stderr, but processing continues. (one of these is dramatic and one is not, and you know which is which π)
You can give any number of filenames on the command-line. The results are catenated on standard output. π
ok so here's the option menu, bestie:
-Dsymβ define a textual replacement (default value is1)-Dsym=valβ define a textual replacement with a specific value-Ipathβ add a directory to the search path for#include's-Ofileβ specify a file for output (default isstdout)--nomacroβ only process#ifdef's and#include's, do not expand macros--nolineβ remove#linedroppings from the output--stripβ convert C-style comments to whitespace, even outside cpp directives--hashesβ recognise the ANSI#stringise operator, and##for token catenation, within macros--textβ treat the input as plain text, not Haskell code--layoutβ preserve newlines within macro expansions--unlitβ remove literate-style comments--versionβ report version number ofcpphsand stop
There are NO textual replacements defined by default. (Normalcppusually has definitions formachine,OS, etc. These could easily be added to thecpphssource code if you wish.)
The search path is searched in order of the -I options, except that the directory of the calling file, then the current directory, are always searched first. Again, there is no default search path (and again, this could easily be changed). π«Ά
π DIFFERENCES FROM CPP π
In general, cpphs is based on the -traditional behaviour, not ANSI C, and has the following main differences from the standard cpp.
π General π
- The
#that introduces any cpp directive must be in the first column of a line (whereas ANSI permits whitespace before the#). - Generates the
#line n "filename"syntax, not the# n "filename"variant. - C comments are only removed from within cpp directives. They are not stripped from other text. Consider for instance that in Haskell, all of the following are valid operator symbols:
/**/*/*β However, you can turn on C-comment removal with the--stripoption.
π§ Macro language π§
- Accepts
/**/for token-pasting in a macro definition. However,/* */(with any text between the open/close comment) inserts whitespace. - The ANSI
##token-pasting operator is available with the--hashesflag. This is to avoid misinterpreting any valid Haskell operator of the same name. - Replaces a macro formal parameter with the actual, even inside a string (double or single quoted). This is
-traditionalbehaviour, not supported in ANSI. - Recognises the
#stringisation operator in a macro definition only if you use the--hashesoption. (It is an ANSI addition, only needed because quoted stringisation (above) is prohibited by ANSI.) - Preserves whitespace within a textual replacement definition exactly (modulo newlines), but leading and trailing space is eliminated.
- Preserves whitespace within a macro definition (and trailing it) exactly (modulo newlines), but leading space is eliminated.
- Preserves whitespace within macro call arguments exactly (including newlines), but leading and trailing space is eliminated.
- With the
--layoutoption, line continuations in a textual replacement or macro definition are preserved as line-breaks in the macro call. (Useful for layout-sensitive code in Haskell.)
π BUGS π
Bug reports, and any other feedback, should be sent to Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
π COPYRIGHT π
Copyright Β© 2004-2005 Malcolm Wallace, except for ParseLib (Copyright Β© 1995 Graham Hutton and Erik Meijer).
The library modules in cpphs are distributed under the terms of the LGPL. If that's a problem for you, contact me to make other arrangements. The application module Main.hs itself is GPL.
π¦ SEE ALSO π¦
π AUTHOR π
This manual page was written, based on index.html, by Ian Lynagh <igloo@debian.org> for the Debian system (but may be used by others).
and that's the whole vibe check, bestie β¨ this was cpphs version 0.9, dated 2004-10-01 β go forth and preprocess, you absolute icon ππ
πΈ
π¦ where this page comes from
- debian bookworm: cpphs 1.20.9.1-2+b1 Β· LGPL-2.1-only
- debian trixie: cpphs 1.20.9.1-4+b1 Β· LGPL-2.1-only
- epel 10: cpphs 1.20.9.1-20.el10_0 Β· GPL-2.0-or-later AND LGPL-2.1-or-later
- epel 9: cpphs 1.20.9.1-6.el9 Β· GPL+ and LGPLv2+
- fedora 43: cpphs 1.20.9.1-27.fc43 Β· GPL-2.0-or-later AND LGPL-2.1-or-later
- fedora 44: cpphs 1.20.10-1.fc44 Β· GPL-2.0-or-later
- ubuntu jammy: cpphs 1.20.9.1-1build4.1 Β· LGPL-2.1-only
- ubuntu noble: cpphs 1.20.9.1-3build1 Β· LGPL-2.1-only
- ubuntu questing: cpphs 1.20.9.1-4
- ubuntu resolute: cpphs 1.20.10-1build1 Β· LGPL-2.1-only
- ubuntu stonking: cpphs 1.20.10-1build1 Β· LGPL-2.1-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms