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