diff options
Diffstat (limited to 'gdb/ui-out.c')
-rw-r--r-- | gdb/ui-out.c | 182 |
1 files changed, 180 insertions, 2 deletions
diff --git a/gdb/ui-out.c b/gdb/ui-out.c index e8fe44c..8cbaa4e 100644 --- a/gdb/ui-out.c +++ b/gdb/ui-out.c @@ -563,12 +563,190 @@ 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); + do_message (style, format, args); + 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 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); } |