1 /* Output generating routines for GDB.
3 Copyright (C) 1999-2016 Free Software Foundation, Inc.
5 Contributed by Cygnus Solutions.
6 Written by Fernando Nasser for Cygnus.
8 This file is part of GDB.
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
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
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.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 #include "expression.h" /* For language.h */
32 /* A header of a ui_out_table. */
38 explicit ui_out_hdr (int number
, int min_width
, ui_align alignment
,
39 const std::string
&name
, const std::string
&header
)
41 m_min_width (min_width
),
42 m_alignment (alignment
),
53 int min_width () const
58 ui_align
alignment () const
63 const std::string
&header () const
68 const std::string
&name () const
75 /* The number of the table column this header represents, 1-based. */
78 /* Minimal column width in characters. May or may not be applicable,
79 depending on the actual implementation of ui_out. */
82 /* Alignment of the content in the column. May or may not be applicable,
83 depending on the actual implementation of ui_out. */
86 /* Internal column name, used to internally refer to the column. */
89 /* Printed header text of the column. */
95 /* Count each field; the first element is for non-list fields. */
97 /* The type of this level. */
98 enum ui_out_type type
;
102 /* Tables are special. Maintain a separate structure that tracks
103 their state. At present an output can only contain a single table
104 but that restriction might eventually be lifted. */
108 /* If on, a table is being generated. */
111 /* If on, the body of a table is being generated. If off, the table
112 header is being generated. */
115 /* The level at which each entry of the table is to be found. A row
116 (a tuple) is made up of entries. Consequently ENTRY_LEVEL is one
117 above that of the table. */
120 /* Number of table columns (as specified in the table_begin call). */
123 /* String identifying the table (as specified in the table_begin
127 /* Pointers to the column headers. */
128 std::vector
<std::unique_ptr
<ui_out_hdr
>> headers
;
130 /* Iterator over the headers vector, used when printing successive fields. */
131 std::vector
<std::unique_ptr
<ui_out_hdr
>>::const_iterator headers_iterator
;
136 /* The ui_out structure */
141 /* Specific implementation of ui-out. */
142 const struct ui_out_impl
*impl
;
148 /* Vector to store and track the ui-out levels. */
149 std::vector
<std::unique_ptr
<ui_out_level
>> levels
;
151 /* A table, if any. At present only a single table is supported. */
152 struct ui_out_table table
;
155 /* The current (inner most) level. */
156 static struct ui_out_level
*
157 current_level (struct ui_out
*uiout
)
159 return uiout
->levels
[uiout
->level
].get ();
162 /* Create a new level, of TYPE. Return the new level's index. */
164 push_level (struct ui_out
*uiout
,
165 enum ui_out_type type
)
167 std::unique_ptr
<ui_out_level
> current (new ui_out_level ());
169 current
->field_count
= 0;
170 current
->type
= type
;
173 uiout
->levels
.push_back (std::move (current
));
178 /* Discard the current level, return the discarded level's index.
179 TYPE is the type of the level being discarded. */
181 pop_level (struct ui_out
*uiout
,
182 enum ui_out_type type
)
184 /* We had better not underflow the buffer. */
185 gdb_assert (uiout
->level
> 0);
186 gdb_assert (current_level (uiout
)->type
== type
);
188 uiout
->levels
.pop_back ();
191 return uiout
->level
+ 1;
194 /* These are the interfaces to implementation functions. */
196 static void uo_table_begin (struct ui_out
*uiout
, int nbrofcols
,
197 int nr_rows
, const char *tblid
);
198 static void uo_table_body (struct ui_out
*uiout
);
199 static void uo_table_end (struct ui_out
*uiout
);
200 static void uo_table_header (struct ui_out
*uiout
, int width
,
202 const std::string
&col_name
,
203 const std::string
&col_hdr
);
204 static void uo_begin (struct ui_out
*uiout
,
205 enum ui_out_type type
,
206 int level
, const char *id
);
207 static void uo_end (struct ui_out
*uiout
,
208 enum ui_out_type type
,
210 static void uo_field_int (struct ui_out
*uiout
, int fldno
, int width
,
211 enum ui_align align
, const char *fldname
, int value
);
212 static void uo_field_skip (struct ui_out
*uiout
, int fldno
, int width
,
213 enum ui_align align
, const char *fldname
);
214 static void uo_field_fmt (struct ui_out
*uiout
, int fldno
, int width
,
215 enum ui_align align
, const char *fldname
,
216 const char *format
, va_list args
)
217 ATTRIBUTE_PRINTF (6, 0);
218 static void uo_spaces (struct ui_out
*uiout
, int numspaces
);
219 static void uo_text (struct ui_out
*uiout
, const char *string
);
220 static void uo_message (struct ui_out
*uiout
,
221 const char *format
, va_list args
)
222 ATTRIBUTE_PRINTF (2, 0);
223 static void uo_wrap_hint (struct ui_out
*uiout
, const char *identstring
);
224 static void uo_flush (struct ui_out
*uiout
);
225 static int uo_redirect (struct ui_out
*uiout
, struct ui_file
*outstream
);
227 /* Prototypes for local functions */
229 static void append_header_to_list (struct ui_out
*uiout
, int width
,
230 enum ui_align alignment
,
231 const std::string
&col_name
,
232 const std::string
&col_hdr
);
233 static int get_next_header (struct ui_out
*uiout
, int *colno
, int *width
,
234 enum ui_align
*alignment
, const char **col_hdr
);
235 static void clear_header_list (struct ui_out
*uiout
);
236 static void clear_table (struct ui_out
*uiout
);
237 static void verify_field (struct ui_out
*uiout
, int *fldno
, int *width
,
238 enum ui_align
*align
);
240 /* exported functions (ui_out API) */
242 /* Mark beginning of a table. */
245 ui_out_table_begin (struct ui_out
*uiout
, int nbrofcols
,
246 int nr_rows
, const std::string
&tblid
)
248 if (uiout
->table
.flag
)
249 internal_error (__FILE__
, __LINE__
,
250 _("tables cannot be nested; table_begin found before \
251 previous table_end."));
253 uiout
->table
.flag
= 1;
254 uiout
->table
.body_flag
= 0;
255 uiout
->table
.entry_level
= uiout
->level
+ 1;
256 uiout
->table
.columns
= nbrofcols
;
257 uiout
->table
.id
= tblid
;
259 clear_header_list (uiout
);
261 uo_table_begin (uiout
, nbrofcols
, nr_rows
, uiout
->table
.id
.c_str ());
265 ui_out_table_body (struct ui_out
*uiout
)
267 if (!uiout
->table
.flag
)
268 internal_error (__FILE__
, __LINE__
,
269 _("table_body outside a table is not valid; it must be \
270 after a table_begin and before a table_end."));
271 if (uiout
->table
.body_flag
)
272 internal_error (__FILE__
, __LINE__
,
273 _("extra table_body call not allowed; there must be \
274 only one table_body after a table_begin and before a table_end."));
275 if (uiout
->table
.headers
.size () != uiout
->table
.columns
)
276 internal_error (__FILE__
, __LINE__
,
277 _("number of headers differ from number of table \
280 uiout
->table
.body_flag
= 1;
282 uo_table_body (uiout
);
286 ui_out_table_end (struct ui_out
*uiout
)
288 if (!uiout
->table
.flag
)
289 internal_error (__FILE__
, __LINE__
,
290 _("misplaced table_end or missing table_begin."));
292 uiout
->table
.entry_level
= 0;
293 uiout
->table
.body_flag
= 0;
294 uiout
->table
.flag
= 0;
296 uo_table_end (uiout
);
301 ui_out_table_header (struct ui_out
*uiout
, int width
, enum ui_align alignment
,
302 const std::string
&col_name
, const std::string
&col_hdr
)
304 if (!uiout
->table
.flag
|| uiout
->table
.body_flag
)
305 internal_error (__FILE__
, __LINE__
,
306 _("table header must be specified after table_begin \
307 and before table_body."));
309 append_header_to_list (uiout
, width
, alignment
, col_name
, col_hdr
);
311 uo_table_header (uiout
, width
, alignment
, col_name
, col_hdr
);
315 do_cleanup_table_end (void *data
)
317 struct ui_out
*ui_out
= (struct ui_out
*) data
;
319 ui_out_table_end (ui_out
);
323 make_cleanup_ui_out_table_begin_end (struct ui_out
*ui_out
, int nr_cols
,
324 int nr_rows
, const char *tblid
)
326 ui_out_table_begin (ui_out
, nr_cols
, nr_rows
, tblid
);
327 return make_cleanup (do_cleanup_table_end
, ui_out
);
331 ui_out_begin (struct ui_out
*uiout
,
332 enum ui_out_type type
,
337 if (uiout
->table
.flag
&& !uiout
->table
.body_flag
)
338 internal_error (__FILE__
, __LINE__
,
339 _("table header or table_body expected; lists must be \
340 specified after table_body."));
342 /* Be careful to verify the ``field'' before the new tuple/list is
343 pushed onto the stack. That way the containing list/table/row is
344 verified and not the newly created tuple/list. This verification
345 is needed (at least) for the case where a table row entry
346 contains either a tuple/list. For that case bookkeeping such as
347 updating the column count or advancing to the next heading still
348 needs to be performed. */
354 verify_field (uiout
, &fldno
, &width
, &align
);
357 new_level
= push_level (uiout
, type
);
359 /* If the push puts us at the same level as a table row entry, we've
360 got a new table row. Put the header pointer back to the start. */
361 if (uiout
->table
.body_flag
362 && uiout
->table
.entry_level
== new_level
)
363 uiout
->table
.headers_iterator
= uiout
->table
.headers
.begin ();
365 uo_begin (uiout
, type
, new_level
, id
);
369 ui_out_end (struct ui_out
*uiout
,
370 enum ui_out_type type
)
372 int old_level
= pop_level (uiout
, type
);
374 uo_end (uiout
, type
, old_level
);
377 struct ui_out_end_cleanup_data
379 struct ui_out
*uiout
;
380 enum ui_out_type type
;
384 do_cleanup_end (void *data
)
386 struct ui_out_end_cleanup_data
*end_cleanup_data
387 = (struct ui_out_end_cleanup_data
*) data
;
389 ui_out_end (end_cleanup_data
->uiout
, end_cleanup_data
->type
);
390 xfree (end_cleanup_data
);
393 static struct cleanup
*
394 make_cleanup_ui_out_end (struct ui_out
*uiout
,
395 enum ui_out_type type
)
397 struct ui_out_end_cleanup_data
*end_cleanup_data
;
399 end_cleanup_data
= XNEW (struct ui_out_end_cleanup_data
);
400 end_cleanup_data
->uiout
= uiout
;
401 end_cleanup_data
->type
= type
;
402 return make_cleanup (do_cleanup_end
, end_cleanup_data
);
406 make_cleanup_ui_out_tuple_begin_end (struct ui_out
*uiout
,
409 ui_out_begin (uiout
, ui_out_type_tuple
, id
);
410 return make_cleanup_ui_out_end (uiout
, ui_out_type_tuple
);
414 make_cleanup_ui_out_list_begin_end (struct ui_out
*uiout
,
417 ui_out_begin (uiout
, ui_out_type_list
, id
);
418 return make_cleanup_ui_out_end (uiout
, ui_out_type_list
);
422 ui_out_field_int (struct ui_out
*uiout
,
430 verify_field (uiout
, &fldno
, &width
, &align
);
432 uo_field_int (uiout
, fldno
, width
, align
, fldname
, value
);
436 ui_out_field_fmt_int (struct ui_out
*uiout
,
438 enum ui_align input_align
,
446 verify_field (uiout
, &fldno
, &width
, &align
);
448 uo_field_int (uiout
, fldno
, input_width
, input_align
, fldname
, value
);
451 /* Documented in ui-out.h. */
454 ui_out_field_core_addr (struct ui_out
*uiout
,
456 struct gdbarch
*gdbarch
,
459 ui_out_field_string (uiout
, fldname
,
460 print_core_address (gdbarch
, address
));
464 ui_out_field_stream (struct ui_out
*uiout
,
466 struct ui_file
*stream
)
468 std::string buffer
= ui_file_as_string (stream
);
470 if (!buffer
.empty ())
471 ui_out_field_string (uiout
, fldname
, buffer
.c_str ());
473 ui_out_field_skip (uiout
, fldname
);
474 ui_file_rewind (stream
);
477 /* Used to omit a field. */
480 ui_out_field_skip (struct ui_out
*uiout
,
487 verify_field (uiout
, &fldno
, &width
, &align
);
489 uo_field_skip (uiout
, fldno
, width
, align
, fldname
);
493 ui_out_field_string (struct ui_out
*uiout
,
501 verify_field (uiout
, &fldno
, &width
, &align
);
503 uo_field_string (uiout
, fldno
, width
, align
, fldname
, string
);
508 ui_out_field_fmt (struct ui_out
*uiout
,
510 const char *format
, ...)
517 /* Will not align, but has to call anyway. */
518 verify_field (uiout
, &fldno
, &width
, &align
);
520 va_start (args
, format
);
522 uo_field_fmt (uiout
, fldno
, width
, align
, fldname
, format
, args
);
528 ui_out_spaces (struct ui_out
*uiout
, int numspaces
)
530 uo_spaces (uiout
, numspaces
);
534 ui_out_text (struct ui_out
*uiout
,
537 uo_text (uiout
, string
);
541 ui_out_message (struct ui_out
*uiout
, const char *format
, ...)
545 va_start (args
, format
);
546 uo_message (uiout
, format
, args
);
551 ui_out_wrap_hint (struct ui_out
*uiout
, const char *identstring
)
553 uo_wrap_hint (uiout
, identstring
);
557 ui_out_flush (struct ui_out
*uiout
)
563 ui_out_redirect (struct ui_out
*uiout
, struct ui_file
*outstream
)
565 return uo_redirect (uiout
, outstream
);
568 /* Test the flags against the mask given. */
570 ui_out_test_flags (struct ui_out
*uiout
, int mask
)
572 return (uiout
->flags
& mask
);
576 ui_out_is_mi_like_p (struct ui_out
*uiout
)
578 return uiout
->impl
->is_mi_like_p
;
581 /* Interface to the implementation functions. */
584 uo_table_begin (struct ui_out
*uiout
, int nbrofcols
,
588 if (!uiout
->impl
->table_begin
)
590 uiout
->impl
->table_begin (uiout
, nbrofcols
, nr_rows
, tblid
);
594 uo_table_body (struct ui_out
*uiout
)
596 if (!uiout
->impl
->table_body
)
598 uiout
->impl
->table_body (uiout
);
602 uo_table_end (struct ui_out
*uiout
)
604 if (!uiout
->impl
->table_end
)
606 uiout
->impl
->table_end (uiout
);
610 uo_table_header (struct ui_out
*uiout
, int width
, enum ui_align align
,
611 const std::string
&col_name
, const std::string
&col_hdr
)
613 if (!uiout
->impl
->table_header
)
615 uiout
->impl
->table_header (uiout
, width
, align
, col_name
, col_hdr
);
618 /* Clear the table associated with UIOUT. */
621 clear_table (struct ui_out
*uiout
)
623 uiout
->table
.id
.clear ();
624 clear_header_list (uiout
);
628 uo_begin (struct ui_out
*uiout
,
629 enum ui_out_type type
,
633 if (uiout
->impl
->begin
== NULL
)
635 uiout
->impl
->begin (uiout
, type
, level
, id
);
639 uo_end (struct ui_out
*uiout
,
640 enum ui_out_type type
,
643 if (uiout
->impl
->end
== NULL
)
645 uiout
->impl
->end (uiout
, type
, level
);
649 uo_field_int (struct ui_out
*uiout
, int fldno
, int width
, enum ui_align align
,
653 if (!uiout
->impl
->field_int
)
655 uiout
->impl
->field_int (uiout
, fldno
, width
, align
, fldname
, value
);
659 uo_field_skip (struct ui_out
*uiout
, int fldno
, int width
, enum ui_align align
,
662 if (!uiout
->impl
->field_skip
)
664 uiout
->impl
->field_skip (uiout
, fldno
, width
, align
, fldname
);
668 uo_field_string (struct ui_out
*uiout
, int fldno
, int width
,
673 if (!uiout
->impl
->field_string
)
675 uiout
->impl
->field_string (uiout
, fldno
, width
, align
, fldname
, string
);
679 uo_field_fmt (struct ui_out
*uiout
, int fldno
, int width
, enum ui_align align
,
684 if (!uiout
->impl
->field_fmt
)
686 uiout
->impl
->field_fmt (uiout
, fldno
, width
, align
, fldname
, format
, args
);
690 uo_spaces (struct ui_out
*uiout
, int numspaces
)
692 if (!uiout
->impl
->spaces
)
694 uiout
->impl
->spaces (uiout
, numspaces
);
698 uo_text (struct ui_out
*uiout
,
701 if (!uiout
->impl
->text
)
703 uiout
->impl
->text (uiout
, string
);
707 uo_message (struct ui_out
*uiout
,
711 if (!uiout
->impl
->message
)
713 uiout
->impl
->message (uiout
, format
, args
);
717 uo_wrap_hint (struct ui_out
*uiout
, const char *identstring
)
719 if (!uiout
->impl
->wrap_hint
)
721 uiout
->impl
->wrap_hint (uiout
, identstring
);
725 uo_flush (struct ui_out
*uiout
)
727 if (!uiout
->impl
->flush
)
729 uiout
->impl
->flush (uiout
);
733 uo_redirect (struct ui_out
*uiout
, struct ui_file
*outstream
)
735 if (!uiout
->impl
->redirect
)
737 return uiout
->impl
->redirect (uiout
, outstream
);
740 /* local functions */
742 /* List of column headers manipulation routines. */
745 clear_header_list (struct ui_out
*uiout
)
747 uiout
->table
.headers
.clear ();
748 uiout
->table
.headers_iterator
= uiout
->table
.headers
.end ();
752 append_header_to_list (struct ui_out
*uiout
,
754 enum ui_align alignment
,
755 const std::string
&col_name
,
756 const std::string
&col_hdr
)
758 std::unique_ptr
<ui_out_hdr
> temphdr(
759 new ui_out_hdr (uiout
->table
.headers
.size () + 1, width
,
760 alignment
, col_name
, col_hdr
));
762 uiout
->table
.headers
.push_back (std::move (temphdr
));
765 /* Extract the format information for the NEXT header and advance
766 the header pointer. Return 0 if there was no next header. */
769 get_next_header (struct ui_out
*uiout
,
772 enum ui_align
*alignment
,
773 const char **col_hdr
)
775 /* There may be no headers at all or we may have used all columns. */
776 if (uiout
->table
.headers_iterator
== uiout
->table
.headers
.end ())
779 ui_out_hdr
*hdr
= uiout
->table
.headers_iterator
->get ();
781 *colno
= hdr
->number ();
782 *width
= hdr
->min_width ();
783 *alignment
= hdr
->alignment ();
784 *col_hdr
= hdr
->header ().c_str ();
786 /* Advance the header pointer to the next entry. */
787 uiout
->table
.headers_iterator
++;
793 /* Verify that the field/tuple/list is correctly positioned. Return
794 the field number and corresponding alignment (if
795 available/applicable). */
798 verify_field (struct ui_out
*uiout
, int *fldno
, int *width
,
799 enum ui_align
*align
)
801 struct ui_out_level
*current
= current_level (uiout
);
804 if (uiout
->table
.flag
)
806 if (!uiout
->table
.body_flag
)
807 internal_error (__FILE__
, __LINE__
,
808 _("table_body missing; table fields must be \
809 specified after table_body and inside a list."));
810 /* NOTE: cagney/2001-12-08: There was a check here to ensure
811 that this code was only executed when uiout->level was
812 greater than zero. That no longer applies - this code is run
813 before each table row tuple is started and at that point the
817 current
->field_count
+= 1;
819 if (uiout
->table
.body_flag
820 && uiout
->table
.entry_level
== uiout
->level
821 && get_next_header (uiout
, fldno
, width
, align
, &text
))
823 if (*fldno
!= current
->field_count
)
824 internal_error (__FILE__
, __LINE__
,
825 _("ui-out internal error in handling headers."));
831 *fldno
= current
->field_count
;
836 /* Access to ui-out members data. */
839 ui_out_data (struct ui_out
*uiout
)
844 /* Access table field parameters. */
846 ui_out_query_field (struct ui_out
*uiout
, int colno
,
847 int *width
, int *alignment
, const char **col_name
)
849 if (!uiout
->table
.flag
)
852 /* Column numbers are 1-based, so convert to 0-based index. */
853 int index
= colno
- 1;
855 if (index
>= 0 && index
< uiout
->table
.headers
.size ())
857 ui_out_hdr
*hdr
= uiout
->table
.headers
[index
].get ();
859 gdb_assert (colno
== hdr
->number ());
861 *width
= hdr
->min_width ();
862 *alignment
= hdr
->alignment ();
863 *col_name
= hdr
->name ().c_str ();
871 /* Initialize private members at startup. */
874 ui_out_new (const struct ui_out_impl
*impl
, void *data
,
877 struct ui_out
*uiout
= new ui_out ();
878 std::unique_ptr
<ui_out_level
> current (new ui_out_level ());
882 uiout
->flags
= flags
;
883 uiout
->table
.flag
= 0;
884 uiout
->table
.body_flag
= 0;
887 /* Create uiout->level 0, the default level. */
888 current
->type
= ui_out_type_tuple
;
889 current
->field_count
= 0;
890 uiout
->levels
.push_back (std::move (current
));
892 uiout
->table
.headers_iterator
= uiout
->table
.headers
.end ();