1/* MI Command Set - output generating routines. 2 3 Copyright (C) 2000-2020 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 "mi-out.h" 24 25#include <vector> 26 27#include "interps.h" 28#include "ui-out.h" 29#include "utils.h" 30 31/* Mark beginning of a table. */ 32 33void 34mi_ui_out::do_table_begin (int nr_cols, int nr_rows, 35 const char *tblid) 36{ 37 open (tblid, ui_out_type_tuple); 38 do_field_signed (-1, -1, ui_left, "nr_rows", nr_rows); 39 do_field_signed (-1, -1, ui_left, "nr_cols", nr_cols); 40 open ("hdr", ui_out_type_list); 41} 42 43/* Mark beginning of a table body. */ 44 45void 46mi_ui_out::do_table_body () 47{ 48 /* close the table header line if there were any headers */ 49 close (ui_out_type_list); 50 open ("body", ui_out_type_list); 51} 52 53/* Mark end of a table. */ 54 55void 56mi_ui_out::do_table_end () 57{ 58 close (ui_out_type_list); /* body */ 59 close (ui_out_type_tuple); 60} 61 62/* Specify table header. */ 63 64void 65mi_ui_out::do_table_header (int width, ui_align alignment, 66 const std::string &col_name, 67 const std::string &col_hdr) 68{ 69 open (NULL, ui_out_type_tuple); 70 do_field_signed (0, 0, ui_center, "width", width); 71 do_field_signed (0, 0, ui_center, "alignment", alignment); 72 do_field_string (0, 0, ui_center, "col_name", col_name.c_str (), 73 ui_file_style ()); 74 do_field_string (0, width, alignment, "colhdr", col_hdr.c_str (), 75 ui_file_style ()); 76 close (ui_out_type_tuple); 77} 78 79/* Mark beginning of a list. */ 80 81void 82mi_ui_out::do_begin (ui_out_type type, const char *id) 83{ 84 open (id, type); 85} 86 87/* Mark end of a list. */ 88 89void 90mi_ui_out::do_end (ui_out_type type) 91{ 92 close (type); 93} 94 95/* Output an int field. */ 96 97void 98mi_ui_out::do_field_signed (int fldno, int width, ui_align alignment, 99 const char *fldname, LONGEST value) 100{ 101 do_field_string (fldno, width, alignment, fldname, plongest (value), 102 ui_file_style ()); 103} 104 105/* Output an unsigned field. */ 106 107void 108mi_ui_out::do_field_unsigned (int fldno, int width, ui_align alignment, 109 const char *fldname, ULONGEST value) 110{ 111 do_field_string (fldno, width, alignment, fldname, pulongest (value), 112 ui_file_style ()); 113} 114 115/* Used to omit a field. */ 116 117void 118mi_ui_out::do_field_skip (int fldno, int width, ui_align alignment, 119 const char *fldname) 120{ 121} 122 123/* Other specific mi_field_* end up here so alignment and field 124 separators are both handled by mi_field_string. */ 125 126void 127mi_ui_out::do_field_string (int fldno, int width, ui_align align, 128 const char *fldname, const char *string, 129 const ui_file_style &style) 130{ 131 ui_file *stream = m_streams.back (); 132 field_separator (); 133 134 if (fldname) 135 fprintf_unfiltered (stream, "%s=", fldname); 136 fprintf_unfiltered (stream, "\""); 137 if (string) 138 fputstr_unfiltered (string, '"', stream); 139 fprintf_unfiltered (stream, "\""); 140} 141 142void 143mi_ui_out::do_field_fmt (int fldno, int width, ui_align align, 144 const char *fldname, const ui_file_style &style, 145 const char *format, va_list args) 146{ 147 ui_file *stream = m_streams.back (); 148 field_separator (); 149 150 if (fldname) 151 fprintf_unfiltered (stream, "%s=\"", fldname); 152 else 153 fputs_unfiltered ("\"", stream); 154 vfprintf_unfiltered (stream, format, args); 155 fputs_unfiltered ("\"", stream); 156} 157 158void 159mi_ui_out::do_spaces (int numspaces) 160{ 161} 162 163void 164mi_ui_out::do_text (const char *string) 165{ 166} 167 168void 169mi_ui_out::do_message (const ui_file_style &style, 170 const char *format, va_list args) 171{ 172} 173 174void 175mi_ui_out::do_wrap_hint (const char *identstring) 176{ 177 wrap_here (identstring); 178} 179 180void 181mi_ui_out::do_flush () 182{ 183 184 gdb_flush (m_streams.back ()); 185} 186 187void 188mi_ui_out::do_redirect (ui_file *outstream) 189{ 190 if (outstream != NULL) 191 m_streams.push_back (outstream); 192 else 193 m_streams.pop_back (); 194} 195 196void 197mi_ui_out::field_separator () 198{ 199 if (m_suppress_field_separator) 200 m_suppress_field_separator = false; 201 else 202 fputc_unfiltered (',', m_streams.back ()); 203} 204 205void 206mi_ui_out::open (const char *name, ui_out_type type) 207{ 208 ui_file *stream = m_streams.back (); 209 210 field_separator (); 211 m_suppress_field_separator = true; 212 213 if (name) 214 fprintf_unfiltered (stream, "%s=", name); 215 216 switch (type) 217 { 218 case ui_out_type_tuple: 219 fputc_unfiltered ('{', stream); 220 break; 221 222 case ui_out_type_list: 223 fputc_unfiltered ('[', stream); 224 break; 225 226 default: 227 internal_error (__FILE__, __LINE__, _("bad switch")); 228 } 229} 230 231void 232mi_ui_out::close (ui_out_type type) 233{ 234 ui_file *stream = m_streams.back (); 235 236 switch (type) 237 { 238 case ui_out_type_tuple: 239 fputc_unfiltered ('}', stream); 240 break; 241 242 case ui_out_type_list: 243 fputc_unfiltered (']', stream); 244 break; 245 246 default: 247 internal_error (__FILE__, __LINE__, _("bad switch")); 248 } 249 250 m_suppress_field_separator = false; 251} 252 253string_file * 254mi_ui_out::main_stream () 255{ 256 gdb_assert (m_streams.size () == 1); 257 258 return (string_file *) m_streams.back (); 259} 260 261/* Clear the buffer. */ 262 263void 264mi_ui_out::rewind () 265{ 266 main_stream ()->clear (); 267} 268 269/* Dump the buffer onto the specified stream. */ 270 271void 272mi_ui_out::put (ui_file *where) 273{ 274 string_file *mi_stream = main_stream (); 275 276 where->write (mi_stream->data (), mi_stream->size ()); 277 mi_stream->clear (); 278} 279 280/* Return the current MI version. */ 281 282int 283mi_ui_out::version () 284{ 285 return m_mi_version; 286} 287 288/* Constructor for an `mi_out_data' object. */ 289 290mi_ui_out::mi_ui_out (int mi_version) 291: ui_out (mi_version >= 3 292 ? fix_multi_location_breakpoint_output : (ui_out_flag) 0), 293 m_suppress_field_separator (false), 294 m_suppress_output (false), 295 m_mi_version (mi_version) 296{ 297 string_file *stream = new string_file (); 298 m_streams.push_back (stream); 299} 300 301mi_ui_out::~mi_ui_out () 302{ 303} 304 305/* See mi/mi-out.h. */ 306 307mi_ui_out * 308mi_out_new (const char *mi_version) 309{ 310 if (streq (mi_version, INTERP_MI3) || streq (mi_version, INTERP_MI)) 311 return new mi_ui_out (3); 312 313 if (streq (mi_version, INTERP_MI2)) 314 return new mi_ui_out (2); 315 316 if (streq (mi_version, INTERP_MI1)) 317 return new mi_ui_out (1); 318 319 return nullptr; 320} 321 322/* Helper function to return the given UIOUT as an mi_ui_out. It is an error 323 to call this function with an ui_out that is not an MI. */ 324 325static mi_ui_out * 326as_mi_ui_out (ui_out *uiout) 327{ 328 mi_ui_out *mi_uiout = dynamic_cast<mi_ui_out *> (uiout); 329 330 gdb_assert (mi_uiout != NULL); 331 332 return mi_uiout; 333} 334 335int 336mi_version (ui_out *uiout) 337{ 338 return as_mi_ui_out (uiout)->version (); 339} 340 341void 342mi_out_put (ui_out *uiout, struct ui_file *stream) 343{ 344 return as_mi_ui_out (uiout)->put (stream); 345} 346 347void 348mi_out_rewind (ui_out *uiout) 349{ 350 return as_mi_ui_out (uiout)->rewind (); 351} 352