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