MyNixOS website logo
Description

A Haskell pre-processor.

See the README for usage examples

The hpp Executable

hpp is a Haskell pre-processor that is also a C90-compatible pre-processor (with the addition of a --cpp flag). It is packaged as both a library and an executable.

To use as a Haskell preprocessor for resolving #ifdef conditionals and macro expansion, an invocation might look like,

hpp -DDEBUG Foo.hs

To use as a C preprocessor, an invocation might look like,

hpp -DDEBUG --cpp foo.c

To have GHC use hpp as the C pre-processor, add this line to the top of a Haskell source file that makes use of the CPP LANGUAGE pragma,

{-# OPTIONS_GHC -cpp -pgmPhpp #-}

Or add this line to your .cabal file:

ghc-options: -pgmPhpp

Note that you will need to ensure that the hpp executable is available in your build environment (e.g. you can add hpp as a build-depends in your .cabal file).

The hpp Library

The hpp executable is a command-line interface to the hpp library. While the hpp package has been designed to have minimal dependencies beyond what the GHC compiler itself uses, it does include a few small, framework-free unit tests that demonstrate basic usage as a library. In the testIf example, we preprocess the sourceIfdef input with a starting definition equivalent to #define FOO 1. In testArith1, we exercise basic integer arithmetic and comparison. The hppHelper function shows how to run your source input through the preprocessor: expand initialState (preproces mySource). If you want to support #includeing other files, you will use runHpp or streamHpp that operate in IO and support searching among a list of include paths.

{-# LANGUAGE OverloadedStrings #-}
import Control.Monad.Trans.Except
import Data.ByteString.Char8 (ByteString)
import Data.Maybe (fromMaybe)
import Data.Monoid ((<>))
import Hpp
import System.Exit

sourceIfdef :: [ByteString]
sourceIfdef = [ "#ifdef FOO"
              , "x = 42"
              , "#else"
              , "x = 99"
              , "#endif" ]

sourceArith1 :: ByteString -> [ByteString]
sourceArith1 s = [ "#define x 3"
                 , "#if 5 + x > " <> s
                 , "yay"
                 , "#else"
                 , "boo"
                 , "#endif" ]

hppHelper :: HppState -> [ByteString] -> [ByteString] -> IO Bool
hppHelper st src expected =
  case runExcept (expand st (preprocess src)) of
    Left e -> putStrLn ("Error running hpp: " ++ show e) >> return False
    Right (res, _) -> if hppOutput res == expected
                      then return True
                      else do putStr ("Expected "++show expected++", got")
                              print (hppOutput res)
                              return False

testElse :: IO Bool
testElse = hppHelper emptyHppState sourceIfdef ["x = 99\n","\n"]

testIf :: IO Bool
testIf = hppHelper (fromMaybe (error "Preprocessor definition did not parse")
                              (addDefinition "FOO" "1" emptyHppState))
                   sourceIfdef
                   ["x = 42\n","\n"]

testArith1 :: IO Bool
testArith1 = (&&) <$> hppHelper emptyHppState (sourceArith1 "7") ["yay\n","\n"]
                  <*> hppHelper emptyHppState (sourceArith1 "8") ["boo\n","\n"]

main :: IO ()
main = do results <- sequenceA [testElse, testIf, testArith1]
          if and results then exitWith ExitSuccess else exitWith (ExitFailure 1)
Metadata

Version

0.6.5

Executables (1)

  • bin/hpp

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-darwin
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-darwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows