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