Wrap locally used classes in anonymous namespace
[deliverable/binutils-gdb.git] / gdb / ui-out.c
CommitLineData
8b93c638 1/* Output generating routines for GDB.
349c5d5f 2
61baf725 3 Copyright (C) 1999-2017 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
3b31d625
EZ
403static void
404do_cleanup_table_end (void *data)
405{
112e8700 406 ui_out *uiout = (ui_out *) data;
3b31d625 407
112e8700 408 uiout->table_end ();
3b31d625
EZ
409}
410
411struct cleanup *
112e8700
SM
412make_cleanup_ui_out_table_begin_end (ui_out *uiout, int nr_cols, int nr_rows,
413 const char *tblid)
3b31d625 414{
112e8700
SM
415 uiout->table_begin (nr_cols, nr_rows, tblid);
416 return make_cleanup (do_cleanup_table_end, uiout);
3b31d625
EZ
417}
418
8b93c638 419void
112e8700 420ui_out::begin (ui_out_type type, const char *id)
8b93c638 421{
a6c47c14
AC
422 /* Be careful to verify the ``field'' before the new tuple/list is
423 pushed onto the stack. That way the containing list/table/row is
424 verified and not the newly created tuple/list. This verification
425 is needed (at least) for the case where a table row entry
426 contains either a tuple/list. For that case bookkeeping such as
427 updating the column count or advancing to the next heading still
428 needs to be performed. */
429 {
430 int fldno;
431 int width;
112e8700 432 ui_align align;
5d502164 433
112e8700 434 verify_field (&fldno, &width, &align);
a6c47c14
AC
435 }
436
112e8700 437 push_level (type);
a6c47c14
AC
438
439 /* If the push puts us at the same level as a table row entry, we've
440 got a new table row. Put the header pointer back to the start. */
112e8700
SM
441 if (m_table_up != nullptr
442 && m_table_up->current_state () == ui_out_table::state::BODY
443 && m_table_up->entry_level () == level ())
444 m_table_up->start_row ();
a6c47c14 445
112e8700 446 do_begin (type, id);
631ec795
AC
447}
448
631ec795 449void
112e8700 450ui_out::end (ui_out_type type)
631ec795 451{
112e8700 452 pop_level (type);
5d502164 453
112e8700 454 do_end (type);
8b93c638
JM
455}
456
127431f9
AC
457struct ui_out_end_cleanup_data
458{
459 struct ui_out *uiout;
460 enum ui_out_type type;
461};
462
e6e0bfab 463static void
127431f9
AC
464do_cleanup_end (void *data)
465{
19ba03f4
SM
466 struct ui_out_end_cleanup_data *end_cleanup_data
467 = (struct ui_out_end_cleanup_data *) data;
5d502164 468
112e8700 469 end_cleanup_data->uiout->end (end_cleanup_data->type);
127431f9
AC
470 xfree (end_cleanup_data);
471}
472
473static struct cleanup *
474make_cleanup_ui_out_end (struct ui_out *uiout,
475 enum ui_out_type type)
476{
477 struct ui_out_end_cleanup_data *end_cleanup_data;
5d502164 478
70ba0933 479 end_cleanup_data = XNEW (struct ui_out_end_cleanup_data);
127431f9
AC
480 end_cleanup_data->uiout = uiout;
481 end_cleanup_data->type = type;
482 return make_cleanup (do_cleanup_end, end_cleanup_data);
483}
484
e6e0bfab 485struct cleanup *
666547aa
AC
486make_cleanup_ui_out_tuple_begin_end (struct ui_out *uiout,
487 const char *id)
488{
112e8700 489 uiout->begin (ui_out_type_tuple, id);
666547aa
AC
490 return make_cleanup_ui_out_end (uiout, ui_out_type_tuple);
491}
492
493struct cleanup *
6b28c186
AC
494make_cleanup_ui_out_list_begin_end (struct ui_out *uiout,
495 const char *id)
e6e0bfab 496{
112e8700 497 uiout->begin (ui_out_type_list, id);
127431f9 498 return make_cleanup_ui_out_end (uiout, ui_out_type_list);
e6e0bfab
MK
499}
500
8b93c638 501void
112e8700 502ui_out::field_int (const char *fldname, int value)
8b93c638
JM
503{
504 int fldno;
505 int width;
112e8700 506 ui_align align;
8b93c638 507
112e8700 508 verify_field (&fldno, &width, &align);
8b93c638 509
112e8700 510 do_field_int (fldno, width, align, fldname, value);
8b93c638
JM
511}
512
52c6a6ac 513void
112e8700
SM
514ui_out::field_fmt_int (int input_width, ui_align input_align,
515 const char *fldname, int value)
52c6a6ac
JJ
516{
517 int fldno;
518 int width;
112e8700 519 ui_align align;
52c6a6ac 520
112e8700 521 verify_field (&fldno, &width, &align);
52c6a6ac 522
112e8700 523 do_field_int (fldno, input_width, input_align, fldname, value);
52c6a6ac
JJ
524}
525
15230f37
TJB
526/* Documented in ui-out.h. */
527
8b93c638 528void
112e8700
SM
529ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch,
530 CORE_ADDR address)
8b93c638 531{
112e8700 532 field_string (fldname, print_core_address (gdbarch, address));
8b93c638
JM
533}
534
535void
d7e74731 536ui_out::field_stream (const char *fldname, string_file &stream)
8b93c638 537{
d7e74731
PA
538 if (!stream.empty ())
539 field_string (fldname, stream.c_str ());
8b93c638 540 else
112e8700 541 field_skip (fldname);
d7e74731 542 stream.clear ();
8b93c638
JM
543}
544
581e13c1 545/* Used to omit a field. */
8b93c638
JM
546
547void
112e8700 548ui_out::field_skip (const char *fldname)
8b93c638
JM
549{
550 int fldno;
551 int width;
112e8700 552 ui_align align;
8b93c638 553
112e8700 554 verify_field (&fldno, &width, &align);
8b93c638 555
112e8700 556 do_field_skip (fldno, width, align, fldname);
8b93c638
JM
557}
558
559void
112e8700 560ui_out::field_string (const char *fldname, const char *string)
8b93c638
JM
561{
562 int fldno;
563 int width;
112e8700 564 ui_align align;
8b93c638 565
112e8700 566 verify_field (&fldno, &width, &align);
8b93c638 567
112e8700 568 do_field_string (fldno, width, align, fldname, string);
8b93c638
JM
569}
570
571/* VARARGS */
572void
112e8700 573ui_out::field_fmt (const char *fldname, const char *format, ...)
8b93c638
JM
574{
575 va_list args;
576 int fldno;
577 int width;
112e8700 578 ui_align align;
8b93c638 579
581e13c1 580 /* Will not align, but has to call anyway. */
112e8700 581 verify_field (&fldno, &width, &align);
8b93c638
JM
582
583 va_start (args, format);
584
112e8700 585 do_field_fmt (fldno, width, align, fldname, format, args);
8b93c638
JM
586
587 va_end (args);
588}
589
590void
112e8700 591ui_out::spaces (int numspaces)
8b93c638 592{
112e8700 593 do_spaces (numspaces);
8b93c638
JM
594}
595
596void
112e8700 597ui_out::text (const char *string)
8b93c638 598{
112e8700 599 do_text (string);
8b93c638
JM
600}
601
602void
112e8700 603ui_out::message (const char *format, ...)
8b93c638
JM
604{
605 va_list args;
606
607 va_start (args, format);
112e8700 608 do_message (format, args);
8b93c638
JM
609 va_end (args);
610}
611
8b93c638 612void
112e8700 613ui_out::wrap_hint (const char *identstring)
8b93c638 614{
112e8700 615 do_wrap_hint (identstring);
8b93c638
JM
616}
617
618void
112e8700 619ui_out::flush ()
8b93c638 620{
112e8700 621 do_flush ();
8b93c638
JM
622}
623
7becfd03 624void
112e8700 625ui_out::redirect (ui_file *outstream)
0fac0b41 626{
7becfd03 627 do_redirect (outstream);
0fac0b41
DJ
628}
629
581e13c1 630/* Test the flags against the mask given. */
112e8700
SM
631ui_out_flags
632ui_out::test_flags (ui_out_flags mask)
8b93c638 633{
112e8700 634 return m_flags & mask;
8b93c638
JM
635}
636
112e8700
SM
637bool
638ui_out::is_mi_like_p ()
8b93c638 639{
112e8700 640 return do_is_mi_like_p ();
0fac0b41
DJ
641}
642
a6c47c14
AC
643/* Verify that the field/tuple/list is correctly positioned. Return
644 the field number and corresponding alignment (if
645 available/applicable). */
8b93c638 646
112e8700
SM
647void
648ui_out::verify_field (int *fldno, int *width, ui_align *align)
8b93c638 649{
112e8700 650 ui_out_level *current = current_level ();
c5209615 651 const char *text;
a6c47c14 652
112e8700
SM
653 if (m_table_up != nullptr
654 && m_table_up->current_state () != ui_out_table::state::BODY)
8b93c638 655 {
77a179e7
SM
656 internal_error (__FILE__, __LINE__,
657 _("table_body missing; table fields must be \
e2e0b3e5 658specified after table_body and inside a list."));
8b93c638 659 }
8b93c638 660
909c0aa5 661 current->inc_field_count ();
8b93c638 662
112e8700
SM
663 if (m_table_up != nullptr
664 && m_table_up->current_state () == ui_out_table::state::BODY
665 && m_table_up->entry_level () == level ()
666 && m_table_up->get_next_header (fldno, width, align, &text))
8b93c638 667 {
909c0aa5 668 if (*fldno != current->field_count ())
8e65ff28 669 internal_error (__FILE__, __LINE__,
e2e0b3e5 670 _("ui-out internal error in handling headers."));
8b93c638
JM
671 }
672 else
673 {
674 *width = 0;
675 *align = ui_noalign;
909c0aa5 676 *fldno = current->field_count ();
8b93c638
JM
677 }
678}
679
170b53b2 680/* Access table field parameters. */
112e8700
SM
681
682bool
683ui_out::query_table_field (int colno, int *width, int *alignment,
684 const char **col_name)
170b53b2 685{
112e8700
SM
686 if (m_table_up == nullptr)
687 return false;
170b53b2 688
112e8700 689 return m_table_up->query_field (colno, width, alignment, col_name);
170b53b2
UW
690}
691
112e8700 692/* The constructor. */
8b93c638 693
112e8700
SM
694ui_out::ui_out (ui_out_flags flags)
695: m_flags (flags)
8b93c638 696{
33b2fac6 697 /* Create the ui-out level #1, the default level. */
112e8700
SM
698 push_level (ui_out_type_tuple);
699}
54eb231c 700
112e8700
SM
701ui_out::~ui_out ()
702{
8b93c638 703}
This page took 1.724897 seconds and 4 git commands to generate.