1 /* Host support routines for MinGW, for GDB, the GNU debugger.
3 Copyright (C) 2006-2019 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
23 #include "event-loop.h"
25 #include "gdb_select.h"
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. */
33 windows_get_absolute_argv0 (const char *argv0
)
35 char full_name
[PATH_MAX
];
37 if (GetModuleFileName (NULL
, full_name
, PATH_MAX
))
38 return xstrdup (full_name
);
39 return xstrdup (argv0
);
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.
46 The arguments to this function are the same as the traditional
47 arguments to select on POSIX platforms. */
50 gdb_select (int n
, fd_set
*readfds
, fd_set
*writefds
, fd_set
*exceptfds
,
51 struct timeval
*timeout
)
53 static HANDLE never_handle
;
54 HANDLE handles
[MAXIMUM_WAIT_OBJECTS
];
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. */
70 for (fd
= 0; fd
< n
; ++fd
)
72 HANDLE read
= NULL
, except
= NULL
;
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
));
80 if ((!readfds
|| !FD_ISSET (fd
, readfds
))
81 && (!exceptfds
|| !FD_ISSET (fd
, exceptfds
)))
84 scb
= serial_for_fd (fd
);
87 serial_wait_handle (scb
, &read
, &except
);
88 scbs
[num_scbs
++] = scb
;
92 read
= (HANDLE
) _get_osfhandle (fd
);
96 never_handle
= CreateEvent (0, FALSE
, FALSE
, 0);
98 except
= never_handle
;
101 if (readfds
&& FD_ISSET (fd
, readfds
))
103 gdb_assert (num_handles
< MAXIMUM_WAIT_OBJECTS
);
104 handles
[num_handles
++] = read
;
107 if (exceptfds
&& FD_ISSET (fd
, exceptfds
))
109 gdb_assert (num_handles
< MAXIMUM_WAIT_OBJECTS
);
110 handles
[num_handles
++] = except
;
114 gdb_assert (num_handles
<= MAXIMUM_WAIT_OBJECTS
);
116 event
= WaitForMultipleObjects (num_handles
,
120 ? (timeout
->tv_sec
* 1000
121 + timeout
->tv_usec
/ 1000)
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
)
133 if (event
== WAIT_TIMEOUT
)
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
)
142 if ((!readfds
|| !FD_ISSET (fd
, readfds
))
143 && (!exceptfds
|| !FD_ISSET (fd
, exceptfds
)))
146 if (readfds
&& FD_ISSET (fd
, readfds
))
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
);
157 if (exceptfds
&& FD_ISSET (fd
, exceptfds
))
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
);
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. */
176 rgb_to_16colors (const ui_file_style::color
&color
)
182 for (int i
= 0; i
< 3; i
++)
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);
197 /* Zero if not yet initialized, 1 if stdout is a console device, else -1. */
198 static int mingw_console_initialized
;
200 /* Handle to stdout . */
201 static HANDLE hstdout
= INVALID_HANDLE_VALUE
;
203 /* Text attribute to use for normal text (the "none" pseudo-color). */
204 static SHORT norm_attr
;
206 /* The most recently applied style. */
207 static ui_file_style last_style
;
209 /* Alternative for the libc 'fputs' which handles embedded SGR
210 sequences in support of styling. */
213 gdb_console_fputs (const char *linebuf
, FILE *fstream
)
215 if (!mingw_console_initialized
)
217 hstdout
= (HANDLE
)_get_osfhandle (fileno (fstream
));
219 CONSOLE_SCREEN_BUFFER_INFO csbi
;
221 if (hstdout
!= INVALID_HANDLE_VALUE
222 && GetConsoleMode (hstdout
, &cmode
) != 0
223 && GetConsoleScreenBufferInfo (hstdout
, &csbi
))
225 norm_attr
= csbi
.wAttributes
;
226 mingw_console_initialized
= 1;
228 else if (hstdout
!= INVALID_HANDLE_VALUE
)
229 mingw_console_initialized
= -1; /* valid, but not a console device */
231 /* If our stdout is not a console device, let the default 'fputs'
233 if (mingw_console_initialized
<= 0)
236 /* Mapping between 8 ANSI colors and Windows console attributes. */
237 static int fg_color
[] = {
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 */
247 static int bg_color
[] = {
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 */
258 ui_file_style style
= last_style
;
262 for ( ; (c
= *linebuf
) != 0; linebuf
+= n_read
)
267 bool parsed
= style
.parse (linebuf
, &n_read
);
268 if (n_read
<= 0) /* should never happen */
272 /* This means we silently swallow SGR sequences we
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
;
281 fgcolor
= norm_attr
& 15;
282 else if (fg
.is_basic ())
283 fgcolor
= fg_color
[fg
.get_value () & 15];
285 fgcolor
= rgb_to_16colors (fg
);
287 bgcolor
= norm_attr
& (15 << 4);
288 else if (bg
.is_basic ())
289 bgcolor
= bg_color
[bg
.get_value () & 15];
291 bgcolor
= rgb_to_16colors (bg
) << 4;
294 switch (style
.get_intensity ())
296 case ui_file_style::NORMAL
:
297 case ui_file_style::DIM
:
300 case ui_file_style::BOLD
:
304 gdb_assert_not_reached ("invalid intensity");
308 if (style
.is_reverse ())
313 /* Construct the attribute. */
317 fgcolor
= (bgcolor
>> 4);
321 fgcolor
|= FOREGROUND_INTENSITY
;
323 SHORT attr
= (bgcolor
& (15 << 4)) | (fgcolor
& 15);
325 /* Apply the attribute. */
326 SetConsoleTextAttribute (hstdout
, attr
);
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. */
339 CONSOLE_SCREEN_BUFFER_INFO csbi
;
342 GetConsoleScreenBufferInfo (hstdout
, &csbi
);
344 if (csbi
.wAttributes
!= norm_attr
)
346 start_pos
= csbi
.dwCursorPosition
;
347 nchars
= csbi
.dwSize
.X
- start_pos
.X
;
349 FillConsoleOutputAttribute (hstdout
, norm_attr
, nchars
,
350 start_pos
, &written
);
351 FillConsoleOutputCharacter (hstdout
, ' ', nchars
,
352 start_pos
, &written
);