9fec04ddf68a2411f4aeaaa5f127ab988dceed2a
[ghc-hetmet.git] / ghc / lib / std / System.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1994-1996
3 %
4
5 \section[System]{Module @System@}
6
7 \begin{code}
8 module System ( 
9     ExitCode(ExitSuccess,ExitFailure),
10     getArgs, getProgName, getEnv, system, exitWith
11   ) where
12
13 import Prelude
14 import PrelAddr
15 import PrelIOBase       ( IOError(..), IOErrorType(..), constructErrorAndFailWithInfo )
16 import PrelPack         ( unpackCString )
17
18 \end{code}
19
20 %*********************************************************
21 %*                                                      *
22 \subsection{The @ExitCode@ type}
23 %*                                                      *
24 %*********************************************************
25
26 The $ExitCode$ type defines the exit codes that a program
27 can return.  $ExitSuccess$ indicates successful termination;
28 and $ExitFailure code$ indicates program failure
29 with value {\em code}.  The exact interpretation of {\em code}
30 is operating-system dependent.  In particular, some values of 
31 {\em code} may be prohibited (e.g. 0 on a POSIX-compliant system).
32
33 \begin{code}
34 data ExitCode = ExitSuccess | ExitFailure Int 
35                 deriving (Eq, Ord, Read, Show)
36
37 \end{code}
38
39
40 %*********************************************************
41 %*                                                      *
42 \subsection{Other functions}
43 %*                                                      *
44 %*********************************************************
45
46 \begin{code}
47 getArgs                 :: IO [String]
48 getProgName             :: IO String
49 getEnv                  :: String -> IO String
50 system                  :: String -> IO ExitCode
51 exitWith                :: ExitCode -> IO a
52 \end{code}
53
54 Computation $getArgs$ returns a list of the program's command
55 line arguments (not including the program name).
56
57 \begin{code}
58 getArgs = return (unpackArgv ``prog_argv'' (``prog_argc''::Int))
59 \end{code}
60
61 Computation $getProgName$ returns the name of the program
62 as it was invoked.
63
64 \begin{code}
65 getProgName = return (unpackProgName ``prog_argv'')
66 \end{code}
67
68 Computation $getEnv var$ returns the value
69 of the environment variable {\em var}.  
70
71 This computation may fail with
72 \begin{itemize}
73 \item $NoSuchThing$
74 The environment variable does not exist.
75 \end{itemize}
76
77 \begin{code}
78 getEnv name = do
79     litstring <- _ccall_ getenv name
80     if litstring /= ``NULL'' 
81         then return (unpackCString litstring)
82         else fail (IOError Nothing NoSuchThing "getEnv"
83                         ("environment variable: " ++ name))
84 \end{code}
85
86 Computation $system cmd$ returns the exit code
87 produced when the operating system processes the command {\em cmd}.
88
89 This computation may fail with
90 \begin{itemize}
91 \item $PermissionDenied$
92 The process has insufficient privileges to perform the operation.
93 \item $ResourceExhausted$
94 Insufficient resources are available to perform the operation.  
95 \item $UnsupportedOperation$
96 The implementation does not support system calls.
97 \end{itemize}
98
99 \begin{code}
100 system "" = fail (IOError Nothing InvalidArgument "system" "null command")
101 system cmd = do
102     status <- _ccall_ systemCmd cmd
103     case status of
104         0  -> return ExitSuccess
105         -1 -> constructErrorAndFailWithInfo "system" cmd
106         n  -> return (ExitFailure n)
107
108 \end{code}
109
110 Computation $exitWith code$ terminates the
111 program, returning {\em code} to the program's caller.
112 Before it terminates, any open or semi-closed handles are first closed.
113
114 \begin{code}
115 exitWith ExitSuccess = do
116     _ccall_ EXIT (0::Int)
117     fail (IOError Nothing OtherError "exitWith" "exit should not return")
118
119 exitWith (ExitFailure n) 
120   | n == 0 = fail (IOError Nothing InvalidArgument "exitWith" "ExitFailure 0")
121   | otherwise = do
122     _ccall_ EXIT n
123     fail (IOError Nothing OtherError "exitWith" "exit should not return")
124 \end{code}
125
126
127 %*********************************************************
128 %*                                                      *
129 \subsection{Local utilities}
130 %*                                                      *
131 %*********************************************************
132
133 \begin{code}
134 type CHAR_STAR_STAR     = Addr  -- this is all a  HACK
135 type CHAR_STAR          = Addr
136
137 unpackArgv      :: CHAR_STAR_STAR -> Int -> [String] -- argv[1 .. argc-1]
138 unpackProgName  :: CHAR_STAR_STAR        -> String   -- argv[0]
139
140 unpackArgv argv argc = unpack 1
141   where
142     unpack :: Int -> [String]
143     unpack n
144       = if (n >= argc)
145         then ([] :: [String])
146         else case (indexAddrOffAddr argv n) of { item ->
147              unpackCString item : unpack (n + 1) }
148
149 unpackProgName argv
150   = case (indexAddrOffAddr argv 0) of { prog ->
151     de_slash [] (unpackCString prog) }
152   where
153     -- re-start accumulating at every '/'
154     de_slash :: String -> String -> String
155     de_slash acc []       = reverse acc
156     de_slash acc ('/':xs) = de_slash []      xs
157     de_slash acc (x:xs)   = de_slash (x:acc) xs
158 \end{code}