----------------------------------------------------------------------------- -- | -- Module : ReadFirst -- Copyright : 2004 Malcolm Wallace -- Licence : LGPL -- -- Maintainer : Malcolm Wallace -- Stability : experimental -- Portability : All -- -- Read the first file that matches in a list of search paths. ----------------------------------------------------------------------------- module Language.Preprocessor.Cpphs.ReadFirst ( readFirst , readFileUTF8 , writeFileUTF8 ) where import System.IO import System.Directory (doesFileExist,findFile) import System.FilePath (isRelative) import Data.List (intersperse) import Control.Exception as E import Control.Monad (when) import Language.Preprocessor.Cpphs.Position (Posn,directory) -- | 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 , String ) -- ^ discovered filepath, and file contents readFirst name demand paths warn = do case (isRelative name, directory demand) of (False, _) -> try name [] (_, "") -> try name (".":paths) (_, dd) -> try name (dd:".":paths) where try name ds = do file <- findFile ds name case file of Just f -> do content <- readFileUTF8 f return (f,content) Nothing -> do hPutStrLn stderr ("Warning: Can't find file \""++name ++"\" in directories\n\t" ++concat (intersperse "\n\t" ds) ++"\n Asked for by: "++show demand) return ("missing file: "++name,"") 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)