Plan 9 from Bell Labs’s /usr/web/sources/contrib/fernan/nhc98/src/hmake/runhs.hs

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


{- Program:   runhs [-e] script [args...]
-- Author:    Malcolm Wallace
-- Copyright: 2005
-- Licence:   GPL
-- Description:
     A simple utility to run a Haskell program from source.
     The given script can be either a .hs, .lhs, or with no extension.
     Just put #!/path/to/runhs on the first line.
     This implementation
       * copies the script to /tmp, adding a .hs extension if required, and
         stripping the #! line if required;
       * uses hmake (with your default haskell compiler) to build the program;
       * then runs it with the given arguments.
     If you don't change the script between uses, the executable cached
     in /tmp is not rebuilt.
-}
#if defined(__HBC__) || defined (__NHC__)
import Time (ClockTime)
import Monad (when)
import System (system,getArgs,exitWith,ExitCode(..))
import Directory (doesFileExist,getModificationTime)
#else
import Control.Monad      (when)
import System.Cmd         (system)
import System.Directory   (doesFileExist, getModificationTime)
import System.Environment (getArgs)
import System.Exit        (exitWith, ExitCode(..))
#if __GLASGOW_HASKELL__ >= 604
#define HASCOPYFILE
#endif
#endif
#ifdef HASCOPYFILE
import System.Directory   (copyFile)
#else
copyFile src dst = do shell (unwords ["cp",src,dst]); return ()
#endif

{- original shell script:  (Haskell now departs from this slightly)
  #!/bin/sh	runhs [-e] script [args...]
case $1 in
  -?) shift ;;
  *)  ;;
esac
src=$1
shift
case $src in
  *.hs)  prog=`basename $src .hs`;  tmpsrc=/tmp/`basename $src`    ;;
  *.lhs) prog=`basename $src .lhs`; tmpsrc=/tmp/`basename $src`    ;;
  *)     prog=`basename $src`;      tmpsrc=/tmp/`basename $src`.hs ;;
esac
tmpexe=/tmp/$prog
if [ ! -f $tmpsrc -o $src -nt $tmpsrc ]
then if head -n 1 $src | grep '^#!' >/dev/null
     then tail +2 $src >$tmpsrc
     else cp $src $tmpsrc
     fi
fi
{ hmake $tmpexe >/dev/null 2>&1 ||\
  { echo "$prog: compilation error" && exit 1; } \
} && $tmpexe "$@"
-}

main = do argv <- getArgs
          (src:args) <- case argv of
                          [] -> exitWith ExitSuccess
                          (('-':_):as) -> return as
                          _ -> return argv
          let prog = basename (case reverse src of
                                ('s':'h':'.':f) ->     reverse f
                                ('s':'h':'l':'.':f) -> reverse f
                                _ ->                   src)
              tmpsrc = "/tmp/"++(case reverse src of
                                   ('s':'h':'.':f) ->     basename src
                                   ('s':'h':'l':'.':f) -> basename src
                                   _ ->                   basename src++".hs")
              tmpexe = "/tmp/"++prog
          exists <- doesFileExist tmpsrc
          copy <- if exists then do t0 <- getModificationTime src
                                    t1 <- getModificationTime tmpsrc
                                    return (t0>t1)
                            else return True
          when copy
               (do txt <- readFile src
                   case txt of
                     ('#':'!':_) ->
                          do shell ("{ echo; tail +2 "++src++"; } >"++tmpsrc)
                             return ()
                     _ -> copyFile src tmpsrc)
          -- now compile and run it
          e <- shell ("hmake "++tmpexe++">/dev/null")
          ifErr e (\c-> do putStrLn ("runhs: error in "++prog);
                           exitWith c)
          err <- shell (tmpexe++" "++unwords args)
          exitWith err


-- | Strip directory and suffix from filenames (analogous to the shell
--   command of the same name).
basename :: String -> String
basename = reverse .            takeWhile (not.(`elem`"\\/")) . reverse

-- | Strip non-directory suffix from file name (analogous to the shell
--   command of the same name).
dirname :: String -> String
dirname  = reverse . safetail . dropWhile (not.(`elem`"\\/")) . reverse
  where safetail [] = []
        safetail (_:x) = x

shell :: String -> IO ExitCode
shell = system	-- only on Unix

ifErr :: ExitCode -> (ExitCode->IO ()) -> IO ()
ifErr code@(ExitFailure _) err = err code
ifErr _ _ = return ()


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.