Remove make_cleanup_ui_out_table_begin_end
[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
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
127431f9
AC
441struct ui_out_end_cleanup_data
442{
443 struct ui_out *uiout;
444 enum ui_out_type type;
445};
446
e6e0bfab 447static void
127431f9
AC
448do_cleanup_end (void *data)
449{
19ba03f4
SM
450 struct ui_out_end_cleanup_data *end_cleanup_data
451 = (struct ui_out_end_cleanup_data *) data;
5d502164 452
112e8700 453 end_cleanup_data->uiout->end (end_cleanup_data->type);
127431f9
AC
454 xfree (end_cleanup_data);
455}
456
457static struct cleanup *
458make_cleanup_ui_out_end (struct ui_out *uiout,
459 enum ui_out_type type)
460{
461 struct ui_out_end_cleanup_data *end_cleanup_data;
5d502164 462
70ba0933 463 end_cleanup_data = XNEW (struct ui_out_end_cleanup_data);
127431f9
AC
464 end_cleanup_data->uiout = uiout;
465 end_cleanup_data->type = type;
466 return make_cleanup (do_cleanup_end, end_cleanup_data);
467}
468
e6e0bfab 469struct cleanup *
666547aa
AC
470make_cleanup_ui_out_tuple_begin_end (struct ui_out *uiout,
471 const char *id)
472{
112e8700 473 uiout->begin (ui_out_type_tuple, id);
666547aa
AC
474 return make_cleanup_ui_out_end (uiout, ui_out_type_tuple);
475}
476
477struct cleanup *
6b28c186
AC
478make_cleanup_ui_out_list_begin_end (struct ui_out *uiout,
479 const char *id)
e6e0bfab 480{
112e8700 481 uiout->begin (ui_out_type_list, id);
127431f9 482 return make_cleanup_ui_out_end (uiout, ui_out_type_list);
e6e0bfab
MK
483}
484
8b93c638 485void
112e8700 486ui_out::field_int (const char *fldname, int value)
8b93c638
JM
487{
488 int fldno;
489 int width;
112e8700 490 ui_align align;
8b93c638 491
112e8700 492 verify_field (&fldno, &width, &align);
8b93c638 493
112e8700 494 do_field_int (fldno, width, align, fldname, value);
8b93c638
JM
495}
496
52c6a6ac 497void
112e8700
SM
498ui_out::field_fmt_int (int input_width, ui_align input_align,
499 const char *fldname, int value)
52c6a6ac
JJ
500{
501 int fldno;
502 int width;
112e8700 503 ui_align align;
52c6a6ac 504
112e8700 505 verify_field (&fldno, &width, &align);
52c6a6ac 506
112e8700 507 do_field_int (fldno, input_width, input_align, fldname, value);
52c6a6ac
JJ
508}
509
15230f37
TJB
510/* Documented in ui-out.h. */
511
8b93c638 512void
112e8700
SM
513ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch,
514 CORE_ADDR address)
8b93c638 515{
112e8700 516 field_string (fldname, print_core_address (gdbarch, address));
8b93c638
JM
517}
518
519void
d7e74731 520ui_out::field_stream (const char *fldname, string_file &stream)
8b93c638 521{
d7e74731
PA
522 if (!stream.empty ())
523 field_string (fldname, stream.c_str ());
8b93c638 524 else
112e8700 525 field_skip (fldname);
d7e74731 526 stream.clear ();
8b93c638
JM
527}
528
581e13c1 529/* Used to omit a field. */
8b93c638
JM
530
531void
112e8700 532ui_out::field_skip (const char *fldname)
8b93c638
JM
533{
534 int fldno;
535 int width;
112e8700 536 ui_align align;
8b93c638 537
112e8700 538 verify_field (&fldno, &width, &align);
8b93c638 539
112e8700 540 do_field_skip (fldno, width, align, fldname);
8b93c638
JM
541}
542
543void
112e8700 544ui_out::field_string (const char *fldname, const char *string)
8b93c638
JM
545{
546 int fldno;
547 int width;
112e8700 548 ui_align align;
8b93c638 549
112e8700 550 verify_field (&fldno, &width, &align);
8b93c638 551
112e8700 552 do_field_string (fldno, width, align, fldname, string);
8b93c638
JM
553}
554
555/* VARARGS */
556void
112e8700 557ui_out::field_fmt (const char *fldname, const char *format, ...)
8b93c638
JM
558{
559 va_list args;
560 int fldno;
561 int width;
112e8700 562 ui_align align;
8b93c638 563
581e13c1 564 /* Will not align, but has to call anyway. */
112e8700 565 verify_field (&fldno, &width, &align);
8b93c638
JM
566
567 va_start (args, format);
568
112e8700 569 do_field_fmt (fldno, width, align, fldname, format, args);
8b93c638
JM
570
571 va_end (args);
572}
573
574void
112e8700 575ui_out::spaces (int numspaces)
8b93c638 576{
112e8700 577 do_spaces (numspaces);
8b93c638
JM
578}
579
580void
112e8700 581ui_out::text (const char *string)
8b93c638 582{
112e8700 583 do_text (string);
8b93c638
JM
584}
585
586void
112e8700 587ui_out::message (const char *format, ...)
8b93c638
JM
588{
589 va_list args;
590
591 va_start (args, format);
112e8700 592 do_message (format, args);
8b93c638
JM
593 va_end (args);
594}
595
8b93c638 596void
112e8700 597ui_out::wrap_hint (const char *identstring)
8b93c638 598{
112e8700 599 do_wrap_hint (identstring);
8b93c638
JM
600}
601
602void
112e8700 603ui_out::flush ()
8b93c638 604{
112e8700 605 do_flush ();
8b93c638
JM
606}
607
7becfd03 608void
112e8700 609ui_out::redirect (ui_file *outstream)
0fac0b41 610{
7becfd03 611 do_redirect (outstream);
0fac0b41
DJ
612}
613
581e13c1 614/* Test the flags against the mask given. */
112e8700
SM
615ui_out_flags
616ui_out::test_flags (ui_out_flags mask)
8b93c638 617{
112e8700 618 return m_flags & mask;
8b93c638
JM
619}
620
112e8700
SM
621bool
622ui_out::is_mi_like_p ()
8b93c638 623{
112e8700 624 return do_is_mi_like_p ();
0fac0b41
DJ
625}
626
a6c47c14
AC
627/* Verify that the field/tuple/list is correctly positioned. Return
628 the field number and corresponding alignment (if
629 available/applicable). */
8b93c638 630
112e8700
SM
631void
632ui_out::verify_field (int *fldno, int *width, ui_align *align)
8b93c638 633{
112e8700 634 ui_out_level *current = current_level ();
c5209615 635 const char *text;
a6c47c14 636
112e8700
SM
637 if (m_table_up != nullptr
638 && m_table_up->current_state () != ui_out_table::state::BODY)
8b93c638 639 {
77a179e7
SM
640 internal_error (__FILE__, __LINE__,
641 _("table_body missing; table fields must be \
e2e0b3e5 642specified after table_body and inside a list."));
8b93c638 643 }
8b93c638 644
909c0aa5 645 current->inc_field_count ();
8b93c638 646
112e8700
SM
647 if (m_table_up != nullptr
648 && m_table_up->current_state () == ui_out_table::state::BODY
649 && m_table_up->entry_level () == level ()
650 && m_table_up->get_next_header (fldno, width, align, &text))
8b93c638 651 {
909c0aa5 652 if (*fldno != current->field_count ())
8e65ff28 653 internal_error (__FILE__, __LINE__,
e2e0b3e5 654 _("ui-out internal error in handling headers."));
8b93c638
JM
655 }
656 else
657 {
658 *width = 0;
659 *align = ui_noalign;
909c0aa5 660 *fldno = current->field_count ();
8b93c638
JM
661 }
662}
663
170b53b2 664/* Access table field parameters. */
112e8700
SM
665
666bool
667ui_out::query_table_field (int colno, int *width, int *alignment,
668 const char **col_name)
170b53b2 669{
112e8700
SM
670 if (m_table_up == nullptr)
671 return false;
170b53b2 672
112e8700 673 return m_table_up->query_field (colno, width, alignment, col_name);
170b53b2
UW
674}
675
112e8700 676/* The constructor. */
8b93c638 677
112e8700
SM
678ui_out::ui_out (ui_out_flags flags)
679: m_flags (flags)
8b93c638 680{
33b2fac6 681 /* Create the ui-out level #1, the default level. */
112e8700
SM
682 push_level (ui_out_type_tuple);
683}
54eb231c 684
112e8700
SM
685ui_out::~ui_out ()
686{
8b93c638 687}
This page took 1.850934 seconds and 4 git commands to generate.