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