module GHC.Settings.Utils where

import Prelude -- See Note [Why do we import Prelude here?]

import Data.Char (isSpace)
import Data.Map (Map)
import qualified Data.Map as Map

import GHC.BaseDir
import GHC.Platform.ArchOS

maybeRead :: Read a => String -> Maybe a
maybeRead :: forall a. Read a => String -> Maybe a
maybeRead String
str = case forall a. Read a => ReadS a
reads String
str of
  [(a
x, String
"")] -> forall a. a -> Maybe a
Just a
x
  [(a, String)]
_ -> forall a. Maybe a
Nothing

maybeReadFuzzy :: Read a => String -> Maybe a
maybeReadFuzzy :: forall a. Read a => String -> Maybe a
maybeReadFuzzy String
str = case forall a. Read a => ReadS a
reads String
str of
  [(a
x, String
s)] | forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isSpace String
s -> forall a. a -> Maybe a
Just a
x
  [(a, String)]
_ -> forall a. Maybe a
Nothing


-- Note [Settings file]
-- ~~~~~~~~~~~~~~~~~~~~
--
-- GHC has a file, `${top_dir}/settings`, which is the main source of run-time
-- configuration. ghc-pkg needs just a little bit of it: the target platform CPU
-- arch and OS. It uses that to figure out what subdirectory of `~/.ghc` is
-- associated with the current version/target platform.
--
-- This module has just enough code to read key value pairs from the settings
-- file, and read the target platform from those pairs.

type RawSettings = Map String String

-- | Read target Arch/OS from the settings
getTargetArchOS
  :: FilePath     -- ^ Settings filepath (for error messages)
  -> RawSettings  -- ^ Raw settings file contents
  -> Either String ArchOS
getTargetArchOS :: String -> RawSettings -> Either String ArchOS
getTargetArchOS String
settingsFile RawSettings
settings =
  Arch -> OS -> ArchOS
ArchOS forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a.
(Show a, Read a) =>
String -> RawSettings -> String -> Either String a
readRawSetting String
settingsFile RawSettings
settings String
"target arch"
         forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a.
(Show a, Read a) =>
String -> RawSettings -> String -> Either String a
readRawSetting String
settingsFile RawSettings
settings String
"target os"


getRawSetting
  :: FilePath -> RawSettings -> String -> Either String String
getRawSetting :: String -> RawSettings -> String -> Either String String
getRawSetting String
settingsFile RawSettings
settings String
key = case forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
key RawSettings
settings of
  Just String
xs -> forall a b. b -> Either a b
Right String
xs
  Maybe String
Nothing -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ String
"No entry for " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show String
key forall a. [a] -> [a] -> [a]
++ String
" in " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show String
settingsFile

getRawFilePathSetting
  :: FilePath -> FilePath -> RawSettings -> String -> Either String String
getRawFilePathSetting :: String -> String -> RawSettings -> String -> Either String String
getRawFilePathSetting String
top_dir String
settingsFile RawSettings
settings String
key =
  String -> String -> String
expandTopDir String
top_dir forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> RawSettings -> String -> Either String String
getRawSetting String
settingsFile RawSettings
settings String
key

getRawBooleanSetting
  :: FilePath -> RawSettings -> String -> Either String Bool
getRawBooleanSetting :: String -> RawSettings -> String -> Either String Bool
getRawBooleanSetting String
settingsFile RawSettings
settings String
key = do
  String
rawValue <- String -> RawSettings -> String -> Either String String
getRawSetting String
settingsFile RawSettings
settings String
key
  case String
rawValue of
    String
"YES" -> forall a b. b -> Either a b
Right Bool
True
    String
"NO" -> forall a b. b -> Either a b
Right Bool
False
    String
xs -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ String
"Bad value for " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show String
key forall a. [a] -> [a] -> [a]
++ String
": " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show String
xs

readRawSetting
  :: (Show a, Read a) => FilePath -> RawSettings -> String -> Either String a
readRawSetting :: forall a.
(Show a, Read a) =>
String -> RawSettings -> String -> Either String a
readRawSetting String
settingsFile RawSettings
settings String
key = case forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
key RawSettings
settings of
  Just String
xs -> case forall a. Read a => String -> Maybe a
maybeRead String
xs of
    Just a
v -> forall a b. b -> Either a b
Right a
v
    Maybe a
Nothing -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ String
"Failed to read " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show String
key forall a. [a] -> [a] -> [a]
++ String
" value " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show String
xs
  Maybe String
Nothing -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ String
"No entry for " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show String
key forall a. [a] -> [a] -> [a]
++ String
" in " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show String
settingsFile