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