+We (allege) that it is quicker to build up a mapping from module names
+to the paths to their corresponding interface files once, than to search
+along the import part every time we slurp in a new module (which we
+do quite a lot of.)
+
+\begin{code}
+mkModuleHiMaps :: SearchPath -> IO (ModuleHiMap, ModuleHiMap)
+mkModuleHiMaps dirs = foldM (getAllFilesMatching dirs) (env,env) dirs
+ where
+ env = emptyFM
+
+{- a pseudo file which signals that the interface files
+ contained in a particular directory have got their
+ corresponding object codes stashed away in a DLL
+
+ This stuff is only needed to deal with Win32 DLLs,
+ and conceivably we conditionally compile in support
+ for handling it. (ToDo?)
+-}
+dir_contain_dll_his = "dLL_ifs.hi"
+
+getAllFilesMatching :: SearchPath
+ -> (ModuleHiMap, ModuleHiMap)
+ -> (FilePath, String)
+ -> IO (ModuleHiMap, ModuleHiMap)
+getAllFilesMatching dirs hims (dir_path, suffix) = ( do
+ -- fpaths entries do not have dir_path prepended
+ fpaths <- getDirectoryContents dir_path
+ is_dyns <- catch
+ (if opt_Static || dir_path == "." then
+ return False
+ else
+ doesFileExist (dir_path ++ '/': dir_contain_dll_his))
+ (\ _ {-don't care-} -> return False)
+ return (foldl (addModules is_dyns) hims fpaths)
+ ) -- soft failure
+ `catch`
+ (\ err -> do
+ hPutStrLn stderr
+ ("Import path element `" ++ dir_path ++
+ if (isDoesNotExistError err) then
+ "' does not exist, ignoring."
+ else
+ "' couldn't read, ignoring.")
+
+ return hims
+ )
+ where
+ xiffus = reverse dotted_suffix
+
+ dotted_suffix =
+ case suffix of
+ [] -> []
+ ('.':xs) -> suffix
+ ls -> '.':ls
+
+ hi_boot_version_xiffus =
+ reverse (show interfaceFileFormatVersion) ++ '-':hi_boot_xiffus
+ hi_boot_xiffus = "toob-ih." -- .hi-boot reversed.
+
+ addModules is_dll his@(hi_env, hib_env) nm = fromMaybe his $
+ FMAP (\ (mod_nm,v) -> (addToFM_C addNewOne hi_env mod_nm (v, is_dll), hib_env))
+ (go xiffus rev_nm) `seqMaybe`
+
+ FMAP (\ (mod_nm,v) -> (hi_env, addToFM_C overrideNew hib_env mod_nm (v,is_dll)))
+ (go hi_boot_version_xiffus rev_nm) `seqMaybe`
+
+ FMAP (\ (mod_nm,v) -> (hi_env, addToFM_C addNewOne hib_env mod_nm (v,is_dll)))
+ (go hi_boot_xiffus rev_nm)
+ where
+ rev_nm = reverse nm
+
+ go [] xs = Just (reverse xs, dir_path ++'/':nm)
+ go _ [] = Nothing
+ go (x:xs) (y:ys)
+ | x == y = go xs ys
+ | otherwise = Nothing
+
+ addNewOne
+ | opt_WarnHiShadows = conflict
+ | otherwise = stickWithOld
+
+ stickWithOld old new = old
+ overrideNew old new = new
+
+ conflict old_path new_path
+ | old_path /= new_path =
+ pprTrace "Warning: " (text "Identically named interface files present on the import path, " $$
+ text (show old_path) <+> text "shadows" $$
+ text (show new_path) $$
+ text "on the import path: " <+>
+ text (concat (intersperse ":" (map fst dirs))))
+ old_path
+ | otherwise = old_path -- don't warn about innocous shadowings.
+