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