1 -----------------------------------------------------------------------------
2 -- $Id: DriverUtil.hs,v 1.11 2000/11/20 16:28:29 simonmar Exp $
4 -- Utils for the driver
6 -- (c) The University of Glasgow 2000
8 -----------------------------------------------------------------------------
10 module DriverUtil where
12 #include "HsVersions.h"
27 -----------------------------------------------------------------------------
30 short_usage = "Usage: For basic information, try the `--help' option."
32 GLOBAL_VAR(v_Path_usage, "", String)
35 usage_path <- readIORef v_Path_usage
36 usage <- readFile usage_path
41 dump ('$':'$':s) = hPutStr stderr prog_name >> dump s
42 dump (c:s) = hPutChar stderr c >> dump s
45 = PhaseFailed String ExitCode
47 | UsageError String -- prints the short usage msg after the error
48 | OtherError String -- just prints the error message
51 prog_name = unsafePerformIO (getProgName)
52 {-# NOINLINE prog_name #-}
54 instance Show BarfKind where
55 showsPrec _ e = showString prog_name . showString ": " . showBarf e
57 showBarf (UsageError str)
58 = showString str . showChar '\n' . showString short_usage
59 showBarf (OtherError str)
61 showBarf (PhaseFailed phase code)
62 = showString phase . showString " failed, code = " . shows code
63 showBarf (Interrupted)
64 = showString "interrupted"
66 unknownFlagErr f = throwDyn (UsageError ("unrecognised flag: " ++ f))
68 barfKindTc = mkTyCon "BarfKind"
69 {-# NOINLINE barfKindTc #-}
70 instance Typeable BarfKind where
71 typeOf _ = mkAppTy barfKindTc []
73 -----------------------------------------------------------------------------
74 -- Reading OPTIONS pragmas
77 :: String -- input file
78 -> IO [String] -- options, if any
79 getOptionsFromSource file
80 = do h <- openFile file ReadMode
81 catchJust ioErrors (look h)
82 (\e -> if isEOFError e then return [] else ioError e)
88 | prefixMatch "#" l -> look h
89 | prefixMatch "{-# LINE" l -> look h -- -}
90 | Just (opts:_) <- matchRegex optionRegex l
91 -> return (words opts)
92 | otherwise -> return []
94 optionRegex = mkRegex "\\{-#[ \t]+OPTIONS[ \t]+(.*)#-\\}" -- -}
96 -----------------------------------------------------------------------------
99 my_partition :: (a -> Maybe b) -> [a] -> ([(a,b)],[a])
100 my_partition _ [] = ([],[])
101 my_partition p (a:as)
102 = let (bs,cs) = my_partition p as in
105 Just b -> ((a,b):bs,cs)
107 my_prefix_match :: String -> String -> Maybe String
108 my_prefix_match [] rest = Just rest
109 my_prefix_match (_:_) [] = Nothing
110 my_prefix_match (p:pat) (r:rest)
111 | p == r = my_prefix_match pat rest
112 | otherwise = Nothing
116 handleDyn :: Typeable ex => (ex -> IO a) -> IO a -> IO a
117 handleDyn = flip catchDyn
119 split :: Char -> String -> [String]
120 split c s = case rest of
122 _:rest -> chunk : split c rest
123 where (chunk, rest) = break (==c) s
125 add :: IORef [a] -> a -> IO ()
128 writeIORef var (x:xs)
130 addNoDups :: Eq a => IORef [a] -> a -> IO ()
133 unless (x `elem` xs) $ writeIORef var (x:xs)
135 splitFilename :: String -> (String,String)
136 splitFilename f = split_longest_prefix f '.'
138 -- "foo/bar/xyzzy.ext" -> ("foo/bar", "xyzzy", ".ext")
139 splitFilename3 :: String -> (String,String,String)
141 = let (dir, rest) = split_longest_prefix str '/'
142 (name, ext) = splitFilename rest
143 real_dir | null dir = "."
145 in (real_dir, name, ext)
147 remove_suffix :: Char -> String -> String
149 | null pre = reverse suf
150 | otherwise = reverse pre
151 where (suf,pre) = break (==c) (reverse s)
153 drop_longest_prefix :: String -> Char -> String
154 drop_longest_prefix s c = reverse suf
155 where (suf,_pre) = break (==c) (reverse s)
157 take_longest_prefix :: String -> Char -> String
158 take_longest_prefix s c = reverse pre
159 where (_suf,pre) = break (==c) (reverse s)
161 -- split a string at the last occurence of 'c', returning the two
162 -- parts of the string with the 'c' removed. If the string contains
163 -- no 'c's, the entire string is returned in the second component.
164 split_longest_prefix :: String -> Char -> (String,String)
165 split_longest_prefix s c
167 [] -> ([], reverse suf)
168 (_:pre) -> (reverse pre, reverse suf)
169 where (suf,pre) = break (==c) (reverse s)
171 newsuf :: String -> String -> String
172 newsuf suf s = remove_suffix '.' s ++ suf
174 -- getdir strips the filename off the input string, returning the directory.
175 getdir :: String -> String
176 getdir s = if null dir then "." else init dir
177 where dir = take_longest_prefix s '/'
179 newdir :: String -> String -> String
180 newdir dir s = dir ++ '/':drop_longest_prefix s '/'
182 remove_spaces :: String -> String
183 remove_spaces = reverse . dropWhile isSpace . reverse . dropWhile isSpace