Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / ui-out.c
CommitLineData
8b93c638 1/* Output generating routines for GDB.
349c5d5f 2
3666a048 3 Copyright (C) 1999-2021 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)
215 internal_error (__FILE__, __LINE__,
216 _("extra table_body call not allowed; there must be only "
217 "one table_body after a table_begin and before a "
218 "table_end."));
219
220 /* Check if the number of defined headers matches the number of expected
221 columns. */
222 if (m_headers.size () != m_nr_cols)
223 internal_error (__FILE__, __LINE__,
224 _("number of headers differ from number of table "
225 "columns."));
226
227 m_state = state::BODY;
228 m_headers_iterator = m_headers.begin ();
229}
230
231/* See ui-out.h. */
232
233void ui_out_table::append_header (int width, ui_align alignment,
234 const std::string &col_name,
235 const std::string &col_hdr)
236{
237 if (m_state != state::HEADERS)
238 internal_error (__FILE__, __LINE__,
239 _("table header must be specified after table_begin and "
240 "before table_body."));
241
242 std::unique_ptr<ui_out_hdr> header (new ui_out_hdr (m_headers.size () + 1,
243 width, alignment,
244 col_name, col_hdr));
245
246 m_headers.push_back (std::move (header));
247}
248
249/* See ui-out.h. */
250
251void ui_out_table::start_row ()
252{
253 m_headers_iterator = m_headers.begin ();
254}
255
256/* See ui-out.h. */
257
258bool ui_out_table::get_next_header (int *colno, int *width, ui_align *alignment,
259 const char **col_hdr)
260{
261 /* There may be no headers at all or we may have used all columns. */
262 if (m_headers_iterator == m_headers.end ())
263 return false;
264
265 ui_out_hdr *hdr = m_headers_iterator->get ();
266
267 *colno = hdr->number ();
268 *width = hdr->min_width ();
269 *alignment = hdr->alignment ();
270 *col_hdr = hdr->header ().c_str ();
271
272 /* Advance the header pointer to the next entry. */
273 m_headers_iterator++;
274
275 return true;
276}
277
278/* See ui-out.h. */
279
280bool ui_out_table::query_field (int colno, int *width, int *alignment,
281 const char **col_name) const
282{
283 /* Column numbers are 1-based, so convert to 0-based index. */
284 int index = colno - 1;
285
286 if (index >= 0 && index < m_headers.size ())
287 {
288 ui_out_hdr *hdr = m_headers[index].get ();
289
290 gdb_assert (colno == hdr->number ());
291
292 *width = hdr->min_width ();
293 *alignment = hdr->alignment ();
294 *col_name = hdr->name ().c_str ();
295
296 return true;
297 }
298 else
299 return false;
300}
301
302/* See ui-out.h. */
303
304ui_out_table::state ui_out_table::current_state () const
305{
306 return m_state;
307}
308
309/* See ui-out.h. */
310
311int ui_out_table::entry_level () const
312{
313 return m_entry_level;
314}
bafdd3b3 315
112e8700
SM
316int
317ui_out::level () const
318{
319 return m_levels.size ();
320}
8b93c638 321
581e13c1 322/* The current (inner most) level. */
112e8700
SM
323
324ui_out_level *
325ui_out::current_level () const
80f49b30 326{
112e8700 327 return m_levels.back ().get ();
80f49b30
AC
328}
329
33b2fac6 330/* Create a new level, of TYPE. */
112e8700
SM
331void
332ui_out::push_level (ui_out_type type)
80f49b30 333{
909c0aa5 334 std::unique_ptr<ui_out_level> level (new ui_out_level (type));
56df3084 335
112e8700 336 m_levels.push_back (std::move (level));
80f49b30
AC
337}
338
33b2fac6
SM
339/* Discard the current level. TYPE is the type of the level being
340 discarded. */
112e8700
SM
341void
342ui_out::pop_level (ui_out_type type)
80f49b30 343{
581e13c1 344 /* We had better not underflow the buffer. */
112e8700
SM
345 gdb_assert (m_levels.size () > 0);
346 gdb_assert (current_level ()->type () == type);
347
348 m_levels.pop_back ();
349}
8b93c638 350
581e13c1 351/* Mark beginning of a table. */
8b93c638 352
112e8700
SM
353void
354ui_out::table_begin (int nr_cols, int nr_rows, const std::string &tblid)
8b93c638 355{
112e8700 356 if (m_table_up != nullptr)
8e65ff28 357 internal_error (__FILE__, __LINE__,
e2e0b3e5
AC
358 _("tables cannot be nested; table_begin found before \
359previous table_end."));
8b93c638 360
112e8700 361 m_table_up.reset (new ui_out_table (level () + 1, nr_cols, tblid));
95a23284 362
112e8700 363 do_table_begin (nr_cols, nr_rows, tblid.c_str ());
8b93c638
JM
364}
365
366void
112e8700
SM
367ui_out::table_header (int width, ui_align alignment,
368 const std::string &col_name, const std::string &col_hdr)
8b93c638 369{
112e8700 370 if (m_table_up == nullptr)
8e65ff28 371 internal_error (__FILE__, __LINE__,
112e8700
SM
372 _("table_header outside a table is not valid; it must be \
373after a table_begin and before a table_body."));
77a179e7 374
112e8700 375 m_table_up->append_header (width, alignment, col_name, col_hdr);
8b93c638 376
112e8700 377 do_table_header (width, alignment, col_name, col_hdr);
8b93c638
JM
378}
379
112e8700
SM
380void
381ui_out::table_body ()
8b93c638 382{
112e8700 383 if (m_table_up == nullptr)
8e65ff28 384 internal_error (__FILE__, __LINE__,
112e8700
SM
385 _("table_body outside a table is not valid; it must be "
386 "after a table_begin and before a table_end."));
8b93c638 387
112e8700 388 m_table_up->start_body ();
36d18bc5 389
112e8700 390 do_table_body ();
8b93c638
JM
391}
392
393void
112e8700 394ui_out::table_end ()
8b93c638 395{
112e8700 396 if (m_table_up == nullptr)
8e65ff28 397 internal_error (__FILE__, __LINE__,
112e8700 398 _("misplaced table_end or missing table_begin."));
8b93c638 399
112e8700 400 do_table_end ();
8b93c638 401
112e8700 402 m_table_up = nullptr;
8b93c638
JM
403}
404
405void
112e8700 406ui_out::begin (ui_out_type type, const char *id)
8b93c638 407{
a6c47c14
AC
408 /* Be careful to verify the ``field'' before the new tuple/list is
409 pushed onto the stack. That way the containing list/table/row is
410 verified and not the newly created tuple/list. This verification
411 is needed (at least) for the case where a table row entry
412 contains either a tuple/list. For that case bookkeeping such as
413 updating the column count or advancing to the next heading still
414 needs to be performed. */
415 {
416 int fldno;
417 int width;
112e8700 418 ui_align align;
5d502164 419
112e8700 420 verify_field (&fldno, &width, &align);
a6c47c14
AC
421 }
422
112e8700 423 push_level (type);
a6c47c14
AC
424
425 /* If the push puts us at the same level as a table row entry, we've
426 got a new table row. Put the header pointer back to the start. */
112e8700
SM
427 if (m_table_up != nullptr
428 && m_table_up->current_state () == ui_out_table::state::BODY
429 && m_table_up->entry_level () == level ())
430 m_table_up->start_row ();
a6c47c14 431
112e8700 432 do_begin (type, id);
631ec795
AC
433}
434
631ec795 435void
112e8700 436ui_out::end (ui_out_type type)
631ec795 437{
112e8700 438 pop_level (type);
5d502164 439
112e8700 440 do_end (type);
8b93c638
JM
441}
442
8b93c638 443void
381befee 444ui_out::field_signed (const char *fldname, LONGEST value)
8b93c638
JM
445{
446 int fldno;
447 int width;
112e8700 448 ui_align align;
8b93c638 449
112e8700 450 verify_field (&fldno, &width, &align);
8b93c638 451
381befee 452 do_field_signed (fldno, width, align, fldname, value);
8b93c638
JM
453}
454
52c6a6ac 455void
381befee
TT
456ui_out::field_fmt_signed (int input_width, ui_align input_align,
457 const char *fldname, LONGEST value)
52c6a6ac
JJ
458{
459 int fldno;
460 int width;
112e8700 461 ui_align align;
52c6a6ac 462
112e8700 463 verify_field (&fldno, &width, &align);
52c6a6ac 464
381befee 465 do_field_signed (fldno, input_width, input_align, fldname, value);
52c6a6ac
JJ
466}
467
1f77b012
TT
468/* See ui-out.h. */
469
470void
471ui_out::field_unsigned (const char *fldname, ULONGEST value)
472{
473 int fldno;
474 int width;
475 ui_align align;
476
477 verify_field (&fldno, &width, &align);
478
479 do_field_unsigned (fldno, width, align, fldname, value);
480}
481
15230f37
TJB
482/* Documented in ui-out.h. */
483
8b93c638 484void
112e8700
SM
485ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch,
486 CORE_ADDR address)
8b93c638 487{
35fb8261 488 field_string (fldname, print_core_address (gdbarch, address),
e43b10e1 489 address_style.style ());
8b93c638
JM
490}
491
492void
cbe56571 493ui_out::field_stream (const char *fldname, string_file &stream,
e43b10e1 494 const ui_file_style &style)
8b93c638 495{
d7e74731 496 if (!stream.empty ())
cbe56571 497 field_string (fldname, stream.c_str (), style);
8b93c638 498 else
112e8700 499 field_skip (fldname);
d7e74731 500 stream.clear ();
8b93c638
JM
501}
502
581e13c1 503/* Used to omit a field. */
8b93c638
JM
504
505void
112e8700 506ui_out::field_skip (const char *fldname)
8b93c638
JM
507{
508 int fldno;
509 int width;
112e8700 510 ui_align align;
8b93c638 511
112e8700 512 verify_field (&fldno, &width, &align);
8b93c638 513
112e8700 514 do_field_skip (fldno, width, align, fldname);
8b93c638
JM
515}
516
517void
cbe56571 518ui_out::field_string (const char *fldname, const char *string,
e43b10e1 519 const ui_file_style &style)
8b93c638
JM
520{
521 int fldno;
522 int width;
112e8700 523 ui_align align;
8b93c638 524
112e8700 525 verify_field (&fldno, &width, &align);
8b93c638 526
cbe56571 527 do_field_string (fldno, width, align, fldname, string, style);
8b93c638
JM
528}
529
530/* VARARGS */
531void
112e8700 532ui_out::field_fmt (const char *fldname, const char *format, ...)
8b93c638
JM
533{
534 va_list args;
535 int fldno;
536 int width;
112e8700 537 ui_align align;
8b93c638 538
112e8700 539 verify_field (&fldno, &width, &align);
8b93c638
JM
540
541 va_start (args, format);
542
7f6aba03
TT
543 do_field_fmt (fldno, width, align, fldname, ui_file_style (), format, args);
544
545 va_end (args);
546}
547
548void
549ui_out::field_fmt (const char *fldname, const ui_file_style &style,
550 const char *format, ...)
551{
552 va_list args;
553 int fldno;
554 int width;
555 ui_align align;
556
557 verify_field (&fldno, &width, &align);
558
559 va_start (args, format);
560
561 do_field_fmt (fldno, width, align, fldname, style, format, args);
8b93c638
JM
562
563 va_end (args);
564}
565
566void
112e8700 567ui_out::spaces (int numspaces)
8b93c638 568{
112e8700 569 do_spaces (numspaces);
8b93c638
JM
570}
571
572void
112e8700 573ui_out::text (const char *string)
8b93c638 574{
112e8700 575 do_text (string);
8b93c638
JM
576}
577
578void
2a3c1174
PA
579ui_out::call_do_message (const ui_file_style &style, const char *format,
580 ...)
8b93c638
JM
581{
582 va_list args;
583
584 va_start (args, format);
284782de
SM
585
586 /* Since call_do_message is only used as a helper of vmessage, silence the
587 warning here once instead of at all call sites in vmessage, if we were
588 to put a "format" attribute on call_do_message. */
589 DIAGNOSTIC_PUSH
590 DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
2a3c1174 591 do_message (style, format, args);
284782de
SM
592 DIAGNOSTIC_POP
593
2a3c1174
PA
594 va_end (args);
595}
596
597void
598ui_out::vmessage (const ui_file_style &in_style, const char *format,
599 va_list args)
600{
601 format_pieces fpieces (&format, true);
602
603 ui_file_style style = in_style;
604
605 for (auto &&piece : fpieces)
606 {
607 const char *current_substring = piece.string;
608
609 gdb_assert (piece.n_int_args >= 0 && piece.n_int_args <= 2);
610 int intvals[2] = { 0, 0 };
611 for (int i = 0; i < piece.n_int_args; ++i)
612 intvals[i] = va_arg (args, int);
613
614 /* The only ones we support for now. */
615 gdb_assert (piece.n_int_args == 0
616 || piece.argclass == string_arg
617 || piece.argclass == int_arg
618 || piece.argclass == long_arg);
619
620 switch (piece.argclass)
621 {
622 case string_arg:
623 {
624 const char *str = va_arg (args, const char *);
625 switch (piece.n_int_args)
626 {
627 case 0:
628 call_do_message (style, current_substring, str);
629 break;
630 case 1:
631 call_do_message (style, current_substring, intvals[0], str);
632 break;
633 case 2:
634 call_do_message (style, current_substring,
635 intvals[0], intvals[1], str);
636 break;
637 }
638 }
639 break;
640 case wide_string_arg:
641 gdb_assert_not_reached (_("wide_string_arg not supported in vmessage"));
642 break;
643 case wide_char_arg:
644 gdb_assert_not_reached (_("wide_char_arg not supported in vmessage"));
645 break;
646 case long_long_arg:
647 call_do_message (style, current_substring, va_arg (args, long long));
648 break;
649 case int_arg:
650 {
651 int val = va_arg (args, int);
652 switch (piece.n_int_args)
653 {
654 case 0:
655 call_do_message (style, current_substring, val);
656 break;
657 case 1:
658 call_do_message (style, current_substring, intvals[0], val);
659 break;
660 case 2:
661 call_do_message (style, current_substring,
662 intvals[0], intvals[1], val);
663 break;
664 }
665 }
666 break;
667 case long_arg:
668 {
669 long val = va_arg (args, long);
670 switch (piece.n_int_args)
671 {
672 case 0:
673 call_do_message (style, current_substring, val);
674 break;
675 case 1:
676 call_do_message (style, current_substring, intvals[0], val);
677 break;
678 case 2:
679 call_do_message (style, current_substring,
680 intvals[0], intvals[1], val);
681 break;
682 }
683 }
684 break;
e06f3d6e
AB
685 case size_t_arg:
686 {
687 size_t val = va_arg (args, size_t);
688 switch (piece.n_int_args)
689 {
690 case 0:
691 call_do_message (style, current_substring, val);
692 break;
693 case 1:
694 call_do_message (style, current_substring, intvals[0], val);
695 break;
696 case 2:
697 call_do_message (style, current_substring,
698 intvals[0], intvals[1], val);
699 break;
700 }
701 }
702 break;
2a3c1174
PA
703 case double_arg:
704 call_do_message (style, current_substring, va_arg (args, double));
705 break;
706 case long_double_arg:
707 gdb_assert_not_reached (_("long_double_arg not supported in vmessage"));
708 break;
709 case dec32float_arg:
710 gdb_assert_not_reached (_("dec32float_arg not supported in vmessage"));
711 break;
712 case dec64float_arg:
713 gdb_assert_not_reached (_("dec64float_arg not supported in vmessage"));
714 break;
715 case dec128float_arg:
716 gdb_assert_not_reached (_("dec128float_arg not supported in vmessage"));
717 break;
718 case ptr_arg:
719 switch (current_substring[2])
720 {
721 case 'F':
722 {
723 gdb_assert (!test_flags (disallow_ui_out_field));
724 base_field_s *bf = va_arg (args, base_field_s *);
725 switch (bf->kind)
726 {
28ce7b07 727 case field_kind::FIELD_SIGNED:
2a3c1174
PA
728 {
729 auto *f = (signed_field_s *) bf;
730 field_signed (f->name, f->val);
731 }
732 break;
28ce7b07 733 case field_kind::FIELD_STRING:
2a3c1174
PA
734 {
735 auto *f = (string_field_s *) bf;
736 field_string (f->name, f->str);
737 }
738 break;
739 }
740 }
741 break;
742 case 's':
743 {
744 styled_string_s *ss = va_arg (args, styled_string_s *);
745 call_do_message (ss->style, "%s", ss->str);
746 }
747 break;
748 case '[':
749 style = *va_arg (args, const ui_file_style *);
750 break;
751 case ']':
752 {
753 void *arg = va_arg (args, void *);
754 gdb_assert (arg == nullptr);
755
756 style = {};
757 }
758 break;
759 default:
760 call_do_message (style, current_substring, va_arg (args, void *));
761 break;
762 }
763 break;
764 case literal_piece:
765 /* Print a portion of the format string that has no
766 directives. Note that this will not include any ordinary
767 %-specs, but it might include "%%". That is why we use
768 call_do_message here. Also, we pass a dummy argument
769 because some platforms have modified GCC to include
770 -Wformat-security by default, which will warn here if
771 there is no argument. */
772 call_do_message (style, current_substring, 0);
773 break;
774 default:
775 internal_error (__FILE__, __LINE__,
776 _("failed internal consistency check"));
777 }
778 }
779}
780
781void
782ui_out::message (const char *format, ...)
783{
784 va_list args;
785 va_start (args, format);
786
787 vmessage (ui_file_style (), format, args);
788
8b93c638
JM
789 va_end (args);
790}
791
8b93c638 792void
112e8700 793ui_out::wrap_hint (const char *identstring)
8b93c638 794{
112e8700 795 do_wrap_hint (identstring);
8b93c638
JM
796}
797
798void
112e8700 799ui_out::flush ()
8b93c638 800{
112e8700 801 do_flush ();
8b93c638
JM
802}
803
7becfd03 804void
112e8700 805ui_out::redirect (ui_file *outstream)
0fac0b41 806{
7becfd03 807 do_redirect (outstream);
0fac0b41
DJ
808}
809
581e13c1 810/* Test the flags against the mask given. */
112e8700
SM
811ui_out_flags
812ui_out::test_flags (ui_out_flags mask)
8b93c638 813{
112e8700 814 return m_flags & mask;
8b93c638
JM
815}
816
112e8700 817bool
4904c3c6 818ui_out::is_mi_like_p () const
8b93c638 819{
112e8700 820 return do_is_mi_like_p ();
0fac0b41
DJ
821}
822
a6c47c14
AC
823/* Verify that the field/tuple/list is correctly positioned. Return
824 the field number and corresponding alignment (if
825 available/applicable). */
8b93c638 826
112e8700
SM
827void
828ui_out::verify_field (int *fldno, int *width, ui_align *align)
8b93c638 829{
112e8700 830 ui_out_level *current = current_level ();
c5209615 831 const char *text;
a6c47c14 832
112e8700
SM
833 if (m_table_up != nullptr
834 && m_table_up->current_state () != ui_out_table::state::BODY)
8b93c638 835 {
77a179e7
SM
836 internal_error (__FILE__, __LINE__,
837 _("table_body missing; table fields must be \
e2e0b3e5 838specified after table_body and inside a list."));
8b93c638 839 }
8b93c638 840
909c0aa5 841 current->inc_field_count ();
8b93c638 842
112e8700
SM
843 if (m_table_up != nullptr
844 && m_table_up->current_state () == ui_out_table::state::BODY
845 && m_table_up->entry_level () == level ()
846 && m_table_up->get_next_header (fldno, width, align, &text))
8b93c638 847 {
909c0aa5 848 if (*fldno != current->field_count ())
8e65ff28 849 internal_error (__FILE__, __LINE__,
e2e0b3e5 850 _("ui-out internal error in handling headers."));
8b93c638
JM
851 }
852 else
853 {
854 *width = 0;
855 *align = ui_noalign;
909c0aa5 856 *fldno = current->field_count ();
8b93c638
JM
857 }
858}
859
170b53b2 860/* Access table field parameters. */
112e8700
SM
861
862bool
863ui_out::query_table_field (int colno, int *width, int *alignment,
864 const char **col_name)
170b53b2 865{
112e8700
SM
866 if (m_table_up == nullptr)
867 return false;
170b53b2 868
112e8700 869 return m_table_up->query_field (colno, width, alignment, col_name);
170b53b2
UW
870}
871
112e8700 872/* The constructor. */
8b93c638 873
112e8700
SM
874ui_out::ui_out (ui_out_flags flags)
875: m_flags (flags)
8b93c638 876{
33b2fac6 877 /* Create the ui-out level #1, the default level. */
112e8700
SM
878 push_level (ui_out_type_tuple);
879}
54eb231c 880
112e8700
SM
881ui_out::~ui_out ()
882{
8b93c638 883}
This page took 2.622149 seconds and 4 git commands to generate.