1 /* MI Command Set - output generating routines. 2 3 Copyright (C) 2000-2013 Free Software Foundation, Inc. 4 5 Contributed by Cygnus Solutions (a Red Hat company). 6 7 This file is part of GDB. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 22 #include "defs.h" 23 #include "ui-out.h" 24 #include "mi-out.h" 25 26 struct ui_out_data 27 { 28 int suppress_field_separator; 29 int suppress_output; 30 int mi_version; 31 struct ui_file *buffer; 32 struct ui_file *original_buffer; 33 }; 34 typedef struct ui_out_data mi_out_data; 35 36 /* These are the MI output functions */ 37 38 static void mi_table_begin (struct ui_out *uiout, int nbrofcols, 39 int nr_rows, const char *tblid); 40 static void mi_table_body (struct ui_out *uiout); 41 static void mi_table_end (struct ui_out *uiout); 42 static void mi_table_header (struct ui_out *uiout, int width, 43 enum ui_align alig, const char *col_name, 44 const char *colhdr); 45 static void mi_begin (struct ui_out *uiout, enum ui_out_type type, 46 int level, const char *id); 47 static void mi_end (struct ui_out *uiout, enum ui_out_type type, int level); 48 static void mi_field_int (struct ui_out *uiout, int fldno, int width, 49 enum ui_align alig, const char *fldname, int value); 50 static void mi_field_skip (struct ui_out *uiout, int fldno, int width, 51 enum ui_align alig, const char *fldname); 52 static void mi_field_string (struct ui_out *uiout, int fldno, int width, 53 enum ui_align alig, const char *fldname, 54 const char *string); 55 static void mi_field_fmt (struct ui_out *uiout, int fldno, 56 int width, enum ui_align align, 57 const char *fldname, const char *format, 58 va_list args) ATTRIBUTE_PRINTF (6, 0); 59 static void mi_spaces (struct ui_out *uiout, int numspaces); 60 static void mi_text (struct ui_out *uiout, const char *string); 61 static void mi_message (struct ui_out *uiout, int verbosity, 62 const char *format, va_list args) 63 ATTRIBUTE_PRINTF (3, 0); 64 static void mi_wrap_hint (struct ui_out *uiout, char *identstring); 65 static void mi_flush (struct ui_out *uiout); 66 static int mi_redirect (struct ui_out *uiout, struct ui_file *outstream); 67 68 /* This is the MI ui-out implementation functions vector */ 69 70 /* FIXME: This can be initialized dynamically after default is set to 71 handle initial output in main.c */ 72 73 struct ui_out_impl mi_ui_out_impl = 74 { 75 mi_table_begin, 76 mi_table_body, 77 mi_table_end, 78 mi_table_header, 79 mi_begin, 80 mi_end, 81 mi_field_int, 82 mi_field_skip, 83 mi_field_string, 84 mi_field_fmt, 85 mi_spaces, 86 mi_text, 87 mi_message, 88 mi_wrap_hint, 89 mi_flush, 90 mi_redirect, 91 0, 92 1, /* Needs MI hacks. */ 93 }; 94 95 /* Prototypes for local functions */ 96 97 extern void _initialize_mi_out (void); 98 static void field_separator (struct ui_out *uiout); 99 static void mi_open (struct ui_out *uiout, const char *name, 100 enum ui_out_type type); 101 static void mi_close (struct ui_out *uiout, enum ui_out_type type); 102 103 /* Mark beginning of a table. */ 104 105 void 106 mi_table_begin (struct ui_out *uiout, 107 int nr_cols, 108 int nr_rows, 109 const char *tblid) 110 { 111 mi_open (uiout, tblid, ui_out_type_tuple); 112 mi_field_int (uiout, -1, -1, -1, "nr_rows", nr_rows); 113 mi_field_int (uiout, -1, -1, -1, "nr_cols", nr_cols); 114 mi_open (uiout, "hdr", ui_out_type_list); 115 } 116 117 /* Mark beginning of a table body. */ 118 119 void 120 mi_table_body (struct ui_out *uiout) 121 { 122 mi_out_data *data = ui_out_data (uiout); 123 124 if (data->suppress_output) 125 return; 126 /* close the table header line if there were any headers */ 127 mi_close (uiout, ui_out_type_list); 128 mi_open (uiout, "body", ui_out_type_list); 129 } 130 131 /* Mark end of a table. */ 132 133 void 134 mi_table_end (struct ui_out *uiout) 135 { 136 mi_out_data *data = ui_out_data (uiout); 137 138 data->suppress_output = 0; 139 mi_close (uiout, ui_out_type_list); /* body */ 140 mi_close (uiout, ui_out_type_tuple); 141 } 142 143 /* Specify table header. */ 144 145 void 146 mi_table_header (struct ui_out *uiout, int width, enum ui_align alignment, 147 const char *col_name, const char *colhdr) 148 { 149 mi_out_data *data = ui_out_data (uiout); 150 151 if (data->suppress_output) 152 return; 153 154 mi_open (uiout, NULL, ui_out_type_tuple); 155 mi_field_int (uiout, 0, 0, 0, "width", width); 156 mi_field_int (uiout, 0, 0, 0, "alignment", alignment); 157 mi_field_string (uiout, 0, 0, 0, "col_name", col_name); 158 mi_field_string (uiout, 0, width, alignment, "colhdr", colhdr); 159 mi_close (uiout, ui_out_type_tuple); 160 } 161 162 /* Mark beginning of a list. */ 163 164 void 165 mi_begin (struct ui_out *uiout, enum ui_out_type type, int level, 166 const char *id) 167 { 168 mi_out_data *data = ui_out_data (uiout); 169 170 if (data->suppress_output) 171 return; 172 173 mi_open (uiout, id, type); 174 } 175 176 /* Mark end of a list. */ 177 178 void 179 mi_end (struct ui_out *uiout, enum ui_out_type type, int level) 180 { 181 mi_out_data *data = ui_out_data (uiout); 182 183 if (data->suppress_output) 184 return; 185 186 mi_close (uiout, type); 187 } 188 189 /* Output an int field. */ 190 191 static void 192 mi_field_int (struct ui_out *uiout, int fldno, int width, 193 enum ui_align alignment, const char *fldname, int value) 194 { 195 char buffer[20]; /* FIXME: how many chars long a %d can become? */ 196 mi_out_data *data = ui_out_data (uiout); 197 198 if (data->suppress_output) 199 return; 200 201 xsnprintf (buffer, sizeof (buffer), "%d", value); 202 mi_field_string (uiout, fldno, width, alignment, fldname, buffer); 203 } 204 205 /* Used to omit a field. */ 206 207 void 208 mi_field_skip (struct ui_out *uiout, int fldno, int width, 209 enum ui_align alignment, const char *fldname) 210 { 211 } 212 213 /* Other specific mi_field_* end up here so alignment and field 214 separators are both handled by mi_field_string. */ 215 216 void 217 mi_field_string (struct ui_out *uiout, int fldno, int width, 218 enum ui_align align, const char *fldname, const char *string) 219 { 220 mi_out_data *data = ui_out_data (uiout); 221 222 if (data->suppress_output) 223 return; 224 225 field_separator (uiout); 226 if (fldname) 227 fprintf_unfiltered (data->buffer, "%s=", fldname); 228 fprintf_unfiltered (data->buffer, "\""); 229 if (string) 230 fputstr_unfiltered (string, '"', data->buffer); 231 fprintf_unfiltered (data->buffer, "\""); 232 } 233 234 /* This is the only field function that does not align. */ 235 236 void 237 mi_field_fmt (struct ui_out *uiout, int fldno, int width, 238 enum ui_align align, const char *fldname, 239 const char *format, va_list args) 240 { 241 mi_out_data *data = ui_out_data (uiout); 242 243 if (data->suppress_output) 244 return; 245 246 field_separator (uiout); 247 if (fldname) 248 fprintf_unfiltered (data->buffer, "%s=\"", fldname); 249 else 250 fputs_unfiltered ("\"", data->buffer); 251 vfprintf_unfiltered (data->buffer, format, args); 252 fputs_unfiltered ("\"", data->buffer); 253 } 254 255 void 256 mi_spaces (struct ui_out *uiout, int numspaces) 257 { 258 } 259 260 void 261 mi_text (struct ui_out *uiout, const char *string) 262 { 263 } 264 265 void 266 mi_message (struct ui_out *uiout, int verbosity, 267 const char *format, va_list args) 268 { 269 } 270 271 void 272 mi_wrap_hint (struct ui_out *uiout, char *identstring) 273 { 274 wrap_here (identstring); 275 } 276 277 void 278 mi_flush (struct ui_out *uiout) 279 { 280 mi_out_data *data = ui_out_data (uiout); 281 282 gdb_flush (data->buffer); 283 } 284 285 int 286 mi_redirect (struct ui_out *uiout, struct ui_file *outstream) 287 { 288 mi_out_data *data = ui_out_data (uiout); 289 290 if (outstream != NULL) 291 { 292 data->original_buffer = data->buffer; 293 data->buffer = outstream; 294 } 295 else if (data->original_buffer != NULL) 296 { 297 data->buffer = data->original_buffer; 298 data->original_buffer = NULL; 299 } 300 301 return 0; 302 } 303 304 /* local functions */ 305 306 /* access to ui_out format private members */ 307 308 static void 309 field_separator (struct ui_out *uiout) 310 { 311 mi_out_data *data = ui_out_data (uiout); 312 313 if (data->suppress_field_separator) 314 data->suppress_field_separator = 0; 315 else 316 fputc_unfiltered (',', data->buffer); 317 } 318 319 static void 320 mi_open (struct ui_out *uiout, const char *name, enum ui_out_type type) 321 { 322 mi_out_data *data = ui_out_data (uiout); 323 324 field_separator (uiout); 325 data->suppress_field_separator = 1; 326 if (name) 327 fprintf_unfiltered (data->buffer, "%s=", name); 328 switch (type) 329 { 330 case ui_out_type_tuple: 331 fputc_unfiltered ('{', data->buffer); 332 break; 333 case ui_out_type_list: 334 fputc_unfiltered ('[', data->buffer); 335 break; 336 default: 337 internal_error (__FILE__, __LINE__, _("bad switch")); 338 } 339 } 340 341 static void 342 mi_close (struct ui_out *uiout, enum ui_out_type type) 343 { 344 mi_out_data *data = ui_out_data (uiout); 345 346 switch (type) 347 { 348 case ui_out_type_tuple: 349 fputc_unfiltered ('}', data->buffer); 350 break; 351 case ui_out_type_list: 352 fputc_unfiltered (']', data->buffer); 353 break; 354 default: 355 internal_error (__FILE__, __LINE__, _("bad switch")); 356 } 357 data->suppress_field_separator = 0; 358 } 359 360 /* Add a string to the buffer. */ 361 362 void 363 mi_out_buffered (struct ui_out *uiout, char *string) 364 { 365 mi_out_data *data = ui_out_data (uiout); 366 367 fprintf_unfiltered (data->buffer, "%s", string); 368 } 369 370 /* Clear the buffer. */ 371 372 void 373 mi_out_rewind (struct ui_out *uiout) 374 { 375 mi_out_data *data = ui_out_data (uiout); 376 377 ui_file_rewind (data->buffer); 378 } 379 380 /* Dump the buffer onto the specified stream. */ 381 382 static void 383 do_write (void *data, const char *buffer, long length_buffer) 384 { 385 ui_file_write (data, buffer, length_buffer); 386 } 387 388 void 389 mi_out_put (struct ui_out *uiout, struct ui_file *stream) 390 { 391 mi_out_data *data = ui_out_data (uiout); 392 393 ui_file_put (data->buffer, do_write, stream); 394 ui_file_rewind (data->buffer); 395 } 396 397 /* Return the current MI version. */ 398 399 int 400 mi_version (struct ui_out *uiout) 401 { 402 mi_out_data *data = ui_out_data (uiout); 403 404 return data->mi_version; 405 } 406 407 /* Initialize private members at startup. */ 408 409 struct ui_out * 410 mi_out_new (int mi_version) 411 { 412 int flags = 0; 413 414 mi_out_data *data = XMALLOC (mi_out_data); 415 data->suppress_field_separator = 0; 416 data->suppress_output = 0; 417 data->mi_version = mi_version; 418 /* FIXME: This code should be using a ``string_file'' and not the 419 TUI buffer hack. */ 420 data->buffer = mem_fileopen (); 421 return ui_out_new (&mi_ui_out_impl, data, flags); 422 } 423