1 /* Output generating routines for GDB CLI. 2 3 Copyright (C) 1999-2019 Free Software Foundation, Inc. 4 5 Contributed by Cygnus Solutions. 6 Written by Fernando Nasser for Cygnus. 7 8 This file is part of GDB. 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 3 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 22 23 #include "defs.h" 24 #include "ui-out.h" 25 #include "cli-out.h" 26 #include "completer.h" 27 #include "readline/readline.h" 28 #include "cli/cli-style.h" 29 30 /* These are the CLI output functions */ 31 32 /* Mark beginning of a table */ 33 34 void 35 cli_ui_out::do_table_begin (int nbrofcols, int nr_rows, const char *tblid) 36 { 37 if (nr_rows == 0) 38 m_suppress_output = true; 39 else 40 /* Only the table suppresses the output and, fortunately, a table 41 is not a recursive data structure. */ 42 gdb_assert (!m_suppress_output); 43 } 44 45 /* Mark beginning of a table body */ 46 47 void 48 cli_ui_out::do_table_body () 49 { 50 if (m_suppress_output) 51 return; 52 53 /* first, close the table header line */ 54 text ("\n"); 55 } 56 57 /* Mark end of a table */ 58 59 void 60 cli_ui_out::do_table_end () 61 { 62 m_suppress_output = false; 63 } 64 65 /* Specify table header */ 66 67 void 68 cli_ui_out::do_table_header (int width, ui_align alignment, 69 const std::string &col_name, 70 const std::string &col_hdr) 71 { 72 if (m_suppress_output) 73 return; 74 75 do_field_string (0, width, alignment, 0, col_hdr.c_str (), 76 ui_out_style_kind::DEFAULT); 77 } 78 79 /* Mark beginning of a list */ 80 81 void 82 cli_ui_out::do_begin (ui_out_type type, const char *id) 83 { 84 } 85 86 /* Mark end of a list */ 87 88 void 89 cli_ui_out::do_end (ui_out_type type) 90 { 91 } 92 93 /* output an int field */ 94 95 void 96 cli_ui_out::do_field_int (int fldno, int width, ui_align alignment, 97 const char *fldname, int value) 98 { 99 if (m_suppress_output) 100 return; 101 102 std::string str = string_printf ("%d", value); 103 104 do_field_string (fldno, width, alignment, fldname, str.c_str (), 105 ui_out_style_kind::DEFAULT); 106 } 107 108 /* used to omit a field */ 109 110 void 111 cli_ui_out::do_field_skip (int fldno, int width, ui_align alignment, 112 const char *fldname) 113 { 114 if (m_suppress_output) 115 return; 116 117 do_field_string (fldno, width, alignment, fldname, "", 118 ui_out_style_kind::DEFAULT); 119 } 120 121 /* other specific cli_field_* end up here so alignment and field 122 separators are both handled by cli_field_string */ 123 124 void 125 cli_ui_out::do_field_string (int fldno, int width, ui_align align, 126 const char *fldname, const char *string, 127 ui_out_style_kind style) 128 { 129 int before = 0; 130 int after = 0; 131 132 if (m_suppress_output) 133 return; 134 135 if ((align != ui_noalign) && string) 136 { 137 before = width - strlen (string); 138 if (before <= 0) 139 before = 0; 140 else 141 { 142 if (align == ui_right) 143 after = 0; 144 else if (align == ui_left) 145 { 146 after = before; 147 before = 0; 148 } 149 else 150 /* ui_center */ 151 { 152 after = before / 2; 153 before -= after; 154 } 155 } 156 } 157 158 if (before) 159 spaces (before); 160 161 if (string) 162 { 163 ui_file_style fstyle; 164 switch (style) 165 { 166 case ui_out_style_kind::DEFAULT: 167 /* Nothing. */ 168 break; 169 case ui_out_style_kind::FILE: 170 /* Nothing. */ 171 fstyle = file_name_style.style (); 172 break; 173 case ui_out_style_kind::FUNCTION: 174 fstyle = function_name_style.style (); 175 break; 176 case ui_out_style_kind::VARIABLE: 177 fstyle = variable_name_style.style (); 178 break; 179 case ui_out_style_kind::ADDRESS: 180 fstyle = address_style.style (); 181 break; 182 default: 183 gdb_assert_not_reached ("missing case"); 184 } 185 fputs_styled (string, fstyle, m_streams.back ()); 186 } 187 188 if (after) 189 spaces (after); 190 191 if (align != ui_noalign) 192 field_separator (); 193 } 194 195 /* Output field containing ARGS using printf formatting in FORMAT. */ 196 197 void 198 cli_ui_out::do_field_fmt (int fldno, int width, ui_align align, 199 const char *fldname, const char *format, 200 va_list args) 201 { 202 if (m_suppress_output) 203 return; 204 205 std::string str = string_vprintf (format, args); 206 207 do_field_string (fldno, width, align, fldname, str.c_str (), 208 ui_out_style_kind::DEFAULT); 209 } 210 211 void 212 cli_ui_out::do_spaces (int numspaces) 213 { 214 if (m_suppress_output) 215 return; 216 217 print_spaces_filtered (numspaces, m_streams.back ()); 218 } 219 220 void 221 cli_ui_out::do_text (const char *string) 222 { 223 if (m_suppress_output) 224 return; 225 226 fputs_filtered (string, m_streams.back ()); 227 } 228 229 void 230 cli_ui_out::do_message (const char *format, va_list args) 231 { 232 if (m_suppress_output) 233 return; 234 235 vfprintf_unfiltered (m_streams.back (), format, args); 236 } 237 238 void 239 cli_ui_out::do_wrap_hint (const char *identstring) 240 { 241 if (m_suppress_output) 242 return; 243 244 wrap_here (identstring); 245 } 246 247 void 248 cli_ui_out::do_flush () 249 { 250 gdb_flush (m_streams.back ()); 251 } 252 253 /* OUTSTREAM as non-NULL will push OUTSTREAM on the stack of output streams 254 and make it therefore active. OUTSTREAM as NULL will pop the last pushed 255 output stream; it is an internal error if it does not exist. */ 256 257 void 258 cli_ui_out::do_redirect (ui_file *outstream) 259 { 260 if (outstream != NULL) 261 m_streams.push_back (outstream); 262 else 263 m_streams.pop_back (); 264 } 265 266 /* local functions */ 267 268 void 269 cli_ui_out::field_separator () 270 { 271 fputc_filtered (' ', m_streams.back ()); 272 } 273 274 /* Constructor for cli_ui_out. */ 275 276 cli_ui_out::cli_ui_out (ui_file *stream, ui_out_flags flags) 277 : ui_out (flags), 278 m_suppress_output (false) 279 { 280 gdb_assert (stream != NULL); 281 282 m_streams.push_back (stream); 283 } 284 285 cli_ui_out::~cli_ui_out () 286 { 287 } 288 289 /* Initialize private members at startup. */ 290 291 cli_ui_out * 292 cli_out_new (struct ui_file *stream) 293 { 294 return new cli_ui_out (stream, ui_source_list); 295 } 296 297 ui_file * 298 cli_ui_out::set_stream (struct ui_file *stream) 299 { 300 ui_file *old; 301 302 old = m_streams.back (); 303 m_streams.back () = stream; 304 305 return old; 306 } 307 308 /* CLI interface to display tab-completion matches. */ 309 310 /* CLI version of displayer.crlf. */ 311 312 static void 313 cli_mld_crlf (const struct match_list_displayer *displayer) 314 { 315 rl_crlf (); 316 } 317 318 /* CLI version of displayer.putch. */ 319 320 static void 321 cli_mld_putch (const struct match_list_displayer *displayer, int ch) 322 { 323 putc (ch, rl_outstream); 324 } 325 326 /* CLI version of displayer.puts. */ 327 328 static void 329 cli_mld_puts (const struct match_list_displayer *displayer, const char *s) 330 { 331 fputs (s, rl_outstream); 332 } 333 334 /* CLI version of displayer.flush. */ 335 336 static void 337 cli_mld_flush (const struct match_list_displayer *displayer) 338 { 339 fflush (rl_outstream); 340 } 341 342 EXTERN_C void _rl_erase_entire_line (void); 343 344 /* CLI version of displayer.erase_entire_line. */ 345 346 static void 347 cli_mld_erase_entire_line (const struct match_list_displayer *displayer) 348 { 349 _rl_erase_entire_line (); 350 } 351 352 /* CLI version of displayer.beep. */ 353 354 static void 355 cli_mld_beep (const struct match_list_displayer *displayer) 356 { 357 rl_ding (); 358 } 359 360 /* CLI version of displayer.read_key. */ 361 362 static int 363 cli_mld_read_key (const struct match_list_displayer *displayer) 364 { 365 return rl_read_key (); 366 } 367 368 /* CLI version of rl_completion_display_matches_hook. 369 See gdb_display_match_list for a description of the arguments. */ 370 371 void 372 cli_display_match_list (char **matches, int len, int max) 373 { 374 struct match_list_displayer displayer; 375 376 rl_get_screen_size (&displayer.height, &displayer.width); 377 displayer.crlf = cli_mld_crlf; 378 displayer.putch = cli_mld_putch; 379 displayer.puts = cli_mld_puts; 380 displayer.flush = cli_mld_flush; 381 displayer.erase_entire_line = cli_mld_erase_entire_line; 382 displayer.beep = cli_mld_beep; 383 displayer.read_key = cli_mld_read_key; 384 385 gdb_display_match_list (matches, len, max, &displayer); 386 rl_forced_update_display (); 387 } 388