1 /* Output generating routines for GDB CLI. 2 3 Copyright (C) 1999-2015 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 "vec.h" 27 28 typedef struct cli_ui_out_data cli_out_data; 29 30 31 /* Prototypes for local functions */ 32 33 static void cli_text (struct ui_out *uiout, const char *string); 34 35 static void field_separator (void); 36 37 static void out_field_fmt (struct ui_out *uiout, int fldno, 38 const char *fldname, 39 const char *format,...) ATTRIBUTE_PRINTF (4, 5); 40 41 /* The destructor. */ 42 43 static void 44 cli_uiout_dtor (struct ui_out *ui_out) 45 { 46 cli_out_data *data = ui_out_data (ui_out); 47 48 VEC_free (ui_filep, data->streams); 49 xfree (data); 50 } 51 52 /* These are the CLI output functions */ 53 54 /* Mark beginning of a table */ 55 56 static void 57 cli_table_begin (struct ui_out *uiout, int nbrofcols, 58 int nr_rows, 59 const char *tblid) 60 { 61 cli_out_data *data = ui_out_data (uiout); 62 63 if (nr_rows == 0) 64 data->suppress_output = 1; 65 else 66 /* Only the table suppresses the output and, fortunately, a table 67 is not a recursive data structure. */ 68 gdb_assert (data->suppress_output == 0); 69 } 70 71 /* Mark beginning of a table body */ 72 73 static void 74 cli_table_body (struct ui_out *uiout) 75 { 76 cli_out_data *data = ui_out_data (uiout); 77 78 if (data->suppress_output) 79 return; 80 /* first, close the table header line */ 81 cli_text (uiout, "\n"); 82 } 83 84 /* Mark end of a table */ 85 86 static void 87 cli_table_end (struct ui_out *uiout) 88 { 89 cli_out_data *data = ui_out_data (uiout); 90 91 data->suppress_output = 0; 92 } 93 94 /* Specify table header */ 95 96 static void 97 cli_table_header (struct ui_out *uiout, int width, enum ui_align alignment, 98 const char *col_name, 99 const char *colhdr) 100 { 101 cli_out_data *data = ui_out_data (uiout); 102 103 if (data->suppress_output) 104 return; 105 106 /* Always go through the function pointer (virtual function call). 107 We may have been extended. */ 108 uo_field_string (uiout, 0, width, alignment, 0, colhdr); 109 } 110 111 /* Mark beginning of a list */ 112 113 static void 114 cli_begin (struct ui_out *uiout, 115 enum ui_out_type type, 116 int level, 117 const char *id) 118 { 119 cli_out_data *data = ui_out_data (uiout); 120 121 if (data->suppress_output) 122 return; 123 } 124 125 /* Mark end of a list */ 126 127 static void 128 cli_end (struct ui_out *uiout, 129 enum ui_out_type type, 130 int level) 131 { 132 cli_out_data *data = ui_out_data (uiout); 133 134 if (data->suppress_output) 135 return; 136 } 137 138 /* output an int field */ 139 140 static void 141 cli_field_int (struct ui_out *uiout, int fldno, int width, 142 enum ui_align alignment, 143 const char *fldname, int value) 144 { 145 char buffer[20]; /* FIXME: how many chars long a %d can become? */ 146 cli_out_data *data = ui_out_data (uiout); 147 148 if (data->suppress_output) 149 return; 150 xsnprintf (buffer, sizeof (buffer), "%d", value); 151 152 /* Always go through the function pointer (virtual function call). 153 We may have been extended. */ 154 uo_field_string (uiout, fldno, width, alignment, fldname, buffer); 155 } 156 157 /* used to ommit a field */ 158 159 static void 160 cli_field_skip (struct ui_out *uiout, int fldno, int width, 161 enum ui_align alignment, 162 const char *fldname) 163 { 164 cli_out_data *data = ui_out_data (uiout); 165 166 if (data->suppress_output) 167 return; 168 169 /* Always go through the function pointer (virtual function call). 170 We may have been extended. */ 171 uo_field_string (uiout, fldno, width, alignment, fldname, ""); 172 } 173 174 /* other specific cli_field_* end up here so alignment and field 175 separators are both handled by cli_field_string */ 176 177 static void 178 cli_field_string (struct ui_out *uiout, 179 int fldno, 180 int width, 181 enum ui_align align, 182 const char *fldname, 183 const char *string) 184 { 185 int before = 0; 186 int after = 0; 187 cli_out_data *data = ui_out_data (uiout); 188 189 if (data->suppress_output) 190 return; 191 192 if ((align != ui_noalign) && string) 193 { 194 before = width - strlen (string); 195 if (before <= 0) 196 before = 0; 197 else 198 { 199 if (align == ui_right) 200 after = 0; 201 else if (align == ui_left) 202 { 203 after = before; 204 before = 0; 205 } 206 else 207 /* ui_center */ 208 { 209 after = before / 2; 210 before -= after; 211 } 212 } 213 } 214 215 if (before) 216 ui_out_spaces (uiout, before); 217 if (string) 218 out_field_fmt (uiout, fldno, fldname, "%s", string); 219 if (after) 220 ui_out_spaces (uiout, after); 221 222 if (align != ui_noalign) 223 field_separator (); 224 } 225 226 /* This is the only field function that does not align. */ 227 228 static void ATTRIBUTE_PRINTF (6, 0) 229 cli_field_fmt (struct ui_out *uiout, int fldno, 230 int width, enum ui_align align, 231 const char *fldname, 232 const char *format, 233 va_list args) 234 { 235 cli_out_data *data = ui_out_data (uiout); 236 struct ui_file *stream; 237 238 if (data->suppress_output) 239 return; 240 241 stream = VEC_last (ui_filep, data->streams); 242 vfprintf_filtered (stream, format, args); 243 244 if (align != ui_noalign) 245 field_separator (); 246 } 247 248 static void 249 cli_spaces (struct ui_out *uiout, int numspaces) 250 { 251 cli_out_data *data = ui_out_data (uiout); 252 struct ui_file *stream; 253 254 if (data->suppress_output) 255 return; 256 257 stream = VEC_last (ui_filep, data->streams); 258 print_spaces_filtered (numspaces, stream); 259 } 260 261 static void 262 cli_text (struct ui_out *uiout, const char *string) 263 { 264 cli_out_data *data = ui_out_data (uiout); 265 struct ui_file *stream; 266 267 if (data->suppress_output) 268 return; 269 270 stream = VEC_last (ui_filep, data->streams); 271 fputs_filtered (string, stream); 272 } 273 274 static void ATTRIBUTE_PRINTF (3, 0) 275 cli_message (struct ui_out *uiout, int verbosity, 276 const char *format, va_list args) 277 { 278 cli_out_data *data = ui_out_data (uiout); 279 280 if (data->suppress_output) 281 return; 282 283 if (ui_out_get_verblvl (uiout) >= verbosity) 284 { 285 struct ui_file *stream = VEC_last (ui_filep, data->streams); 286 287 vfprintf_unfiltered (stream, format, args); 288 } 289 } 290 291 static void 292 cli_wrap_hint (struct ui_out *uiout, char *identstring) 293 { 294 cli_out_data *data = ui_out_data (uiout); 295 296 if (data->suppress_output) 297 return; 298 wrap_here (identstring); 299 } 300 301 static void 302 cli_flush (struct ui_out *uiout) 303 { 304 cli_out_data *data = ui_out_data (uiout); 305 struct ui_file *stream = VEC_last (ui_filep, data->streams); 306 307 gdb_flush (stream); 308 } 309 310 /* OUTSTREAM as non-NULL will push OUTSTREAM on the stack of output streams 311 and make it therefore active. OUTSTREAM as NULL will pop the last pushed 312 output stream; it is an internal error if it does not exist. */ 313 314 static int 315 cli_redirect (struct ui_out *uiout, struct ui_file *outstream) 316 { 317 cli_out_data *data = ui_out_data (uiout); 318 319 if (outstream != NULL) 320 VEC_safe_push (ui_filep, data->streams, outstream); 321 else 322 VEC_pop (ui_filep, data->streams); 323 324 return 0; 325 } 326 327 /* local functions */ 328 329 /* Like cli_field_fmt, but takes a variable number of args 330 and makes a va_list and does not insert a separator. */ 331 332 /* VARARGS */ 333 static void 334 out_field_fmt (struct ui_out *uiout, int fldno, 335 const char *fldname, 336 const char *format,...) 337 { 338 cli_out_data *data = ui_out_data (uiout); 339 struct ui_file *stream = VEC_last (ui_filep, data->streams); 340 va_list args; 341 342 va_start (args, format); 343 vfprintf_filtered (stream, format, args); 344 345 va_end (args); 346 } 347 348 /* Access to ui_out format private members. */ 349 350 static void 351 field_separator (void) 352 { 353 cli_out_data *data = ui_out_data (current_uiout); 354 struct ui_file *stream = VEC_last (ui_filep, data->streams); 355 356 fputc_filtered (' ', stream); 357 } 358 359 /* This is the CLI ui-out implementation functions vector */ 360 361 const struct ui_out_impl cli_ui_out_impl = 362 { 363 cli_table_begin, 364 cli_table_body, 365 cli_table_end, 366 cli_table_header, 367 cli_begin, 368 cli_end, 369 cli_field_int, 370 cli_field_skip, 371 cli_field_string, 372 cli_field_fmt, 373 cli_spaces, 374 cli_text, 375 cli_message, 376 cli_wrap_hint, 377 cli_flush, 378 cli_redirect, 379 cli_uiout_dtor, 380 0, /* Does not need MI hacks (i.e. needs CLI hacks). */ 381 }; 382 383 /* Constructor for a `cli_out_data' object. */ 384 385 void 386 cli_out_data_ctor (cli_out_data *self, struct ui_file *stream) 387 { 388 gdb_assert (stream != NULL); 389 390 self->streams = NULL; 391 VEC_safe_push (ui_filep, self->streams, stream); 392 393 self->suppress_output = 0; 394 } 395 396 /* Initialize private members at startup. */ 397 398 struct ui_out * 399 cli_out_new (struct ui_file *stream) 400 { 401 int flags = ui_source_list; 402 cli_out_data *data = XNEW (cli_out_data); 403 404 cli_out_data_ctor (data, stream); 405 return ui_out_new (&cli_ui_out_impl, data, flags); 406 } 407 408 struct ui_file * 409 cli_out_set_stream (struct ui_out *uiout, struct ui_file *stream) 410 { 411 cli_out_data *data = ui_out_data (uiout); 412 struct ui_file *old; 413 414 old = VEC_pop (ui_filep, data->streams); 415 VEC_quick_push (ui_filep, data->streams, stream); 416 417 return old; 418 } 419