[project @ 1996-12-19 18:35:23 by simonpj]
[ghc-hetmet.git] / ghc / lib / ghc / IOHandle.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1994-1996
3 %
4
5 \section[IOHandle]{Module @IOHandle@}
6
7 This module defines Haskell {\em handles} and the basic operations
8 which are supported for them.
9
10 \begin{code}
11 #include "error.h"
12
13 module IOHandle where
14
15 import Prelude  ()
16 import ST
17 import STBase
18 import ArrBase  ( ByteArray(..) )
19 import PrelRead ( Read )
20 import Ix
21 import IOBase
22 import PrelTup
23 import PrelBase
24 import GHC
25
26 \end{code}
27
28
29 %*********************************************************
30 %*                                                      *
31 \subsection{Types @FilePath@, @Handle@, @Handle__@}
32 %*                                                      *
33 %*********************************************************
34
35 \begin{code}
36 type FilePath = String
37
38 #if defined(__CONCURRENT_HASKELL__)
39 type Handle = MVar Handle__
40
41 newHandle   = newMVar
42 readHandle  = takeMVar
43 writeHandle = putMVar
44
45 #else
46 type Handle = MutableVar RealWorld Handle__
47
48 newHandle v     = stToIO (newVar   v)
49 readHandle h    = stToIO (readVar  h)
50 writeHandle h v = stToIO (writeVar h v)
51
52 #endif {- __CONCURRENT_HASKELL__ -}
53
54 data Handle__
55   = ErrorHandle         IOError
56   | ClosedHandle
57   | SemiClosedHandle    Addr (Addr, Int)
58   | ReadHandle          Addr (Maybe BufferMode) Bool
59   | WriteHandle         Addr (Maybe BufferMode) Bool
60   | AppendHandle        Addr (Maybe BufferMode) Bool
61   | ReadWriteHandle     Addr (Maybe BufferMode) Bool
62
63 instance Eq Handle{-partain:????-}
64
65 {-# INLINE newHandle   #-}
66 {-# INLINE readHandle  #-}
67 {-# INLINE writeHandle #-}
68
69 newHandle   :: Handle__ -> IO Handle
70 readHandle  :: Handle   -> IO Handle__
71 writeHandle :: Handle -> Handle__ -> IO ()
72 \end{code}
73
74 %*********************************************************
75 %*                                                      *
76 \subsection{Functions}
77 %*                                                      *
78 %*********************************************************
79
80 \begin{code}
81 filePtr :: Handle__ -> Addr
82 filePtr (SemiClosedHandle fp _)  = fp
83 filePtr (ReadHandle fp _ _)      = fp
84 filePtr (WriteHandle fp _ _)     = fp
85 filePtr (AppendHandle fp _ _)    = fp
86 filePtr (ReadWriteHandle fp _ _) = fp
87
88 bufferMode :: Handle__ -> Maybe BufferMode
89 bufferMode (ReadHandle _ m _)      = m
90 bufferMode (WriteHandle _ m _)     = m
91 bufferMode (AppendHandle _ m _)    = m
92 bufferMode (ReadWriteHandle _ m _) = m
93
94 markHandle :: Handle__ -> Handle__
95 markHandle h@(ReadHandle fp m b)
96   | b = h
97   | otherwise = ReadHandle fp m True
98 markHandle h@(WriteHandle fp m b)
99   | b = h
100   | otherwise = WriteHandle fp m True
101 markHandle h@(AppendHandle fp m b)
102   | b = h
103   | otherwise = AppendHandle fp m True
104 markHandle h@(ReadWriteHandle fp m b)
105   | b = h
106   | otherwise = ReadWriteHandle fp m True
107 \end{code}
108
109 -------------------------------------------
110
111 %*********************************************************
112 %*                                                      *
113 \subsection[StdHandles]{Standard handles}
114 %*                                                      *
115 %*********************************************************
116
117 Three handles are allocated during program initialisation.  The first
118 two manage input or output from the Haskell program's standard input
119 or output channel respectively.  The third manages output to the
120 standard error channel. These handles are initially open.
121
122 \begin{code}
123 stdin, stdout, stderr :: Handle
124
125 stdin = unsafePerformPrimIO (
126     _ccall_ getLock (``stdin''::Addr) 0         >>= \ rc ->
127     (case rc of
128        0 -> new_handle ClosedHandle
129        1 -> new_handle (ReadHandle ``stdin'' Nothing False)
130        _ -> constructError "stdin"              >>= \ ioError -> 
131             new_handle (ErrorHandle ioError)
132     )                                           >>= \ handle ->
133     returnPrimIO handle
134   )
135   where
136     new_handle x = ioToST (newHandle x)
137
138 stdout = unsafePerformPrimIO (
139     _ccall_ getLock (``stdout''::Addr) 1        >>= \ rc ->
140     (case rc of
141        0 -> new_handle ClosedHandle
142        1 -> new_handle (WriteHandle ``stdout'' Nothing False)
143        _ -> constructError "stdout"             >>= \ ioError -> 
144             new_handle (ErrorHandle ioError)
145     )                                           >>= \ handle ->
146     returnPrimIO handle
147   )
148   where
149     new_handle x = ioToST (newHandle x)
150
151 stderr = unsafePerformPrimIO (
152     _ccall_ getLock (``stderr''::Addr) 1        >>= \ rc ->
153     (case rc of
154        0 -> new_handle ClosedHandle
155        1 -> new_handle (WriteHandle ``stderr'' (Just NoBuffering) False)        
156        _ -> constructError "stderr"             >>= \ ioError -> 
157             new_handle (ErrorHandle ioError)
158     )                                           >>= \ handle ->
159     returnPrimIO handle
160   )
161   where
162     new_handle x = ioToST (newHandle x)
163 \end{code}
164
165 %*********************************************************
166 %*                                                      *
167 \subsection[OpeningClosing]{Opening and Closing Files}
168 %*                                                      *
169 %*********************************************************
170
171 \begin{code}
172 data IOMode      =  ReadMode | WriteMode | AppendMode | ReadWriteMode
173                     deriving (Eq, Ord, Ix, Enum, Read, Show)
174
175 openFile :: FilePath -> IOMode -> IO Handle
176
177 openFile f m = 
178     stToIO (_ccall_ openFile f m')                  >>= \ ptr ->
179     if ptr /= ``NULL'' then
180         newHandle (htype ptr Nothing False)
181     else
182         stToIO (constructError "openFile")          >>= \ ioError -> 
183         let
184             improved_error -- a HACK, I guess
185               = case ioError of
186                   AlreadyExists    msg -> AlreadyExists    (msg ++ ": " ++ f)
187                   NoSuchThing      msg -> NoSuchThing      (msg ++ ": " ++ f)
188                   PermissionDenied msg -> PermissionDenied (msg ++ ": " ++ f)
189                   _                    -> ioError
190         in
191         fail improved_error
192   where
193     m' = case m of 
194            ReadMode      -> "r"
195            WriteMode     -> "w"
196            AppendMode    -> "a"
197            ReadWriteMode -> "r+"
198
199     htype = case m of 
200               ReadMode      -> ReadHandle
201               WriteMode     -> WriteHandle
202               AppendMode    -> AppendHandle
203               ReadWriteMode -> ReadWriteHandle
204 \end{code}
205
206 Computation $openFile file mode$ allocates and returns a new, open
207 handle to manage the file {\em file}.  It manages input if {\em mode}
208 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
209 and both input and output if mode is $ReadWriteMode$.
210
211 If the file does not exist and it is opened for output, it should be
212 created as a new file.  If {\em mode} is $WriteMode$ and the file
213 already exists, then it should be truncated to zero length.  The
214 handle is positioned at the end of the file if {\em mode} is
215 $AppendMode$, and otherwise at the beginning (in which case its
216 internal position is 0).
217
218 Implementations should enforce, locally to the Haskell process,
219 multiple-reader single-writer locking on files, which is to say that
220 there may either be many handles on the same file which manage input,
221 or just one handle on the file which manages output.  If any open or
222 semi-closed handle is managing a file for output, no new handle can be
223 allocated for that file.  If any open or semi-closed handle is
224 managing a file for input, new handles can only be allocated if they
225 do not manage output.
226
227 Two files are the same if they have the same absolute name.  An
228 implementation is free to impose stricter conditions.
229
230 \begin{code}
231 hClose :: Handle -> IO ()
232
233 hClose handle =
234     readHandle handle                               >>= \ htype ->
235     writeHandle handle ClosedHandle                 >>
236     case htype of 
237       ErrorHandle ioError ->
238           fail ioError
239       ClosedHandle -> 
240           fail (IllegalOperation "handle is closed")
241       SemiClosedHandle fp (buf,_) ->
242           (if buf /= ``NULL'' then
243               _ccall_ free buf
244            else                     
245               returnPrimIO ())                      `thenIO_Prim` \ () ->
246           if fp /= ``NULL'' then
247               _ccall_ closeFile fp                  `thenIO_Prim` \ rc ->
248               if rc == 0 then 
249                   return ()
250               else
251                   constructErrorAndFail "hClose"
252           else                      
253               return ()
254       other -> 
255           _ccall_ closeFile (filePtr other)         `thenIO_Prim` \ rc ->
256           if rc == 0 then 
257               return ()
258           else
259               constructErrorAndFail "hClose"
260 \end{code}
261
262 Computation $hClose hdl$ makes handle {\em hdl} closed.  Before the
263 computation finishes, any items buffered for output and not already
264 sent to the operating system are flushed as for $flush$.
265
266 %*********************************************************
267 %*                                                      *
268 \subsection[EOF]{Detecting the End of Input}
269 %*                                                      *
270 %*********************************************************
271
272
273 For a handle {\em hdl} which attached to a physical file, $hFileSize
274 hdl$ returns the size of {\em hdl} in terms of the number of items
275 which can be read from {\em hdl}.
276
277 \begin{code}
278 hFileSize :: Handle -> IO Integer
279 hFileSize handle =
280     readHandle handle                               >>= \ htype ->
281     case htype of 
282       ErrorHandle ioError ->
283           writeHandle handle htype                          >>
284           fail ioError
285       ClosedHandle -> 
286           writeHandle handle htype                          >>
287           fail (IllegalOperation "handle is closed")
288       SemiClosedHandle _ _ -> 
289           writeHandle handle htype                          >>
290           fail (IllegalOperation "handle is closed")
291       other ->
292           -- HACK!  We build a unique MP_INT of the right shape to hold
293           -- a single unsigned word, and we let the C routine change the data bits
294           _casm_ ``%r = 1;''                        `thenIO_Prim` \ (I# hack#) ->
295           case int2Integer# hack# of
296             result@(J# _ _ d#) ->
297                 let
298                     bogus_bounds = (error "fileSize"::(Int,Int))
299                 in
300                 _ccall_ fileSize (filePtr other) (ByteArray bogus_bounds d#)
301                                                     `thenIO_Prim` \ rc ->
302                writeHandle handle htype             >>
303                if rc == 0 then
304                    return result
305                else
306                     constructErrorAndFail "hFileSize"
307 \end{code}
308
309 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
310 $True$ if no further input can be taken from {\em hdl} or for a
311 physical file, if the current I/O position is equal to the length of
312 the file.  Otherwise, it returns $False$.
313
314 \begin{code}
315 hIsEOF :: Handle -> IO Bool
316 hIsEOF handle =
317     readHandle handle                               >>= \ htype ->
318     case htype of 
319       ErrorHandle ioError ->
320           writeHandle handle htype                  >>
321           fail ioError
322       ClosedHandle -> 
323           writeHandle handle htype                  >>
324           fail (IllegalOperation "handle is closed")
325       SemiClosedHandle _ _ -> 
326           writeHandle handle htype                  >>
327           fail (IllegalOperation "handle is closed")
328       WriteHandle _ _ _ -> 
329           writeHandle handle htype                  >>
330           fail (IllegalOperation "handle is not open for reading")
331       AppendHandle _ _ _ -> 
332           writeHandle handle htype                  >>
333           fail (IllegalOperation "handle is not open for reading")
334       other -> 
335           _ccall_ fileEOF (filePtr other)           `thenIO_Prim` \ rc ->
336           writeHandle handle (markHandle htype)     >>
337           case rc of
338             0 -> return False
339             1 -> return True
340             _ -> constructErrorAndFail "hIsEOF"
341
342 isEOF :: IO Bool
343 isEOF = hIsEOF stdin
344 \end{code}
345
346 %*********************************************************
347 %*                                                      *
348 \subsection[Buffering]{Buffering Operations}
349 %*                                                      *
350 %*********************************************************
351
352 Three kinds of buffering are supported: line-buffering, 
353 block-buffering or no-buffering.  These modes have the following effects.
354 For output, items are written out from the internal buffer 
355 according to the buffer mode:
356 \begin{itemize}
357 \item[line-buffering]  the entire output buffer is written
358 out whenever a newline is output, the output buffer overflows, 
359 a flush is issued, or the handle is closed.
360
361 \item[block-buffering] the entire output buffer is written out whenever 
362 it overflows, a flush is issued, or the handle
363 is closed.
364
365 \item[no-buffering] output is written immediately, and never stored
366 in the output buffer.
367 \end{itemize}
368
369 The output buffer is emptied as soon as it has been written out.
370
371 Similarly, input occurs according to the buffer mode for handle {\em hdl}.
372 \begin{itemize}
373 \item[line-buffering] when the input buffer for {\em hdl} is not empty,
374 the next item is obtained from the buffer;
375 otherwise, when the input buffer is empty,
376 characters up to and including the next newline
377 character are read into the buffer.  No characters
378 are available until the newline character is
379 available.
380 \item[block-buffering] when the input buffer for {\em hdl} becomes empty,
381 the next block of data is read into this buffer.
382 \item[no-buffering] the next input item is read and returned.
383 \end{itemize}
384 For most implementations, physical files will normally be block-buffered 
385 and terminals will normally be line-buffered.
386
387 \begin{code}
388 data BufferMode  =  NoBuffering | LineBuffering | BlockBuffering (Maybe Int)
389                     deriving (Eq, Ord, Read, Show)
390 \end{code}
391
392 Computation $hSetBuffering hdl mode$ sets the mode of buffering for
393 handle {\em hdl} on subsequent reads and writes.
394
395 \begin{itemize}
396 \item
397 If {\em mode} is $LineBuffering$, line-buffering should be
398 enabled if possible.
399 \item
400 If {\em mode} is $BlockBuffering$ {\em size}, then block-buffering
401 should be enabled if possible.  The size of the buffer is {\em n} items
402 if {\em size} is $Just${\em n} and is otherwise implementation-dependent.
403 \item
404 If {\em mode} is $NoBuffering$, then buffering is disabled if possible.
405 \end{itemize}
406
407 If the buffer mode is changed from $BlockBuffering$ or $LineBuffering$
408 to $NoBuffering$, then any items in the output buffer are written to
409 the device, and any items in the input buffer are discarded.  The
410 default buffering mode when a handle is opened is
411 implementation-dependent and may depend on the object which is
412 attached to that handle.
413
414 \begin{code}
415 hSetBuffering :: Handle -> BufferMode -> IO ()
416
417 hSetBuffering handle mode =
418     case mode of
419       (BlockBuffering (Just n)) 
420         | n <= 0 -> fail (InvalidArgument "illegal buffer size")
421       other ->
422           readHandle handle                         >>= \ htype ->
423           if isMarked htype then
424               writeHandle handle htype              >>
425               fail (UnsupportedOperation "can't set buffering for a dirty handle")
426           else
427               case htype of
428                 ErrorHandle ioError ->
429                     writeHandle handle htype        >>
430                     fail ioError
431                 ClosedHandle ->
432                     writeHandle handle htype        >>
433                     fail (IllegalOperation "handle is closed")
434                 SemiClosedHandle _ _ ->
435                     writeHandle handle htype        >>
436                     fail (IllegalOperation "handle is closed")
437                 other ->
438                     _ccall_ setBuffering (filePtr other) bsize
439                                                     `thenIO_Prim` \ rc -> 
440                     if rc == 0 then
441                         writeHandle handle ((hcon other) (filePtr other) (Just mode) True)
442                                                     >>
443                         return ()
444                     else
445                         writeHandle handle htype         >>
446                         constructErrorAndFail "hSetBuffering"
447                 
448   where
449     isMarked :: Handle__ -> Bool
450     isMarked (ReadHandle fp m b) = b
451     isMarked (WriteHandle fp m b) = b
452     isMarked (AppendHandle fp m b) = b
453     isMarked (ReadWriteHandle fp m b) = b
454
455     bsize :: Int
456     bsize = case mode of
457               NoBuffering -> 0
458               LineBuffering -> -1
459               BlockBuffering Nothing -> -2
460               BlockBuffering (Just n) -> n
461
462     hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
463     hcon (ReadHandle _ _ _) = ReadHandle
464     hcon (WriteHandle _ _ _) = WriteHandle
465     hcon (AppendHandle _ _ _) = AppendHandle
466     hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
467 \end{code}
468
469 Computation $flush hdl$ causes any items buffered for output in handle
470 {\em hdl} to be sent immediately to the operating system.
471
472 \begin{code}
473 hFlush :: Handle -> IO () 
474 hFlush handle = 
475     readHandle handle                               >>= \ htype ->
476     case htype of 
477       ErrorHandle ioError ->
478           writeHandle handle htype                  >>
479           fail ioError
480       ClosedHandle ->
481           writeHandle handle htype                  >>
482           fail (IllegalOperation "handle is closed")
483       SemiClosedHandle _ _ ->
484           writeHandle handle htype                  >>
485           fail (IllegalOperation "handle is closed")
486       other ->
487           _ccall_ flushFile (filePtr other)         `thenIO_Prim` \ rc ->
488           writeHandle handle (markHandle htype)   >>
489                if rc == 0 then 
490                    return ()
491                else
492                     constructErrorAndFail "hFlush"
493 \end{code}
494
495
496 %*********************************************************
497 %*                                                      *
498 \subsection[Seeking]{Repositioning Handles}
499 %*                                                      *
500 %*********************************************************
501
502 \begin{code}
503 data HandlePosn = HandlePosn Handle Int
504
505 instance Eq HandlePosn{-partain-}
506
507 data SeekMode    =  AbsoluteSeek | RelativeSeek | SeekFromEnd
508                     deriving (Eq, Ord, Ix, Enum, Read, Show)
509 \end{code}
510
511 Computation $hGetPosn hdl$ returns the current I/O
512 position of {\em hdl} as an abstract position.  Computation
513 $hSetPosn p$ sets the position of {\em hdl}
514 to a previously obtained position {\em p}.
515
516 \begin{code}
517 hGetPosn :: Handle -> IO HandlePosn
518 hGetPosn handle = 
519     readHandle handle                               >>= \ htype ->
520     case htype of 
521       ErrorHandle ioError ->
522           writeHandle handle htype                  >>
523           fail ioError
524       ClosedHandle ->
525           writeHandle handle htype                  >>
526           fail (IllegalOperation "handle is closed")
527       SemiClosedHandle _ _ ->
528           writeHandle handle htype                  >>
529           fail (IllegalOperation "handle is closed")
530       other -> 
531           _ccall_ getFilePosn (filePtr other)      `thenIO_Prim` \ posn ->
532           writeHandle handle htype                  >>
533           if posn /= -1 then
534               return (HandlePosn handle posn)
535           else
536               constructErrorAndFail "hGetPosn"
537
538 hSetPosn :: HandlePosn -> IO () 
539 hSetPosn (HandlePosn handle posn) = 
540     readHandle handle                               >>= \ htype ->
541     case htype of 
542       ErrorHandle ioError ->
543           writeHandle handle htype                  >>
544           fail ioError
545       ClosedHandle ->
546           writeHandle handle htype                  >>
547           fail (IllegalOperation "handle is closed")
548       SemiClosedHandle _ _ ->
549           writeHandle handle htype                  >>
550           fail (IllegalOperation "handle is closed")
551       AppendHandle _ _ _ ->
552           writeHandle handle htype                  >>
553           fail (IllegalOperation "handle is not seekable")
554       other -> 
555           _ccall_ setFilePosn (filePtr other) posn `thenIO_Prim` \ rc ->
556           writeHandle handle (markHandle htype)    >>
557                if rc == 0 then 
558                    return ()
559                else
560                    constructErrorAndFail "hSetPosn"
561 \end{code}
562
563 Computation $hSeek hdl mode i$ sets the position of handle
564 {\em hdl} depending on $mode$.  If {\em mode} is
565 \begin{itemize}
566 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
567 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
568 the current position.
569 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
570 the end of the file.
571 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
572 the beginning of the file.
573 \end{itemize}
574
575 Some handles may not be seekable $hIsSeekable$, or only support a
576 subset of the possible positioning operations (e.g. it may only be
577 possible to seek to the end of a tape, or to a positive offset from
578 the beginning or current position).
579
580 It is not possible to set a negative I/O position, or for a physical
581 file, an I/O position beyond the current end-of-file. 
582
583 \begin{code}
584 hSeek :: Handle -> SeekMode -> Integer -> IO () 
585 hSeek handle mode offset@(J# _ s# d#) = 
586     readHandle handle                               >>= \ htype ->
587     case htype of 
588       ErrorHandle ioError ->
589           writeHandle handle htype                  >>
590           fail ioError
591       ClosedHandle ->
592           writeHandle handle htype                  >>
593           fail (IllegalOperation "handle is closed")
594       SemiClosedHandle _ _ ->
595           writeHandle handle htype                  >>
596           fail (IllegalOperation "handle is closed")
597       AppendHandle _ _ _ ->
598           writeHandle handle htype                  >>
599           fail (IllegalOperation "handle is not seekable")
600       other -> 
601           _ccall_ seekFile (filePtr other) whence (I# s#) (ByteArray (0,0) d#)
602                                                     `thenIO_Prim` \ rc ->
603           writeHandle handle (markHandle htype)   >>
604                if rc == 0 then 
605                    return ()
606                else
607                     constructErrorAndFail "hSeek"
608   where
609     whence :: Int
610     whence = case mode of
611                AbsoluteSeek -> ``SEEK_SET''
612                RelativeSeek -> ``SEEK_CUR''
613                SeekFromEnd -> ``SEEK_END''
614 \end{code}
615
616 %*********************************************************
617 %*                                                      *
618 \subsection[Query]{Handle Properties}
619 %*                                                      *
620 %*********************************************************
621
622 A number of operations return information about the properties of a
623 handle.  Each of these operations returns $True$ if the
624 handle has the specified property, and $False$
625 otherwise.
626
627 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
628 {\em hdl} is not block-buffered.  Otherwise it returns 
629 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and 
630 $( Just n )$ for block-buffering of {\em n} bytes.
631
632 \begin{code}
633 hIsOpen :: Handle -> IO Bool
634 hIsOpen handle = 
635     readHandle handle                               >>= \ htype ->
636     case htype of 
637       ErrorHandle ioError ->
638           writeHandle handle htype                  >>
639           fail ioError
640       ClosedHandle ->
641           writeHandle handle htype                  >>
642           return False
643       SemiClosedHandle _ _ ->
644           writeHandle handle htype                  >>
645           return False
646       other ->
647           writeHandle handle htype                  >>
648           return True
649
650 hIsClosed :: Handle -> IO Bool
651 hIsClosed handle = 
652     readHandle handle                               >>= \ htype ->
653     case htype of 
654       ErrorHandle ioError ->
655           writeHandle handle htype                  >>
656           fail ioError
657       ClosedHandle ->
658           writeHandle handle htype                  >>
659           return True
660       other ->
661           writeHandle handle htype                  >>
662           return False
663
664 hIsReadable :: Handle -> IO Bool
665 hIsReadable handle = 
666     readHandle handle                               >>= \ htype ->
667     case htype of 
668       ErrorHandle ioError ->
669           writeHandle handle htype                  >>
670           fail ioError
671       ClosedHandle ->
672           writeHandle handle htype                  >>
673           fail (IllegalOperation "handle is closed")
674       SemiClosedHandle _ _ ->
675           writeHandle handle htype                  >>
676           fail (IllegalOperation "handle is closed")
677       other ->
678           writeHandle handle htype                  >>
679           return (isReadable other)
680   where
681     isReadable (ReadHandle _ _ _) = True
682     isReadable (ReadWriteHandle _ _ _) = True
683     isReadable _ = False
684
685 hIsWritable :: Handle -> IO Bool
686 hIsWritable handle = 
687     readHandle handle                       >>= \ htype ->
688     case htype of 
689       ErrorHandle ioError ->
690           writeHandle handle htype          >>
691           fail ioError
692       ClosedHandle ->
693           writeHandle handle htype          >>
694           fail (IllegalOperation "handle is closed")
695       SemiClosedHandle _ _ ->
696           writeHandle handle htype          >>
697           fail (IllegalOperation "handle is closed")
698       other ->
699           writeHandle handle htype          >>
700           return (isWritable other)
701   where
702     isWritable (AppendHandle _ _ _) = True
703     isWritable (WriteHandle _ _ _) = True
704     isWritable (ReadWriteHandle _ _ _) = True
705     isWritable _ = False
706
707 getBufferMode :: Handle__ -> PrimIO Handle__
708 getBufferMode htype =
709     case bufferMode htype of
710       Just x -> returnPrimIO htype
711       Nothing ->
712         _ccall_ getBufferMode (filePtr htype)       `thenPrimIO` \ rc ->
713         let 
714             mode = 
715                 case rc of
716                   0  -> Just NoBuffering
717                   -1 -> Just LineBuffering
718                   -2 -> Just (BlockBuffering Nothing)
719                   -3 -> Nothing
720                   n  -> Just (BlockBuffering (Just n))
721         in
722         returnPrimIO (case htype of
723           ReadHandle      fp _ b -> ReadHandle      fp mode b
724           WriteHandle     fp _ b -> WriteHandle     fp mode b
725           AppendHandle    fp _ b -> AppendHandle    fp mode b
726           ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
727
728 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
729 hIsBlockBuffered handle =
730     readHandle handle                               >>= \ htype ->
731     case htype of 
732       ErrorHandle ioError ->
733           writeHandle handle htype                  >>
734           fail ioError
735       ClosedHandle ->
736           writeHandle handle htype                  >>
737           fail (IllegalOperation "handle is closed")
738       SemiClosedHandle _ _ ->
739           writeHandle handle htype                  >>
740           fail (IllegalOperation "handle is closed")
741       other ->
742           getBufferMode other                       `thenIO_Prim` \ other ->
743           case bufferMode other of
744             Just (BlockBuffering size) ->
745                 writeHandle handle other            >>
746                 return (True, size)
747             Just _ ->
748                 writeHandle handle other            >>
749                 return (False, Nothing)
750             Nothing -> 
751                 constructErrorAndFail "hIsBlockBuffered"
752
753 hIsLineBuffered :: Handle -> IO Bool
754 hIsLineBuffered handle =
755     readHandle handle                               >>= \ htype ->
756     case htype of 
757       ErrorHandle ioError ->
758           writeHandle handle htype                  >>
759           fail ioError
760       ClosedHandle ->
761           writeHandle handle htype                  >>
762           fail (IllegalOperation "handle is closed")
763       SemiClosedHandle _ _ ->
764           writeHandle handle htype                  >>
765           fail (IllegalOperation "handle is closed")
766       other ->
767           getBufferMode other                       `thenIO_Prim` \ other ->
768           case bufferMode other of
769             Just LineBuffering ->
770                 writeHandle handle other            >>
771                 return True
772             Just _ ->
773                 writeHandle handle other            >>
774                 return False
775             Nothing -> 
776                 constructErrorAndFail "hIsLineBuffered"
777
778 hIsNotBuffered :: Handle -> IO Bool
779 hIsNotBuffered handle =
780     readHandle handle                               >>= \ htype ->
781     case htype of 
782       ErrorHandle ioError ->
783           writeHandle handle htype                  >>
784           fail ioError
785       ClosedHandle ->
786           writeHandle handle htype                  >>
787           fail (IllegalOperation "handle is closed")
788       SemiClosedHandle _ _ ->
789           writeHandle handle htype                  >>
790           fail (IllegalOperation "handle is closed")
791       other ->
792           getBufferMode other                       `thenIO_Prim` \ other ->
793           case bufferMode other of
794             Just NoBuffering ->
795                 writeHandle handle other            >>
796                 return True
797             Just _ ->
798                 writeHandle handle other            >>
799                 return False
800             Nothing -> 
801                 constructErrorAndFail "hIsNotBuffered"
802
803 hGetBuffering :: Handle -> IO BufferMode
804 hGetBuffering hndl =
805     readHandle hndl                                 >>= \ htype ->
806     case htype of 
807       ErrorHandle ioError ->
808           writeHandle hndl htype                    >>
809           fail ioError
810       ClosedHandle ->
811           writeHandle hndl htype                    >>
812           fail (IllegalOperation "handle is closed")
813       SemiClosedHandle _ _ ->
814           writeHandle hndl htype                    >>
815           fail (IllegalOperation "handle is closed")
816       other ->
817           getBufferMode other                       `thenIO_Prim` \ other ->
818           case bufferMode other of
819             Just v ->
820                 writeHandle hndl other              >>
821                 return v
822             Nothing -> 
823                 constructErrorAndFail "hGetBuffering"
824
825 hIsSeekable :: Handle -> IO Bool
826 hIsSeekable handle = 
827     readHandle handle                               >>= \ htype ->
828     case htype of 
829       ErrorHandle ioError ->
830           writeHandle handle htype                  >>
831           fail ioError
832       ClosedHandle ->
833           writeHandle handle htype                  >>
834           fail (IllegalOperation "handle is closed")
835       SemiClosedHandle _ _ ->
836           writeHandle handle htype                  >>
837           fail (IllegalOperation "handle is closed")
838       AppendHandle _ _ _ ->
839           writeHandle handle htype                  >>
840           return False
841       other ->
842           _ccall_ seekFileP (filePtr other)         `thenIO_Prim` \ rc ->
843           writeHandle handle htype                  >>
844           case rc of
845             0 -> return False
846             1 -> return True
847             _ -> constructErrorAndFail "hIsSeekable"
848 \end{code}
849
850
851 %*********************************************************
852 %*                                                      *
853 \subsection{Miscellaneous}
854 %*                                                      *
855 %*********************************************************
856
857 These two functions are meant to get things out of @IOErrors@.  They don't!
858
859 \begin{code}
860 ioeGetFileName        :: IOError -> Maybe FilePath
861 ioeGetHandle          :: IOError -> Maybe Handle
862
863
864 ioeGetHandle   _ = Nothing -- a stub, essentially
865 ioeGetFileName _ = Nothing -- a stub, essentially
866 \end{code}
867