1 /* Output generating routines for GDB CLI. 2 3 Copyright (C) 1999-2017 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 29 /* These are the CLI output functions */ 30 31 /* Mark beginning of a table */ 32 33 void 34 cli_ui_out::do_table_begin (int nbrofcols, int nr_rows, const char *tblid) 35 { 36 if (nr_rows == 0) 37 m_suppress_output = true; 38 else 39 /* Only the table suppresses the output and, fortunately, a table 40 is not a recursive data structure. */ 41 gdb_assert (!m_suppress_output); 42 } 43 44 /* Mark beginning of a table body */ 45 46 void 47 cli_ui_out::do_table_body () 48 { 49 if (m_suppress_output) 50 return; 51 52 /* first, close the table header line */ 53 text ("\n"); 54 } 55 56 /* Mark end of a table */ 57 58 void 59 cli_ui_out::do_table_end () 60 { 61 m_suppress_output = false; 62 } 63 64 /* Specify table header */ 65 66 void 67 cli_ui_out::do_table_header (int width, ui_align alignment, 68 const std::string &col_name, 69 const std::string &col_hdr) 70 { 71 if (m_suppress_output) 72 return; 73 74 do_field_string (0, width, alignment, 0, col_hdr.c_str ()); 75 } 76 77 /* Mark beginning of a list */ 78 79 void 80 cli_ui_out::do_begin (ui_out_type type, const char *id) 81 { 82 } 83 84 /* Mark end of a list */ 85 86 void 87 cli_ui_out::do_end (ui_out_type type) 88 { 89 } 90 91 /* output an int field */ 92 93 void 94 cli_ui_out::do_field_int (int fldno, int width, ui_align alignment, 95 const char *fldname, int value) 96 { 97 char buffer[20]; /* FIXME: how many chars long a %d can become? */ 98 99 if (m_suppress_output) 100 return; 101 102 xsnprintf (buffer, sizeof (buffer), "%d", value); 103 104 do_field_string (fldno, width, alignment, fldname, buffer); 105 } 106 107 /* used to omit a field */ 108 109 void 110 cli_ui_out::do_field_skip (int fldno, int width, ui_align alignment, 111 const char *fldname) 112 { 113 if (m_suppress_output) 114 return; 115 116 do_field_string (fldno, width, alignment, fldname, ""); 117 } 118 119 /* other specific cli_field_* end up here so alignment and field 120 separators are both handled by cli_field_string */ 121 122 void 123 cli_ui_out::do_field_string (int fldno, int width, ui_align align, 124 const char *fldname, const char *string) 125 { 126 int before = 0; 127 int after = 0; 128 129 if (m_suppress_output) 130 return; 131 132 if ((align != ui_noalign) && string) 133 { 134 before = width - strlen (string); 135 if (before <= 0) 136 before = 0; 137 else 138 { 139 if (align == ui_right) 140 after = 0; 141 else if (align == ui_left) 142 { 143 after = before; 144 before = 0; 145 } 146 else 147 /* ui_center */ 148 { 149 after = before / 2; 150 before -= after; 151 } 152 } 153 } 154 155 if (before) 156 spaces (before); 157 158 if (string) 159 out_field_fmt (fldno, fldname, "%s", string); 160 161 if (after) 162 spaces (after); 163 164 if (align != ui_noalign) 165 field_separator (); 166 } 167 168 /* This is the only field function that does not align. */ 169 170 void 171 cli_ui_out::do_field_fmt (int fldno, int width, ui_align align, 172 const char *fldname, const char *format, 173 va_list args) 174 { 175 if (m_suppress_output) 176 return; 177 178 vfprintf_filtered (m_streams.back (), format, args); 179 180 if (align != ui_noalign) 181 field_separator (); 182 } 183 184 void 185 cli_ui_out::do_spaces (int numspaces) 186 { 187 if (m_suppress_output) 188 return; 189 190 print_spaces_filtered (numspaces, m_streams.back ()); 191 } 192 193 void 194 cli_ui_out::do_text (const char *string) 195 { 196 if (m_suppress_output) 197 return; 198 199 fputs_filtered (string, m_streams.back ()); 200 } 201 202 void 203 cli_ui_out::do_message (const char *format, va_list args) 204 { 205 if (m_suppress_output) 206 return; 207 208 vfprintf_unfiltered (m_streams.back (), format, args); 209 } 210 211 void 212 cli_ui_out::do_wrap_hint (const char *identstring) 213 { 214 if (m_suppress_output) 215 return; 216 217 wrap_here (identstring); 218 } 219 220 void 221 cli_ui_out::do_flush () 222 { 223 gdb_flush (m_streams.back ()); 224 } 225 226 /* OUTSTREAM as non-NULL will push OUTSTREAM on the stack of output streams 227 and make it therefore active. OUTSTREAM as NULL will pop the last pushed 228 output stream; it is an internal error if it does not exist. */ 229 230 void 231 cli_ui_out::do_redirect (ui_file *outstream) 232 { 233 if (outstream != NULL) 234 m_streams.push_back (outstream); 235 else 236 m_streams.pop_back (); 237 } 238 239 /* local functions */ 240 241 /* Like cli_ui_out::do_field_fmt, but takes a variable number of args 242 and makes a va_list and does not insert a separator. */ 243 244 /* VARARGS */ 245 void 246 cli_ui_out::out_field_fmt (int fldno, const char *fldname, 247 const char *format, ...) 248 { 249 va_list args; 250 251 va_start (args, format); 252 vfprintf_filtered (m_streams.back (), format, args); 253 254 va_end (args); 255 } 256 257 void 258 cli_ui_out::field_separator () 259 { 260 fputc_filtered (' ', m_streams.back ()); 261 } 262 263 /* Constructor for cli_ui_out. */ 264 265 cli_ui_out::cli_ui_out (ui_file *stream, ui_out_flags flags) 266 : ui_out (flags), 267 m_suppress_output (false) 268 { 269 gdb_assert (stream != NULL); 270 271 m_streams.push_back (stream); 272 } 273 274 cli_ui_out::~cli_ui_out () 275 { 276 } 277 278 /* Initialize private members at startup. */ 279 280 cli_ui_out * 281 cli_out_new (struct ui_file *stream) 282 { 283 return new cli_ui_out (stream, ui_source_list); 284 } 285 286 ui_file * 287 cli_ui_out::set_stream (struct ui_file *stream) 288 { 289 ui_file *old; 290 291 old = m_streams.back (); 292 m_streams.back () = stream; 293 294 return old; 295 } 296 297 /* CLI interface to display tab-completion matches. */ 298 299 /* CLI version of displayer.crlf. */ 300 301 static void 302 cli_mld_crlf (const struct match_list_displayer *displayer) 303 { 304 rl_crlf (); 305 } 306 307 /* CLI version of displayer.putch. */ 308 309 static void 310 cli_mld_putch (const struct match_list_displayer *displayer, int ch) 311 { 312 putc (ch, rl_outstream); 313 } 314 315 /* CLI version of displayer.puts. */ 316 317 static void 318 cli_mld_puts (const struct match_list_displayer *displayer, const char *s) 319 { 320 fputs (s, rl_outstream); 321 } 322 323 /* CLI version of displayer.flush. */ 324 325 static void 326 cli_mld_flush (const struct match_list_displayer *displayer) 327 { 328 fflush (rl_outstream); 329 } 330 331 EXTERN_C void _rl_erase_entire_line (void); 332 333 /* CLI version of displayer.erase_entire_line. */ 334 335 static void 336 cli_mld_erase_entire_line (const struct match_list_displayer *displayer) 337 { 338 _rl_erase_entire_line (); 339 } 340 341 /* CLI version of displayer.beep. */ 342 343 static void 344 cli_mld_beep (const struct match_list_displayer *displayer) 345 { 346 rl_ding (); 347 } 348 349 /* CLI version of displayer.read_key. */ 350 351 static int 352 cli_mld_read_key (const struct match_list_displayer *displayer) 353 { 354 return rl_read_key (); 355 } 356 357 /* CLI version of rl_completion_display_matches_hook. 358 See gdb_display_match_list for a description of the arguments. */ 359 360 void 361 cli_display_match_list (char **matches, int len, int max) 362 { 363 struct match_list_displayer displayer; 364 365 rl_get_screen_size (&displayer.height, &displayer.width); 366 displayer.crlf = cli_mld_crlf; 367 displayer.putch = cli_mld_putch; 368 displayer.puts = cli_mld_puts; 369 displayer.flush = cli_mld_flush; 370 displayer.erase_entire_line = cli_mld_erase_entire_line; 371 displayer.beep = cli_mld_beep; 372 displayer.read_key = cli_mld_read_key; 373 374 gdb_display_match_list (matches, len, max, &displayer); 375 rl_forced_update_display (); 376 } 377