diff --git a/CHANGELOG b/CHANGELOG
deleted file mode 100644
--- a/CHANGELOG
+++ /dev/null
@@ -1,159 +0,0 @@
-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.
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,232 @@
+Version 1.20.10
+---------------
+
+_Andreas Abel, 2025-09-14_
+
+  * Drop support for GHC 7.
+  * Remove cabal flag `old-locale`.
+  * Compatibility with `{-# LANGUAGE RecordDotSyntax #-}` (Lennart Augustsson).
+  * Build tested with GHC 8.0 - 9.14 alpha1.
+
+Version 1.20
+------------
+  * bugfixes for `#if defined(FOO) && FOO(a,b)`
+  * (1.20.1): fix version number
+  * (1.20.2): ensure all input/output is UTF8, regardless of locale
+  * (1.20.3): detect an absolute windows path with a drive letter in a #include
+  * (1.20.4): more windows path handling
+  * (1.20.5): revert change in 1.20.4
+  * (1.20.6): minor bugfix for crash in obscure corner case
+  * (1.20.7): bugfix for windows drive letter in #include
+  * (1.20.8): another bugfix for windows drive letter in #include
+
+Version 1.19
+------------
+  * expose more of the cpphs API
+  * allow the static linking exception to the LGPL
+  * (1.19.1): don't warn about trailing comments in #ifdefs
+  * (1.19.2): fix build error
+  * (1.19.3): bugfix for hlint ticket #161 - interaction of --unlit/--linepragma
+
+Version 1.18
+------------
+  * better lexing of Template Haskell single quotes (thanks to Stefan Wehr)
+  * (1.18.1): fix incomplete pattern match
+  * (1.18.2): bugfix for erroneous boolean intepretation of some macro
+              expansions in #if clauses
+  * (1.18.3): further rewrites of the #if expression parser
+  * (1.18.4): fix the accidental flipping of comment-stripping behaviour
+              with --cpp -traditional flags
+  * (1.18.5): fix a bug with windows filepath directory separators in a
+              #include
+  * (1.18.6): bugfix to reject a macro usage with different arity than
+              its definition
+  * (1.18.7): bugfix to accept a #include with absolute filepath
+  * (1.18.8): fix version number
+  * (1.18.9): accept #if defined foo as well as #if defined(foo)
+
+Version 1.17
+------------
+  * recursively evaluate #if expressions after macro expansion (fix)
+  * (1.17.1): report the right version with cpphs --version
+
+Version 1.16
+------------
+  * fix interaction of runCpphsReturningSymTab with --nomacro
+
+Version 1.15
+------------
+  * Fix the interaction of --nomacro with --strip.
+  * Fix the error message received when # appears without a command.
+
+Version 1.14
+------------
+  * New API to return symbol table after processing.
+
+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.
diff --git a/LICENCE-GPL b/LICENCE-GPL
--- a/LICENCE-GPL
+++ b/LICENCE-GPL
@@ -2,7 +2,7 @@
 		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
diff --git a/LICENCE-LGPL b/LICENCE-LGPL
--- a/LICENCE-LGPL
+++ b/LICENCE-LGPL
@@ -2,7 +2,7 @@
                        Version 2.1, February 1999
 
  Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
diff --git a/LICENCE-commercial b/LICENCE-commercial
new file mode 100644
--- /dev/null
+++ b/LICENCE-commercial
@@ -0,0 +1,29 @@
+Commercial licence for cpphs.
+
+Copyright 2004-2010, Malcolm Wallace (malcolm.wallace@me.com)
+All rights reserved.
+
+* This software, built from original unmodified sources, may be used for
+  any purpose whatsoever, without restriction.
+
+* Redistribution in binary form, without modification, is permitted
+  provided that the above copyright notice, these conditions and the
+  following disclaimer are reproduced in the documentation and/or other
+  materials provided with the distribution.
+
+* Redistribution in source form, with or without modification, is not
+  permitted under this license.
+
+THIS SOFTWARE IS PROVIDED BY Malcolm Wallace
+AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+Malcolm Wallace OR THE CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
diff --git a/Language/Preprocessor/Cpphs.hs b/Language/Preprocessor/Cpphs.hs
--- a/Language/Preprocessor/Cpphs.hs
+++ b/Language/Preprocessor/Cpphs.hs
@@ -12,15 +12,23 @@
 -----------------------------------------------------------------------------
 
 module Language.Preprocessor.Cpphs
