[project @ 2000-01-13 14:33:57 by hwloidl]
[ghc-hetmet.git] / ghc / lib / std / PrelHandle.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1994-1996
3 %
4
5 \section[PrelHandle]{Module @PrelHandle@}
6
7 This module defines Haskell {\em handles} and the basic operations
8 which are supported for them.
9
10 \begin{code}
11 {-# OPTIONS -fno-implicit-prelude -#include "cbits/stgio.h" #-}
12 #include "cbits/stgerror.h"
13
14 #ifndef __HUGS__ /* Hugs just includes this in PreludeBuiltin so no header needed */
15 module PrelHandle where
16
17 import PrelBase
18 import PrelAddr         ( Addr, nullAddr )
19 import PrelArr          ( newVar, readVar, writeVar )
20 import PrelByteArr      ( ByteArray(..) )
21 import PrelRead         ( Read )
22 import PrelList         ( span )
23 import PrelIOBase
24 import PrelException
25 import PrelMaybe        ( Maybe(..) )
26 import PrelEnum
27 import PrelNum          ( toBig, Integer(..), Num(..) )
28 import PrelShow
29 import PrelAddr         ( Addr, nullAddr )
30 import PrelReal         ( toInteger )
31 import PrelPack         ( packString )
32 #ifndef __PARALLEL_HASKELL__
33 import PrelWeak         ( addForeignFinalizer )
34 #endif
35 import Ix
36
37 #ifdef __CONCURRENT_HASKELL__
38 import PrelConc
39 #endif
40
41 #ifndef __PARALLEL_HASKELL__
42 import PrelForeign  ( makeForeignObj )
43 #endif
44
45 #endif /* ndef(__HUGS__) */
46
47 #ifdef __HUGS__
48 #define __CONCURRENT_HASKELL__
49 #define stToIO id
50 #endif
51
52 #ifndef __PARALLEL_HASKELL__
53 #define FILE_OBJECT         ForeignObj
54 #else
55 #define FILE_OBJECT         Addr
56 #endif
57 \end{code}
58
59 %*********************************************************
60 %*                                                      *
61 \subsection{Types @Handle@, @Handle__@}
62 %*                                                      *
63 %*********************************************************
64
65 The @Handle@ and @Handle__@ types are defined in @IOBase@.
66
67 \begin{code}
68 {-# INLINE newHandle   #-}
69 {-# INLINE withHandle #-}
70 newHandle     :: Handle__ -> IO Handle
71
72 #if defined(__CONCURRENT_HASKELL__)
73
74 -- Use MVars for concurrent Haskell
75 newHandle hc  = newMVar hc      >>= \ h ->
76                 return (Handle h)
77 #else 
78
79 -- Use ordinary MutableVars for non-concurrent Haskell
80 newHandle hc  = stToIO (newVar  hc      >>= \ h ->
81                         return (Handle h))
82 #endif
83 \end{code}
84
85 %*********************************************************
86 %*                                                      *
87 \subsection{@withHandle@ operations}
88 %*                                                      *
89 %*********************************************************
90
91 In the concurrent world, handles are locked during use.  This is done
92 by wrapping an MVar around the handle which acts as a mutex over
93 operations on the handle.
94
95 To avoid races, we use the following bracketing operations.  The idea
96 is to obtain the lock, do some operation and replace the lock again,
97 whether the operation succeeded or failed.  We also want to handle the
98 case where the thread receives an exception while processing the IO
99 operation: in these cases we also want to relinquish the lock.
100
101 There are three versions of @withHandle@: corresponding to the three
102 possible combinations of:
103
104         - the operation may side-effect the handle
105         - the operation may return a result
106
107 If the operation generates an error or an exception is raised, the
108 orignal handle is always replaced [ this is the case at the moment,
109 but we might want to revisit this in the future --SDM ].
110
111 \begin{code}
112 #ifdef __CONCURRENT_HASKELL__
113 withHandle :: Handle -> (Handle__ -> IO (Handle__,a)) -> IO a
114 withHandle (Handle h) act = do
115    h_ <- takeMVar h
116    (h',v)  <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
117    putMVar h h'
118    return v
119
120 withHandle_ :: Handle -> (Handle__ -> IO a) -> IO a
121 withHandle_ (Handle h) act = do
122    h_ <- takeMVar h
123    v  <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
124    putMVar h h_
125    return v
126    
127 withHandle__ :: Handle -> (Handle__ -> IO Handle__) -> IO ()
128 withHandle__ (Handle h) act = do
129    h_ <- takeMVar h
130    h'  <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
131    putMVar h h'
132    return ()
133
134 #else
135    -- of questionable value to install this exception
136    -- handler, but let's do it in the non-concurrent
137    -- case too, for now.
138 withHandle (Handle h) act = do
139    h_ <- stToIO (readVar h)
140    v  <- catchException (act h_) (\ ex -> stToIO (writeVar h h_) >> throw ex)
141    return v
142
143 #endif
144 \end{code}
145
146 nullFile__ is only used for closed handles, plugging it in as a null
147 file object reference.
148
149 \begin{code}
150 nullFile__ :: FILE_OBJECT
151 nullFile__ = 
152 #ifndef __PARALLEL_HASKELL__
153     unsafePerformIO (makeForeignObj nullAddr)
154 #else
155     nullAddr
156 #endif
157
158
159 mkClosedHandle__ :: Handle__
160 mkClosedHandle__ = 
161   Handle__ 
162            nullFile__
163            ClosedHandle 
164            NoBuffering
165            "closed file"
166
167 mkErrorHandle__ :: IOError -> Handle__
168 mkErrorHandle__ ioe =
169   Handle__
170            nullFile__ 
171            (ErrorHandle ioe)
172            NoBuffering
173            "error handle"
174 \end{code}
175
176 %*********************************************************
177 %*                                                      *
178 \subsection{Handle Finalizers}
179 %*                                                      *
180 %*********************************************************
181
182 \begin{code}
183 foreign import "libHS_cbits" "freeStdFileObject" unsafe
184         freeStdFileObject :: FILE_OBJECT -> IO ()
185 foreign import "libHS_cbits" "freeFileObject" unsafe
186         freeFileObject :: FILE_OBJECT -> IO ()
187
188 \end{code}
189
190 %*********************************************************
191 %*                                                      *
192 \subsection[StdHandles]{Standard handles}
193 %*                                                      *
194 %*********************************************************
195
196 Three handles are allocated during program initialisation.  The first
197 two manage input or output from the Haskell program's standard input
198 or output channel respectively.  The third manages output to the
199 standard error channel. These handles are initially open.
200
201
202 \begin{code}
203 stdin, stdout, stderr :: Handle
204
205 stdout = unsafePerformIO (do
206     rc <- getLock (1::Int) (1::Int)   -- ConcHask: SAFE, won't block
207     case (rc::Int) of
208        0 -> newHandle (mkClosedHandle__)
209        1 -> do
210             fo <- openStdFile (1::Int) 
211                               (0::Int){-writeable-}  -- ConcHask: SAFE, won't block
212
213 #ifndef __PARALLEL_HASKELL__
214             fo <- makeForeignObj fo
215             addForeignFinalizer fo (freeStdFileObject fo)
216 #endif
217
218 #ifdef __HUGS__
219 /* I dont care what the Haskell report says, in an interactive system,
220  * stdout should be unbuffered by default.
221  */
222             let bm = NoBuffering
223 #else
224             (bm, bf_size)  <- getBMode__ fo
225             mkBuffer__ fo bf_size
226 #endif
227             newHandle (Handle__ fo WriteHandle bm "stdout")
228        _ -> do ioError <- constructError "stdout"
229                newHandle (mkErrorHandle__ ioError)
230   )
231
232 stdin = unsafePerformIO (do
233     rc <- getLock (0::Int) (0::Int)   -- ConcHask: SAFE, won't block
234     case (rc::Int) of
235        0 -> newHandle (mkClosedHandle__)
236        1 -> do
237             fo <- openStdFile (0::Int)
238                               (1::Int){-readable-}  -- ConcHask: SAFE, won't block
239
240 #ifndef __PARALLEL_HASKELL__
241             fo <- makeForeignObj fo
242             addForeignFinalizer fo (freeStdFileObject fo)
243 #endif
244             (bm, bf_size) <- getBMode__ fo
245             mkBuffer__ fo bf_size
246             hdl <- newHandle (Handle__ fo ReadHandle bm "stdin")
247              -- when stdin and stdout are both connected to a terminal, ensure
248              -- that anything buffered on stdout is flushed prior to reading from stdin.
249              -- 
250             hConnectTerms stdout hdl
251             return hdl
252        _ -> do ioError <- constructError "stdin"
253                newHandle (mkErrorHandle__ ioError)
254   )
255
256
257 stderr = unsafePerformIO (do
258     rc <- getLock (2::Int) (1::Int){-writeable-}  -- ConcHask: SAFE, won't block
259     case (rc::Int) of
260        0 -> newHandle (mkClosedHandle__)
261        1 -> do
262             fo <- openStdFile (2::Int)
263                               (0::Int){-writeable-} -- ConcHask: SAFE, won't block
264
265 #ifndef __PARALLEL_HASKELL__
266             fo <- makeForeignObj fo
267             addForeignFinalizer fo (freeStdFileObject fo)
268 #endif
269             hdl <- newHandle (Handle__ fo WriteHandle NoBuffering "stderr")
270             -- when stderr and stdout are both connected to a terminal, ensure
271             -- that anything buffered on stdout is flushed prior to writing to
272             -- stderr.
273             hConnectTo stdout hdl
274             return hdl
275
276        _ -> do ioError <- constructError "stderr"
277                newHandle (mkErrorHandle__ ioError)
278   )
279 \end{code}
280
281 %*********************************************************
282 %*                                                      *
283 \subsection[OpeningClosing]{Opening and Closing Files}
284 %*                                                      *
285 %*********************************************************
286
287 \begin{code}
288 data IOMode      =  ReadMode | WriteMode | AppendMode | ReadWriteMode
289                     deriving (Eq, Ord, Ix, Enum, Read, Show)
290
291 data IOModeEx 
292  = BinaryMode IOMode
293  | TextMode   IOMode
294    deriving (Eq, Read, Show)
295
296 openFile :: FilePath -> IOMode -> IO Handle
297 openFile fp im = openFileEx fp (TextMode im)
298
299 openFileEx :: FilePath -> IOModeEx -> IO Handle
300
301 openFileEx f m = do
302     fo <- primOpenFile (packString f)
303                        (file_mode::Int) 
304                        (binary::Int)     -- ConcHask: SAFE, won't block
305     if fo /= nullAddr then do
306 #ifndef __PARALLEL_HASKELL__
307         fo  <- makeForeignObj fo
308         addForeignFinalizer fo (freeFileObject fo)
309 #endif
310         (bm, bf_size)  <- getBMode__ fo
311         mkBuffer__ fo bf_size
312         newHandle (Handle__ fo htype bm f)
313       else do
314         constructErrorAndFailWithInfo "openFile" f
315   where
316     (imo, binary) =
317       case m of
318         BinaryMode bmo -> (bmo, 1)
319         TextMode tmo   -> (tmo, 0)
320
321     file_mode =
322       case imo of
323            AppendMode    -> 0
324            WriteMode     -> 1
325            ReadMode      -> 2
326            ReadWriteMode -> 3
327
328     htype = case imo of 
329               ReadMode      -> ReadHandle
330               WriteMode     -> WriteHandle
331               AppendMode    -> AppendHandle
332               ReadWriteMode -> ReadWriteHandle
333 \end{code}
334
335 Computation $openFile file mode$ allocates and returns a new, open
336 handle to manage the file {\em file}.  It manages input if {\em mode}
337 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
338 and both input and output if mode is $ReadWriteMode$.
339
340 If the file does not exist and it is opened for output, it should be
341 created as a new file.  If {\em mode} is $WriteMode$ and the file
342 already exists, then it should be truncated to zero length.  The
343 handle is positioned at the end of the file if {\em mode} is
344 $AppendMode$, and otherwise at the beginning (in which case its
345 internal position is 0).
346
347 Implementations should enforce, locally to the Haskell process,
348 multiple-reader single-writer locking on files, which is to say that
349 there may either be many handles on the same file which manage input,
350 or just one handle on the file which manages output.  If any open or
351 semi-closed handle is managing a file for output, no new handle can be
352 allocated for that file.  If any open or semi-closed handle is
353 managing a file for input, new handles can only be allocated if they
354 do not manage output.
355
356 Two files are the same if they have the same absolute name.  An
357 implementation is free to impose stricter conditions.
358
359 \begin{code}
360 hClose :: Handle -> IO ()
361
362 hClose handle =
363     withHandle__ handle $ \ handle_ -> do
364     case haType__ handle_ of 
365       ErrorHandle theError -> ioError theError
366       ClosedHandle         -> return handle_
367       _ -> do
368           rc      <- closeFile (haFO__ handle_)
369                                (1::Int){-flush if you can-}  -- ConcHask: SAFE, won't block
370           {- We explicitly close a file object so that we can be told
371              if there were any errors. Note that after @hClose@
372              has been performed, the ForeignObj embedded in the Handle
373              is still lying around in the heap, so care is taken
374              to avoid closing the file object when the ForeignObj
375              is finalized. (we overwrite the file ptr in the underlying
376              FileObject with a NULL as part of closeFile())
377           -}
378           if rc == (0::Int)
379            then return (handle_{ haType__   = ClosedHandle,
380                                  haFO__     = nullFile__ })
381            else constructErrorAndFail "hClose"
382
383 \end{code}
384
385 Computation $hClose hdl$ makes handle {\em hdl} closed.  Before the
386 computation finishes, any items buffered for output and not already
387 sent to the operating system are flushed as for $flush$.
388
389 %*********************************************************
390 %*                                                      *
391 \subsection[EOF]{Detecting the End of Input}
392 %*                                                      *
393 %*********************************************************
394
395
396 For a handle {\em hdl} which attached to a physical file, $hFileSize
397 hdl$ returns the size of {\em hdl} in terms of the number of items
398 which can be read from {\em hdl}.
399
400 \begin{code}
401 hFileSize :: Handle -> IO Integer
402 hFileSize handle =
403     withHandle_ handle $ \ handle_ -> do
404     case haType__ handle_ of 
405       ErrorHandle theError      -> ioError theError
406       ClosedHandle              -> ioe_closedHandle "hFileSize" handle
407       SemiClosedHandle          -> ioe_closedHandle "hFileSize" handle
408 #ifdef __HUGS__
409       _ -> do
410           mem <- primNewByteArray 8{-sizeof_int64-}
411           rc <- fileSize_int64 (haFO__ handle_) mem  -- ConcHask: SAFE, won't block
412           if rc == 0 then do
413              result <- primReadInt64Array mem 0
414              return (primInt64ToInteger result)
415            else 
416              constructErrorAndFail "hFileSize"
417 #else
418       _ ->
419           -- HACK!  We build a unique MP_INT of the right shape to hold
420           -- a single unsigned word, and we let the C routine 
421           -- change the data bits
422           --
423           case int2Integer# 1# of
424               (# s, d #) -> do
425                 rc <- fileSize (haFO__ handle_) d  -- ConcHask: SAFE, won't block
426                 if rc == (0::Int) then
427                    return (J# s d)
428                  else
429                    constructErrorAndFail "hFileSize"
430 #endif
431 \end{code}
432
433 For a readable handle {\em hdl}, @hIsEOF hdl@ returns
434 @True@ if no further input can be taken from @hdl@ or for a
435 physical file, if the current I/O position is equal to the length of
436 the file.  Otherwise, it returns @False@.
437
438 \begin{code}
439 hIsEOF :: Handle -> IO Bool
440 hIsEOF handle =
441     wantReadableHandle "hIsEOF" handle $ \ handle_ -> do
442     let fo = haFO__ handle_
443     rc      <- mayBlock fo (fileEOF fo)  -- ConcHask: UNSAFE, may block
444     case rc of
445       0 -> return False
446       1 -> return True
447       _ -> constructErrorAndFail "hIsEOF"
448
449 isEOF :: IO Bool
450 isEOF = hIsEOF stdin
451 \end{code}
452
453 %*********************************************************
454 %*                                                      *
455 \subsection[Buffering]{Buffering Operations}
456 %*                                                      *
457 %*********************************************************
458
459 Three kinds of buffering are supported: line-buffering, 
460 block-buffering or no-buffering.  See @IOBase@ for definition
461 and further explanation of what the type represent.
462
463 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
464 handle {\em hdl} on subsequent reads and writes.
465
466 \begin{itemize}
467 \item
468 If {\em mode} is @LineBuffering@, line-buffering should be
469 enabled if possible.
470 \item
471 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
472 should be enabled if possible.  The size of the buffer is {\em n} items
473 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
474 \item
475 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
476 \end{itemize}
477
478 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
479 to @NoBuffering@, then any items in the output buffer are written to
480 the device, and any items in the input buffer are discarded.  The
481 default buffering mode when a handle is opened is
482 implementation-dependent and may depend on the object which is
483 attached to that handle.
484
485 \begin{code}
486 hSetBuffering :: Handle -> BufferMode -> IO ()
487
488 hSetBuffering handle mode =
489     case mode of
490       BlockBuffering (Just n) 
491         | n <= 0 -> ioError
492                          (IOError (Just handle)
493                                   InvalidArgument
494                                   "hSetBuffering"
495                                   ("illegal buffer size " ++ showsPrec 9 n []))  -- 9 => should be parens'ified.
496       _ ->
497           withHandle__ handle $ \ handle_ -> do
498           case haType__ handle_ of
499              ErrorHandle theError -> ioError theError
500              ClosedHandle         -> ioe_closedHandle "hSetBuffering" handle
501              _ -> do
502                 {- Note:
503                     - we flush the old buffer regardless of whether
504                       the new buffer could fit the contents of the old buffer 
505                       or not.
506                     - allow a handle's buffering to change even if IO has
507                       occurred (ANSI C spec. does not allow this, nor did
508                       the previous implementation of IO.hSetBuffering).
509                     - a non-standard extension is to allow the buffering
510                       of semi-closed handles to change [sof 6/98]
511                 -}
512                 let fo = haFO__ handle_
513                 rc <- mayBlock fo (setBuffering fo bsize) -- ConcHask: UNSAFE, may block
514                 if rc == 0 
515                  then do
516                    return (handle_{ haBufferMode__ = mode })
517                  else do
518                    -- Note: failure to change the buffer size will cause old buffer to be flushed.
519                    constructErrorAndFail "hSetBuffering"
520   where
521     bsize :: Int
522     bsize = case mode of
523               NoBuffering             ->  0
524               LineBuffering           -> -1
525               BlockBuffering Nothing  -> -2
526               BlockBuffering (Just n) ->  n
527 \end{code}
528
529 The action @hFlush hdl@ causes any items buffered for output
530 in handle {\em hdl} to be sent immediately to the operating
531 system.
532
533 \begin{code}
534 hFlush :: Handle -> IO () 
535 hFlush handle =
536     wantWriteableHandle "hFlush" handle $ \ handle_ -> do
537     let fo = haFO__ handle_
538     rc      <- mayBlock fo (flushFile fo)   -- ConcHask: UNSAFE, may block
539     if rc == 0 then 
540        return ()
541      else
542        constructErrorAndFail "hFlush"
543
544 \end{code}
545
546
547 %*********************************************************
548 %*                                                      *
549 \subsection[Seeking]{Repositioning Handles}
550 %*                                                      *
551 %*********************************************************
552
553 \begin{code}
554 data HandlePosn
555  = HandlePosn 
556         Handle   -- Q: should this be a weak or strong ref. to the handle?
557                  --    [what's the winning argument for it not being strong? --sof]
558         HandlePosition
559
560 instance Eq HandlePosn where
561     (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
562
563   -- HandlePosition is the Haskell equivalent of POSIX' off_t.
564   -- We represent it as an Integer on the Haskell side, but
565   -- cheat slightly in that hGetPosn calls upon a C helper
566   -- that reports the position back via (merely) an Int.
567 type HandlePosition = Integer
568
569 mkHandlePosn :: Handle -> HandlePosition -> HandlePosn
570 mkHandlePosn h p = HandlePosn h p
571
572 data SeekMode    =  AbsoluteSeek | RelativeSeek | SeekFromEnd
573                     deriving (Eq, Ord, Ix, Enum, Read, Show)
574 \end{code}
575
576 Computation @hGetPosn hdl@ returns the current I/O
577 position of {\em hdl} as an abstract position.  Computation
578 $hSetPosn p$ sets the position of {\em hdl}
579 to a previously obtained position {\em p}.
580
581 \begin{code}
582 hGetPosn :: Handle -> IO HandlePosn
583 hGetPosn handle =
584     wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
585     posn    <- getFilePosn (haFO__ handle_)   -- ConcHask: SAFE, won't block
586     if posn /= -1 then do
587       return (mkHandlePosn handle (fromInt posn))
588      else
589       constructErrorAndFail "hGetPosn"
590
591 hSetPosn :: HandlePosn -> IO () 
592 hSetPosn (HandlePosn handle i@(S# _))   = hSetPosn (HandlePosn handle (toBig i))
593 hSetPosn (HandlePosn handle (J# s# d#)) = 
594     wantSeekableHandle "hSetPosn" handle $ \ handle_ -> do 
595            -- not as silly as it looks: the handle may have been closed in the meantime.
596     let fo = haFO__ handle_
597     rc     <- mayBlock fo (setFilePosn fo (I# s#) d#)    -- ConcHask: UNSAFE, may block
598     if rc == 0 then do
599        return ()
600      else
601         constructErrorAndFail "hSetPosn"
602 \end{code}
603
604 The action @hSeek hdl mode i@ sets the position of handle
605 @hdl@ depending on @mode@.  If @mode@ is
606
607  * AbsoluteSeek - The position of @hdl@ is set to @i@.
608  * RelativeSeek - The position of @hdl@ is set to offset @i@ from
609                   the current position.
610  * SeekFromEnd  - The position of @hdl@ is set to offset @i@ from
611                   the end of the file.
612
613 Some handles may not be seekable (see @hIsSeekable@), or only
614 support a subset of the possible positioning operations (e.g. it may
615 only be possible to seek to the end of a tape, or to a positive
616 offset from the beginning or current position).
617
618 It is not possible to set a negative I/O position, or for a physical
619 file, an I/O position beyond the current end-of-file. 
620
621 Note: 
622  - when seeking using @SeekFromEnd@, positive offsets (>=0) means
623    seeking at or past EOF.
624  - relative seeking on buffered handles can lead to non-obvious results.
625
626 \begin{code}
627 hSeek :: Handle -> SeekMode -> Integer -> IO () 
628 #ifdef __HUGS__
629 hSeek handle mode offset = 
630     wantSeekableHandle "hSeek" handle $ \ handle_ -> do
631     let fo = haFO__ handle_
632     rc      <- mayBlock fo (seekFile fo whence (primIntegerToInt64 offset))  -- ConcHask: UNSAFE, may block
633 #else
634 hSeek handle mode i@(S# _) = hSeek handle mode (toBig i)
635 hSeek handle mode (J# s# d#) =
636     wantSeekableHandle "hSeek" handle $ \ handle_ -> do
637     let fo = haFO__ handle_
638     rc      <- mayBlock fo (seekFile fo whence (I# s#) d#)  -- ConcHask: UNSAFE, may block
639 #endif
640     if rc == 0 then do
641        return ()
642      else
643         constructErrorAndFail "hSeek"
644   where
645     whence :: Int
646     whence = case mode of
647                AbsoluteSeek -> 0
648                RelativeSeek -> 1
649                SeekFromEnd  -> 2
650 \end{code}
651
652 %*********************************************************
653 %*                                                      *
654 \subsection[Query]{Handle Properties}
655 %*                                                      *
656 %*********************************************************
657
658 A number of operations return information about the properties of a
659 handle.  Each of these operations returns $True$ if the
660 handle has the specified property, and $False$
661 otherwise.
662
663 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
664 {\em hdl} is not block-buffered.  Otherwise it returns 
665 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and 
666 $( Just n )$ for block-buffering of {\em n} bytes.
667
668 \begin{code}
669 hIsOpen :: Handle -> IO Bool
670 hIsOpen handle =
671     withHandle_ handle $ \ handle_ -> do
672     case haType__ handle_ of 
673       ErrorHandle theError -> ioError theError
674       ClosedHandle         -> return False
675       SemiClosedHandle     -> return False
676       _                    -> return True
677
678 hIsClosed :: Handle -> IO Bool
679 hIsClosed handle =
680     withHandle_ handle $ \ handle_ -> do
681     case haType__ handle_ of 
682       ErrorHandle theError -> ioError theError
683       ClosedHandle         -> return True
684       _                    -> return False
685
686 {- not defined, nor exported, but mentioned
687    here for documentation purposes:
688
689     hSemiClosed :: Handle -> IO Bool
690     hSemiClosed h = do
691        ho <- hIsOpen h
692        hc <- hIsClosed h
693        return (not (ho || hc))
694 -}
695
696 hIsReadable :: Handle -> IO Bool
697 hIsReadable handle =
698     withHandle_ handle $ \ handle_ -> do
699     case haType__ handle_ of 
700       ErrorHandle theError -> ioError theError
701       ClosedHandle         -> ioe_closedHandle "hIsReadable" handle
702       SemiClosedHandle     -> ioe_closedHandle "hIsReadable" handle
703       htype                -> return (isReadable htype)
704   where
705     isReadable ReadHandle      = True
706     isReadable ReadWriteHandle = True
707     isReadable _               = False
708
709 hIsWritable :: Handle -> IO Bool
710 hIsWritable handle =
711     withHandle_ handle $ \ handle_ -> do
712     case haType__ handle_ of 
713       ErrorHandle theError -> ioError theError
714       ClosedHandle         -> ioe_closedHandle "hIsWritable" handle
715       SemiClosedHandle     -> ioe_closedHandle "hIsWritable" handle
716       htype                -> return (isWritable htype)
717   where
718     isWritable AppendHandle    = True
719     isWritable WriteHandle     = True
720     isWritable ReadWriteHandle = True
721     isWritable _               = False
722
723
724 #ifndef __PARALLEL_HASKELL__
725 getBMode__ :: ForeignObj -> IO (BufferMode, Int)
726 #else
727 getBMode__ :: Addr -> IO (BufferMode, Int)
728 #endif
729 getBMode__ fo = do
730   rc <- getBufferMode fo    -- ConcHask: SAFE, won't block
731   case (rc::Int) of
732     0  -> return (NoBuffering, 0)
733     -1 -> return (LineBuffering, default_buffer_size)
734     -2 -> return (BlockBuffering Nothing, default_buffer_size)
735     -3 -> return (NoBuffering, 0)               -- only happens on un-stat()able files.
736     n  -> return (BlockBuffering (Just n), n)
737  where
738    default_buffer_size :: Int
739    default_buffer_size = (const_BUFSIZ - 1)
740 \end{code}
741
742 Querying how a handle buffers its data:
743
744 \begin{code}
745 hGetBuffering :: Handle -> IO BufferMode
746 hGetBuffering handle = 
747     withHandle_ handle $ \ handle_ -> do
748     case haType__ handle_ of 
749       ErrorHandle theError -> ioError theError
750       ClosedHandle         -> ioe_closedHandle "hGetBuffering" handle
751       _ -> 
752           {-
753            We're being non-standard here, and allow the buffering
754            of a semi-closed handle to be queried.   -- sof 6/98
755           -}
756           return (haBufferMode__ handle_)  -- could be stricter..
757 \end{code}
758
759 \begin{code}
760 hIsSeekable :: Handle -> IO Bool
761 hIsSeekable handle =
762     withHandle_ handle $ \ handle_ -> do
763     case haType__ handle_ of 
764       ErrorHandle theError -> ioError theError
765       ClosedHandle         -> ioe_closedHandle "hIsSeekable" handle
766       SemiClosedHandle     -> ioe_closedHandle "hIsSeekable" handle
767       AppendHandle         -> return False
768       _ -> do
769           rc <- seekFileP (haFO__ handle_)   -- ConcHask: SAFE, won't block
770           case (rc::Int) of
771             0 -> return False
772             1 -> return True
773             _ -> constructErrorAndFail "hIsSeekable"
774 \end{code}
775
776
777 %*********************************************************
778 %*                                                      *
779 \subsection{Changing echo status}
780 %*                                                      *
781 %*********************************************************
782
783 Non-standard GHC extension is to allow the echoing status
784 of a handles connected to terminals to be reconfigured:
785
786 \begin{code}
787 hSetEcho :: Handle -> Bool -> IO ()
788 hSetEcho handle on = do
789     isT   <- hIsTerminalDevice handle
790     if not isT
791      then return ()
792      else
793       withHandle_ handle $ \ handle_ -> do
794       case haType__ handle_ of 
795          ErrorHandle theError -> ioError theError
796          ClosedHandle         -> ioe_closedHandle "hSetEcho" handle
797          _ -> do
798             rc <- setTerminalEcho (haFO__ handle_) (if on then 1 else 0)  -- ConcHask: SAFE, won't block
799             if rc /= ((-1)::Int)
800              then return ()
801              else constructErrorAndFail "hSetEcho"
802
803 hGetEcho :: Handle -> IO Bool
804 hGetEcho handle = do
805     isT   <- hIsTerminalDevice handle
806     if not isT
807      then return False
808      else
809        withHandle_ handle $ \ handle_ -> do
810        case haType__ handle_ of 
811          ErrorHandle theError -> ioError theError
812          ClosedHandle         -> ioe_closedHandle "hGetEcho" handle
813          _ -> do
814             rc <- getTerminalEcho (haFO__ handle_)  -- ConcHask: SAFE, won't block
815             case (rc::Int) of
816               1 -> return True
817               0 -> return False
818               _ -> constructErrorAndFail "hSetEcho"
819
820 hIsTerminalDevice :: Handle -> IO Bool
821 hIsTerminalDevice handle = do
822     withHandle_ handle $ \ handle_ -> do
823      case haType__ handle_ of 
824        ErrorHandle theError -> ioError theError
825        ClosedHandle         -> ioe_closedHandle "hIsTerminalDevice" handle
826        _ -> do
827           rc <- isTerminalDevice (haFO__ handle_)   -- ConcHask: SAFE, won't block
828           case (rc::Int) of
829             1 -> return True
830             0 -> return False
831             _ -> constructErrorAndFail "hIsTerminalDevice"
832 \end{code}
833
834 \begin{code}
835 hConnectTerms :: Handle -> Handle -> IO ()
836 hConnectTerms hW hR = hConnectHdl_ hW hR 1{-check if they're both coming connected to ttys-}
837
838 hConnectTo :: Handle -> Handle -> IO ()
839 hConnectTo hW hR = hConnectHdl_ hW hR 0{-connect regardless-}
840
841 hConnectHdl_ :: Handle -> Handle -> Int -> IO ()
842 hConnectHdl_ hW hR is_tty =
843   wantRWHandle "hConnectTo" hW $ \ hW_ ->
844   wantRWHandle "hConnectTo" hR $ \ hR_ -> do
845   setConnectedTo (haFO__ hR_) (haFO__ hW_) is_tty  -- ConcHask: SAFE, won't block
846
847 #ifndef __PARALLEL_HASKELL__
848 #define FILE_OBJECT     ForeignObj
849 #else
850 #define FILE_OBJECT     Addr
851 #endif
852
853 \end{code}
854
855 As an extension, we also allow characters to be pushed back.
856 Like ANSI C stdio, we guarantee no more than one character of
857 pushback. (For unbuffered channels, the (default) push-back limit is
858 2 chars tho.)
859
860 \begin{code}
861 hUngetChar :: Handle -> Char -> IO ()
862 hUngetChar handle c = 
863     wantReadableHandle "hLookAhead" handle $ \ handle_ -> do
864     rc      <- ungetChar (haFO__ handle_) c  -- ConcHask: SAFE, won't block
865     if rc == ((-1)::Int)
866      then constructErrorAndFail "hUngetChar"
867      else return ()
868
869 \end{code}
870
871
872 Hoisting files in in one go is sometimes useful, so we support
873 this as an extension:
874
875 \begin{code}
876 -- in one go, read file into an externally allocated buffer.
877 slurpFile :: FilePath -> IO (Addr, Int)
878 slurpFile fname = do
879   handle <- openFile fname ReadMode
880   sz     <- hFileSize handle
881   if sz > toInteger (maxBound::Int) then 
882     ioError (userError "slurpFile: file too big")
883    else do
884      let sz_i = fromInteger sz
885      chunk <- allocMemory__ sz_i
886      if chunk == nullAddr 
887       then do
888         hClose handle
889         constructErrorAndFail "slurpFile"
890       else do
891         rc <- withHandle_ handle ( \ handle_ -> do
892           let fo = haFO__ handle_
893           mayBlock fo (readChunk fo chunk sz_i)    -- ConcHask: UNSAFE, may block.
894          )
895         hClose handle
896         if rc < (0::Int)
897          then constructErrorAndFail "slurpFile"
898          else return (chunk, rc)
899
900 #ifndef __HUGS__ /* Hugs' Prelude doesn't need this */
901 hFillBufBA :: Handle -> ByteArray Int -> Int -> IO Int
902 hFillBufBA handle buf sz
903   | sz <= 0 = ioError (IOError (Just handle)
904                             InvalidArgument
905                             "hFillBufBA"
906                             ("illegal buffer size " ++ showsPrec 9 sz []))  -- 9 => should be parens'ified.
907   | otherwise = 
908     wantReadableHandle "hFillBufBA" handle $ \ handle_ -> do
909     let fo  = haFO__ handle_
910     rc      <- mayBlock fo (readChunkBA fo buf sz)    -- ConcHask: UNSAFE, may block.
911     if rc >= (0::Int)
912      then return rc
913      else constructErrorAndFail "hFillBufBA"
914 #endif
915
916 hFillBuf :: Handle -> Addr -> Int -> IO Int
917 hFillBuf handle buf sz
918   | sz <= 0 = ioError (IOError (Just handle)
919                             InvalidArgument
920                             "hFillBuf"
921                             ("illegal buffer size " ++ showsPrec 9 sz []))  -- 9 => should be parens'ified.
922   | otherwise = 
923     wantReadableHandle "hFillBuf" handle $ \ handle_ -> do
924     let fo  = haFO__ handle_
925     rc      <- mayBlock fo (readChunk fo buf sz)    -- ConcHask: UNSAFE, may block.
926     if rc >= 0
927      then return rc
928      else constructErrorAndFail "hFillBuf"
929
930 \end{code}
931
932 The @hPutBuf hdl buf len@ action writes an already packed sequence of
933 bytes to the file/channel managed by @hdl@ - non-standard.
934
935 \begin{code}
936 hPutBuf :: Handle -> Addr -> Int -> IO ()
937 hPutBuf handle buf len = 
938     wantWriteableHandle "hPutBuf" handle $ \ handle_ -> do
939     let fo  = haFO__ handle_
940     rc      <- mayBlock fo (writeBuf fo buf len)  -- ConcHask: UNSAFE, may block.
941     if rc == (0::Int)
942      then return ()
943      else constructErrorAndFail "hPutBuf"
944
945 #ifndef __HUGS__ /* An_ one Hugs doesn't provide */
946 hPutBufBA :: Handle -> ByteArray Int -> Int -> IO ()
947 hPutBufBA handle buf len =
948     wantWriteableHandle "hPutBufBA" handle $ \ handle_ -> do
949     let fo = haFO__ handle_
950     rc      <- mayBlock fo (writeBufBA fo buf len)  -- ConcHask: UNSAFE, may block.
951     if rc == (0::Int)
952      then return ()
953      else constructErrorAndFail "hPutBuf"
954 #endif
955 \end{code}
956
957 Sometimes it's useful to get at the file descriptor that
958 the Handle contains..
959
960 \begin{code}
961 getHandleFd :: Handle -> IO Int
962 getHandleFd handle =
963     withHandle_ handle $ \ handle_ -> do
964     case (haType__ handle_) of
965       ErrorHandle theError -> ioError theError
966       ClosedHandle         -> ioe_closedHandle "getHandleFd" handle
967       _ -> do
968           fd <- getFileFd (haFO__ handle_)
969           return fd
970 \end{code}
971
972
973 %*********************************************************
974 %*                                                      *
975 \subsection{Miscellaneous}
976 %*                                                      *
977 %*********************************************************
978
979 These three functions are meant to get things out of @IOErrors@.
980
981 (ToDo: improve!)
982
983 \begin{code}
984 ioeGetFileName        :: IOError -> Maybe FilePath
985 ioeGetErrorString     :: IOError -> String
986 ioeGetHandle          :: IOError -> Maybe Handle
987
988 ioeGetHandle   (IOError h _ _ _)   = h
989 ioeGetErrorString (IOError _ iot _ str) =
990  case iot of
991    EOF -> "end of file"
992    _   -> str
993
994 ioeGetFileName (IOError _ _  _ str) = 
995  case span (/=':') str of
996    (_,[])  -> Nothing
997    (fs,_)  -> Just fs
998
999 \end{code}
1000
1001 'Top-level' IO actions want to catch exceptions (e.g., forkIO and 
1002 PrelMain.mainIO) and report them - topHandler is the exception
1003 handler they should use for this:
1004
1005 \begin{code}
1006 -- make sure we handle errors while reporting the error!
1007 -- (e.g. evaluating the string passed to 'error' might generate
1008 --  another error, etc.)
1009 topHandler :: Bool -> Exception -> IO ()
1010 topHandler bombOut err = catchException (real_handler bombOut err) (topHandler bombOut)
1011
1012 real_handler :: Bool -> Exception -> IO ()
1013 real_handler bombOut ex =
1014   case ex of
1015         AsyncException StackOverflow -> reportStackOverflow bombOut
1016         ErrorCall s -> reportError bombOut s
1017         other       -> reportError bombOut (showsPrec 0 other "\n")
1018
1019 reportStackOverflow :: Bool -> IO ()
1020 reportStackOverflow bombOut = do
1021    (hFlush stdout) `catchException` (\ _ -> return ())
1022    callStackOverflowHook
1023    if bombOut then
1024      stg_exit 2
1025     else
1026      return ()
1027
1028 reportError :: Bool -> String -> IO ()
1029 reportError bombOut str = do
1030    (hFlush stdout) `catchException` (\ _ -> return ())
1031    let bs@(ByteArray _ len _) = packString str
1032    writeErrString addrOf_ErrorHdrHook bs len
1033    if bombOut then
1034      stg_exit 1
1035     else
1036      return ()
1037
1038 foreign label "ErrorHdrHook" 
1039         addrOf_ErrorHdrHook :: Addr
1040
1041 foreign import ccall "writeErrString__" unsafe
1042         writeErrString :: Addr -> ByteArray Int -> Int -> IO ()
1043
1044 foreign import ccall "stackOverflow"
1045         callStackOverflowHook :: IO ()
1046
1047 foreign import ccall "stg_exit"
1048         stg_exit :: Int -> IO ()
1049 \end{code}
1050
1051
1052 A number of operations want to get at a readable or writeable handle, and fail
1053 if it isn't:
1054
1055 \begin{code}
1056 wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1057 wantReadableHandle fun handle act = 
1058     withHandle_ handle $ \ handle_ -> do
1059     case haType__ handle_ of 
1060       ErrorHandle theError -> ioError theError
1061       ClosedHandle         -> ioe_closedHandle fun handle
1062       SemiClosedHandle     -> ioe_closedHandle fun handle
1063       AppendHandle         -> ioError not_readable_error
1064       WriteHandle          -> ioError not_readable_error
1065       _                    -> act handle_
1066   where
1067    not_readable_error = 
1068            IOError (Just handle) IllegalOperation fun   
1069                    ("handle is not open for reading")
1070
1071 wantWriteableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1072 wantWriteableHandle fun handle act = 
1073     withHandle_ handle $ \ handle_ -> do
1074     case haType__ handle_ of 
1075       ErrorHandle theError -> ioError theError
1076       ClosedHandle         -> ioe_closedHandle fun handle
1077       SemiClosedHandle     -> ioe_closedHandle fun handle
1078       ReadHandle           -> ioError not_writeable_error
1079       _                    -> act handle_
1080   where
1081    not_writeable_error = 
1082            IOError (Just handle) IllegalOperation fun
1083                    ("handle is not open for writing")
1084
1085 wantRWHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1086 wantRWHandle fun handle act = 
1087     withHandle_ handle $ \ handle_ -> do
1088     case haType__ handle_ of 
1089       ErrorHandle theError -> ioError theError
1090       ClosedHandle         -> ioe_closedHandle fun handle
1091       SemiClosedHandle     -> ioe_closedHandle fun handle
1092       _                    -> act handle_
1093
1094 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1095 wantSeekableHandle fun handle act =
1096     withHandle_ handle $ \ handle_ -> do
1097     case haType__ handle_ of 
1098       ErrorHandle theError -> ioError theError
1099       ClosedHandle         -> ioe_closedHandle fun handle
1100       SemiClosedHandle     -> ioe_closedHandle fun handle
1101       _                    -> act handle_
1102   where
1103    not_seekable_error = 
1104            IOError (Just handle) 
1105                    IllegalOperation fun
1106                    ("handle is not seekable")
1107
1108 \end{code}
1109
1110 Internal function for creating an @IOError@ representing the
1111 access to a closed file.
1112
1113 \begin{code}
1114 ioe_closedHandle :: String -> Handle -> IO a
1115 ioe_closedHandle fun h = ioError (IOError (Just h) IllegalOperation fun "handle is closed")
1116 \end{code}
1117
1118 Internal helper functions for Concurrent Haskell implementation
1119 of IO:
1120
1121 \begin{code}
1122 #ifndef __PARALLEL_HASKELL__
1123 mayBlock :: ForeignObj -> IO Int -> IO Int
1124 #else
1125 mayBlock :: Addr  -> IO Int -> IO Int
1126 #endif
1127
1128 mayBlock fo act = do
1129    rc <- act
1130    case rc of
1131      -5 -> do  -- (possibly blocking) read
1132         fd <- getFileFd fo
1133         threadWaitRead fd
1134         mayBlock fo act  -- input available, re-try
1135      -6 -> do  -- (possibly blocking) write
1136         fd <- getFileFd fo
1137         threadWaitWrite fd
1138         mayBlock fo act  -- output possible
1139      -7 -> do  -- (possibly blocking) write on connected handle
1140         fd <- getConnFileFd fo
1141         threadWaitWrite fd
1142         mayBlock fo act  -- output possible
1143      _ -> do
1144         return rc
1145 \end{code}
1146
1147 Foreign import declarations of helper functions:
1148
1149 \begin{code}
1150
1151 #ifdef __HUGS__
1152 type Bytes = PrimByteArray RealWorld
1153 #else
1154 type Bytes = ByteArray#
1155 #endif
1156
1157 foreign import "libHS_cbits" "inputReady"  unsafe
1158            inputReady       :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1159 foreign import "libHS_cbits" "fileGetc"    unsafe
1160            fileGetc         :: FILE_OBJECT -> IO Int
1161 foreign import "libHS_cbits" "fileLookAhead" unsafe
1162            fileLookAhead    :: FILE_OBJECT -> IO Int
1163 foreign import "libHS_cbits" "readBlock" unsafe
1164            readBlock        :: FILE_OBJECT -> IO Int
1165 foreign import "libHS_cbits" "readLine" unsafe
1166            readLine         :: FILE_OBJECT -> IO Int
1167 foreign import "libHS_cbits" "readChar" unsafe
1168            readChar         :: FILE_OBJECT -> IO Int
1169 foreign import "libHS_cbits" "writeFileObject" unsafe
1170            writeFileObject  :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1171 foreign import "libHS_cbits" "filePutc" unsafe
1172            filePutc         :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1173 foreign import "libHS_cbits" "getBufStart" unsafe
1174            getBufStart      :: FILE_OBJECT -> Int -> IO Addr
1175 foreign import "libHS_cbits" "getWriteableBuf" unsafe
1176            getWriteableBuf  :: FILE_OBJECT -> IO Addr
1177 foreign import "libHS_cbits" "getBufWPtr" unsafe
1178            getBufWPtr       :: FILE_OBJECT -> IO Int
1179 foreign import "libHS_cbits" "setBufWPtr" unsafe
1180            setBufWPtr       :: FILE_OBJECT -> Int -> IO ()
1181 foreign import "libHS_cbits" "closeFile" unsafe
1182            closeFile        :: FILE_OBJECT -> Int{-Flush-} -> IO Int{-ret code-}
1183 foreign import "libHS_cbits" "fileEOF" unsafe
1184            fileEOF           :: FILE_OBJECT -> IO Int{-ret code-}
1185 foreign import "libHS_cbits" "setBuffering" unsafe
1186            setBuffering      :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1187 foreign import "libHS_cbits" "flushFile" unsafe
1188            flushFile         :: FILE_OBJECT -> IO Int{-ret code-}
1189 foreign import "libHS_cbits" "flushConnectedBuf" unsafe
1190            flushConnectedBuf :: FILE_OBJECT -> IO ()
1191 foreign import "libHS_cbits" "getBufferMode" unsafe
1192            getBufferMode     :: FILE_OBJECT -> IO Int{-ret code-}
1193 #ifdef __HUGS__
1194 foreign import "libHS_cbits" "seekFile_int64" unsafe
1195            seekFile    :: FILE_OBJECT -> Int -> Int64 -> IO Int
1196 #else
1197 foreign import "libHS_cbits" "seekFile" unsafe
1198            seekFile    :: FILE_OBJECT -> Int -> Int -> Bytes -> IO Int
1199 #endif 
1200
1201 foreign import "libHS_cbits" "seekFileP" unsafe
1202            seekFileP        :: FILE_OBJECT -> IO Int{-ret code-}
1203 foreign import "libHS_cbits" "setTerminalEcho" unsafe
1204            setTerminalEcho  :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1205 foreign import "libHS_cbits" "getTerminalEcho" unsafe
1206            getTerminalEcho  :: FILE_OBJECT -> IO Int{-ret code-}
1207 foreign import "libHS_cbits" "isTerminalDevice" unsafe
1208            isTerminalDevice :: FILE_OBJECT -> IO Int{-ret code-}
1209 foreign import "libHS_cbits" "setConnectedTo" unsafe
1210            setConnectedTo   :: FILE_OBJECT -> FILE_OBJECT -> Int -> IO ()
1211 foreign import "libHS_cbits" "ungetChar" unsafe
1212            ungetChar        :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1213 foreign import "libHS_cbits" "readChunk" unsafe
1214            readChunk        :: FILE_OBJECT -> Addr -> Int -> IO Int{-ret code-}
1215 foreign import "libHS_cbits" "readChunk" unsafe
1216            readChunkBA      :: FILE_OBJECT -> ByteArray Int -> Int -> IO Int{-ret code-}
1217 foreign import "libHS_cbits" "writeBuf" unsafe
1218            writeBuf         :: FILE_OBJECT -> Addr -> Int -> IO Int{-ret code-}
1219 #ifndef __HUGS__
1220 foreign import "libHS_cbits" "writeBufBA" unsafe
1221            writeBufBA       :: FILE_OBJECT -> ByteArray Int -> Int -> IO Int{-ret code-}
1222 #endif
1223 foreign import "libHS_cbits" "getFileFd" unsafe
1224            getFileFd        :: FILE_OBJECT -> IO Int{-fd-}
1225 #ifdef __HUGS__
1226 foreign import "libHS_cbits" "fileSize_int64" unsafe
1227            fileSize_int64   :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1228 #else
1229 foreign import "libHS_cbits" "fileSize" unsafe
1230            fileSize  :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1231 #endif
1232
1233 foreign import "libHS_cbits" "getFilePosn" unsafe
1234            getFilePosn      :: FILE_OBJECT -> IO Int
1235 foreign import "libHS_cbits" "setFilePosn" unsafe
1236            setFilePosn      :: FILE_OBJECT -> Int -> ByteArray# -> IO Int
1237 foreign import "libHS_cbits" "getConnFileFd" unsafe
1238            getConnFileFd    :: FILE_OBJECT -> IO Int{-fd-}
1239 foreign import "libHS_cbits" "getLock" unsafe
1240            getLock  :: Int{-Fd-} -> Int{-exclusive-} -> IO Int{-return code-}
1241 foreign import "libHS_cbits" "openStdFile" unsafe
1242            openStdFile      :: Int{-fd-} -> Int{-Readable?-} -> IO Addr{-file obj-}
1243 foreign import "libHS_cbits" "openFile" unsafe
1244            primOpenFile         :: ByteArray Int{-CString-}
1245                                 -> Int{-How-}
1246                                 -> Int{-Binary-}
1247                                 -> IO Addr {-file obj-}
1248 foreign import "libHS_cbits" "const_BUFSIZ" unsafe
1249            const_BUFSIZ          :: Int
1250
1251 foreign import "libHS_cbits" "setBinaryMode__" 
1252            setBinaryMode :: FILE_OBJECT -> Int -> IO Int
1253 \end{code}
1254
1255