[project @ 2001-01-10 16:28:15 by qrczak]
[ghc-hetmet.git] / ghc / lib / std / PrelHandle.lhs
1 % ------------------------------------------------------------------------------
2 % $Id: PrelHandle.lhs,v 1.64 2001/01/10 16:28:15 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 "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 (UserError _) = Nothing
942 ioeGetHandle _ = error "IO.ioeGetHandle: not an IO error"
943
944 ioeGetErrorString (IOException (IOError _ iot _ str)) =
945   case iot of
946     EOF -> "end of file"
947     _   -> str
948 ioeGetErrorString (UserError str) = str
949 ioeGetErrorString _ = error "IO.ioeGetErrorString: not an IO error"
950
951 ioeGetFileName (IOException (IOError _ _  _ str)) = 
952   case break (== ':') str of
953     (_, [])      -> Nothing
954     (_, _:' ':fs)-> Just fs
955 ioeGetFileName (UserError _) = Nothing
956 ioeGetFileName _ = error "IO.ioeGetFileName: not an IO error"
957 \end{code}
958
959 'Top-level' IO actions want to catch exceptions (e.g., forkIO and 
960 PrelMain.mainIO) and report them - topHandler is the exception
961 handler they should use for this:
962
963 \begin{code}
964 -- make sure we handle errors while reporting the error!
965 -- (e.g. evaluating the string passed to 'error' might generate
966 --  another error, etc.)
967 topHandler :: Bool -> Exception -> IO ()
968 topHandler bombOut err = catchException (real_handler bombOut err) (topHandler bombOut)
969
970 real_handler :: Bool -> Exception -> IO ()
971 real_handler bombOut ex =
972   case ex of
973         AsyncException StackOverflow -> reportStackOverflow bombOut
974         ErrorCall s -> reportError bombOut s
975         other       -> reportError bombOut (showsPrec 0 other "\n")
976
977 reportStackOverflow :: Bool -> IO ()
978 reportStackOverflow bombOut = do
979    (hFlush stdout) `catchException` (\ _ -> return ())
980    callStackOverflowHook
981    if bombOut then
982      stg_exit 2
983     else
984      return ()
985
986 reportError :: Bool -> String -> IO ()
987 reportError bombOut str = do
988    (hFlush stdout) `catchException` (\ _ -> return ())
989    let bs@(ByteArray _ len _) = packString str
990    writeErrString addrOf_ErrorHdrHook bs len
991    if bombOut then
992      stg_exit 1
993     else
994      return ()
995
996 foreign import ccall "addrOf_ErrorHdrHook" unsafe
997         addrOf_ErrorHdrHook :: Addr
998
999 foreign import ccall "writeErrString__" unsafe
1000         writeErrString :: Addr -> ByteArray Int -> Int -> IO ()
1001
1002 -- SUP: Are the hooks allowed to re-enter Haskell land? If yes, remove the unsafe below.
1003 foreign import ccall "stackOverflow" unsafe
1004         callStackOverflowHook :: IO ()
1005
1006 foreign import ccall "stg_exit" unsafe
1007         stg_exit :: Int -> IO ()
1008 \end{code}
1009
1010
1011 A number of operations want to get at a readable or writeable handle, and fail
1012 if it isn't:
1013
1014 \begin{code}
1015 wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1016 wantReadableHandle fun handle act = 
1017     withHandle_ handle $ \ handle_ -> do
1018     case haType__ handle_ of 
1019       ClosedHandle         -> ioe_closedHandle fun handle
1020       SemiClosedHandle     -> ioe_closedHandle fun handle
1021       AppendHandle         -> ioException not_readable_error
1022       WriteHandle          -> ioException not_readable_error
1023       _                    -> act handle_
1024   where
1025    not_readable_error = 
1026            IOError (Just handle) IllegalOperation fun   
1027                    ("handle is not open for reading")
1028
1029 wantWriteableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1030 wantWriteableHandle fun handle act = 
1031     withHandle_ handle $ \ handle_ ->
1032         checkWriteableHandle fun handle handle_ (act handle_)
1033
1034 wantWriteableHandle_ :: String -> Handle -> (Handle__ -> IO (Handle__, a)) -> IO a
1035 wantWriteableHandle_ fun handle act = 
1036     withHandle handle $ \ handle_ -> 
1037         checkWriteableHandle fun handle handle_ (act handle_)
1038
1039 checkWriteableHandle fun handle handle_ act
1040   = case haType__ handle_ of 
1041       ClosedHandle         -> ioe_closedHandle fun handle
1042       SemiClosedHandle     -> ioe_closedHandle fun handle
1043       ReadHandle           -> ioError not_writeable_error
1044       _                    -> act
1045   where
1046    not_writeable_error = 
1047            IOException (IOError (Just handle) IllegalOperation fun
1048                                         ("handle is not open for writing"))
1049
1050 wantRWHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1051 wantRWHandle fun handle act = 
1052     withHandle_ handle $ \ handle_ -> do
1053     case haType__ handle_ of 
1054       ClosedHandle         -> ioe_closedHandle fun handle
1055       SemiClosedHandle     -> ioe_closedHandle fun handle
1056       _                    -> act handle_
1057
1058 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1059 wantSeekableHandle fun handle act =
1060     withHandle_ handle $ \ handle_ -> do
1061     case haType__ handle_ of 
1062       ClosedHandle         -> ioe_closedHandle fun handle
1063       SemiClosedHandle     -> ioe_closedHandle fun handle
1064       _                    -> act handle_
1065 \end{code}
1066
1067 Internal function for creating an @IOError@ representing the
1068 access to a closed file.
1069
1070 \begin{code}
1071 ioe_closedHandle :: String -> Handle -> IO a
1072 ioe_closedHandle fun h = ioError (IOException (IOError (Just h) IllegalOperation fun 
1073                                         "handle is closed"))
1074 \end{code}
1075
1076 Internal helper functions for Concurrent Haskell implementation
1077 of IO:
1078
1079 \begin{code}
1080 mayBlock :: FILE_OBJECT -> IO Int -> IO Int
1081 mayBlock fo act = do
1082    rc <- act
1083    case rc of
1084      -5 -> do  -- (possibly blocking) read
1085         fd <- getFileFd fo
1086         threadWaitRead fd
1087         mayBlock fo act  -- input available, re-try
1088      -6 -> do  -- (possibly blocking) write
1089         fd <- getFileFd fo
1090         threadWaitWrite fd
1091         mayBlock fo act  -- output possible
1092      -7 -> do  -- (possibly blocking) write on connected handle
1093         fd <- getConnFileFd fo
1094         threadWaitWrite fd
1095         mayBlock fo act  -- output possible
1096      _ -> do
1097         return rc
1098
1099 data MayBlock a
1100   = BlockRead Int
1101   | BlockWrite Int
1102   | NoBlock a
1103
1104 mayBlockRead :: String -> Handle -> (FILE_OBJECT -> IO Int) -> IO Int
1105 mayBlockRead fname handle fn = do
1106     r <- wantReadableHandle fname handle $ \ handle_ -> do
1107          let fo = haFO__ handle_
1108          rc <- fn fo
1109          case rc of
1110            -5 -> do  -- (possibly blocking) read
1111              fd <- getFileFd fo
1112              return (BlockRead fd)
1113            -6 -> do  -- (possibly blocking) write
1114              fd <- getFileFd fo
1115              return (BlockWrite fd)
1116            -7 -> do  -- (possibly blocking) write on connected handle
1117              fd <- getConnFileFd fo
1118              return (BlockWrite fd)
1119            _ ->
1120              if rc >= 0
1121                   then return (NoBlock rc)
1122                   else constructErrorAndFail fname
1123     case r of
1124         BlockRead fd -> do
1125            threadWaitRead fd
1126            mayBlockRead fname handle fn
1127         BlockWrite fd -> do
1128            threadWaitWrite fd
1129            mayBlockRead fname handle fn
1130         NoBlock c -> return c
1131
1132 mayBlockRead' :: String -> Handle
1133         -> (FILE_OBJECT -> IO Int)
1134         -> (FILE_OBJECT -> Int -> IO a)
1135         -> IO a
1136 mayBlockRead' fname handle fn io = do
1137     r <- wantReadableHandle fname handle $ \ handle_ -> do
1138          let fo = haFO__ handle_
1139          rc <- fn fo
1140          case rc of
1141            -5 -> do  -- (possibly blocking) read
1142              fd <- getFileFd fo
1143              return (BlockRead fd)
1144            -6 -> do  -- (possibly blocking) write
1145              fd <- getFileFd fo
1146              return (BlockWrite fd)
1147            -7 -> do  -- (possibly blocking) write on connected handle
1148              fd <- getConnFileFd fo
1149              return (BlockWrite fd)
1150            _ ->
1151              if rc >= 0
1152                   then do a <- io fo rc 
1153                           return (NoBlock a)
1154                   else constructErrorAndFail fname
1155     case r of
1156         BlockRead fd -> do
1157            threadWaitRead fd
1158            mayBlockRead' fname handle fn io
1159         BlockWrite fd -> do
1160            threadWaitWrite fd
1161            mayBlockRead' fname handle fn io
1162         NoBlock c -> return c
1163
1164 mayBlockWrite :: String -> Handle -> (FILE_OBJECT -> IO Int) -> IO Int
1165 mayBlockWrite fname handle fn = do
1166     r <- wantWriteableHandle fname handle $ \ handle_ -> do
1167          let fo = haFO__ handle_
1168          rc <- fn fo
1169          case rc of
1170            -5 -> do  -- (possibly blocking) read
1171              fd <- getFileFd fo
1172              return (BlockRead fd)
1173            -6 -> do  -- (possibly blocking) write
1174              fd <- getFileFd fo
1175              return (BlockWrite fd)
1176            -7 -> do  -- (possibly blocking) write on connected handle
1177              fd <- getConnFileFd fo
1178              return (BlockWrite fd)
1179            _ ->
1180              if rc >= 0
1181                   then return (NoBlock rc)
1182                   else constructErrorAndFail fname
1183     case r of
1184         BlockRead fd -> do
1185            threadWaitRead fd
1186            mayBlockWrite fname handle fn
1187         BlockWrite fd -> do
1188            threadWaitWrite fd
1189            mayBlockWrite fname handle fn
1190         NoBlock c -> return c
1191 \end{code}
1192
1193 Foreign import declarations of helper functions:
1194
1195 \begin{code}
1196
1197 #ifdef __HUGS__
1198 type Bytes = PrimByteArray RealWorld
1199 #else
1200 type Bytes = ByteArray#
1201 #endif
1202
1203 foreign import "libHS_cbits" "inputReady"  unsafe
1204            inputReady       :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1205 foreign import "libHS_cbits" "fileGetc"    unsafe
1206            fileGetc         :: FILE_OBJECT -> IO Int
1207 foreign import "libHS_cbits" "fileLookAhead" unsafe
1208            fileLookAhead    :: FILE_OBJECT -> IO Int
1209 foreign import "libHS_cbits" "readBlock" unsafe
1210            readBlock        :: FILE_OBJECT -> IO Int
1211 foreign import "libHS_cbits" "readLine" unsafe
1212            readLine         :: FILE_OBJECT -> IO Int
1213 foreign import "libHS_cbits" "readChar" unsafe
1214            readChar         :: FILE_OBJECT -> IO Int
1215 foreign import "libHS_cbits" "writeFileObject" unsafe
1216            writeFileObject  :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1217 foreign import "libHS_cbits" "filePutc" unsafe
1218            filePutc         :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1219 foreign import "libHS_cbits" "write_" unsafe
1220            write_           :: FILE_OBJECT -> Addr -> Int -> IO Int{-ret code-}
1221 foreign import "libHS_cbits" "getBufStart" unsafe
1222            getBufStart      :: FILE_OBJECT -> Int -> IO Addr
1223 foreign import "libHS_cbits" "getWriteableBuf" unsafe
1224            getWriteableBuf  :: FILE_OBJECT -> IO Addr
1225 foreign import "libHS_cbits" "getBuf" unsafe
1226            getBuf           :: FILE_OBJECT -> IO Addr
1227 foreign import "libHS_cbits" "getBufWPtr" unsafe
1228            getBufWPtr       :: FILE_OBJECT -> IO Int
1229 foreign import "libHS_cbits" "setBufWPtr" unsafe
1230            setBufWPtr       :: FILE_OBJECT -> Int -> IO ()
1231 foreign import "libHS_cbits" "closeFile" unsafe
1232            closeFile        :: FILE_OBJECT -> Int{-Flush-} -> IO Int{-ret code-}
1233 foreign import "libHS_cbits" "fileEOF" unsafe
1234            fileEOF           :: FILE_OBJECT -> IO Int{-ret code-}
1235 foreign import "libHS_cbits" "setBuffering" unsafe
1236            setBuffering      :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1237 foreign import "libHS_cbits" "flushFile" unsafe
1238            flushFile         :: FILE_OBJECT -> IO Int{-ret code-}
1239 foreign import "libHS_cbits" "flushConnectedBuf" unsafe
1240            flushConnectedBuf :: FILE_OBJECT -> IO ()
1241 foreign import "libHS_cbits" "getBufferMode" unsafe
1242            getBufferMode     :: FILE_OBJECT -> IO Int{-ret code-}
1243 #ifdef __HUGS__
1244 foreign import "libHS_cbits" "seekFile_int64" unsafe
1245            seekFile    :: FILE_OBJECT -> Int -> Int64 -> IO Int
1246 #else
1247 foreign import "libHS_cbits" "seekFile" unsafe
1248            seekFile    :: FILE_OBJECT -> Int -> Int -> Bytes -> IO Int
1249 #endif 
1250
1251 foreign import "libHS_cbits" "seekFileP" unsafe
1252            seekFileP        :: FILE_OBJECT -> IO Int{-ret code-}
1253 foreign import "libHS_cbits" "setTerminalEcho" unsafe
1254            setTerminalEcho  :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1255 foreign import "libHS_cbits" "getTerminalEcho" unsafe
1256            getTerminalEcho  :: FILE_OBJECT -> IO Int{-ret code-}
1257 foreign import "libHS_cbits" "isTerminalDevice" unsafe
1258            isTerminalDevice :: FILE_OBJECT -> IO Int{-ret code-}
1259 foreign import "libHS_cbits" "setConnectedTo" unsafe
1260            setConnectedTo   :: FILE_OBJECT -> FILE_OBJECT -> Int -> IO ()
1261 foreign import "libHS_cbits" "ungetChar" unsafe
1262            ungetChar        :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1263 foreign import "libHS_cbits" "readChunk" unsafe
1264            readChunk        :: FILE_OBJECT -> Addr -> Int -> Int -> IO Int{-ret code-}
1265 foreign import "libHS_cbits" "getFileFd" unsafe
1266            getFileFd        :: FILE_OBJECT -> IO Int{-fd-}
1267 #ifdef __HUGS__
1268 foreign import "libHS_cbits" "fileSize_int64" unsafe
1269            fileSize_int64   :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1270 #else
1271 foreign import "libHS_cbits" "fileSize" unsafe
1272            fileSize  :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1273 #endif
1274
1275 foreign import "libHS_cbits" "getFilePosn" unsafe
1276            getFilePosn      :: FILE_OBJECT -> IO Int
1277 foreign import "libHS_cbits" "setFilePosn" unsafe
1278            setFilePosn      :: FILE_OBJECT -> Int -> ByteArray# -> IO Int
1279 foreign import "libHS_cbits" "getConnFileFd" unsafe
1280            getConnFileFd    :: FILE_OBJECT -> IO Int{-fd-}
1281 foreign import "libHS_cbits" "getLock" unsafe
1282            getLock  :: Int{-Fd-} -> Int{-exclusive-} -> IO Int{-return code-}
1283 foreign import "libHS_cbits" "openStdFile" unsafe
1284            openStdFile      :: Int{-fd-} -> Int{-Readable?-} -> IO Addr{-file obj-}
1285 foreign import "libHS_cbits" "openFile" unsafe
1286            primOpenFile         :: ByteArray Int{-CString-}
1287                                 -> Int{-How-}
1288                                 -> Int{-Binary-}
1289                                 -> IO Addr {-file obj-}
1290 foreign import "libHS_cbits" "const_BUFSIZ" unsafe
1291            const_BUFSIZ          :: Int
1292
1293 foreign import "libHS_cbits" "setBinaryMode__" unsafe
1294            setBinaryMode :: FILE_OBJECT -> Int -> IO Int
1295 \end{code}
1296
1297