/* Language independent support for printing types for GDB, the GNU debugger.
- Copyright (C) 1986-2020 Free Software Foundation, Inc.
+ Copyright (C) 1986-2022 Free Software Foundation, Inc.
This file is part of GDB.
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
-#include "gdb_obstack.h"
+#include "gdbsupport/gdb_obstack.h"
#include "bfd.h" /* Binary File Description */
#include "symtab.h"
#include "gdbtypes.h"
1, /* print_methods */
1, /* print_typedefs */
0, /* print_offsets */
+ 0, /* print_in_hex */
0, /* print_nested_type_limit */
NULL, /* local_typedefs */
NULL, /* global_table */
1, /* print_methods */
1, /* print_typedefs */
0, /* print_offsets */
+ 0, /* print_in_hex */
0, /* print_nested_type_limit */
NULL, /* local_typedefs */
NULL, /* global_table */
/* See typeprint.h. */
-const int print_offset_data::indentation = 23;
+const int print_offset_data::indentation = 27;
+/* See typeprint.h. */
+
+print_offset_data::print_offset_data (const struct type_print_options *flags)
+{
+ if (flags != nullptr)
+ print_in_hex = flags->print_in_hex;
+}
/* See typeprint.h. */
unsigned int hole_bit = hole % TARGET_CHAR_BIT;
if (hole_bit > 0)
- fprintf_filtered (stream, "/* XXX %2u-bit %s */\n", hole_bit,
- for_what);
+ {
+ fprintf_styled (stream, highlight_style.style (),
+ "/* XXX %2u-bit %-7s */", hole_bit, for_what);
+ gdb_puts ("\n", stream);
+ }
if (hole_byte > 0)
- fprintf_filtered (stream, "/* XXX %2u-byte %s */\n", hole_byte,
- for_what);
+ {
+ fprintf_styled (stream, highlight_style.style (),
+ "/* XXX %2u-byte %-7s */", hole_byte, for_what);
+ gdb_puts ("\n", stream);
+ }
}
}
{
if (field_is_static (&type->field (field_idx)))
{
- print_spaces_filtered (indentation, stream);
+ print_spaces (indentation, stream);
return;
}
{
/* Since union fields don't have the concept of offsets, we just
print their sizes. */
- fprintf_filtered (stream, "/* %4s */",
- pulongest (TYPE_LENGTH (ftype)));
+ gdb_printf (stream, "/* %6s */",
+ (print_in_hex ?
+ hex_string_custom (TYPE_LENGTH (ftype), 4) :
+ pulongest (TYPE_LENGTH (ftype))));
return;
}
- unsigned int bitpos = TYPE_FIELD_BITPOS (type, field_idx);
+ unsigned int bitpos = type->field (field_idx).loc_bitpos ();
unsigned int fieldsize_byte = TYPE_LENGTH (ftype);
unsigned int fieldsize_bit = fieldsize_byte * TARGET_CHAR_BIT;
unsigned real_bitpos = bitpos + offset_bitpos;
- fprintf_filtered (stream, "/* %4u:%2u", real_bitpos / TARGET_CHAR_BIT,
- real_bitpos % TARGET_CHAR_BIT);
+ gdb_printf (stream,
+ (print_in_hex ? "/* 0x%04x: 0x%x" : "/* %6u:%2u "),
+ real_bitpos / TARGET_CHAR_BIT,
+ real_bitpos % TARGET_CHAR_BIT);
}
else
{
/* The position of the field, relative to the beginning of the
struct. */
- fprintf_filtered (stream, "/* %4u",
- (bitpos + offset_bitpos) / TARGET_CHAR_BIT);
+ gdb_printf (stream, (print_in_hex ? "/* 0x%04x" : "/* %6u"),
+ (bitpos + offset_bitpos) / TARGET_CHAR_BIT);
- fprintf_filtered (stream, " ");
+ gdb_printf (stream, " ");
}
- fprintf_filtered (stream, " | %4u */", fieldsize_byte);
+ gdb_printf (stream, (print_in_hex ? " | 0x%04x */" : " | %6u */"),
+ fieldsize_byte);
end_bitpos = bitpos + fieldsize_bit;
}
unsigned int bitpos = TYPE_LENGTH (type) * TARGET_CHAR_BIT;
maybe_print_hole (stream, bitpos, "padding");
- fputs_filtered ("\n", stream);
- print_spaces_filtered (level + 4 + print_offset_data::indentation, stream);
- fprintf_filtered (stream, "/* total size (bytes): %4s */\n",
- pulongest (TYPE_LENGTH (type)));
+ gdb_puts ("\n", stream);
+ print_spaces (level + 4 + print_offset_data::indentation, stream);
+ gdb_printf (stream, "/* total size (bytes): %4s */\n",
+ pulongest (TYPE_LENGTH (type)));
}
\f
hash_typedef_field (const void *p)
{
const struct decl_field *tf = (const struct decl_field *) p;
- struct type *t = check_typedef (tf->type);
- return htab_hash_string (TYPE_SAFE_NAME (t));
+ return htab_hash_string (TYPE_SAFE_NAME (tf->type));
}
/* An equality function for a typedef field. */
void **slot;
/* We only want type-valued template parameters in the hash. */
- if (SYMBOL_CLASS (TYPE_TEMPLATE_ARGUMENT (t, i)) != LOC_TYPEDEF)
+ if (TYPE_TEMPLATE_ARGUMENT (t, i)->aclass () != LOC_TYPEDEF)
continue;
tf = XOBNEW (&m_storage, struct decl_field);
tf->name = TYPE_TEMPLATE_ARGUMENT (t, i)->linkage_name ();
- tf->type = SYMBOL_TYPE (TYPE_TEMPLATE_ARGUMENT (t, i));
+ tf->type = TYPE_TEMPLATE_ARGUMENT (t, i)->type ();
slot = htab_find_slot (m_table.get (), tf, INSERT);
if (*slot == NULL)
type_print (struct type *type, const char *varstring, struct ui_file *stream,
int show)
{
- LA_PRINT_TYPE (type, varstring, stream, show, 0, &default_ptype_flags);
+ current_language->print_type (type, varstring, stream, show, 0,
+ &default_ptype_flags);
}
/* Print TYPE to a string, returning it. The caller is responsible for
string_file stb;
type_print (type, "", &stb, -1);
- return std::move (stb.string ());
+ return stb.release ();
}
catch (const gdb_exception &except)
{
}
break;
}
+ case 'x':
+ flags.print_in_hex = 1;
+ break;
+ case 'd':
+ flags.print_in_hex = 0;
+ break;
default:
error (_("unrecognized flag '%c'"), *exp);
}
"whatis" prints the type of the expression without stripping
any typedef level. "ptype" always strips all levels of
typedefs. */
- if (show == -1 && expr->elts[0].opcode == OP_TYPE)
+ val = evaluate_type (expr.get ());
+ type = value_type (val);
+
+ if (show == -1 && expr->first_opcode () == OP_TYPE)
{
/* The user expression names a type directly. */
- type = expr->elts[1].type;
/* If this is a typedef, then find its immediate target.
Use check_typedef to resolve stubs, but ignore its result
value to fetch the dynamic type from. */
val = NULL;
}
- else
- {
- /* The user expression names a type indirectly by naming an
- object or expression of that type. Find that
- indirectly-named type. */
- val = evaluate_type (expr.get ());
- type = value_type (val);
- }
}
else
{
get_user_print_options (&opts);
if (val != NULL && opts.objectprint)
{
- if (((type->code () == TYPE_CODE_PTR) || TYPE_IS_REFERENCE (type))
+ if (type->is_pointer_or_reference ()
&& (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_STRUCT))
real_type = value_rtti_indirect_type (val, &full, &top, &using_enc);
else if (type->code () == TYPE_CODE_STRUCT)
if (flags.print_offsets
&& (type->code () == TYPE_CODE_STRUCT
|| type->code () == TYPE_CODE_UNION))
- fprintf_filtered (gdb_stdout, "/* offset | size */ ");
+ gdb_printf ("/* offset | size */ ");
- printf_filtered ("type = ");
+ gdb_printf ("type = ");
std::unique_ptr<typedef_hash_table> table_holder;
std::unique_ptr<ext_lang_type_printers> printer_holder;
if (real_type)
{
- printf_filtered ("/* real type = ");
+ gdb_printf ("/* real type = ");
type_print (real_type, "", gdb_stdout, -1);
if (! full)
- printf_filtered (" (incomplete object)");
- printf_filtered (" */\n");
+ gdb_printf (" (incomplete object)");
+ gdb_printf (" */\n");
}
- LA_PRINT_TYPE (type, "", gdb_stdout, show, 0, &flags);
- printf_filtered ("\n");
+ current_language->print_type (type, "", gdb_stdout, show, 0, &flags);
+ gdb_printf ("\n");
}
static void
len = type->num_fields ();
for (i = 0; i < len; i++)
{
- if (TYPE_FIELD_ENUMVAL (type, i) == val)
+ if (type->field (i).loc_enumval () == val)
{
break;
}
}
if (i < len)
{
- fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+ gdb_puts (type->field (i).name (), stream);
}
else
{
break;
case TYPE_CODE_CHAR:
- LA_PRINT_CHAR ((unsigned char) val, type, stream);
+ current_language->printchar ((unsigned char) val, type, stream);
break;
case TYPE_CODE_BOOL:
- fprintf_filtered (stream, val ? "TRUE" : "FALSE");
+ gdb_printf (stream, val ? "TRUE" : "FALSE");
break;
case TYPE_CODE_RANGE:
{
std::string small_img = type->fixed_point_scaling_factor ().str ();
- fprintf_filtered (stream, "%s-byte fixed point (small = %s)",
- pulongest (TYPE_LENGTH (type)), small_img.c_str ());
+ gdb_printf (stream, "%s-byte fixed point (small = %s)",
+ pulongest (TYPE_LENGTH (type)), small_img.c_str ());
}
/* Dump details of a type specified either directly or indirectly.
void
maintenance_print_type (const char *type_name, int from_tty)
{
- struct value *val;
- struct type *type;
-
if (type_name != NULL)
{
expression_up expr = parse_expression (type_name);
- if (expr->elts[0].opcode == OP_TYPE)
- {
- /* The user expression names a type directly, just use that type. */
- type = expr->elts[1].type;
- }
- else
- {
- /* The user expression may name a type indirectly by naming an
- object of that type. Find that indirectly named type. */
- val = evaluate_type (expr.get ());
- type = value_type (val);
- }
- if (type != NULL)
- {
- recursive_dump_type (type, 0);
- }
+ struct value *val = evaluate_type (expr.get ());
+ struct type *type = value_type (val);
+
+ if (type != nullptr)
+ recursive_dump_type (type, 0);
}
}
\f
show_print_type_methods (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("Printing of methods defined in a class in %s\n"),
- value);
+ gdb_printf (file, _("Printing of methods defined in a class in %s\n"),
+ value);
}
static bool print_typedefs = true;
show_print_type_typedefs (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("Printing of typedefs defined in a class in %s\n"),
- value);
+ gdb_printf (file, _("Printing of typedefs defined in a class in %s\n"),
+ value);
}
/* Limit on the number of nested type definitions to print or -1 to print
{
if (*value == '0')
{
- fprintf_filtered (file,
- _("Will not print nested types defined in a class\n"));
+ gdb_printf (file,
+ _("Will not print nested types defined in a class\n"));
}
else
{
- fprintf_filtered (file,
- _("Will print %s nested types defined in a class\n"),
- value);
+ gdb_printf (file,
+ _("Will print %s nested types defined in a class\n"),
+ value);
}
}
+/* When printing structs, offsets and sizes of members can be displayed using
+ decimal notation or hexadecimal notation. By default, Decimal notation is
+ used. */
+
+static bool print_offsets_and_sizes_in_hex = false;
+
+/* Set the flags that instructs if sizes and offsets of struct members are
+ displayed in hexadecimal or decimal notation. */
+
+static void
+set_print_offsets_and_sizes_in_hex (const char *args,
+ int from_tty, struct cmd_list_element *c)
+{
+ default_ptype_flags.print_in_hex = print_offsets_and_sizes_in_hex;
+}
+
+/* Display whether struct members sizes and offsets are printed
+ using decimal or hexadecimal notation. */
+
+static void
+show_print_offsets_and_sizes_in_hex (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ gdb_printf (file, _("\
+Display of struct members offsets and sizes in hexadecimal is %s\n"),
+ value);
+}
+
void _initialize_typeprint ();
void
_initialize_typeprint ()
/M print methods defined in a class\n\
/t do not print typedefs defined in a class\n\
/T print typedefs defined in a class\n\
- /o print offsets and sizes of fields in a struct (like pahole)"));
+ /o print offsets and sizes of fields in a struct (like pahole)\n\
+ /x use hexadecimal notation when displaying sizes and offsets\n\
+ of struct members\n\
+ /d use decimal notation when displaying sizes and offsets\n\
+ of struct members "));
set_cmd_completer (c, expression_completer);
c = add_com ("whatis", class_vars, whatis_command,
Only one level of typedefs is unrolled. See also \"ptype\"."));
set_cmd_completer (c, expression_completer);
- add_show_prefix_cmd ("type", no_class,
- _("Generic command for showing type-printing settings."),
- &showprinttypelist, "show print type ", 0,
- &showprintlist);
- add_basic_prefix_cmd ("type", no_class,
- _("Generic command for setting how types print."),
- &setprinttypelist, "set print type ", 0,
- &setprintlist);
+ add_setshow_prefix_cmd ("type", no_class,
+ _("Generic command for showing type-printing settings."),
+ _("Generic command for setting how types print."),
+ &setprinttypelist, &showprinttypelist,
+ &setprintlist, &showprintlist);
add_setshow_boolean_cmd ("methods", no_class, &print_methods,
_("\
set_print_type_nested_types,
show_print_type_nested_types,
&setprinttypelist, &showprinttypelist);
+
+ add_setshow_boolean_cmd ("hex", no_class, &print_offsets_and_sizes_in_hex,
+ _("\
+Set printing of struct members sizes and offsets using hex notation."), _("\
+Show whether sizes and offsets of struct members are printed using hex \
+notation."), nullptr, set_print_offsets_and_sizes_in_hex,
+ show_print_offsets_and_sizes_in_hex,
+ &setprinttypelist, &showprinttypelist);
}
/* Print <not allocated> status to stream STREAM. */