+const struct type_print_options type_print_raw_options =
+{
+ 1, /* raw */
+ 1, /* print_methods */
+ 1, /* print_typedefs */
+ 0, /* print_offsets */
+ 0, /* print_nested_type_limit */
+ NULL, /* local_typedefs */
+ NULL, /* global_table */
+ NULL /* global_printers */
+};
+
+/* The default flags for 'ptype' and 'whatis'. */
+
+static struct type_print_options default_ptype_flags =
+{
+ 0, /* raw */
+ 1, /* print_methods */
+ 1, /* print_typedefs */
+ 0, /* print_offsets */
+ 0, /* print_nested_type_limit */
+ NULL, /* local_typedefs */
+ NULL, /* global_table */
+ NULL /* global_printers */
+};
+
+\f
+
+/* See typeprint.h. */
+
+const int print_offset_data::indentation = 23;
+
+
+/* See typeprint.h. */
+
+void
+print_offset_data::maybe_print_hole (struct ui_file *stream,
+ unsigned int bitpos,
+ const char *for_what)
+{
+ /* We check for END_BITPOS > 0 because there is a specific
+ scenario when END_BITPOS can be zero and BITPOS can be >
+ 0: when we are dealing with a struct/class with a virtual method.
+ Because of the vtable, the first field of the struct/class will
+ have an offset of sizeof (void *) (the size of the vtable). If
+ we do not check for END_BITPOS > 0 here, GDB will report
+ a hole before the first field, which is not accurate. */
+ if (end_bitpos > 0 && end_bitpos < bitpos)
+ {
+ /* If END_BITPOS is smaller than the current type's
+ bitpos, it means there's a hole in the struct, so we report
+ it here. */
+ unsigned int hole = bitpos - end_bitpos;
+ unsigned int hole_byte = hole / TARGET_CHAR_BIT;
+ unsigned int hole_bit = hole % TARGET_CHAR_BIT;
+
+ if (hole_bit > 0)
+ fprintf_filtered (stream, "/* XXX %2u-bit %s */\n", hole_bit,
+ for_what);
+
+ if (hole_byte > 0)
+ fprintf_filtered (stream, "/* XXX %2u-byte %s */\n", hole_byte,
+ for_what);
+ }
+}
+
+/* See typeprint.h. */
+
+void
+print_offset_data::update (struct type *type, unsigned int field_idx,
+ struct ui_file *stream)
+{
+ if (field_is_static (&TYPE_FIELD (type, field_idx)))
+ {
+ print_spaces_filtered (indentation, stream);
+ return;
+ }
+
+ struct type *ftype = check_typedef (TYPE_FIELD_TYPE (type, field_idx));
+ if (TYPE_CODE (type) == TYPE_CODE_UNION)
+ {
+ /* Since union fields don't have the concept of offsets, we just
+ print their sizes. */
+ fprintf_filtered (stream, "/* %4s */",
+ pulongest (TYPE_LENGTH (ftype)));
+ return;
+ }
+
+ unsigned int bitpos = TYPE_FIELD_BITPOS (type, field_idx);
+ unsigned int fieldsize_byte = TYPE_LENGTH (ftype);
+ unsigned int fieldsize_bit = fieldsize_byte * TARGET_CHAR_BIT;
+
+ maybe_print_hole (stream, bitpos, "hole");
+
+ if (TYPE_FIELD_PACKED (type, field_idx)
+ || offset_bitpos % TARGET_CHAR_BIT != 0)
+ {
+ /* We're dealing with a bitfield. Print the bit offset. */
+ fieldsize_bit = TYPE_FIELD_BITSIZE (type, field_idx);
+
+ unsigned real_bitpos = bitpos + offset_bitpos;
+
+ fprintf_filtered (stream, "/* %4u:%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);
+
+ fprintf_filtered (stream, " ");
+ }
+
+ fprintf_filtered (stream, " | %4u */", fieldsize_byte);
+
+ end_bitpos = bitpos + fieldsize_bit;
+}
+
+/* See typeprint.h. */
+
+void
+print_offset_data::finish (struct type *type, int level,
+ struct ui_file *stream)
+{
+ 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)));
+}
+
+\f
+
+/* A hash function for a typedef_field. */
+
+static hashval_t
+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));
+}
+
+/* An equality function for a typedef field. */
+
+static int
+eq_typedef_field (const void *a, const void *b)
+{
+ const struct decl_field *tfa = (const struct decl_field *) a;
+ const struct decl_field *tfb = (const struct decl_field *) b;
+
+ return types_equal (tfa->type, tfb->type);
+}
+
+/* See typeprint.h. */
+
+void
+typedef_hash_table::recursively_update (struct type *t)
+{
+ int i;
+
+ for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (t); ++i)
+ {
+ struct decl_field *tdef = &TYPE_TYPEDEF_FIELD (t, i);
+ void **slot;
+
+ slot = htab_find_slot (m_table, tdef, INSERT);
+ /* Only add a given typedef name once. Really this shouldn't
+ happen; but it is safe enough to do the updates breadth-first
+ and thus use the most specific typedef. */
+ if (*slot == NULL)
+ *slot = tdef;
+ }
+
+ /* Recurse into superclasses. */
+ for (i = 0; i < TYPE_N_BASECLASSES (t); ++i)
+ recursively_update (TYPE_BASECLASS (t, i));
+}
+
+/* See typeprint.h. */
+
+void
+typedef_hash_table::add_template_parameters (struct type *t)
+{
+ int i;
+
+ for (i = 0; i < TYPE_N_TEMPLATE_ARGUMENTS (t); ++i)
+ {
+ struct decl_field *tf;
+ void **slot;
+
+ /* We only want type-valued template parameters in the hash. */
+ if (SYMBOL_CLASS (TYPE_TEMPLATE_ARGUMENT (t, i)) != 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));
+
+ slot = htab_find_slot (m_table, tf, INSERT);
+ if (*slot == NULL)
+ *slot = tf;
+ }
+}
+
+/* See typeprint.h. */
+
+typedef_hash_table::typedef_hash_table ()
+{
+ m_table = htab_create_alloc (10, hash_typedef_field, eq_typedef_field,
+ NULL, xcalloc, xfree);
+}
+
+/* Free a typedef field table. */
+
+typedef_hash_table::~typedef_hash_table ()
+{
+ htab_delete (m_table);
+}
+
+/* Helper function for typedef_hash_table::copy. */
+
+static int
+copy_typedef_hash_element (void **slot, void *nt)
+{
+ htab_t new_table = (htab_t) nt;
+ void **new_slot;
+
+ new_slot = htab_find_slot (new_table, *slot, INSERT);
+ if (*new_slot == NULL)
+ *new_slot = *slot;
+
+ return 1;
+}
+
+/* See typeprint.h. */
+
+typedef_hash_table::typedef_hash_table (const typedef_hash_table &table)
+{
+ m_table = htab_create_alloc (10, hash_typedef_field, eq_typedef_field,
+ NULL, xcalloc, xfree);
+ htab_traverse_noresize (table.m_table, copy_typedef_hash_element,
+ m_table);
+}
+
+/* Look up the type T in the global typedef hash. If it is found,
+ return the typedef name. If it is not found, apply the
+ type-printers, if any, given by start_script_type_printers and return the
+ result. A NULL return means that the name was not found. */
+
+const char *
+typedef_hash_table::find_global_typedef (const struct type_print_options *flags,
+ struct type *t)
+{
+ char *applied;
+ void **slot;
+ struct decl_field tf, *new_tf;
+
+ if (flags->global_typedefs == NULL)
+ return NULL;
+
+ tf.name = NULL;
+ tf.type = t;
+
+ slot = htab_find_slot (flags->global_typedefs->m_table, &tf, INSERT);
+ if (*slot != NULL)
+ {
+ new_tf = (struct decl_field *) *slot;
+ return new_tf->name;
+ }
+
+ /* Put an entry into the hash table now, in case
+ apply_ext_lang_type_printers recurses. */
+ new_tf = XOBNEW (&flags->global_typedefs->m_storage, struct decl_field);
+ new_tf->name = NULL;
+ new_tf->type = t;
+
+ *slot = new_tf;
+
+ applied = apply_ext_lang_type_printers (flags->global_printers, t);