Change Python code to use new_reference
[deliverable/binutils-gdb.git] / gdb / ui-out.c
CommitLineData
8b93c638 1/* Output generating routines for GDB.
349c5d5f 2
e2882c85 3 Copyright (C) 1999-2018 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{
112e8700 472 field_string (fldname, print_core_address (gdbarch, address));
8b93c638
JM
473}
474
475void
d7e74731 476ui_out::field_stream (const char *fldname, string_file &stream)
8b93c638 477{
d7e74731
PA
478 if (!stream.empty ())
479 field_string (fldname, stream.c_str ());
8b93c638 480 else
112e8700 481 field_skip (fldname);
d7e74731 482 stream.clear ();
8b93c638
JM
483}
484
581e13c1 485/* Used to omit a field. */
8b93c638
JM
486
487void
112e8700 488ui_out::field_skip (const char *fldname)
8b93c638
JM
489{
490 int fldno;
491 int width;
112e8700 492 ui_align align;
8b93c638 493
112e8700 494 verify_field (&fldno, &width, &align);
8b93c638 495
112e8700 496 do_field_skip (fldno, width, align, fldname);
8b93c638
JM
497}
498
499void
112e8700 500ui_out::field_string (const char *fldname, const char *string)
8b93c638
JM
501{
502 int fldno;
503 int width;
112e8700 504 ui_align align;
8b93c638 505
112e8700 506 verify_field (&fldno, &width, &align);
8b93c638 507
112e8700 508 do_field_string (fldno, width, align, fldname, string);
8b93c638
JM
509}
510
6fb16ce6
SM
511void
512ui_out::field_string (const char *fldname, const std::string &string)
513{
514 field_string (fldname, string.c_str ());
515}
516
8b93c638
JM
517/* VARARGS */
518void
112e8700 519ui_out::field_fmt (const char *fldname, const char *format, ...)
8b93c638
JM
520{
521 va_list args;
522 int fldno;
523 int width;
112e8700 524 ui_align align;
8b93c638 525
581e13c1 526 /* Will not align, but has to call anyway. */
112e8700 527 verify_field (&fldno, &width, &align);
8b93c638
JM
528
529 va_start (args, format);
530
112e8700 531 do_field_fmt (fldno, width, align, fldname, format, args);
8b93c638
JM
532
533 va_end (args);
534}
535
536void
112e8700 537ui_out::spaces (int numspaces)
8b93c638 538{
112e8700 539 do_spaces (numspaces);
8b93c638
JM
540}
541
542void
112e8700 543ui_out::text (const char *string)
8b93c638 544{
112e8700 545 do_text (string);
8b93c638
JM
546}
547
548void
112e8700 549ui_out::message (const char *format, ...)
8b93c638
JM
550{
551 va_list args;
552
553 va_start (args, format);
112e8700 554 do_message (format, args);
8b93c638
JM
555 va_end (args);
556}
557
8b93c638 558void
112e8700 559ui_out::wrap_hint (const char *identstring)
8b93c638 560{
112e8700 561 do_wrap_hint (identstring);
8b93c638
JM
562}
563
564void
112e8700 565ui_out::flush ()
8b93c638 566{
112e8700 567 do_flush ();
8b93c638
JM
568}
569
7becfd03 570void
112e8700 571ui_out::redirect (ui_file *outstream)
0fac0b41 572{
7becfd03 573 do_redirect (outstream);
0fac0b41
DJ
574}
575
581e13c1 576/* Test the flags against the mask given. */
112e8700
SM
577ui_out_flags
578ui_out::test_flags (ui_out_flags mask)
8b93c638 579{
112e8700 580 return m_flags & mask;
8b93c638
JM
581}
582
112e8700
SM
583bool
584ui_out::is_mi_like_p ()
8b93c638 585{
112e8700 586 return do_is_mi_like_p ();
0fac0b41
DJ
587}
588
a6c47c14
AC
589/* Verify that the field/tuple/list is correctly positioned. Return
590 the field number and corresponding alignment (if
591 available/applicable). */
8b93c638 592
112e8700
SM
593void
594ui_out::verify_field (int *fldno, int *width, ui_align *align)
8b93c638 595{
112e8700 596 ui_out_level *current = current_level ();
c5209615 597 const char *text;
a6c47c14 598
112e8700
SM
599 if (m_table_up != nullptr
600 && m_table_up->current_state () != ui_out_table::state::BODY)
8b93c638 601 {
77a179e7
SM
602 internal_error (__FILE__, __LINE__,
603 _("table_body missing; table fields must be \
e2e0b3e5 604specified after table_body and inside a list."));
8b93c638 605 }
8b93c638 606
909c0aa5 607 current->inc_field_count ();
8b93c638 608
112e8700
SM
609 if (m_table_up != nullptr
610 && m_table_up->current_state () == ui_out_table::state::BODY
611 && m_table_up->entry_level () == level ()
612 && m_table_up->get_next_header (fldno, width, align, &text))
8b93c638 613 {
909c0aa5 614 if (*fldno != current->field_count ())
8e65ff28 615 internal_error (__FILE__, __LINE__,
e2e0b3e5 616 _("ui-out internal error in handling headers."));
8b93c638
JM
617 }
618 else
619 {
620 *width = 0;
621 *align = ui_noalign;
909c0aa5 622 *fldno = current->field_count ();
8b93c638
JM
623 }
624}
625
170b53b2 626/* Access table field parameters. */
112e8700
SM
627
628bool
629ui_out::query_table_field (int colno, int *width, int *alignment,
630 const char **col_name)
170b53b2 631{
112e8700
SM
632 if (m_table_up == nullptr)
633 return false;
170b53b2 634
112e8700 635 return m_table_up->query_field (colno, width, alignment, col_name);
170b53b2
UW
636}
637
112e8700 638/* The constructor. */
8b93c638 639
112e8700
SM
640ui_out::ui_out (ui_out_flags flags)
641: m_flags (flags)
8b93c638 642{
33b2fac6 643 /* Create the ui-out level #1, the default level. */
112e8700
SM
644 push_level (ui_out_type_tuple);
645}
54eb231c 646
112e8700
SM
647ui_out::~ui_out ()
648{
8b93c638 649}
This page took 2.011436 seconds and 4 git commands to generate.