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