X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fui-out.c;h=80845f4bcaa8d61ee3e7c202b645831a8b22e8da;hb=2365f8d70c50afbfd6be69a4076ea6e78fb5485d;hp=42cffbe7f741868a61a9cc76e55fdae9bbd01cfc;hpb=d7e747318f4d04af033f16325f9b6d74f67079ec;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ui-out.c b/gdb/ui-out.c index 42cffbe7f7..80845f4bca 100644 --- a/gdb/ui-out.c +++ b/gdb/ui-out.c @@ -1,6 +1,6 @@ /* Output generating routines for GDB. - Copyright (C) 1999-2017 Free Software Foundation, Inc. + Copyright (C) 1999-2019 Free Software Foundation, Inc. Contributed by Cygnus Solutions. Written by Fernando Nasser for Cygnus. @@ -24,11 +24,15 @@ #include "expression.h" /* For language.h */ #include "language.h" #include "ui-out.h" +#include "gdbsupport/format.h" +#include "cli/cli-style.h" +#include "diagnostics.h" #include #include #include -#include + +namespace { /* A header of a ui_out_table. */ @@ -91,6 +95,8 @@ class ui_out_hdr std::string m_header; }; +} // namespace + /* A level of nesting (either a list or a tuple) in a ui_out output. */ class ui_out_level @@ -396,22 +402,6 @@ ui_out::table_end () m_table_up = nullptr; } -static void -do_cleanup_table_end (void *data) -{ - ui_out *uiout = (ui_out *) data; - - uiout->table_end (); -} - -struct cleanup * -make_cleanup_ui_out_table_begin_end (ui_out *uiout, int nr_cols, int nr_rows, - const char *tblid) -{ - uiout->table_begin (nr_cols, nr_rows, tblid); - return make_cleanup (do_cleanup_table_end, uiout); -} - void ui_out::begin (ui_out_type type, const char *id) { @@ -450,52 +440,21 @@ ui_out::end (ui_out_type type) do_end (type); } -struct ui_out_end_cleanup_data -{ - struct ui_out *uiout; - enum ui_out_type type; -}; - -static void -do_cleanup_end (void *data) -{ - struct ui_out_end_cleanup_data *end_cleanup_data - = (struct ui_out_end_cleanup_data *) data; - - end_cleanup_data->uiout->end (end_cleanup_data->type); - xfree (end_cleanup_data); -} - -static struct cleanup * -make_cleanup_ui_out_end (struct ui_out *uiout, - enum ui_out_type type) +void +ui_out::field_signed (const char *fldname, LONGEST value) { - struct ui_out_end_cleanup_data *end_cleanup_data; - - end_cleanup_data = XNEW (struct ui_out_end_cleanup_data); - end_cleanup_data->uiout = uiout; - end_cleanup_data->type = type; - return make_cleanup (do_cleanup_end, end_cleanup_data); -} + int fldno; + int width; + ui_align align; -struct cleanup * -make_cleanup_ui_out_tuple_begin_end (struct ui_out *uiout, - const char *id) -{ - uiout->begin (ui_out_type_tuple, id); - return make_cleanup_ui_out_end (uiout, ui_out_type_tuple); -} + verify_field (&fldno, &width, &align); -struct cleanup * -make_cleanup_ui_out_list_begin_end (struct ui_out *uiout, - const char *id) -{ - uiout->begin (ui_out_type_list, id); - return make_cleanup_ui_out_end (uiout, ui_out_type_list); + do_field_signed (fldno, width, align, fldname, value); } void -ui_out::field_int (const char *fldname, int value) +ui_out::field_fmt_signed (int input_width, ui_align input_align, + const char *fldname, LONGEST value) { int fldno; int width; @@ -503,12 +462,13 @@ ui_out::field_int (const char *fldname, int value) verify_field (&fldno, &width, &align); - do_field_int (fldno, width, align, fldname, value); + do_field_signed (fldno, input_width, input_align, fldname, value); } +/* See ui-out.h. */ + void -ui_out::field_fmt_int (int input_width, ui_align input_align, - const char *fldname, int value) +ui_out::field_unsigned (const char *fldname, ULONGEST value) { int fldno; int width; @@ -516,7 +476,7 @@ ui_out::field_fmt_int (int input_width, ui_align input_align, verify_field (&fldno, &width, &align); - do_field_int (fldno, input_width, input_align, fldname, value); + do_field_unsigned (fldno, width, align, fldname, value); } /* Documented in ui-out.h. */ @@ -525,14 +485,16 @@ void ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch, CORE_ADDR address) { - field_string (fldname, print_core_address (gdbarch, address)); + field_string (fldname, print_core_address (gdbarch, address), + address_style.style ()); } void -ui_out::field_stream (const char *fldname, string_file &stream) +ui_out::field_stream (const char *fldname, string_file &stream, + const ui_file_style &style) { if (!stream.empty ()) - field_string (fldname, stream.c_str ()); + field_string (fldname, stream.c_str (), style); else field_skip (fldname); stream.clear (); @@ -553,7 +515,8 @@ ui_out::field_skip (const char *fldname) } void -ui_out::field_string (const char *fldname, const char *string) +ui_out::field_string (const char *fldname, const char *string, + const ui_file_style &style) { int fldno; int width; @@ -561,7 +524,13 @@ ui_out::field_string (const char *fldname, const char *string) verify_field (&fldno, &width, &align); - do_field_string (fldno, width, align, fldname, string); + do_field_string (fldno, width, align, fldname, string, style); +} + +void +ui_out::field_string (const char *fldname, const std::string &string) +{ + field_string (fldname, string.c_str ()); } /* VARARGS */ @@ -573,12 +542,29 @@ ui_out::field_fmt (const char *fldname, const char *format, ...) int width; ui_align align; - /* Will not align, but has to call anyway. */ verify_field (&fldno, &width, &align); va_start (args, format); - do_field_fmt (fldno, width, align, fldname, format, args); + do_field_fmt (fldno, width, align, fldname, ui_file_style (), format, args); + + va_end (args); +} + +void +ui_out::field_fmt (const char *fldname, const ui_file_style &style, + const char *format, ...) +{ + va_list args; + int fldno; + int width; + ui_align align; + + verify_field (&fldno, &width, &align); + + va_start (args, format); + + do_field_fmt (fldno, width, align, fldname, style, format, args); va_end (args); } @@ -596,12 +582,216 @@ ui_out::text (const char *string) } void -ui_out::message (const char *format, ...) +ui_out::call_do_message (const ui_file_style &style, const char *format, + ...) { va_list args; va_start (args, format); - do_message (format, args); + + /* Since call_do_message is only used as a helper of vmessage, silence the + warning here once instead of at all call sites in vmessage, if we were + to put a "format" attribute on call_do_message. */ + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL + do_message (style, format, args); + DIAGNOSTIC_POP + + va_end (args); +} + +void +ui_out::vmessage (const ui_file_style &in_style, const char *format, + va_list args) +{ + format_pieces fpieces (&format, true); + + ui_file_style style = in_style; + + for (auto &&piece : fpieces) + { + const char *current_substring = piece.string; + + gdb_assert (piece.n_int_args >= 0 && piece.n_int_args <= 2); + int intvals[2] = { 0, 0 }; + for (int i = 0; i < piece.n_int_args; ++i) + intvals[i] = va_arg (args, int); + + /* The only ones we support for now. */ + gdb_assert (piece.n_int_args == 0 + || piece.argclass == string_arg + || piece.argclass == int_arg + || piece.argclass == long_arg); + + switch (piece.argclass) + { + case string_arg: + { + const char *str = va_arg (args, const char *); + switch (piece.n_int_args) + { + case 0: + call_do_message (style, current_substring, str); + break; + case 1: + call_do_message (style, current_substring, intvals[0], str); + break; + case 2: + call_do_message (style, current_substring, + intvals[0], intvals[1], str); + break; + } + } + break; + case wide_string_arg: + gdb_assert_not_reached (_("wide_string_arg not supported in vmessage")); + break; + case wide_char_arg: + gdb_assert_not_reached (_("wide_char_arg not supported in vmessage")); + break; + case long_long_arg: + call_do_message (style, current_substring, va_arg (args, long long)); + break; + case int_arg: + { + int val = va_arg (args, int); + switch (piece.n_int_args) + { + case 0: + call_do_message (style, current_substring, val); + break; + case 1: + call_do_message (style, current_substring, intvals[0], val); + break; + case 2: + call_do_message (style, current_substring, + intvals[0], intvals[1], val); + break; + } + } + break; + case long_arg: + { + long val = va_arg (args, long); + switch (piece.n_int_args) + { + case 0: + call_do_message (style, current_substring, val); + break; + case 1: + call_do_message (style, current_substring, intvals[0], val); + break; + case 2: + call_do_message (style, current_substring, + intvals[0], intvals[1], val); + break; + } + } + break; + case size_t_arg: + { + size_t val = va_arg (args, size_t); + switch (piece.n_int_args) + { + case 0: + call_do_message (style, current_substring, val); + break; + case 1: + call_do_message (style, current_substring, intvals[0], val); + break; + case 2: + call_do_message (style, current_substring, + intvals[0], intvals[1], val); + break; + } + } + break; + case double_arg: + call_do_message (style, current_substring, va_arg (args, double)); + break; + case long_double_arg: + gdb_assert_not_reached (_("long_double_arg not supported in vmessage")); + break; + case dec32float_arg: + gdb_assert_not_reached (_("dec32float_arg not supported in vmessage")); + break; + case dec64float_arg: + gdb_assert_not_reached (_("dec64float_arg not supported in vmessage")); + break; + case dec128float_arg: + gdb_assert_not_reached (_("dec128float_arg not supported in vmessage")); + break; + case ptr_arg: + switch (current_substring[2]) + { + case 'F': + { + gdb_assert (!test_flags (disallow_ui_out_field)); + base_field_s *bf = va_arg (args, base_field_s *); + switch (bf->kind) + { + case field_kind::SIGNED: + { + auto *f = (signed_field_s *) bf; + field_signed (f->name, f->val); + } + break; + case field_kind::STRING: + { + auto *f = (string_field_s *) bf; + field_string (f->name, f->str); + } + break; + } + } + break; + case 's': + { + styled_string_s *ss = va_arg (args, styled_string_s *); + call_do_message (ss->style, "%s", ss->str); + } + break; + case '[': + style = *va_arg (args, const ui_file_style *); + break; + case ']': + { + void *arg = va_arg (args, void *); + gdb_assert (arg == nullptr); + + style = {}; + } + break; + default: + call_do_message (style, current_substring, va_arg (args, void *)); + break; + } + break; + case literal_piece: + /* Print a portion of the format string that has no + directives. Note that this will not include any ordinary + %-specs, but it might include "%%". That is why we use + call_do_message here. Also, we pass a dummy argument + because some platforms have modified GCC to include + -Wformat-security by default, which will warn here if + there is no argument. */ + call_do_message (style, current_substring, 0); + break; + default: + internal_error (__FILE__, __LINE__, + _("failed internal consistency check")); + } + } +} + +void +ui_out::message (const char *format, ...) +{ + va_list args; + va_start (args, format); + + vmessage (ui_file_style (), format, args); + va_end (args); } @@ -631,7 +821,7 @@ ui_out::test_flags (ui_out_flags mask) } bool -ui_out::is_mi_like_p () +ui_out::is_mi_like_p () const { return do_is_mi_like_p (); }