summaryrefslogtreecommitdiff
path: root/ghc/lib/prelude/PreludeWriteTextIO.lhs
blob: 000c3436370a332f95709c4b14e665fadff3d857 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
%
% (c) The GRASP/AQUA Project, Glasgow University, 1994
%
\section[PrelWriteTextIO]{Haskell 1.3 Text Output}

This module defines the standard set of output operations for writing
characters and strings to text files, using 
$handles$

\begin{code}
module PreludeWriteTextIO (
    hPutChar,
    putChar,
    hPutStr,
    putStr,
    hPutText,
    putText,
    print13,
    writeFile13,
    appendFile13
  ) where

import Cls
import Core
import IChar
import IInt
import IList
import List		( splitAt, (++) )
import Prel		( ord, (.), otherwise )
import Text
import TyArray		-- instance _CCallable (_ByteArray a)

import PreludeIOError
import PreludeMonadicIO
import PreludePrimIO
import PreludeGlaST
import PreludeStdIO
import PS

hPutChar :: Handle -> Char -> IO ()
hPutChar handle c =
    takeMVar handle				    >>= \ htype ->
    case htype of 
      _ErrorHandle ioError ->
	  putMVar handle htype			    >>
          failWith ioError
      _ClosedHandle ->
	  putMVar handle htype			    >>
	  failWith (IllegalOperation "handle is closed")
      _SemiClosedHandle _ _ ->
	  putMVar handle htype			    >>
	  failWith (IllegalOperation "handle is closed")
      _ReadHandle _ _ _ ->
	  putMVar handle htype			    >>
	  failWith (IllegalOperation "handle is not open for writing")
      other -> 
	  _ccall_ filePutc (_filePtr other) (ord c) `thenPrimIO` \ rc ->
	  putMVar handle (_markHandle htype)	    >>
          if rc == 0 then
              return ()
          else
              _constructError			    `thenPrimIO` \ ioError ->
	      failWith ioError

putChar :: Char -> IO () 
putChar = hPutChar stdout13

\end{code}

Computation $hPutChar hdl c$ writes the character {\em c} to the file
or channel managed by {\em hdl}.  Characters may be buffered if
buffering is enabled for {\em hdl}.

\begin{code}
hPutStr :: Handle -> String -> IO ()
hPutStr handle str = 
    takeMVar handle				    >>= \ htype ->
    case htype of 
      _ErrorHandle ioError ->
	  putMVar handle htype			    >>
          failWith ioError
      _ClosedHandle ->
	  putMVar handle htype			    >>
	  failWith (IllegalOperation "handle is closed")
      _SemiClosedHandle _ _ ->
	  putMVar handle htype			    >>
	  failWith (IllegalOperation "handle is closed")
      _ReadHandle _ _ _ ->
	  putMVar handle htype			    >>
	  failWith (IllegalOperation "handle is not open for writing")
      other -> 
          _getBufferMode other			    `thenPrimIO` \ other ->
          (case _bufferMode other of
            Just LineBuffering ->
		writeLines (_filePtr other) str
            Just (BlockBuffering (Just size)) ->
	        writeBlocks (_filePtr other) size str
            Just (BlockBuffering Nothing) ->
	        writeBlocks (_filePtr other) ``BUFSIZ'' str
            _ -> -- Nothing is treated pessimistically as NoBuffering
	        writeChars (_filePtr other) str
	  )    					    `thenPrimIO` \ success ->
	    putMVar handle (_markHandle other)	    `seqPrimIO`
          if success then
              return ()
          else
              _constructError			    `thenPrimIO` \ ioError ->
	      failWith ioError

  where

    writeBlocks :: _Addr -> Int -> String -> PrimIO Bool
    writeBlocks fp size "" = returnPrimIO True
    writeBlocks fp size s =
        let
	    (some, more) = splitAt size s
        in
	    _packBytesForCST some		    `thenPrimIO` 
              \ bytes@(_ByteArray (0, count) _) ->
	    _ccall_ writeFile bytes fp (count+1)    `thenPrimIO` \ rc ->
            if rc == 0 then
		writeBlocks fp size more
	    else
		returnPrimIO False

    writeLines :: _Addr -> String -> PrimIO Bool
    writeLines fp "" = returnPrimIO True
    writeLines fp s =
        let
	    (some, more) = breakLine s
        in
	    _packBytesForCST some		    `thenPrimIO` 
              \ bytes@(_ByteArray (0, count) _) ->
	    _ccall_ writeFile bytes fp (count+1)    `thenPrimIO` \ rc ->
            if rc == 0 then
		writeLines fp more
	    else
		returnPrimIO False
      where
        breakLine ""	= ("","")
        breakLine (x:xs)
	  | x == '\n'	= ([x],xs)
	  | otherwise	= let (ys,zs) = breakLine xs in (x:ys,zs)

    writeChars :: _Addr -> String -> PrimIO Bool
    writeChars fp "" = returnPrimIO True
    writeChars fp (c:cs) =
	_ccall_ filePutc fp (ord c)		    `thenPrimIO` \ rc ->
        if rc == 0 then
	    writeChars fp cs
	else
	    returnPrimIO False

putStr :: String -> IO () 
putStr = hPutStr stdout13

hPutText :: Text a => Handle -> a -> IO ()
hPutText hdl = hPutStr hdl . show

putText :: Text a => a -> IO () 
putText = hPutText stdout13

print13 :: Text a => a -> IO ()
print13 x = putText x >> putChar '\n'

\end{code}

Computation $hPutStr hdl s$ writes the string {\em s} to the file or
channel managed by {\em hdl}.

Computation $putStr s$ writes the string {\em s} to $stdout$.

Computation $hPutText hdl t$ writes the string representation of {\em
t} given by the $shows$ function to the file or channel managed by
{\em hdl}.

\begin{code}

writeFile13 :: FilePath -> String -> IO ()
writeFile13 name str =
 openFile name WriteMode >>= \hdl -> hPutStr hdl str >> hClose hdl

appendFile13 :: FilePath -> String -> IO ()
appendFile13 name str =
 openFile name AppendMode >>= \hdl -> hPutStr hdl str >> hClose hdl

\end{code}

$writeFile file s$ replaces the contents of {\em file} by the string
{\em s}. $appendFile file s$ appends string {\em s} to {\em file}.