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 */
31 /* table header structures */
37 enum ui_align alignment
;
40 struct ui_out_hdr
*next
;
45 /* Count each field; the first element is for non-list fields. */
47 /* The type of this level. */
48 enum ui_out_type type
;
52 /* Tables are special. Maintain a separate structure that tracks
53 their state. At present an output can only contain a single table
54 but that restriction might eventually be lifted. */
58 /* If on, a table is being generated. */
61 /* If on, the body of a table is being generated. If off, the table
62 header is being generated. */
65 /* The level at which each entry of the table is to be found. A row
66 (a tuple) is made up of entries. Consequently ENTRY_LEVEL is one
67 above that of the table. */
70 /* Number of table columns (as specified in the table_begin call). */
73 /* String identifying the table (as specified in the table_begin
77 /* Points to the first table header (if any). */
78 struct ui_out_hdr
*header_first
;
80 /* Points to the last table header (if any). */
81 struct ui_out_hdr
*header_last
;
83 /* Points to header of NEXT column to format. */
84 struct ui_out_hdr
*header_next
;
89 /* The ui_out structure */
94 /* Specific implementation of ui-out. */
95 const struct ui_out_impl
*impl
;
101 /* Vector to store and track the ui-out levels. */
102 std::vector
<std::unique_ptr
<ui_out_level
>> levels
;
104 /* A table, if any. At present only a single table is supported. */
105 struct ui_out_table table
;
108 /* The current (inner most) level. */
109 static struct ui_out_level
*
110 current_level (struct ui_out
*uiout
)
112 return uiout
->levels
[uiout
->level
].get ();
115 /* Create a new level, of TYPE. Return the new level's index. */
117 push_level (struct ui_out
*uiout
,
118 enum ui_out_type type
)
120 std::unique_ptr
<ui_out_level
> current (new ui_out_level ());
122 current
->field_count
= 0;
123 current
->type
= type
;
126 uiout
->levels
.push_back (std::move (current
));
131 /* Discard the current level, return the discarded level's index.
132 TYPE is the type of the level being discarded. */
134 pop_level (struct ui_out
*uiout
,
135 enum ui_out_type type
)
137 /* We had better not underflow the buffer. */
138 gdb_assert (uiout
->level
> 0);
139 gdb_assert (current_level (uiout
)->type
== type
);
141 uiout
->levels
.pop_back ();
144 return uiout
->level
+ 1;
147 /* These are the interfaces to implementation functions. */
149 static void uo_table_begin (struct ui_out
*uiout
, int nbrofcols
,
150 int nr_rows
, const char *tblid
);
151 static void uo_table_body (struct ui_out
*uiout
);
152 static void uo_table_end (struct ui_out
*uiout
);
153 static void uo_table_header (struct ui_out
*uiout
, int width
,
154 enum ui_align align
, const char *col_name
,
156 static void uo_begin (struct ui_out
*uiout
,
157 enum ui_out_type type
,
158 int level
, const char *id
);
159 static void uo_end (struct ui_out
*uiout
,
160 enum ui_out_type type
,
162 static void uo_field_int (struct ui_out
*uiout
, int fldno
, int width
,
163 enum ui_align align
, const char *fldname
, int value
);
164 static void uo_field_skip (struct ui_out
*uiout
, int fldno
, int width
,
165 enum ui_align align
, const char *fldname
);
166 static void uo_field_fmt (struct ui_out
*uiout
, int fldno
, int width
,
167 enum ui_align align
, const char *fldname
,
168 const char *format
, va_list args
)
169 ATTRIBUTE_PRINTF (6, 0);
170 static void uo_spaces (struct ui_out
*uiout
, int numspaces
);
171 static void uo_text (struct ui_out
*uiout
, const char *string
);
172 static void uo_message (struct ui_out
*uiout
,
173 const char *format
, va_list args
)
174 ATTRIBUTE_PRINTF (2, 0);
175 static void uo_wrap_hint (struct ui_out
*uiout
, const char *identstring
);
176 static void uo_flush (struct ui_out
*uiout
);
177 static int uo_redirect (struct ui_out
*uiout
, struct ui_file
*outstream
);
179 /* Prototypes for local functions */
181 static void append_header_to_list (struct ui_out
*uiout
, int width
,
182 enum ui_align alignment
, const char *col_name
,
184 static int get_next_header (struct ui_out
*uiout
, int *colno
, int *width
,
185 enum ui_align
*alignment
, char **colhdr
);
186 static void clear_header_list (struct ui_out
*uiout
);
187 static void clear_table (struct ui_out
*uiout
);
188 static void verify_field (struct ui_out
*uiout
, int *fldno
, int *width
,
189 enum ui_align
*align
);
191 /* exported functions (ui_out API) */
193 /* Mark beginning of a table. */
196 ui_out_table_begin (struct ui_out
*uiout
, int nbrofcols
,
200 if (uiout
->table
.flag
)
201 internal_error (__FILE__
, __LINE__
,
202 _("tables cannot be nested; table_begin found before \
203 previous table_end."));
205 uiout
->table
.flag
= 1;
206 uiout
->table
.body_flag
= 0;
207 uiout
->table
.entry_level
= uiout
->level
+ 1;
208 uiout
->table
.columns
= nbrofcols
;
210 uiout
->table
.id
= xstrdup (tblid
);
212 uiout
->table
.id
= NULL
;
213 clear_header_list (uiout
);
215 uo_table_begin (uiout
, nbrofcols
, nr_rows
, uiout
->table
.id
);
219 ui_out_table_body (struct ui_out
*uiout
)
221 if (!uiout
->table
.flag
)
222 internal_error (__FILE__
, __LINE__
,
223 _("table_body outside a table is not valid; it must be \
224 after a table_begin and before a table_end."));
225 if (uiout
->table
.body_flag
)
226 internal_error (__FILE__
, __LINE__
,
227 _("extra table_body call not allowed; there must be \
228 only one table_body after a table_begin and before a table_end."));
229 if (uiout
->table
.header_next
->colno
!= uiout
->table
.columns
)
230 internal_error (__FILE__
, __LINE__
,
231 _("number of headers differ from number of table \
234 uiout
->table
.body_flag
= 1;
235 uiout
->table
.header_next
= uiout
->table
.header_first
;
237 uo_table_body (uiout
);
241 ui_out_table_end (struct ui_out
*uiout
)
243 if (!uiout
->table
.flag
)
244 internal_error (__FILE__
, __LINE__
,
245 _("misplaced table_end or missing table_begin."));
247 uiout
->table
.entry_level
= 0;
248 uiout
->table
.body_flag
= 0;
249 uiout
->table
.flag
= 0;
251 uo_table_end (uiout
);
256 ui_out_table_header (struct ui_out
*uiout
, int width
, enum ui_align alignment
,
257 const char *col_name
,
260 if (!uiout
->table
.flag
|| uiout
->table
.body_flag
)
261 internal_error (__FILE__
, __LINE__
,
262 _("table header must be specified after table_begin \
263 and before table_body."));
265 append_header_to_list (uiout
, width
, alignment
, col_name
, colhdr
);
267 uo_table_header (uiout
, width
, alignment
, col_name
, colhdr
);
271 do_cleanup_table_end (void *data
)
273 struct ui_out
*ui_out
= (struct ui_out
*) data
;
275 ui_out_table_end (ui_out
);
279 make_cleanup_ui_out_table_begin_end (struct ui_out
*ui_out
, int nr_cols
,
280 int nr_rows
, const char *tblid
)
282 ui_out_table_begin (ui_out
, nr_cols
, nr_rows
, tblid
);
283 return make_cleanup (do_cleanup_table_end
, ui_out
);
287 ui_out_begin (struct ui_out
*uiout
,
288 enum ui_out_type type
,
293 if (uiout
->table
.flag
&& !uiout
->table
.body_flag
)
294 internal_error (__FILE__
, __LINE__
,
295 _("table header or table_body expected; lists must be \
296 specified after table_body."));
298 /* Be careful to verify the ``field'' before the new tuple/list is
299 pushed onto the stack. That way the containing list/table/row is
300 verified and not the newly created tuple/list. This verification
301 is needed (at least) for the case where a table row entry
302 contains either a tuple/list. For that case bookkeeping such as
303 updating the column count or advancing to the next heading still
304 needs to be performed. */
310 verify_field (uiout
, &fldno
, &width
, &align
);
313 new_level
= push_level (uiout
, type
);
315 /* If the push puts us at the same level as a table row entry, we've
316 got a new table row. Put the header pointer back to the start. */
317 if (uiout
->table
.body_flag
318 && uiout
->table
.entry_level
== new_level
)
319 uiout
->table
.header_next
= uiout
->table
.header_first
;
321 uo_begin (uiout
, type
, new_level
, id
);
325 ui_out_end (struct ui_out
*uiout
,
326 enum ui_out_type type
)
328 int old_level
= pop_level (uiout
, type
);
330 uo_end (uiout
, type
, old_level
);
333 struct ui_out_end_cleanup_data
335 struct ui_out
*uiout
;
336 enum ui_out_type type
;
340 do_cleanup_end (void *data
)
342 struct ui_out_end_cleanup_data
*end_cleanup_data
343 = (struct ui_out_end_cleanup_data
*) data
;
345 ui_out_end (end_cleanup_data
->uiout
, end_cleanup_data
->type
);
346 xfree (end_cleanup_data
);
349 static struct cleanup
*
350 make_cleanup_ui_out_end (struct ui_out
*uiout
,
351 enum ui_out_type type
)
353 struct ui_out_end_cleanup_data
*end_cleanup_data
;
355 end_cleanup_data
= XNEW (struct ui_out_end_cleanup_data
);
356 end_cleanup_data
->uiout
= uiout
;
357 end_cleanup_data
->type
= type
;
358 return make_cleanup (do_cleanup_end
, end_cleanup_data
);
362 make_cleanup_ui_out_tuple_begin_end (struct ui_out
*uiout
,
365 ui_out_begin (uiout
, ui_out_type_tuple
, id
);
366 return make_cleanup_ui_out_end (uiout
, ui_out_type_tuple
);
370 make_cleanup_ui_out_list_begin_end (struct ui_out
*uiout
,
373 ui_out_begin (uiout
, ui_out_type_list
, id
);
374 return make_cleanup_ui_out_end (uiout
, ui_out_type_list
);
378 ui_out_field_int (struct ui_out
*uiout
,
386 verify_field (uiout
, &fldno
, &width
, &align
);
388 uo_field_int (uiout
, fldno
, width
, align
, fldname
, value
);
392 ui_out_field_fmt_int (struct ui_out
*uiout
,
394 enum ui_align input_align
,
402 verify_field (uiout
, &fldno
, &width
, &align
);
404 uo_field_int (uiout
, fldno
, input_width
, input_align
, fldname
, value
);
407 /* Documented in ui-out.h. */
410 ui_out_field_core_addr (struct ui_out
*uiout
,
412 struct gdbarch
*gdbarch
,
415 ui_out_field_string (uiout
, fldname
,
416 print_core_address (gdbarch
, address
));
420 ui_out_field_stream (struct ui_out
*uiout
,
422 struct ui_file
*stream
)
424 std::string buffer
= ui_file_as_string (stream
);
426 if (!buffer
.empty ())
427 ui_out_field_string (uiout
, fldname
, buffer
.c_str ());
429 ui_out_field_skip (uiout
, fldname
);
430 ui_file_rewind (stream
);
433 /* Used to omit a field. */
436 ui_out_field_skip (struct ui_out
*uiout
,
443 verify_field (uiout
, &fldno
, &width
, &align
);
445 uo_field_skip (uiout
, fldno
, width
, align
, fldname
);
449 ui_out_field_string (struct ui_out
*uiout
,
457 verify_field (uiout
, &fldno
, &width
, &align
);
459 uo_field_string (uiout
, fldno
, width
, align
, fldname
, string
);
464 ui_out_field_fmt (struct ui_out
*uiout
,
466 const char *format
, ...)
473 /* Will not align, but has to call anyway. */
474 verify_field (uiout
, &fldno
, &width
, &align
);
476 va_start (args
, format
);
478 uo_field_fmt (uiout
, fldno
, width
, align
, fldname
, format
, args
);
484 ui_out_spaces (struct ui_out
*uiout
, int numspaces
)
486 uo_spaces (uiout
, numspaces
);
490 ui_out_text (struct ui_out
*uiout
,
493 uo_text (uiout
, string
);
497 ui_out_message (struct ui_out
*uiout
, const char *format
, ...)
501 va_start (args
, format
);
502 uo_message (uiout
, format
, args
);
507 ui_out_wrap_hint (struct ui_out
*uiout
, const char *identstring
)
509 uo_wrap_hint (uiout
, identstring
);
513 ui_out_flush (struct ui_out
*uiout
)
519 ui_out_redirect (struct ui_out
*uiout
, struct ui_file
*outstream
)
521 return uo_redirect (uiout
, outstream
);
524 /* Test the flags against the mask given. */
526 ui_out_test_flags (struct ui_out
*uiout
, int mask
)
528 return (uiout
->flags
& mask
);
532 ui_out_is_mi_like_p (struct ui_out
*uiout
)
534 return uiout
->impl
->is_mi_like_p
;
537 /* Interface to the implementation functions. */
540 uo_table_begin (struct ui_out
*uiout
, int nbrofcols
,
544 if (!uiout
->impl
->table_begin
)
546 uiout
->impl
->table_begin (uiout
, nbrofcols
, nr_rows
, tblid
);
550 uo_table_body (struct ui_out
*uiout
)
552 if (!uiout
->impl
->table_body
)
554 uiout
->impl
->table_body (uiout
);
558 uo_table_end (struct ui_out
*uiout
)
560 if (!uiout
->impl
->table_end
)
562 uiout
->impl
->table_end (uiout
);
566 uo_table_header (struct ui_out
*uiout
, int width
, enum ui_align align
,
567 const char *col_name
,
570 if (!uiout
->impl
->table_header
)
572 uiout
->impl
->table_header (uiout
, width
, align
, col_name
, colhdr
);
575 /* Clear the table associated with UIOUT. */
578 clear_table (struct ui_out
*uiout
)
580 xfree (uiout
->table
.id
);
581 uiout
->table
.id
= NULL
;
582 clear_header_list (uiout
);
586 uo_begin (struct ui_out
*uiout
,
587 enum ui_out_type type
,
591 if (uiout
->impl
->begin
== NULL
)
593 uiout
->impl
->begin (uiout
, type
, level
, id
);
597 uo_end (struct ui_out
*uiout
,
598 enum ui_out_type type
,
601 if (uiout
->impl
->end
== NULL
)
603 uiout
->impl
->end (uiout
, type
, level
);
607 uo_field_int (struct ui_out
*uiout
, int fldno
, int width
, enum ui_align align
,
611 if (!uiout
->impl
->field_int
)
613 uiout
->impl
->field_int (uiout
, fldno
, width
, align
, fldname
, value
);
617 uo_field_skip (struct ui_out
*uiout
, int fldno
, int width
, enum ui_align align
,
620 if (!uiout
->impl
->field_skip
)
622 uiout
->impl
->field_skip (uiout
, fldno
, width
, align
, fldname
);
626 uo_field_string (struct ui_out
*uiout
, int fldno
, int width
,
631 if (!uiout
->impl
->field_string
)
633 uiout
->impl
->field_string (uiout
, fldno
, width
, align
, fldname
, string
);
637 uo_field_fmt (struct ui_out
*uiout
, int fldno
, int width
, enum ui_align align
,
642 if (!uiout
->impl
->field_fmt
)
644 uiout
->impl
->field_fmt (uiout
, fldno
, width
, align
, fldname
, format
, args
);
648 uo_spaces (struct ui_out
*uiout
, int numspaces
)
650 if (!uiout
->impl
->spaces
)
652 uiout
->impl
->spaces (uiout
, numspaces
);
656 uo_text (struct ui_out
*uiout
,
659 if (!uiout
->impl
->text
)
661 uiout
->impl
->text (uiout
, string
);
665 uo_message (struct ui_out
*uiout
,
669 if (!uiout
->impl
->message
)
671 uiout
->impl
->message (uiout
, format
, args
);
675 uo_wrap_hint (struct ui_out
*uiout
, const char *identstring
)
677 if (!uiout
->impl
->wrap_hint
)
679 uiout
->impl
->wrap_hint (uiout
, identstring
);
683 uo_flush (struct ui_out
*uiout
)
685 if (!uiout
->impl
->flush
)
687 uiout
->impl
->flush (uiout
);
691 uo_redirect (struct ui_out
*uiout
, struct ui_file
*outstream
)
693 if (!uiout
->impl
->redirect
)
695 return uiout
->impl
->redirect (uiout
, outstream
);
698 /* local functions */
700 /* List of column headers manipulation routines. */
703 clear_header_list (struct ui_out
*uiout
)
705 while (uiout
->table
.header_first
!= NULL
)
707 uiout
->table
.header_next
= uiout
->table
.header_first
;
708 uiout
->table
.header_first
= uiout
->table
.header_first
->next
;
709 xfree (uiout
->table
.header_next
->colhdr
);
710 xfree (uiout
->table
.header_next
->col_name
);
711 delete uiout
->table
.header_next
;
714 gdb_assert (uiout
->table
.header_first
== NULL
);
715 uiout
->table
.header_last
= NULL
;
716 uiout
->table
.header_next
= NULL
;
720 append_header_to_list (struct ui_out
*uiout
,
722 enum ui_align alignment
,
723 const char *col_name
,
726 struct ui_out_hdr
*temphdr
;
728 temphdr
= new ui_out_hdr ();
729 temphdr
->width
= width
;
730 temphdr
->alignment
= alignment
;
731 /* We have to copy the column title as the original may be an
734 temphdr
->colhdr
= xstrdup (colhdr
);
736 temphdr
->colhdr
= NULL
;
738 if (col_name
!= NULL
)
739 temphdr
->col_name
= xstrdup (col_name
);
740 else if (colhdr
!= NULL
)
741 temphdr
->col_name
= xstrdup (colhdr
);
743 temphdr
->col_name
= NULL
;
745 temphdr
->next
= NULL
;
746 if (uiout
->table
.header_first
== NULL
)
749 uiout
->table
.header_first
= temphdr
;
750 uiout
->table
.header_last
= temphdr
;
754 temphdr
->colno
= uiout
->table
.header_last
->colno
+ 1;
755 uiout
->table
.header_last
->next
= temphdr
;
756 uiout
->table
.header_last
= temphdr
;
758 uiout
->table
.header_next
= uiout
->table
.header_last
;
761 /* Extract the format information for the NEXT header and advance
762 the header pointer. Return 0 if there was no next header. */
765 get_next_header (struct ui_out
*uiout
,
768 enum ui_align
*alignment
,
771 /* There may be no headers at all or we may have used all columns. */
772 if (uiout
->table
.header_next
== NULL
)
774 *colno
= uiout
->table
.header_next
->colno
;
775 *width
= uiout
->table
.header_next
->width
;
776 *alignment
= uiout
->table
.header_next
->alignment
;
777 *colhdr
= uiout
->table
.header_next
->colhdr
;
778 /* Advance the header pointer to the next entry. */
779 uiout
->table
.header_next
= uiout
->table
.header_next
->next
;
784 /* Verify that the field/tuple/list is correctly positioned. Return
785 the field number and corresponding alignment (if
786 available/applicable). */
789 verify_field (struct ui_out
*uiout
, int *fldno
, int *width
,
790 enum ui_align
*align
)
792 struct ui_out_level
*current
= current_level (uiout
);
795 if (uiout
->table
.flag
)
797 if (!uiout
->table
.body_flag
)
798 internal_error (__FILE__
, __LINE__
,
799 _("table_body missing; table fields must be \
800 specified after table_body and inside a list."));
801 /* NOTE: cagney/2001-12-08: There was a check here to ensure
802 that this code was only executed when uiout->level was
803 greater than zero. That no longer applies - this code is run
804 before each table row tuple is started and at that point the
808 current
->field_count
+= 1;
810 if (uiout
->table
.body_flag
811 && uiout
->table
.entry_level
== uiout
->level
812 && get_next_header (uiout
, fldno
, width
, align
, &text
))
814 if (*fldno
!= current
->field_count
)
815 internal_error (__FILE__
, __LINE__
,
816 _("ui-out internal error in handling headers."));
822 *fldno
= current
->field_count
;
827 /* Access to ui-out members data. */
830 ui_out_data (struct ui_out
*uiout
)
835 /* Access table field parameters. */
837 ui_out_query_field (struct ui_out
*uiout
, int colno
,
838 int *width
, int *alignment
, char **col_name
)
840 struct ui_out_hdr
*hdr
;
842 if (!uiout
->table
.flag
)
845 for (hdr
= uiout
->table
.header_first
; hdr
; hdr
= hdr
->next
)
846 if (hdr
->colno
== colno
)
849 *alignment
= hdr
->alignment
;
850 *col_name
= hdr
->col_name
;
857 /* Initialize private members at startup. */
860 ui_out_new (const struct ui_out_impl
*impl
, void *data
,
863 struct ui_out
*uiout
= new ui_out ();
864 std::unique_ptr
<ui_out_level
> current (new ui_out_level ());
868 uiout
->flags
= flags
;
869 uiout
->table
.flag
= 0;
870 uiout
->table
.body_flag
= 0;
873 /* Create uiout->level 0, the default level. */
874 current
->type
= ui_out_type_tuple
;
875 current
->field_count
= 0;
876 uiout
->levels
.push_back (std::move (current
));
878 uiout
->table
.id
= NULL
;
879 uiout
->table
.header_first
= NULL
;
880 uiout
->table
.header_last
= NULL
;
881 uiout
->table
.header_next
= NULL
;
This page took 0.054766 seconds and 5 git commands to generate.