Remove readline hack from gdb_select
[deliverable/binutils-gdb.git] / gdb / mingw-hdep.c
1 /* Host support routines for MinGW, for GDB, the GNU debugger.
2
3 Copyright (C) 2006-2019 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21 #include "main.h"
22 #include "serial.h"
23 #include "event-loop.h"
24
25 #include "gdb_select.h"
26
27 #include <windows.h>
28
29 /* Return an absolute file name of the running GDB, if possible, or
30 ARGV0 if not. The return value is in malloc'ed storage. */
31
32 char *
33 windows_get_absolute_argv0 (const char *argv0)
34 {
35 char full_name[PATH_MAX];
36
37 if (GetModuleFileName (NULL, full_name, PATH_MAX))
38 return xstrdup (full_name);
39 return xstrdup (argv0);
40 }
41
42 /* Wrapper for select. On Windows systems, where the select interface
43 only works for sockets, this uses the GDB serial abstraction to
44 handle sockets, consoles, pipes, and serial ports.
45
46 The arguments to this function are the same as the traditional
47 arguments to select on POSIX platforms. */
48
49 int
50 gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
51 struct timeval *timeout)
52 {
53 static HANDLE never_handle;
54 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
55 HANDLE h;
56 DWORD event;
57 DWORD num_handles;
58 /* SCBS contains serial control objects corresponding to file
59 descriptors in READFDS and WRITEFDS. */
60 struct serial *scbs[MAXIMUM_WAIT_OBJECTS];
61 /* The number of valid entries in SCBS. */
62 size_t num_scbs;
63 int fd;
64 int num_ready;
65 size_t indx;
66
67 num_ready = 0;
68 num_handles = 0;
69 num_scbs = 0;
70 for (fd = 0; fd < n; ++fd)
71 {
72 HANDLE read = NULL, except = NULL;
73 struct serial *scb;
74
75 /* There is no support yet for WRITEFDS. At present, this isn't
76 used by GDB -- but we do not want to silently ignore WRITEFDS
77 if something starts using it. */
78 gdb_assert (!writefds || !FD_ISSET (fd, writefds));
79
80 if ((!readfds || !FD_ISSET (fd, readfds))
81 && (!exceptfds || !FD_ISSET (fd, exceptfds)))
82 continue;
83
84 scb = serial_for_fd (fd);
85 if (scb)
86 {
87 serial_wait_handle (scb, &read, &except);
88 scbs[num_scbs++] = scb;
89 }
90
91 if (read == NULL)
92 read = (HANDLE) _get_osfhandle (fd);
93 if (except == NULL)
94 {
95 if (!never_handle)
96 never_handle = CreateEvent (0, FALSE, FALSE, 0);
97
98 except = never_handle;
99 }
100
101 if (readfds && FD_ISSET (fd, readfds))
102 {
103 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
104 handles[num_handles++] = read;
105 }
106
107 if (exceptfds && FD_ISSET (fd, exceptfds))
108 {
109 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
110 handles[num_handles++] = except;
111 }
112 }
113
114 gdb_assert (num_handles <= MAXIMUM_WAIT_OBJECTS);
115
116 event = WaitForMultipleObjects (num_handles,
117 handles,
118 FALSE,
119 timeout
120 ? (timeout->tv_sec * 1000
121 + timeout->tv_usec / 1000)
122 : INFINITE);
123 /* EVENT can only be a value in the WAIT_ABANDONED_0 range if the
124 HANDLES included an abandoned mutex. Since GDB doesn't use
125 mutexes, that should never occur. */
126 gdb_assert (!(WAIT_ABANDONED_0 <= event
127 && event < WAIT_ABANDONED_0 + num_handles));
128 /* We no longer need the helper threads to check for activity. */
129 for (indx = 0; indx < num_scbs; ++indx)
130 serial_done_wait_handle (scbs[indx]);
131 if (event == WAIT_FAILED)
132 return -1;
133 if (event == WAIT_TIMEOUT)
134 return 0;
135 /* Run through the READFDS, clearing bits corresponding to descriptors
136 for which input is unavailable. */
137 h = handles[event - WAIT_OBJECT_0];
138 for (fd = 0, indx = 0; fd < n; ++fd)
139 {
140 HANDLE fd_h;
141
142 if ((!readfds || !FD_ISSET (fd, readfds))
143 && (!exceptfds || !FD_ISSET (fd, exceptfds)))
144 continue;
145
146 if (readfds && FD_ISSET (fd, readfds))
147 {
148 fd_h = handles[indx++];
149 /* This handle might be ready, even though it wasn't the handle
150 returned by WaitForMultipleObjects. */
151 if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
152 FD_CLR (fd, readfds);
153 else
154 num_ready++;
155 }
156
157 if (exceptfds && FD_ISSET (fd, exceptfds))
158 {
159 fd_h = handles[indx++];
160 /* This handle might be ready, even though it wasn't the handle
161 returned by WaitForMultipleObjects. */
162 if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
163 FD_CLR (fd, exceptfds);
164 else
165 num_ready++;
166 }
167 }
168
169 return num_ready;
170 }
171
172 /* Map COLOR's RGB triplet, with 8 bits per component, into 16 Windows
173 console colors, where each component has just 1 bit, plus a single
174 intensity bit which affects all 3 components. */
175 static int
176 rgb_to_16colors (const ui_file_style::color &color)
177 {
178 uint8_t rgb[3];
179 color.get_rgb (rgb);
180
181 int retval = 0;
182 for (int i = 0; i < 3; i++)
183 {
184 /* Subdivide 256 possible values of each RGB component into 3
185 regions: no color, normal color, bright color. 256 / 3 = 85,
186 but ui-style.c follows xterm and uses 92 for R and G
187 components of the bright-blue color, so we bias the divisor a
188 bit to have the bright colors between 9 and 15 identical to
189 what ui-style.c expects. */
190 int bits = rgb[i] / 93;
191 retval |= ((bits > 0) << (2 - i)) | ((bits > 1) << 3);
192 }
193
194 return retval;
195 }
196
197 /* Zero if not yet initialized, 1 if stdout is a console device, else -1. */
198 static int mingw_console_initialized;
199
200 /* Handle to stdout . */
201 static HANDLE hstdout = INVALID_HANDLE_VALUE;
202
203 /* Text attribute to use for normal text (the "none" pseudo-color). */
204 static SHORT norm_attr;
205
206 /* The most recently applied style. */
207 static ui_file_style last_style;
208
209 /* Alternative for the libc 'fputs' which handles embedded SGR
210 sequences in support of styling. */
211
212 int
213 gdb_console_fputs (const char *linebuf, FILE *fstream)
214 {
215 if (!mingw_console_initialized)
216 {
217 hstdout = (HANDLE)_get_osfhandle (fileno (fstream));
218 DWORD cmode;
219 CONSOLE_SCREEN_BUFFER_INFO csbi;
220
221 if (hstdout != INVALID_HANDLE_VALUE
222 && GetConsoleMode (hstdout, &cmode) != 0
223 && GetConsoleScreenBufferInfo (hstdout, &csbi))
224 {
225 norm_attr = csbi.wAttributes;
226 mingw_console_initialized = 1;
227 }
228 else if (hstdout != INVALID_HANDLE_VALUE)
229 mingw_console_initialized = -1; /* valid, but not a console device */
230 }
231 /* If our stdout is not a console device, let the default 'fputs'
232 handle the task. */
233 if (mingw_console_initialized <= 0)
234 return 0;
235
236 /* Mapping between 8 ANSI colors and Windows console attributes. */
237 static int fg_color[] = {
238 0, /* black */
239 FOREGROUND_RED, /* red */
240 FOREGROUND_GREEN, /* green */
241 FOREGROUND_GREEN | FOREGROUND_RED, /* yellow */
242 FOREGROUND_BLUE, /* blue */
243 FOREGROUND_BLUE | FOREGROUND_RED, /* magenta */
244 FOREGROUND_BLUE | FOREGROUND_GREEN, /* cyan */
245 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE /* gray */
246 };
247 static int bg_color[] = {
248 0, /* black */
249 BACKGROUND_RED, /* red */
250 BACKGROUND_GREEN, /* green */
251 BACKGROUND_GREEN | BACKGROUND_RED, /* yellow */
252 BACKGROUND_BLUE, /* blue */
253 BACKGROUND_BLUE | BACKGROUND_RED, /* magenta */
254 BACKGROUND_BLUE | BACKGROUND_GREEN, /* cyan */
255 BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE /* gray */
256 };
257
258 ui_file_style style = last_style;
259 unsigned char c;
260 size_t n_read;
261
262 for ( ; (c = *linebuf) != 0; linebuf += n_read)
263 {
264 if (c == '\033')
265 {
266 fflush (fstream);
267 bool parsed = style.parse (linebuf, &n_read);
268 if (n_read <= 0) /* should never happen */
269 n_read = 1;
270 if (!parsed)
271 {
272 /* This means we silently swallow SGR sequences we
273 cannot parse. */
274 continue;
275 }
276 /* Colors. */
277 const ui_file_style::color &fg = style.get_foreground ();
278 const ui_file_style::color &bg = style.get_background ();
279 int fgcolor, bgcolor, bright, inverse;
280 if (fg.is_none ())
281 fgcolor = norm_attr & 15;
282 else if (fg.is_basic ())
283 fgcolor = fg_color[fg.get_value () & 15];
284 else
285 fgcolor = rgb_to_16colors (fg);
286 if (bg.is_none ())
287 bgcolor = norm_attr & (15 << 4);
288 else if (bg.is_basic ())
289 bgcolor = bg_color[bg.get_value () & 15];
290 else
291 bgcolor = rgb_to_16colors (bg) << 4;
292
293 /* Intensity. */
294 switch (style.get_intensity ())
295 {
296 case ui_file_style::NORMAL:
297 case ui_file_style::DIM:
298 bright = 0;
299 break;
300 case ui_file_style::BOLD:
301 bright = 1;
302 break;
303 default:
304 gdb_assert_not_reached ("invalid intensity");
305 }
306
307 /* Inverse video. */
308 if (style.is_reverse ())
309 inverse = 1;
310 else
311 inverse = 0;
312
313 /* Construct the attribute. */
314 if (inverse)
315 {
316 int t = fgcolor;
317 fgcolor = (bgcolor >> 4);
318 bgcolor = (t << 4);
319 }
320 if (bright)
321 fgcolor |= FOREGROUND_INTENSITY;
322
323 SHORT attr = (bgcolor & (15 << 4)) | (fgcolor & 15);
324
325 /* Apply the attribute. */
326 SetConsoleTextAttribute (hstdout, attr);
327 }
328 else
329 {
330 /* When we are about to write newline, we need to clear to
331 EOL with the normal attribute, to avoid spilling the
332 colors to the next screen line. We assume here that no
333 non-default attribute extends beyond the newline. */
334 if (c == '\n')
335 {
336 DWORD nchars;
337 COORD start_pos;
338 DWORD written;
339 CONSOLE_SCREEN_BUFFER_INFO csbi;
340
341 fflush (fstream);
342 GetConsoleScreenBufferInfo (hstdout, &csbi);
343
344 if (csbi.wAttributes != norm_attr)
345 {
346 start_pos = csbi.dwCursorPosition;
347 nchars = csbi.dwSize.X - start_pos.X;
348
349 FillConsoleOutputAttribute (hstdout, norm_attr, nchars,
350 start_pos, &written);
351 FillConsoleOutputCharacter (hstdout, ' ', nchars,
352 start_pos, &written);
353 }
354 }
355 fputc (c, fstream);
356 n_read = 1;
357 }
358 }
359
360 last_style = style;
361 return 1;
362 }
This page took 0.052968 seconds and 5 git commands to generate.