[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / ghc / lib / haskell-1.3 / LibPosixTTY.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1995
3 %
4 \section[LibPosixTTY]{Haskell 1.3 POSIX Device-Specific Functions}
5
6 \begin{code}
7 module LibPosixTTY (
8     BaudRate(..),
9     ControlCharacter(..),
10     FlowAction(..),
11     QueueSelector(..),
12     TerminalAttributes(..),
13     TerminalMode(..),
14     TerminalState(..),
15     bitsPerByte,
16     controlChar,
17     controlFlow,
18     discardData,
19     drainOutput,
20     getTerminalAttributes,
21     getTerminalProcessGroupID,
22     inputSpeed,
23     inputTime,
24     minInput,
25     outputSpeed,
26     sendBreak,
27     setTerminalAttributes,
28     setTerminalProcessGroupID,
29     terminalMode,
30     withBits,
31     withCC,
32     withInputSpeed,
33     withMinInput,
34     withMode,
35     withOutputSpeed,
36     withTime,
37     withoutCC,
38     withoutMode
39     ) where
40
41 import PreludeGlaST
42
43 import LibPosixUtil
44
45 type TerminalAttributes = _ByteArray ()
46
47 data TerminalMode = InterruptOnBreak
48                   | MapCRtoLF
49                   | IgnoreBreak
50                   | IgnoreCR
51                   | IgnoreParityErrors
52                   | MapLFtoCR
53                   | CheckParity
54                   | StripHighBit
55                   | StartStopInput
56                   | StartStopOutput
57                   | MarkParityErrors
58                   | ProcessOutput
59                   | LocalMode
60                   | ReadEnable
61                   | TwoStopBits
62                   | HangupOnClose
63                   | EnableParity
64                   | OddParity
65                   | EnableEcho
66                   | EchoErase
67                   | EchoKill
68                   | EchoLF
69                   | ProcessInput
70                   | ExtendedFunctions
71                   | KeyboardInterrupts
72                   | NoFlushOnInterrupt
73                   | BackgroundWriteInterrupt
74
75 withoutMode :: TerminalAttributes -> TerminalMode -> TerminalAttributes
76 withoutMode termios InterruptOnBreak = clearInputFlag ``BRKINT'' termios
77 withoutMode termios MapCRtoLF = clearInputFlag ``ICRNL'' termios
78 withoutMode termios IgnoreBreak = clearInputFlag ``IGNBRK'' termios
79 withoutMode termios IgnoreCR = clearInputFlag ``IGNCR'' termios
80 withoutMode termios IgnoreParityErrors = clearInputFlag ``IGNPAR'' termios
81 withoutMode termios MapLFtoCR = clearInputFlag ``INLCR'' termios
82 withoutMode termios CheckParity = clearInputFlag ``INPCK'' termios
83 withoutMode termios StripHighBit = clearInputFlag ``ISTRIP'' termios
84 withoutMode termios StartStopInput = clearInputFlag ``IXOFF'' termios
85 withoutMode termios StartStopOutput = clearInputFlag ``IXON'' termios
86 withoutMode termios MarkParityErrors = clearInputFlag ``PARMRK'' termios
87 withoutMode termios ProcessOutput = unsafePerformPrimIO (
88     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
89     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
90              ((struct termios *)%0)->c_oflag &= ~OPOST;'' bytes termios
91                                                     `thenPrimIO` \ () ->
92     freeze bytes                                    `thenStrictlyST` \ termios ->
93     returnPrimIO termios)
94 withoutMode termios LocalMode = clearControlFlag ``CLOCAL'' termios
95 withoutMode termios ReadEnable = clearControlFlag ``CREAD'' termios
96 withoutMode termios TwoStopBits = clearControlFlag ``CSTOPB'' termios
97 withoutMode termios HangupOnClose = clearControlFlag ``HUPCL'' termios
98 withoutMode termios EnableParity = clearControlFlag ``PARENB'' termios
99 withoutMode termios OddParity = clearControlFlag ``PARODD'' termios
100 withoutMode termios EnableEcho = clearLocalFlag ``ECHO'' termios
101 withoutMode termios EchoErase = clearLocalFlag ``ECHOE'' termios
102 withoutMode termios EchoKill = clearLocalFlag ``ECHOK'' termios
103 withoutMode termios EchoLF = clearLocalFlag ``ECHONL'' termios
104 withoutMode termios ProcessInput = clearLocalFlag ``ICANON'' termios
105 withoutMode termios ExtendedFunctions = clearLocalFlag ``IEXTEN'' termios
106 withoutMode termios KeyboardInterrupts = clearLocalFlag ``ISIG'' termios
107 withoutMode termios NoFlushOnInterrupt = setLocalFlag ``NOFLSH'' termios
108 withoutMode termios BackgroundWriteInterrupt = clearLocalFlag ``TOSTOP'' termios
109
110 withMode :: TerminalAttributes -> TerminalMode -> TerminalAttributes
111 withMode termios InterruptOnBreak = setInputFlag ``BRKINT'' termios
112 withMode termios MapCRtoLF = setInputFlag ``ICRNL'' termios
113 withMode termios IgnoreBreak = setInputFlag ``IGNBRK'' termios
114 withMode termios IgnoreCR = setInputFlag ``IGNCR'' termios
115 withMode termios IgnoreParityErrors = setInputFlag ``IGNPAR'' termios
116 withMode termios MapLFtoCR = setInputFlag ``INLCR'' termios
117 withMode termios CheckParity = setInputFlag ``INPCK'' termios
118 withMode termios StripHighBit = setInputFlag ``ISTRIP'' termios
119 withMode termios StartStopInput = setInputFlag ``IXOFF'' termios
120 withMode termios StartStopOutput = setInputFlag ``IXON'' termios
121 withMode termios MarkParityErrors = setInputFlag ``PARMRK'' termios
122 withMode termios ProcessOutput = unsafePerformPrimIO (
123     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
124     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
125              ((struct termios *)%0)->c_oflag |= OPOST;'' bytes termios
126                                                     `thenPrimIO` \ () ->
127     freeze bytes                                    `thenStrictlyST` \ termios ->
128     returnPrimIO termios)
129 withMode termios LocalMode = setControlFlag ``CLOCAL'' termios
130 withMode termios ReadEnable = setControlFlag ``CREAD'' termios
131 withMode termios TwoStopBits = setControlFlag ``CSTOPB'' termios
132 withMode termios HangupOnClose = setControlFlag ``HUPCL'' termios
133 withMode termios EnableParity = setControlFlag ``PARENB'' termios
134 withMode termios OddParity = setControlFlag ``PARODD'' termios
135 withMode termios EnableEcho = setLocalFlag ``ECHO'' termios
136 withMode termios EchoErase = setLocalFlag ``ECHOE'' termios
137 withMode termios EchoKill = setLocalFlag ``ECHOK'' termios
138 withMode termios EchoLF = setLocalFlag ``ECHONL'' termios
139 withMode termios ProcessInput = setLocalFlag ``ICANON'' termios
140 withMode termios ExtendedFunctions = setLocalFlag ``IEXTEN'' termios
141 withMode termios KeyboardInterrupts = setLocalFlag ``ISIG'' termios
142 withMode termios NoFlushOnInterrupt = clearLocalFlag ``NOFLSH'' termios
143 withMode termios BackgroundWriteInterrupt = setLocalFlag ``TOSTOP'' termios
144
145 terminalMode :: TerminalMode -> TerminalAttributes -> Bool
146 terminalMode InterruptOnBreak = testInputFlag ``BRKINT''
147 terminalMode MapCRtoLF = testInputFlag ``ICRNL''
148 terminalMode IgnoreBreak = testInputFlag ``IGNBRK''
149 terminalMode IgnoreCR = testInputFlag ``IGNCR''
150 terminalMode IgnoreParityErrors = testInputFlag ``IGNPAR''
151 terminalMode MapLFtoCR = testInputFlag ``INLCR''
152 terminalMode CheckParity = testInputFlag ``INPCK''
153 terminalMode StripHighBit = testInputFlag ``ISTRIP''
154 terminalMode StartStopInput = testInputFlag ``IXOFF''
155 terminalMode StartStopOutput = testInputFlag ``IXON''
156 terminalMode MarkParityErrors = testInputFlag ``PARMRK''
157 terminalMode ProcessOutput = \ termios -> unsafePerformPrimIO (
158     _casm_ ``%r = ((struct termios *)%0)->c_oflag & OPOST;'' termios
159                                                     `thenPrimIO` \ (W# flags#) ->
160     returnPrimIO (flags# `neWord#` int2Word# 0#))
161 terminalMode LocalMode = testControlFlag ``CLOCAL''
162 terminalMode ReadEnable = testControlFlag ``CREAD''
163 terminalMode TwoStopBits = testControlFlag ``CSTOPB''
164 terminalMode HangupOnClose = testControlFlag ``HUPCL''
165 terminalMode EnableParity = testControlFlag ``PARENB''
166 terminalMode OddParity = testControlFlag ``PARODD''
167 terminalMode EnableEcho = testLocalFlag ``ECHO''
168 terminalMode EchoErase = testLocalFlag ``ECHOE''
169 terminalMode EchoKill = testLocalFlag ``ECHOK''
170 terminalMode EchoLF = testLocalFlag ``ECHONL''
171 terminalMode ProcessInput = testLocalFlag ``ICANON''
172 terminalMode ExtendedFunctions = testLocalFlag ``IEXTEN''
173 terminalMode KeyboardInterrupts = testLocalFlag ``ISIG''
174 terminalMode NoFlushOnInterrupt = not . testLocalFlag ``NOFLSH''
175 terminalMode BackgroundWriteInterrupt = testLocalFlag ``TOSTOP''
176
177 bitsPerByte :: TerminalAttributes -> Int
178 bitsPerByte termios = unsafePerformPrimIO (
179     _casm_ ``%r = ((struct termios *)%0)->c_cflag & CSIZE;'' termios
180                                                     `thenPrimIO` \ w ->
181     returnPrimIO (word2Bits w))
182   where
183     word2Bits :: _Word -> Int
184     word2Bits x =
185         if x == ``CS5'' then 5
186         else if x == ``CS6'' then 6
187         else if x == ``CS7'' then 7
188         else if x == ``CS8'' then 8
189         else 0
190
191 withBits :: TerminalAttributes -> Int -> TerminalAttributes
192 withBits termios bits = unsafePerformPrimIO (
193     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
194     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
195              ((struct termios *)%0)->c_cflag = 
196              (((struct termios *)%1)->c_cflag & ~CSIZE) | %2;'' 
197         bytes termios (mask bits)                   `thenPrimIO` \ () ->
198     freeze bytes                                    `thenStrictlyST` \ termios ->
199     returnPrimIO termios)
200   where
201     mask :: Int -> _Word
202     mask 5 = ``CS5''
203     mask 6 = ``CS6''
204     mask 7 = ``CS7''
205     mask 8 = ``CS8''
206     mask _ = error "withBits bit value out of range [5..8]"
207
208 data ControlCharacter = EndOfFile
209                       | EndOfLine
210                       | Erase
211                       | Interrupt
212                       | Kill
213                       | Quit
214                       | Suspend
215                       | Start
216                       | Stop
217
218 controlChar :: TerminalAttributes -> ControlCharacter -> Maybe Char
219 controlChar termios cc = unsafePerformPrimIO (
220     _casm_ ``%r = ((struct termios *)%0)->c_cc[%1];'' termios (cc2Word cc)
221                                                     `thenPrimIO` \ val ->
222     if val == ``_POSIX_VDISABLE'' then
223         returnPrimIO Nothing
224     else
225         returnPrimIO (Just (chr val)))
226
227 withCC :: TerminalAttributes 
228        -> (ControlCharacter, Char)
229        -> TerminalAttributes
230 withCC termios (cc, c) = unsafePerformPrimIO (
231     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
232     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
233              ((struct termios *)%0)->c_cc[%2] = %3;'' 
234         bytes termios (cc2Word cc) c                `thenPrimIO` \ () ->
235     freeze bytes                                    `thenStrictlyST` \ termios ->
236     returnPrimIO termios)
237
238 withoutCC :: TerminalAttributes 
239           -> ControlCharacter 
240           -> TerminalAttributes
241 withoutCC termios cc = unsafePerformPrimIO (
242     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
243     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
244              ((struct termios *)%0)->c_cc[%2] = _POSIX_VDISABLE;'' 
245         bytes termios (cc2Word cc)                  `thenPrimIO` \ () ->
246     freeze bytes                                    `thenStrictlyST` \ termios ->
247     returnPrimIO termios)
248
249 inputTime :: TerminalAttributes -> Int
250 inputTime termios = unsafePerformPrimIO (
251     _casm_ ``%r = ((struct termios *)%0)->c_cc[VTIME];'' termios
252                                                     `thenPrimIO` \ count ->
253     returnPrimIO count)
254
255 withTime :: TerminalAttributes -> Int -> TerminalAttributes
256 withTime termios time = unsafePerformPrimIO (
257     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
258     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
259              ((struct termios *)%0)->c_cc[VTIME] = %2;'' bytes termios time
260                                                     `thenPrimIO` \ () ->
261     freeze bytes                                    `thenStrictlyST` \ termios ->
262     returnPrimIO termios)
263
264 minInput :: TerminalAttributes -> Int
265 minInput termios = unsafePerformPrimIO (
266     _casm_ ``%r = ((struct termios *)%0)->c_cc[VMIN];'' termios
267                                                     `thenPrimIO` \ count ->
268     returnPrimIO count)
269
270 withMinInput :: TerminalAttributes -> Int -> TerminalAttributes
271 withMinInput termios count = unsafePerformPrimIO (
272     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
273     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
274              ((struct termios *)%0)->c_cc[VMIN] = %2;'' bytes termios count
275                                                     `thenPrimIO` \ () ->
276     freeze bytes                                    `thenStrictlyST` \ termios ->
277     returnPrimIO termios)
278
279 data BaudRate = B0 
280               | B50 
281               | B75 
282               | B110 
283               | B134 
284               | B150 
285               | B200 
286               | B300 
287               | B600
288               | B1200 
289               | B1800 
290               | B2400 
291               | B4800 
292               | B9600 
293               | B19200 
294               | B38400
295
296 inputSpeed :: TerminalAttributes -> BaudRate
297 inputSpeed termios = unsafePerformPrimIO (
298     _casm_ ``%r = cfgetispeed((struct termios *)%0);'' termios
299                                                     `thenPrimIO` \ w ->
300     returnPrimIO (word2Baud w))
301
302 withInputSpeed :: TerminalAttributes -> BaudRate -> TerminalAttributes
303 withInputSpeed termios br = unsafePerformPrimIO (
304     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
305     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
306              cfsetispeed((struct termios *)%0, %2);'' bytes termios (baud2Word br)
307                                                     `thenPrimIO` \ () ->
308     freeze bytes                                    `thenStrictlyST` \ termios ->
309     returnPrimIO termios)
310
311 outputSpeed :: TerminalAttributes -> BaudRate
312 outputSpeed termios = unsafePerformPrimIO (
313     _casm_ ``%r = cfgetospeed((struct termios *)%0);'' termios
314                                                     `thenPrimIO` \ w ->
315     returnPrimIO (word2Baud w))
316
317 withOutputSpeed :: TerminalAttributes -> BaudRate -> TerminalAttributes
318 withOutputSpeed termios br = unsafePerformPrimIO (
319     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
320     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
321              cfsetospeed((struct termios *)%0, %2);'' bytes termios (baud2Word br)
322                                                     `thenPrimIO` \ () ->
323     freeze bytes                                    `thenStrictlyST` \ termios ->
324     returnPrimIO termios)
325
326 getTerminalAttributes :: Channel -> IO TerminalAttributes
327 getTerminalAttributes fd =
328     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
329     _casm_ ``%r = tcgetattr(%0,(struct termios *)%1);'' fd bytes
330                                                     `thenPrimIO` \ rc ->
331     if rc /= -1 then
332         freeze bytes                                `thenStrictlyST` \ termios ->
333         return termios
334     else
335         syserr "getTerminalAttributes"
336
337 data TerminalState = Immediately
338                    | WhenDrained 
339                    | WhenFlushed
340
341 setTerminalAttributes :: Channel 
342                       -> TerminalAttributes 
343                       -> TerminalState
344                       -> IO ()
345 setTerminalAttributes fd termios state =
346     _casm_ ``%r = tcsetattr(%0,%1,(struct termios *)%2);'' fd (state2Int state) termios
347                                                     `thenPrimIO` \ rc ->
348     if rc /= -1 then
349         return ()
350     else
351         syserr "setTerminalAttributes"
352   where
353     state2Int :: TerminalState -> Int
354     state2Int Immediately = ``TCSANOW''
355     state2Int WhenDrained = ``TCSADRAIN''
356     state2Int WhenFlushed = ``TCSAFLUSH''
357
358 sendBreak :: Channel -> Int -> IO ()
359 sendBreak fd duration = 
360     _ccall_ tcsendbreak fd duration                 `thenPrimIO` \ rc ->
361     if rc == 0 then
362         return ()
363     else
364         syserr "sendBreak"
365
366 drainOutput :: Channel -> IO ()
367 drainOutput fd = 
368     _ccall_ tcdrain fd                              `thenPrimIO` \ rc ->
369     if rc == 0 then
370         return ()
371     else
372         syserr "drainOutput"
373
374 data QueueSelector = InputQueue 
375                    | OutputQueue 
376                    | BothQueues
377
378 discardData :: Channel -> QueueSelector -> IO ()
379 discardData fd queue =
380     _ccall_ tcflush fd (queue2Int queue)            `thenPrimIO` \ rc ->
381     if rc /= -1 then
382         return ()
383     else
384         syserr "discardData"
385   where
386     queue2Int :: QueueSelector -> Int
387     queue2Int InputQueue  = ``TCIFLUSH''
388     queue2Int OutputQueue = ``TCOFLUSH''
389     queue2Int BothQueues  = ``TCIOFLUSH''
390
391 data FlowAction = SuspendOutput 
392                 | RestartOutput 
393                 | TransmitStop 
394                 | TransmitStart
395
396 controlFlow :: Channel -> FlowAction -> IO ()
397 controlFlow fd action = 
398     _ccall_ tcflow fd (action2Int action)           `thenPrimIO` \ rc ->
399     if rc /= -1 then
400         return ()
401     else
402         syserr "controlFlow"
403   where
404     action2Int :: FlowAction -> Int
405     action2Int SuspendOutput = ``TCOOFF''
406     action2Int RestartOutput = ``TCOON''
407     action2Int TransmitStop  = ``TCIOFF''
408     action2Int TransmitStart = ``TCION''
409
410 getTerminalProcessGroupID :: Channel -> IO ProcessGroupID
411 getTerminalProcessGroupID fd =
412     _ccall_ tcgetpgrp fd                            `thenPrimIO` \ pgid ->
413     if pgid /= -1 then
414         return pgid
415     else
416         syserr "getTerminalProcessGroupID"
417
418 setTerminalProcessGroupID :: Channel -> ProcessGroupID -> IO ()
419 setTerminalProcessGroupID fd pgid =
420     _ccall_ tcsetpgrp fd pgid                       `thenPrimIO` \ rc ->
421     if rc == 0 then
422         return ()
423     else
424         syserr "setTerminalProcessGroupID"
425
426 \end{code}
427
428 Local utility functions
429
430 \begin{code}
431
432 -- Convert Haskell ControlCharacter to Int
433
434 cc2Word :: ControlCharacter -> _Word
435 cc2Word EndOfFile = ``VEOF''
436 cc2Word EndOfLine = ``VEOL''
437 cc2Word Erase     = ``VERASE''
438 cc2Word Interrupt = ``VINTR''
439 cc2Word Kill      = ``VKILL''
440 cc2Word Quit      = ``VQUIT''
441 cc2Word Suspend   = ``VSUSP''
442 cc2Word Start     = ``VSTART''
443 cc2Word Stop      = ``VSTOP''
444
445 -- Convert Haskell BaudRate to unsigned integral type (_Word)
446
447 baud2Word :: BaudRate -> _Word
448 baud2Word B0 = ``B0''
449 baud2Word B50 = ``B50''
450 baud2Word B75 = ``B75''
451 baud2Word B110 = ``B110''
452 baud2Word B134 = ``B134''
453 baud2Word B150 = ``B150''
454 baud2Word B200 = ``B200''
455 baud2Word B300 = ``B300''
456 baud2Word B600 = ``B600''
457 baud2Word B1200 = ``B1200''
458 baud2Word B1800 = ``B1800''
459 baud2Word B2400 = ``B2400''
460 baud2Word B4800 = ``B4800''
461 baud2Word B9600 = ``B9600''
462 baud2Word B19200 = ``B19200''
463 baud2Word B38400 = ``B38400''
464
465 -- And convert a word back to a baud rate
466 -- We really need some cpp macros here.
467
468 word2Baud :: _Word -> BaudRate
469 word2Baud x =
470     if x == ``B0'' then B0
471     else if x == ``B50'' then B50
472     else if x == ``B75'' then B75
473     else if x == ``B110'' then B110
474     else if x == ``B134'' then B134
475     else if x == ``B150'' then B150
476     else if x == ``B200'' then B200
477     else if x == ``B300'' then B300
478     else if x == ``B600'' then B600
479     else if x == ``B1200'' then B1200
480     else if x == ``B1800'' then B1800
481     else if x == ``B2400'' then B2400
482     else if x == ``B4800'' then B4800
483     else if x == ``B9600'' then B9600
484     else if x == ``B19200'' then B19200
485     else if x == ``B38400'' then B38400
486     else error "unknown baud rate"
487
488 -- Clear termios i_flag
489
490 clearInputFlag :: _Word -> TerminalAttributes -> TerminalAttributes
491 clearInputFlag flag termios = unsafePerformPrimIO (
492     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
493     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
494              ((struct termios *)%0)->c_iflag &= ~%2;'' bytes termios flag
495                                                     `thenPrimIO` \ () ->
496     freeze bytes                                    `thenStrictlyST` \ termios ->
497     returnPrimIO termios)
498
499 -- Set termios i_flag
500
501 setInputFlag :: _Word -> TerminalAttributes -> TerminalAttributes
502 setInputFlag flag termios = unsafePerformPrimIO (
503     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
504     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
505              ((struct termios *)%0)->c_iflag |= %2;'' bytes termios flag
506                                                     `thenPrimIO` \ () ->
507     freeze bytes                                    `thenStrictlyST` \ termios ->
508     returnPrimIO termios)
509
510 -- Examine termios i_flag
511
512 testInputFlag :: _Word -> TerminalAttributes -> Bool
513 testInputFlag flag termios = unsafePerformPrimIO (
514     _casm_ ``%r = ((struct termios *)%0)->c_iflag & %1;'' termios flag
515                                                     `thenPrimIO` \ (W# flags#) ->
516     returnPrimIO (flags# `neWord#` int2Word# 0#))
517
518 -- Clear termios c_flag
519
520 clearControlFlag :: _Word -> TerminalAttributes -> TerminalAttributes
521 clearControlFlag flag termios = unsafePerformPrimIO (
522     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
523     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
524              ((struct termios *)%0)->c_cflag &= ~%2;'' bytes termios flag
525                                                     `thenPrimIO` \ () ->
526     freeze bytes                                    `thenStrictlyST` \ termios ->
527     returnPrimIO termios)
528
529 -- Set termios c_flag
530
531 setControlFlag :: _Word -> TerminalAttributes -> TerminalAttributes
532 setControlFlag flag termios = unsafePerformPrimIO (
533     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
534     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
535              ((struct termios *)%0)->c_cflag |= %2;'' bytes termios flag
536                                                     `thenPrimIO` \ () ->
537     freeze bytes                                    `thenStrictlyST` \ termios ->
538     returnPrimIO termios)
539
540 -- Examine termios c_flag
541
542 testControlFlag :: _Word -> TerminalAttributes -> Bool
543 testControlFlag flag termios = unsafePerformPrimIO (
544     _casm_ ``%r = ((struct termios *)%0)->c_cflag & %1;'' termios flag
545                                                     `thenPrimIO` \ (W# flags#) ->
546     returnPrimIO (flags# `neWord#` int2Word# 0#))
547
548 -- Clear termios l_flag
549
550 clearLocalFlag :: _Word -> TerminalAttributes -> TerminalAttributes
551 clearLocalFlag flag termios = unsafePerformPrimIO (
552     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
553     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
554              ((struct termios *)%0)->c_lflag &= ~%2;'' bytes termios flag
555                                                     `thenPrimIO` \ () ->
556     freeze bytes                                    `thenStrictlyST` \ termios ->
557     returnPrimIO termios)
558
559 -- Set termios l_flag
560
561 setLocalFlag :: _Word -> TerminalAttributes -> TerminalAttributes
562 setLocalFlag flag termios = unsafePerformPrimIO (
563     allocChars ``sizeof(struct termios)''           `thenStrictlyST` \ bytes ->
564     _casm_ ``*(struct termios *)%0 = *(struct termios *)%1;
565              ((struct termios *)%0)->c_lflag |= %2;'' bytes termios flag
566                                                     `thenPrimIO` \ () ->
567     freeze bytes                                    `thenStrictlyST` \ termios ->
568     returnPrimIO termios)
569
570 -- Examine termios l_flag
571
572 testLocalFlag :: _Word -> TerminalAttributes -> Bool
573 testLocalFlag flag termios = unsafePerformPrimIO (
574     _casm_ ``%r = ((struct termios *)%0)->c_iflag & %1;'' termios flag
575                                                     `thenPrimIO` \ (W# flags#) ->
576     returnPrimIO (flags# `neWord#` int2Word# 0#))
577
578 \end{code}