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