-  ( runCpphs, cppIfdef, macroPass, CpphsOptions(..), BoolOptions(..)
+  ( runCpphs, runCpphsPass1, runCpphsPass2, runCpphsReturningSymTab
+  , cppIfdef, tokenise, WordStyle(..)
+  , macroPass, macroPassReturningSymTab
+  , CpphsOptions(..), BoolOptions(..)
   , parseOptions, defaultCpphsOptions, defaultBoolOptions
   , module Language.Preprocessor.Cpphs.Position
   ) where
 
 import Language.Preprocessor.Cpphs.CppIfdef(cppIfdef)
-import Language.Preprocessor.Cpphs.MacroPass(macroPass)
-import Language.Preprocessor.Cpphs.RunCpphs(runCpphs)
+import Language.Preprocessor.Cpphs.MacroPass(macroPass
+                                            ,macroPassReturningSymTab)
+import Language.Preprocessor.Cpphs.RunCpphs(runCpphs
+                                           ,runCpphsPass1
+                                           ,runCpphsPass2
+                                           ,runCpphsReturningSymTab)
 import Language.Preprocessor.Cpphs.Options
        (CpphsOptions(..), BoolOptions(..), parseOptions
        ,defaultCpphsOptions,defaultBoolOptions)
 import Language.Preprocessor.Cpphs.Position
+import Language.Preprocessor.Cpphs.Tokenise
diff --git a/Language/Preprocessor/Cpphs/CppIfdef.hs b/Language/Preprocessor/Cpphs/CppIfdef.hs
--- a/Language/Preprocessor/Cpphs/CppIfdef.hs
+++ b/Language/Preprocessor/Cpphs/CppIfdef.hs
@@ -3,23 +3,23 @@
 -- Module      :  CppIfdef
 -- Copyright   :  1999-2004 Malcolm Wallace
 -- Licence     :  LGPL
--- 
+--
 -- 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.
 -----------------------------------------------------------------------------
 
 module Language.Preprocessor.Cpphs.CppIfdef
-  ( cppIfdef	-- :: FilePath -> [(String,String)] -> [String] -> Options
-		--      -> String -> IO [(Posn,String)]
+  ( cppIfdef    -- :: FilePath -> [(String,String)] -> [String] -> Options
+                --      -> String -> IO [(Posn,String)]
   ) where
 
 
+import Text.Parse
 import Language.Preprocessor.Cpphs.SymTab
-import Text.ParserCombinators.HuttonMeijer
 import Language.Preprocessor.Cpphs.Position  (Posn,newfile,newline,newlines
                                              ,cppline,cpp2hask,newpos)
 import Language.Preprocessor.Cpphs.ReadFirst (readFirst)
@@ -28,110 +28,119 @@
 import Language.Preprocessor.Cpphs.HashDefine(HashDefine(..),parseHashDefine
                                              ,expandMacro)
 import Language.Preprocessor.Cpphs.MacroPass (preDefine,defineMacro)
-import Char      (isDigit)
-import Numeric   (readHex,readOct,readDec)
+import Data.Char        (isDigit,isSpace,isAlphaNum)
+import Data.List        (intercalate,isPrefixOf)
+import Numeric          (readHex,readOct,readDec)
 import System.IO.Unsafe (unsafeInterleaveIO)
-import IO        (hPutStrLn,stderr)
-
+import System.IO        (hPutStrLn,stderr)
+import Control.Monad    (when)
 
 -- | Run a first pass of cpp, evaluating \#ifdef's and processing \#include's,
 --   whilst taking account of \#define's and \#undef's as we encounter them.
-cppIfdef :: FilePath		-- ^ File for error reports
-	-> [(String,String)]	-- ^ Pre-defined symbols and their values
-	-> [String]		-- ^ Search path for \#includes
-	-> BoolOptions		-- ^ Options controlling output style
-	-> String		-- ^ The input file content
-	-> IO [(Posn,String)]	-- ^ The file after processing (in lines)
+cppIfdef :: FilePath            -- ^ File for error reports
+        -> [(String,String)]    -- ^ Pre-defined symbols and their values
+        -> [String]             -- ^ Search path for \#includes
+        -> BoolOptions          -- ^ Options controlling output style
+        -> 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 []) . initial . linesCpp
   where
     posn = newfile fp
     defs = preDefine options syms
+    initial = if literate options then id else (cppline posn:)
 -- Previous versions had a very simple symbol table  mapping strings
 -- to strings.  Now the #ifdef pass uses a more elaborate table, in
 -- particular to deal with parameterised macros in conditionals.
 
 
 -- | 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
-        sym  = head (tail ws)
-        rest = tail (tail ws)
+        cmd = if null ws then "" else head ws
+        line = if null ws then [] else tail ws
+        sym  = if null line then "" else head line
+        rest = if null line then [] else tail line
         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
-	"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
-	"include"-> do (inc,content) <- readFirst (file syms (unwords line))
+        "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"     -> do b <- gatherDefined p syms (unwords line)
+                       skipn syms False (keepIf b) xs
+        "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
+        "warning"-> if warnings options then
                       do hPutStrLn stderr (l++"\nin "++show p)
-                         skipn syms False Keep xs
-                    else skipn syms False Keep xs
-	"error"  -> error (l++"\nin "++show p)
-	"line"   | all isDigit sym
-	         -> (if locations options && hashline options then emitOne (p,l)
+                         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
-	n | all isDigit n
-	         -> (if locations options && hashline options then emitOne (p,l)
+                        syms path options (Keep ps) xs
+        n | all isDigit n && not (null 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
+                    cpp (newpos (read n) (un (tail ws)) p)
+                        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
-                    else emitOne (p,l) $
-                                 cpp (newline p) syms path options Keep xs
+                 -> do when (warnings options) $
+                           hPutStrLn stderr ("Warning: unknown directive #"++n
+                                             ++"\nin "++show p)
+                       emitOne (p,l) $
+                               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
-        delif s  | n==1 && not b && gatherDefined p syms s
-                             = Keep
-                 | otherwise = Drop n b
+        cmd = if null ws then "" else head ws
+        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 v  | n==1 && not b && v
+                             = 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,21 @@
     in
     if      cmd == "ifndef" ||
             cmd == "if"     ||
-            cmd == "ifdef"  then  skipn (Drop (n+1) b) 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
-	-- define, undef, include, error, warning, pragma, line
+            cmd == "ifdef" then    skipn (Drop (n+1) b (p:ps)) xs
+    else if cmd == "elif"  then do v <- gatherDefined p syms (unwords (tail ws))
+                                   skipn (delif v) xs
+    else if cmd == "else"  then    skipn  delse 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
 
@@ -164,52 +177,142 @@
 
 
 ----
-gatherDefined :: Posn -> SymTab HashDefine -> String -> Bool
+gatherDefined :: Posn -> SymTab HashDefine -> String -> IO Bool
 gatherDefined p st inp =
-  case papply (parseBoolExp st) inp of
-    []      -> error ("Cannot parse #if directive in file "++show p)
-    [(b,_)] -> b
-    _       -> error ("Ambiguous parse for #if directive in file "++show p)
+  case runParser (preExpand st) inp of
+    (Left msg, _) -> error ("Cannot expand #if directive in file "++show p
+                           ++":\n    "++msg)
+    (Right s, xs) -> do
+--      hPutStrLn stderr $ "Expanded #if at "++show p++" is:\n  "++s
+        when (any (not . isSpace) xs) $
+             hPutStrLn stderr ("Warning: trailing characters after #if"
+                              ++" macro expansion in file "++show p++": "++xs)
 
-parseBoolExp :: SymTab HashDefine -> Parser Bool
-parseBoolExp st =
-  do  a <- parseExp1 st
-      skip (string "||")
-      b <- first (skip (parseBoolExp st))
-      return (a || b)
-  +++
-      parseExp1 st
+        case runParser parseBoolExp s of
+          (Left msg, _) -> error ("Cannot parse #if directive in file "++show p
+                                 ++":\n    "++msg)
+          (Right b, xs) -> do when (any (not . isSpace) xs && notComment xs) $
+                                   hPutStrLn stderr
+                                     ("Warning: trailing characters after #if"
+                                      ++" directive in file "++show p++": "++xs)
+                              return b
 
-parseExp1 :: SymTab HashDefine -> Parser Bool
-parseExp1 st =
-  do  a <- parseExp0 st
-      skip (string "&&")
-      b <- first (skip (parseExp1 st))
-      return (a && b)
-  +++
-      parseExp0 st
+notComment = not . ("//"`isPrefixOf`) . dropWhile isSpace
 
-parseExp0 :: SymTab HashDefine -> Parser Bool
-parseExp0 st =
-  do  skip (string "defined")
-      sym <- parens parseSym
-      return (definedST sym st)
-  +++
-  do  parens (parseBoolExp st)
-  +++
-  do  skip (char '!')
-      a <- parseExp0 st
+
+-- | The preprocessor must expand all macros (recursively) before evaluating
+--   the conditional.
+preExpand :: SymTab HashDefine -> TextParser String
+preExpand st =
+  do  eof
+      return ""
+  <|>
+  do  a <- many1 (satisfy notIdent)
+      commit $ pure (a++) `apply` preExpand st
+  <|>
+  do  b <- expandSymOrCall st
+      commit $ pure (b++) `apply` preExpand st
+
+-- | Expansion of symbols.
+expandSymOrCall :: SymTab HashDefine -> TextParser String
+expandSymOrCall st =
+  do sym <- parseSym
+     if sym=="defined" then do arg <- skip parseSym; convert sym [arg]
+                            <|>
+                            do arg <- skip $ parenthesis (do x <- skip parseSym;
+                                                             skip (return x))
+                               convert sym [arg]
+                            <|> convert sym []
+      else
+      ( do  args <- parenthesis (commit $ fragment `sepBy` skip (isWord ","))
+            args' <- flip mapM args $ \arg->
+                         case runParser (preExpand st) arg of
+                             (Left msg, _) -> fail msg
+                             (Right s, _)  -> return s
+            convert sym args'
+        <|> convert sym []
+      )
+  where
+    fragment = many1 (satisfy (`notElem`",)"))
+    convert "defined" [arg] =
+      case lookupST arg st of
+        Nothing | all isDigit arg    -> return arg
+        Nothing                      -> return "0"
+        Just (a@AntiDefined{})       -> return "0"
+        Just (a@SymbolReplacement{}) -> return "1"
+        Just (a@MacroExpansion{})    -> return "1"
+    convert sym args =
+      case lookupST sym st of
+        Nothing  -> if null args then return sym
+                    else return "0"
+                 -- else fail (disp sym args++" is not a defined macro")
+        Just (a@SymbolReplacement{}) -> do reparse (replacement a)
+                                           return ""
+        Just (a@MacroExpansion{})    -> do reparse (expandMacro a args False)
+                                           return ""
+        Just (a@AntiDefined{})       ->
+                    if null args then return sym
+                    else return "0"
+                 -- else fail (disp sym args++" explicitly undefined with -U")
+    disp sym args = let len = length args
+                        chars = map (:[]) ['a'..'z']
+                    in sym ++ if null args then ""
+                              else "("++intercalate "," (take len chars)++")"
+
+parseBoolExp :: TextParser Bool
+parseBoolExp =
+  do  a <- parseExp1
+      bs <- many (do skip (isWord "||")
+                     commit $ skip parseBoolExp)
+      return $ foldr (||) a bs
+
+parseExp1 :: TextParser Bool
+parseExp1 =
+  do  a <- parseExp0
+      bs <- many (do skip (isWord "&&")
+                     commit $ skip parseExp1)
+      return $ foldr (&&) a bs
+
+parseExp0 :: TextParser Bool
+parseExp0 =
+  do  skip (isWord "!")
+      a <- commit $ parseExp0
       return (not a)
-  +++
-  do  sym1 <- parseSymOrCall st
-      op <- parseOp st
-      sym2 <- parseSymOrCall st
-      return (op (safeRead sym1) (safeRead sym2))
-  +++
-  do  sym <- parseSymOrCall st
-      case safeRead sym of
+  <|>
+  do  val1 <- parseArithExp1
+      op   <- parseCmpOp
+      val2 <- parseArithExp1
+      return (val1 `op` val2)
+  <|>
+  do  sym <- parseArithExp1
+      case sym of
         0 -> return False
         _ -> return True
+  <|>
+  do  parenthesis (commit parseBoolExp)
+
+parseArithExp1 :: TextParser Integer
+parseArithExp1 =
+  do  val1 <- parseArithExp0
+      ( do op   <- parseArithOp1
+           val2 <- parseArithExp1
+           return (val1 `op` val2)
+        <|> return val1 )
+  <|>
+  do  parenthesis parseArithExp1
+
+parseArithExp0 :: TextParser Integer
+parseArithExp0 =
+  do  val1 <- parseNumber
+      ( do op   <- parseArithOp0
+           val2 <- parseArithExp0
+           return (val1 `op` val2)
+        <|> return val1 )
+  <|>
+  do  parenthesis parseArithExp0
+
+parseNumber :: TextParser Integer
+parseNumber = fmap safeRead $ skip parseSym
   where
     safeRead s =
       case s of
@@ -221,53 +324,87 @@
         []        -> 0 :: Integer
         ((n,_):_) -> n :: Integer
 
-parseOp :: SymTab HashDefine -> Parser (Integer -> Integer -> Bool)
-parseOp _ =
-  do  skip (string ">=")
+parseCmpOp :: TextParser (Integer -> Integer -> Bool)
+parseCmpOp =
+  do  skip (isWord ">=")
       return (>=)
-  +++
-  do  skip (char '>')
+  <|>
+  do  skip (isWord ">")
       return (>)
-  +++
-  do  skip (string "<=")
+  <|>
+  do  skip (isWord "<=")
       return (<=)
-  +++
-  do  skip (char '<')
+  <|>
+  do  skip (isWord "<")
       return (<)
-  +++
-  do  skip (string "==")
+  <|>
+  do  skip (isWord "==")
       return (==)
-  +++
-  do  skip (string "!=")
+  <|>
+  do  skip (isWord "!=")
       return (/=)
 
-parseSymOrCall :: SymTab HashDefine -> Parser String
+parseArithOp1 :: TextParser (Integer -> Integer -> Integer)
+parseArithOp1 =
+  do  skip (isWord "+")
+      return (+)
+  <|>
+  do  skip (isWord "-")
+      return (-)
+
+parseArithOp0 :: TextParser (Integer -> Integer -> Integer)
+parseArithOp0 =
+  do  skip (isWord "*")
+      return (*)
+  <|>
+  do  skip (isWord "/")
+      return (div)
+  <|>
+  do  skip (isWord "%")
+      return (rem)
+
+-- | Return the expansion of the symbol (if there is one).
+parseSymOrCall :: SymTab HashDefine -> TextParser String
 parseSymOrCall st =
   do  sym <- skip parseSym
-      args <- parens (parseSymOrCall st `sepby` skip (char ','))
-      return (convert sym args)
-  +++
+      args <- parenthesis (commit $ parseSymOrCall st `sepBy` skip (isWord ","))
+      return $ convert sym args
+  <|>
   do  sym <- skip parseSym
-      return (convert sym [])
+      return $ convert sym []
   where
     convert sym args =
       case lookupST sym st of
         Nothing  -> sym
         Just (a@SymbolReplacement{}) -> recursivelyExpand st (replacement a)
-        Just (a@MacroExpansion{})    -> expandMacro a args False
+        Just (a@MacroExpansion{})    -> recursivelyExpand st (expandMacro a args False)
         Just (a@AntiDefined{})       -> name a
 
 recursivelyExpand :: SymTab HashDefine -> String -> String
 recursivelyExpand st inp =
-  case papply (parseSymOrCall st) inp of
-    [(b,_)] -> b
-    _       -> inp
+  case runParser (parseSymOrCall st) inp of
+    (Left msg, _) -> inp
+    (Right s,  _) -> s
 
-parseSym :: Parser String
-parseSym = many1 (alphanum+++char '\''+++char '`')
+parseSym :: TextParser String
+parseSym = many1 (satisfy (\c-> isAlphaNum c || c`elem`"'`_"))
+           `onFail`
+           do xs <- allAsString
+              fail $ "Expected an identifier, got \""++xs++"\""
 
-parens p = bracket (skip (char '(')) (skip p) (skip (char ')'))
+notIdent :: Char -> Bool
+notIdent c = not (isAlphaNum c || c`elem`"'`_")
 
+skip :: TextParser a -> TextParser a
+skip p = many (satisfy isSpace) >> p
+
+-- | The standard "parens" parser does not work for us here.  Define our own.
+parenthesis :: TextParser a -> TextParser a
+parenthesis p = do isWord "("
+                   x <- p
+                   isWord ")"
+                   return x
+
 -- | Determine filename in \#include
 file :: SymTab HashDefine -> String -> String
 file st name =
@@ -276,3 +413,4 @@
       ('<':ns) -> init ns
       _ -> let ex = recursivelyExpand st name in
            if ex == name then name else file st ex
+
diff --git a/Language/Preprocessor/Cpphs/HashDefine.hs b/Language/Preprocessor/Cpphs/HashDefine.hs
--- a/Language/Preprocessor/Cpphs/HashDefine.hs
+++ b/Language/Preprocessor/Cpphs/HashDefine.hs
@@ -10,44 +10,45 @@
 --
 -- What structures are declared in a \#define.
 -----------------------------------------------------------------------------
- 
+
 module Language.Preprocessor.Cpphs.HashDefine
   ( HashDefine(..)
   , ArgOrText(..)
   , expandMacro
   , parseHashDefine
+  , simplifyHashDefines
   ) where
 
-import Char (isSpace)
-import List (intersperse)
+import Data.Char (isSpace)
+import Data.List (intercalate)
 
 data HashDefine
-	= LineDrop
-		{ name :: String }
-	| Pragma
-		{ name :: String }
+        = LineDrop
+                { name :: String }
+        | Pragma
+                { name :: String }
         | AntiDefined
-		{ name          :: String
-		, linebreaks    :: Int
-		}
-	| SymbolReplacement
-		{ name		:: String
-		, replacement	:: String
-		, linebreaks    :: Int
-		}
-	| MacroExpansion
-		{ name		:: String
-		, arguments	:: [String]
-		, expansion	:: [(ArgOrText,String)]
-		, linebreaks    :: Int
-		}
+                { name          :: String
+                , linebreaks    :: Int
+                }
+        | SymbolReplacement
+                { name          :: String
+                , replacement   :: String
+                , linebreaks    :: Int
+                }
+        | MacroExpansion
+                { name          :: String
+                , arguments     :: [String]
+                , expansion     :: [(ArgOrText,String)]
+                , linebreaks    :: Int
+                }
     deriving (Eq,Show)
 
 -- | 'smart' constructor to avoid warnings from ghc (undefined fields)
 symbolReplacement :: HashDefine
 symbolReplacement =
     SymbolReplacement
-	 { name=undefined, replacement=undefined, linebreaks=undefined }
+         { name=undefined, replacement=undefined, linebreaks=undefined }
 
 -- | Macro expansion text is divided into sections, each of which is classified
 --   as one of three kinds: a formal argument (Arg), plain text (Text),
@@ -59,12 +60,18 @@
 expandMacro :: HashDefine -> [String] -> Bool -> String
 expandMacro macro parameters layout =
     let env = zip (arguments macro) parameters
-        replace (Arg,s)  = maybe (error "formal param") id (lookup s env)
-        replace (Str,s)  = maybe (error "formal param") str (lookup s env)
+        replace (Arg,s)  = maybe ("")      id (lookup s env)
+        replace (Str,s)  = maybe (str "") str (lookup s env)
         replace (Text,s) = if layout then s else filter (/='\n') s
         str s = '"':s++"\""
+        checkArity | length (arguments macro) == 1 && length parameters <= 1
+                   || length (arguments macro) == length parameters = id
+                   | otherwise = error ("macro "++name macro++" expected "++
+                                        show (length (arguments macro))++
+                                        " arguments, but was given "++
+                                        show (length parameters))
     in
-    concatMap replace (expansion macro)
+    checkArity $ concatMap replace (expansion macro)
 
 -- | Parse a \#define, or \#undef, ignoring other \# directives
 parseHashDefine :: Bool -> [String] -> Maybe HashDefine
@@ -93,7 +100,7 @@
     macroHead sym args (var:xs) = (macroHead sym (var:args) . skip) xs
     macroHead sym args []       = error ("incomplete macro definition:\n"
                                         ++"  #define "++sym++"("
-                                        ++concat (intersperse "," args))
+                                        ++intercalate "," args)
     classifyRhs args ("#":x:xs)
                           | ansi &&
                             x `elem` args    = (Str,x): classifyRhs args xs
@@ -109,3 +116,14 @@
     count = length . filter (=='\n') . concat
     chop  = reverse . dropWhile (all isSpace) . reverse
 
+-- | Pretty-print hash defines to a simpler format, as key-value pairs.
+simplifyHashDefines :: [HashDefine] -> [(String,String)]
+simplifyHashDefines = concatMap simp
+  where
+    simp hd@LineDrop{}    = []
+    simp hd@Pragma{}      = []
+    simp hd@AntiDefined{} = []
+    simp hd@SymbolReplacement{} = [(name hd, replacement hd)]
+    simp hd@MacroExpansion{}    = [(name hd++"("++intercalate "," (arguments hd)
+                                           ++")"
+                                   ,concatMap snd (expansion hd))]
diff --git a/Language/Preprocessor/Cpphs/MacroPass.hs b/Language/Preprocessor/Cpphs/MacroPass.hs
--- a/Language/Preprocessor/Cpphs/MacroPass.hs
+++ b/Language/Preprocessor/Cpphs/MacroPass.hs
@@ -16,41 +16,76 @@
   ( macroPass
   , preDefine
   , defineMacro
+  , macroPassReturningSymTab
   ) where
 
-import Language.Preprocessor.Cpphs.HashDefine (HashDefine(..), expandMacro)
+import Language.Preprocessor.Cpphs.HashDefine (HashDefine(..), expandMacro
+                                              , simplifyHashDefines)
 import Language.Preprocessor.Cpphs.Tokenise   (tokenise, WordStyle(..)
                                               , parseMacroCall)
 import Language.Preprocessor.Cpphs.SymTab     (SymTab, lookupST, insertST
-                                              , emptyST)
+                                              , emptyST, flattenST)
 import Language.Preprocessor.Cpphs.Position   (Posn, newfile, filename, lineno)
 import Language.Preprocessor.Cpphs.Options    (BoolOptions(..))
 import System.IO.Unsafe (unsafeInterleaveIO)
 import Control.Monad    ((=<<))
-import Time       (getClockTime, toCalendarTime, formatCalendarTime)
-import Locale     (defaultTimeLocale)
+--import System.Time       (getClockTime, toCalendarTime, formatCalendarTime)
+import Data.Time.Clock  (getCurrentTime)
+import Data.Time.Format (formatTime)
+import TimeCompat       (defaultTimeLocale)
 
 noPos :: Posn
 noPos = newfile "preDefined"
 
 -- | Walk through the document, replacing calls of macros with the expanded RHS.
-macroPass :: [(String,String)]	-- ^ Pre-defined symbols and their values
-          -> BoolOptions	-- ^ Options that alter processing style
-          -> [(Posn,String)]	-- ^ The input file content
-          -> IO String		-- ^ The file after processing
+macroPass :: [(String,String)]  -- ^ Pre-defined symbols and their values
+          -> BoolOptions        -- ^ Options that alter processing style
+          -> [(Posn,String)]    -- ^ The input file content
+          -> IO String          -- ^ The file after processing
 macroPass syms options =
-    fmap (safetail		-- to remove extra "\n" inserted below
-         . concat)
+    fmap (safetail              -- to remove extra "\n" inserted below
+         . concat
+         . onlyRights)
     . macroProcess (pragma options) (layout options) (lang options)
                    (preDefine options syms)
     . tokenise (stripEol options) (stripC89 options)
                (ansi options) (lang options)
-    . ((noPos,""):)	-- ensure recognition of "\n#" at start of file
+    . ((noPos,""):)     -- ensure recognition of "\n#" at start of file
   where
     safetail [] = []
     safetail (_:xs) = xs
 
+-- | auxiliary
+onlyRights :: [Either a b] -> [b]
+onlyRights = concatMap (\x->case x of Right t-> [t]; Left _-> [];)
 
+-- | Walk through the document, replacing calls of macros with the expanded RHS.
+--   Additionally returns the active symbol table after processing.
+macroPassReturningSymTab
+          :: [(String,String)]  -- ^ Pre-defined symbols and their values
+          -> BoolOptions        -- ^ Options that alter processing style
+          -> [(Posn,String)]    -- ^ The input file content
+          -> IO (String,[(String,String)])
+                                -- ^ The file and symbol table after processing
+macroPassReturningSymTab syms options =
+    fmap (mapFst (safetail              -- to remove extra "\n" inserted below
+                 . concat)
+         . walk)
+    . macroProcess (pragma options) (layout options) (lang options)
+                   (preDefine options syms)
+    . tokenise (stripEol options) (stripC89 options)
+               (ansi options) (lang options)
+    . ((noPos,""):)     -- ensure recognition of "\n#" at start of file
+  where
+    safetail [] = []
+    safetail (_:xs) = xs
+    walk (Right x: rest) = let (xs,   foo) = walk rest
+                           in  (x:xs, foo)
+    walk (Left  x: [])   =     ( [] , simplifyHashDefines (flattenST x) )
+    walk (Left  x: rest) = walk rest
+    mapFst f (a,b) = (f a, b)
+
+
 -- | Turn command-line definitions (from @-D@) into 'HashDefine's.
 preDefine :: BoolOptions -> [(String,String)] -> SymTab HashDefine
 preDefine options defines =
@@ -73,9 +108,12 @@
 --   All valid identifiers are checked for the presence of a definition
 --   of that name in the symbol table, and if so, expanded appropriately.
 --   (Bool arguments are: keep pragmas?  retain layout?  haskell language?)
+--   The result lazily intersperses output text with symbol tables.  Lines
+--   are emitted as they are encountered.  A symbol table is emitted after
+--   each change to the defined symbols, and always at the end of processing.
 macroProcess :: Bool -> Bool -> Bool -> SymTab HashDefine -> [WordStyle]
-             -> IO [String]
-macroProcess _ _ _ _         []          = return []
+             -> IO [Either (SymTab HashDefine) String]
+macroProcess _ _ _ st        []          = return [Left st]
 macroProcess p y l st (Other x: ws)      = emit x    $ macroProcess p y l st ws
 macroProcess p y l st (Cmd Nothing: ws)  = emit "\n" $ macroProcess p y l st ws
 macroProcess p y l st (Cmd (Just (LineDrop x)): ws)
@@ -85,20 +123,27 @@
                | pragma    = emit "\n" $ emit x $ macroProcess pragma y l st ws
                | otherwise = emit "\n" $          macroProcess pragma y l st ws
 macroProcess p layout lang st (Cmd (Just hd): ws) =
-    let n = 1 + linebreaks hd in
+    let n = 1 + linebreaks hd
+        newST = insertST (name hd, hd) st
+    in
     emit (replicate n '\n') $
-    macroProcess p layout lang (insertST (name hd, hd) st) ws
+    emitSymTab newST $
+    macroProcess p layout lang newST ws
 macroProcess pr layout lang st (Ident p x: ws) =
     case x of
       "__FILE__" -> emit (show (filename p))$ macroProcess pr layout lang st ws
       "__LINE__" -> emit (show (lineno p))  $ macroProcess pr layout lang st ws
       "__DATE__" -> do w <- return .
-                            formatCalendarTime defaultTimeLocale "\"%d %b %Y\""
-                            =<< toCalendarTime =<< getClockTime
+                         -- formatCalendarTime defaultTimeLocale "\"%d %b %Y\""
+                         -- =<< toCalendarTime =<< getClockTime
+                            formatTime defaultTimeLocale "\"%d %b %Y\""
+                            =<< getCurrentTime
                        emit w $ macroProcess pr layout lang st ws
       "__TIME__" -> do w <- return .
-                            formatCalendarTime defaultTimeLocale "\"%H:%M:%S\""
-                            =<< toCalendarTime =<< getClockTime
+                         -- formatCalendarTime defaultTimeLocale "\"%H:%M:%S\""
+                         -- =<< toCalendarTime =<< getClockTime
+                            formatTime defaultTimeLocale "\"%H:%M:%S\""
+                            =<< getCurrentTime
                        emit w $ macroProcess pr layout lang st ws
       _ ->
         case lookupST x st of
@@ -122,9 +167,9 @@
                             Just (args,ws') ->
                                 if length args /= length (arguments hd) then
                                      emit x $ macroProcess pr layout lang st ws
-                                else do args' <- mapM (fmap concat .
-                                                       macroProcess pr layout
-                                                                       lang st)
+                                else do args' <- mapM (fmap (concat . onlyRights)
+                                                       . macroProcess pr layout
+                                                                        lang st)
                                                       args
                                         -- one-level expansion only:
                                         -- emit (expandMacro hd args' layout) $
@@ -136,6 +181,10 @@
                                             ++ ws')
 
 -- | Useful helper function.
-emit :: a -> IO [a] -> IO [a]
+emit :: a -> IO [Either b a] -> IO [Either b a]
 emit x io = do xs <- unsafeInterleaveIO io
-               return (x:xs)
+               return (Right x:xs)
+-- | Useful helper function.
+emitSymTab :: b -> IO [Either b a] -> IO [Either b a]
+emitSymTab x io = do xs <- unsafeInterleaveIO io
+                     return (Left x:xs)
diff --git a/Language/Preprocessor/Cpphs/Options.hs b/Language/Preprocessor/Cpphs/Options.hs
--- a/Language/Preprocessor/Cpphs/Options.hs
+++ b/Language/Preprocessor/Cpphs/Options.hs
@@ -17,20 +17,21 @@
   , parseOptions
   , defaultCpphsOptions
   , defaultBoolOptions
+  , trailing
   ) where
 
-import Maybe
-import List (isPrefixOf)
+import Data.Maybe
+import Data.List (isPrefixOf)
 
 -- | Cpphs options structure.
-data CpphsOptions = CpphsOptions 
-    { infiles	:: [FilePath]
-    , outfiles	:: [FilePath]
-    , defines	:: [(String,String)]
-    , includes	:: [String]
-    , preInclude:: [FilePath]	-- ^ Files to #include before anything else
-    , boolopts	:: BoolOptions
-    }
+data CpphsOptions = CpphsOptions
+    { infiles   :: [FilePath]
+    , outfiles  :: [FilePath]
+    , defines   :: [(String,String)]
+    , includes  :: [String]
+    , preInclude:: [FilePath]   -- ^ Files to \#include before anything else
+    , boolopts  :: BoolOptions
+    } deriving (Show)
 
 -- | Default options.
 defaultCpphsOptions :: CpphsOptions
@@ -41,18 +42,18 @@
 
 -- | Options representable as Booleans.
 data BoolOptions = BoolOptions
-    { macros	:: Bool  -- ^ Leave \#define and \#undef in output of ifdef?
-    , locations	:: Bool	 -- ^ Place #line droppings in output?
-    , hashline	:: Bool	 -- ^ Write #line or {-# LINE #-} ?
-    , pragma	:: Bool  -- ^ Keep #pragma in final output?
-    , stripEol	:: Bool  -- ^ Remove C eol (\/\/) comments everywhere?
-    , stripC89	:: Bool  -- ^ Remove C inline (\/**\/) comments everywhere?
-    , lang	:: Bool  -- ^ Lex input as Haskell code?
-    , ansi	:: Bool  -- ^ Permit stringise \# and catenate \#\# operators?
-    , layout	:: Bool  -- ^ Retain newlines in macro expansions?
-    , literate	:: Bool  -- ^ Remove literate markup?
-    , warnings	:: Bool  -- ^ Issue warnings?
-    }
+    { macros    :: Bool  -- ^ Leave \#define and \#undef in output of ifdef?
+    , locations :: Bool  -- ^ Place \#line droppings in output?
+    , hashline  :: Bool  -- ^ Write \#line or {-\# LINE \#-} ?
+    , pragma    :: Bool  -- ^ Keep \#pragma in final output?
+    , stripEol  :: Bool  -- ^ Remove C eol (\/\/) comments everywhere?
+    , stripC89  :: Bool  -- ^ Remove C inline (\/**\/) comments everywhere?
+    , lang      :: Bool  -- ^ Lex input as Haskell code?
+    , ansi      :: Bool  -- ^ Permit stringise \# and catenate \#\# operators?
+    , layout    :: Bool  -- ^ Retain newlines in macro expansions?
+    , literate  :: Bool  -- ^ Remove literate markup?
+    , warnings  :: Bool  -- ^ Issue warnings?
+    } deriving (Show)
 
 -- | Default settings of boolean options.
 defaultBoolOptions :: BoolOptions
@@ -80,6 +81,7 @@
     | Macro (String,String)
     | Path String
     | PreInclude FilePath
+    | IgnoredForCompatibility
       deriving (Eq, Show)
 
 flags :: [(String, RawOption)]
@@ -103,11 +105,15 @@
     where a = lookup x flags
 rawOption ('-':'D':xs) = Just $ Macro (s, if null d then "1" else tail d)
     where (s,d) = break (=='=') xs
+rawOption ('-':'U':xs) = Just $ IgnoredForCompatibility
 rawOption ('-':'I':xs) = Just $ Path $ trailing "/\\" xs
 rawOption xs | "--include="`isPrefixOf`xs
             = Just $ PreInclude (drop 10 xs)
 rawOption _ = Nothing
 
+-- | Trim trailing elements of the second list that match any from
+--   the first list.  Typically used to remove trailing forward\/back
+--   slashes from a directory path.
 trailing :: (Eq a) => [a] -> [a] -> [a]
 trailing xs = reverse . dropWhile (`elem`xs) . reverse
 
@@ -115,17 +121,17 @@
 boolOpts :: [RawOption] -> BoolOptions
 boolOpts opts =
   BoolOptions
-    { macros	= not (NoMacro `elem` opts)
-    , locations	= not (NoLine  `elem` opts)
-    , hashline	= not (LinePragma `elem` opts)
-    , pragma	=      Pragma  `elem` opts
-    , stripEol	=      StripEol`elem` opts
-    , stripC89	=      StripEol`elem` opts || Strip `elem` opts
+    { macros    = not (NoMacro `elem` opts)
+    , locations = not (NoLine  `elem` opts)
+    , hashline  = not (LinePragma `elem` opts)
+    , pragma    =      Pragma  `elem` opts
+    , stripEol  =      StripEol`elem` opts
+    , stripC89  =      StripEol`elem` opts || Strip `elem` opts
     , lang      = not (Text    `elem` opts)
-    , ansi	=      Ansi    `elem` opts
-    , layout	=      Layout  `elem` opts
-    , literate	=      Unlit   `elem` opts
-    , warnings	= not (SuppressWarnings `elem` opts)
+    , ansi      =      Ansi    `elem` opts
+    , layout    =      Layout  `elem` opts
+    , literate  =      Unlit   `elem` opts
+    , warnings  = not (SuppressWarnings `elem` opts)
     }
 
 -- | Parse all command-line options.
diff --git a/Language/Preprocessor/Cpphs/Position.hs b/Language/Preprocessor/Cpphs/Position.hs
--- a/Language/Preprocessor/Cpphs/Position.hs
+++ b/Language/Preprocessor/Cpphs/Position.hs
@@ -17,9 +17,10 @@
   , addcol, newline, tab, newlines, newpos
   , cppline, haskline, cpp2hask
   , filename, lineno, directory
+  , cleanPath
   ) where
 
-import List (isPrefixOf)
+import Data.List (isPrefixOf)
 
 -- | Source positions contain a filename, line, column, and an
 --   inclusion point, which is itself another source position,
@@ -38,7 +39,7 @@
 
 -- | Constructor.  Argument is filename.
 newfile :: String -> Posn
-newfile name = Pn name 1 1 Nothing
+newfile name = Pn (cleanPath name) 1 1 Nothing
 
 -- | Increment column number by given quantity.
 addcol :: Int -> Posn -> Posn
@@ -88,7 +89,8 @@
 cpp2hask line | "#line" `isPrefixOf` line = "{-# LINE "
                                             ++unwords (tail (words line))
                                             ++" #-}"
-                                                                                
+              | otherwise = line
+
 -- | Strip non-directory suffix from file name (analogous to the shell
 --   command of the same name).
 dirname :: String -> String
@@ -96,3 +98,9 @@
   where safetail [] = []
         safetail (_:x) = x
 
+-- | Sigh.  Mixing Windows filepaths with unix is bad.  Make sure there is a
+--   canonical path separator.
+cleanPath :: FilePath -> FilePath
+cleanPath [] = []
+cleanPath ('\\':cs) = '/': cleanPath cs
+cleanPath (c:cs)    = c:   cleanPath cs
diff --git a/Language/Preprocessor/Cpphs/ReadFirst.hs b/Language/Preprocessor/Cpphs/ReadFirst.hs
--- a/Language/Preprocessor/Cpphs/ReadFirst.hs
+++ b/Language/Preprocessor/Cpphs/ReadFirst.hs
@@ -3,7 +3,7 @@
 -- Module      :  ReadFirst
 -- Copyright   :  2004 Malcolm Wallace
 -- Licence     :  LGPL
--- 
+--
 -- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
 -- Stability   :  experimental
 -- Portability :  All
@@ -13,41 +13,68 @@
 
 module Language.Preprocessor.Cpphs.ReadFirst
   ( readFirst
+  , readFileUTF8
+  , writeFileUTF8
   ) where
 
-import IO        (hPutStrLn, stderr)
-import Directory (doesFileExist)
-import List      (intersperse)
-import Monad     (when)
-import Language.Preprocessor.Cpphs.Position  (Posn,directory)
+import System.IO
+import System.Directory (doesFileExist)
+import Data.List        (intersperse)
+import Control.Exception as E
+import Control.Monad    (when)
+import Language.Preprocessor.Cpphs.Position  (Posn,directory,cleanPath)
 
 -- | Attempt to read the given file from any location within the search path.
 --   The first location found is returned, together with the file content.
 --   (The directory of the calling file is always searched first, then
 --    the current directory, finally any specified search path.)
-readFirst :: String		-- ^ filename
-	-> Posn			-- ^ inclusion point
-	-> [String]		-- ^ search path
-	-> Bool			-- ^ report warnings?
-	-> IO ( FilePath
+readFirst :: String             -- ^ filename
+        -> Posn                 -- ^ inclusion point
+        -> [String]             -- ^ search path
+        -> Bool                 -- ^ report warnings?
+        -> IO ( FilePath
               , String
-              )			-- ^ discovered filepath, and file contents
+              )                 -- ^ discovered filepath, and file contents
 
 readFirst name demand path warn =
-    try (cons dd (".":path))
+    case name of
+                       -- Windows drive in absolute path
+       c:':':'\\':nm-> try nm   (Just (c:':':[])) [""]
+       c:':':'/':nm -> try nm   (Just (c:':':[])) [""]
+                       -- Windows drive in relative path
+       c:':':nm     -> try nm   (Just (c:':':[])) (cons dd (".":path))
+                       -- unix-like absolute path
+       '/':nm       -> try nm   Nothing           [""]
+                       -- any relative path
+       _            -> try name Nothing           (cons dd (".":path))
   where
     dd = directory demand
     cons x xs = if null x then xs else x:xs
-    try [] = do
+    try name _ [] = do
         when warn $
           hPutStrLn stderr ("Warning: Can't find file \""++name
                            ++"\" in directories\n\t"
                            ++concat (intersperse "\n\t" (cons dd (".":path)))
                            ++"\n  Asked for by: "++show demand)
         return ("missing file: "++name,"")
-    try (p:ps) = do
-        let file = p++'/':name
+    try name drive (p:ps) = do
+        let file = (maybe id (++) drive) $ cleanPath p++'/':cleanPath name
         ok <- doesFileExist file
-        if not ok then try ps
-          else do content <- readFile file
+        if not ok then try name drive ps
+          else do content <- readFileUTF8 file
                   return (file,content)
+
+readFileUTF8 :: FilePath -> IO String
+readFileUTF8 file = do
+    h <- openFile file ReadMode
+    (do utf8r <- mkTextEncoding "UTF-8//ROUNDTRIP"
+        hSetEncoding h utf8r
+        hGetContents h) `E.onException` (hClose h)
+
+writeFileUTF8 :: FilePath -> String -> IO ()
+writeFileUTF8 f txt = withFile f WriteMode $ \hdl->
+                          do utf8r <- mkTextEncoding "UTF-8//ROUNDTRIP"
+                             hSetEncoding hdl utf8r
+                             hPutStr hdl txt
+                          `E.onException` (hClose hdl)
+
diff --git a/Language/Preprocessor/Cpphs/RunCpphs.hs b/Language/Preprocessor/Cpphs/RunCpphs.hs
--- a/Language/Preprocessor/Cpphs/RunCpphs.hs
+++ b/Language/Preprocessor/Cpphs/RunCpphs.hs
@@ -2,29 +2,81 @@
 -- The main program for cpphs, a simple C pre-processor written in Haskell.
 
 -- Copyright (c) 2004 Malcolm Wallace
--- This file is GPL, although the libraries it uses are either standard
--- Haskell'98 or distributed under the LGPL.
+-- This file is LGPL (relicensed from the GPL by Malcolm Wallace, October 2011).
 -}
-module Language.Preprocessor.Cpphs.RunCpphs ( runCpphs ) where
+module Language.Preprocessor.Cpphs.RunCpphs ( runCpphs
+                                            , runCpphsPass1
+                                            , runCpphsPass2
+                                            , runCpphsReturningSymTab
+                                            ) where
 
 import Language.Preprocessor.Cpphs.CppIfdef (cppIfdef)
-import Language.Preprocessor.Cpphs.MacroPass(macroPass)
-import Language.Preprocessor.Cpphs.Options  (CpphsOptions(..), BoolOptions(..))
+import Language.Preprocessor.Cpphs.MacroPass(macroPass,macroPassReturningSymTab)
+import Language.Preprocessor.Cpphs.Options  (CpphsOptions(..), BoolOptions(..)
+                                            ,trailing)
+import Language.Preprocessor.Cpphs.Tokenise (deWordStyle, tokenise)
+import Language.Preprocessor.Cpphs.Position (cleanPath, Posn)
 import Language.Preprocessor.Unlit as Unlit (unlit)
 
 
 runCpphs :: CpphsOptions -> FilePath -> String -> IO String
 runCpphs options filename input = do
+  pass1 <- runCpphsPass1 options filename input
+  runCpphsPass2 (boolopts options) (defines options) filename pass1
+
+runCpphsPass1 :: CpphsOptions -> FilePath -> String -> IO [(Posn,String)]
+runCpphsPass1 options' filename input = do
+  let options= options'{ includes= map (trailing "\\/") (includes options') }
   let bools  = boolopts options
       preInc = case preInclude options of
                  [] -> ""
-                 is -> concatMap (\f->"#include \""++f++"\"\n") is 
-                       ++ "#line 1 \""++filename++"\"\n"
+                 is -> concatMap (\f->"#include \""++f++"\"\n") is
+                       ++ "#line 1 \""++cleanPath filename++"\"\n"
 
   pass1 <- cppIfdef filename (defines options) (includes options) bools
                     (preInc++input)
-  pass2 <- macroPass (defines options) bools pass1
-  let result= if not (macros bools) then unlines (map snd pass1) else pass2
-      pass3 = if literate bools then Unlit.unlit filename else id
+  return pass1
 
+runCpphsPass2 :: BoolOptions -> [(String,String)] -> FilePath -> [(Posn,String)] -> IO String
+runCpphsPass2 bools defines filename pass1 = do
+  pass2 <- macroPass defines bools pass1
+  let result= if not (macros bools)
+              then if   stripC89 bools || stripEol bools
+                   then concatMap deWordStyle $
+                        tokenise (stripEol bools) (stripC89 bools)
+                                 (ansi bools) (lang bools) pass1
+                   else unlines (map snd pass1)
+              else pass2
+      pass3 = if literate bools then Unlit.unlit filename else id
   return (pass3 result)
+
+runCpphsReturningSymTab :: CpphsOptions -> FilePath -> String
+             -> IO (String,[(String,String)])
+runCpphsReturningSymTab options' filename input = do
+  let options= options'{ includes= map (trailing "\\/") (includes options') }
+  let bools  = boolopts options
+      preInc = case preInclude options of
+                 [] -> ""
+                 is -> concatMap (\f->"#include \""++f++"\"\n") is
+                       ++ "#line 1 \""++cleanPath filename++"\"\n"
+  (pass2,syms) <-
+      if macros bools then do
+          pass1 <- cppIfdef filename (defines options) (includes options)
+                            bools (preInc++input)
+          macroPassReturningSymTab (defines options) bools pass1
+      else do
+          pass1 <- cppIfdef filename (defines options) (includes options)
+                            bools{macros=True} (preInc++input)
+          (_,syms) <- macroPassReturningSymTab (defines options) bools pass1
+          pass1 <- cppIfdef filename (defines options) (includes options)
+                            bools (preInc++input)
+          let result = if   stripC89 bools || stripEol bools
+                       then concatMap deWordStyle $
+                            tokenise (stripEol bools) (stripC89 bools)
+                                     (ansi bools) (lang bools) pass1
+                       else init $ unlines (map snd pass1)
+          return (result,syms)
+
+  let pass3 = if literate bools then Unlit.unlit filename else id
+  return (pass3 pass2, syms)
+
diff --git a/Language/Preprocessor/Cpphs/SymTab.hs b/Language/Preprocessor/Cpphs/SymTab.hs
--- a/Language/Preprocessor/Cpphs/SymTab.hs
+++ b/Language/Preprocessor/Cpphs/SymTab.hs
@@ -3,7 +3,7 @@
 -- Module      :  SymTab
 -- Copyright   :  2000-2004 Malcolm Wallace
 -- Licence     :  LGPL
--- 
+--
 -- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
 -- Stability   :  Stable
 -- Portability :  All
@@ -19,6 +19,7 @@
   , deleteST
   , lookupST
   , definedST
+  , flattenST
   , IndTree
   ) where
 
@@ -31,15 +32,17 @@
 deleteST  :: String -> SymTab v -> SymTab v
 lookupST  :: String -> SymTab v -> Maybe v
 definedST :: String -> SymTab v -> Bool
+flattenST :: SymTab v -> [v]
 
 emptyST           = itgen maxHash []
 insertST (s,v) ss = itiap (hash s) ((s,v):)    ss id
-deleteST  s    ss = itiap (hash s) (filter ((/=s).fst)) ss id
-lookupST  s    ss = let vs = filter ((==s).fst) ((itind (hash s)) ss)
+deleteST  s    ss = itiap (hash s) (filter ((/=s) . fst)) ss id
+lookupST  s    ss = let vs = filter ((==s) . fst) ((itind (hash s)) ss)
                     in if null vs then Nothing
                        else (Just . snd . head) vs
-definedST s    ss = let vs = filter ((==s).fst) ((itind (hash s)) ss)
+definedST s    ss = let vs = filter ((==s) . fst) ((itind (hash s)) ss)
                     in (not . null) vs
+flattenST      ss = itfold (map snd) (++) ss
 
 
 ----
@@ -62,10 +65,13 @@
        itiap i f lt $ \lt' -> k (Fork n lt' rt)
   else itiap (i-n) f rt $ \rt' -> k (Fork n lt rt')
 
-itind :: Int -> IndTree a -> a  
+itind :: Int -> IndTree a -> a
 itind _ (Leaf x) = x
 itind i (Fork n lt rt) = if i<n then itind i lt else itind (i-n) rt
 
+itfold :: (a->b) -> (b->b->b) -> IndTree a -> b
+itfold leaf _fork (Leaf x) = leaf x
+itfold leaf  fork (Fork _ l r) = fork (itfold leaf fork l) (itfold leaf fork r)
 
 ----
 -- Hash values
diff --git a/Language/Preprocessor/Cpphs/Tokenise.hs b/Language/Preprocessor/Cpphs/Tokenise.hs
--- a/Language/Preprocessor/Cpphs/Tokenise.hs
+++ b/Language/Preprocessor/Cpphs/Tokenise.hs
@@ -22,7 +22,7 @@
   , parseMacroCall
   ) where
 
-import Char
+import Data.Char
 import Language.Preprocessor.Cpphs.HashDefine
 import Language.Preprocessor.Cpphs.Position
 
@@ -106,8 +106,15 @@
                                             haskell CLineComment "  " p ls xs
   haskell Any acc p ls ('"':xs)           = emit acc $
                                             haskell (String '"') ['"'] p ls xs
-  haskell Any acc p ls ('\'':xs)          = emit acc $
+  haskell Any acc p ls ('\'':'\'':xs)     = emit acc $ -- TH type quote
+                                            haskell Any "''" p ls xs
+  haskell Any acc p ls ('\'':xs@('\\':_)) = emit acc $ -- escaped char literal
                                             haskell (String '\'') "'" p ls xs
+  haskell Any acc p ls ('\'':x:'\'':xs)   = emit acc $ -- character literal
+                                            emit ['\'', x, '\''] $
+                                            haskell Any [] p ls xs
+  haskell Any acc p ls ('\'':xs)          = emit acc $ -- TH name quote
+                                            haskell Any "'" p ls xs
   haskell Any acc p ls (x:xs) | single x  = emit acc $ emit [x] $
                                             haskell Any [] p ls xs
   haskell Any acc p ls (x:xs) | space x   = emit acc $
@@ -146,7 +153,7 @@
                                                                         p ls xs
   haskell CComment acc p ls ('*':'/':xs)  = emit ("  "++acc) $
                                             haskell Any [] p ls xs
-  haskell CComment acc p ls (_:xs)        = haskell CComment (' ':acc) p ls xs
+  haskell CComment acc p ls (x:xs)        = haskell CComment (white x:acc) p ls xs
   haskell CLineComment acc p ls xs@('\n':_)= emit acc $ haskell Any [] p ls xs
   haskell CLineComment acc p ls (_:xs)    = haskell CLineComment (' ':acc)
                                                                        p ls xs
@@ -197,7 +204,7 @@
     lexcpp LineComment w l ls (_:xs)      = lexcpp LineComment (' ':w) l ls xs
     lexcpp (NestComment _) w l ls ('*':'/':xs)
                                           = lexcpp Any [] (w*/*l) ls xs
-    lexcpp (NestComment n) w l ls (_:xs)  = lexcpp (NestComment n) (' ':w) l
+    lexcpp (NestComment n) w l ls (x:xs)  = lexcpp (NestComment n) (white x:w) l
                                                                         ls xs
     lexcpp mode w l ((p,l'):ls) []        = cpp mode next w l p ls ('\n':l')
     lexcpp _    _ _ []          []        = []
@@ -228,7 +235,7 @@
                                              plaintext Any [] p ls xs
   plaintext CComment acc p ls ('*':'/':xs) = emit ("  "++acc) $
                                              plaintext Any [] p ls xs
-  plaintext CComment acc p ls (_:xs)    = plaintext CComment (' ':acc) p ls xs
+  plaintext CComment acc p ls (x:xs)       = plaintext CComment (white x:acc) p ls xs
   plaintext CLineComment acc p ls xs@('\n':_)
                                         = emit acc $ plaintext Any [] p ls xs
   plaintext CLineComment acc p ls (_:xs)= plaintext CLineComment (' ':acc)
@@ -242,6 +249,10 @@
   symbol x = x `elem` ":!#$%&*+./<=>?@\\^|-~"
   single x = x `elem` "(),[];{}"
   space  x = x `elem` " \t"
+  -- conversion of comment text to whitespace
+  white '\n' = '\n'
+  white '\r' = '\r'
+  white _    = ' '
   -- emit a token (if there is one) from the accumulator
   emit ""  = id
   emit xs  = (Other (reverse xs):)
@@ -268,4 +279,3 @@
     args n w acc (x@(Other _)  :xs)  = args n     (x:w)         acc    xs
     args _ _ _   _                   = Nothing
     addone w acc = reverse (skip w): acc
-
diff --git a/Language/Preprocessor/Unlit.hs b/Language/Preprocessor/Unlit.hs
--- a/Language/Preprocessor/Unlit.hs
+++ b/Language/Preprocessor/Unlit.hs
@@ -2,8 +2,8 @@
 --   version 1.2, appendix C.
 module Language.Preprocessor.Unlit (unlit) where
 
-import Char
-import List (isPrefixOf)
+import Data.Char
+import Data.List (isPrefixOf)
 
 data Classified = Program String | Blank | Comment
                 | Include Int String | Pre String
@@ -14,13 +14,14 @@
    where allProg [] = []  -- Should give an error message,
                           -- but I have no good position information.
          allProg (('\\':x):xs) |  "end{code}"`isPrefixOf`x = Blank : classify xs
-	 allProg (x:xs) = Program x:allProg xs
+         allProg (x:xs) = Program x:allProg xs
 classify (('>':x):xs)      = Program (' ':x) : classify xs
 classify (('#':x):xs)      = (case words x of
                                 (line:rest) | all isDigit line
                                    -> Include (read line) (unwords rest)
                                 _  -> Pre x
                              ) : classify xs
+--classify (x:xs) | "{-# LINE" `isPrefixOf` x = Program x: classify xs
 classify (x:xs) | all isSpace x = Blank:classify xs
 classify (x:xs)                 = Comment:classify xs
 
@@ -64,8 +65,8 @@
 inlines s = lines' s id
   where
   lines' []             acc = [acc []]
-  lines' ('\^M':'\n':s) acc = acc [] : lines' s id	-- DOS
-  lines' ('\^M':s)      acc = acc [] : lines' s id	-- MacOS
-  lines' ('\n':s)       acc = acc [] : lines' s id	-- Unix
+  lines' ('\^M':'\n':s) acc = acc [] : lines' s id      -- DOS
+  lines' ('\^M':s)      acc = acc [] : lines' s id      -- MacOS
+  lines' ('\n':s)       acc = acc [] : lines' s id      -- Unix
   lines' (c:s)          acc = lines' s (acc . (c:))
 
diff --git a/Makefile b/Makefile
deleted file mode 100644
--- a/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-LIBRARY = cpphs
-VERSION = 1.11
-
-DIRS	= Language/Preprocessor/Cpphs \
-	  Text/ParserCombinators
-
-SRCS	= Language/Preprocessor/Cpphs.hs \
-          Language/Preprocessor/Cpphs/CppIfdef.hs \
-          Language/Preprocessor/Cpphs/HashDefine.hs \
-          Language/Preprocessor/Cpphs/MacroPass.hs \
-          Language/Preprocessor/Cpphs/Options.hs \
-          Language/Preprocessor/Cpphs/Position.hs \
-          Language/Preprocessor/Cpphs/ReadFirst.hs \
-          Language/Preprocessor/Cpphs/RunCpphs.hs \
-          Language/Preprocessor/Cpphs/SymTab.hs \
-          Language/Preprocessor/Cpphs/Tokenise.hs \
-          Language/Preprocessor/Unlit.hs \
-          Text/ParserCombinators/HuttonMeijer.hs \
-          cpphs.hs
-
-AUX	= README LICENCE* CHANGELOG $(LIBRARY).cabal Setup.hs Makefile \
-	  cpphs.hugs cpphs.compat \
-	  tests/[A-BD-Z]* tests/[a-np-z]* \
-	  docs/[a-z]*
-
-HC	= ghc
-HFLAGS	=
-HEAP	=
-HOSTSTRIP = strip
-
-all: $(LIBRARY)
-package:
-	tar cf tmp.tar $(SRCS) $(AUX)
-	mkdir $(LIBRARY)-$(VERSION)
-	cd $(LIBRARY)-$(VERSION); tar xf ../tmp.tar
-	tar zcf $(LIBRARY)-$(VERSION).tar.gz $(LIBRARY)-$(VERSION)
-	zip -r $(LIBRARY)-$(VERSION).zip $(LIBRARY)-$(VERSION)
-	rm -r tmp.tar $(LIBRARY)-$(VERSION)
-haddock: $(SRCS)
-	mkdir -p docs/$(LIBRARY)
-	for dir in $(DIRS); do mkdir -p docs/$(LIBRARY)/$$dir; done
-	for file in $(SRCS); \
-	    do HsColour -anchor -html $$file \
-	          >docs/$(LIBRARY)/`dirname $$file`/`basename $$file .hs`.html;\
-	    done
-	haddock --html --title=$(LIBRARY) \
-	    --odir=docs/$(LIBRARY) --package=$(LIBRARY) \
-	    --source-module="%{MODULE/.//}.html" \
-	    --source-entity="%{MODULE/.//}.html#%{NAME}" \
-	    $(SRCS)
-
-
-
-$(LIBRARY): $(SRCS)
-	$(HC) $(HFLAGS) $(HEAP) -o $@  $(SRCS)
-	$(HOSTSTRIP) $@
diff --git a/README b/README
deleted file mode 100644
--- a/README
+++ /dev/null
@@ -1,50 +0,0 @@
-This directory contains 'cpphs', a simplified but robust
-re-implementation of cpp, the C pre-processor, in Haskell.
-
-TO BUILD
---------
-Just use
-    hmake cpphs [-package base]
-or
-    ghc --make cpphs [-o cpphs]		#  -o needed for ghc <= 6.4.1 ]
-or
-    runhugs cpphs	# or rename the script cpphs.hugs to cpphs
-
-
-USAGE
------
-	cpphs  [filename | -Dsym | -Dsym=val | -Ipath]+  [-Ofile]
-               [ --include=file ]*
-               [ --nomacro | --noline | --nowarn | --strip | --strip-eol |
-                 --pragma | --text | --hashes | --layout | --unlit |
-                 --linepragma ]*
-               [ --cpp compatopts ]
-
-For fuller details, see docs/index.html
-
-If you want to use cpphs as a completely drop-in replacement for the
-real cpp, that is, to accept the same arguments, and have broadly
-the same behaviour in response to them, then use the --cpp compatibility
-option.
-
-
-COPYRIGHT
----------
-Copyright (c) 2004-2010 Malcolm Wallace (Malcolm.Wallace@cs.york.ac.uk)
-except for Text.ParserCombinators.HuttonMeijer (Copyright (c) 1995
-Graham Hutton and Erik Meijer).
-
-
-LICENCE
--------
-These library modules are distributed under the terms of the LGPL.
-The application module 'cpphs.hs' is GPL.
-
-This software comes with no warranty.  Use at your own risk.
-
-
-WEBSITE
--------
-http://haskell.org/cpphs/
-http://www.cs.york.ac.uk/fp/cpphs/
-darcs get http://www.cs.york.ac.uk/fp/darcs/cpphs
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,60 @@
+[![Hackage version](https://img.shields.io/hackage/v/cpphs.svg?label=Hackage)](http://hackage.haskell.org/package/cpphs)
+[![Stackage LTS version](https://www.stackage.org/package/cpphs/badge/lts?label=Stackage)](https://www.stackage.org/package/cpphs)
+[![cpphs on Stackage Nightly](https://stackage.org/package/cpphs/badge/nightly)](https://stackage.org/nightly/package/cpphs)
+[![Cabal build](https://github.com/haskell-pkg-janitors/cpphs/workflows/Haskell-CI/badge.svg)](https://github.com/haskell-pkg-janitors/cpphs/actions)
+
+cpphs
+=====
+
+A liberalised re-implementation of `cpp`, the C pre-processor.
+
+`cpphs` is a re-implementation of the C pre-processor that is both more compatible with Haskell,
+and itself written in Haskell so that it can be distributed with compilers.
+
+This version of the C pre-processor is pretty-much feature-complete and compatible with traditional (K&R) pre-processors.
+Additional features include: a plain-text mode; an option to unlit literate code files; and an option to turn off macro-expansion.
+
+Usage
+-----
+
+    cpphs  [filename | -Dsym | -Dsym=val | -Ipath]+  [-Ofile]
+           [ --include=file ]*
+           [ --nomacro | --noline | --nowarn | --strip | --strip-eol |
+             --pragma | --text | --hashes | --layout | --unlit |
+             --linepragma ]*
+           [ --cpp compatopts ]
+
+For fuller details, see [docs/index.html](docs/index.html).
+
+If you want to use `cpphs` as a completely drop-in replacement for the
+real cpp, that is, to accept the same arguments, and have broadly
+the same behaviour in response to them, then use the `--cpp` compatibility
+option.
+
+
+Copyright
+---------
+
+(c) 2004-2017 Malcolm Wallace (Malcolm.Wallace@me.com)
+
+
+Licence
+-------
+
+These library modules are distributed under the terms of the LGPL.
+The application module `cpphs.hs` is GPL.
+
+This software comes with no warranty.  Use at your own risk.
+
+If you have a commercial use for cpphs, and feel the terms of the (L)GPL
+are too onerous, you have the option of distributing unmodified binaries
+(only, not sources) under the terms of a different licence (see
+LICENCE-commercial).
+
+
+Website
+-------
+
+Description see: https://hackage.haskell.org/package/cpphs
+
+Old homepage: https://archives.haskell.org/projects.haskell.org/cpphs/
diff --git a/Text/ParserCombinators/HuttonMeijer.hs b/Text/ParserCombinators/HuttonMeijer.hs
deleted file mode 100644
--- a/Text/ParserCombinators/HuttonMeijer.hs
+++ /dev/null
@@ -1,218 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  ParseLib
--- Copyright   :  ...
--- Copyright   :  Graham Hutton (University of Nottingham), Erik Meijer (University of Utrecht)
--- 
--- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
--- Stability   :  Stable
--- Portability :  All
---
---                  A LIBRARY OF MONADIC PARSER COMBINATORS
--- 
---                               29th July 1996
--- 
---                  Graham Hutton               Erik Meijer
---             University of Nottingham    University of Utrecht
--- 
--- This Haskell script defines a library of parser combinators, and is
--- taken from sections 1-6 of our article "Monadic Parser Combinators".
--- Some changes to the library have been made in the move from Gofer
--- to Haskell:
--- 
---    * Do notation is used in place of monad comprehension notation;
--- 
---    * The parser datatype is defined using "newtype", to avoid the overhead
---      of tagging and untagging parsers with the P constructor.
------------------------------------------------------------------------------
-
-
-module Text.ParserCombinators.HuttonMeijer
-   (Parser(..), item, first, papply, (+++), sat, {-tok,-} many, many1,
-    sepby, sepby1, chainl,
-    chainl1, chainr, chainr1, ops, bracket, char, digit, lower, upper,
-    letter, alphanum, string, ident, nat, int, spaces, comment, junk,
-    skip, token, natural, integer, symbol, identifier) where
-
-import Char
-import Monad
-
-infixr 5 +++
-
-type Token = Char
-
----------------------------------------------------------
--- | The parser monad
-
-newtype Parser a   = P ([Token] -> [(a,[Token])])
-
-instance Functor Parser where
-   -- map         :: (a -> b) -> (Parser a -> Parser b)
-   fmap f (P p)    = P (\inp -> [(f v, out) | (v,out) <- p inp])
-
-instance Monad Parser where
-   -- return      :: a -> Parser a
-   return v        = P (\inp -> [(v,inp)])
-
-   -- >>=         :: Parser a -> (a -> Parser b) -> Parser b
-   (P p) >>= f     = P (\inp -> concat [papply (f v) out | (v,out) <- p inp])
-
-   -- fail        :: String -> Parser a
-   fail _          = P (\_ -> [])
-
-instance MonadPlus Parser where
-   -- mzero       :: Parser a
-   mzero           = P (\_ -> [])
-
-   -- mplus       :: Parser a -> Parser a -> Parser a
-   (P p) `mplus` (P q)  = P (\inp -> (p inp ++ q inp))
-
--- ------------------------------------------------------------
--- * Other primitive parser combinators
--- ------------------------------------------------------------
-
-item               :: Parser Token
-item                = P (\inp -> case inp of
-                                   []     -> []
-                                   (x:xs) -> [(x,xs)])
-
-first             :: Parser a -> Parser a
-first (P p)        = P (\inp -> case p inp of
-                                   []    -> []
-                                   (x:_) -> [x])
-
-papply            :: Parser a -> [Token] -> [(a,[Token])]
-papply (P p) inp   = p inp
-
--- ------------------------------------------------------------
--- * Derived combinators
--- ------------------------------------------------------------
-
-(+++)             :: Parser a -> Parser a -> Parser a
-p +++ q            = first (p `mplus` q)
-
-sat               :: (Token -> Bool) -> Parser Token
-sat p              = do {x <- item; if p x then return x else mzero}
-
---tok               :: Token -> Parser Token
---tok t              = do {x <- item; if t==snd x then return t else mzero}
-
-many              :: Parser a -> Parser [a]
-many p             = many1 p +++ return []
---many p           = force (many1 p +++ return [])
-
-many1             :: Parser a -> Parser [a]
-many1 p            = do {x <- p; xs <- many p; return (x:xs)}
-
-sepby             :: Parser a -> Parser b -> Parser [a]
-p `sepby` sep      = (p `sepby1` sep) +++ return []
-
-sepby1            :: Parser a -> Parser b -> Parser [a]
-p `sepby1` sep     = do {x <- p; xs <- many (do {sep; p}); return (x:xs)}
-
-chainl            :: Parser a -> Parser (a -> a -> a) -> a -> Parser a
-chainl p op v      = (p `chainl1` op) +++ return v
-
-chainl1           :: Parser a -> Parser (a -> a -> a) -> Parser a
-p `chainl1` op     = do {x <- p; rest x}
-                     where
-                        rest x = do {f <- op; y <- p; rest (f x y)}
-                                 +++ return x
-
-chainr            :: Parser a -> Parser (a -> a -> a) -> a -> Parser a
-chainr p op v      = (p `chainr1` op) +++ return v
-
-chainr1           :: Parser a -> Parser (a -> a -> a) -> Parser a
-p `chainr1` op     = do {x <- p; rest x}
-                     where
-                        rest x = do {f <- op; y <- p `chainr1` op; return (f x y)}
-                                 +++ return x
-
-ops               :: [(Parser a, b)] -> Parser b
-ops xs             = foldr1 (+++) [do {p; return op} | (p,op) <- xs]
-
-bracket           :: Parser a -> Parser b -> Parser c -> Parser b
-bracket open p close = do {open; x <- p; close; return x}
-
--- ------------------------------------------------------------
--- * Useful parsers
--- ------------------------------------------------------------
-
-char              :: Char -> Parser Char
-char x             = sat (\y -> x == y)
-
-digit             :: Parser Char
-digit              = sat isDigit
-
-lower             :: Parser Char
-lower              = sat isLower
-
-upper             :: Parser Char
-upper              = sat isUpper
-
-letter            :: Parser Char
-letter             = sat isAlpha
-
-alphanum          :: Parser Char
-alphanum           = sat isAlphaNum +++ char '_'
-
-string            :: String -> Parser String
-string ""          = return ""
-string (x:xs)      = do {char x; string xs; return (x:xs)}
-
-ident             :: Parser String
-ident              = do {x <- lower; xs <- many alphanum; return (x:xs)}
-
-nat               :: Parser Int
-nat                = do {x <- digit; return (fromEnum x - fromEnum '0')} `chainl1` return op
-                     where
-                        m `op` n = 10*m + n
-
-int               :: Parser Int
-int                = do {char '-'; n <- nat; return (-n)} +++ nat
-
--- ------------------------------------------------------------
--- * Lexical combinators
--- ------------------------------------------------------------
-
-spaces            :: Parser ()
-spaces             = do {many1 (sat isSpace); return ()}
-
-comment           :: Parser ()
---comment            = do {string "--"; many (sat (\x -> x /= '\n')); return ()}
---comment            = do 
---                       _ <- string "--"
---                       _ <- many (sat (\x -> x /= '\n'))
---                       return ()
-comment            = do
-                       bracket (string "/*") (many item) (string "*/")
-                       return ()
-
-junk              :: Parser ()
-junk               = do {many (spaces +++ comment); return ()}
-
-skip              :: Parser a -> Parser a
-skip p             = do {junk; p}
-
-token             :: Parser a -> Parser a
-token p            = do {v <- p; junk; return v}
-
--- ------------------------------------------------------------
--- * Token parsers
--- ------------------------------------------------------------
-
-natural           :: Parser Int
-natural            = token nat
-
-integer           :: Parser Int
-integer            = token int
-
-symbol            :: String -> Parser String
-symbol xs          = token (string xs)
-
-identifier        :: [String] -> Parser String
-identifier ks      = token (do {x <- ident;
-                                if not (elem x ks) then return x
-                                else return mzero})
-
-------------------------------------------------------------------------------
diff --git a/cpphs.cabal b/cpphs.cabal
--- a/cpphs.cabal
+++ b/cpphs.cabal
@@ -1,52 +1,109 @@
+Cabal-Version: 1.18
 Name: cpphs
-Version: 1.11
-Copyright: 2004-2010, Malcolm Wallace
-Build-Depends: base < 6, haskell98
+Version: 1.20.10
+Copyright: 2004-2017, Malcolm Wallace
 License: LGPL
 License-File: LICENCE-LGPL
-Author: Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
-Maintainer: Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
-Homepage: http://haskell.org/cpphs/
+Author: Malcolm Wallace <Malcolm.Wallace@me.com>
+Maintainer: Andreas Abel
+-- homepage:
+bug-reports: https://github.com/haskell-pkg-janitors/cpphs/issues
 Synopsis: A liberalised re-implementation of cpp, the C pre-processor.
 Description:
-	Cpphs is a re-implementation of the C pre-processor that is both
-	more compatible with Haskell, and itself written in Haskell so
-	that it can be distributed with compilers.
-	.
-	This version of the C pre-processor is pretty-much
-	feature-complete and compatible with traditional (K&R)
-	pre-processors.  Additional features include: a plain-text mode;
-	an option to unlit literate code files; and an option to turn
-	off macro-expansion.
+    Cpphs is a re-implementation of the C pre-processor that is both
+    more compatible with Haskell, and itself written in Haskell so
+    that it can be distributed with compilers.
+    .
+    This version of the C pre-processor is pretty-much
+    feature-complete and compatible with traditional (K&R)
+    pre-processors.  Additional features include: a plain-text mode;
+    an option to unlit literate code files; and an option to turn
+    off macro-expansion.
+    .
+    Old homepage: <https://archives.haskell.org/projects.haskell.org/cpphs/>
 Category: Development
 Build-type: Simple
-Exposed-Modules:
-	Language.Preprocessor.Cpphs
-	Language.Preprocessor.Unlit
-Other-Modules:
-	Language.Preprocessor.Cpphs.CppIfdef,
-	Language.Preprocessor.Cpphs.HashDefine,
-	Language.Preprocessor.Cpphs.MacroPass,
-	Language.Preprocessor.Cpphs.Options,
-	Language.Preprocessor.Cpphs.Position,
-	Language.Preprocessor.Cpphs.ReadFirst,
-	Language.Preprocessor.Cpphs.RunCpphs,
-	Language.Preprocessor.Cpphs.SymTab,
-	Language.Preprocessor.Cpphs.Tokenise,
-	Text.ParserCombinators.HuttonMeijer
 
-Executable: cpphs
-Main-Is: cpphs.hs
-Other-Modules:
-	Language.Preprocessor.Cpphs
-	Language.Preprocessor.Unlit
-	Language.Preprocessor.Cpphs.CppIfdef,
-	Language.Preprocessor.Cpphs.HashDefine,
-	Language.Preprocessor.Cpphs.MacroPass,
-	Language.Preprocessor.Cpphs.Options,
-	Language.Preprocessor.Cpphs.Position,
-	Language.Preprocessor.Cpphs.ReadFirst,
-	Language.Preprocessor.Cpphs.RunCpphs,
-	Language.Preprocessor.Cpphs.SymTab,
-	Language.Preprocessor.Cpphs.Tokenise,
-	Text.ParserCombinators.HuttonMeijer
+Extra-Doc-Files:
+  README.md
+  LICENCE-GPL
+  LICENCE-commercial
+  CHANGELOG.md
+  docs/cpphs.1
+  docs/index.html
+
+tested-with:
+  GHC == 9.14.1
+  GHC == 9.12.2
+  GHC == 9.10.2
+  GHC == 9.8.4
+  GHC == 9.6.7
+  GHC == 9.4.8
+  GHC == 9.2.8
+  GHC == 9.0.2
+  GHC == 8.10.7
+  GHC == 8.8.4
+  GHC == 8.6.5
+  GHC == 8.4.4
+  GHC == 8.2.2
+  GHC == 8.0.2
+
+Source-Repository head
+    Type:     git
+    Location: https://github.com/haskell-pkg-janitors/cpphs.git
+
+Library
+    Hs-Source-Dirs: . new
+
+    Build-Depends:
+      -- GHC-shipped libraries
+        base      >= 4.9  && < 5
+      , directory            < 1.4
+      , time      >= 1.5  && < 2
+      -- Other libraries
+      , polyparse >= 1.13 && < 1.14
+
+    Exposed-Modules:
+        Language.Preprocessor.Cpphs
+        Language.Preprocessor.Unlit
+    Other-Modules:
+        Language.Preprocessor.Cpphs.CppIfdef
+        Language.Preprocessor.Cpphs.HashDefine
+        Language.Preprocessor.Cpphs.MacroPass
+        Language.Preprocessor.Cpphs.Options
+        Language.Preprocessor.Cpphs.Position
+        Language.Preprocessor.Cpphs.ReadFirst
+        Language.Preprocessor.Cpphs.RunCpphs
+        Language.Preprocessor.Cpphs.SymTab
+        Language.Preprocessor.Cpphs.Tokenise
+        TimeCompat
+
+    default-language: Haskell2010
+
+Executable cpphs
+    Hs-Source-Dirs: . new
+    Main-Is: cpphs.hs
+
+    Build-Depends:
+      -- GHC-shipped libraries
+        base      >= 4.9  && < 5
+      , directory            < 1.4
+      , time      >= 1.5  && < 2
+      -- Other libraries
+      , polyparse >= 1.13 && < 1.14
+
+    Other-Modules:
+        Language.Preprocessor.Cpphs
+        Language.Preprocessor.Unlit
+        Language.Preprocessor.Cpphs.CppIfdef
+        Language.Preprocessor.Cpphs.HashDefine
+        Language.Preprocessor.Cpphs.MacroPass
+        Language.Preprocessor.Cpphs.Options
+        Language.Preprocessor.Cpphs.Position
+        Language.Preprocessor.Cpphs.ReadFirst
+        Language.Preprocessor.Cpphs.RunCpphs
+        Language.Preprocessor.Cpphs.SymTab
+        Language.Preprocessor.Cpphs.Tokenise
+        TimeCompat
+
+    default-language: Haskell2010
diff --git a/cpphs.compat b/cpphs.compat
deleted file mode 100644
--- a/cpphs.compat
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/sh
-#	A minimal compatibility script to make cpphs accept the same
-#	arguments as real cpp, wherever possible.
-CPPHS=/usr/malcolm/Haskell/cpphs/cpphs
-
-processArgs () {
-  TRADITIONAL=no
-  STRIP=yes
-  INFILE="-"
-  OUTFILE="-"
-  while test "$1" != ""
-  do
-    case $1 in
-      -D)            shift; echo -D$1 ;;
-      -D*)           echo $1 ;;
-      -U)            shift; echo -U$1 ;;
-      -U*)           echo $1 ;;
-      -I)            shift; echo -I$1 ;;
-      -I*)           echo $1 ;;
-      -o)            shift; echo -O$1 ;;
-      -o*)           echo -O`echo $1 | cut -c3-` ;;
-      -std*)         ;;		# ignore language spec
-      -x)            shift ;;	# ignore language spec
-      -ansi*)        TRADITIONAL=no ;;
-      -traditional*) TRADITIONAL=yes ;;
-      -include)      shift; echo $1 ;;
-      -P)            echo --noline ;;
-      -C)            STRIP=no ;;
-      -CC)           STRIP=no ;;
-      -A)            shift ;;	# strip assertions
-      --help)        echo $1 ;;
-      -version)      echo -$1 ;;
-      --version)     echo $1 ;;
-      -*)            ;;	# strip all other flags
-      *)     if [ "$INFILE" = "-" ]
-             then INFILE=$1
-             else OUTFILE=$1
-             fi ;;
-    esac
-    if test "$1" != ""; then shift; fi
-  done
-  if [ "$TRADITIONAL" = "no" ]; then echo "--hashes";   fi
-  if [ "$STRIP" = "yes" ];      then echo "--strip";    fi
-  echo $INFILE
-  if [ "$OUTFILE" != "-" ];     then echo "-O$OUTFILE"; fi
-}
-
-exec $CPPHS `processArgs "$@"`
diff --git a/cpphs.hs b/cpphs.hs
--- a/cpphs.hs
+++ b/cpphs.hs
@@ -11,21 +11,27 @@
 -}
 module Main where
 
