cpphs 1.13.2 → 1.13.3
raw patch · 5 files changed
+1107/−39 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG +167/−0
- Language/Preprocessor/Cpphs/CppIfdef.hs +48/−36
- cpphs.cabal +3/−3
- docs/cpphs.1 +276/−0
- docs/index.html +613/−0
+ CHANGELOG view
@@ -0,0 +1,167 @@+Version 1.13+------------+ * Accept -U cmdline option for compatibility with cpp.++Version 1.12+------------+ * Allow it to build with ghc-7.2.++Version 1.11+------------+ * API change: runCpphs, cppIfdef, and macroPass are now in the IO monad.++Version 1.10+-----------+ * New command-line option: "--linepragma"+ It converts #line droppings into {-# LINE #-}.++Version 1.9+-----------+ * Bugfix for #undef.++Version 1.8+-----------+ * Bugfix for off-by-one error in line numbers with --include=file.++Version 1.7+-----------+ * Bugfix in interaction of --unlit with \end{code}++Version 1.6+-----------+ * New command-line option: "--include=filename".+ * New command-line option: "--strip-eol" for comment-stripping.+ * Line pragmas can have filenames containing spaces.++Version 1.5+-----------+ * Parametrised macro-calls now permitted in #ifdef's.+ * Recursive textual expansion now permitted in #ifdef's.+ * Better options-handling when used as a library.+ * Various small bugfixes++Version 1.4+-----------+ * Added a "--pragma" option to retain #pragma in the output.+ * Fixed a number of obscure corner cases involving the interaction of+ multiple features e.g. foo##__LINE__.+ * Added the "--nowarn" option.++Version 1.3+-----------+ * Added a "--cpp" option for drop-in compatibility with standard cpp.+ It causes cpphs to accept standard cpp flags and translate+ them to cpphs equivalents. Compatibility options include: -o, -ansi,+ -traditional, -stdc, -x, -include, -P, -C, -CC, -A. The file+ behaviour is different too - if two filenames are given on the+ commandline, then the second is treated as the output location.+ * Fixed a corner-case bug in evaluating chained and overlapping #ifdefs.++Version 1.2+-----------+ * Re-arranged the source files into hierarchical libraries.+ * Exposed the library interface as an installable Cabal package, with+ Haddock documentation.+ * Added the --unlit option, for removing literate-style comments.++Version 1.1+-----------+ * Fix the .cabal way of building cpphs.+ * Update the --version reported (forgotten in 1.0, which still reports 0.9)+ * No longer throws an error when given an empty file as input.++Version 1.0+-----------+ * Add a compatibility script cpphs.compat, allowing cpphs to act as+ a drop-in replacement for cpp, e.g.+ ghc -cpp -pgmP cpphs.compat+ * Place quotes around replacements for special macros __FILE__, __DATE__,+ and __TIME__.+ * If no files are specified, read from stdin.+ * Ignore #! lines (e.g. in scripts)+ * Parse -D commandline options once only, and consistently with cpp,+ i.e. -Dfoo means foo=1+ * Fix compatibility with preprocessors like hsc2hs, which use+ non-cpp directives like #def. They are now passed through to the+ output with a warning to stderr.++Version 0.9+-----------+ * Bugfix for ghc-6.4 -O: flush the output buffer.++Version 0.8+-----------+ * Added the --text option, to signify the input should not+ be lexed as Haskell. This causes macros to be defined or expanded+ regardless of their location within comments, string delimiters, etc.+ * Shuffle a few files around to make it easier to say 'hmake cpphs'.+ There is also now a runhugs script to invoke cpphs nicely.++Version 0.7+-----------+ * Enable the __FILE__, __LINE__, __DATE__, and __TIME__ specials, which+ can be useful for creating DIY error messages.++Version 0.6+-----------+ * Recognise and ignore the #pragma cpp directive.+ * Fix beginning-of-file bug, where in --noline mode, a # cpp directive+ at the top of the file appeared in the output.+ * Fix chained parenthesised boolean exprs in #if, e.g.+ #if ( foo ) && ( bar )+ * Fix precedence in chained unparenthesised boolean exprs in #if, e.g.+ #if foo && bar || baz && frob+ * For better compatibility with cpp, and because otherwise+ there are certain constructs that cannot be expressed, we no+ longer permit whitespace in a <tt>#define</tt> between the+ symbolname and an opening parenthesis, e.g.+ #define f (f' id)+ Previously, this was interpreted as a parametrised macro,+ with arguments in the parens, and no expansion. Now, the space+ indicates that this is a textual replacement, and the parenthesised+ expression is in fact the replacement.++Version 0.5+-----------+ * Added a --version flag to report the version number.+ * Renamed --stringise to --hashes, and use it to turn on ## catenation+ as well.+ * Bugfix for #if 1, previously taken as false.+ * Bugfix for --nolines: it no longer adds extra spurious newlines.+ * File inclusion now looks in the directory of the calling file.+ * Failure to find an include file is now merely a warning to stderr+ rather than an error.+ * Added a --layout flag. Previously, line continuations in a macro+ definition were always preserved in the output, permitting use+ of the Haskell layout rule even inside a macro. The default is now+ to remove line continuations for conformance with cpp, but the option+ of using --layout is still possible.++Version 0.4+-----------+ * New flag -Ofile to redirect output+ * Bugfix for precedence in #if !False && False+ * Bugfix for whitespace between # and if+ * Bugfix for #define F "blah"; #include F++Version 0.3+-----------+ * Bugfix for recursive macro expansion.+ * New flag --strip to remove C comments even outside cpp directives.+ * New flag --stringise to recognise the # stringise operator in macros.++Version 0.2+-----------+ * New flag --noline to eliminate #line directives from output.+ * Add symbol-replacement and macro-expansion.+ * New flag --nomacro to turn off symbol/macro-expansion.++2004-Apr-21+-----------+ * Now accept multi-line # commands via the \ line continuation operator.+ The original file line numbering is preserved in the output by+ some tricky acrobatics.++Version 0.1+-----------+ * Initial release.
Language/Preprocessor/Cpphs/CppIfdef.hs view
@@ -7,7 +7,7 @@ -- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk> -- Stability : experimental -- Portability : All---+ -- Perform a cpp.first-pass, gathering \#define's and evaluating \#ifdef's. -- and \#include's. -----------------------------------------------------------------------------@@ -43,7 +43,7 @@ -> String -- ^ The input file content -> IO [(Posn,String)] -- ^ The file after processing (in lines) cppIfdef fp syms search options =- cpp posn defs search options Keep . (cppline posn:) . linesCpp+ cpp posn defs search options (Keep []) . (cppline posn:) . linesCpp where posn = newfile fp defs = preDefine options syms@@ -53,17 +53,23 @@ -- | Internal state for whether lines are being kept or dropped.--- In @Drop n b@, @n@ is the depth of nesting, @b@ is whether+-- In @Drop n b ps@, @n@ is the depth of nesting, @b@ is whether -- we have already succeeded in keeping some lines in a chain of--- @elif@'s-data KeepState = Keep | Drop Int Bool+-- @elif@'s, and @ps@ is the stack of positions of open @#if@ contexts,+-- used for error messages in case EOF is reached too soon.+data KeepState = Keep [Posn] | Drop Int Bool [Posn] -- | Return just the list of lines that the real cpp would decide to keep. cpp :: Posn -> SymTab HashDefine -> [String] -> BoolOptions -> KeepState -> [String] -> IO [(Posn,String)]++cpp _ _ _ _ (Keep ps) [] | not (null ps) = do+ hPutStrLn stderr $ "Unmatched #if: positions of open context are:\n"+++ unlines (map show ps)+ return [] cpp _ _ _ _ _ [] = return [] -cpp p syms path options Keep (l@('#':x):xs) =+cpp p syms path options (Keep ps) (l@('#':x):xs) = let ws = words x cmd = head ws line = tail ws@@ -71,67 +77,70 @@ rest = tail (tail ws) def = defineMacro options (sym++" "++ maybe "1" id (un rest)) un v = if null v then Nothing else Just (unwords v)- keepIf p = if p then Keep else (Drop 1 False)+ keepIf b = if b then Keep (p:ps) else Drop 1 False (p:ps) skipn syms' retain ud xs' = let n = 1 + length (filter (=='\n') l) in (if macros options && retain then emitOne (p,reslash l) else emitMany (replicate n (p,""))) $ cpp (newlines n p) syms' path options ud xs' in case cmd of- "define" -> skipn (insertST def syms) True Keep xs- "undef" -> skipn (deleteST sym syms) True Keep xs+ "define" -> skipn (insertST def syms) True (Keep ps) xs+ "undef" -> skipn (deleteST sym syms) True (Keep ps) xs "ifndef" -> skipn syms False (keepIf (not (definedST sym syms))) xs "ifdef" -> skipn syms False (keepIf (definedST sym syms)) xs "if" -> skipn syms False (keepIf (gatherDefined p syms (unwords line))) xs- "else" -> skipn syms False (Drop 1 False) xs- "elif" -> skipn syms False (Drop 1 True) xs- "endif" -> skipn syms False Keep xs- "pragma" -> skipn syms True Keep xs- ('!':_) -> skipn syms False Keep xs -- \#!runhs scripts+ "else" -> skipn syms False (Drop 1 False ps) xs+ "elif" -> skipn syms False (Drop 1 True ps) xs+ "endif" | null ps ->+ do hPutStrLn stderr $ "Unmatched #endif at "++show p+ return []+ "endif" -> skipn syms False (Keep (tail ps)) xs+ "pragma" -> skipn syms True (Keep ps) xs+ ('!':_) -> skipn syms False (Keep ps) xs -- \#!runhs scripts "include"-> do (inc,content) <- readFirst (file syms (unwords line)) p path (warnings options)- cpp p syms path options Keep (("#line 1 "++show inc)- : linesCpp content+ cpp p syms path options (Keep ps)+ (("#line 1 "++show inc): linesCpp content ++ cppline (newline p): xs) "warning"-> if warnings options then do hPutStrLn stderr (l++"\nin "++show p)- skipn syms False Keep xs- else skipn syms False Keep xs+ skipn syms False (Keep ps) xs+ else skipn syms False (Keep ps) xs "error" -> error (l++"\nin "++show p) "line" | all isDigit sym -> (if locations options && hashline options then emitOne (p,l) else if locations options then emitOne (p,cpp2hask l) else id) $ cpp (newpos (read sym) (un rest) p)- syms path options Keep xs+ syms path options (Keep ps) xs n | all isDigit n -> (if locations options && hashline options then emitOne (p,l) else if locations options then emitOne (p,cpp2hask l) else id) $ cpp (newpos (read n) (un (tail ws)) p)- syms path options Keep xs+ syms path options (Keep ps) xs | otherwise -> if warnings options then do hPutStrLn stderr ("Warning: unknown directive #"++n ++"\nin "++show p) emitOne (p,l) $- cpp (newline p) syms path options Keep xs+ cpp (newline p) syms path options (Keep ps) xs else emitOne (p,l) $- cpp (newline p) syms path options Keep xs+ cpp (newline p) syms path options (Keep ps) xs -cpp p syms path options (Drop n b) (('#':x):xs) =+cpp p syms path options (Drop n b ps) (('#':x):xs) = let ws = words x cmd = head ws- delse | n==1 && b = Drop 1 b- | n==1 = Keep- | otherwise = Drop n b- dend | n==1 = Keep- | otherwise = Drop (n-1) b+ delse | n==1 && b = Drop 1 b ps+ | n==1 = Keep ps+ | otherwise = Drop n b ps+ dend | n==1 = Keep (tail ps)+ | otherwise = Drop (n-1) b (tail ps) delif s | n==1 && not b && gatherDefined p syms s- = Keep- | otherwise = Drop n b+ = Keep ps+ | otherwise = Drop n b ps skipn ud xs' = let n' = 1 + length (filter (=='\n') x) in emitMany (replicate n' (p,"")) $@@ -139,17 +148,20 @@ in if cmd == "ifndef" || cmd == "if" ||- cmd == "ifdef" then skipn (Drop (n+1) b) xs+ cmd == "ifdef" then skipn (Drop (n+1) b (p:ps)) xs else if cmd == "elif" then skipn (delif (unwords (tail ws))) xs else if cmd == "else" then skipn delse xs- else if cmd == "endif" then skipn dend xs- else skipn (Drop n b) xs+ else if cmd == "endif" then+ if null ps then do hPutStrLn stderr $ "Unmatched #endif at "++show p+ return []+ else skipn dend xs+ else skipn (Drop n b ps) xs -- define, undef, include, error, warning, pragma, line -cpp p syms path options Keep (x:xs) =+cpp p syms path options (Keep ps) (x:xs) = let p' = newline p in seq p' $- emitOne (p,x) $ cpp p' syms path options Keep xs-cpp p syms path options d@(Drop _ _) (_:xs) =+ emitOne (p,x) $ cpp p' syms path options (Keep ps) xs+cpp p syms path options d@(Drop _ _ _) (_:xs) = let p' = newline p in seq p' $ emitOne (p,"") $ cpp p' syms path options d xs
cpphs.cabal view
@@ -1,6 +1,6 @@ Name: cpphs-Version: 1.13.2-Copyright: 2004-2011, Malcolm Wallace+Version: 1.13.3+Copyright: 2004-2012, Malcolm Wallace License: LGPL License-File: LICENCE-LGPL Cabal-Version: >= 1.6@@ -20,7 +20,7 @@ off macro-expansion. Category: Development Build-type: Simple-Extra-Source-Files: README, LICENCE-GPL, LICENCE-commercial+Extra-Source-Files: README, LICENCE-GPL, LICENCE-commercial, CHANGELOG, docs/cpphs.1, docs/index.html Library Build-Depends: base>3&&<6, old-locale, old-time, directory
+ docs/cpphs.1 view
@@ -0,0 +1,276 @@+.TH CPPHS 1 2004-10-01 "cpphs version 0.9" "User Manual"++.SH NAME+cpphs \- liberalised cpp-a-like preprocessor for Haskell++.SH SYNOPSIS+.B cpphs+[\fIFILENAME\fR|\fIOPTION\fR]...++.SH DESCRIPTION+.ds c \fIcpphs\fP+\*c is a liberalised re-implementation of+.B cpp (1),+the C pre-processor, in and for Haskell.+.PP+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:+.IP+For some Haskell systems, notably Hugs on Windows, a true cpp+is not available by default.+.IP+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.+.PP+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.+.PP+\*c is pretty-much feature-complete,+and compatible with the+.B \-traditional+style of cpp.+It has two modes:+.IP+conditional compilation only (\fB\-\-nomacro\fR),+.IP+and full macro-expansion (default).+.PP+In+.B \-\-nomacro+mode, \*c performs only conditional compilation actions, i.e.+\fB#include\fR's, \fB#if\fR's, and \fB#ifdef\fR'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.+.PP+Working Features:+.TP+.B #ifdef+simple conditional compilation+.TP+.B #if+the full boolean language of defined(), &&, ||, ==, etc.+.TP+.B #elif+chained conditionals+.TP+.B #define+in-line definitions (text replacements and macros)+.TP+.B #undef+in-line revocation of definitions+.TP+.B #include+file inclusion+.TP+.B #line+line number directives+.TP+.B \\\\n+line continuations within all # directives+.TP+.B /**/+token catenation within a macro definition+.TP+.B ##+ANSI-style token catenation+.TP+.B #+ANSI-style token stringisation+.TP+.B __FILE__+special text replacement for DIY error messages+.TP+.B __LINE__+special text replacement for DIY error messages+.TP+.B __DATE__+special text replacement+.TP+.B __TIME__+special text replacement+.PP+Macro expansion is recursive. Redefinition of a macro name does not+generate a warning. Macros can be defined on the command-line with+.B \-D+just like textual replacements. Macro names are permitted to be+Haskell identifiers e.g. with the prime \(ga and backtick \(aa characters,+which is slightly looser than in C, but they still may not include+operator symbols.+.PP+Numbering of lines in the output is preserved so that any later+processor can give meaningful error messages. When a file is+\fB#include\fR'd, \*c inserts+.B #line+directives for the same reason. Numbering should be correct+even in the presence of line continuations. If you don't want+.B #line+directives in the final output, use the+.B \-\-noline+option.+.PP+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.+.PP+You can give any number of filenames on the command-line. The+results are catenated on standard output.+.TP+.B \-D\fIsym\fR+define a textual replacement (default value is 1)+.TP+.B \-Dsym=\fIval\fR+define a textual replacement with a specific value+.TP+.B \-I\fIpath\fR+add a directory to the search path for #include's+.TP+.B \-O\fIfile\fR+specify a file for output (default is stdout)+.TP+.B \-\-nomacro+only process #ifdef's and #include's,+ do not expand macros+.TP+.B \-\-noline+remove #line droppings from the output+.TP+.B \-\-strip+convert C-style comments to whitespace, even outside+ cpp directives+.TP+.B \-\-hashes+recognise the ANSI # stringise operator, and ## for+ token catenation, within macros+.TP+.B \-\-text+treat the input as plain text, not Haskell code+.TP+.B \-\-layout+preserve newlines within macro expansions+.TP+.B \-\-unlit+remove literate-style comments+.TP+.B \-\-version+report version number of cpphs and stop+.PP+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+.B \-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).++.SH "DIFFERENCES FROM CPP"+.PP+In general, cpphs is based on the+.B \-traditional+behaviour, not ANSI C, and has the following main differences from the+standard cpp.++.B General+.PP+The+.B #+that introduces any cpp directive must be in the first+column of a line (whereas ANSI permits whitespace before the+.B #+).+.PP+Generates the+.B "#line \fIn\fR \(dq\fIfilename\fR\(dq"+syntax, not the+.B "# \fIn\fR \(dq\fIfilename\fR\(dq"+variant.+.PP+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:+.B /* */ */*+However, you can turn on C-comment removal with the+.B \-\-strip+option.++.B Macro language+.PP+Accepts+.B /**/+for token-pasting in a macro definition.+However,+.B /* */+(with any text between the open/close comment) inserts whitespace.+.PP+The ANSI+.B ##+token-pasting operator is available with+the+.B \-\-hashes+flag. This is to avoid misinterpreting+any valid Haskell operator of the same name.+.PP+Replaces a macro formal parameter with the actual, even inside a+string (double or single quoted). This is \-traditional behaviour,+not supported in ANSI.+.PP+Recognises the+.B #+stringisation operator in a macro+definition only if you use the+.B \-\-hashes+option. (It is+an ANSI addition, only needed because quoted stringisation (above)+is prohibited by ANSI.)+.PP+Preserves whitespace within a textual replacement definition+exactly (modulo newlines), but leading and trailing space is eliminated.+.PP+Preserves whitespace within a macro definition (and trailing it)+exactly (modulo newlines), but leading space is eliminated.+.PP+Preserves whitespace within macro call arguments exactly+(including newlines), but leading and trailing space is eliminated.+.PP+With the+.B \-\-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.)++.SH BUGS+Bug reports, and any other feedback, should be sent to+Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>+.SH COPYRIGHT+Copyright \(co 2004-2005 Malcolm Wallace,+except for ParseLib (Copyright \(co 1995 Graham Hutton and Erik Meijer).+.PP+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+.B Main.hs+itself is GPL.+.SH "SEE ALSO"+.BR cpp (1)++.SH AUTHOR++This manual page was written, based on \fBindex.html\fR,+by Ian Lynagh <igloo@debian.org> for the Debian+system (but may be used by others).++
+ docs/index.html view
@@ -0,0 +1,613 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">+<html>+<head>+<title>+ cpphs+</title>+</head>+ +<body bgcolor='#ffffff'>++<center>+<h1>cpphs</h1>+<table><tr><td width=200 align=center>+<a href="#what">What is cpphs?</a><br>+<a href="#how">How do I use it?</a><br>+<a href="#download">Downloads</a><br>+</td><td width=200 align=center>+<a href="#diff">Differences to cpp</a><br>+<a href="#library">cpphs as a library</a><br>+<a href="#who">Contacts</a><br>+</td></tr></table>+</center>+<hr>++<center><h3><a name="what">What is cpphs?</a></h3></center>+<p>+<b>cpphs</b> is a liberalised re-implementation of+<a href="http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp.html">cpp</a>,+the C pre-processor, in <a href="http://haskell.org/">Haskell</a>.++<p>+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:+<ul>+ <li> For some Haskell systems, notably Hugs on Windows, a true cpp+ is not available by default.+ <li> Even for the other Haskell systems, the common cpp provided by+ the gcc 3.x and 4.x series has changed 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.+</ul>+So, it seemed right to provide an alternative to cpp, both more+compatible with Haskell, and itself written in Haskell so that it+can be distributed with compilers.++<p>+This version of the C pre-processor is pretty-much feature-complete,+and compatible with the <tt>-traditional</tt> style.+It has two main modes:+<ul>+ <li> conditional compilation only (--nomacro),+ <li> and full macro-expansion (default).+</ul>+In <tt>--nomacro</tt> mode, cpphs performs only conditional compilation+actions, namely <tt>#include</tt>'s, <tt>#if</tt>'s, and+<tt>#ifdef</tt>'s are processed according to text-replacement+definitions and macro expansions (both command-line and internal).+In full compatibility mode (the default), textual replacements and macro+expansions are also processed in the remaining body of non-cpp text.++<p>+Source language features:+<table border=0 align=center>+<tr><td>#ifdef</td> <td>simple conditional compilation</td></tr>+<tr><td>#if</td> <td>the full boolean language of defined(),+ &&, ||, ==, etc.</td></tr>+<tr><td>#elif</td> <td>chained conditionals</td></tr>+<tr><td>#define</td> <td>in-line definitions (text replacements and macros)</td></tr>+<tr><td>#undef</td> <td>in-line revocation of definitions</td></tr>+<tr><td>#include</td><td>file inclusion</td></tr>+<tr><td>#line</td> <td>line number directives</td></tr>+<tr><td>#pragma</td> <td>cpp pragmas (ignored)</td></tr>+<tr><td>\\n</td> <td>line continuations within all # directives</td></tr>+<tr><td>/**/</td> <td>token catenation within a macro definition</td></tr>+<tr><td>##</td> <td>ANSI-style token catenation</td></tr>+<tr><td>#</td> <td>ANSI-style token stringisation</td></tr>+<tr><td>__FILE__</td><td>special text replacement for DIY error messages</td></tr>+<tr><td>__LINE__</td><td>special text replacement for DIY error messages</td></tr>+<tr><td>__DATE__</td><td>special text replacement</td></tr>+<tr><td>__TIME__</td><td>special text replacement</td></tr>+</table>++<p>+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.++<p>+Numbering of lines in the output is preserved so that any later+processor can give meaningful error messages. When a file is+<tt>#include</tt>'d, cpphs inserts <tt>#line</tt> directives for the+same reason. Numbering should be correct even in the presence of+line continuations. If you don't want <tt>#line</tt> directives in+the final output, use the <tt>--noline</tt> option, or if you would+prefer them in <tt>{-# LINE #-}</tt> Haskell pragma format, use the+<tt>--linepragma</tt> option.++<p>+Any syntax error in a cpp directive gives a warning message to stderr.+Failure to find a #include'd file also produces a warning to stderr. In+both cases, processing continues on the rest of the input.++<hr>+<center><h3><a name="how">How do I use it?</a></h3></center>+<p>+<center><pre>+Usage: cpphs [ filename | -Dsym | -Dsym=val | -Ipath ]+ [-Ofile]+ [--include=file]*+ [--nomacro] [--noline] [--linepragma] [--nowarn] [--pragma]+ [--strip] [--strip-eol]+ [--text] [--hashes] [--layout] [--unlit]+ [ --cpp compatopts ]+ cpphs --version +</pre></center>+<p>+You can give any number of filenames on the command-line. The results+are catenated on standard output. (Macro definitions in one file do not+carry over into the next.) If no filename is given, cpphs reads from+standard input.++<p> <em>Note:</em> if you wish to use cpphs as a replacement for gcc's+cpp in conjunction with the ghc compiler then the extra options you need+to give to ghc are these:+<pre>+ -cpp -pgmPcpphs -optP--cpp+</pre>++<p>+Options:+<table border=0 align=center>+<tr><td>-Dsym</td>+ <td>define a textual replacement (default value is 1)</td></tr>+<tr><td>-Dsym=val</td>+ <td>define a textual replacement with a specific value</td></tr>+<tr><td>-Dsym(args)=val</td>+ <td>define a macro with arguments</td></tr>+<tr><td>-Ipath</td>+ <td>add a directory to the search path for #include's</td></tr>+<tr><td>-Ofile</td>+ <td>specify a file for output (default is stdout)</td></tr>+<tr><td>--include=file</td>+ <td>#include the given file at the start of the input</td></tr>+<tr><td>--nomacro</td>+ <td>only process #ifdef's and #include's, do not expand macros</td></tr>+<tr><td>--noline</td>+ <td>remove #line droppings from the output</td></tr>+<tr><td>--linepragma</td>+ <td>convert #line droppings into {-# LINE #-} format</td></tr>+<tr><td>--nowarn</td>+ <td>suppress messages from missing #include files, or #warning</td></tr>+<tr><td>--pragma</td>+ <td>retain #pragma in the output (normally removed)</td></tr>+<tr><td>--strip</td>+ <td>convert traditional C-style comments (not eol //) to whitespace,+ even outside cpp directives</td></tr>+<tr><td>--strip-eol</td>+ <td>convert modern C-style comments (including /**/ and //) to whitespace,+ even outside cpp directives</td></tr>+<tr><td>--hashes</td>+ <td>recognise the ANSI # stringise operator, and ## for+ token catenation, within macros</td></tr>+<tr><td>--text</td>+ <td>treat input as plain text, not Haskell code</td></tr>+<tr><td>--layout</td>+ <td>preserve newlines within macro expansions</td></tr>+<tr><td>--unlit</td>+ <td>unlit literate source code</td></tr>+<tr><td>--cpp compatopts</td>+ <td>accept standard cpp options: -o, -x, -ansi, -traditional,+ -P, -C, -A, etc</td></tr>+<tr><td>--version</td>+ <td>report version number of cpphs and stop</td></tr>+</table>++<p>+There are NO textual replacements defined by default. (Normal cpp+usually has definitions for machine, OS, etc. You can easily create+a wrapper script if you need these.) 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 (unless you define one via a wrapper script).+++<hr>+<center><h3><a name="download">Downloads</a></h3></center>++<p>+<b>Current stable version:</b>++<p>+cpphs-1.13, release date 2011.09.26<br>+By HTTP:+<a href="http://code.haskell.org/cpphs/cpphs-1.13.tar.gz">.tar.gz</a>,+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.+<ul>+<li> Accept the -U commandline option for compatibility with cpp.+</ul>++<p>+<b>Development:</b>+<p>+The current <a href="http://darcs.net/">darcs</a> repository of+cpphs is available at+<pre>+ darcs get http://code.haskell.org/cpphs+</pre>+(Users on Windows or MacOS filesystems may need to use the+<tt>--partial</tt> flag.) <!-- The source tree and version history can+be browsed on-line through+<a href="http://www.cs.york.ac.uk/fp/darcs/">darcsweb</a>. -->+What's new, over and above the latest stable release?+<ul>+<li> Nothing since last release.+</ul>++<p>+<b>Older versions:</b>++<p>+cpphs-1.12, release date 2011.06.26<br>+By HTTP:+<a href="http://code.haskell.org/cpphs/cpphs-1.12.tar.gz">.tar.gz</a>,+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.+<ul>+<li> Compatibility fixes for ghc-7.2.+</ul>++<p>+cpphs-1.11, release date 2010.01.31<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.11.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.11.zip">.zip</a>,+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.+<ul>+<li> Major API change: runCpphs, cppIfdef and macroPass are now in the IO monad.+</ul>++<p>+cpphs-1.10, release date 2010.01.30<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.10.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.10.zip">.zip</a>,+<ul>+<li> New command-line flag: --linepragma+</ul>++<p>+cpphs-1.9, release date 2009.09.07<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.9.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.9.zip">.zip</a>.+<ul>+<li> Bugfix for #undef.+</ul>++<p>+cpphs-1.8, release date 2009.08.06<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.8.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.8.zip">.zip</a>.+<ul>+<li> Bugfix for off-by-one error in line numbers with --include=file.+</ul>++<p>+cpphs-1.7, release date 2009.06.22<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.7.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.7.zip">.zip</a>.+<ul>+<li> Bugfix for --unlit interaction with \end{code}.+</ul>++<p>+cpphs-1.6, release date 2008.10.09<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.6.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.6.zip">.zip</a>.+<ul>+<li> New option <tt>--include=filename</tt>, compatible with cpp's+ <tt>-include filename</tt>.+<li> New option <tt>--strip-eol</tt> now strips C eol <tt>//</tt> comments+ in addition to <tt>/**/</tt>.+<li> Line pragmas can now have filenames containing spaces.+<li> Bugfix for cpp directives within <tt>{- -}</tt> Haskell comments.+</ul>+<p>+cpphs-1.5, release date 2007.06.05<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.5.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.5.zip">.zip</a>.+<a href="http://www.cs.york.ac.uk/fp/cpphs-1.5-win32.zip">Windows binary</a>,+<ul>+<li> Fixed some more obscure corner cases, involving parameterised macro+ expansion within conditionals e.g. #if FOO(BAR,QUUX)+<li> Internal refactoring, affecting parts of the library API.+</ul>++<p>+cpphs-1.4, release date 2007.04.17<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.4.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.4.zip">.zip</a>.+<ul>+<li> Added a "--pragma" option to retain #pragma in the output.+<li> Fixed a number of obscure corner cases involving the interaction of+ multiple features e.g. foo##__LINE__.+<li> Added the "--nowarn" option.+</ul>++<p>+cpphs-1.3, release date 2006.10.09<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.3.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.3.zip">.zip</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs-1.3-win32.zip">Windows binary</a>.+<ul>+<li> Added a "--cpp" option for drop-in compatibility with standard cpp.+ It causes cpphs to accept standard cpp flags and translate+ them to cpphs equivalents. Compatibility options include: -o, -ansi,+ -traditional, -stdc, -x, -include, -P, -C, -CC, -A. The file+ behaviour is different too - if two filenames are given on the+ commandline, then the second is treated as the output location.+<li> Fixed a corner-case bug in evaluating chained and overlapping #ifdefs.+</ul>++<p>+cpphs-1.2, release date 2006.05.04<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.2.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.2.zip">.zip</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs-1.2-win32.zip">Windows binary</a>.+<ul>+<li> Re-arranged the source files into hierarchical libraries.+<li> Exposed the library interface as an installable Cabal package, with+ Haddock documentation.+<li> Added the --unlit option, for removing literate-style comments.+</ul>++<p>+cpphs-1.1, release date 2005.10.14<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.1.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.1.zip">.zip</a>.+<ul>+<li> Fixed the .cabal way of building cpphs.+<li> Update the --version reported (forgotten in 1.0, which still+ mistakenly reports 0.9).+<li> No longer throws an error on an empty file.+</ul>++<p>+cpphs-1.0, release date 2005.10.05<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.0.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-1.0.zip">.zip</a>.+<ul>+<li> Included the <tt>cpphs.compat</tt> script for argument+ compatibility with the original <em>cpp</em>.+<li> Placed quotes around replacements for special macros __FILE__, __DATE__,+ and __TIME__.+<li> If no files are specified, read from stdin.+<li> Ignore #! lines (e.g. in scripts)+<li> Parse -D commandline options consistently with cpp,+ i.e. -Dfoo means foo=1+<li> Fix compatibility with preprocessors like hsc2hs, which use+ non-cpp directives like #def. They are now passed through to the+ output with a warning to stderr.+</ul>++<p>+cpphs-0.9, release date 2005.03.17<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.9.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.9.zip">.zip</a>.+<ul>+<li> Bugfix for <tt>ghc-6.4 -O</tt>: flush output buffer.+</ul>++<p>+cpphs-0.8, release date 2004.11.14<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.8.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.8.zip">.zip</a>.+<ul>+<li> Added the <tt>--text</tt> option, to signify the input should not+ be lexed as Haskell. This causes macros to be defined or expanded+ regardless of their location within comments, string delimiters, etc.+<li> Shuffled some source files around - there is now a runhugs script+ to invoke cpphs nicely.+</ul>++<p>+cpphs-0.7, release date 2004.09.01<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.7.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.7.zip">.zip</a>.+<ul>+<li> Enable the <tt>__FILE__</tt>, <tt>__LINE__</tt>, <tt>__DATE__</tt>,+ and <tt>__TIME__</tt> specials, which can be useful for creating+ DIY error messages.+</ul>++<p>+cpphs-0.6, release date 2004.07.30<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.6.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.6.zip">.zip</a>.+<ul>+<li> Recognise and ignore the <tt>#pragma</tt> cpp directive.+<li> Fix beginning-of-file bug, where in <tt>--noline</tt> mode, a+ <tt>#line</tt> cpp directive appeared at the top of the output file.+<li> Fix chained parenthesised boolean exprs in <tt>#if</tt>, e.g.+ <pre>#if ( foo ) && ( bar )</pre>+<li> Fix precedence in chained unparenthesised boolean exprs in+ <tt>#if</tt>, e.g.+ <pre>#if foo && bar || baz && frob</pre>+<li> For better compatibility with cpp, and because otherwise+ there are certain constructs that cannot be expressed, we no+ longer permit whitespace in a <tt>#define</tt> between the+ symbolname and an opening parenthesis, e.g. + <pre>#define f (f' id)</pre>. Previously, this was interpreted+ as a parametrised macro, with arguments in the parens, and+ no expansion. Now, the space indicates that this is a textual+ replacement, and the parenthesised expression is in fact the+ replacement.+</ul>++<p>+cpphs-0.5, release date 2004.06.07<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.5.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.5.zip">.zip</a>.+<ul>+<li> Added a --version flag to report the version number.+<li> Renamed --stringise to --hashes, and use it to turn on ## catenation+ as well.+<li> Bugfix for <tt>#if 1</tt>, previously interpreted as false.+<li> Bugfix for --nolines: it no longer adds extra spurious newlines.+<li> File inclusion now looks in the directory of the calling file.+<li> Failure to find an include file is now merely a warning to stderr+ rather than an error.+<li> Added a --layout flag. Previously, line continuations in a macro+ definition were always preserved in the output, permitting use+ of the Haskell layout rule even inside a macro. The default is now+ to remove line continuations for conformance with cpp, but the option+ of using --layout is still possible.+</ul>++<p>+cpphs-0.4, release date 2004.05.19<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.4.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.4.zip">.zip</a>.+<ul>+<li> New flag -Ofile to redirect output+<li> Bugfix for precedence of ! in #if !False && False+<li> Bugfix for whitespace permitted between # and if+<li> Bugfix for <tt>#define F "blah"; #include F</tt>+</ul>++<p>+cpphs-0.3, release date 2004.05.18<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.3.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.3.zip">.zip</a>.+<p>+Fix recursive macro expansion bug. Added option to strip C comments.+Added option to recognise the # stringise operator.++<p>+cpphs-0.2, release date 2004.05.15<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.2.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.2.zip">.zip</a>.+<p>+Implements textual replacement and macro expansion.++<p>+cpphs-0.1, release date 2004.04.07<br>+By HTTP:+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.1.tar.gz">.tar.gz</a>,+<a href="http://www.cs.york.ac.uk/fp/cpphs/cpphs-0.1.zip">.zip</a>.+<p>+Initial release: implements conditional compilation and file inclusion only.+++<p>+<b>Building instructions</b>+<p>+To build cpphs, use+<pre> hmake cpphs [-package base]+</pre>+or+<pre> ghc --make cpphs [-o cpphs]+</pre>+or+<pre> mv cpphs.hugs cpphs # a simple runhugs script+</pre>++<p>+You will notice that the command-line arguments for <em>cpphs</em>+are not the same as for the original <em>cpp</em>. If you want+to use <em>cpphs</em> as a completely drop-in replacement for+the real <em>cpp</em>, that is, to accept the same arguments, and+have broadly the same behaviour in response to them, then use the+<tt>--cpp</tt> compatibility option as the first commandline flag.+++<hr>+<center><h3><a name="diff">Differences from cpp</a></h3></center>+<p>+In general, cpphs is based on the <tt>-traditional</tt> behaviour, not+ANSI C, and has the following main differences from the standard cpp.++<p>+<b>General</b>+<ul>+<li> The <tt>#</tt> that introduces any cpp directive must be in the first+ column of a line (whereas ANSI permits whitespace before the <tt>#</tt>).+<li> Generates the <tt>#line n "filename"</tt> syntax, not the <tt># n+ "filename"</tt> variant.+<li> 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: <tt>/*+ */ */*</tt> However, you can turn on C-comment removal with the+ <tt>--strip</tt> option.+<li> Macros are never expanded within Haskell comments, strings,+ or character constants, unless you give the <tt>--text</tt> option to+ disable lexing the input as Haskell.+<li> Macros are always expanded recursively, unlike ANSI, which detects+ and prevents self-recursion. For instance, <tt>#define foo x:foo</tt>+ expands <tt>foo</tt> once only to <tt>x:foo</tt> in ANSI, but in cpphs+ it becomes an infinite list <tt>x:x:x:x:...</tt>, i.e. cpphs does not+ terminate.+</ul>+<p>+<b>Macro definition language</b>+<ul>+<li> Accepts <tt>/**/</tt> for token-pasting in a macro definition.+ However, <tt>/* */</tt> (with any text between the open/close+ comment) inserts whitespace.+<li> The ANSI <tt>##</tt> token-pasting operator is available with+ the <tt>--hashes</tt> flag. This is to avoid misinterpreting+ any valid Haskell operator of the same name.+<li> Replaces a macro formal parameter with the actual, even inside a+ string (double or single quoted). This is -traditional behaviour,+ not supported in ANSI.+<li> Recognises the <tt>#</tt> stringisation operator in a macro+ definition only if you use the <tt>--hashes</tt> option. (It is+ an ANSI addition, only needed because quoted stringisation (above)+ is prohibited by ANSI.)+<li> Preserves whitespace within a textual replacement definition+ exactly (modulo newlines), but leading and trailing space is eliminated.+<li> Preserves whitespace within a macro definition (and trailing it)+ exactly (modulo newlines), but leading space is eliminated.+<li> Preserves whitespace within macro call arguments exactly+ (including newlines), but leading and trailing space is eliminated.+<li> With the <tt>--layout</tt> 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.)+</ul>++<hr>+<center><h3><a name="library">cpphs as a library</a></h3></center>+<p>+You can use cpphs as a library from within a Haskell program. The main+interface is in <tt>Language.Preprocessor.Cpphs</tt>. Haddock+documentation is <a href="cpphs/">here</a>. To make the library+available to your haskell compiler, you must install the cpphs package+using Cabal.++<hr>+<center><h3><a name="who">Contacts</a></h3></center>+<p>+I am interested in hearing your feedback on cpphs. Bug reports+especially welcome. You can send feature requests too, but I won't+guarantee to implement them if they depart much from the ordinary+cpp's behaviour. Please mail+<ul>+<li> <a href="mailto:Malcolm.Wallace@me.com">+ Malcolm.Wallace@me.com</a> +</ul>++<p><b>Copyright:</b> © 2004-2011 Malcolm Wallace,+except for ParseLib (Copyright © 1995 Graham Hutton and Erik Meijer)++<p><b>License:</b> The library modules in cpphs are distributed under+the terms of the LGPL (see file <a href="LICENCE-LGPL">LICENCE-LGPL</a>+for more details). If that's a problem for you, contact me to make+other arrangements. The application module 'cpphs.hs' itself is GPL+(see file <a href="LICENCE-GPL">LICENCE-GPL</a>). If you have a+commercial use for cpphs and find the terms of the (L)GPL too onerous,+you can instead choose to distribute unmodified binaries (not source),+under the terms of <a href="LICENCE-commercial">LICENCE-commercial</a>++<p>+This software comes with no warranty. Use at your own risk.++<hr>+ +</body>+</html>