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