]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/ui-out.c
internal_error: remove need to pass __FILE__/__LINE__
[thirdparty/binutils-gdb.git] / gdb / ui-out.c
CommitLineData
8b93c638 1/* Output generating routines for GDB.
349c5d5f 2
4a94e368 3 Copyright (C) 1999-2022 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"
e43b10e1
TT
27#include "gdbsupport/format.h"
28#include "cli/cli-style.h"
284782de 29#include "diagnostics.h"
8b93c638 30
56df3084
SM
31#include <vector>
32#include <memory>
95a23284 33#include <string>
56df3084 34
ffdbe864
YQ
35namespace {
36
37e20dd6 37/* A header of a ui_out_table. */
8b93c638 38
37e20dd6
SM
39class ui_out_hdr
40{
41 public:
42
43 explicit ui_out_hdr (int number, int min_width, ui_align alignment,
44 const std::string &name, const std::string &header)
45 : m_number (number),
46 m_min_width (min_width),
47 m_alignment (alignment),
48 m_name (name),
49 m_header (header)
8b93c638 50 {
37e20dd6
SM
51 }
52
53 int number () const
54 {
55 return m_number;
56 }
57
58 int min_width () const
59 {
60 return m_min_width;
61 }
62
63 ui_align alignment () const
64 {
65 return m_alignment;
66 }
67
68 const std::string &header () const
69 {
70 return m_header;
71 }
72
73 const std::string &name () const
74 {
75 return m_name;
76 }
77
78 private:
79
80 /* The number of the table column this header represents, 1-based. */
81 int m_number;
82
83 /* Minimal column width in characters. May or may not be applicable,
84 depending on the actual implementation of ui_out. */
85 int m_min_width;
86
87 /* Alignment of the content in the column. May or may not be applicable,
88 depending on the actual implementation of ui_out. */
89 ui_align m_alignment;
90
91 /* Internal column name, used to internally refer to the column. */
92 std::string m_name;
93
94 /* Printed header text of the column. */
95 std::string m_header;
96};
8b93c638 97
ffdbe864
YQ
98} // namespace
99
909c0aa5
SM
100/* A level of nesting (either a list or a tuple) in a ui_out output. */
101
102class ui_out_level
103{
104 public:
105
106 explicit ui_out_level (ui_out_type type)
107 : m_type (type),
108 m_field_count (0)
80f49b30 109 {
909c0aa5
SM
110 }
111
112 ui_out_type type () const
113 {
114 return m_type;
115 }
116
117 int field_count () const
118 {
119 return m_field_count;
120 }
121
122 void inc_field_count ()
123 {
124 m_field_count++;
125 }
126
127 private:
128
129 /* The type of this level. */
130 ui_out_type m_type;
131
132 /* Count each field; the first element is for non-list fields. */
133 int m_field_count;
134};
80f49b30 135
bafdd3b3
AC
136/* Tables are special. Maintain a separate structure that tracks
137 their state. At present an output can only contain a single table
138 but that restriction might eventually be lifted. */
139
36d18bc5 140class ui_out_table
bafdd3b3 141{
36d18bc5
SM
142 public:
143
144 /* States (steps) of a table generation. */
145
146 enum class state
147 {
148 /* We are generating the table headers. */
149 HEADERS,
150
151 /* We are generating the table body. */
152 BODY,
153 };
154
155 explicit ui_out_table (int entry_level, int nr_cols, const std::string &id)
156 : m_state (state::HEADERS),
157 m_entry_level (entry_level),
158 m_nr_cols (nr_cols),
159 m_id (id)
160 {
161 }
162
163 /* Start building the body of the table. */
164
165 void start_body ();
166
167 /* Add a new header to the table. */
168
169 void append_header (int width, ui_align alignment,
170 const std::string &col_name, const std::string &col_hdr);
bafdd3b3 171
36d18bc5
SM
172 void start_row ();
173
174 /* Extract the format information for the next header and advance
175 the header iterator. Return false if there was no next header. */
176
177 bool get_next_header (int *colno, int *width, ui_align *alignment,
178 const char **col_hdr);
179
180 bool query_field (int colno, int *width, int *alignment,
181 const char **col_name) const;
182
183 state current_state () const;
184
185 int entry_level () const;
186
187 private:
188
189 state m_state;
bafdd3b3 190
a6c47c14
AC
191 /* The level at which each entry of the table is to be found. A row
192 (a tuple) is made up of entries. Consequently ENTRY_LEVEL is one
193 above that of the table. */
36d18bc5 194 int m_entry_level;
a6c47c14 195
bafdd3b3 196 /* Number of table columns (as specified in the table_begin call). */
36d18bc5 197 int m_nr_cols;
bafdd3b3
AC
198
199 /* String identifying the table (as specified in the table_begin
200 call). */
36d18bc5 201 std::string m_id;
bafdd3b3 202
78afa7f8 203 /* Pointers to the column headers. */
36d18bc5 204 std::vector<std::unique_ptr<ui_out_hdr>> m_headers;
bafdd3b3 205
78afa7f8 206 /* Iterator over the headers vector, used when printing successive fields. */
36d18bc5 207 std::vector<std::unique_ptr<ui_out_hdr>>::const_iterator m_headers_iterator;
bafdd3b3
AC
208};
209
36d18bc5
SM
210/* See ui-out.h. */
211
212void ui_out_table::start_body ()
213{
214 if (m_state != state::HEADERS)
f34652de 215 internal_error (_("extra table_body call not allowed; there must be only "
36d18bc5
SM
216 "one table_body after a table_begin and before a "
217 "table_end."));
218
219 /* Check if the number of defined headers matches the number of expected
220 columns. */
221 if (m_headers.size () != m_nr_cols)
f34652de 222 internal_error (_("number of headers differ from number of table "
36d18bc5
SM
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)
f34652de 236 internal_error (_("table header must be specified after table_begin and "
36d18bc5
SM
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)
f34652de 354 internal_error (_("tables cannot be nested; table_begin found before \
e2e0b3e5 355previous table_end."));
8b93c638 356
112e8700 357 m_table_up.reset (new ui_out_table (level () + 1, nr_cols, tblid));
95a23284 358
112e8700 359 do_table_begin (nr_cols, nr_rows, tblid.c_str ());
8b93c638
JM
360}
361
362void
112e8700
SM
363ui_out::table_header (int width, ui_align alignment,
364 const std::string &col_name, const std::string &col_hdr)
8b93c638 365{
112e8700 366 if (m_table_up == nullptr)
f34652de 367 internal_error (_("table_header outside a table is not valid; it must be \
112e8700 368after a table_begin and before a table_body."));
77a179e7 369
112e8700 370 m_table_up->append_header (width, alignment, col_name, col_hdr);
8b93c638 371
112e8700 372 do_table_header (width, alignment, col_name, col_hdr);
8b93c638
JM
373}
374
112e8700
SM
375void
376ui_out::table_body ()
8b93c638 377{
112e8700 378 if (m_table_up == nullptr)
f34652de 379 internal_error (_("table_body outside a table is not valid; it must be "
112e8700 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)
f34652de 391 internal_error (_("misplaced table_end or missing table_begin."));
8b93c638 392
112e8700 393 do_table_end ();
8b93c638 394
112e8700 395 m_table_up = nullptr;
8b93c638
JM
396}
397
398void
112e8700 399ui_out::begin (ui_out_type type, const char *id)
8b93c638 400{
a6c47c14
AC
401 /* Be careful to verify the ``field'' before the new tuple/list is
402 pushed onto the stack. That way the containing list/table/row is
403 verified and not the newly created tuple/list. This verification
404 is needed (at least) for the case where a table row entry
405 contains either a tuple/list. For that case bookkeeping such as
406 updating the column count or advancing to the next heading still
407 needs to be performed. */
408 {
409 int fldno;
410 int width;
112e8700 411 ui_align align;
5d502164 412
112e8700 413 verify_field (&fldno, &width, &align);
a6c47c14
AC
414 }
415
112e8700 416 push_level (type);
a6c47c14
AC
417
418 /* If the push puts us at the same level as a table row entry, we've
419 got a new table row. Put the header pointer back to the start. */
112e8700
SM
420 if (m_table_up != nullptr
421 && m_table_up->current_state () == ui_out_table::state::BODY
422 && m_table_up->entry_level () == level ())
423 m_table_up->start_row ();
a6c47c14 424
112e8700 425 do_begin (type, id);
631ec795
AC
426}
427
631ec795 428void
112e8700 429ui_out::end (ui_out_type type)
631ec795 430{
112e8700 431 pop_level (type);
5d502164 432
112e8700 433 do_end (type);
8b93c638
JM
434}
435
8b93c638 436void
381befee 437ui_out::field_signed (const char *fldname, LONGEST value)
8b93c638
JM
438{
439 int fldno;
440 int width;
112e8700 441 ui_align align;
8b93c638 442
112e8700 443 verify_field (&fldno, &width, &align);
8b93c638 444
381befee 445 do_field_signed (fldno, width, align, fldname, value);
8b93c638
JM
446}
447
52c6a6ac 448void
381befee
TT
449ui_out::field_fmt_signed (int input_width, ui_align input_align,
450 const char *fldname, LONGEST value)
52c6a6ac
JJ
451{
452 int fldno;
453 int width;
112e8700 454 ui_align align;
52c6a6ac 455
112e8700 456 verify_field (&fldno, &width, &align);
52c6a6ac 457
381befee 458 do_field_signed (fldno, input_width, input_align, fldname, value);
52c6a6ac
JJ
459}
460
1f77b012
TT
461/* See ui-out.h. */
462
463void
464ui_out::field_unsigned (const char *fldname, ULONGEST value)
465{
466 int fldno;
467 int width;
468 ui_align align;
469
470 verify_field (&fldno, &width, &align);
471
472 do_field_unsigned (fldno, width, align, fldname, value);
473}
474
15230f37
TJB
475/* Documented in ui-out.h. */
476
8b93c638 477void
112e8700
SM
478ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch,
479 CORE_ADDR address)
8b93c638 480{
35fb8261 481 field_string (fldname, print_core_address (gdbarch, address),
e43b10e1 482 address_style.style ());
8b93c638
JM
483}
484
485void
cbe56571 486ui_out::field_stream (const char *fldname, string_file &stream,
e43b10e1 487 const ui_file_style &style)
8b93c638 488{
d7e74731 489 if (!stream.empty ())
cbe56571 490 field_string (fldname, stream.c_str (), style);
8b93c638 491 else
112e8700 492 field_skip (fldname);
d7e74731 493 stream.clear ();
8b93c638
JM
494}
495
581e13c1 496/* Used to omit a field. */
8b93c638
JM
497
498void
112e8700 499ui_out::field_skip (const char *fldname)
8b93c638
JM
500{
501 int fldno;
502 int width;
112e8700 503 ui_align align;
8b93c638 504
112e8700 505 verify_field (&fldno, &width, &align);
8b93c638 506
112e8700 507 do_field_skip (fldno, width, align, fldname);
8b93c638
JM
508}
509
510void
cbe56571 511ui_out::field_string (const char *fldname, const char *string,
e43b10e1 512 const ui_file_style &style)
8b93c638
JM
513{
514 int fldno;
515 int width;
112e8700 516 ui_align align;
8b93c638 517
112e8700 518 verify_field (&fldno, &width, &align);
8b93c638 519
cbe56571 520 do_field_string (fldno, width, align, fldname, string, style);
8b93c638
JM
521}
522
523/* VARARGS */
524void
112e8700 525ui_out::field_fmt (const char *fldname, const char *format, ...)
8b93c638
JM
526{
527 va_list args;
528 int fldno;
529 int width;
112e8700 530 ui_align align;
8b93c638 531
112e8700 532 verify_field (&fldno, &width, &align);
8b93c638
JM
533
534 va_start (args, format);
535
7f6aba03
TT
536 do_field_fmt (fldno, width, align, fldname, ui_file_style (), format, args);
537
538 va_end (args);
539}
540
541void
542ui_out::field_fmt (const char *fldname, const ui_file_style &style,
543 const char *format, ...)
544{
545 va_list args;
546 int fldno;
547 int width;
548 ui_align align;
549
550 verify_field (&fldno, &width, &align);
551
552 va_start (args, format);
553
554 do_field_fmt (fldno, width, align, fldname, style, format, args);
8b93c638
JM
555
556 va_end (args);
557}
558
559void
112e8700 560ui_out::spaces (int numspaces)
8b93c638 561{
112e8700 562 do_spaces (numspaces);
8b93c638
JM
563}
564
565void
112e8700 566ui_out::text (const char *string)
8b93c638 567{
112e8700 568 do_text (string);
8b93c638
JM
569}
570
571void
2a3c1174
PA
572ui_out::call_do_message (const ui_file_style &style, const char *format,
573 ...)
8b93c638
JM
574{
575 va_list args;
576
577 va_start (args, format);
284782de
SM
578
579 /* Since call_do_message is only used as a helper of vmessage, silence the
580 warning here once instead of at all call sites in vmessage, if we were
581 to put a "format" attribute on call_do_message. */
582 DIAGNOSTIC_PUSH
583 DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
2a3c1174 584 do_message (style, format, args);
284782de
SM
585 DIAGNOSTIC_POP
586
2a3c1174
PA
587 va_end (args);
588}
589
590void
591ui_out::vmessage (const ui_file_style &in_style, const char *format,
592 va_list args)
593{
594 format_pieces fpieces (&format, true);
595
596 ui_file_style style = in_style;
597
598 for (auto &&piece : fpieces)
599 {
600 const char *current_substring = piece.string;
601
602 gdb_assert (piece.n_int_args >= 0 && piece.n_int_args <= 2);
603 int intvals[2] = { 0, 0 };
604 for (int i = 0; i < piece.n_int_args; ++i)
605 intvals[i] = va_arg (args, int);
606
607 /* The only ones we support for now. */
608 gdb_assert (piece.n_int_args == 0
609 || piece.argclass == string_arg
610 || piece.argclass == int_arg
611 || piece.argclass == long_arg);
612
613 switch (piece.argclass)
614 {
615 case string_arg:
616 {
617 const char *str = va_arg (args, const char *);
618 switch (piece.n_int_args)
619 {
620 case 0:
621 call_do_message (style, current_substring, str);
622 break;
623 case 1:
624 call_do_message (style, current_substring, intvals[0], str);
625 break;
626 case 2:
627 call_do_message (style, current_substring,
628 intvals[0], intvals[1], str);
629 break;
630 }
631 }
632 break;
633 case wide_string_arg:
557b4d76 634 gdb_assert_not_reached ("wide_string_arg not supported in vmessage");
2a3c1174
PA
635 break;
636 case wide_char_arg:
557b4d76 637 gdb_assert_not_reached ("wide_char_arg not supported in vmessage");
2a3c1174
PA
638 break;
639 case long_long_arg:
640 call_do_message (style, current_substring, va_arg (args, long long));
641 break;
642 case int_arg:
643 {
644 int val = va_arg (args, int);
645 switch (piece.n_int_args)
646 {
647 case 0:
648 call_do_message (style, current_substring, val);
649 break;
650 case 1:
651 call_do_message (style, current_substring, intvals[0], val);
652 break;
653 case 2:
654 call_do_message (style, current_substring,
655 intvals[0], intvals[1], val);
656 break;
657 }
658 }
659 break;
660 case long_arg:
661 {
662 long val = va_arg (args, long);
663 switch (piece.n_int_args)
664 {
665 case 0:
666 call_do_message (style, current_substring, val);
667 break;
668 case 1:
669 call_do_message (style, current_substring, intvals[0], val);
670 break;
671 case 2:
672 call_do_message (style, current_substring,
673 intvals[0], intvals[1], val);
674 break;
675 }
676 }
677 break;
e06f3d6e
AB
678 case size_t_arg:
679 {
680 size_t val = va_arg (args, size_t);
681 switch (piece.n_int_args)
682 {
683 case 0:
684 call_do_message (style, current_substring, val);
685 break;
686 case 1:
687 call_do_message (style, current_substring, intvals[0], val);
688 break;
689 case 2:
690 call_do_message (style, current_substring,
691 intvals[0], intvals[1], val);
692 break;
693 }
694 }
695 break;
2a3c1174
PA
696 case double_arg:
697 call_do_message (style, current_substring, va_arg (args, double));
698 break;
699 case long_double_arg:
557b4d76 700 gdb_assert_not_reached ("long_double_arg not supported in vmessage");
2a3c1174
PA
701 break;
702 case dec32float_arg:
557b4d76 703 gdb_assert_not_reached ("dec32float_arg not supported in vmessage");
2a3c1174
PA
704 break;
705 case dec64float_arg:
557b4d76 706 gdb_assert_not_reached ("dec64float_arg not supported in vmessage");
2a3c1174
PA
707 break;
708 case dec128float_arg:
557b4d76 709 gdb_assert_not_reached ("dec128float_arg not supported in vmessage");
2a3c1174
PA
710 break;
711 case ptr_arg:
712 switch (current_substring[2])
713 {
714 case 'F':
715 {
716 gdb_assert (!test_flags (disallow_ui_out_field));
717 base_field_s *bf = va_arg (args, base_field_s *);
718 switch (bf->kind)
719 {
28ce7b07 720 case field_kind::FIELD_SIGNED:
2a3c1174
PA
721 {
722 auto *f = (signed_field_s *) bf;
723 field_signed (f->name, f->val);
724 }
725 break;
28ce7b07 726 case field_kind::FIELD_STRING:
2a3c1174
PA
727 {
728 auto *f = (string_field_s *) bf;
729 field_string (f->name, f->str);
730 }
731 break;
732 }
733 }
734 break;
735 case 's':
736 {
737 styled_string_s *ss = va_arg (args, styled_string_s *);
738 call_do_message (ss->style, "%s", ss->str);
739 }
740 break;
741 case '[':
742 style = *va_arg (args, const ui_file_style *);
743 break;
744 case ']':
745 {
746 void *arg = va_arg (args, void *);
747 gdb_assert (arg == nullptr);
748
749 style = {};
750 }
751 break;
752 default:
753 call_do_message (style, current_substring, va_arg (args, void *));
754 break;
755 }
756 break;
757 case literal_piece:
758 /* Print a portion of the format string that has no
759 directives. Note that this will not include any ordinary
760 %-specs, but it might include "%%". That is why we use
761 call_do_message here. Also, we pass a dummy argument
762 because some platforms have modified GCC to include
763 -Wformat-security by default, which will warn here if
764 there is no argument. */
765 call_do_message (style, current_substring, 0);
766 break;
767 default:
f34652de 768 internal_error (_("failed internal consistency check"));
2a3c1174
PA
769 }
770 }
771}
772
773void
774ui_out::message (const char *format, ...)
775{
776 va_list args;
777 va_start (args, format);
778
779 vmessage (ui_file_style (), format, args);
780
8b93c638
JM
781 va_end (args);
782}
783
8b93c638 784void
6c92c339 785ui_out::wrap_hint (int indent)
8b93c638 786{
6c92c339 787 do_wrap_hint (indent);
8b93c638
JM
788}
789
790void
112e8700 791ui_out::flush ()
8b93c638 792{
112e8700 793 do_flush ();
8b93c638
JM
794}
795
7becfd03 796void
112e8700 797ui_out::redirect (ui_file *outstream)
0fac0b41 798{
7becfd03 799 do_redirect (outstream);
0fac0b41
DJ
800}
801
581e13c1 802/* Test the flags against the mask given. */
112e8700
SM
803ui_out_flags
804ui_out::test_flags (ui_out_flags mask)
8b93c638 805{
112e8700 806 return m_flags & mask;
8b93c638
JM
807}
808
112e8700 809bool
4904c3c6 810ui_out::is_mi_like_p () const
8b93c638 811{
112e8700 812 return do_is_mi_like_p ();
0fac0b41
DJ
813}
814
a6c47c14
AC
815/* Verify that the field/tuple/list is correctly positioned. Return
816 the field number and corresponding alignment (if
817 available/applicable). */
8b93c638 818
112e8700
SM
819void
820ui_out::verify_field (int *fldno, int *width, ui_align *align)
8b93c638 821{
112e8700 822 ui_out_level *current = current_level ();
c5209615 823 const char *text;
a6c47c14 824
112e8700
SM
825 if (m_table_up != nullptr
826 && m_table_up->current_state () != ui_out_table::state::BODY)
8b93c638 827 {
f34652de 828 internal_error (_("table_body missing; table fields must be \
e2e0b3e5 829specified after table_body and inside a list."));
8b93c638 830 }
8b93c638 831
909c0aa5 832 current->inc_field_count ();
8b93c638 833
112e8700
SM
834 if (m_table_up != nullptr
835 && m_table_up->current_state () == ui_out_table::state::BODY
836 && m_table_up->entry_level () == level ()
837 && m_table_up->get_next_header (fldno, width, align, &text))
8b93c638 838 {
909c0aa5 839 if (*fldno != current->field_count ())
f34652de 840 internal_error (_("ui-out internal error in handling headers."));
8b93c638
JM
841 }
842 else
843 {
844 *width = 0;
845 *align = ui_noalign;
909c0aa5 846 *fldno = current->field_count ();
8b93c638
JM
847 }
848}
849
170b53b2 850/* Access table field parameters. */
112e8700
SM
851
852bool
853ui_out::query_table_field (int colno, int *width, int *alignment,
854 const char **col_name)
170b53b2 855{
112e8700
SM
856 if (m_table_up == nullptr)
857 return false;
170b53b2 858
112e8700 859 return m_table_up->query_field (colno, width, alignment, col_name);
170b53b2
UW
860}
861
112e8700 862/* The constructor. */
8b93c638 863
112e8700
SM
864ui_out::ui_out (ui_out_flags flags)
865: m_flags (flags)
8b93c638 866{
33b2fac6 867 /* Create the ui-out level #1, the default level. */
112e8700
SM
868 push_level (ui_out_type_tuple);
869}
54eb231c 870
112e8700
SM
871ui_out::~ui_out ()
872{
8b93c638 873}