1 -----------------------------------------------------------------------------
2 -- $Id: DriverUtil.hs,v 1.10 2000/11/20 15:40:54 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 = (reverse (stripDot rev_basename), reverse rev_ext)
137 where (rev_ext, rev_basename) = span ('.' /=) (reverse f)
138 stripDot ('.':xs) = xs
141 -- "foo/bar/xyzzy.ext" -> ("foo/bar", "xyzzy", ".ext")
142 splitFilename3 :: String -> (String,String,String)
144 = let (dir, rest) = split_longest_prefix str '/'
145 (name, ext) = splitFilename rest
146 real_dir | null dir = "."
148 in (real_dir, name, ext)
150 remove_suffix :: Char -> String -> String
152 | null pre = reverse suf
153 | otherwise = reverse pre
154 where (suf,pre) = break (==c) (reverse s)
156 drop_longest_prefix :: String -> Char -> String
157 drop_longest_prefix s c = reverse suf
158 where (suf,_pre) = break (==c) (reverse s)
160 take_longest_prefix :: String -> Char -> String
161 take_longest_prefix s c = reverse pre
162 where (_suf,pre) = break (==c) (reverse s)
164 -- split a string at the last occurence of 'c', returning the two
165 -- parts of the string with the 'c' removed. If the string contains
166 -- no 'c's, the entire string is returned in the second component.
167 split_longest_prefix :: String -> Char -> (String,String)
168 split_longest_prefix s c
170 [] -> ([], reverse suf)
171 (_:pre) -> (reverse pre, reverse suf)
172 where (suf,pre) = break (==c) (reverse s)
174 newsuf :: String -> String -> String
175 newsuf suf s = remove_suffix '.' s ++ suf
177 -- getdir strips the filename off the input string, returning the directory.
178 getdir :: String -> String
179 getdir s = if null dir then "." else init dir
180 where dir = take_longest_prefix s '/'
182 newdir :: String -> String -> String
183 newdir dir s = dir ++ '/':drop_longest_prefix s '/'
185 remove_spaces :: String -> String
186 remove_spaces = reverse . dropWhile isSpace . reverse . dropWhile isSpace