NAME¶
cpphs - liberalised cpp-a-like preprocessor for Haskell
SYNOPSIS¶
cpphs [
FILENAME|
OPTION]...
DESCRIPTION¶
cpphs is a liberalised re-implementation of
cpp (1), the C
pre-processor, in and for Haskell.
Why re-implement cpp? Rightly or wrongly, the C pre-processor is widely used in
Haskell source code. It enables conditional compilation for different
compilers, different versions of the same compiler, and different OS
platforms. It is also occasionally used for its macro language, which can
enable certain forms of platform-specific detail-filling, such as the tedious
boilerplate generation of instance definitions and FFI declarations. However,
there are two problems with cpp, aside from the obvious aesthetic ones:
- For some Haskell systems, notably Hugs on Windows, a true cpp is not
available by default.
- Even for the other Haskell systems, the common cpp provided by the gcc 3.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. 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.
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.
Working Features:
- #ifdef
- simple conditional compilation
- #if
- the full boolean language of defined(), &&, ||, ==, 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. 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.
You can give any number of filenames on the command-line. The results are
catenated on standard output.
- -Dsym
- define a textual replacement (default value is 1)
- -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 is stdout)
- --nomacro
- only process #ifdef's and #include's,
do not expand macros
- --noline
- remove #line droppings 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 of cpphs and stop
There are NO textual replacements defined by default. (Normal cpp usually has
definitions for machine, OS, etc. These could easily be added to the cpphs
source 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
--strip option.
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
--hashes
flag. 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 -traditional behaviour, not supported in ANSI.
Recognises the
# stringisation operator in a macro definition only if you
use the
--hashes option. (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
--layout option, 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¶
cpp(1)
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).