2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[PrelHandle]{Module @PrelHandle@}
7 This module defines Haskell {\em handles} and the basic operations
8 which are supported for them.
11 {-# OPTIONS -fno-implicit-prelude -#include "cbits/stgio.h" #-}
12 #include "cbits/error.h"
14 #ifndef __HUGS__ /* Hugs just includes this in PreludeBuiltin so no header needed */
15 module PrelHandle where
18 import PrelArr ( newVar, readVar, writeVar, ByteArray )
19 import PrelRead ( Read )
20 import PrelList ( span )
22 import PrelException ( throw, ioError, catchException )
23 import PrelMaybe ( Maybe(..) )
24 import PrelAddr ( Addr, nullAddr )
25 import PrelBounded () -- get at Bounded Int instance.
26 import PrelNum ( toInteger )
27 import PrelWeak ( addForeignFinaliser )
28 #if __CONCURRENT_HASKELL__
33 #ifndef __PARALLEL_HASKELL__
34 import PrelForeign ( makeForeignObj )
37 #endif /* ndef(__HUGS__) */
40 #define cat2(x,y) x/**/y
41 #define CCALL(fun) cat2(prim_,fun)
42 #define __CONCURRENT_HASKELL__
44 #define sizeof_int64 8
46 #define CCALL(fun) _ccall_ fun
47 #define const_BUFSIZ ``BUFSIZ''
48 #define primPackString
51 #ifndef __PARALLEL_HASKELL__
52 #define FILE_OBJECT ForeignObj
54 #define FILE_OBJECT Addr
59 %*********************************************************
61 \subsection{Types @Handle@, @Handle__@}
63 %*********************************************************
65 The @Handle@ and @Handle__@ types are defined in @IOBase@.
68 {-# INLINE newHandle #-}
69 {-# INLINE withHandle #-}
70 {-# INLINE writeHandle #-}
71 newHandle :: Handle__ -> IO Handle
72 withHandle :: Handle -> (Handle__ -> IO a) -> IO a
73 writeHandle :: Handle -> Handle__ -> IO ()
75 #if defined(__CONCURRENT_HASKELL__)
77 -- Use MVars for concurrent Haskell
78 newHandle hc = newMVar hc >>= \ h ->
81 -- withHandle grabs the handle lock, performs
82 -- some operation over it, making sure that we
83 -- unlock & reset the handle state should an
84 -- exception occur while performing said op.
85 withHandle (Handle h) act = do
87 v <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
90 writeHandle (Handle h) hc = putMVar h hc
93 -- Use ordinary MutableVars for non-concurrent Haskell
94 newHandle hc = stToIO (newVar hc >>= \ h ->
97 -- of questionable value to install this exception
98 -- handler, but let's do it in the non-concurrent
100 withHandle (Handle h) act = do
101 h_ <- stToIO (readVar h)
102 v <- catchException (act h_) (\ ex -> stToIO (writeVar h h_) >> throw ex)
105 writeHandle (Handle h) hc = stToIO (writeVar h hc)
110 nullFile__ is only used for closed handles, plugging it in as a null
111 file object reference.
114 nullFile__ :: FILE_OBJECT
116 #ifndef __PARALLEL_HASKELL__
117 unsafePerformIO (makeForeignObj nullAddr)
123 mkClosedHandle__ :: Handle__
131 mkErrorHandle__ :: IOError -> Handle__
132 mkErrorHandle__ ioe =
140 %*********************************************************
142 \subsection{Handle Finalisers}
144 %*********************************************************
148 freeStdFileObject :: ForeignObj -> IO ()
149 freeStdFileObject fo = CCALL(freeStdFileObject) fo
151 freeFileObject :: ForeignObj -> IO ()
152 freeFileObject fo = CCALL(freeFileObject) fo
154 foreign import stdcall "libHS_cbits.so" "freeStdFileObject" freeStdFileObject :: ForeignObj -> IO ()
155 foreign import stdcall "libHS_cbits.so" "freeFileObject" freeFileObject :: ForeignObj -> IO ()
159 %*********************************************************
161 \subsection[StdHandles]{Standard handles}
163 %*********************************************************
165 Three handles are allocated during program initialisation. The first
166 two manage input or output from the Haskell program's standard input
167 or output channel respectively. The third manages output to the
168 standard error channel. These handles are initially open.
172 stdin, stdout, stderr :: Handle
174 stdout = unsafePerformIO (do
175 rc <- CCALL(getLock) (1::Int) (1::Int) -- ConcHask: SAFE, won't block
177 0 -> newHandle (mkClosedHandle__)
179 #ifndef __CONCURRENT_HASKELL__
180 fo <- CCALL(openStdFile) (1::Int)
181 (1::Int){-flush on close-}
182 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
184 fo <- CCALL(openStdFile) (1::Int)
185 ((1{-flush on close-} {-+ 128 don't block on I/O-})::Int)
186 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
188 -- NOTE: turn off non-blocking I/O until
189 -- we've got proper support for threadWait{Read,Write}
191 #ifndef __PARALLEL_HASKELL__
192 fo <- makeForeignObj fo
193 addForeignFinaliser fo (freeStdFileObject fo)
197 /* I dont care what the Haskell report says, in an interactive system,
198 * stdout should be unbuffered by default.
202 (bm, bf_size) <- getBMode__ fo
203 mkBuffer__ fo bf_size
205 newHandle (Handle__ fo WriteHandle bm "stdout")
206 _ -> do ioError <- constructError "stdout"
207 newHandle (mkErrorHandle__ ioError)
210 stdin = unsafePerformIO (do
211 rc <- CCALL(getLock) (0::Int) (0::Int) -- ConcHask: SAFE, won't block
213 0 -> newHandle (mkClosedHandle__)
215 #ifndef __CONCURRENT_HASKELL__
216 fo <- CCALL(openStdFile) (0::Int)
217 (0::Int){-don't flush on close -}
218 (1::Int){-readable-} -- ConcHask: SAFE, won't block
220 fo <- CCALL(openStdFile) (0::Int)
221 ((0{-flush on close-} {-+ 128 don't block on I/O-})::Int)
222 (1::Int){-readable-} -- ConcHask: SAFE, won't block
225 #ifndef __PARALLEL_HASKELL__
226 fo <- makeForeignObj fo
227 addForeignFinaliser fo (freeStdFileObject fo)
229 (bm, bf_size) <- getBMode__ fo
230 mkBuffer__ fo bf_size
231 hdl <- newHandle (Handle__ fo ReadHandle bm "stdin")
232 -- when stdin and stdout are both connected to a terminal, ensure
233 -- that anything buffered on stdout is flushed prior to reading from stdin.
235 hConnectTerms stdout hdl
237 _ -> do ioError <- constructError "stdin"
238 newHandle (mkErrorHandle__ ioError)
242 stderr = unsafePerformIO (do
243 rc <- CCALL(getLock) (2::Int) (1::Int){-writeable-} -- ConcHask: SAFE, won't block
245 0 -> newHandle (mkClosedHandle__)
247 #ifndef __CONCURRENT_HASKELL__
248 fo <- CCALL(openStdFile) (2::Int)
249 (1::Int){-flush on close-}
250 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
252 fo <- CCALL(openStdFile) (2::Int)
253 ((1{-flush on close-} {- + 128 don't block on I/O-})::Int)
254 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
257 #ifndef __PARALLEL_HASKELL__
258 fo <- makeForeignObj fo
259 addForeignFinaliser fo (freeStdFileObject fo)
261 hdl <- newHandle (Handle__ fo WriteHandle NoBuffering "stderr")
262 -- when stderr and stdout are both connected to a terminal, ensure
263 -- that anything buffered on stdout is flushed prior to writing to
265 hConnectTo stdout hdl
268 _ -> do ioError <- constructError "stderr"
269 newHandle (mkErrorHandle__ ioError)
273 %*********************************************************
275 \subsection[OpeningClosing]{Opening and Closing Files}
277 %*********************************************************
280 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
281 deriving (Eq, Ord, Ix, Enum, Read, Show)
286 deriving (Eq, Read, Show)
288 openFile :: FilePath -> IOMode -> IO Handle
289 openFile fp im = openFileEx fp (TextMode im)
291 openFileEx :: FilePath -> IOModeEx -> IO Handle
294 fo <- CCALL(openFile) (primPackString f) (file_mode::Int)
296 (file_flags::Int) -- ConcHask: SAFE, won't block
297 if fo /= nullAddr then do
298 #ifndef __PARALLEL_HASKELL__
299 fo <- makeForeignObj fo
300 addForeignFinaliser fo (freeFileObject fo)
302 (bm, bf_size) <- getBMode__ fo
303 mkBuffer__ fo bf_size
304 newHandle (Handle__ fo htype bm f)
306 constructErrorAndFailWithInfo "openFile" f
310 BinaryMode bmo -> (bmo, 1)
311 TextMode tmo -> (tmo, 0)
313 #ifndef __CONCURRENT_HASKELL__
314 file_flags = file_flags'
316 -- See comment next to 'stderr' for why we leave
317 -- non-blocking off for now.
318 file_flags = file_flags' {-+ 128 Don't block on I/O-}
321 (file_flags', file_mode) =
326 ReadWriteMode -> (1, 3)
329 ReadMode -> ReadHandle
330 WriteMode -> WriteHandle
331 AppendMode -> AppendHandle
332 ReadWriteMode -> ReadWriteHandle
335 Computation $openFile file mode$ allocates and returns a new, open
336 handle to manage the file {\em file}. It manages input if {\em mode}
337 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
338 and both input and output if mode is $ReadWriteMode$.
340 If the file does not exist and it is opened for output, it should be
341 created as a new file. If {\em mode} is $WriteMode$ and the file
342 already exists, then it should be truncated to zero length. The
343 handle is positioned at the end of the file if {\em mode} is
344 $AppendMode$, and otherwise at the beginning (in which case its
345 internal position is 0).
347 Implementations should enforce, locally to the Haskell process,
348 multiple-reader single-writer locking on files, which is to say that
349 there may either be many handles on the same file which manage input,
350 or just one handle on the file which manages output. If any open or
351 semi-closed handle is managing a file for output, no new handle can be
352 allocated for that file. If any open or semi-closed handle is
353 managing a file for input, new handles can only be allocated if they
354 do not manage output.
356 Two files are the same if they have the same absolute name. An
357 implementation is free to impose stricter conditions.
360 hClose :: Handle -> IO ()
363 withHandle handle $ \ handle_ -> do
364 case haType__ handle_ of
365 ErrorHandle theError -> do
366 writeHandle handle handle_
369 writeHandle handle handle_
370 ioe_closedHandle "hClose" handle
372 rc <- CCALL(closeFile) (haFO__ handle_) (1::Int){-flush if you can-} -- ConcHask: SAFE, won't block
373 {- We explicitly close a file object so that we can be told
374 if there were any errors. Note that after @hClose@
375 has been performed, the ForeignObj embedded in the Handle
376 is still lying around in the heap, so care is taken
377 to avoid closing the file object when the ForeignObj
378 is finalised. (we overwrite the file ptr in the underlying
379 FileObject with a NULL as part of closeFile())
383 writeHandle handle (handle_{ haType__ = ClosedHandle,
384 haFO__ = nullFile__ })
386 writeHandle handle handle_
387 constructErrorAndFail "hClose"
391 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
392 computation finishes, any items buffered for output and not already
393 sent to the operating system are flushed as for $flush$.
395 %*********************************************************
397 \subsection[EOF]{Detecting the End of Input}
399 %*********************************************************
402 For a handle {\em hdl} which attached to a physical file, $hFileSize
403 hdl$ returns the size of {\em hdl} in terms of the number of items
404 which can be read from {\em hdl}.
407 hFileSize :: Handle -> IO Integer
409 withHandle handle $ \ handle_ -> do
410 case haType__ handle_ of
411 ErrorHandle theError -> do
412 writeHandle handle handle_
415 writeHandle handle handle_
416 ioe_closedHandle "hFileSize" handle
417 SemiClosedHandle -> do
418 writeHandle handle handle_
419 ioe_closedHandle "hFileSize" handle
422 mem <- primNewByteArray sizeof_int64
423 rc <- CCALL(fileSize_int64) (haFO__ handle_) mem -- ConcHask: SAFE, won't block
424 writeHandle handle handle_
426 result <- primReadInt64Array mem 0
427 return (primInt64ToInteger result)
429 constructErrorAndFail "hFileSize"
432 -- HACK! We build a unique MP_INT of the right shape to hold
433 -- a single unsigned word, and we let the C routine
434 -- change the data bits
436 -- For some reason, this fails to typecheck if converted to a do
438 _casm_ ``%r = 1;'' >>= \(I# hack#) ->
439 case int2Integer hack# of
440 result@(J# _ _ d#) -> do
441 rc <- CCALL(fileSize) (haFO__ handle_) d# -- ConcHask: SAFE, won't block
442 writeHandle handle handle_
443 if rc == (0::Int) then
446 constructErrorAndFail "hFileSize"
450 For a readable handle {\em hdl}, @hIsEOF hdl@ returns
451 @True@ if no further input can be taken from @hdl@ or for a
452 physical file, if the current I/O position is equal to the length of
453 the file. Otherwise, it returns @False@.
456 hIsEOF :: Handle -> IO Bool
458 wantReadableHandle "hIsEOF" handle $ \ handle_ -> do
459 let fo = haFO__ handle_
460 rc <- mayBlock fo (CCALL(fileEOF) fo) -- ConcHask: UNSAFE, may block
461 writeHandle handle handle_
465 _ -> constructErrorAndFail "hIsEOF"
471 %*********************************************************
473 \subsection[Buffering]{Buffering Operations}
475 %*********************************************************
477 Three kinds of buffering are supported: line-buffering,
478 block-buffering or no-buffering. See @IOBase@ for definition
479 and further explanation of what the type represent.
481 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
482 handle {\em hdl} on subsequent reads and writes.
486 If {\em mode} is @LineBuffering@, line-buffering should be
489 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
490 should be enabled if possible. The size of the buffer is {\em n} items
491 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
493 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
496 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
497 to @NoBuffering@, then any items in the output buffer are written to
498 the device, and any items in the input buffer are discarded. The
499 default buffering mode when a handle is opened is
500 implementation-dependent and may depend on the object which is
501 attached to that handle.
504 hSetBuffering :: Handle -> BufferMode -> IO ()
506 hSetBuffering handle mode =
508 BlockBuffering (Just n)
510 (IOError (Just handle)
513 ("illegal buffer size " ++ showsPrec 9 n [])) -- 9 => should be parens'ified.
515 withHandle handle $ \ handle_ -> do
516 case haType__ handle_ of
517 ErrorHandle theError -> do
518 writeHandle handle handle_
521 writeHandle handle handle_
522 ioe_closedHandle "hSetBuffering" handle
525 - we flush the old buffer regardless of whether
526 the new buffer could fit the contents of the old buffer
528 - allow a handle's buffering to change even if IO has
529 occurred (ANSI C spec. does not allow this, nor did
530 the previous implementation of IO.hSetBuffering).
531 - a non-standard extension is to allow the buffering
532 of semi-closed handles to change [sof 6/98]
534 let fo = haFO__ handle_
535 rc <- mayBlock fo (CCALL(setBuffering) fo bsize) -- ConcHask: UNSAFE, may block
538 writeHandle handle (handle_{ haBufferMode__ = mode })
540 -- Note: failure to change the buffer size will cause old buffer to be flushed.
541 writeHandle handle handle_
542 constructErrorAndFail "hSetBuffering"
548 BlockBuffering Nothing -> -2
549 BlockBuffering (Just n) -> n
552 The action @hFlush hdl@ causes any items buffered for output
553 in handle {\em hdl} to be sent immediately to the operating
557 hFlush :: Handle -> IO ()
559 wantWriteableHandle "hFlush" handle $ \ handle_ -> do
560 let fo = haFO__ handle_
561 rc <- mayBlock fo (CCALL(flushFile) fo) -- ConcHask: UNSAFE, may block
562 writeHandle handle handle_
566 constructErrorAndFail "hFlush"
571 %*********************************************************
573 \subsection[Seeking]{Repositioning Handles}
575 %*********************************************************
580 Handle -- Q: should this be a weak or strong ref. to the handle?
583 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
584 deriving (Eq, Ord, Ix, Enum, Read, Show)
587 Computation @hGetPosn hdl@ returns the current I/O
588 position of {\em hdl} as an abstract position. Computation
589 $hSetPosn p$ sets the position of {\em hdl}
590 to a previously obtained position {\em p}.
593 hGetPosn :: Handle -> IO HandlePosn
595 wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
596 posn <- CCALL(getFilePosn) (haFO__ handle_) -- ConcHask: SAFE, won't block
597 writeHandle handle handle_
599 return (HandlePosn handle posn)
601 constructErrorAndFail "hGetPosn"
603 hSetPosn :: HandlePosn -> IO ()
604 hSetPosn (HandlePosn handle posn) =
605 wantSeekableHandle "hSetPosn" handle $ \ handle_ -> do -- not as silly as it looks: the handle may have been closed in the meantime.
606 let fo = haFO__ handle_
607 rc <- mayBlock fo (CCALL(setFilePosn) fo posn) -- ConcHask: UNSAFE, may block
608 writeHandle handle handle_
612 constructErrorAndFail "hSetPosn"
615 The action @hSeek hdl mode i@ sets the position of handle
616 @hdl@ depending on @mode@. If @mode@ is
618 \item[{\bf AbsoluteSeek}] The position of @hdl@ is set to @i@.
619 \item[{\bf RelativeSeek}] The position of @hdl@ is set to offset @i@ from
620 the current position.
621 \item[{\bf SeekFromEnd}] The position of @hdl@ is set to offset @i@ from
625 Some handles may not be seekable (see @hIsSeekable@), or only support a
626 subset of the possible positioning operations (e.g. it may only be
627 possible to seek to the end of a tape, or to a positive offset from
628 the beginning or current position).
630 It is not possible to set a negative I/O position, or for a physical
631 file, an I/O position beyond the current end-of-file.
634 - when seeking using @SeekFromEnd@, positive offsets (>=0) means seeking
636 - relative seeking on buffered handles can lead to non-obvious results.
639 hSeek :: Handle -> SeekMode -> Integer -> IO ()
641 hSeek handle mode offset =
642 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
643 let fo = haFO__ handle_
644 rc <- mayBlock fo (CCALL(seekFile_int64) fo whence (primIntegerToInt64 offset)) -- ConcHask: UNSAFE, may block
646 hSeek handle mode (J# _ s# d#) =
647 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
648 let fo = haFO__ handle_
649 rc <- mayBlock fo (CCALL(seekFile) fo whence (I# s#) d#) -- ConcHask: UNSAFE, may block
651 writeHandle handle handle_
655 constructErrorAndFail "hSeek"
658 whence = case mode of
664 %*********************************************************
666 \subsection[Query]{Handle Properties}
668 %*********************************************************
670 A number of operations return information about the properties of a
671 handle. Each of these operations returns $True$ if the
672 handle has the specified property, and $False$
675 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
676 {\em hdl} is not block-buffered. Otherwise it returns
677 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
678 $( Just n )$ for block-buffering of {\em n} bytes.
681 hIsOpen :: Handle -> IO Bool
683 withHandle handle $ \ handle_ -> do
684 case haType__ handle_ of
685 ErrorHandle theError -> do
686 writeHandle handle handle_
689 writeHandle handle handle_
691 SemiClosedHandle -> do
692 writeHandle handle handle_
695 writeHandle handle handle_
698 hIsClosed :: Handle -> IO Bool
700 withHandle handle $ \ handle_ -> do
701 case haType__ handle_ of
702 ErrorHandle theError -> do
703 writeHandle handle handle_
706 writeHandle handle handle_
709 writeHandle handle handle_
712 {- not defined, nor exported, but mentioned
713 here for documentation purposes:
715 hSemiClosed :: Handle -> IO Bool
719 return (not (ho || hc))
722 hIsReadable :: Handle -> IO Bool
724 withHandle handle $ \ handle_ -> do
725 case haType__ handle_ of
726 ErrorHandle theError -> do
727 writeHandle handle handle_
730 writeHandle handle handle_
731 ioe_closedHandle "hIsReadable" handle
732 SemiClosedHandle -> do
733 writeHandle handle handle_
734 ioe_closedHandle "hIsReadable" handle
736 writeHandle handle handle_
737 return (isReadable htype)
739 isReadable ReadHandle = True
740 isReadable ReadWriteHandle = True
743 hIsWritable :: Handle -> IO Bool
745 withHandle handle $ \ handle_ -> do
746 case haType__ handle_ of
747 ErrorHandle theError -> do
748 writeHandle handle handle_
751 writeHandle handle handle_
752 ioe_closedHandle "hIsWritable" handle
753 SemiClosedHandle -> do
754 writeHandle handle handle_
755 ioe_closedHandle "hIsWritable" handle
757 writeHandle handle handle_
758 return (isWritable htype)
760 isWritable AppendHandle = True
761 isWritable WriteHandle = True
762 isWritable ReadWriteHandle = True
766 #ifndef __PARALLEL_HASKELL__
767 getBMode__ :: ForeignObj -> IO (BufferMode, Int)
769 getBMode__ :: Addr -> IO (BufferMode, Int)
772 rc <- CCALL(getBufferMode) fo -- ConcHask: SAFE, won't block
774 0 -> return (NoBuffering, 0)
775 -1 -> return (LineBuffering, default_buffer_size)
776 -2 -> return (BlockBuffering Nothing, default_buffer_size)
777 -3 -> return (NoBuffering, 0) -- only happens on un-stat()able files.
778 n -> return (BlockBuffering (Just n), n)
780 default_buffer_size :: Int
781 default_buffer_size = (const_BUFSIZ - 1)
784 Querying how a handle buffers its data:
787 hGetBuffering :: Handle -> IO BufferMode
788 hGetBuffering handle =
789 withHandle handle $ \ handle_ -> do
790 case haType__ handle_ of
791 ErrorHandle theError -> do
792 writeHandle handle handle_
795 writeHandle handle handle_
796 ioe_closedHandle "hGetBuffering" handle
799 We're being non-standard here, and allow the buffering
800 of a semi-closed handle to be queried. -- sof 6/98
802 let v = haBufferMode__ handle_
803 writeHandle handle handle_
804 return v -- could be stricter..
809 hIsSeekable :: Handle -> IO Bool
811 withHandle handle $ \ handle_ -> do
812 case haType__ handle_ of
813 ErrorHandle theError -> do
814 writeHandle handle handle_
817 writeHandle handle handle_
818 ioe_closedHandle "hIsSeekable" handle
819 SemiClosedHandle -> do
820 writeHandle handle handle_
821 ioe_closedHandle "hIsSeekable" handle
823 writeHandle handle handle_
826 rc <- CCALL(seekFileP) (haFO__ handle_) -- ConcHask: SAFE, won't block
827 writeHandle handle handle_
831 _ -> constructErrorAndFail "hIsSeekable"
835 %*********************************************************
837 \subsection{Changing echo status}
839 %*********************************************************
841 Non-standard GHC extension is to allow the echoing status
842 of a handles connected to terminals to be reconfigured:
845 hSetEcho :: Handle -> Bool -> IO ()
846 hSetEcho handle on = do
847 isT <- hIsTerminalDevice handle
851 withHandle handle $ \ handle_ -> do
852 case haType__ handle_ of
853 ErrorHandle theError -> do
854 writeHandle handle handle_
857 writeHandle handle handle_
858 ioe_closedHandle "hSetEcho" handle
860 rc <- CCALL(setTerminalEcho) (haFO__ handle_) ((if on then 1 else 0)::Int) -- ConcHask: SAFE, won't block
861 writeHandle handle handle_
864 else constructErrorAndFail "hSetEcho"
866 hGetEcho :: Handle -> IO Bool
868 isT <- hIsTerminalDevice handle
872 withHandle handle $ \ handle_ -> do
873 case haType__ handle_ of
874 ErrorHandle theError -> do
875 writeHandle handle handle_
878 writeHandle handle handle_
879 ioe_closedHandle "hGetEcho" handle
881 rc <- CCALL(getTerminalEcho) (haFO__ handle_) -- ConcHask: SAFE, won't block
882 writeHandle handle handle_
886 _ -> constructErrorAndFail "hSetEcho"
888 hIsTerminalDevice :: Handle -> IO Bool
889 hIsTerminalDevice handle = do
890 withHandle handle $ \ handle_ -> do
891 case haType__ handle_ of
892 ErrorHandle theError -> do
893 writeHandle handle handle_
896 writeHandle handle handle_
897 ioe_closedHandle "hIsTerminalDevice" handle
899 rc <- CCALL(isTerminalDevice) (haFO__ handle_) -- ConcHask: SAFE, won't block
900 writeHandle handle handle_
904 _ -> constructErrorAndFail "hIsTerminalDevice"
908 hConnectTerms :: Handle -> Handle -> IO ()
909 hConnectTerms hW hR = hConnectHdl_ hW hR 1{-check if they're both coming connected to ttys-}
911 hConnectTo :: Handle -> Handle -> IO ()
912 hConnectTo hW hR = hConnectHdl_ hW hR 0{-connect regardless-}
914 hConnectHdl_ :: Handle -> Handle -> Int -> IO ()
915 hConnectHdl_ hW hR is_tty =
916 wantRWHandle "hConnectTo" hW $ \ hW_ -> do
917 wantRWHandle "hConnectTo" hR $ \ hR_ -> do
918 CCALL(setConnectedTo) (haFO__ hR_) (haFO__ hW_) is_tty -- ConcHask: SAFE, won't block
922 #ifndef __PARALLEL_HASKELL__
923 #define FILE_OBJECT ForeignObj
925 #define FILE_OBJECT Addr
928 flushConnectedBuf :: FILE_OBJECT -> IO ()
929 flushConnectedBuf fo = CCALL(flushConnectedBuf) fo
932 As an extension, we also allow characters to be pushed back.
933 Like ANSI C stdio, we guarantee no more than one character of
934 pushback. (For unbuffered channels, the (default) push-back limit is
938 hUngetChar :: Handle -> Char -> IO ()
939 hUngetChar handle c =
940 wantReadableHandle "hLookAhead" handle $ \ handle_ -> do
941 rc <- CCALL(ungetChar) (haFO__ handle_) c -- ConcHask: SAFE, won't block
942 writeHandle handle handle_
944 then constructErrorAndFail "hUngetChar"
950 Hoisting files in in one go is sometimes useful, so we support
951 this as an extension:
954 -- in one go, read file into an externally allocated buffer.
955 slurpFile :: FilePath -> IO (Addr, Int)
957 handle <- openFile fname ReadMode
958 sz <- hFileSize handle
959 if sz > toInteger (maxBound::Int) then
960 ioError (userError "slurpFile: file too big")
962 let sz_i = fromInteger sz
963 chunk <- CCALL(allocMemory__) (sz_i::Int)
967 constructErrorAndFail "slurpFile"
969 withHandle handle $ \ handle_ -> do
970 let fo = haFO__ handle_
971 rc <- mayBlock fo (CCALL(readChunk) fo chunk sz_i) -- ConcHask: UNSAFE, may block.
972 writeHandle handle handle_
975 then constructErrorAndFail "slurpFile"
976 else return (chunk, rc)
978 #ifndef __HUGS__ /* Hugs' Prelude doesn't need this */
979 hFillBufBA :: Handle -> ByteArray Int -> Int -> IO Int
980 hFillBufBA handle buf sz
981 | sz <= 0 = ioError (IOError (Just handle)
984 ("illegal buffer size " ++ showsPrec 9 sz [])) -- 9 => should be parens'ified.
986 wantReadableHandle "hFillBufBA" handle $ \ handle_ -> do
987 let fo = haFO__ handle_
989 rc <- mayBlock fo (CCALL(readChunkBA) fo buf sz) -- ConcHask: UNSAFE, may block.
991 rc <- mayBlock fo (CCALL(readChunk) fo buf sz) -- ConcHask: UNSAFE, may block.
993 writeHandle handle handle_
996 else constructErrorAndFail "hFillBufBA"
999 hFillBuf :: Handle -> Addr -> Int -> IO Int
1000 hFillBuf handle buf sz
1001 | sz <= 0 = ioError (IOError (Just handle)
1004 ("illegal buffer size " ++ showsPrec 9 sz [])) -- 9 => should be parens'ified.
1006 wantReadableHandle "hFillBuf" handle $ \ handle_ -> do
1007 let fo = haFO__ handle_
1008 rc <- mayBlock fo (CCALL(readChunk) fo buf sz) -- ConcHask: UNSAFE, may block.
1009 writeHandle handle handle_
1012 else constructErrorAndFail "hFillBuf"
1016 The @hPutBuf hdl buf len@ action writes an already packed sequence of
1017 bytes to the file/channel managed by @hdl@ - non-standard.
1020 hPutBuf :: Handle -> Addr -> Int -> IO ()
1021 hPutBuf handle buf len =
1022 wantWriteableHandle "hPutBuf" handle $ \ handle_ -> do
1023 let fo = haFO__ handle_
1024 rc <- mayBlock fo (CCALL(writeBuf) fo buf len) -- ConcHask: UNSAFE, may block.
1025 writeHandle handle handle_
1028 else constructErrorAndFail "hPutBuf"
1030 #ifndef __HUGS__ /* An_ one Hugs doesn't provide */
1031 hPutBufBA :: Handle -> ByteArray Int -> Int -> IO ()
1032 hPutBufBA handle buf len =
1033 wantWriteableHandle "hPutBufBA" handle $ \ handle_ -> do
1034 let fo = haFO__ handle_
1035 rc <- mayBlock fo (CCALL(writeBufBA) fo buf len) -- ConcHask: UNSAFE, may block.
1036 writeHandle handle handle_
1039 else constructErrorAndFail "hPutBuf"
1043 Sometimes it's useful to get at the file descriptor that
1044 the Handle contains..
1047 getHandleFd :: Handle -> IO Int
1048 getHandleFd handle = do
1049 withHandle handle $ \ handle_ -> do
1050 case (haType__ handle_) of
1051 ErrorHandle theError -> do
1052 writeHandle handle handle_
1055 writeHandle handle handle_
1056 ioe_closedHandle "getHandleFd" handle
1058 fd <- CCALL(getFileFd) (haFO__ handle_)
1059 writeHandle handle handle_
1064 %*********************************************************
1066 \subsection{Miscellaneous}
1068 %*********************************************************
1070 These three functions are meant to get things out of @IOErrors@.
1075 ioeGetFileName :: IOError -> Maybe FilePath
1076 ioeGetErrorString :: IOError -> String
1077 ioeGetHandle :: IOError -> Maybe Handle
1079 ioeGetHandle (IOError h _ _ _) = h
1080 ioeGetErrorString (IOError _ iot _ str) =
1082 EOF -> "end of file"
1085 ioeGetFileName (IOError _ _ _ str) =
1086 case span (/=':') str of
1092 A number of operations want to get at a readable or writeable handle, and fail
1096 wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1097 wantReadableHandle fun handle act =
1098 withHandle handle $ \ handle_ -> do
1099 case haType__ handle_ of
1100 ErrorHandle theError -> do
1101 writeHandle handle handle_
1104 writeHandle handle handle_
1105 ioe_closedHandle fun handle
1106 SemiClosedHandle -> do
1107 writeHandle handle handle_
1108 ioe_closedHandle fun handle
1110 writeHandle handle handle_
1111 ioError not_readable_error
1113 writeHandle handle handle_
1114 ioError not_readable_error
1117 not_readable_error =
1118 IOError (Just handle) IllegalOperation fun
1119 ("handle is not open for reading")
1121 wantWriteableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1122 wantWriteableHandle fun handle act =
1123 withHandle handle $ \ handle_ -> do
1124 case haType__ handle_ of
1125 ErrorHandle theError -> do
1126 writeHandle handle handle_
1129 writeHandle handle handle_
1130 ioe_closedHandle fun handle
1131 SemiClosedHandle -> do
1132 writeHandle handle handle_
1133 ioe_closedHandle fun handle
1135 writeHandle handle handle_
1136 ioError not_writeable_error
1139 not_writeable_error =
1140 IOError (Just handle) IllegalOperation fun
1141 ("handle is not open for writing")
1143 wantRWHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1144 wantRWHandle fun handle act =
1145 withHandle handle $ \ handle_ -> do
1146 case haType__ handle_ of
1147 ErrorHandle theError -> do
1148 writeHandle handle handle_
1151 writeHandle handle handle_
1152 ioe_closedHandle fun handle
1153 SemiClosedHandle -> do
1154 writeHandle handle handle_
1155 ioe_closedHandle fun handle
1159 IOError (Just handle) IllegalOperation fun
1160 ("handle is not open for reading or writing")
1162 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1163 wantSeekableHandle fun handle act =
1164 withHandle handle $ \ handle_ -> do
1165 case haType__ handle_ of
1166 ErrorHandle theError -> do
1167 writeHandle handle handle_
1170 writeHandle handle handle_
1171 ioe_closedHandle fun handle
1172 SemiClosedHandle -> do
1173 writeHandle handle handle_
1174 ioe_closedHandle fun handle
1176 writeHandle handle handle_
1177 ioError not_seekable_error
1180 not_seekable_error =
1181 IOError (Just handle)
1182 IllegalOperation fun
1183 ("handle is not seekable")
1187 Internal function for creating an @IOError@ representing the
1188 access to a closed file.
1191 ioe_closedHandle :: String -> Handle -> IO a
1192 ioe_closedHandle fun h = ioError (IOError (Just h) IllegalOperation fun "handle is closed")
1195 Internal helper functions for Concurrent Haskell implementation
1199 #ifndef __PARALLEL_HASKELL__
1200 mayBlock :: ForeignObj -> IO Int -> IO Int
1202 mayBlock :: Addr -> IO Int -> IO Int
1205 #ifndef notyet /*__CONCURRENT_HASKELL__*/
1206 mayBlock _ act = act
1208 mayBlock fo act = do
1211 -5 -> do -- (possibly blocking) read
1212 fd <- CCALL(getFileFd) fo
1214 CCALL(clearNonBlockingIOFlag__) fo -- force read to happen this time.
1215 mayBlock fo act -- input available, re-try
1216 -6 -> do -- (possibly blocking) write
1217 fd <- CCALL(getFileFd) fo
1219 CCALL(clearNonBlockingIOFlag__) fo -- force write to happen this time.
1220 mayBlock fo act -- output possible
1221 -7 -> do -- (possibly blocking) write on connected handle
1222 fd <- CCALL(getConnFileFd) fo
1224 CCALL(clearConnNonBlockingIOFlag__) fo -- force write to happen this time.
1225 mayBlock fo act -- output possible
1227 CCALL(setNonBlockingIOFlag__) fo -- reset file object.
1228 CCALL(setConnNonBlockingIOFlag__) fo -- reset (connected) file object.
1235 threadDelay, threadWaitRead, threadWaitWrite :: Int -> IO ()
1237 -- Hugs does actually have the primops needed to implement these
1238 -- but, like GHC, the primops don't actually do anything...
1239 threadDelay _ = return ()
1240 threadWaitRead _ = return ()
1241 threadWaitWrite _ = return ()
1250 type Exclusive = Int -- really Bool
1253 type OpenStdFlags = Int
1254 type OpenFlags = Int
1255 type Readable = Int -- really Bool
1256 type Flush = Int -- really Bool
1257 type RC = Int -- standard return code
1259 type IOFileAddr = Addr -- as returned from functions
1260 type CString = PrimByteArray
1261 type Bytes = PrimMutableByteArray RealWorld
1263 #ifndef __PARALLEL_HASKELL__
1264 type FILE_OBJ = ForeignObj -- as passed into functions
1266 type FILE_OBJ = Addr
1269 foreign import ccall "libHS_cbits.so" "setBuf" unsafe prim_setBuf :: FILE_OBJ -> Addr -> Int -> IO ()
1270 foreign import ccall "libHS_cbits.so" "getBufSize" unsafe prim_getBufSize :: FILE_OBJ -> IO Int
1271 foreign import ccall "libHS_cbits.so" "inputReady" unsafe prim_inputReady :: FILE_OBJ -> Int -> IO RC
1272 foreign import ccall "libHS_cbits.so" "fileGetc" unsafe prim_fileGetc :: FILE_OBJ -> IO Int
1273 foreign import ccall "libHS_cbits.so" "fileLookAhead" unsafe prim_fileLookAhead :: FILE_OBJ -> IO Int
1274 foreign import ccall "libHS_cbits.so" "readBlock" unsafe prim_readBlock :: FILE_OBJ -> IO Int
1275 foreign import ccall "libHS_cbits.so" "readLine" unsafe prim_readLine :: FILE_OBJ -> IO Int
1276 foreign import ccall "libHS_cbits.so" "readChar" unsafe prim_readChar :: FILE_OBJ -> IO Int
1277 foreign import ccall "libHS_cbits.so" "writeFileObject" unsafe prim_writeFileObject :: FILE_OBJ -> Int -> IO RC
1278 foreign import ccall "libHS_cbits.so" "filePutc" unsafe prim_filePutc :: FILE_OBJ -> Char -> IO RC
1279 foreign import ccall "libHS_cbits.so" "getBufStart" unsafe prim_getBufStart :: FILE_OBJ -> Int -> IO Addr
1280 foreign import ccall "libHS_cbits.so" "getWriteableBuf" unsafe prim_getWriteableBuf :: FILE_OBJ -> IO Addr
1281 foreign import ccall "libHS_cbits.so" "getBufWPtr" unsafe prim_getBufWPtr :: FILE_OBJ -> IO Int
1282 foreign import ccall "libHS_cbits.so" "setBufWPtr" unsafe prim_setBufWPtr :: FILE_OBJ -> Int -> IO ()
1283 foreign import ccall "libHS_cbits.so" "closeFile" unsafe prim_closeFile :: FILE_OBJ -> Flush -> IO RC
1284 foreign import ccall "libHS_cbits.so" "fileEOF" unsafe prim_fileEOF :: FILE_OBJ -> IO RC
1285 foreign import ccall "libHS_cbits.so" "setBuffering" unsafe prim_setBuffering :: FILE_OBJ -> Int -> IO RC
1286 foreign import ccall "libHS_cbits.so" "flushFile" unsafe prim_flushFile :: FILE_OBJ -> IO RC
1287 foreign import ccall "libHS_cbits.so" "flushConnectedBuf" unsafe prim_flushConnectedBuf :: FILE_OBJ -> IO RC
1288 foreign import ccall "libHS_cbits.so" "getBufferMode" unsafe prim_getBufferMode :: FILE_OBJ -> IO RC
1289 foreign import ccall "libHS_cbits.so" "seekFile_int64" unsafe prim_seekFile_int64 :: FILE_OBJ -> Int -> Int64 -> IO RC
1290 foreign import ccall "libHS_cbits.so" "seekFileP" unsafe prim_seekFileP :: FILE_OBJ -> IO RC
1291 foreign import ccall "libHS_cbits.so" "setTerminalEcho" unsafe prim_setTerminalEcho :: FILE_OBJ -> Int -> IO RC
1292 foreign import ccall "libHS_cbits.so" "getTerminalEcho" unsafe prim_getTerminalEcho :: FILE_OBJ -> IO RC
1293 foreign import ccall "libHS_cbits.so" "isTerminalDevice" unsafe prim_isTerminalDevice :: FILE_OBJ -> IO RC
1294 foreign import ccall "libHS_cbits.so" "setConnectedTo" unsafe prim_setConnectedTo :: FILE_OBJ -> FILE_OBJ -> Int -> IO ()
1295 foreign import ccall "libHS_cbits.so" "ungetChar" unsafe prim_ungetChar :: FILE_OBJ -> Char -> IO RC
1296 foreign import ccall "libHS_cbits.so" "readChunk" unsafe prim_readChunk :: FILE_OBJ -> Addr -> Int -> IO RC
1297 foreign import ccall "libHS_cbits.so" "writeBuf" unsafe prim_writeBuf :: FILE_OBJ -> Addr -> Int -> IO RC
1298 foreign import ccall "libHS_cbits.so" "getFileFd" unsafe prim_getFileFd :: FILE_OBJ -> IO FD
1299 foreign import ccall "libHS_cbits.so" "fileSize_int64" unsafe prim_fileSize_int64 :: FILE_OBJ -> Bytes -> IO RC
1300 foreign import ccall "libHS_cbits.so" "getFilePosn" unsafe prim_getFilePosn :: FILE_OBJ -> IO Int
1301 foreign import ccall "libHS_cbits.so" "setFilePosn" unsafe prim_setFilePosn :: FILE_OBJ -> Int -> IO Int
1302 foreign import ccall "libHS_cbits.so" "getConnFileFd" unsafe prim_getConnFileFd :: FILE_OBJ -> IO FD
1303 foreign import ccall "libHS_cbits.so" "allocMemory__" unsafe prim_allocMemory__ :: Int -> IO Addr
1304 foreign import ccall "libHS_cbits.so" "getLock" unsafe prim_getLock :: FD -> Exclusive -> IO RC
1305 foreign import ccall "libHS_cbits.so" "openStdFile" unsafe prim_openStdFile :: FD -> OpenStdFlags -> Readable -> IO IOFileAddr
1306 foreign import ccall "libHS_cbits.so" "openFile" unsafe prim_openFile :: CString -> How -> Binary -> OpenFlags -> IO IOFileAddr
1307 foreign import ccall "libHS_cbits.so" "freeFileObject" unsafe prim_freeFileObject :: FILE_OBJ -> IO ()
1308 foreign import ccall "libHS_cbits.so" "freeStdFileObject" unsafe prim_freeStdFileObject :: FILE_OBJ -> IO ()
1309 foreign import ccall "libHS_cbits.so" "const_BUFSIZ" unsafe const_BUFSIZ :: Int
1311 foreign import ccall "libHS_cbits.so" "setConnNonBlockingIOFlag__" unsafe prim_setConnNonBlockingIOFlag__ :: FILE_OBJ -> IO ()
1312 foreign import ccall "libHS_cbits.so" "clearConnNonBlockingIOFlag__" unsafe prim_clearConnNonBlockingIOFlag__ :: FILE_OBJ -> IO ()
1313 foreign import ccall "libHS_cbits.so" "setNonBlockingIOFlag__" unsafe prim_setNonBlockingIOFlag__ :: FILE_OBJ -> IO ()
1314 foreign import ccall "libHS_cbits.so" "clearNonBlockingIOFlag__" unsafe prim_clearNonBlockingIOFlag__ :: FILE_OBJ -> IO ()
1316 foreign import ccall "libHS_cbits.so" "getErrStr__" unsafe prim_getErrStr__ :: IO Addr
1317 foreign import ccall "libHS_cbits.so" "getErrNo__" unsafe prim_getErrNo__ :: IO Int
1318 foreign import ccall "libHS_cbits.so" "getErrType__" unsafe prim_getErrType__ :: IO Int