-import System ( getArgs, getProgName, exitWith, ExitCode(..) )
-import Maybe
+import System.Environment ( getArgs, getProgName)
+import System.Exit ( exitWith, ExitCode(..) )
+import Data.Maybe
 import Language.Preprocessor.Cpphs ( runCpphs, CpphsOptions(..), parseOptions )
-import IO     ( stdout, IOMode(WriteMode), openFile, hPutStr, hFlush, hClose )
-import Monad  ( when )
-import List   ( isPrefixOf )
+import Language.Preprocessor.Cpphs.ReadFirst ( readFileUTF8, writeFileUTF8 )
+import System.IO     ( stdin, stdout, stderr, hFlush, hSetEncoding, utf8 )
+import Control.Monad  ( when )
+import Data.List   ( isPrefixOf )
 
 version :: String
-version = "1.11"
+version = "1.20.9"
 
 main :: IO ()
 main = do
+  hSetEncoding stdin  utf8
+  hSetEncoding stdout utf8
+  hSetEncoding stderr utf8
+
   args <- getArgs
   args <- return $ if "--cpp" `elem` args then convertArgs args else args
-  
+
   prog <- getProgName
   when ("--version" `elem` args)
        (do putStrLn (prog++" "++version)
@@ -43,7 +49,7 @@
       ins  = infiles  options
       outs = outfiles options
       out = listToMaybe outs
-  
+
   when (isLeft parsedArgs)
        (do putStrLn $ "Unknown option "++fromLeft parsedArgs
                       ++", for valid options try "++prog++" --help\n"
@@ -59,10 +65,10 @@
 execute :: CpphsOptions -> Maybe FilePath -> Maybe FilePath -> IO ()
 execute opts ofile infile =
   let (filename, readIt) = case infile of
-                             Just x  -> (x,       readFile x)
+                             Just x  -> (x,       readFileUTF8 x)
                              Nothing -> ("stdin", getContents)
       output Nothing x  = do putStr x; hFlush stdout
-      output (Just f) x = writeFile f x
+      output (Just f) x = writeFileUTF8 f x
   in do contents <- readIt
         transformed <- runCpphs opts filename contents
         output ofile transformed
@@ -82,7 +88,7 @@
 convertArgs xs = f (ConvertArgs False True "-" "-") xs
     where
         flg = "DUI"
-    
+
         f e (['-',r]:x:xs) | r `elem` flg = ('-':r:x) : f e xs
         f e (x@('-':r:_):xs) | r `elem` flg = x : f e xs
         f e ("-o":x:xs) = ('-':'O':x) : f e xs
@@ -100,11 +106,10 @@
         f e ("-version":xs) = "--version" : f e xs
         f e (('-':x):xs) = f e xs -- strip all other flags
         f e (x:xs) = f (if infile e == "-" then e{infile=x} else e{outfile=x}) xs
-        
+
         f e [] = ["--hashes" | not (traditional e)] ++
                  ["--strip" | traditional e && strip e] ++
                  ["--strip-eol" | not (traditional e) && strip e] ++
                  [infile e] ++
                  ["-O" ++ outfile e | outfile e /= "-"]
-
 
diff --git a/cpphs.hugs b/cpphs.hugs
deleted file mode 100644
--- a/cpphs.hugs
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-runhugs cpphs.hs --noline -D__HASKELL98__ -D__HUGS__ "$@"
diff --git a/docs/design b/docs/design
deleted file mode 100644
--- a/docs/design
+++ /dev/null
@@ -1,29 +0,0 @@
-Design for hspp
-
-First pass:
------------
-  * traverse the file,
-      - processing #if's and #ifdef's
-      - reading #include's and recursively doing this pass on them
-      - leaving #line's behind
-      - whilst taking account of #define's and #undef's
-  * only needs to look at lines beginning with a #
-  * should discard C-style comments?  (no)
-  * DO NOT gather the #define's for macros - their sequence matters!
-
-pass1 :: SymTab -> String -> String
-
-Second pass:
-------------
-  * traverse the residual file,
-      - keeping track of #define'd macros
-      - expanding #define'd macros when an instance is encountered
-  * needs a whitespace-preserving tokeniser with odd rules to
-    cover e.g. token concatenation.  Within Haskell, quotation marks start
-    strings, haskell comments are preserved.  Within a cpp directive,
-    quotation marks do not start a string, and C-style comments are
-    converted to whitespace.
-  * Line continuation characters are tricky; probably should only
-    be recognised within a macro definition, not in ordinary code.
-
-pass2 :: SymTab -> String -> String
diff --git a/docs/index.html b/docs/index.html
--- a/docs/index.html
+++ b/docs/index.html
@@ -198,13 +198,11 @@
 <b>Current stable version:</b>
 
 <p>
-cpphs-1.11, release date 2010.01.31<br>
+cpphs-1.20.8, release date 2017-06-22<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.
+<li> (1.20.8) another bugfix for windows drive letters in #includes.
 </ul>
 
 <p>
@@ -213,12 +211,12 @@
 The current <a href="http://darcs.net/">darcs</a> repository of
 cpphs is available at
 <pre>
-    darcs get http://www.cs.york.ac.uk/fp/darcs/cpphs
+    darcs get http://code.haskell.org/cpphs
 </pre>
-(Users on Windows or MacOS filesystems need to use the
-<tt>--partial</tt> flag.)  The source tree and version history can
+(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>.
+<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.
@@ -228,6 +226,246 @@
 <b>Older versions:</b>
 
 <p>
+cpphs-1.20.8, release date 2017-06-22<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> (1.20.8) another bugfix for windows drive letters in #includes.
+<li> (1.20.7) bugfix for windows drive letters in #includes.
+<li> (1.20.6) minor bugfix to avoid a crash in an obscure corner case
+</ul>
+
+<p>
+cpphs-1.20.5, release date 2017-04-11<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> (1.20.5) reverts the changes in 1.20.4
+</ul>
+
+<p>
+cpphs-1.20.4, release date 2017-02-27<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> (1.20.4) more windows path handling
+</ul>
+
+<p>
+cpphs-1.20.3, release date 2017-02-06<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> (1.20.3) detect an absolute windows path with a drive letter in a #include
+</ul>
+
+<p>
+cpphs-1.20.2, release date 2016-09-05<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> (1.20.2) ensure all input/output is UTF8, regardless of locale
+</ul>
+
+<p>
+cpphs-1.20, release date 2016-03-04<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> bugfix for #if defined(FOO) &amp;&amp; FOO(a,b)
+<li> (1.20.1) fix version number
+</ul>
+
+<p>
+cpphs-1.19.3, release date 2015-08-23<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> bugfix for hlint ticket #161, for
+     the interaction of --unlit and --linepragma options
+</ul>
+
+<p>
+cpphs-1.19.2, release date 2015-07-31<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> fix build error
+</ul>
+
+<p>
+cpphs-1.19.1, release date 2015-07-30<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> don't warn about trailing comments in #ifdefs
+</ul>
+
+<p>
+cpphs-1.19, release date 2015-03-30<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> expose more of the API
+</ul>
+
+<p>
+cpphs-1.18.9, release date 2015-02-19<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> accept "#if defined foo" as well as "#if defined(foo)"
+</ul>
+
+<p>
+cpphs-1.18.8, release date 2015-01-20<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> fix version number
+</ul>
+
+<p>
+cpphs-1.18.7, release date 2015.01.17<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> bugfix to accept a #include with absolute filepath
+</ul>
+
+<p>
+cpphs-1.18.6, release date 2014.10.17<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> bugfix to reject a macro usage with different arity than its definition
+</ul>
+
+<p>
+cpphs-1.18.5, release date 2014.06.26<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> fix a bug related to windows filepath directory separators in #includes
+</ul>
+
+<p>
+cpphs-1.18.4, release date 2014.03.22<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> fix the accidental flipping of comment-stripping behaviour
+     with --cpp -traditional flags.
+</ul>
+
+<p>
+cpphs-1.18.3, release date 2014.03.03<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> further rewrites of the #if expression parser, for better error messages,
+     support for integer operations, and fewer precedence bugs
+</ul>
+
+<p>
+cpphs-1.18.2, release date 2014.02.24<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> bugfix for erroneous boolean interpretation of some macro
+     expansions in #if clauses
+</ul>
+
+<p>
+cpphs-1.18.1, release date 2014.02.18<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> fix for incomplete pattern-match
+</ul>
+
+<p>
+cpphs-1.18, release date 2014.02.04<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> Better lexing of Template Haskell single quotes.  (Thanks to Stephan Wehr)
+</ul>
+
+<p>
+cpphs-1.17.1, release date 2013.08.18<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> (minor) Report the correct version number with <tt>cpphs --version</tt>
+</ul>
+
+<p>
+cpphs-1.17, release date 2013.08.16<br>
+By HTTP:
+<a href="http://code.haskell.org/cpphs/cpphs-1.17.tar.gz">.tar.gz</a>,
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> Recursively evaluate #if expressions after macro expansion (bugfix).
+</ul>
+
+<p>
+cpphs-1.16, release date 2013.01.22<br>
+By HTTP:
+<a href="http://code.haskell.org/cpphs/cpphs-1.16.tar.gz">.tar.gz</a>,
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> Fix the interaction of runCpphsReturningSymTab with --nomacro.
+</ul>
+
+<p>
+cpphs-1.15, release date 2012.11.30<br>
+By HTTP:
+<a href="http://code.haskell.org/cpphs/cpphs-1.15.tar.gz">.tar.gz</a>,
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> Fix the interaction of --nomacro with --strip.
+<li> Fix the error message received when # appears without a command.
+</ul>
+
+<p>
+cpphs-1.14, release date 2012.07.11<br>
+By HTTP:
+<a href="http://code.haskell.org/cpphs/cpphs-1.14.tar.gz">.tar.gz</a>,
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> New API to return symbol table after processing.
+</ul>
+
+<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>
+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>,
@@ -570,18 +808,20 @@
 guarantee to implement them if they depart much from the ordinary
 cpp's behaviour.  Please mail
 <ul>
-<li>    <a href="mailto:Malcolm.Wallace@cs.york.ac.uk">
-        Malcolm.Wallace@cs.york.ac.uk</a> 
+<li>    <a href="mailto:Malcolm.Wallace@me.com">
+        Malcolm.Wallace@me.com</a> 
 </ul>
 
-<p><b>Copyright:</b> &copy; 2004-2010 Malcolm Wallace,
-except for ParseLib (Copyright &copy; 1995 Graham Hutton and Erik Meijer)
+<p><b>Copyright:</b> &copy; 2004-2016 Malcolm Wallace
 
 <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
+for more details), with a special exception for static linking (see file <a href="COPYRIGHT">COPYRIGHT</a>.  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>).
+(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.
diff --git a/new/TimeCompat.hs b/new/TimeCompat.hs
new file mode 100644
--- /dev/null
+++ b/new/TimeCompat.hs
@@ -0,0 +1,2 @@
+module TimeCompat (defaultTimeLocale) where
+import Data.Time.Format (defaultTimeLocale)
diff --git a/tests/Arr.lhs b/tests/Arr.lhs
deleted file mode 100644
--- a/tests/Arr.lhs
+++ /dev/null
@@ -1,683 +0,0 @@
-\begin{code}
-{-# OPTIONS_GHC -fno-implicit-prelude -fno-bang-patterns #-}
------------------------------------------------------------------------------
--- |
--- Module      :  GHC.Arr
--- Copyright   :  (c) The University of Glasgow, 1994-2000
--- License     :  see libraries/base/LICENSE
--- 
--- Maintainer  :  cvs-ghc@haskell.org
--- Stability   :  internal
--- Portability :  non-portable (GHC extensions)
---
--- GHC\'s array implementation.
--- 
------------------------------------------------------------------------------
-
--- #hide
-module GHC.Arr where
-
-import {-# SOURCE #-} GHC.Err ( error )
-import GHC.Enum
-import GHC.Num
-import GHC.ST
-import GHC.Base
-import GHC.List
-import GHC.Show
-
-infixl 9  !, //
-
-default ()
-\end{code}
-
-
-%*********************************************************
-%*							*
-\subsection{The @Ix@ class}
-%*							*
-%*********************************************************
-
-\begin{code}
--- | The 'Ix' class is used to map a contiguous subrange of values in
--- a type onto integers.  It is used primarily for array indexing
--- (see "Data.Array", "Data.Array.IArray" and "Data.Array.MArray").
---
--- The first argument @(l,u)@ of each of these operations is a pair
--- specifying the lower and upper bounds of a contiguous subrange of values.
---
--- An implementation is entitled to assume the following laws about these
--- operations:
---
--- * @'inRange' (l,u) i == 'elem' i ('range' (l,u))@
---
--- * @'range' (l,u) '!!' 'index' (l,u) i == i@, when @'inRange' (l,u) i@
---
--- * @'map' ('index' (l,u)) ('range' (l,u))) == [0..'rangeSize' (l,u)-1]@
---
--- * @'rangeSize' (l,u) == 'length' ('range' (l,u))@
---
--- Minimal complete instance: 'range', 'index' and 'inRange'.
---
-class (Ord a) => Ix a where
-    -- | The list of values in the subrange defined by a bounding pair.
-    range		:: (a,a) -> [a]
-    -- | The position of a subscript in the subrange.
-    index		:: (a,a) -> a -> Int
-    -- | Like 'index', but without checking that the value is in range.
-    unsafeIndex		:: (a,a) -> a -> Int
-    -- | Returns 'True' the given subscript lies in the range defined
-    -- the bounding pair.
-    inRange		:: (a,a) -> a -> Bool
-    -- | The size of the subrange defined by a bounding pair.
-    rangeSize		:: (a,a) -> Int
-    -- | like 'rangeSize', but without checking that the upper bound is
-    -- in range.
-    unsafeRangeSize     :: (a,a) -> Int
-
-	-- Must specify one of index, unsafeIndex
-    index b i | inRange b i = unsafeIndex b i	
-	      | otherwise   = error "Error in array index"
-    unsafeIndex b i = index b i
-
-    rangeSize b@(_l,h) | inRange b h = unsafeIndex b h + 1
-		       | otherwise   = 0	-- This case is only here to
-						-- check for an empty range
-	-- NB: replacing (inRange b h) by (l <= h) fails for
-	--     tuples.  E.g.  (1,2) <= (2,1) but the range is empty
-
-    unsafeRangeSize b@(_l,h) = unsafeIndex b h + 1
-\end{code}
-
-Note that the following is NOT right
-	rangeSize (l,h) | l <= h    = index b h + 1
-			| otherwise = 0
-
-Because it might be the case that l<h, but the range
-is nevertheless empty.  Consider
-	((1,2),(2,1))
-Here l<h, but the second index ranges from 2..1 and
-hence is empty
-
-%*********************************************************
-%*							*
-\subsection{Instances of @Ix@}
-%*							*
-%*********************************************************
-
-\begin{code}
--- abstract these errors from the relevant index functions so that
--- the guts of the function will be small enough to inline.
-
-{-# NOINLINE indexError #-}
-indexError :: Show a => (a,a) -> a -> String -> b
-indexError rng i tp
-  = error (showString "Ix{" . showString tp . showString "}.index: Index " .
-           showParen True (showsPrec 0 i) .
-	   showString " out of range " $
-	   showParen True (showsPrec 0 rng) "")
-
-----------------------------------------------------------------------
-instance  Ix Char  where
-    {-# INLINE range #-}
-    range (m,n) = [m..n]
-
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex (m,_n) i = fromEnum i - fromEnum m
-
-    index b i | inRange b i =  unsafeIndex b i
-	      | otherwise   =  indexError b i "Char"
-
-    inRange (m,n) i	=  m <= i && i <= n
-
-----------------------------------------------------------------------
-instance  Ix Int  where
-    {-# INLINE range #-}
-	-- The INLINE stops the build in the RHS from getting inlined,
-	-- so that callers can fuse with the result of range
-    range (m,n) = [m..n]
-
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex (m,_n) i = i - m
-
-    index b i | inRange b i =  unsafeIndex b i
-	      | otherwise   =  indexError b i "Int"
-
-    {-# INLINE inRange #-}
-    inRange (I# m,I# n) (I# i) =  m <=# i && i <=# n
-
-----------------------------------------------------------------------
-instance  Ix Integer  where
-    {-# INLINE range #-}
-    range (m,n) = [m..n]
-
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex (m,_n) i   = fromInteger (i - m)
-
-    index b i | inRange b i =  unsafeIndex b i
-	      | otherwise   =  indexError b i "Integer"
-
-    inRange (m,n) i	=  m <= i && i <= n
-
-----------------------------------------------------------------------
-instance Ix Bool where -- as derived
-    {-# INLINE range #-}
-    range (m,n) = [m..n]
-
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex (l,_) i = fromEnum i - fromEnum l
-
-    index b i | inRange b i =  unsafeIndex b i
-	      | otherwise   =  indexError b i "Bool"
-
-    inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
-
-----------------------------------------------------------------------
-instance Ix Ordering where -- as derived
-    {-# INLINE range #-}
-    range (m,n) = [m..n]
-
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex (l,_) i = fromEnum i - fromEnum l
-
-    index b i | inRange b i =  unsafeIndex b i
-	      | otherwise   =  indexError b i "Ordering"
-
-    inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
-
-----------------------------------------------------------------------
-instance Ix () where
-    {-# INLINE range #-}
-    range   ((), ())    = [()]
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex   ((), ()) () = 0
-    {-# INLINE inRange #-}
-    inRange ((), ()) () = True
-    {-# INLINE index #-}
-    index b i = unsafeIndex b i
-
-----------------------------------------------------------------------
-instance (Ix a, Ix b) => Ix (a, b) where -- as derived
-    {-# SPECIALISE instance Ix (Int,Int) #-}
-
-    {- INLINE range #-}
-    range ((l1,l2),(u1,u2)) =
-      [ (i1,i2) | i1 <- range (l1,u1), i2 <- range (l2,u2) ]
-
-    {- INLINE unsafeIndex #-}
-    unsafeIndex ((l1,l2),(u1,u2)) (i1,i2) =
-      unsafeIndex (l1,u1) i1 * unsafeRangeSize (l2,u2) + unsafeIndex (l2,u2) i2
-
-    {- INLINE inRange #-}
-    inRange ((l1,l2),(u1,u2)) (i1,i2) =
-      inRange (l1,u1) i1 && inRange (l2,u2) i2
-
-    -- Default method for index
-
-----------------------------------------------------------------------
-instance  (Ix a1, Ix a2, Ix a3) => Ix (a1,a2,a3)  where
-    {-# SPECIALISE instance Ix (Int,Int,Int) #-}
-
-    range ((l1,l2,l3),(u1,u2,u3)) =
-        [(i1,i2,i3) | i1 <- range (l1,u1),
-                      i2 <- range (l2,u2),
-                      i3 <- range (l3,u3)]
-
-    unsafeIndex ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
-      unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
-      unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
-      unsafeIndex (l1,u1) i1))
-
-    inRange ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
-      inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
-      inRange (l3,u3) i3
-
-    -- Default method for index
-
-----------------------------------------------------------------------
-instance  (Ix a1, Ix a2, Ix a3, Ix a4) => Ix (a1,a2,a3,a4)  where
-    range ((l1,l2,l3,l4),(u1,u2,u3,u4)) =
-      [(i1,i2,i3,i4) | i1 <- range (l1,u1),
-                       i2 <- range (l2,u2),
-                       i3 <- range (l3,u3),
-                       i4 <- range (l4,u4)]
-
-    unsafeIndex ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
-      unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
-      unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
-      unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
-      unsafeIndex (l1,u1) i1)))
-
-    inRange ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
-      inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
-      inRange (l3,u3) i3 && inRange (l4,u4) i4
-
-    -- Default method for index
-
-instance  (Ix a1, Ix a2, Ix a3, Ix a4, Ix a5) => Ix (a1,a2,a3,a4,a5)  where
-    range ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) =
-      [(i1,i2,i3,i4,i5) | i1 <- range (l1,u1),
-                          i2 <- range (l2,u2),
-                          i3 <- range (l3,u3),
-                          i4 <- range (l4,u4),
-                          i5 <- range (l5,u5)]
-
-    unsafeIndex ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
-      unsafeIndex (l5,u5) i5 + unsafeRangeSize (l5,u5) * (
-      unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
-      unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
-      unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
-      unsafeIndex (l1,u1) i1))))
-
-    inRange ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
-      inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
-      inRange (l3,u3) i3 && inRange (l4,u4) i4 && 
-      inRange (l5,u5) i5
-
-    -- Default method for index
-\end{code}
-
-%*********************************************************
-%*							*
-\subsection{The @Array@ types}
-%*							*
-%*********************************************************
-
-\begin{code}
-type IPr = (Int, Int)
-
--- | The type of immutable non-strict (boxed) arrays
--- with indices in @i@ and elements in @e@.
-data Ix i => Array     i e = Array   !i !i (Array# e)
-
--- | Mutable, boxed, non-strict arrays in the 'ST' monad.  The type
--- arguments are as follows:
---
---  * @s@: the state variable argument for the 'ST' type
---
---  * @i@: the index type of the array (should be an instance of 'Ix')
---
---  * @e@: the element type of the array.
---
-data         STArray s i e = STArray !i !i (MutableArray# s e)
-	-- No Ix context for STArray.  They are stupid,
-	-- and force an Ix context on the equality instance.
-
--- Just pointer equality on mutable arrays:
-instance Eq (STArray s i e) where
-    STArray _ _ arr1# == STArray _ _ arr2# =
-        sameMutableArray# arr1# arr2#
-\end{code}
-
-
-%*********************************************************
-%*							*
-\subsection{Operations on immutable arrays}
-%*							*
-%*********************************************************
-
-\begin{code}
-{-# NOINLINE arrEleBottom #-}
-arrEleBottom :: a
-arrEleBottom = error "(Array.!): undefined array element"
-
--- | Construct an array with the specified bounds and containing values
--- for given indices within these bounds.
---
--- The array is undefined (i.e. bottom) if any index in the list is
--- out of bounds.  The Haskell 98 Report further specifies that if any
--- two associations in the list have the same index, the value at that
--- index is undefined (i.e. bottom).  However in GHC's implementation,
--- the value at such an index is the value part of the last association
--- with that index in the list.
---
--- Because the indices must be checked for these errors, 'array' is
--- strict in the bounds argument and in the indices of the association
--- list, but nonstrict in the values.  Thus, recurrences such as the
--- following are possible:
---
--- > a = array (1,100) ((1,1) : [(i, i * a!(i-1)) | i <- [2..100]])
---
--- Not every index within the bounds of the array need appear in the
--- association list, but the values associated with indices that do not
--- appear will be undefined (i.e. bottom).
---
--- If, in any dimension, the lower bound is greater than the upper bound,
--- then the array is legal, but empty.  Indexing an empty array always
--- gives an array-bounds error, but 'bounds' still yields the bounds
--- with which the array was constructed.
-{-# INLINE array #-}
-array :: Ix i
-	=> (i,i)	-- ^ a pair of /bounds/, each of the index type
-			-- of the array.  These bounds are the lowest and
-			-- highest indices in the array, in that order.
-			-- For example, a one-origin vector of length
-			-- '10' has bounds '(1,10)', and a one-origin '10'
-			-- by '10' matrix has bounds '((1,1),(10,10))'.
-	-> [(i, e)]	-- ^ a list of /associations/ of the form
-			-- (/index/, /value/).  Typically, this list will
-			-- be expressed as a comprehension.  An
-			-- association '(i, x)' defines the value of
-			-- the array at index 'i' to be 'x'.
-	-> Array i e
-array (l,u) ies = unsafeArray (l,u) [(index (l,u) i, e) | (i, e) <- ies]
-
-{-# INLINE unsafeArray #-}
-unsafeArray :: Ix i => (i,i) -> [(Int, e)] -> Array i e
-unsafeArray (l,u) ies = runST (ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# arrEleBottom s1#  of { (# s2#, marr# #) ->
-    foldr (fill marr#) (done l u marr#) ies s2# }})
-
-{-# INLINE fill #-}
-fill :: MutableArray# s e -> (Int, e) -> STRep s a -> STRep s a
-fill marr# (I# i#, e) next s1# =
-    case writeArray# marr# i# e s1#     of { s2# ->
-    next s2# }
-
-{-# INLINE done #-}
-done :: Ix i => i -> i -> MutableArray# s e -> STRep s (Array i e)
-done l u marr# s1# =
-    case unsafeFreezeArray# marr# s1#   of { (# s2#, arr# #) ->
-    (# s2#, Array l u arr# #) }
-
--- This is inefficient and I'm not sure why:
--- listArray (l,u) es = unsafeArray (l,u) (zip [0 .. rangeSize (l,u) - 1] es)
--- The code below is better. It still doesn't enable foldr/build
--- transformation on the list of elements; I guess it's impossible
--- using mechanisms currently available.
-
--- | Construct an array from a pair of bounds and a list of values in
--- index order.
-{-# INLINE listArray #-}
-listArray :: Ix i => (i,i) -> [e] -> Array i e
-listArray (l,u) es = runST (ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# arrEleBottom s1#  of { (# s2#, marr# #) ->
-    let fillFromList i# xs s3# | i# ==# n# = s3#
-                               | otherwise = case xs of
-            []   -> s3#
-            y:ys -> case writeArray# marr# i# y s3# of { s4# ->
-                    fillFromList (i# +# 1#) ys s4# } in
-    case fillFromList 0# es s2#         of { s3# ->
-    done l u marr# s3# }}})
-
--- | The value at the given index in an array.
-{-# INLINE (!) #-}
-(!) :: Ix i => Array i e -> i -> e
-arr@(Array l u _) ! i = unsafeAt arr (index (l,u) i)
-
-{-# INLINE unsafeAt #-}
-unsafeAt :: Ix i => Array i e -> Int -> e
-unsafeAt (Array _ _ arr#) (I# i#) =
-    case indexArray# arr# i# of (# e #) -> e
-
--- | The bounds with which an array was constructed.
-{-# INLINE bounds #-}
-bounds :: Ix i => Array i e -> (i,i)
-bounds (Array l u _) = (l,u)
-
--- | The list of indices of an array in ascending order.
-{-# INLINE indices #-}
-indices :: Ix i => Array i e -> [i]
-indices (Array l u _) = range (l,u)
-
--- | The list of elements of an array in index order.
-{-# INLINE elems #-}
-elems :: Ix i => Array i e -> [e]
-elems arr@(Array l u _) =
-    [unsafeAt arr i | i <- [0 .. rangeSize (l,u) - 1]]
-
--- | The list of associations of an array in index order.
-{-# INLINE assocs #-}
-assocs :: Ix i => Array i e -> [(i, e)]
-assocs arr@(Array l u _) =
-    [(i, unsafeAt arr (unsafeIndex (l,u) i)) | i <- range (l,u)]
-
--- | The 'accumArray' deals with repeated indices in the association
--- list using an /accumulating function/ which combines the values of
--- associations with the same index.
--- For example, given a list of values of some index type, @hist@
--- produces a histogram of the number of occurrences of each index within
--- a specified range:
---
--- > hist :: (Ix a, Num b) => (a,a) -> [a] -> Array a b
--- > hist bnds is = accumArray (+) 0 bnds [(i, 1) | i<-is, inRange bnds i]
---
--- If the accumulating function is strict, then 'accumArray' is strict in
--- the values, as well as the indices, in the association list.  Thus,
--- unlike ordinary arrays built with 'array', accumulated arrays should
--- not in general be recursive.
-{-# INLINE accumArray #-}
-accumArray :: Ix i
-	=> (e -> a -> e)	-- ^ accumulating function
-	-> e			-- ^ initial value
-	-> (i,i)		-- ^ bounds of the array
-	-> [(i, a)]		-- ^ association list
-	-> Array i e
-accumArray f init (l,u) ies =
-    unsafeAccumArray f init (l,u) [(index (l,u) i, e) | (i, e) <- ies]
-
-{-# INLINE unsafeAccumArray #-}
-unsafeAccumArray :: Ix i => (e -> a -> e) -> e -> (i,i) -> [(Int, a)] -> Array i e
-unsafeAccumArray f init (l,u) ies = runST (ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# init s1#          of { (# s2#, marr# #) ->
-    foldr (adjust f marr#) (done l u marr#) ies s2# }})
-
-{-# INLINE adjust #-}
-adjust :: (e -> a -> e) -> MutableArray# s e -> (Int, a) -> STRep s b -> STRep s b
-adjust f marr# (I# i#, new) next s1# =
-    case readArray# marr# i# s1#        of { (# s2#, old #) ->
-    case writeArray# marr# i# (f old new) s2# of { s3# ->
-    next s3# }}
-
--- | Constructs an array identical to the first argument except that it has
--- been updated by the associations in the right argument.
--- For example, if @m@ is a 1-origin, @n@ by @n@ matrix, then
---
--- > m//[((i,i), 0) | i <- [1..n]]
---
--- is the same matrix, except with the diagonal zeroed.
---
--- Repeated indices in the association list are handled as for 'array':
--- Haskell 98 specifies that the resulting array is undefined (i.e. bottom),
--- but GHC's implementation uses the last association for each index.
-{-# INLINE (//) #-}
-(//) :: Ix i => Array i e -> [(i, e)] -> Array i e
-arr@(Array l u _) // ies =
-    unsafeReplace arr [(index (l,u) i, e) | (i, e) <- ies]
-
-{-# INLINE unsafeReplace #-}
-unsafeReplace :: Ix i => Array i e -> [(Int, e)] -> Array i e
-unsafeReplace arr@(Array l u _) ies = runST (do
-    STArray _ _ marr# <- thawSTArray arr
-    ST (foldr (fill marr#) (done l u marr#) ies))
-
--- | @'accum' f@ takes an array and an association list and accumulates
--- pairs from the list into the array with the accumulating function @f@.
--- Thus 'accumArray' can be defined using 'accum':
---
--- > accumArray f z b = accum f (array b [(i, z) | i <- range b])
---
-{-# INLINE accum #-}
-accum :: Ix i => (e -> a -> e) -> Array i e -> [(i, a)] -> Array i e
-accum f arr@(Array l u _) ies =
-    unsafeAccum f arr [(index (l,u) i, e) | (i, e) <- ies]
-
-{-# INLINE unsafeAccum #-}
-unsafeAccum :: Ix i => (e -> a -> e) -> Array i e -> [(Int, a)] -> Array i e
-unsafeAccum f arr@(Array l u _) ies = runST (do
-    STArray _ _ marr# <- thawSTArray arr
-    ST (foldr (adjust f marr#) (done l u marr#) ies))
-
-{-# INLINE amap #-}
-amap :: Ix i => (a -> b) -> Array i a -> Array i b
-amap f arr@(Array l u _) =
-    unsafeArray (l,u) [(i, f (unsafeAt arr i)) | i <- [0 .. rangeSize (l,u) - 1]]
-
--- | 'ixmap' allows for transformations on array indices.
--- It may be thought of as providing function composition on the right
--- with the mapping that the original array embodies.
---
--- A similar transformation of array values may be achieved using 'fmap'
--- from the 'Array' instance of the 'Functor' class.
-{-# INLINE ixmap #-}
-ixmap :: (Ix i, Ix j) => (i,i) -> (i -> j) -> Array j e -> Array i e
-ixmap (l,u) f arr =
-    unsafeArray (l,u) [(unsafeIndex (l,u) i, arr ! f i) | i <- range (l,u)]
-
-{-# INLINE eqArray #-}
-eqArray :: (Ix i, Eq e) => Array i e -> Array i e -> Bool
-eqArray arr1@(Array l1 u1 _) arr2@(Array l2 u2 _) =
-    if rangeSize (l1,u1) == 0 then rangeSize (l2,u2) == 0 else
-    l1 == l2 && u1 == u2 &&
-    and [unsafeAt arr1 i == unsafeAt arr2 i | i <- [0 .. rangeSize (l1,u1) - 1]]
-
-{-# INLINE cmpArray #-}
-cmpArray :: (Ix i, Ord e) => Array i e -> Array i e -> Ordering
-cmpArray arr1 arr2 = compare (assocs arr1) (assocs arr2)
-
-{-# INLINE cmpIntArray #-}
-cmpIntArray :: Ord e => Array Int e -> Array Int e -> Ordering
-cmpIntArray arr1@(Array l1 u1 _) arr2@(Array l2 u2 _) =
-    if rangeSize (l1,u1) == 0 then if rangeSize (l2,u2) == 0 then EQ else LT else
-    if rangeSize (l2,u2) == 0 then GT else
-    case compare l1 l2 of
-        EQ    -> foldr cmp (compare u1 u2) [0 .. rangeSize (l1, min u1 u2) - 1]
-        other -> other
-    where
-    cmp i rest = case compare (unsafeAt arr1 i) (unsafeAt arr2 i) of
-        EQ    -> rest
-        other -> other
-
-{-# RULES "cmpArray/Int" cmpArray = cmpIntArray #-}
-\end{code}
-
-
-%*********************************************************
-%*							*
-\subsection{Array instances}
-%*							*
-%*********************************************************
-
-\begin{code}
-instance Ix i => Functor (Array i) where
-    fmap = amap
-
-instance (Ix i, Eq e) => Eq (Array i e) where
-    (==) = eqArray
-
-instance (Ix i, Ord e) => Ord (Array i e) where
-    compare = cmpArray
-
-instance (Ix a, Show a, Show b) => Show (Array a b) where
-    showsPrec p a =
-        showParen (p > appPrec) $
-        showString "array " .
-        showsPrec appPrec1 (bounds a) .
-        showChar ' ' .
-        showsPrec appPrec1 (assocs a)
-	-- Precedence of 'array' is the precedence of application
-
--- The Read instance is in GHC.Read
-\end{code}
-
-
-%*********************************************************
-%*							*
-\subsection{Operations on mutable arrays}
-%*							*
-%*********************************************************
-
-Idle ADR question: What's the tradeoff here between flattening these
-datatypes into @STArray ix ix (MutableArray# s elt)@ and using
-it as is?  As I see it, the former uses slightly less heap and
-provides faster access to the individual parts of the bounds while the
-code used has the benefit of providing a ready-made @(lo, hi)@ pair as
-required by many array-related functions.  Which wins? Is the
-difference significant (probably not).
-
-Idle AJG answer: When I looked at the outputted code (though it was 2
-years ago) it seems like you often needed the tuple, and we build
-it frequently. Now we've got the overloading specialiser things
-might be different, though.
-
-\begin{code}
-{-# INLINE newSTArray #-}
-newSTArray :: Ix i => (i,i) -> e -> ST s (STArray s i e)
-newSTArray (l,u) init = ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# init s1#          of { (# s2#, marr# #) ->
-    (# s2#, STArray l u marr# #) }}
-
-{-# INLINE boundsSTArray #-}
-boundsSTArray :: STArray s i e -> (i,i)  
-boundsSTArray (STArray l u _) = (l,u)
-
-{-# INLINE readSTArray #-}
-readSTArray :: Ix i => STArray s i e -> i -> ST s e
-readSTArray marr@(STArray l u _) i =
-    unsafeReadSTArray marr (index (l,u) i)
-
-{-# INLINE unsafeReadSTArray #-}
-unsafeReadSTArray :: Ix i => STArray s i e -> Int -> ST s e
-unsafeReadSTArray (STArray _ _ marr#) (I# i#) = ST $ \s1# ->
-    readArray# marr# i# s1#
-
-{-# INLINE writeSTArray #-}
-writeSTArray :: Ix i => STArray s i e -> i -> e -> ST s () 
-writeSTArray marr@(STArray l u _) i e =
-    unsafeWriteSTArray marr (index (l,u) i) e
-
-{-# INLINE unsafeWriteSTArray #-}
-unsafeWriteSTArray :: Ix i => STArray s i e -> Int -> e -> ST s () 
-unsafeWriteSTArray (STArray _ _ marr#) (I# i#) e = ST $ \s1# ->
-    case writeArray# marr# i# e s1#     of { s2# ->
-    (# s2#, () #) }
-\end{code}
-
-
-%*********************************************************
-%*							*
-\subsection{Moving between mutable and immutable}
-%*							*
-%*********************************************************
-
-\begin{code}
-freezeSTArray :: Ix i => STArray s i e -> ST s (Array i e)
-freezeSTArray (STArray l u marr#) = ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# arrEleBottom s1#  of { (# s2#, marr'# #) ->
-    let copy i# s3# | i# ==# n# = s3#
-                    | otherwise =
-            case readArray# marr# i# s3# of { (# s4#, e #) ->
-            case writeArray# marr'# i# e s4# of { s5# ->
-            copy (i# +# 1#) s5# }} in
-    case copy 0# s2#                    of { s3# ->
-    case unsafeFreezeArray# marr'# s3#  of { (# s4#, arr# #) ->
-    (# s4#, Array l u arr# #) }}}}
-
-{-# INLINE unsafeFreezeSTArray #-}
-unsafeFreezeSTArray :: Ix i => STArray s i e -> ST s (Array i e)
-unsafeFreezeSTArray (STArray l u marr#) = ST $ \s1# ->
-    case unsafeFreezeArray# marr# s1#   of { (# s2#, arr# #) ->
-    (# s2#, Array l u arr# #) }
-
-thawSTArray :: Ix i => Array i e -> ST s (STArray s i e)
-thawSTArray (Array l u arr#) = ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# arrEleBottom s1#  of { (# s2#, marr# #) ->
-    let copy i# s3# | i# ==# n# = s3#
-                    | otherwise =
-            case indexArray# arr# i#    of { (# e #) ->
-            case writeArray# marr# i# e s3# of { s4# ->
-            copy (i# +# 1#) s4# }} in
-    case copy 0# s2#                    of { s3# ->
-    (# s3#, STArray l u marr# #) }}}
-
-{-# INLINE unsafeThawSTArray #-}
-unsafeThawSTArray :: Ix i => Array i e -> ST s (STArray s i e)
-unsafeThawSTArray (Array l u arr#) = ST $ \s1# ->
-    case unsafeThawArray# arr# s1#      of { (# s2#, marr# #) ->
-    (# s2#, STArray l u marr# #) }
-\end{code}
diff --git a/tests/HsOpenGLExt.h b/tests/HsOpenGLExt.h
deleted file mode 100644
--- a/tests/HsOpenGLExt.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Module      :  GL extension support for Graphics.Rendering.OpenGL
- * Copyright   :  (c) Sven Panne 2002-2004
- * License     :  BSD-style (see the file libraries/OpenGL/LICENSE)
- * 
- * Maintainer  :  sven.panne@aedion.de
- * Stability   :  provisional
- * Portability :  portable
- *
- * This header should only define preprocessor macros!
- *
- * -------------------------------------------------------------------------- */
-
-#ifndef HSOPENGLEXT_H
-#define HSOPENGLEXT_H
-
-/* NOTE: The macro must immediately start with the foreign declaration,
-   otherwise the magic mangler (hack_foreign) in the Hugs build system
-   doesn't recognize it. */
-#define EXTENSION_ENTRY(_msg,_entry,_ty) \
-foreign import CALLCONV unsafe "dynamic" dyn_/**/_entry :: Graphics.Rendering.OpenGL.GL.Extensions.Invoker (_ty) ; \
-_entry :: (_ty) ; \
-_entry = dyn_##_entry ptr_##_entry ; \
-ptr_/**/_entry :: FunPtr a ; \
-ptr_/**/_entry = unsafePerformIO (Graphics.Rendering.OpenGL.GL.Extensions.getProcAddress (_msg) ("_entry")) ; \
-{-# NOINLINE ptr_/**/_entry #-}
-
-#endif
-
-EXTENSION_ENTRY("GL_EXT_fog_coord or OpenGL 1.4",glFogCoorddEXT,GLdouble -> IO ())
diff --git a/tests/MachDeps.h b/tests/MachDeps.h
deleted file mode 100644
--- a/tests/MachDeps.h
+++ /dev/null
diff --git a/tests/Storable.hs b/tests/Storable.hs
deleted file mode 100644
--- a/tests/Storable.hs
+++ /dev/null
@@ -1,246 +0,0 @@
-{-# OPTIONS -fno-implicit-prelude #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Foreign.Storable
--- Copyright   :  (c) The FFI task force 2001
--- License     :  see libraries/base/LICENSE
--- 
--- Maintainer  :  ffi@haskell.org
--- Stability   :  provisional
--- Portability :  portable
---
--- The module "Foreign.Storable" provides most elementary support for
--- marshalling and is part of the language-independent portion of the
--- Foreign Function Interface (FFI), and will normally be imported via
--- the "Foreign" module.
---
------------------------------------------------------------------------------
-
-module Foreign.Storable
-	( Storable(
-	     sizeOf,         -- :: a -> Int
-	     alignment,      -- :: a -> Int
-	     peekElemOff,    -- :: Ptr a -> Int      -> IO a
-	     pokeElemOff,    -- :: Ptr a -> Int -> a -> IO ()
-	     peekByteOff,    -- :: Ptr b -> Int      -> IO a
-	     pokeByteOff,    -- :: Ptr b -> Int -> a -> IO ()
-	     peek,           -- :: Ptr a             -> IO a
-	     poke)           -- :: Ptr a        -> a -> IO ()
-        ) where
-
-
-#ifdef __NHC__
-import NHC.FFI (Storable(..),Ptr,FunPtr,StablePtr
-               ,Int8,Int16,Int32,Int64,Word8,Word16,Word32,Word64)
-#else
-
-import Control.Monad		( liftM )
-
-#include "MachDeps.h"
-#include "config.h"
-
-#ifdef __GLASGOW_HASKELL__
-import GHC.Storable
-import GHC.Stable	( StablePtr )
-import GHC.Num
-import GHC.Int
-import GHC.Word
-import GHC.Stable
-import GHC.Ptr
-import GHC.Float
-import GHC.Err
-import GHC.IOBase
-import GHC.Base
-#else
-import Data.Int
-import Data.Word
-import Foreign.Ptr
-import Foreign.StablePtr
-#endif
-
-#ifdef __HUGS__
-import Hugs.Prelude
-import Hugs.Storable
-#endif
-
-{- |
-The member functions of this class facilitate writing values of
-primitive types to raw memory (which may have been allocated with the
-above mentioned routines) and reading values from blocks of raw
-memory.  The class, furthermore, includes support for computing the
-storage requirements and alignment restrictions of storable types.
-
-Memory addresses are represented as values of type @'Ptr' a@, for some
-@a@ which is an instance of class 'Storable'.  The type argument to
-'Ptr' helps provide some valuable type safety in FFI code (you can\'t
-mix pointers of different types without an explicit cast), while
-helping the Haskell type system figure out which marshalling method is
-needed for a given pointer.
-
-All marshalling between Haskell and a foreign language ultimately
-boils down to translating Haskell data structures into the binary
-representation of a corresponding data structure of the foreign
-language and vice versa.  To code this marshalling in Haskell, it is
-necessary to manipulate primtive data types stored in unstructured
-memory blocks.  The class 'Storable' facilitates this manipulation on
-all types for which it is instantiated, which are the standard basic
-types of Haskell, the fixed size @Int@ types ('Int8', 'Int16',
-'Int32', 'Int64'), the fixed size @Word@ types ('Word8', 'Word16',
-'Word32', 'Word64'), 'StablePtr', all types from "Foreign.C.Types",
-as well as 'Ptr'.
-
-Minimal complete definition: 'sizeOf', 'alignment', one of 'peek',
-'peekElemOff' and 'peekByteOff', and one of 'poke', 'pokeElemOff' and
-'pokeByteOff'.
--}
-
-class Storable a where
-
-   sizeOf      :: a -> Int
-   -- ^ Computes the storage requirements (in bytes) of the argument.
-   -- The value of the argument is not used.
-
-   alignment   :: a -> Int
-   -- ^ Computes the alignment constraint of the argument.  An
-   -- alignment constraint @x@ is fulfilled by any address divisible
-   -- by @x@.  The value of the argument is not used.
-
-   peekElemOff :: Ptr a -> Int      -> IO a
-   -- ^       Read a value from a memory area regarded as an array
-   --         of values of the same kind.  The first argument specifies
-   --         the start address of the array and the second the index into
-   --         the array (the first element of the array has index
-   --         @0@).  The following equality holds,
-   -- 
-   -- > peekElemOff addr idx = IOExts.fixIO $ \result ->
-   -- >   peek (addr `plusPtr` (idx * sizeOf result))
-   --
-   --         Note that this is only a specification, not
-   --         necessarily the concrete implementation of the
-   --         function.
-
-   pokeElemOff :: Ptr a -> Int -> a -> IO ()
-   -- ^       Write a value to a memory area regarded as an array of
-   --         values of the same kind.  The following equality holds:
-   -- 
-   -- > pokeElemOff addr idx x = 
-   -- >   poke (addr `plusPtr` (idx * sizeOf x)) x
-
-   peekByteOff :: Ptr b -> Int      -> IO a
-   -- ^       Read a value from a memory location given by a base
-   --         address and offset.  The following equality holds:
-   --
-   -- > peekByteOff addr off = peek (addr `plusPtr` off)
-
-   pokeByteOff :: Ptr b -> Int -> a -> IO ()
-   -- ^       Write a value to a memory location given by a base
-   --         address and offset.  The following equality holds:
-   --
-   -- > pokeByteOff addr off x = poke (addr `plusPtr` off) x
-  
-   peek        :: Ptr a      -> IO a
-   -- ^ Read a value from the given memory location.
-   --
-   --  Note that the peek and poke functions might require properly
-   --  aligned addresses to function correctly.  This is architecture
-   --  dependent; thus, portable code should ensure that when peeking or
-   --  poking values of some type @a@, the alignment
-   --  constraint for @a@, as given by the function
-   --  'alignment' is fulfilled.
-
-   poke        :: Ptr a -> a -> IO ()
-   -- ^ Write the given value to the given memory location.  Alignment
-   -- restrictions might apply; see 'peek'.
- 
-   -- circular default instances
-#ifdef __GLASGOW_HASKELL__
-   peekElemOff = peekElemOff_ undefined
-      where peekElemOff_ :: a -> Ptr a -> Int -> IO a
-            peekElemOff_ undef ptr off = peekByteOff ptr (off * sizeOf undef)
-#else
-   peekElemOff ptr off = peekByteOff ptr (off * sizeOfPtr ptr undefined)
-#endif
-   pokeElemOff ptr off val = pokeByteOff ptr (off * sizeOf val) val
-
-   peekByteOff ptr off = peek (ptr `plusPtr` off)
-   pokeByteOff ptr off = poke (ptr `plusPtr` off)
-
-   peek ptr = peekElemOff ptr 0
-   poke ptr = pokeElemOff ptr 0
-
-#ifndef __GLASGOW_HASKELL__
-sizeOfPtr :: Storable a => Ptr a -> a -> Int
-sizeOfPtr px x = sizeOf x
-#endif
-
--- System-dependent, but rather obvious instances
-
-instance Storable Bool where
-   sizeOf _          = sizeOf (undefined::HTYPE_INT)
-   alignment _       = alignment (undefined::HTYPE_INT)
-   peekElemOff p i   = liftM (/= (0::HTYPE_INT)) $ peekElemOff (castPtr p) i
-   pokeElemOff p i x = pokeElemOff (castPtr p) i (if x then 1 else 0::HTYPE_INT)
-
-#define STORABLE(T,size,align,read,write)	\
-instance Storable (T) where {			\
-    sizeOf    _ = size;				\
-    alignment _ = align;			\
-    peekElemOff = read;				\
-    pokeElemOff = write }
-
-#ifdef __GLASGOW_HASKELL__
-STORABLE(Char,SIZEOF_INT32,ALIGNMENT_INT32,
-	 readWideCharOffPtr,writeWideCharOffPtr)
-#elif defined(__HUGS__)
-STORABLE(Char,SIZEOF_HSCHAR,ALIGNMENT_HSCHAR,
-	 readCharOffPtr,writeCharOffPtr)
-#endif
-
-STORABLE(Int,SIZEOF_HSINT,ALIGNMENT_HSINT,
-	 readIntOffPtr,writeIntOffPtr)
-
-#ifdef __GLASGOW_HASKELL__
-STORABLE(Word,SIZEOF_HSWORD,ALIGNMENT_HSWORD,
-	 readWordOffPtr,writeWordOffPtr)
-#endif
-
-STORABLE((Ptr a),SIZEOF_HSPTR,ALIGNMENT_HSPTR,
-	 readPtrOffPtr,writePtrOffPtr)
-
-STORABLE((FunPtr a),SIZEOF_HSFUNPTR,ALIGNMENT_HSFUNPTR,
-	 readFunPtrOffPtr,writeFunPtrOffPtr)
-
-STORABLE((StablePtr a),SIZEOF_HSSTABLEPTR,ALIGNMENT_HSSTABLEPTR,
-	 readStablePtrOffPtr,writeStablePtrOffPtr)
-
-STORABLE(Float,SIZEOF_HSFLOAT,ALIGNMENT_HSFLOAT,
-	 readFloatOffPtr,writeFloatOffPtr)
-
-STORABLE(Double,SIZEOF_HSDOUBLE,ALIGNMENT_HSDOUBLE,
-	 readDoubleOffPtr,writeDoubleOffPtr)
-
-STORABLE(Word8,SIZEOF_WORD8,ALIGNMENT_WORD8,
-	 readWord8OffPtr,writeWord8OffPtr)
-
-STORABLE(Word16,SIZEOF_WORD16,ALIGNMENT_WORD16,
-	 readWord16OffPtr,writeWord16OffPtr)
-
-STORABLE(Word32,SIZEOF_WORD32,ALIGNMENT_WORD32,
-	 readWord32OffPtr,writeWord32OffPtr)
-
-STORABLE(Word64,SIZEOF_WORD64,ALIGNMENT_WORD64,
-	 readWord64OffPtr,writeWord64OffPtr)
-
-STORABLE(Int8,SIZEOF_INT8,ALIGNMENT_INT8,
-	 readInt8OffPtr,writeInt8OffPtr)
-
-STORABLE(Int16,SIZEOF_INT16,ALIGNMENT_INT16,
-	 readInt16OffPtr,writeInt16OffPtr)
-
-STORABLE(Int32,SIZEOF_INT32,ALIGNMENT_INT32,
-	 readInt32OffPtr,writeInt32OffPtr)
-
-STORABLE(Int64,SIZEOF_INT64,ALIGNMENT_INT64,
-	 readInt64OffPtr,writeInt64OffPtr)
-
-#endif
diff --git a/tests/Test.hsc b/tests/Test.hsc
deleted file mode 100644
--- a/tests/Test.hsc
+++ /dev/null
@@ -1,11 +0,0 @@
-module Test where
-
-main :: IO ()
-main = putStrLn "shows a cpphs+hsc2hs bug with comments"
-
-#def inline int that_one_will_work(void) {return 42;}
-
-{-
-#def inline int cpphs_will_stumble(void) {return 42;}
--}
-
diff --git a/tests/chains b/tests/chains
deleted file mode 100644
--- a/tests/chains
+++ /dev/null
@@ -1,16 +0,0 @@
-For this test, assume that all of e,f,g,h are defined.
-Also that c,d are defined, a,b are not.
-If cpphs does operator precedence wrongly in infix chains, the final
-conditional will be interpreted wrongly.
-
-#if defined(a) || defined(b) || defined(c) || defined(d)
-chained || OK
-#endif
-#if defined(e) && defined(f) && defined(g) && defined(h)
-chained && OK
-#endif
-#if defined(a) && defined(b) || defined(c) && defined(d)
-mixed chain of || and && OK
-#else
-mixed chain of || and && BROKEN
-#endif
diff --git a/tests/comments b/tests/comments
deleted file mode 100644
--- a/tests/comments
+++ /dev/null
@@ -1,3 +0,0 @@
-here is an ordinary C comment:			/* comment here */
-and here is a C++-style end-of-line comment:	// comment here
-this line has no comments
diff --git a/tests/config.h b/tests/config.h
deleted file mode 100644
--- a/tests/config.h
+++ /dev/null
diff --git a/tests/cpp b/tests/cpp
deleted file mode 100644
--- a/tests/cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#define /**/ ++ `mplus`		// not expected to work
-#define 0   mzero		// not expected to work
-#define x0  X'			// should work
-#define x'  Xprime		// should work
-#define `foo` .(foo)/**/,	// bizarreness
-
-x ++ y = x0 * 0 * y `foo` x' 
-
-//  /*
diff --git a/tests/elif b/tests/elif
deleted file mode 100644
--- a/tests/elif
+++ /dev/null
@@ -1,10 +0,0 @@
-#if ( defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ > 502 ) || \
-    ( defined(__NHC__) && __NHC__ > 114 ) || defined(__HUGS__)
-import System.IO.Unsafe (unsafePerformIO)
-#elif defined(__GLASGOW_HASKELL__)
-import IOExts (unsafePerformIO)
-#elif defined(__NHC__)
-import IOExtras (unsafePerformIO)
-#elif defined(__HBC__)
-import UnsafePerformIO
-#endif
diff --git a/tests/endcode-a b/tests/endcode-a
deleted file mode 100644
--- a/tests/endcode-a
+++ /dev/null
@@ -1,3 +0,0 @@
-\hidden{
-\begin{code}
-\end{code}}
diff --git a/tests/endcode-b b/tests/endcode-b
deleted file mode 100644
--- a/tests/endcode-b
+++ /dev/null
@@ -1,4 +0,0 @@
-\hidden{
-\begin{code}
-\end{code}
-}
diff --git a/tests/expect1 b/tests/expect1
deleted file mode 100644
--- a/tests/expect1
+++ /dev/null
@@ -1,36 +0,0 @@
-#line 1 "testfile"
-1 top of file
-
-3
-
-5 X is defined
-
-7
-
-
-
-11
-
-
-
-15
-
-
-
-19
-
-
-
-23 no inclusion, this is an else clause
-
-25
-
-
-
-
-
-31 third branch of elif
-
-33
-34 end of file
-
diff --git a/tests/expect10 b/tests/expect10
deleted file mode 100644
--- a/tests/expect10
+++ /dev/null
@@ -1,15 +0,0 @@
-#line 1 "multiline"
-
-
-
-
-5 back to ordinary text.
-#line 1 "./inclusion"
-hello world, this is an inclusion
-
-#line 7 "multiline"
-7 hello again
-8 some more
-9 aLongMacroDefinition(a,b)
-10 end
-
diff --git a/tests/expect11 b/tests/expect11
deleted file mode 100644
--- a/tests/expect11
+++ /dev/null
@@ -1,3 +0,0 @@
-#line 1 "stringise"
-
-This is "abcd ef" foo abcd ef
diff --git a/tests/expect12 b/tests/expect12
deleted file mode 100644
--- a/tests/expect12
+++ /dev/null
@@ -1,5 +0,0 @@
-#line 1 "recursive"
-
-
-
-D D D D D D D D
diff --git a/tests/expect13 b/tests/expect13
deleted file mode 100644
--- a/tests/expect13
+++ /dev/null
@@ -1,20 +0,0 @@
-#line 1 "ross"
-                                                         
-
-                           
-
-
-
-f = 4
-
-                                                             
-
-
-
-
-g = do { putStr "Hello ";   putStrLn "World" }
-
-                          
-
-
-h = 4
diff --git a/tests/expect14 b/tests/expect14
deleted file mode 100644
--- a/tests/expect14
+++ /dev/null
@@ -1,4 +0,0 @@
-#line 1 "precedence"
-
-
-
diff --git a/tests/expect15 b/tests/expect15
deleted file mode 100644
--- a/tests/expect15
+++ /dev/null
@@ -1,6 +0,0 @@
-#line 1 "indirect"
-
-#line 1 "./inclusion"
-hello world, this is an inclusion
-
-#line 3 "indirect"
diff --git a/tests/expect15a b/tests/expect15a
deleted file mode 100644
--- a/tests/expect15a
+++ /dev/null
@@ -1,6 +0,0 @@
-#line 1 "indirect-a"
-
-#line 1 "./inclusion"
-hello world, this is an inclusion
-
-#line 3 "indirect-a"
diff --git a/tests/expect16 b/tests/expect16
deleted file mode 100644
--- a/tests/expect16
+++ /dev/null
@@ -1,30 +0,0 @@
-#line 1 "numbers"
-
-number (1) in if
-
-
-
-
-
-
-
-number (0) in if
-
-
-
-
-
-rejected false hex number in if
-
-
-
-real hex number (0x1) in if
-
-
-
-
-
-
-
-hex number (0x00) in if
-
diff --git a/tests/expect17 b/tests/expect17
deleted file mode 100644
--- a/tests/expect17
+++ /dev/null
@@ -1,2 +0,0 @@
-#line 1 "pragma"
-
diff --git a/tests/expect18 b/tests/expect18
deleted file mode 100644
--- a/tests/expect18
+++ /dev/null
@@ -1,1 +0,0 @@
-
diff --git a/tests/expect19 b/tests/expect19
deleted file mode 100644
--- a/tests/expect19
+++ /dev/null
@@ -1,6 +0,0 @@
-#line 1 "parens"
-
-
-
-
-yes
diff --git a/tests/expect2 b/tests/expect2
deleted file mode 100644
--- a/tests/expect2
+++ /dev/null
@@ -1,36 +0,0 @@
-#line 1 "testfile"
-1 top of file
-
-3
-
-5 X is defined
-
-7
-
-
-
-11
-
-
-
-15
-
-
-
-19
-
-
-
-23 no inclusion, this is an else clause
-
-25
-
-27 no elif
-
-
-
-
-
-33
-34 end of file
-
diff --git a/tests/expect20 b/tests/expect20
deleted file mode 100644
--- a/tests/expect20
+++ /dev/null
@@ -1,17 +0,0 @@
-#line 1 "chains"
-For this test, assume that all of 1,1,1,1 are defined.
-Also that 1,1 are defined, a,b are not.
-If cpphs does operator precedence wrongly in infix chains, the final
-conditional will be interpreted wrongly.
-
-
-chained || OK
-
-
-chained && OK
-
-
-mixed chain of || and && OK
-
-
-
diff --git a/tests/expect21 b/tests/expect21
deleted file mode 100644
--- a/tests/expect21
+++ /dev/null
@@ -1,6 +0,0 @@
-#line 1 "specials"
-
-line 2
-line 3
-line 4  Error "horrible" at line 4 of file "specials"
-line 5
diff --git a/tests/expect22 b/tests/expect22
deleted file mode 100644
--- a/tests/expect22
+++ /dev/null
@@ -1,13 +0,0 @@
-#line 1 "specialinclude"
-1
-2
-#line 1 "./specials"
-
-line 2
-line 3
-line 4  Error "horrible" at line 4 of file "./specials"
-line 5
-
-#line 4 "specialinclude"
-4
-5
diff --git a/tests/expect23 b/tests/expect23
deleted file mode 100644
--- a/tests/expect23
+++ /dev/null
@@ -1,2 +0,0 @@
-#line 1 "incomplete"
-incomplete
diff --git a/tests/expect24 b/tests/expect24
deleted file mode 100644
--- a/tests/expect24
+++ /dev/null
@@ -1,15 +0,0 @@
-#line 1 "text"
-Here is some ordinary text with embedded Haskell-ish constructs,
-that should however /not/ be interpreted as Haskell if the --text
-option is given to cpphs.  For instance, here is a Haskell comment
-including a cpp definition: {-
-#  define FOO bar
-and now we end the comment: -}   and try out the definition:  FOO
-Likewise, double and single quotes no longer delimit strings or chars: "
-#  define BAZ FOO
-and what do we have here?: "  ' BAZ  '
-
-
-Also, in text-mode, macros should be expanded inside Haskell comments:
-    -- expand(this,other,that)
-and strings "expand(this,other,that)".
diff --git a/tests/expect25 b/tests/expect25
deleted file mode 100644
--- a/tests/expect25
+++ /dev/null
@@ -1,15 +0,0 @@
-#line 1 "text"
-Here is some ordinary text with embedded Haskell-ish constructs,
-that should however /not/ be interpreted as Haskell if the --text
-option is given to cpphs.  For instance, here is a Haskell comment
-including a cpp definition: {-
-
-and now we end the comment: -}   and try out the definition:  bar
-Likewise, double and single quotes no longer delimit strings or chars: "
-
-and what do we have here?: "  ' bar  '
-
-
-Also, in text-mode, macros should be expanded inside Haskell comments:
-    -- Some text including this, the other, and that.
-and strings "Some text including this, the other, and that.".
diff --git a/tests/expect26 b/tests/expect26
deleted file mode 100644
--- a/tests/expect26
+++ /dev/null
@@ -1,17 +0,0 @@
-#line 1 "nastyhack"
-
--- hackery to convice cpp to splice 6.2.2 into a string
-version :: String
-version = tail "\ 
-    \ 6.2.2"
-
-version2 = "6.2.2"
-
-
-version3 = "6.2.2"
-
-
-version4 = #6.2.2
-
-
-version5 = "6.2.2"
diff --git a/tests/expect27 b/tests/expect27
deleted file mode 100644
--- a/tests/expect27
+++ /dev/null
@@ -1,17 +0,0 @@
-#line 1 "nastyhack"
-
--- hackery to convice cpp to splice GHC_PKG_VERSION into a string
-version :: String
-version = tail "\ 
-    \ GHC_PKG_VERSION"
-
-version2 = "GHC_PKG_VERSION"
-
-
-version3 = "GHC_PKG_VERSION"
-
-
-version4 = #6.2.2
-
-
-version5 = "6.2.2"
diff --git a/tests/expect28 b/tests/expect28
deleted file mode 100644
--- a/tests/expect28
+++ /dev/null
@@ -1,4 +0,0 @@
-#line 1 "symbolvalue"
-
-the symbol is defined as 1
-
diff --git a/tests/expect29 b/tests/expect29
deleted file mode 100644
--- a/tests/expect29
+++ /dev/null
@@ -1,12 +0,0 @@
-#line 1 "Test.hsc"
-module Test where
-
-main :: IO ()
-main = putStrLn "shows a cpphs+hsc2hs bug with comments"
-
-
-
-{-
-#def inline int cpphs_will_stumble(void) {return 42;}
--}
-
diff --git a/tests/expect3 b/tests/expect3
deleted file mode 100644
--- a/tests/expect3
+++ /dev/null
@@ -1,36 +0,0 @@
-#line 1 "testfile"
-1 top of file
-
-3
-
-5 X is defined
-
-7
-
-
-
-11
-
-
-
-15
-
-
-
-19
-
-
-
-23 no inclusion, this is an else clause
-
-25
-
-
-
-29 this is an elif
-
-
-
-33
-34 end of file
-
diff --git a/tests/expect30 b/tests/expect30
deleted file mode 100644
--- a/tests/expect30
+++ /dev/null
@@ -1,685 +0,0 @@
-#line 1 "Arr.lhs"
-
-{-# OPTIONS_GHC -fno-implicit-prelude -fno-bang-patterns #-}
------------------------------------------------------------------------------
--- |
--- Module      :  GHC.Arr
--- Copyright   :  (c) The University of Glasgow, 1994-2000
--- License     :  see libraries/base/LICENSE
--- 
--- Maintainer  :  cvs-ghc@haskell.org
--- Stability   :  internal
--- Portability :  non-portable (GHC extensions)
---
--- GHC\'s array implementation.
--- 
------------------------------------------------------------------------------
-
--- #hide
-module GHC.Arr where
-
-import {-# SOURCE #-} GHC.Err ( error )
-import GHC.Enum
-import GHC.Num
-import GHC.ST
-import GHC.Base
-import GHC.List
-import GHC.Show
-
-infixl 9  !, //
-
-default ()
-
-
-
-
-
-
-
-
-
-
--- | The 'Ix' class is used to map a contiguous subrange of values in
--- a type onto integers.  It is used primarily for array indexing
--- (see "Data.Array", "Data.Array.IArray" and "Data.Array.MArray").
---
--- The first argument @(l,u)@ of each of these operations is a pair
--- specifying the lower and upper bounds of a contiguous subrange of values.
---
--- An implementation is entitled to assume the following laws about these
--- operations:
---
--- * @'inRange' (l,u) i == 'elem' i ('range' (l,u))@
---
--- * @'range' (l,u) '!!' 'index' (l,u) i == i@, when @'inRange' (l,u) i@
---
--- * @'map' ('index' (l,u)) ('range' (l,u))) == [0..'rangeSize' (l,u)-1]@
---
--- * @'rangeSize' (l,u) == 'length' ('range' (l,u))@
---
--- Minimal complete instance: 'range', 'index' and 'inRange'.
---
-class (Ord a) => Ix a where
-    -- | The list of values in the subrange defined by a bounding pair.
-    range		:: (a,a) -> [a]
-    -- | The position of a subscript in the subrange.
-    index		:: (a,a) -> a -> Int
-    -- | Like 'index', but without checking that the value is in range.
-    unsafeIndex		:: (a,a) -> a -> Int
-    -- | Returns 'True' the given subscript lies in the range defined
-    -- the bounding pair.
-    inRange		:: (a,a) -> a -> Bool
-    -- | The size of the subrange defined by a bounding pair.
-    rangeSize		:: (a,a) -> Int
-    -- | like 'rangeSize', but without checking that the upper bound is
-    -- in range.
-    unsafeRangeSize     :: (a,a) -> Int
-
-	-- Must specify one of index, unsafeIndex
-    index b i | inRange b i = unsafeIndex b i	
-	      | otherwise   = error "Error in array index"
-    unsafeIndex b i = index b i
-
-    rangeSize b@(_l,h) | inRange b h = unsafeIndex b h + 1
-		       | otherwise   = 0	-- This case is only here to
-						-- check for an empty range
-	-- NB: replacing (inRange b h) by (l <= h) fails for
-	--     tuples.  E.g.  (1,2) <= (2,1) but the range is empty
-
-    unsafeRangeSize b@(_l,h) = unsafeIndex b h + 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
--- abstract these errors from the relevant index functions so that
--- the guts of the function will be small enough to inline.
-
-{-# NOINLINE indexError #-}
-indexError :: Show a => (a,a) -> a -> String -> b
-indexError rng i tp
-  = error (showString "Ix{" . showString tp . showString "}.index: Index " .
-           showParen True (showsPrec 0 i) .
-	   showString " out of range " $
-	   showParen True (showsPrec 0 rng) "")
-
-----------------------------------------------------------------------
-instance  Ix Char  where
-    {-# INLINE range #-}
-    range (m,n) = [m..n]
-
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex (m,_n) i = fromEnum i - fromEnum m
-
-    index b i | inRange b i =  unsafeIndex b i
-	      | otherwise   =  indexError b i "Char"
-
-    inRange (m,n) i	=  m <= i && i <= n
-
-----------------------------------------------------------------------
-instance  Ix Int  where
-    {-# INLINE range #-}
-	-- The INLINE stops the build in the RHS from getting inlined,
-	-- so that callers can fuse with the result of range
-    range (m,n) = [m..n]
-
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex (m,_n) i = i - m
-
-    index b i | inRange b i =  unsafeIndex b i
-	      | otherwise   =  indexError b i "Int"
-
-    {-# INLINE inRange #-}
-    inRange (I# m,I# n) (I# i) =  m <=# i && i <=# n
-
-----------------------------------------------------------------------
-instance  Ix Integer  where
-    {-# INLINE range #-}
-    range (m,n) = [m..n]
-
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex (m,_n) i   = fromInteger (i - m)
-
-    index b i | inRange b i =  unsafeIndex b i
-	      | otherwise   =  indexError b i "Integer"
-
-    inRange (m,n) i	=  m <= i && i <= n
-
-----------------------------------------------------------------------
-instance Ix Bool where -- as derived
-    {-# INLINE range #-}
-    range (m,n) = [m..n]
-
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex (l,_) i = fromEnum i - fromEnum l
-
-    index b i | inRange b i =  unsafeIndex b i
-	      | otherwise   =  indexError b i "Bool"
-
-    inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
-
-----------------------------------------------------------------------
-instance Ix Ordering where -- as derived
-    {-# INLINE range #-}
-    range (m,n) = [m..n]
-
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex (l,_) i = fromEnum i - fromEnum l
-
-    index b i | inRange b i =  unsafeIndex b i
-	      | otherwise   =  indexError b i "Ordering"
-
-    inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
-
-----------------------------------------------------------------------
-instance Ix () where
-    {-# INLINE range #-}
-    range   ((), ())    = [()]
-    {-# INLINE unsafeIndex #-}
-    unsafeIndex   ((), ()) () = 0
-    {-# INLINE inRange #-}
-    inRange ((), ()) () = True
-    {-# INLINE index #-}
-    index b i = unsafeIndex b i
-
-----------------------------------------------------------------------
-instance (Ix a, Ix b) => Ix (a, b) where -- as derived
-    {-# SPECIALISE instance Ix (Int,Int) #-}
-
-    {- INLINE range #-}
-    range ((l1,l2),(u1,u2)) =
-      [ (i1,i2) | i1 <- range (l1,u1), i2 <- range (l2,u2) ]
-
-    {- INLINE unsafeIndex #-}
-    unsafeIndex ((l1,l2),(u1,u2)) (i1,i2) =
-      unsafeIndex (l1,u1) i1 * unsafeRangeSize (l2,u2) + unsafeIndex (l2,u2) i2
-
-    {- INLINE inRange #-}
-    inRange ((l1,l2),(u1,u2)) (i1,i2) =
-      inRange (l1,u1) i1 && inRange (l2,u2) i2
-
-    -- Default method for index
-
-----------------------------------------------------------------------
-instance  (Ix a1, Ix a2, Ix a3) => Ix (a1,a2,a3)  where
-    {-# SPECIALISE instance Ix (Int,Int,Int) #-}
-
-    range ((l1,l2,l3),(u1,u2,u3)) =
-        [(i1,i2,i3) | i1 <- range (l1,u1),
-                      i2 <- range (l2,u2),
-                      i3 <- range (l3,u3)]
-
-    unsafeIndex ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
-      unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
-      unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
-      unsafeIndex (l1,u1) i1))
-
-    inRange ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
-      inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
-      inRange (l3,u3) i3
-
-    -- Default method for index
-
-----------------------------------------------------------------------
-instance  (Ix a1, Ix a2, Ix a3, Ix a4) => Ix (a1,a2,a3,a4)  where
-    range ((l1,l2,l3,l4),(u1,u2,u3,u4)) =
-      [(i1,i2,i3,i4) | i1 <- range (l1,u1),
-                       i2 <- range (l2,u2),
-                       i3 <- range (l3,u3),
-                       i4 <- range (l4,u4)]
-
-    unsafeIndex ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
-      unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
-      unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
-      unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
-      unsafeIndex (l1,u1) i1)))
-
-    inRange ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
-      inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
-      inRange (l3,u3) i3 && inRange (l4,u4) i4
-
-    -- Default method for index
-
-instance  (Ix a1, Ix a2, Ix a3, Ix a4, Ix a5) => Ix (a1,a2,a3,a4,a5)  where
-    range ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) =
-      [(i1,i2,i3,i4,i5) | i1 <- range (l1,u1),
-                          i2 <- range (l2,u2),
-                          i3 <- range (l3,u3),
-                          i4 <- range (l4,u4),
-                          i5 <- range (l5,u5)]
-
-    unsafeIndex ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
-      unsafeIndex (l5,u5) i5 + unsafeRangeSize (l5,u5) * (
-      unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
-      unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
-      unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
-      unsafeIndex (l1,u1) i1))))
-
-    inRange ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
-      inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
-      inRange (l3,u3) i3 && inRange (l4,u4) i4 && 
-      inRange (l5,u5) i5
-
-    -- Default method for index
-
-
-
-
-
-
-
-
-
-type IPr = (Int, Int)
-
--- | The type of immutable non-strict (boxed) arrays
--- with indices in @i@ and elements in @e@.
-data Ix i => Array     i e = Array   !i !i (Array# e)
-
--- | Mutable, boxed, non-strict arrays in the 'ST' monad.  The type
--- arguments are as follows:
---
---  * @s@: the state variable argument for the 'ST' type
---
---  * @i@: the index type of the array (should be an instance of 'Ix')
---
---  * @e@: the element type of the array.
---
-data         STArray s i e = STArray !i !i (MutableArray# s e)
-	-- No Ix context for STArray.  They are stupid,
-	-- and force an Ix context on the equality instance.
-
--- Just pointer equality on mutable arrays:
-instance Eq (STArray s i e) where
-    STArray _ _ arr1# == STArray _ _ arr2# =
-        sameMutableArray# arr1# arr2#
-
-
-
-
-
-
-
-
-
-
-{-# NOINLINE arrEleBottom #-}
-arrEleBottom :: a
-arrEleBottom = error "(Array.!): undefined array element"
-
--- | Construct an array with the specified bounds and containing values
--- for given indices within these bounds.
---
--- The array is undefined (i.e. bottom) if any index in the list is
--- out of bounds.  The Haskell 98 Report further specifies that if any
--- two associations in the list have the same index, the value at that
--- index is undefined (i.e. bottom).  However in GHC's implementation,
--- the value at such an index is the value part of the last association
--- with that index in the list.
---
--- Because the indices must be checked for these errors, 'array' is
--- strict in the bounds argument and in the indices of the association
--- list, but nonstrict in the values.  Thus, recurrences such as the
--- following are possible:
---
--- > a = array (1,100) ((1,1) : [(i, i * a!(i-1)) | i <- [2..100]])
---
--- Not every index within the bounds of the array need appear in the
--- association list, but the values associated with indices that do not
--- appear will be undefined (i.e. bottom).
---
--- If, in any dimension, the lower bound is greater than the upper bound,
--- then the array is legal, but empty.  Indexing an empty array always
--- gives an array-bounds error, but 'bounds' still yields the bounds
--- with which the array was constructed.
-{-# INLINE array #-}
-array :: Ix i
-	=> (i,i)	-- ^ a pair of /bounds/, each of the index type
-			-- of the array.  These bounds are the lowest and
-			-- highest indices in the array, in that order.
-			-- For example, a one-origin vector of length
-			-- '10' has bounds '(1,10)', and a one-origin '10'
-			-- by '10' matrix has bounds '((1,1),(10,10))'.
-	-> [(i, e)]	-- ^ a list of /associations/ of the form
-			-- (/index/, /value/).  Typically, this list will
-			-- be expressed as a comprehension.  An
-			-- association '(i, x)' defines the value of
-			-- the array at index 'i' to be 'x'.
-	-> Array i e
-array (l,u) ies = unsafeArray (l,u) [(index (l,u) i, e) | (i, e) <- ies]
-
-{-# INLINE unsafeArray #-}
-unsafeArray :: Ix i => (i,i) -> [(Int, e)] -> Array i e
-unsafeArray (l,u) ies = runST (ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# arrEleBottom s1#  of { (# s2#, marr# #) ->
-    foldr (fill marr#) (done l u marr#) ies s2# }})
-
-{-# INLINE fill #-}
-fill :: MutableArray# s e -> (Int, e) -> STRep s a -> STRep s a
-fill marr# (I# i#, e) next s1# =
-    case writeArray# marr# i# e s1#     of { s2# ->
-    next s2# }
-
-{-# INLINE done #-}
-done :: Ix i => i -> i -> MutableArray# s e -> STRep s (Array i e)
-done l u marr# s1# =
-    case unsafeFreezeArray# marr# s1#   of { (# s2#, arr# #) ->
-    (# s2#, Array l u arr# #) }
-
--- This is inefficient and I'm not sure why:
--- listArray (l,u) es = unsafeArray (l,u) (zip [0 .. rangeSize (l,u) - 1] es)
--- The code below is better. It still doesn't enable foldr/build
--- transformation on the list of elements; I guess it's impossible
--- using mechanisms currently available.
-
--- | Construct an array from a pair of bounds and a list of values in
--- index order.
-{-# INLINE listArray #-}
-listArray :: Ix i => (i,i) -> [e] -> Array i e
-listArray (l,u) es = runST (ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# arrEleBottom s1#  of { (# s2#, marr# #) ->
-    let fillFromList i# xs s3# | i# ==# n# = s3#
-                               | otherwise = case xs of
-            []   -> s3#
-            y:ys -> case writeArray# marr# i# y s3# of { s4# ->
-                    fillFromList (i# +# 1#) ys s4# } in
-    case fillFromList 0# es s2#         of { s3# ->
-    done l u marr# s3# }}})
-
--- | The value at the given index in an array.
-{-# INLINE (!) #-}
-(!) :: Ix i => Array i e -> i -> e
-arr@(Array l u _) ! i = unsafeAt arr (index (l,u) i)
-
-{-# INLINE unsafeAt #-}
-unsafeAt :: Ix i => Array i e -> Int -> e
-unsafeAt (Array _ _ arr#) (I# i#) =
-    case indexArray# arr# i# of (# e #) -> e
-
--- | The bounds with which an array was constructed.
-{-# INLINE bounds #-}
-bounds :: Ix i => Array i e -> (i,i)
-bounds (Array l u _) = (l,u)
-
--- | The list of indices of an array in ascending order.
-{-# INLINE indices #-}
-indices :: Ix i => Array i e -> [i]
-indices (Array l u _) = range (l,u)
-
--- | The list of elements of an array in index order.
-{-# INLINE elems #-}
-elems :: Ix i => Array i e -> [e]
-elems arr@(Array l u _) =
-    [unsafeAt arr i | i <- [0 .. rangeSize (l,u) - 1]]
-
--- | The list of associations of an array in index order.
-{-# INLINE assocs #-}
-assocs :: Ix i => Array i e -> [(i, e)]
-assocs arr@(Array l u _) =
-    [(i, unsafeAt arr (unsafeIndex (l,u) i)) | i <- range (l,u)]
-
--- | The 'accumArray' deals with repeated indices in the association
--- list using an /accumulating function/ which combines the values of
--- associations with the same index.
--- For example, given a list of values of some index type, @hist@
--- produces a histogram of the number of occurrences of each index within
--- a specified range:
---
--- > hist :: (Ix a, Num b) => (a,a) -> [a] -> Array a b
--- > hist bnds is = accumArray (+) 0 bnds [(i, 1) | i<-is, inRange bnds i]
---
--- If the accumulating function is strict, then 'accumArray' is strict in
--- the values, as well as the indices, in the association list.  Thus,
--- unlike ordinary arrays built with 'array', accumulated arrays should
--- not in general be recursive.
-{-# INLINE accumArray #-}
-accumArray :: Ix i
-	=> (e -> a -> e)	-- ^ accumulating function
-	-> e			-- ^ initial value
-	-> (i,i)		-- ^ bounds of the array
-	-> [(i, a)]		-- ^ association list
-	-> Array i e
-accumArray f init (l,u) ies =
-    unsafeAccumArray f init (l,u) [(index (l,u) i, e) | (i, e) <- ies]
-
-{-# INLINE unsafeAccumArray #-}
-unsafeAccumArray :: Ix i => (e -> a -> e) -> e -> (i,i) -> [(Int, a)] -> Array i e
-unsafeAccumArray f init (l,u) ies = runST (ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# init s1#          of { (# s2#, marr# #) ->
-    foldr (adjust f marr#) (done l u marr#) ies s2# }})
-
-{-# INLINE adjust #-}
-adjust :: (e -> a -> e) -> MutableArray# s e -> (Int, a) -> STRep s b -> STRep s b
-adjust f marr# (I# i#, new) next s1# =
-    case readArray# marr# i# s1#        of { (# s2#, old #) ->
-    case writeArray# marr# i# (f old new) s2# of { s3# ->
-    next s3# }}
-
--- | Constructs an array identical to the first argument except that it has
--- been updated by the associations in the right argument.
--- For example, if @m@ is a 1-origin, @n@ by @n@ matrix, then
---
--- > m//[((i,i), 0) | i <- [1..n]]
---
--- is the same matrix, except with the diagonal zeroed.
---
--- Repeated indices in the association list are handled as for 'array':
--- Haskell 98 specifies that the resulting array is undefined (i.e. bottom),
--- but GHC's implementation uses the last association for each index.
-{-# INLINE (//) #-}
-(//) :: Ix i => Array i e -> [(i, e)] -> Array i e
-arr@(Array l u _) // ies =
-    unsafeReplace arr [(index (l,u) i, e) | (i, e) <- ies]
-
-{-# INLINE unsafeReplace #-}
-unsafeReplace :: Ix i => Array i e -> [(Int, e)] -> Array i e
-unsafeReplace arr@(Array l u _) ies = runST (do
-    STArray _ _ marr# <- thawSTArray arr
-    ST (foldr (fill marr#) (done l u marr#) ies))
-
--- | @'accum' f@ takes an array and an association list and accumulates
--- pairs from the list into the array with the accumulating function @f@.
--- Thus 'accumArray' can be defined using 'accum':
---
--- > accumArray f z b = accum f (array b [(i, z) | i <- range b])
---
-{-# INLINE accum #-}
-accum :: Ix i => (e -> a -> e) -> Array i e -> [(i, a)] -> Array i e
-accum f arr@(Array l u _) ies =
-    unsafeAccum f arr [(index (l,u) i, e) | (i, e) <- ies]
-
-{-# INLINE unsafeAccum #-}
-unsafeAccum :: Ix i => (e -> a -> e) -> Array i e -> [(Int, a)] -> Array i e
-unsafeAccum f arr@(Array l u _) ies = runST (do
-    STArray _ _ marr# <- thawSTArray arr
-    ST (foldr (adjust f marr#) (done l u marr#) ies))
-
-{-# INLINE amap #-}
-amap :: Ix i => (a -> b) -> Array i a -> Array i b
-amap f arr@(Array l u _) =
-    unsafeArray (l,u) [(i, f (unsafeAt arr i)) | i <- [0 .. rangeSize (l,u) - 1]]
-
--- | 'ixmap' allows for transformations on array indices.
--- It may be thought of as providing function composition on the right
--- with the mapping that the original array embodies.
---
--- A similar transformation of array values may be achieved using 'fmap'
--- from the 'Array' instance of the 'Functor' class.
-{-# INLINE ixmap #-}
-ixmap :: (Ix i, Ix j) => (i,i) -> (i -> j) -> Array j e -> Array i e
-ixmap (l,u) f arr =
-    unsafeArray (l,u) [(unsafeIndex (l,u) i, arr ! f i) | i <- range (l,u)]
-
-{-# INLINE eqArray #-}
-eqArray :: (Ix i, Eq e) => Array i e -> Array i e -> Bool
-eqArray arr1@(Array l1 u1 _) arr2@(Array l2 u2 _) =
-    if rangeSize (l1,u1) == 0 then rangeSize (l2,u2) == 0 else
-    l1 == l2 && u1 == u2 &&
-    and [unsafeAt arr1 i == unsafeAt arr2 i | i <- [0 .. rangeSize (l1,u1) - 1]]
-
-{-# INLINE cmpArray #-}
-cmpArray :: (Ix i, Ord e) => Array i e -> Array i e -> Ordering
-cmpArray arr1 arr2 = compare (assocs arr1) (assocs arr2)
-
-{-# INLINE cmpIntArray #-}
-cmpIntArray :: Ord e => Array Int e -> Array Int e -> Ordering
-cmpIntArray arr1@(Array l1 u1 _) arr2@(Array l2 u2 _) =
-    if rangeSize (l1,u1) == 0 then if rangeSize (l2,u2) == 0 then EQ else LT else
-    if rangeSize (l2,u2) == 0 then GT else
-    case compare l1 l2 of
-        EQ    -> foldr cmp (compare u1 u2) [0 .. rangeSize (l1, min u1 u2) - 1]
-        other -> other
-    where
-    cmp i rest = case compare (unsafeAt arr1 i) (unsafeAt arr2 i) of
-        EQ    -> rest
-        other -> other
-
-{-# RULES "cmpArray/Int" cmpArray = cmpIntArray #-}
-
-
-
-
-
-
-
-
-
-
-instance Ix i => Functor (Array i) where
-    fmap = amap
-
-instance (Ix i, Eq e) => Eq (Array i e) where
-    (==) = eqArray
-
-instance (Ix i, Ord e) => Ord (Array i e) where
-    compare = cmpArray
-
-instance (Ix a, Show a, Show b) => Show (Array a b) where
-    showsPrec p a =
-        showParen (p > appPrec) $
-        showString "array " .
-        showsPrec appPrec1 (bounds a) .
-        showChar ' ' .
-        showsPrec appPrec1 (assocs a)
-	-- Precedence of 'array' is the precedence of application
-
--- The Read instance is in GHC.Read
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{-# INLINE newSTArray #-}
-newSTArray :: Ix i => (i,i) -> e -> ST s (STArray s i e)
-newSTArray (l,u) init = ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# init s1#          of { (# s2#, marr# #) ->
-    (# s2#, STArray l u marr# #) }}
-
-{-# INLINE boundsSTArray #-}
-boundsSTArray :: STArray s i e -> (i,i)  
-boundsSTArray (STArray l u _) = (l,u)
-
-{-# INLINE readSTArray #-}
-readSTArray :: Ix i => STArray s i e -> i -> ST s e
-readSTArray marr@(STArray l u _) i =
-    unsafeReadSTArray marr (index (l,u) i)
-
-{-# INLINE unsafeReadSTArray #-}
-unsafeReadSTArray :: Ix i => STArray s i e -> Int -> ST s e
-unsafeReadSTArray (STArray _ _ marr#) (I# i#) = ST $ \s1# ->
-    readArray# marr# i# s1#
-
-{-# INLINE writeSTArray #-}
-writeSTArray :: Ix i => STArray s i e -> i -> e -> ST s () 
-writeSTArray marr@(STArray l u _) i e =
-    unsafeWriteSTArray marr (index (l,u) i) e
-
-{-# INLINE unsafeWriteSTArray #-}
-unsafeWriteSTArray :: Ix i => STArray s i e -> Int -> e -> ST s () 
-unsafeWriteSTArray (STArray _ _ marr#) (I# i#) e = ST $ \s1# ->
-    case writeArray# marr# i# e s1#     of { s2# ->
-    (# s2#, () #) }
-
-
-
-
-
-
-
-
-
-
-freezeSTArray :: Ix i => STArray s i e -> ST s (Array i e)
-freezeSTArray (STArray l u marr#) = ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# arrEleBottom s1#  of { (# s2#, marr'# #) ->
-    let copy i# s3# | i# ==# n# = s3#
-                    | otherwise =
-            case readArray# marr# i# s3# of { (# s4#, e #) ->
-            case writeArray# marr'# i# e s4# of { s5# ->
-            copy (i# +# 1#) s5# }} in
-    case copy 0# s2#                    of { s3# ->
-    case unsafeFreezeArray# marr'# s3#  of { (# s4#, arr# #) ->
-    (# s4#, Array l u arr# #) }}}}
-
-{-# INLINE unsafeFreezeSTArray #-}
-unsafeFreezeSTArray :: Ix i => STArray s i e -> ST s (Array i e)
-unsafeFreezeSTArray (STArray l u marr#) = ST $ \s1# ->
-    case unsafeFreezeArray# marr# s1#   of { (# s2#, arr# #) ->
-    (# s2#, Array l u arr# #) }
-
-thawSTArray :: Ix i => Array i e -> ST s (STArray s i e)
-thawSTArray (Array l u arr#) = ST $ \s1# ->
-    case rangeSize (l,u)                of { I# n# ->
-    case newArray# n# arrEleBottom s1#  of { (# s2#, marr# #) ->
-    let copy i# s3# | i# ==# n# = s3#
-                    | otherwise =
-            case indexArray# arr# i#    of { (# e #) ->
-            case writeArray# marr# i# e s3# of { s4# ->
-            copy (i# +# 1#) s4# }} in
-    case copy 0# s2#                    of { s3# ->
-    (# s3#, STArray l u marr# #) }}}
-
-{-# INLINE unsafeThawSTArray #-}
-unsafeThawSTArray :: Ix i => Array i e -> ST s (STArray s i e)
-unsafeThawSTArray (Array l u arr#) = ST $ \s1# ->
-    case unsafeThawArray# arr# s1#      of { (# s2#, marr# #) ->
-    (# s2#, STArray l u marr# #) }
-
-
diff --git a/tests/expect31 b/tests/expect31
deleted file mode 100644
--- a/tests/expect31
+++ /dev/null
@@ -1,11 +0,0 @@
-#line 1 "elif"
-
-
-import System.IO.Unsafe (unsafePerformIO)
-
-
-
-
-
-
-
diff --git a/tests/expect32 b/tests/expect32
deleted file mode 100644
--- a/tests/expect32
+++ /dev/null
@@ -1,2 +0,0 @@
-#line 1 "pragma"
-#pragma  ident   "@(#)time.h     1.39    99/08/10 SMI"                
diff --git a/tests/expect33 b/tests/expect33
deleted file mode 100644
--- a/tests/expect33
+++ /dev/null
@@ -1,1 +0,0 @@
-#pragma  ident   "@(#)time.h     1.39    99/08/10 SMI"                
diff --git a/tests/expect34 b/tests/expect34
deleted file mode 100644
--- a/tests/expect34
+++ /dev/null
@@ -1,11 +0,0 @@
-#line 1 "igloo"
-
-
-
-1
-
-
-foo
-
-
-
diff --git a/tests/expect35 b/tests/expect35
deleted file mode 100644
--- a/tests/expect35
+++ /dev/null
@@ -1,12 +0,0 @@
-#line 1 "igloo2"
-
-
-
-baz
-1
-
-
-foo
-
-
-
diff --git a/tests/expect36 b/tests/expect36
deleted file mode 100644
--- a/tests/expect36
+++ /dev/null
@@ -1,12 +0,0 @@
-#line 1 "igloo3"
-
-
-
-quux
-FOOFOO
-
-
-
-
-bar
-
diff --git a/tests/expect36a b/tests/expect36a
deleted file mode 100644
--- a/tests/expect36a
+++ /dev/null
@@ -1,12 +0,0 @@
-#line 1 "igloo3a"
-
-
-
-quux
-FOOFOO
-
-
-
-
-bar
-
diff --git a/tests/expect36b b/tests/expect36b
deleted file mode 100644
--- a/tests/expect36b
+++ /dev/null
@@ -1,13 +0,0 @@
-#line 1 "igloo3b"
-
-
-
-
-quux
-11
-
-
-foo
-
-
-
diff --git a/tests/expect37 b/tests/expect37
deleted file mode 100644
--- a/tests/expect37
+++ /dev/null
@@ -1,11 +0,0 @@
-#line 1 "igloo4"
-
-
-wibble
-11
-
-
-foo
-
-
-
diff --git a/tests/expect37a b/tests/expect37a
deleted file mode 100644
--- a/tests/expect37a
+++ /dev/null
@@ -1,11 +0,0 @@
-#line 1 "igloo4a"
-
-
-wibble
-11
-
-
-foo
-
-
-
diff --git a/tests/expect38 b/tests/expect38
deleted file mode 100644
--- a/tests/expect38
+++ /dev/null
@@ -1,8 +0,0 @@
-#line 1 "mauke"
-
-
-
-
-
-
-main = print 7 -- should print 7
diff --git a/tests/expect39 b/tests/expect39
deleted file mode 100644
--- a/tests/expect39
+++ /dev/null
@@ -1,5 +0,0 @@
-#line 1 "mauke2"
-
-
-
-4
diff --git a/tests/expect4 b/tests/expect4
deleted file mode 100644
--- a/tests/expect4
+++ /dev/null
@@ -1,39 +0,0 @@
-#line 1 "testfile"
-1 top of file
-
-3
-
-5 X is defined
-
-7
-
-
-
-11
-
-
-
-15
-
-
-
-19
-
-#line 1 "./inclusion"
-hello world, this is an inclusion
-
-#line 22 "testfile"
-
-
-
-25
-
-
-
-
-
-31 third branch of elif
-
-33
-34 end of file
-
diff --git a/tests/expect40 b/tests/expect40
deleted file mode 100644
--- a/tests/expect40
+++ /dev/null
@@ -1,8 +0,0 @@
-#line 1 "fasta"
-
-
-
-
-
-
-b7 = unsafeVisualize(foo)
diff --git a/tests/expect40a b/tests/expect40a
deleted file mode 100644
--- a/tests/expect40a
+++ /dev/null
@@ -1,7 +0,0 @@
-#line 1 "fasta2"
-
-
-
-
-
-b6 = unsafeVisualize(foo)
diff --git a/tests/expect41 b/tests/expect41
deleted file mode 100644
--- a/tests/expect41
+++ /dev/null
@@ -1,6 +0,0 @@
-#line 1 "hashjoin"
-
-
-
-
-2
diff --git a/tests/expect42 b/tests/expect42
deleted file mode 100644
--- a/tests/expect42
+++ /dev/null
@@ -1,5 +0,0 @@
-#line 1 "wrongline"
-
-2
-#line 20 "foo"
-20
diff --git a/tests/expect43 b/tests/expect43
deleted file mode 100644
--- a/tests/expect43
+++ /dev/null
@@ -1,6 +0,0 @@
-#line 1 "param"
-
-
-
-
-11	-- gcc gives BARBAR, cpphs gives 11
diff --git a/tests/expect44 b/tests/expect44
deleted file mode 100644
--- a/tests/expect44
+++ /dev/null
@@ -1,4 +0,0 @@
-#line 1 "comments"
-here is an ordinary C comment:			                  
-and here is a C++-style end-of-line comment:	// comment here
-this line has no comments
diff --git a/tests/expect44a b/tests/expect44a
deleted file mode 100644
--- a/tests/expect44a
+++ /dev/null
@@ -1,4 +0,0 @@
-#line 1 "comments"
-here is an ordinary C comment:			                  
-and here is a C++-style end-of-line comment:	               
-this line has no comments
diff --git a/tests/expect45 b/tests/expect45
deleted file mode 100644
--- a/tests/expect45
+++ /dev/null
@@ -1,8 +0,0 @@
-#line 1 "nestcomment"
-{-
-
-foo
-
-
-
--}
diff --git a/tests/expect46 b/tests/expect46
deleted file mode 100644
--- a/tests/expect46
+++ /dev/null
@@ -1,7 +0,0 @@
-#line 1 "preinclude"
-#line 1 "./inclusion"
-hello world, this is an inclusion
-
-#line 2 "preinclude"
-#line 1 "preinclude"
-something arbitrary
diff --git a/tests/expect47 b/tests/expect47
deleted file mode 100644
--- a/tests/expect47
+++ /dev/null
@@ -1,5 +0,0 @@
-#line 1 "endcode-a"
-
-
-
-
diff --git a/tests/expect48 b/tests/expect48
deleted file mode 100644
--- a/tests/expect48
+++ /dev/null
@@ -1,6 +0,0 @@
-#line 1 "endcode-b"
-
-
-
-
-
diff --git a/tests/expect49 b/tests/expect49
deleted file mode 100644
--- a/tests/expect49
+++ /dev/null
@@ -1,5 +0,0 @@
-#line 1 "undef.hs"
-
-wibble 3
-
-this is FOO
diff --git a/tests/expect5 b/tests/expect5
deleted file mode 100644
--- a/tests/expect5
+++ /dev/null
@@ -1,35 +0,0 @@
-1 top of file
-
-3
-
-5 0 is defined
-
-7
-
-
-
-11
-
-
-
-15
-
-
-
-19
-
-hello world, this is an inclusion
-
-
-
-
-25
-
-
-
-
-
-31 third branch of elif
-
-33
-34 end of file
diff --git a/tests/expect50 b/tests/expect50
deleted file mode 100644
--- a/tests/expect50
+++ /dev/null
@@ -1,9 +0,0 @@
-{-# LINE 1 "linepragma" #-}
-{-# LINE 1 "./inclusion" #-}
-hello world, this is an inclusion
-
-{-# LINE 2 "linepragma" #-}
-{-# LINE 2 "linepragma" #-}
-
-{-# LINE 3 "linepragma" #-}
-
diff --git a/tests/expect6 b/tests/expect6
deleted file mode 100644
--- a/tests/expect6
+++ /dev/null
@@ -1,10 +0,0 @@
-#line 1 "cpp"
-
-
-
-
-
-
-x ++ y = X' * 0 * y .(foo), Xprime 
-
-//  /*
diff --git a/tests/expect7 b/tests/expect7
deleted file mode 100644
--- a/tests/expect7
+++ /dev/null
@@ -1,297 +0,0 @@
-#line 1 "Storable.hs"
-{-# OPTIONS -fno-implicit-prelude #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Foreign.Storable
--- Copyright   :  (c) The FFI task force 2001
--- License     :  see libraries/base/LICENSE
--- 
--- Maintainer  :  ffi@haskell.org
--- Stability   :  provisional
--- Portability :  portable
---
--- The module "Foreign.Storable" provides most elementary support for
--- marshalling and is part of the language-independent portion of the
--- Foreign Function Interface (FFI), and will normally be imported via
--- the "Foreign" module.
---
------------------------------------------------------------------------------
-
-module Foreign.Storable
-	( Storable(
-	     sizeOf,         -- :: a -> Int
-	     alignment,      -- :: a -> Int
-	     peekElemOff,    -- :: Ptr a -> Int      -> IO a
-	     pokeElemOff,    -- :: Ptr a -> Int -> a -> IO ()
-	     peekByteOff,    -- :: Ptr b -> Int      -> IO a
-	     pokeByteOff,    -- :: Ptr b -> Int -> a -> IO ()
-	     peek,           -- :: Ptr a             -> IO a
-	     poke)           -- :: Ptr a        -> a -> IO ()
-        ) where
-
-
-
-
-
-
-
-import Control.Monad		( liftM )
-
-#line 1 "./MachDeps.h"
-#line 40 "Storable.hs"
-#line 1 "./config.h"
-#line 41 "Storable.hs"
-
-
-import GHC.Storable
-import GHC.Stable	( StablePtr )
-import GHC.Num
-import GHC.Int
-import GHC.Word
-import GHC.Stable
-import GHC.Ptr
-import GHC.Float
-import GHC.Err
-import GHC.IOBase
-import GHC.Base
-
-
-
-
-
-
-
-
-
-
-
-
-{- |
-The member functions of this class facilitate writing values of
-primitive types to raw memory (which may have been allocated with the
-above mentioned routines) and reading values from blocks of raw
-memory.  The class, furthermore, includes support for computing the
-storage requirements and alignment restrictions of storable types.
-
-Memory addresses are represented as values of type @'Ptr' a@, for some
-@a@ which is an instance of class 'Storable'.  The type argument to
-'Ptr' helps provide some valuable type safety in FFI code (you can\'t
-mix pointers of different types without an explicit cast), while
-helping the Haskell type system figure out which marshalling method is
-needed for a given pointer.
-
-All marshalling between Haskell and a foreign language ultimately
-boils down to translating Haskell data structures into the binary
-representation of a corresponding data structure of the foreign
-language and vice versa.  To code this marshalling in Haskell, it is
-necessary to manipulate primtive data types stored in unstructured
-memory blocks.  The class 'Storable' facilitates this manipulation on
-all types for which it is instantiated, which are the standard basic
-types of Haskell, the fixed size @Int@ types ('Int8', 'Int16',
-'Int32', 'Int64'), the fixed size @Word@ types ('Word8', 'Word16',
-'Word32', 'Word64'), 'StablePtr', all types from "Foreign.C.Types",
-as well as 'Ptr'.
-
-Minimal complete definition: 'sizeOf', 'alignment', one of 'peek',
-'peekElemOff' and 'peekByteOff', and one of 'poke', 'pokeElemOff' and
-'pokeByteOff'.
--}
-
-class Storable a where
-
-   sizeOf      :: a -> Int
-   -- ^ Computes the storage requirements (in bytes) of the argument.
-   -- The value of the argument is not used.
-
-   alignment   :: a -> Int
-   -- ^ Computes the alignment constraint of the argument.  An
-   -- alignment constraint @x@ is fulfilled by any address divisible
-   -- by @x@.  The value of the argument is not used.
-
-   peekElemOff :: Ptr a -> Int      -> IO a
-   -- ^       Read a value from a memory area regarded as an array
-   --         of values of the same kind.  The first argument specifies
-   --         the start address of the array and the second the index into
-   --         the array (the first element of the array has index
-   --         @0@).  The following equality holds,
-   -- 
-   -- > peekElemOff addr idx = IOExts.fixIO $ \result ->
-   -- >   peek (addr `plusPtr` (idx * sizeOf result))
-   --
-   --         Note that this is only a specification, not
-   --         necessarily the concrete implementation of the
-   --         function.
-
-   pokeElemOff :: Ptr a -> Int -> a -> IO ()
-   -- ^       Write a value to a memory area regarded as an array of
-   --         values of the same kind.  The following equality holds:
-   -- 
-   -- > pokeElemOff addr idx x = 
-   -- >   poke (addr `plusPtr` (idx * sizeOf x)) x
-
-   peekByteOff :: Ptr b -> Int      -> IO a
-   -- ^       Read a value from a memory location given by a base
-   --         address and offset.  The following equality holds:
-   --
-   -- > peekByteOff addr off = peek (addr `plusPtr` off)
-
-   pokeByteOff :: Ptr b -> Int -> a -> IO ()
-   -- ^       Write a value to a memory location given by a base
-   --         address and offset.  The following equality holds:
-   --
-   -- > pokeByteOff addr off x = poke (addr `plusPtr` off) x
-  
-   peek        :: Ptr a      -> IO a
-   -- ^ Read a value from the given memory location.
-   --
-   --  Note that the peek and poke functions might require properly
-   --  aligned addresses to function correctly.  This is architecture
-   --  dependent; thus, portable code should ensure that when peeking or
-   --  poking values of some type @a@, the alignment
-   --  constraint for @a@, as given by the function
-   --  'alignment' is fulfilled.
-
-   poke        :: Ptr a -> a -> IO ()
-   -- ^ Write the given value to the given memory location.  Alignment
-   -- restrictions might apply; see 'peek'.
- 
-   -- circular default instances
-
-   peekElemOff = peekElemOff_ undefined
-      where peekElemOff_ :: a -> Ptr a -> Int -> IO a
-            peekElemOff_ undef ptr off = peekByteOff ptr (off * sizeOf undef)
-
-
-
-   pokeElemOff ptr off val = pokeByteOff ptr (off * sizeOf val) val
-
-   peekByteOff ptr off = peek (ptr `plusPtr` off)
-   pokeByteOff ptr off = poke (ptr `plusPtr` off)
-
-   peek ptr = peekElemOff ptr 0
-   poke ptr = pokeElemOff ptr 0
-
-
-
-
-
-
--- System-dependent, but rather obvious instances
-
-instance Storable Bool where
-   sizeOf _          = sizeOf (undefined::HTYPE_INT)
-   alignment _       = alignment (undefined::HTYPE_INT)
-   peekElemOff p i   = liftM (/= (0::HTYPE_INT)) $ peekElemOff (castPtr p) i
-   pokeElemOff p i x = pokeElemOff (castPtr p) i (if x then 1 else 0::HTYPE_INT)
-
-
-
-
-
-
-
-
-
-instance Storable (Char) where {			
-    sizeOf    _ = SIZEOF_INT32;				
-    alignment _ = ALIGNMENT_INT32;			
-    peekElemOff = readWideCharOffPtr;				
-    pokeElemOff = writeWideCharOffPtr }
-
-
-
-
-
-instance Storable (Int) where {			
-    sizeOf    _ = SIZEOF_HSINT;				
-    alignment _ = ALIGNMENT_HSINT;			
-    peekElemOff = readIntOffPtr;				
-    pokeElemOff = writeIntOffPtr }
-
-
-instance Storable (Word) where {			
-    sizeOf    _ = SIZEOF_HSWORD;				
-    alignment _ = ALIGNMENT_HSWORD;			
-    peekElemOff = readWordOffPtr;				
-    pokeElemOff = writeWordOffPtr }
-
-
-instance Storable ((Ptr a)) where {			
-    sizeOf    _ = SIZEOF_HSPTR;				
-    alignment _ = ALIGNMENT_HSPTR;			
-    peekElemOff = readPtrOffPtr;				
-    pokeElemOff = writePtrOffPtr }
-
-instance Storable ((FunPtr a)) where {			
-    sizeOf    _ = SIZEOF_HSFUNPTR;				
-    alignment _ = ALIGNMENT_HSFUNPTR;			
-    peekElemOff = readFunPtrOffPtr;				
-    pokeElemOff = writeFunPtrOffPtr }
-
-instance Storable ((StablePtr a)) where {			
-    sizeOf    _ = SIZEOF_HSSTABLEPTR;				
-    alignment _ = ALIGNMENT_HSSTABLEPTR;			
-    peekElemOff = readStablePtrOffPtr;				
-    pokeElemOff = writeStablePtrOffPtr }
-
-instance Storable (Float) where {			
-    sizeOf    _ = SIZEOF_HSFLOAT;				
-    alignment _ = ALIGNMENT_HSFLOAT;			
-    peekElemOff = readFloatOffPtr;				
-    pokeElemOff = writeFloatOffPtr }
-
-instance Storable (Double) where {			
-    sizeOf    _ = SIZEOF_HSDOUBLE;				
-    alignment _ = ALIGNMENT_HSDOUBLE;			
-    peekElemOff = readDoubleOffPtr;				
-    pokeElemOff = writeDoubleOffPtr }
-
-instance Storable (Word8) where {			
-    sizeOf    _ = SIZEOF_WORD8;				
-    alignment _ = ALIGNMENT_WORD8;			
-    peekElemOff = readWord8OffPtr;				
-    pokeElemOff = writeWord8OffPtr }
-
-instance Storable (Word16) where {			
-    sizeOf    _ = SIZEOF_WORD16;				
-    alignment _ = ALIGNMENT_WORD16;			
-    peekElemOff = readWord16OffPtr;				
-    pokeElemOff = writeWord16OffPtr }
-
-instance Storable (Word32) where {			
-    sizeOf    _ = SIZEOF_WORD32;				
-    alignment _ = ALIGNMENT_WORD32;			
-    peekElemOff = readWord32OffPtr;				
-    pokeElemOff = writeWord32OffPtr }
-
-instance Storable (Word64) where {			
-    sizeOf    _ = SIZEOF_WORD64;				
-    alignment _ = ALIGNMENT_WORD64;			
-    peekElemOff = readWord64OffPtr;				
-    pokeElemOff = writeWord64OffPtr }
-
-instance Storable (Int8) where {			
-    sizeOf    _ = SIZEOF_INT8;				
-    alignment _ = ALIGNMENT_INT8;			
-    peekElemOff = readInt8OffPtr;				
-    pokeElemOff = writeInt8OffPtr }
-
-instance Storable (Int16) where {			
-    sizeOf    _ = SIZEOF_INT16;				
-    alignment _ = ALIGNMENT_INT16;			
-    peekElemOff = readInt16OffPtr;				
-    pokeElemOff = writeInt16OffPtr }
-
-instance Storable (Int32) where {			
-    sizeOf    _ = SIZEOF_INT32;				
-    alignment _ = ALIGNMENT_INT32;			
-    peekElemOff = readInt32OffPtr;				
-    pokeElemOff = writeInt32OffPtr }
-
-instance Storable (Int64) where {			
-    sizeOf    _ = SIZEOF_INT64;				
-    alignment _ = ALIGNMENT_INT64;			
-    peekElemOff = readInt64OffPtr;				
-    pokeElemOff = writeInt64OffPtr }
-
-
diff --git a/tests/expect8 b/tests/expect8
deleted file mode 100644
--- a/tests/expect8
+++ /dev/null
@@ -1,37 +0,0 @@
-#line 1 "HsOpenGLExt.h"
-/* -----------------------------------------------------------------------------
- *
- * Module      :  GL extension support for Graphics.Rendering.OpenGL
- * Copyright   :  (c) Sven Panne 2002-2004
- * License     :  BSD-style (see the file libraries/OpenGL/LICENSE)
- * 
- * Maintainer  :  sven.panne@aedion.de
- * Stability   :  provisional
- * Portability :  portable
- *
- * This header should only define preprocessor macros!
- *
- * -------------------------------------------------------------------------- */
-
-
-
-
-/* NOTE: The macro must immediately start with the foreign declaration,
-   otherwise the magic mangler (hack_foreign) in the Hugs build system
-   doesn't recognize it. */
-
-
-
-
-
-
-
-
-
-
-foreign import ccall unsafe "dynamic" dyn_glFogCoorddEXT :: Graphics.Rendering.OpenGL.GL.Extensions.Invoker (GLdouble -> IO ()) ; 
-glFogCoorddEXT :: (GLdouble -> IO ()) ; 
-glFogCoorddEXT = dyn_glFogCoorddEXT ptr_glFogCoorddEXT ; 
-ptr_glFogCoorddEXT :: FunPtr a ; 
-ptr_glFogCoorddEXT = unsafePerformIO (Graphics.Rendering.OpenGL.GL.Extensions.getProcAddress ("GL_EXT_fog_coord or OpenGL 1.4") ("glFogCoorddEXT")) ; 
-{-# NOINLINE ptr_glFogCoorddEXT #-}
diff --git a/tests/expect9 b/tests/expect9
deleted file mode 100644
--- a/tests/expect9
+++ /dev/null
@@ -1,16 +0,0 @@
-#line 1 "multiline"
-
-
-
-
-5 back to ordinary text.
-#line 1 "./inclusion"
-hello world, this is an inclusion
-
-#line 7 "multiline"
-7 hello again
-8 some more
-9 some line here;	
-	and some more;	
-	finish now
-10 end
diff --git a/tests/fasta b/tests/fasta
deleted file mode 100644
--- a/tests/fasta
+++ /dev/null
@@ -1,7 +0,0 @@
-#define XCONCAT(a, b) a##b
-#define CONCAT(a, b) XCONCAT(a, b)
-#define PS(val) () <- trace (val) (return ())
-#define VIS(ioaction) let CONCAT(b, __LINE__) = unsafeVisualize(ioaction)
-#define V(ioaction) CONCAT(b, __LINE__) = unsafeVisualize(ioaction)
-
-V(foo)
diff --git a/tests/fasta2 b/tests/fasta2
deleted file mode 100644
--- a/tests/fasta2
+++ /dev/null
@@ -1,6 +0,0 @@
-#define XCONCAT(a, b) a##b
-#define CONCAT(a, b) XCONCAT(a, b)
-#define PS(val) () <- trace (val) (return ())
-#define VIS(ioaction) let CONCAT(b, __LINE__) = unsafeVisualize(ioaction)
-#define V(ioaction) CONCAT(b, __LINE__) = unsafeVisualize(ioaction)
-V(foo)
diff --git a/tests/hashjoin b/tests/hashjoin
deleted file mode 100644
--- a/tests/hashjoin
+++ /dev/null
@@ -1,5 +0,0 @@
-#define FOO 1
-#define BAR FOO##FOO
-#define FOOFOO 2
-
-BAR
diff --git a/tests/igloo b/tests/igloo
deleted file mode 100644
--- a/tests/igloo
+++ /dev/null
@@ -1,10 +0,0 @@
-#define FOO 1
-#define BAR FOO
-
-BAR
-
-#if BAR == 1
-foo
-#else
-bar
-#endif
diff --git a/tests/igloo2 b/tests/igloo2
deleted file mode 100644
--- a/tests/igloo2
+++ /dev/null
@@ -1,11 +0,0 @@
-#define FOO 1
-#define BAZ(x) x
-
-baz
-BAZ(1)
-
-#if BAZ(1) == 1
-foo
-#else
-bar
-#endif
diff --git a/tests/igloo3 b/tests/igloo3
deleted file mode 100644
--- a/tests/igloo3
+++ /dev/null
@@ -1,11 +0,0 @@
-#define FOO 1
-#define QUUX FOO ## FOO
-
-quux
-QUUX
-
-#if QUUX == 11
-foo
-#else
-bar
-#endif
diff --git a/tests/igloo3a b/tests/igloo3a
deleted file mode 100644
--- a/tests/igloo3a
+++ /dev/null
@@ -1,11 +0,0 @@
-#define FOO 1
-#define QUUX FOO##FOO
-
-quux
-QUUX
-
-#if QUUX == 11
-foo
-#else
-bar
-#endif
diff --git a/tests/igloo3b b/tests/igloo3b
deleted file mode 100644
--- a/tests/igloo3b
+++ /dev/null
@@ -1,12 +0,0 @@
-#define FOO 1
-#define QUUX(a) a ## a
-#define WIBBLE QUUX(FOO)
-
-quux
-WIBBLE
-
-#if WIBBLE == 11
-foo
-#else
-bar
-#endif
diff --git a/tests/igloo4 b/tests/igloo4
deleted file mode 100644
--- a/tests/igloo4
+++ /dev/null
@@ -1,10 +0,0 @@
-#define WIBBLE 1 ## 1
-
-wibble
-WIBBLE
-
-#if WIBBLE == 11
-foo
-#else
-bar
-#endif
diff --git a/tests/igloo4a b/tests/igloo4a
deleted file mode 100644
--- a/tests/igloo4a
+++ /dev/null
@@ -1,10 +0,0 @@
-#define WIBBLE 1##1
-
-wibble
-WIBBLE
-
-#if WIBBLE == 11
-foo
-#else
-bar
-#endif
diff --git a/tests/inclusion b/tests/inclusion
deleted file mode 100644
--- a/tests/inclusion
+++ /dev/null
@@ -1,1 +0,0 @@
-hello world, this is an inclusion
diff --git a/tests/incomplete b/tests/incomplete
deleted file mode 100644
--- a/tests/incomplete
+++ /dev/null
@@ -1,1 +0,0 @@
-incomplete
diff --git a/tests/indirect b/tests/indirect
deleted file mode 100644
--- a/tests/indirect
+++ /dev/null
@@ -1,2 +0,0 @@
-#define F "inclusion"
-#include F
diff --git a/tests/indirect-a b/tests/indirect-a
deleted file mode 100644
--- a/tests/indirect-a
+++ /dev/null
@@ -1,2 +0,0 @@
-#define F(f) in##f
-#include F(clusion)
diff --git a/tests/linepragma b/tests/linepragma
deleted file mode 100644
--- a/tests/linepragma
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "inclusion"
-#line 2 "linepragma"
-
-#line 3 "linepragma"
-
diff --git a/tests/mauke b/tests/mauke
deleted file mode 100644
--- a/tests/mauke
+++ /dev/null
@@ -1,7 +0,0 @@
-#define X /\
-* comment */ main
-
-#define Y _\
-_LINE__
-
-X = print Y -- should print 7
diff --git a/tests/mauke2 b/tests/mauke2
deleted file mode 100644
--- a/tests/mauke2
+++ /dev/null
@@ -1,4 +0,0 @@
-#define foo _\
-_LINE__
-
-foo
diff --git a/tests/multiline b/tests/multiline
deleted file mode 100644
--- a/tests/multiline
+++ /dev/null
@@ -1,10 +0,0 @@
-#define aLongMacroDefinition(x,y)	\
-	some line here;	\
-	and some more;	\
-	finish now
-5 back to ordinary text.
-#include "inclusion"
-7 hello again
-8 some more
-9 aLongMacroDefinition(a,b)
-10 end
diff --git a/tests/nastyhack b/tests/nastyhack
deleted file mode 100644
--- a/tests/nastyhack
+++ /dev/null
@@ -1,16 +0,0 @@
-#define GHC_PKG_VERSION 6.2.2
--- hackery to convice cpp to splice GHC_PKG_VERSION into a string
-version :: String
-version = tail "\ 
-    \ GHC_PKG_VERSION"
-
-version2 = "GHC_PKG_VERSION"
-
-#define v3 "GHC_PKG_VERSION"
-version3 = v3
-
-#define stringify(s) #s
-version4 = stringify(GHC_PKG_VERSION)
-
-#define stringify2(s) "s"
-version5 = stringify2(GHC_PKG_VERSION)
diff --git a/tests/nestcomment b/tests/nestcomment
deleted file mode 100644
--- a/tests/nestcomment
+++ /dev/null
@@ -1,7 +0,0 @@
-{-
-#if 1
-foo
-#else
-bar
-#endif
--}
diff --git a/tests/numbers b/tests/numbers
deleted file mode 100644
--- a/tests/numbers
+++ /dev/null
@@ -1,29 +0,0 @@
-#if 1
-number (1) in if
-#else
-rejected number (1) in if
-#endif
-
-#if 0
-wrongly accepted number (0) in if
-#else
-number (0) in if
-#endif
-
-#if eaf
-false hex number in if
-#else
-rejected false hex number in if
-#endif
-
-#if 0x1
-real hex number (0x1) in if
-#else
-rejected real hex number (0x1) in if
-#endif
-
-#if 0x00
-wrongly accepted real hex number (0x00) in if
-#else
-hex number (0x00) in if
-#endif
diff --git a/tests/param b/tests/param
deleted file mode 100644
--- a/tests/param
+++ /dev/null
@@ -1,5 +0,0 @@
-#define FOO 1
-#define BAR FOO
-#define JOIN(f)  f##f
-
-JOIN(BAR)	-- gcc gives BARBAR, cpphs gives 11
diff --git a/tests/parens b/tests/parens
deleted file mode 100644
--- a/tests/parens
+++ /dev/null
@@ -1,5 +0,0 @@
-#if ( defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 600 ) \
-    || ( defined(__NHC__) && __NHC__ >= 117 )
-#define FINALIZERPTR yes
-#endif
-FINALIZERPTR
diff --git a/tests/pragma b/tests/pragma
deleted file mode 100644
--- a/tests/pragma
+++ /dev/null
@@ -1,1 +0,0 @@
-#pragma  ident   "@(#)time.h     1.39    99/08/10 SMI"   /* SVr4.0 1.18 */
diff --git a/tests/precedence b/tests/precedence
deleted file mode 100644
--- a/tests/precedence
+++ /dev/null
@@ -1,3 +0,0 @@
-#if !0 && 0
-boolean operator precedence is wrong
-#endif
diff --git a/tests/preinclude b/tests/preinclude
deleted file mode 100644
--- a/tests/preinclude
+++ /dev/null
@@ -1,1 +0,0 @@
-something arbitrary
diff --git a/tests/recursive b/tests/recursive
deleted file mode 100644
--- a/tests/recursive
+++ /dev/null
@@ -1,4 +0,0 @@
-#define C D D
-#define B C C
-#define A B B
-A
diff --git a/tests/ross b/tests/ross
deleted file mode 100644
--- a/tests/ross
+++ /dev/null
@@ -1,19 +0,0 @@
-/* 1. C comments should be deleted by the preprocessor */
-
-/* 2. repeated expansion */
-#define FOO 4
-#define BAR FOO
-
-f = BAR
-
-/* 3. continuation lines in macros shouldn't give newlines */
-#define LONG_MACRO \
-{ putStr "Hello "; \
-  putStrLn "World" }
-
-g = do LONG_MACRO
-
-/* 4. projection macros */
-#define MACRO(x) x
-
-h = MACRO(FOO)
diff --git a/tests/runtests b/tests/runtests
deleted file mode 100644
--- a/tests/runtests
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/bin/sh
-CPPHS=${1:-"../cpphs"}
-FAIL=0
-
-runtest() {
-  if $1 >out 2>/dev/null && diff $2 out >/dev/null
-  then echo "passed: " $1
-  else FAIL=$?
-       echo "FAILED: ($2) " $1
-  fi
-}
-
-if $CPPHS </dev/null; then echo -n "passed: "; else echo -n "FAILED: "; fi
-echo " $CPPHS </dev/null"
-runtest "$CPPHS --nomacro testfile" expect1
-runtest "$CPPHS --nomacro -Dnoelif testfile" expect2
-runtest "$CPPHS --nomacro -Delif testfile" expect3
-runtest "$CPPHS --nomacro -Dinclude testfile" expect4
-runtest "$CPPHS --noline -Dinclude testfile" expect5
-runtest "$CPPHS cpp" expect6
-runtest "$CPPHS -D__GLASGOW_HASKELL__ --layout Storable.hs " expect7
-runtest "$CPPHS -DCALLCONV=ccall --hashes --layout HsOpenGLExt.h" expect8
-runtest "$CPPHS --layout multiline" expect9
-runtest "$CPPHS --nomacro multiline" expect10
-runtest "$CPPHS --hashes stringise" expect11
-runtest "$CPPHS recursive" expect12
-runtest "$CPPHS --strip ross" expect13
-runtest "$CPPHS precedence" expect14
-runtest "$CPPHS indirect" expect15
-runtest "$CPPHS --hashes indirect-a" expect15a
-runtest "$CPPHS numbers" expect16
-runtest "$CPPHS pragma" expect17		# see also test 32
-runtest "$CPPHS --noline pragma" expect18	# see also test 33
-runtest "$CPPHS -D__NHC__=117 parens" expect19
-runtest "$CPPHS -Dc -Dd -De -Df -Dg -Dh chains" expect20
-runtest "$CPPHS --hashes specials" expect21
-runtest "$CPPHS --hashes specialinclude" expect22
-runtest "$CPPHS incomplete" expect23
-runtest "$CPPHS text" expect24
-runtest "$CPPHS --text text" expect25
-runtest "$CPPHS --text nastyhack" expect26
-runtest "$CPPHS nastyhack" expect27
-runtest "$CPPHS -DXXX symbolvalue" expect28
-runtest "$CPPHS Test.hsc" expect29
-runtest "$CPPHS --unlit Arr.lhs" expect30
-runtest "$CPPHS -D__NHC__=118 elif" expect31
-runtest "$CPPHS --pragma pragma" expect32
-runtest "$CPPHS --pragma --noline pragma" expect33
-runtest "$CPPHS igloo" expect34
-runtest "$CPPHS igloo2" expect35
-runtest "$CPPHS --hashes igloo3" expect36
-runtest "$CPPHS --hashes igloo3a" expect36a
-runtest "$CPPHS --hashes igloo3b" expect36b
-runtest "$CPPHS --hashes igloo4" expect37
-runtest "$CPPHS --hashes igloo4a" expect37a
-runtest "$CPPHS mauke" expect38
-runtest "$CPPHS mauke2" expect39
-runtest "$CPPHS --hashes fasta" expect40
-runtest "$CPPHS --hashes fasta2" expect40a
-runtest "$CPPHS --hashes hashjoin" expect41
-runtest "$CPPHS wrongline" expect42
-runtest "$CPPHS --hashes param" expect43
-runtest "$CPPHS --strip comments" expect44
-runtest "$CPPHS --strip-eol comments" expect44a
-runtest "$CPPHS nestcomment" expect45
-runtest "$CPPHS --include=inclusion preinclude" expect46
-runtest "$CPPHS --unlit endcode-a" expect47
-runtest "$CPPHS --unlit endcode-b" expect48
-runtest "$CPPHS undef.hs" expect49
-runtest "$CPPHS --linepragma linepragma" expect50
-exit $FAIL
diff --git a/tests/specialinclude b/tests/specialinclude
deleted file mode 100644
--- a/tests/specialinclude
+++ /dev/null
@@ -1,5 +0,0 @@
-1
-2
-#include "specials"
-4
-5
diff --git a/tests/specials b/tests/specials
deleted file mode 100644
--- a/tests/specials
+++ /dev/null
@@ -1,5 +0,0 @@
-#define error(s)	Error #s at line __LINE__ of file __FILE__
-line 2
-line 3
-line 4  error(horrible)
-line 5
diff --git a/tests/stringise b/tests/stringise
deleted file mode 100644
--- a/tests/stringise
+++ /dev/null
@@ -1,2 +0,0 @@
-#define foo(x)	This is #x foo x
-foo(abcd ef)
diff --git a/tests/symbolvalue b/tests/symbolvalue
deleted file mode 100644
--- a/tests/symbolvalue
+++ /dev/null
@@ -1,3 +0,0 @@
-#if XXX
-the symbol is defined as XXX
-#endif
diff --git a/tests/testfile b/tests/testfile
deleted file mode 100644
--- a/tests/testfile
+++ /dev/null
@@ -1,34 +0,0 @@
-1 top of file
-#define X 0
-3
-#ifdef X
-5 X is defined
-#endif
-7
-#if X
-9 X is non-zero
-#endif
-11
-#if error
-#error "error message goes here"
-#endif
-15
-#if warning
-#warning "warning message goes here"
-#endif
-19
-#if include
-#include "inclusion"
-#else
-23 no inclusion, this is an else clause
-#endif
-25
-#if noelif
-27 no elif
-#elif elif
-29 this is an elif
-#else
-31 third branch of elif
-#endif
-33
-34 end of file
diff --git a/tests/text b/tests/text
deleted file mode 100644
--- a/tests/text
+++ /dev/null
@@ -1,14 +0,0 @@
-Here is some ordinary text with embedded Haskell-ish constructs,
-that should however /not/ be interpreted as Haskell if the --text
-option is given to cpphs.  For instance, here is a Haskell comment
-including a cpp definition: {-
-#  define FOO bar
-and now we end the comment: -}   and try out the definition:  FOO
-Likewise, double and single quotes no longer delimit strings or chars: "
-#  define BAZ FOO
-and what do we have here?: "  ' BAZ  '
-
-#  define expand(a,b,c)	  Some text including a, the b, and c.
-Also, in text-mode, macros should be expanded inside Haskell comments:
-    -- expand(this,other,that)
-and strings "expand(this,other,that)".
diff --git a/tests/undef.hs b/tests/undef.hs
deleted file mode 100644
--- a/tests/undef.hs
+++ /dev/null
@@ -1,4 +0,0 @@
-#define FOO 3
-wibble FOO
-#undef FOO
-this is FOO
diff --git a/tests/wrongline b/tests/wrongline
deleted file mode 100644
--- a/tests/wrongline
+++ /dev/null
@@ -1,4 +0,0 @@
-#define whereami __LINE__
-whereami
-#line 20 "foo"
-__LINE__
