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