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