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