]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/ui-out.c
Update copyright year range in all GDB files.
[thirdparty/binutils-gdb.git] / gdb / ui-out.c
CommitLineData
8b93c638 1/* Output generating routines for GDB.
349c5d5f 2
42a4f53d 3 Copyright (C) 1999-2019 Free Software Foundation, Inc.
349c5d5f 4
8b93c638
JM
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
a9762ec7 12 the Free Software Foundation; either version 3 of the License, or
8b93c638
JM
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
a9762ec7 21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
8b93c638
JM
22
23#include "defs.h"
8b93c638
JM
24#include "expression.h" /* For language.h */
25#include "language.h"
26#include "ui-out.h"
27
56df3084
SM
28#include <vector>
29#include <memory>
95a23284 30#include <string>
112e8700 31#include <memory>
56df3084 32
ffdbe864
YQ
33namespace {
34
37e20dd6 35/* A header of a ui_out_table. */
8b93c638 36
37e20dd6
SM
37class ui_out_hdr
38{
39 public:
40
41 explicit ui_out_hdr (int number, int min_width, ui_align alignment,
42 const std::string &name, const std::string &header)
43 : m_number (number),
44 m_min_width (min_width),
45 m_alignment (alignment),
46 m_name (name),
47 m_header (header)
8b93c638 48 {
37e20dd6
SM
49 }
50
51 int number () const
52 {
53 return m_number;
54 }
55
56 int min_width () const
57 {
58 return m_min_width;
59 }
60
61 ui_align alignment () const
62 {
63 return m_alignment;
64 }
65
66 const std::string &header () const
67 {
68 return m_header;
69 }
70
71 const std::string &name () const
72 {
73 return m_name;
74 }
75
76 private:
77
78 /* The number of the table column this header represents, 1-based. */
79 int m_number;
80
81 /* Minimal column width in characters. May or may not be applicable,
82 depending on the actual implementation of ui_out. */
83 int m_min_width;
84
85 /* Alignment of the content in the column. May or may not be applicable,
86 depending on the actual implementation of ui_out. */
87 ui_align m_alignment;
88
89 /* Internal column name, used to internally refer to the column. */
90 std::string m_name;
91
92 /* Printed header text of the column. */
93 std::string m_header;
94};
8b93c638 95
ffdbe864
YQ
96} // namespace
97
909c0aa5
SM
98/* A level of nesting (either a list or a tuple) in a ui_out output. */
99
100class ui_out_level
101{
102 public:
103
104 explicit ui_out_level (ui_out_type type)
105 : m_type (type),
106 m_field_count (0)
80f49b30 107 {
909c0aa5
SM
108 }
109
110 ui_out_type type () const
111 {
112 return m_type;
113 }
114
115 int field_count () const
116 {
117 return m_field_count;
118 }
119
120 void inc_field_count ()
121 {
122 m_field_count++;
123 }
124
125 private:
126
127 /* The type of this level. */
128 ui_out_type m_type;
129
130 /* Count each field; the first element is for non-list fields. */
131 int m_field_count;
132};
80f49b30 133
bafdd3b3
AC
134/* Tables are special. Maintain a separate structure that tracks
135 their state. At present an output can only contain a single table
136 but that restriction might eventually be lifted. */
137
36d18bc5 138class ui_out_table
bafdd3b3 139{
36d18bc5
SM
140 public:
141
142 /* States (steps) of a table generation. */
143
144 enum class state
145 {
146 /* We are generating the table headers. */
147 HEADERS,
148
149 /* We are generating the table body. */
150 BODY,
151 };
152
153 explicit ui_out_table (int entry_level, int nr_cols, const std::string &id)
154 : m_state (state::HEADERS),
155 m_entry_level (entry_level),
156 m_nr_cols (nr_cols),
157 m_id (id)
158 {
159 }
160
161 /* Start building the body of the table. */
162
163 void start_body ();
164
165 /* Add a new header to the table. */
166
167 void append_header (int width, ui_align alignment,
168 const std::string &col_name, const std::string &col_hdr);
bafdd3b3 169
36d18bc5
SM
170 void start_row ();
171
172 /* Extract the format information for the next header and advance
173 the header iterator. Return false if there was no next header. */
174
175 bool get_next_header (int *colno, int *width, ui_align *alignment,
176 const char **col_hdr);
177
178 bool query_field (int colno, int *width, int *alignment,
179 const char **col_name) const;
180
181 state current_state () const;
182
183 int entry_level () const;
184
185 private:
186
187 state m_state;
bafdd3b3 188
a6c47c14
AC
189 /* The level at which each entry of the table is to be found. A row
190 (a tuple) is made up of entries. Consequently ENTRY_LEVEL is one
191 above that of the table. */
36d18bc5 192 int m_entry_level;
a6c47c14 193
bafdd3b3 194 /* Number of table columns (as specified in the table_begin call). */
36d18bc5 195 int m_nr_cols;
bafdd3b3
AC
196
197 /* String identifying the table (as specified in the table_begin
198 call). */
36d18bc5 199 std::string m_id;
bafdd3b3 200
78afa7f8 201 /* Pointers to the column headers. */
36d18bc5 202 std::vector<std::unique_ptr<ui_out_hdr>> m_headers;
bafdd3b3 203
78afa7f8 204 /* Iterator over the headers vector, used when printing successive fields. */
36d18bc5 205 std::vector<std::unique_ptr<ui_out_hdr>>::const_iterator m_headers_iterator;
bafdd3b3
AC
206};
207
36d18bc5
SM
208/* See ui-out.h. */
209
210void ui_out_table::start_body ()
211{
212 if (m_state != state::HEADERS)
213 internal_error (__FILE__, __LINE__,
214 _("extra table_body call not allowed; there must be only "
215 "one table_body after a table_begin and before a "
216 "table_end."));
217
218 /* Check if the number of defined headers matches the number of expected
219 columns. */
220 if (m_headers.size () != m_nr_cols)
221 internal_error (__FILE__, __LINE__,
222 _("number of headers differ from number of table "
223 "columns."));
224
225 m_state = state::BODY;
226 m_headers_iterator = m_headers.begin ();
227}
228
229/* See ui-out.h. */
230
231void ui_out_table::append_header (int width, ui_align alignment,
232 const std::string &col_name,
233 const std::string &col_hdr)
234{
235 if (m_state != state::HEADERS)
236 internal_error (__FILE__, __LINE__,
237 _("table header must be specified after table_begin and "
238 "before table_body."));
239
240 std::unique_ptr<ui_out_hdr> header (new ui_out_hdr (m_headers.size () + 1,
241 width, alignment,
242 col_name, col_hdr));
243
244 m_headers.push_back (std::move (header));
245}
246
247/* See ui-out.h. */
248
249void ui_out_table::start_row ()
250{
251 m_headers_iterator = m_headers.begin ();
252}
253
254/* See ui-out.h. */
255
256bool ui_out_table::get_next_header (int *colno, int *width, ui_align *alignment,
257 const char **col_hdr)
258{
259 /* There may be no headers at all or we may have used all columns. */
260 if (m_headers_iterator == m_headers.end ())
261 return false;
262
263 ui_out_hdr *hdr = m_headers_iterator->get ();
264
265 *colno = hdr->number ();
266 *width = hdr->min_width ();
267 *alignment = hdr->alignment ();
268 *col_hdr = hdr->header ().c_str ();
269
270 /* Advance the header pointer to the next entry. */
271 m_headers_iterator++;
272
273 return true;
274}
275
276/* See ui-out.h. */
277
278bool ui_out_table::query_field (int colno, int *width, int *alignment,
279 const char **col_name) const
280{
281 /* Column numbers are 1-based, so convert to 0-based index. */
282 int index = colno - 1;
283
284 if (index >= 0 && index < m_headers.size ())
285 {
286 ui_out_hdr *hdr = m_headers[index].get ();
287
288 gdb_assert (colno == hdr->number ());
289
290 *width = hdr->min_width ();
291 *alignment = hdr->alignment ();
292 *col_name = hdr->name ().c_str ();
293
294 return true;
295 }
296 else
297 return false;
298}
299
300/* See ui-out.h. */
301
302ui_out_table::state ui_out_table::current_state () const
303{
304 return m_state;
305}
306
307/* See ui-out.h. */
308
309int ui_out_table::entry_level () const
310{
311 return m_entry_level;
312}
bafdd3b3 313
112e8700
SM
314int
315ui_out::level () const
316{
317 return m_levels.size ();
318}
8b93c638 319
581e13c1 320/* The current (inner most) level. */
112e8700
SM
321
322ui_out_level *
323ui_out::current_level () const
80f49b30 324{
112e8700 325 return m_levels.back ().get ();
80f49b30
AC
326}
327
33b2fac6 328/* Create a new level, of TYPE. */
112e8700
SM
329void
330ui_out::push_level (ui_out_type type)
80f49b30 331{
909c0aa5 332 std::unique_ptr<ui_out_level> level (new ui_out_level (type));
56df3084 333
112e8700 334 m_levels.push_back (std::move (level));
80f49b30
AC
335}
336
33b2fac6
SM
337/* Discard the current level. TYPE is the type of the level being
338 discarded. */
112e8700
SM
339void
340ui_out::pop_level (ui_out_type type)
80f49b30 341{
581e13c1 342 /* We had better not underflow the buffer. */
112e8700
SM
343 gdb_assert (m_levels.size () > 0);
344 gdb_assert (current_level ()->type () == type);
345
346 m_levels.pop_back ();
347}
8b93c638 348
581e13c1 349/* Mark beginning of a table. */
8b93c638 350
112e8700
SM
351void
352ui_out::table_begin (int nr_cols, int nr_rows, const std::string &tblid)
8b93c638 353{
112e8700 354 if (m_table_up != nullptr)
8e65ff28 355 internal_error (__FILE__, __LINE__,
e2e0b3e5
AC
356 _("tables cannot be nested; table_begin found before \
357previous table_end."));
8b93c638 358
112e8700 359 m_table_up.reset (new ui_out_table (level () + 1, nr_cols, tblid));
95a23284 360
112e8700 361 do_table_begin (nr_cols, nr_rows, tblid.c_str ());
8b93c638
JM
362}
363
364void
112e8700
SM
365ui_out::table_header (int width, ui_align alignment,
366 const std::string &col_name, const std::string &col_hdr)
8b93c638 367{
112e8700 368 if (m_table_up == nullptr)
8e65ff28 369 internal_error (__FILE__, __LINE__,
112e8700
SM
370 _("table_header outside a table is not valid; it must be \
371after a table_begin and before a table_body."));
77a179e7 372
112e8700 373 m_table_up->append_header (width, alignment, col_name, col_hdr);
8b93c638 374
112e8700 375 do_table_header (width, alignment, col_name, col_hdr);
8b93c638
JM
376}
377
112e8700
SM
378void
379ui_out::table_body ()
8b93c638 380{
112e8700 381 if (m_table_up == nullptr)
8e65ff28 382 internal_error (__FILE__, __LINE__,
112e8700
SM
383 _("table_body outside a table is not valid; it must be "
384 "after a table_begin and before a table_end."));
8b93c638 385
112e8700 386 m_table_up->start_body ();
36d18bc5 387
112e8700 388 do_table_body ();
8b93c638
JM
389}
390
391void
112e8700 392ui_out::table_end ()
8b93c638 393{
112e8700 394 if (m_table_up == nullptr)
8e65ff28 395 internal_error (__FILE__, __LINE__,
112e8700 396 _("misplaced table_end or missing table_begin."));
8b93c638 397
112e8700 398 do_table_end ();
8b93c638 399
112e8700 400 m_table_up = nullptr;
8b93c638
JM
401}
402
403void
112e8700 404ui_out::begin (ui_out_type type, const char *id)
8b93c638 405{
a6c47c14
AC
406 /* Be careful to verify the ``field'' before the new tuple/list is
407 pushed onto the stack. That way the containing list/table/row is
408 verified and not the newly created tuple/list. This verification
409 is needed (at least) for the case where a table row entry
410 contains either a tuple/list. For that case bookkeeping such as
411 updating the column count or advancing to the next heading still
412 needs to be performed. */
413 {
414 int fldno;
415 int width;
112e8700 416 ui_align align;
5d502164 417
112e8700 418 verify_field (&fldno, &width, &align);
a6c47c14
AC
419 }
420
112e8700 421 push_level (type);
a6c47c14
AC
422
423 /* If the push puts us at the same level as a table row entry, we've
424 got a new table row. Put the header pointer back to the start. */
112e8700
SM
425 if (m_table_up != nullptr
426 && m_table_up->current_state () == ui_out_table::state::BODY
427 && m_table_up->entry_level () == level ())
428 m_table_up->start_row ();
a6c47c14 429
112e8700 430 do_begin (type, id);
631ec795
AC
431}
432
631ec795 433void
112e8700 434ui_out::end (ui_out_type type)
631ec795 435{
112e8700 436 pop_level (type);
5d502164 437
112e8700 438 do_end (type);
8b93c638
JM
439}
440
8b93c638 441void
112e8700 442ui_out::field_int (const char *fldname, int value)
8b93c638
JM
443{
444 int fldno;
445 int width;
112e8700 446 ui_align align;
8b93c638 447
112e8700 448 verify_field (&fldno, &width, &align);
8b93c638 449
112e8700 450 do_field_int (fldno, width, align, fldname, value);
8b93c638
JM
451}
452
52c6a6ac 453void
112e8700
SM
454ui_out::field_fmt_int (int input_width, ui_align input_align,
455 const char *fldname, int value)
52c6a6ac
JJ
456{
457 int fldno;
458 int width;
112e8700 459 ui_align align;
52c6a6ac 460
112e8700 461 verify_field (&fldno, &width, &align);
52c6a6ac 462
112e8700 463 do_field_int (fldno, input_width, input_align, fldname, value);
52c6a6ac
JJ
464}
465
15230f37
TJB
466/* Documented in ui-out.h. */
467
8b93c638 468void
112e8700
SM
469ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch,
470 CORE_ADDR address)
8b93c638 471{
35fb8261
TT
472 field_string (fldname, print_core_address (gdbarch, address),
473 ui_out_style_kind::ADDRESS);
8b93c638
JM
474}
475
476void
cbe56571
TT
477ui_out::field_stream (const char *fldname, string_file &stream,
478 ui_out_style_kind style)
8b93c638 479{
d7e74731 480 if (!stream.empty ())
cbe56571 481 field_string (fldname, stream.c_str (), style);
8b93c638 482 else
112e8700 483 field_skip (fldname);
d7e74731 484 stream.clear ();
8b93c638
JM
485}
486
581e13c1 487/* Used to omit a field. */
8b93c638
JM
488
489void
112e8700 490ui_out::field_skip (const char *fldname)
8b93c638
JM
491{
492 int fldno;
493 int width;
112e8700 494 ui_align align;
8b93c638 495
112e8700 496 verify_field (&fldno, &width, &align);
8b93c638 497
112e8700 498 do_field_skip (fldno, width, align, fldname);
8b93c638
JM
499}
500
501void
cbe56571
TT
502ui_out::field_string (const char *fldname, const char *string,
503 ui_out_style_kind style)
8b93c638
JM
504{
505 int fldno;
506 int width;
112e8700 507 ui_align align;
8b93c638 508
112e8700 509 verify_field (&fldno, &width, &align);
8b93c638 510
cbe56571 511 do_field_string (fldno, width, align, fldname, string, style);
8b93c638
JM
512}
513
6fb16ce6
SM
514void
515ui_out::field_string (const char *fldname, const std::string &string)
516{
517 field_string (fldname, string.c_str ());
518}
519
8b93c638
JM
520/* VARARGS */
521void
112e8700 522ui_out::field_fmt (const char *fldname, const char *format, ...)
8b93c638
JM
523{
524 va_list args;
525 int fldno;
526 int width;
112e8700 527 ui_align align;
8b93c638 528
112e8700 529 verify_field (&fldno, &width, &align);
8b93c638
JM
530
531 va_start (args, format);
532
112e8700 533 do_field_fmt (fldno, width, align, fldname, format, args);
8b93c638
JM
534
535 va_end (args);
536}
537
538void
112e8700 539ui_out::spaces (int numspaces)
8b93c638 540{
112e8700 541 do_spaces (numspaces);
8b93c638
JM
542}
543
544void
112e8700 545ui_out::text (const char *string)
8b93c638 546{
112e8700 547 do_text (string);
8b93c638
JM
548}
549
550void
112e8700 551ui_out::message (const char *format, ...)
8b93c638
JM
552{
553 va_list args;
554
555 va_start (args, format);
112e8700 556 do_message (format, args);
8b93c638
JM
557 va_end (args);
558}
559
8b93c638 560void
112e8700 561ui_out::wrap_hint (const char *identstring)
8b93c638 562{
112e8700 563 do_wrap_hint (identstring);
8b93c638
JM
564}
565
566void
112e8700 567ui_out::flush ()
8b93c638 568{
112e8700 569 do_flush ();
8b93c638
JM
570}
571
7becfd03 572void
112e8700 573ui_out::redirect (ui_file *outstream)
0fac0b41 574{
7becfd03 575 do_redirect (outstream);
0fac0b41
DJ
576}
577
581e13c1 578/* Test the flags against the mask given. */
112e8700
SM
579ui_out_flags
580ui_out::test_flags (ui_out_flags mask)
8b93c638 581{
112e8700 582 return m_flags & mask;
8b93c638
JM
583}
584
112e8700 585bool
4904c3c6 586ui_out::is_mi_like_p () const
8b93c638 587{
112e8700 588 return do_is_mi_like_p ();
0fac0b41
DJ
589}
590
a6c47c14
AC
591/* Verify that the field/tuple/list is correctly positioned. Return
592 the field number and corresponding alignment (if
593 available/applicable). */
8b93c638 594
112e8700
SM
595void
596ui_out::verify_field (int *fldno, int *width, ui_align *align)
8b93c638 597{
112e8700 598 ui_out_level *current = current_level ();
c5209615 599 const char *text;
a6c47c14 600
112e8700
SM
601 if (m_table_up != nullptr
602 && m_table_up->current_state () != ui_out_table::state::BODY)
8b93c638 603 {
77a179e7
SM
604 internal_error (__FILE__, __LINE__,
605 _("table_body missing; table fields must be \
e2e0b3e5 606specified after table_body and inside a list."));
8b93c638 607 }
8b93c638 608
909c0aa5 609 current->inc_field_count ();
8b93c638 610
112e8700
SM
611 if (m_table_up != nullptr
612 && m_table_up->current_state () == ui_out_table::state::BODY
613 && m_table_up->entry_level () == level ()
614 && m_table_up->get_next_header (fldno, width, align, &text))
8b93c638 615 {
909c0aa5 616 if (*fldno != current->field_count ())
8e65ff28 617 internal_error (__FILE__, __LINE__,
e2e0b3e5 618 _("ui-out internal error in handling headers."));
8b93c638
JM
619 }
620 else
621 {
622 *width = 0;
623 *align = ui_noalign;
909c0aa5 624 *fldno = current->field_count ();
8b93c638
JM
625 }
626}
627
170b53b2 628/* Access table field parameters. */
112e8700
SM
629
630bool
631ui_out::query_table_field (int colno, int *width, int *alignment,
632 const char **col_name)
170b53b2 633{
112e8700
SM
634 if (m_table_up == nullptr)
635 return false;
170b53b2 636
112e8700 637 return m_table_up->query_field (colno, width, alignment, col_name);
170b53b2
UW
638}
639
112e8700 640/* The constructor. */
8b93c638 641
112e8700
SM
642ui_out::ui_out (ui_out_flags flags)
643: m_flags (flags)
8b93c638 644{
33b2fac6 645 /* Create the ui-out level #1, the default level. */
112e8700
SM
646 push_level (ui_out_type_tuple);
647}
54eb231c 648
112e8700
SM
649ui_out::~ui_out ()
650{
8b93c638 651}