{- -- The "real" main program for cpphs, a simple C pre-processor written in Haskell. -- -- This module exports function "runCpps", which performs all of the functions of -- the main program of Cpphs, and which can be called from a stand-alone command line -- program or from some other program (such as a test harness). -- Copyright (c) 2004 Malcolm Wallace -- This file is placed in the public domain, but the library modules it -- refers to are either standard Haskell'98, or distributed under the LGPL. -- Modified: -- 18-May-2004, Graham Klyne: -- separated main program logic from cpphs main program module; -- added -O option, and arranged that output is written to a -- specified stream (retaining stdout as the default); -- strip any trailing '/' and '\' characters from -I options. -} module RunCpphs ( runCpphs ) where import IO (stdout, IOMode(WriteMode), openFile, hClose, hPutStr ) -- [[[GK]]] import List (isPrefixOf) import Monad (when,unless) -- [[[GK]]] import CppIfdef (cppIfdef, preDefine) import Position (newfile) import MacroPass(macroPass) -- Callable form of main program, for testing [[[GK]]] -- Also, add -O option to specify output file runCpphs :: String -> [String] -> IO () runCpphs prog args = do let ds = map (drop 2) (filter ("-D"`isPrefixOf`) args) is = map ((dropTrailing "/\\") . (drop 2)) (filter ("-I"`isPrefixOf`) args) -- [[[GK]]] os = map (drop 2) (filter ("-O"`isPrefixOf`) args) -- [[[GK]]] macro = not ("--nomacro" `elem` args) locat = not ("--noline" `elem` args) files = filter (not . isPrefixOf "-") args when (null files) (error ("Usage: "++prog++" file ... [-Dsym]* |-Dsym=val]* [-Ipath]* [-Ofile]" -- [[[GK]]] ++" [--nomacro] [--noline]")) oh <- if null os then return stdout else openFile (head os) WriteMode -- [[[GK]]] mapM_ (\f-> do c <- readFile f let pass1 = cppIfdef (newfile f) (preDefine ds) is macro locat c pass2 = macroPass ds pass1 putResult = hPutStr oh -- [[[GK]]] if not macro then putResult pass1 else putResult pass2 -- [[[GK]]] ) files unless (null os) (hClose oh) -- [[[GK]]] dropTrailing :: (Eq a) => [a] -> [a] -> [a] -- [[[GK]]] dropTrailing dropVals = reverse . dropWhile (`elem` dropVals) . reverse -- [[[GK]]]