Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 1999-2006, 2008 Henry Cejtin, Matthew Fluet, Suresh |
2 | * Jagannathan, and Stephen Weeks. | |
3 | * Copyright (C) 1997-2000 NEC Research Institute. | |
4 | * | |
5 | * MLton is released under a BSD-style license. | |
6 | * See the file MLton-LICENSE for details. | |
7 | *) | |
8 | ||
9 | structure PosixTTY: POSIX_TTY = | |
10 | struct | |
11 | structure Prim = PrimitiveFFI.Posix.TTY | |
12 | open Prim | |
13 | structure FileDesc = PrePosix.FileDesc | |
14 | structure PId = PrePosix.PId | |
15 | ||
16 | structure Error = PosixError | |
17 | structure SysCall = Error.SysCall | |
18 | ||
19 | type file_desc = FileDesc.t | |
20 | type pid = PId.t | |
21 | ||
22 | structure V = | |
23 | struct | |
24 | open V | |
25 | val nccs = C_Int.toInt NCCS | |
26 | val eof = C_Int.toInt VEOF | |
27 | val eol = C_Int.toInt VEOL | |
28 | val erase = C_Int.toInt VERASE | |
29 | val intr = C_Int.toInt VINTR | |
30 | val kill = C_Int.toInt VKILL | |
31 | val min = C_Int.toInt VMIN | |
32 | val quit = C_Int.toInt VQUIT | |
33 | val susp = C_Int.toInt VSUSP | |
34 | val time = C_Int.toInt VTIME | |
35 | val start = C_Int.toInt VSTART | |
36 | val stop = C_Int.toInt VSTOP | |
37 | ||
38 | type cc = C_CC.t array | |
39 | ||
40 | val default = C_CC.castFromSysWord 0w0 | |
41 | ||
42 | fun new () = Array.array (nccs, default) | |
43 | ||
44 | fun updates (a, l) = | |
45 | List.app (fn (i, cc) => | |
46 | Array.update (a, i, (C_CC.castFromSysWord o Word8.castToSysWord o Byte.charToByte) cc)) | |
47 | l | |
48 | ||
49 | fun cc l = let val a = new () | |
50 | in updates (a, l) | |
51 | ; a | |
52 | end | |
53 | ||
54 | fun update (a, l) = | |
55 | let val a' = new () | |
56 | in Array.copy {src = a, dst = a', di = 0} | |
57 | ; updates (a', l) | |
58 | ; a' | |
59 | end | |
60 | ||
61 | val sub = (Byte.byteToChar o Word8.castFromSysWord o C_CC.castToSysWord) o Array.sub | |
62 | end | |
63 | ||
64 | structure Flags = BitFlags(structure S = C_TCFlag) | |
65 | structure I = | |
66 | struct | |
67 | open I Flags | |
68 | val brkint = BRKINT | |
69 | val icrnl = ICRNL | |
70 | val ignbrk = IGNBRK | |
71 | val igncr = IGNCR | |
72 | val ignpar = IGNPAR | |
73 | val inlcr = INLCR | |
74 | val inpck = INPCK | |
75 | val istrip = ISTRIP | |
76 | val ixany = IXANY | |
77 | val ixoff = IXOFF | |
78 | val ixon = IXON | |
79 | val parmrk = PARMRK | |
80 | end | |
81 | ||
82 | structure O = | |
83 | struct | |
84 | open O Flags | |
85 | val bs0 = BS0 | |
86 | val bs1 = BS1 | |
87 | val bsdly = BSDLY | |
88 | val cr0 = CR0 | |
89 | val cr1 = CR1 | |
90 | val cr2 = CR2 | |
91 | val cr3 = CR3 | |
92 | val crdly = CRDLY | |
93 | val ff0 = FF0 | |
94 | val ff1 = FF1 | |
95 | val ffdly = FFDLY | |
96 | val nl0 = NL0 | |
97 | val nl1 = NL1 | |
98 | val onldly = NLDLY | |
99 | val ocrnl = OCRNL | |
100 | val ofill = OFILL | |
101 | val onlcr = ONLCR | |
102 | val onlret = ONLRET | |
103 | val onocr = ONOCR | |
104 | val opost = OPOST | |
105 | val tab0 = TAB0 | |
106 | val tab1 = TAB1 | |
107 | val tab2 = TAB2 | |
108 | val tab3 = TAB3 | |
109 | val tabdly = TABDLY | |
110 | val vt0 = VT0 | |
111 | val vt1 = VT1 | |
112 | val vtdly = VTDLY | |
113 | end | |
114 | ||
115 | structure C = | |
116 | struct | |
117 | open C Flags | |
118 | val clocal = CLOCAL | |
119 | val cread = CREAD | |
120 | val cs5 = CS5 | |
121 | val cs6 = CS6 | |
122 | val cs7 = CS7 | |
123 | val cs8 = CS8 | |
124 | val csize = CSIZE | |
125 | val cstopb = CSTOPB | |
126 | val hupcl = HUPCL | |
127 | val parenb = PARENB | |
128 | val parodd = PARODD | |
129 | end | |
130 | ||
131 | structure L = | |
132 | struct | |
133 | open L Flags | |
134 | val echo = ECHO | |
135 | val echoe = ECHOE | |
136 | val echok = ECHOK | |
137 | val echonl = ECHONL | |
138 | val icanon = ICANON | |
139 | val iexten = IEXTEN | |
140 | val isig = ISIG | |
141 | val noflsh = NOFLSH | |
142 | val tostop = TOSTOP | |
143 | end | |
144 | ||
145 | type speed = C_Speed.t | |
146 | ||
147 | val b0 = B0 | |
148 | val b110 = B110 | |
149 | val b1200 = B1200 | |
150 | val b134 = B134 | |
151 | val b150 = B150 | |
152 | val b1800 = B1800 | |
153 | val b19200 = B19200 | |
154 | val b200 = B200 | |
155 | val b2400 = B2400 | |
156 | val b300 = B300 | |
157 | val b38400 = B38400 | |
158 | val b4800 = B4800 | |
159 | val b50 = B50 | |
160 | val b600 = B600 | |
161 | val b75 = B75 | |
162 | val b9600 = B9600 | |
163 | ||
164 | val compareSpeed = C_Speed.compare | |
165 | val speedToWord = C_Speed.castToSysWord | |
166 | val wordToSpeed = C_Speed.castFromSysWord | |
167 | ||
168 | type termios = {iflag: I.flags, | |
169 | oflag: O.flags, | |
170 | cflag: C.flags, | |
171 | lflag: L.flags, | |
172 | cc: V.cc, | |
173 | ispeed: speed, | |
174 | ospeed: speed} | |
175 | ||
176 | val id = fn x => x | |
177 | val termios = id | |
178 | val fieldsOf = id | |
179 | ||
180 | val getiflag: termios -> I.flags = #iflag | |
181 | val getoflag: termios -> O.flags = #oflag | |
182 | val getcflag: termios -> C.flags = #cflag | |
183 | val getlflag: termios -> L.flags = #oflag | |
184 | val getcc: termios -> V.cc = #cc | |
185 | ||
186 | structure CF = | |
187 | struct | |
188 | val getospeed: termios -> speed = #ospeed | |
189 | fun setospeed ({iflag, oflag, cflag, lflag, cc, ispeed, ...}: termios, | |
190 | ospeed: speed): termios = | |
191 | {iflag = iflag, | |
192 | oflag = oflag, | |
193 | cflag = cflag, | |
194 | lflag = lflag, | |
195 | cc = cc, | |
196 | ispeed = ispeed, | |
197 | ospeed = ospeed} | |
198 | ||
199 | val getispeed: termios -> speed = #ispeed | |
200 | ||
201 | fun setispeed ({iflag, oflag, cflag, lflag, cc, ospeed, ...}: termios, | |
202 | ispeed: speed): termios = | |
203 | {iflag = iflag, | |
204 | oflag = oflag, | |
205 | cflag = cflag, | |
206 | lflag = lflag, | |
207 | cc = cc, | |
208 | ispeed = ispeed, | |
209 | ospeed = ospeed} | |
210 | end | |
211 | ||
212 | structure Termios = Prim.Termios | |
213 | ||
214 | structure TC = | |
215 | struct | |
216 | open Prim.TC | |
217 | ||
218 | type set_action = C_Int.t | |
219 | val sadrain = TCSADRAIN | |
220 | val saflush = TCSAFLUSH | |
221 | val sanow = TCSANOW | |
222 | ||
223 | type flow_action = C_Int.t | |
224 | val ioff = TCIOFF | |
225 | val ion = TCION | |
226 | val ooff = TCOOFF | |
227 | val oon = TCOON | |
228 | ||
229 | type queue_sel = C_Int.t | |
230 | val iflush = TCIFLUSH | |
231 | val oflush = TCOFLUSH | |
232 | val ioflush = TCIOFLUSH | |
233 | ||
234 | fun getattr fd = | |
235 | SysCall.syscallRestart | |
236 | (fn () => | |
237 | (Prim.TC.getattr (FileDesc.toRep fd), fn _ => | |
238 | {iflag = Termios.getIFlag (), | |
239 | oflag = Termios.getOFlag (), | |
240 | cflag = Termios.getCFlag (), | |
241 | lflag = Termios.getLFlag (), | |
242 | cc = let val a = V.new () | |
243 | in Termios.getCC (a); a | |
244 | end, | |
245 | ispeed = Termios.cfGetISpeed (), | |
246 | ospeed = Termios.cfGetOSpeed ()})) | |
247 | ||
248 | fun setattr (fd, a, | |
249 | {iflag, oflag, cflag, lflag, cc, ispeed, ospeed}) = | |
250 | SysCall.syscallRestart | |
251 | (fn () => | |
252 | (Termios.setIFlag iflag | |
253 | ; Termios.setOFlag oflag | |
254 | ; Termios.setCFlag cflag | |
255 | ; Termios.setLFlag lflag | |
256 | ; SysCall.simple (fn () => Termios.cfSetOSpeed ospeed) | |
257 | ; SysCall.simple (fn () => Termios.cfSetISpeed ispeed) | |
258 | ; Termios.setCC cc | |
259 | ; (Prim.TC.setattr (FileDesc.toRep fd, a), fn _ => ()))) | |
260 | ||
261 | fun sendbreak (fd, n) = | |
262 | SysCall.simpleRestart | |
263 | (fn () => Prim.TC.sendbreak (FileDesc.toRep fd, C_Int.fromInt n)) | |
264 | ||
265 | fun drain fd = | |
266 | SysCall.simpleRestart | |
267 | (fn () => Prim.TC.drain (FileDesc.toRep fd)) | |
268 | ||
269 | fun flush (fd, n) = | |
270 | SysCall.simpleRestart | |
271 | (fn () => Prim.TC.flush (FileDesc.toRep fd, n)) | |
272 | ||
273 | fun flow (fd, n) = | |
274 | SysCall.simpleRestart | |
275 | (fn () => Prim.TC.flow (FileDesc.toRep fd, n)) | |
276 | ||
277 | fun getpgrp fd = | |
278 | (PId.fromRep o SysCall.simpleResultRestart') | |
279 | ({errVal = C_PId.castFromFixedInt ~1}, fn () => | |
280 | Prim.TC.getpgrp (FileDesc.toRep fd)) | |
281 | ||
282 | fun setpgrp (fd, pid) = | |
283 | SysCall.simpleRestart | |
284 | (fn () => Prim.TC.setpgrp (FileDesc.toRep fd, PId.toRep pid)) | |
285 | end | |
286 | end |