ghc-exactprint-0.4.0.0: tests/examples/SegFault.hs
{-# INCLUDE "Parrot_hsc.h" #-}
{-# LINE 1 "Parrot.hsc" #-}
{-# OPTIONS_GHC -fglasgow-exts -cpp -fno-full-laziness -fno-cse #-}
{-# LINE 2 "Parrot.hsc" #-}
{-# LINE 3 "Parrot.hsc" #-}
module Pugs.Embed.Parrot where
import Data.IORef
import System.Cmd
import System.Process
import System.Directory
import System.IO
import System.IO.Unsafe
import Data.Maybe
import Control.Monad
import Pugs.Compat (getEnv, _PUGS_HAVE_POSIX)
import Pugs.Internals (encodeUTF8)
findExecutable' :: String -> IO (Maybe FilePath)
findExecutable' cmd = do
dir <- getEnv "PARROT_PATH"
if isJust dir then (do
rv <- findExecutableInDirectory (fromJust dir) cmd
if isJust rv then return rv else findExecutable'') else do
findExecutable''
where
findExecutable'' = do
rv <- findExecutable cmd
if isJust rv then return rv else do
cwd <- getCurrentDirectory
rv <- findExecutableInDirectory cwd cmd
if isJust rv then return rv else do
return Nothing
findExecutableInDirectory :: FilePath -> FilePath -> IO (Maybe FilePath)
findExecutableInDirectory dir cmd = do
let file | _PUGS_HAVE_POSIX = dir ++ ('/':cmd)
| otherwise = dir ++ ('\\':cmd) ++ ".exe"
ok <- doesFileExist file
return $ if ok then (Just file) else Nothing
findParrot :: IO FilePath
findParrot = do
rv <- findExecutable' "parrot"
case rv of
Nothing -> fail "Cannot find the parrot executable in PATH"
Just cmd -> return cmd
evalParrotFile :: FilePath -> IO ()
evalParrotFile file = do
cmd <- findParrot
-- parrot -j is fatal on systems where jit is not supported,
-- so we use the next fastest CGP core.
args <- getEnv "PUGS_PARROT_OPTS"
let args' | isJust args && fromJust args /= "" = fromJust args
| otherwise = "-f"
rawSystem cmd [args', file]
return ()
evalParrot :: String -> IO ()
evalParrot str = do
tmp <- getTemporaryDirectory
(file, fh) <- openTempFile tmp "pugs.pir"
hPutStr fh str
hClose fh
evalParrotFile file
removeFile file
evalPGE :: FilePath -> String -> String -> [(String, String)] -> IO String
evalPGE path match rule subrules = do
(inp, out, err, pid) <- initPGE path
(`mapM` subrules) $ \(name, rule) -> do
let nameStr = escape name
ruleStr = escape rule
hPutStrLn inp $ unwords
["add_rule", show (length nameStr), show (length ruleStr)]
hPutStrLn inp nameStr
hPutStrLn inp ruleStr
let matchStr = escape match
ruleStr = escape rule
hPutStrLn inp $ unwords
["match", show (length matchStr), show (length ruleStr)]
hPutStrLn inp $ matchStr
hPutStrLn inp $ ruleStr
hFlush inp
rv <- hGetLine out
case rv of
('O':'K':' ':sizeStr) -> do
size <- readIO sizeStr
rv <- sequence (replicate size (hGetChar out))
ln <- hGetLine out
return $ rv ++ ln
_ -> do
errMsg <- hGetContents err
rv <- waitForProcess pid
writeIORef _ParrotInterp Nothing
let msg | null errMsg = show rv
| otherwise = errMsg
fail $ "*** Running external 'parrot' failed:\n" ++ msg
where
escape = escape . encodeUTF8
_escape "" = ""
_escape ('\\':xs) = "\\\\" ++ _escape xs
_escape ('\n':xs) = "\\n" ++ _escape xs
_escape (x:xs) = (x:_escape xs)
initPGE :: FilePath -> IO ParrotInterp
initPGE path = do
rv <- readIORef _ParrotInterp
case rv of
Just interp@(_, _, _, pid) -> do
gone <- getProcessExitCode pid
if isNothing gone then return interp else do
writeIORef _ParrotInterp Nothing
initPGE path
Nothing -> do
cmd <- findParrot
interp <- runInteractiveProcess cmd ["run_pge.pir"] (Just path) Nothing
writeIORef _ParrotInterp (Just interp)
return interp
type ParrotInterp = (Handle, Handle, Handle, ProcessHandle)
{-# NOINLINE _ParrotInterp #-}
_ParrotInterp :: IORef (Maybe ParrotInterp)
_ParrotInterp = unsafePerformIO $ newIORef Nothing
_DoCompile :: Maybe (IORef (String -> FilePath -> String -> IO String))
_DoCompile = Nothing
{-# LINE 387 "Parrot.hsc" #-}