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