xref: /netbsd-src/external/gpl3/gdb.old/dist/gdbsupport/tdesc.cc (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* Target description support for GDB.
27d62b00eSchristos 
3*6881a400Schristos    Copyright (C) 2018-2023 Free Software Foundation, Inc.
47d62b00eSchristos 
57d62b00eSchristos    This file is part of GDB.
67d62b00eSchristos 
77d62b00eSchristos    This program is free software; you can redistribute it and/or modify
87d62b00eSchristos    it under the terms of the GNU General Public License as published by
97d62b00eSchristos    the Free Software Foundation; either version 3 of the License, or
107d62b00eSchristos    (at your option) any later version.
117d62b00eSchristos 
127d62b00eSchristos    This program is distributed in the hope that it will be useful,
137d62b00eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
147d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
157d62b00eSchristos    GNU General Public License for more details.
167d62b00eSchristos 
177d62b00eSchristos    You should have received a copy of the GNU General Public License
187d62b00eSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
197d62b00eSchristos 
207d62b00eSchristos #include "common-defs.h"
217d62b00eSchristos #include "gdbsupport/tdesc.h"
227d62b00eSchristos 
237d62b00eSchristos tdesc_reg::tdesc_reg (struct tdesc_feature *feature, const std::string &name_,
247d62b00eSchristos 		      int regnum, int save_restore_, const char *group_,
257d62b00eSchristos 		      int bitsize_, const char *type_)
267d62b00eSchristos   : name (name_), target_regnum (regnum),
277d62b00eSchristos     save_restore (save_restore_),
287d62b00eSchristos     group (group_ != NULL ? group_ : ""),
297d62b00eSchristos     bitsize (bitsize_),
307d62b00eSchristos     type (type_ != NULL ? type_ : "<unknown>")
317d62b00eSchristos {
327d62b00eSchristos   /* If the register's type is target-defined, look it up now.  We may not
337d62b00eSchristos      have easy access to the containing feature when we want it later.  */
347d62b00eSchristos   tdesc_type = tdesc_named_type (feature, type.c_str ());
357d62b00eSchristos }
367d62b00eSchristos 
377d62b00eSchristos /* Predefined types.  */
387d62b00eSchristos static tdesc_type_builtin tdesc_predefined_types[] =
397d62b00eSchristos {
407d62b00eSchristos   { "bool", TDESC_TYPE_BOOL },
417d62b00eSchristos   { "int8", TDESC_TYPE_INT8 },
427d62b00eSchristos   { "int16", TDESC_TYPE_INT16 },
437d62b00eSchristos   { "int32", TDESC_TYPE_INT32 },
447d62b00eSchristos   { "int64", TDESC_TYPE_INT64 },
457d62b00eSchristos   { "int128", TDESC_TYPE_INT128 },
467d62b00eSchristos   { "uint8", TDESC_TYPE_UINT8 },
477d62b00eSchristos   { "uint16", TDESC_TYPE_UINT16 },
487d62b00eSchristos   { "uint32", TDESC_TYPE_UINT32 },
497d62b00eSchristos   { "uint64", TDESC_TYPE_UINT64 },
507d62b00eSchristos   { "uint128", TDESC_TYPE_UINT128 },
517d62b00eSchristos   { "code_ptr", TDESC_TYPE_CODE_PTR },
527d62b00eSchristos   { "data_ptr", TDESC_TYPE_DATA_PTR },
537d62b00eSchristos   { "ieee_half", TDESC_TYPE_IEEE_HALF },
547d62b00eSchristos   { "ieee_single", TDESC_TYPE_IEEE_SINGLE },
557d62b00eSchristos   { "ieee_double", TDESC_TYPE_IEEE_DOUBLE },
567d62b00eSchristos   { "arm_fpa_ext", TDESC_TYPE_ARM_FPA_EXT },
577d62b00eSchristos   { "i387_ext", TDESC_TYPE_I387_EXT },
587d62b00eSchristos   { "bfloat16", TDESC_TYPE_BFLOAT16 }
597d62b00eSchristos };
607d62b00eSchristos 
617d62b00eSchristos void tdesc_feature::accept (tdesc_element_visitor &v) const
627d62b00eSchristos {
637d62b00eSchristos   v.visit_pre (this);
647d62b00eSchristos 
657d62b00eSchristos   for (const tdesc_type_up &type : types)
667d62b00eSchristos     type->accept (v);
677d62b00eSchristos 
687d62b00eSchristos   for (const tdesc_reg_up &reg : registers)
697d62b00eSchristos     reg->accept (v);
707d62b00eSchristos 
717d62b00eSchristos   v.visit_post (this);
727d62b00eSchristos }
737d62b00eSchristos 
747d62b00eSchristos bool tdesc_feature::operator== (const tdesc_feature &other) const
757d62b00eSchristos {
767d62b00eSchristos   if (name != other.name)
777d62b00eSchristos     return false;
787d62b00eSchristos 
797d62b00eSchristos   if (registers.size () != other.registers.size ())
807d62b00eSchristos     return false;
817d62b00eSchristos 
827d62b00eSchristos   for (int ix = 0; ix < registers.size (); ix++)
837d62b00eSchristos     {
847d62b00eSchristos       const tdesc_reg_up &reg1 = registers[ix];
857d62b00eSchristos       const tdesc_reg_up &reg2 = other.registers[ix];
867d62b00eSchristos 
877d62b00eSchristos       if (reg1 != reg2 && *reg1 != *reg2)
887d62b00eSchristos 	return false;
897d62b00eSchristos       }
907d62b00eSchristos 
917d62b00eSchristos   if (types.size () != other.types.size ())
927d62b00eSchristos     return false;
937d62b00eSchristos 
947d62b00eSchristos   for (int ix = 0; ix < types.size (); ix++)
957d62b00eSchristos     {
967d62b00eSchristos       const tdesc_type_up &type1 = types[ix];
977d62b00eSchristos       const tdesc_type_up &type2 = other.types[ix];
987d62b00eSchristos 
997d62b00eSchristos       if (type1 != type2 && *type1 != *type2)
1007d62b00eSchristos 	return false;
1017d62b00eSchristos     }
1027d62b00eSchristos 
1037d62b00eSchristos   return true;
1047d62b00eSchristos }
1057d62b00eSchristos 
1067d62b00eSchristos /* Lookup a predefined type.  */
1077d62b00eSchristos 
1087d62b00eSchristos static struct tdesc_type *
1097d62b00eSchristos tdesc_predefined_type (enum tdesc_type_kind kind)
1107d62b00eSchristos {
1117d62b00eSchristos   for (int ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++)
1127d62b00eSchristos     if (tdesc_predefined_types[ix].kind == kind)
1137d62b00eSchristos       return &tdesc_predefined_types[ix];
1147d62b00eSchristos 
1157d62b00eSchristos   gdb_assert_not_reached ("bad predefined tdesc type");
1167d62b00eSchristos }
1177d62b00eSchristos 
1187d62b00eSchristos /* See gdbsupport/tdesc.h.  */
1197d62b00eSchristos 
1207d62b00eSchristos struct tdesc_type *
1217d62b00eSchristos tdesc_named_type (const struct tdesc_feature *feature, const char *id)
1227d62b00eSchristos {
1237d62b00eSchristos   /* First try target-defined types.  */
1247d62b00eSchristos   for (const tdesc_type_up &type : feature->types)
1257d62b00eSchristos     if (type->name == id)
1267d62b00eSchristos       return type.get ();
1277d62b00eSchristos 
1287d62b00eSchristos   /* Next try the predefined types.  */
1297d62b00eSchristos   for (int ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++)
1307d62b00eSchristos     if (tdesc_predefined_types[ix].name == id)
1317d62b00eSchristos       return &tdesc_predefined_types[ix];
1327d62b00eSchristos 
1337d62b00eSchristos   return NULL;
1347d62b00eSchristos }
1357d62b00eSchristos 
1367d62b00eSchristos /* See gdbsupport/tdesc.h.  */
1377d62b00eSchristos 
1387d62b00eSchristos void
1397d62b00eSchristos tdesc_create_reg (struct tdesc_feature *feature, const char *name,
1407d62b00eSchristos 		  int regnum, int save_restore, const char *group,
1417d62b00eSchristos 		  int bitsize, const char *type)
1427d62b00eSchristos {
1437d62b00eSchristos   tdesc_reg *reg = new tdesc_reg (feature, name, regnum, save_restore,
1447d62b00eSchristos 				  group, bitsize, type);
1457d62b00eSchristos 
1467d62b00eSchristos   feature->registers.emplace_back (reg);
1477d62b00eSchristos }
1487d62b00eSchristos 
1497d62b00eSchristos /* See gdbsupport/tdesc.h.  */
1507d62b00eSchristos 
1517d62b00eSchristos struct tdesc_type *
1527d62b00eSchristos tdesc_create_vector (struct tdesc_feature *feature, const char *name,
1537d62b00eSchristos 		     struct tdesc_type *field_type, int count)
1547d62b00eSchristos {
1557d62b00eSchristos   tdesc_type_vector *type = new tdesc_type_vector (name, field_type, count);
1567d62b00eSchristos   feature->types.emplace_back (type);
1577d62b00eSchristos 
1587d62b00eSchristos   return type;
1597d62b00eSchristos }
1607d62b00eSchristos 
1617d62b00eSchristos /* See gdbsupport/tdesc.h.  */
1627d62b00eSchristos 
1637d62b00eSchristos tdesc_type_with_fields *
1647d62b00eSchristos tdesc_create_struct (struct tdesc_feature *feature, const char *name)
1657d62b00eSchristos {
1667d62b00eSchristos   tdesc_type_with_fields *type
1677d62b00eSchristos     = new tdesc_type_with_fields (name, TDESC_TYPE_STRUCT);
1687d62b00eSchristos   feature->types.emplace_back (type);
1697d62b00eSchristos 
1707d62b00eSchristos   return type;
1717d62b00eSchristos }
1727d62b00eSchristos 
1737d62b00eSchristos /* See gdbsupport/tdesc.h.  */
1747d62b00eSchristos 
1757d62b00eSchristos void
1767d62b00eSchristos tdesc_set_struct_size (tdesc_type_with_fields *type, int size)
1777d62b00eSchristos {
1787d62b00eSchristos   gdb_assert (type->kind == TDESC_TYPE_STRUCT);
1797d62b00eSchristos   gdb_assert (size > 0);
1807d62b00eSchristos   type->size = size;
1817d62b00eSchristos }
1827d62b00eSchristos 
1837d62b00eSchristos /* See gdbsupport/tdesc.h.  */
1847d62b00eSchristos 
1857d62b00eSchristos tdesc_type_with_fields *
1867d62b00eSchristos tdesc_create_union (struct tdesc_feature *feature, const char *name)
1877d62b00eSchristos {
1887d62b00eSchristos   tdesc_type_with_fields *type
1897d62b00eSchristos     = new tdesc_type_with_fields (name, TDESC_TYPE_UNION);
1907d62b00eSchristos   feature->types.emplace_back (type);
1917d62b00eSchristos 
1927d62b00eSchristos   return type;
1937d62b00eSchristos }
1947d62b00eSchristos 
1957d62b00eSchristos /* See gdbsupport/tdesc.h.  */
1967d62b00eSchristos 
1977d62b00eSchristos tdesc_type_with_fields *
1987d62b00eSchristos tdesc_create_flags (struct tdesc_feature *feature, const char *name,
1997d62b00eSchristos 		    int size)
2007d62b00eSchristos {
2017d62b00eSchristos   gdb_assert (size > 0);
2027d62b00eSchristos 
2037d62b00eSchristos   tdesc_type_with_fields *type
2047d62b00eSchristos     = new tdesc_type_with_fields (name, TDESC_TYPE_FLAGS, size);
2057d62b00eSchristos   feature->types.emplace_back (type);
2067d62b00eSchristos 
2077d62b00eSchristos   return type;
2087d62b00eSchristos }
2097d62b00eSchristos 
2107d62b00eSchristos /* See gdbsupport/tdesc.h.  */
2117d62b00eSchristos 
2127d62b00eSchristos tdesc_type_with_fields *
2137d62b00eSchristos tdesc_create_enum (struct tdesc_feature *feature, const char *name,
2147d62b00eSchristos 		   int size)
2157d62b00eSchristos {
2167d62b00eSchristos   gdb_assert (size > 0);
2177d62b00eSchristos 
2187d62b00eSchristos   tdesc_type_with_fields *type
2197d62b00eSchristos     = new tdesc_type_with_fields (name, TDESC_TYPE_ENUM, size);
2207d62b00eSchristos   feature->types.emplace_back (type);
2217d62b00eSchristos 
2227d62b00eSchristos   return type;
2237d62b00eSchristos }
2247d62b00eSchristos 
2257d62b00eSchristos /* See gdbsupport/tdesc.h.  */
2267d62b00eSchristos 
2277d62b00eSchristos void
2287d62b00eSchristos tdesc_add_field (tdesc_type_with_fields *type, const char *field_name,
2297d62b00eSchristos 		 struct tdesc_type *field_type)
2307d62b00eSchristos {
2317d62b00eSchristos   gdb_assert (type->kind == TDESC_TYPE_UNION
2327d62b00eSchristos 	      || type->kind == TDESC_TYPE_STRUCT);
2337d62b00eSchristos 
2347d62b00eSchristos   /* Initialize start and end so we know this is not a bit-field
2357d62b00eSchristos      when we print-c-tdesc.  */
2367d62b00eSchristos   type->fields.emplace_back (field_name, field_type, -1, -1);
2377d62b00eSchristos }
2387d62b00eSchristos 
2397d62b00eSchristos /* See gdbsupport/tdesc.h.  */
2407d62b00eSchristos 
2417d62b00eSchristos void
2427d62b00eSchristos tdesc_add_typed_bitfield (tdesc_type_with_fields *type, const char *field_name,
2437d62b00eSchristos 			  int start, int end, struct tdesc_type *field_type)
2447d62b00eSchristos {
2457d62b00eSchristos   gdb_assert (type->kind == TDESC_TYPE_STRUCT
2467d62b00eSchristos 	      || type->kind == TDESC_TYPE_FLAGS);
2477d62b00eSchristos   gdb_assert (start >= 0 && end >= start);
2487d62b00eSchristos 
2497d62b00eSchristos   type->fields.emplace_back (field_name, field_type, start, end);
2507d62b00eSchristos }
2517d62b00eSchristos 
2527d62b00eSchristos /* See gdbsupport/tdesc.h.  */
2537d62b00eSchristos 
2547d62b00eSchristos void
2557d62b00eSchristos tdesc_add_bitfield (tdesc_type_with_fields *type, const char *field_name,
2567d62b00eSchristos 		    int start, int end)
2577d62b00eSchristos {
2587d62b00eSchristos   struct tdesc_type *field_type;
2597d62b00eSchristos 
2607d62b00eSchristos   gdb_assert (start >= 0 && end >= start);
2617d62b00eSchristos 
2627d62b00eSchristos   if (type->size > 4)
2637d62b00eSchristos     field_type = tdesc_predefined_type (TDESC_TYPE_UINT64);
2647d62b00eSchristos   else
2657d62b00eSchristos     field_type = tdesc_predefined_type (TDESC_TYPE_UINT32);
2667d62b00eSchristos 
2677d62b00eSchristos   tdesc_add_typed_bitfield (type, field_name, start, end, field_type);
2687d62b00eSchristos }
2697d62b00eSchristos 
2707d62b00eSchristos /* See gdbsupport/tdesc.h.  */
2717d62b00eSchristos 
2727d62b00eSchristos void
2737d62b00eSchristos tdesc_add_flag (tdesc_type_with_fields *type, int start,
2747d62b00eSchristos 		const char *flag_name)
2757d62b00eSchristos {
2767d62b00eSchristos   gdb_assert (type->kind == TDESC_TYPE_FLAGS
2777d62b00eSchristos 	      || type->kind == TDESC_TYPE_STRUCT);
2787d62b00eSchristos 
2797d62b00eSchristos   type->fields.emplace_back (flag_name,
2807d62b00eSchristos 			     tdesc_predefined_type (TDESC_TYPE_BOOL),
2817d62b00eSchristos 			     start, start);
2827d62b00eSchristos }
2837d62b00eSchristos 
2847d62b00eSchristos /* See gdbsupport/tdesc.h.  */
2857d62b00eSchristos 
2867d62b00eSchristos void
2877d62b00eSchristos tdesc_add_enum_value (tdesc_type_with_fields *type, int value,
2887d62b00eSchristos 		      const char *name)
2897d62b00eSchristos {
2907d62b00eSchristos   gdb_assert (type->kind == TDESC_TYPE_ENUM);
2917d62b00eSchristos   type->fields.emplace_back (name,
2927d62b00eSchristos 			     tdesc_predefined_type (TDESC_TYPE_INT32),
2937d62b00eSchristos 			     value, -1);
2947d62b00eSchristos }
2957d62b00eSchristos 
2967d62b00eSchristos void print_xml_feature::visit_pre (const tdesc_feature *e)
2977d62b00eSchristos {
2987d62b00eSchristos   add_line ("<feature name=\"%s\">", e->name.c_str ());
2997d62b00eSchristos   indent (1);
3007d62b00eSchristos }
3017d62b00eSchristos 
3027d62b00eSchristos void print_xml_feature::visit_post (const tdesc_feature *e)
3037d62b00eSchristos {
3047d62b00eSchristos   indent (-1);
3057d62b00eSchristos   add_line ("</feature>");
3067d62b00eSchristos }
3077d62b00eSchristos 
3087d62b00eSchristos void print_xml_feature::visit (const tdesc_type_builtin *t)
3097d62b00eSchristos {
3107d62b00eSchristos   error (_("xml output is not supported for type \"%s\"."), t->name.c_str ());
3117d62b00eSchristos }
3127d62b00eSchristos 
3137d62b00eSchristos void print_xml_feature::visit (const tdesc_type_vector *t)
3147d62b00eSchristos {
3157d62b00eSchristos   add_line ("<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
3167d62b00eSchristos 	    t->name.c_str (), t->element_type->name.c_str (), t->count);
3177d62b00eSchristos }
3187d62b00eSchristos 
3197d62b00eSchristos void print_xml_feature::visit (const tdesc_type_with_fields *t)
3207d62b00eSchristos {
3217d62b00eSchristos   const static char *types[] = { "struct", "union", "flags", "enum" };
3227d62b00eSchristos 
3237d62b00eSchristos   gdb_assert (t->kind >= TDESC_TYPE_STRUCT && t->kind <= TDESC_TYPE_ENUM);
3247d62b00eSchristos 
3257d62b00eSchristos   std::string tmp;
3267d62b00eSchristos 
3277d62b00eSchristos   string_appendf (tmp,
3287d62b00eSchristos 		  "<%s id=\"%s\"", types[t->kind - TDESC_TYPE_STRUCT],
3297d62b00eSchristos 		  t->name.c_str ());
3307d62b00eSchristos 
3317d62b00eSchristos   switch (t->kind)
3327d62b00eSchristos     {
3337d62b00eSchristos     case TDESC_TYPE_STRUCT:
3347d62b00eSchristos     case TDESC_TYPE_FLAGS:
3357d62b00eSchristos       if (t->size > 0)
3367d62b00eSchristos 	string_appendf (tmp, " size=\"%d\"", t->size);
3377d62b00eSchristos       string_appendf (tmp, ">");
3387d62b00eSchristos       add_line (tmp);
3397d62b00eSchristos 
3407d62b00eSchristos       for (const tdesc_type_field &f : t->fields)
3417d62b00eSchristos 	{
3427d62b00eSchristos 	  tmp.clear ();
3437d62b00eSchristos 	  string_appendf (tmp, "  <field name=\"%s\"", f.name.c_str ());
3447d62b00eSchristos 	  if (f.start != -1)
3457d62b00eSchristos 	    string_appendf (tmp, " start=\"%d\" end=\"%d\"", f.start,
3467d62b00eSchristos 			    f.end);
3477d62b00eSchristos 	  string_appendf (tmp, " type=\"%s\"/>",
3487d62b00eSchristos 			  f.type->name.c_str ());
3497d62b00eSchristos 	  add_line (tmp);
3507d62b00eSchristos 	}
3517d62b00eSchristos       break;
3527d62b00eSchristos 
3537d62b00eSchristos     case TDESC_TYPE_ENUM:
354*6881a400Schristos       if (t->size > 0)
355*6881a400Schristos 	string_appendf (tmp, " size=\"%d\"", t->size);
3567d62b00eSchristos       string_appendf (tmp, ">");
3577d62b00eSchristos       add_line (tmp);
358*6881a400Schristos       /* The 'start' of the field is reused as the enum value.  The 'end'
359*6881a400Schristos 	 of the field is always set to -1 for enum values.  */
3607d62b00eSchristos       for (const tdesc_type_field &f : t->fields)
361*6881a400Schristos 	add_line ("  <evalue name=\"%s\" value=\"%d\"/>",
3627d62b00eSchristos 		  f.name.c_str (), f.start);
3637d62b00eSchristos       break;
3647d62b00eSchristos 
3657d62b00eSchristos     case TDESC_TYPE_UNION:
3667d62b00eSchristos       string_appendf (tmp, ">");
3677d62b00eSchristos       add_line (tmp);
3687d62b00eSchristos       for (const tdesc_type_field &f : t->fields)
3697d62b00eSchristos 	add_line ("  <field name=\"%s\" type=\"%s\"/>",
3707d62b00eSchristos 		  f.name.c_str (), f.type->name.c_str ());
3717d62b00eSchristos       break;
3727d62b00eSchristos 
3737d62b00eSchristos     default:
3747d62b00eSchristos       error (_("xml output is not supported for type \"%s\"."),
3757d62b00eSchristos 	     t->name.c_str ());
3767d62b00eSchristos     }
3777d62b00eSchristos 
3787d62b00eSchristos   add_line ("</%s>", types[t->kind - TDESC_TYPE_STRUCT]);
3797d62b00eSchristos }
3807d62b00eSchristos 
3817d62b00eSchristos void print_xml_feature::visit (const tdesc_reg *r)
3827d62b00eSchristos {
3837d62b00eSchristos   std::string tmp;
3847d62b00eSchristos 
3857d62b00eSchristos   string_appendf (tmp,
3867d62b00eSchristos 		  "<reg name=\"%s\" bitsize=\"%d\" type=\"%s\" regnum=\"%ld\"",
3877d62b00eSchristos 		  r->name.c_str (), r->bitsize, r->type.c_str (),
3887d62b00eSchristos 		  r->target_regnum);
3897d62b00eSchristos 
3907d62b00eSchristos   if (r->group.length () > 0)
3917d62b00eSchristos     string_appendf (tmp, " group=\"%s\"", r->group.c_str ());
3927d62b00eSchristos 
3937d62b00eSchristos   if (r->save_restore == 0)
3947d62b00eSchristos     string_appendf (tmp, " save-restore=\"no\"");
3957d62b00eSchristos 
3967d62b00eSchristos   string_appendf (tmp, "/>");
3977d62b00eSchristos 
3987d62b00eSchristos   add_line (tmp);
3997d62b00eSchristos }
4007d62b00eSchristos 
4017d62b00eSchristos void print_xml_feature::visit_pre (const target_desc *e)
4027d62b00eSchristos {
4037d62b00eSchristos #ifndef IN_PROCESS_AGENT
4047d62b00eSchristos   add_line ("<?xml version=\"1.0\"?>");
4057d62b00eSchristos   add_line ("<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
4067d62b00eSchristos   add_line ("<target>");
4077d62b00eSchristos   indent (1);
4087d62b00eSchristos   if (tdesc_architecture_name (e))
4097d62b00eSchristos     add_line ("<architecture>%s</architecture>",
4107d62b00eSchristos 	      tdesc_architecture_name (e));
4117d62b00eSchristos 
4127d62b00eSchristos   const char *osabi = tdesc_osabi_name (e);
4137d62b00eSchristos   if (osabi != nullptr)
4147d62b00eSchristos     add_line ("<osabi>%s</osabi>", osabi);
4157d62b00eSchristos 
4167d62b00eSchristos   const std::vector<tdesc_compatible_info_up> &compatible_list
4177d62b00eSchristos     = tdesc_compatible_info_list (e);
4187d62b00eSchristos   for (const auto &c : compatible_list)
4197d62b00eSchristos     add_line ("<compatible>%s</compatible>",
4207d62b00eSchristos 	      tdesc_compatible_info_arch_name (c));
4217d62b00eSchristos #endif
4227d62b00eSchristos }
4237d62b00eSchristos 
4247d62b00eSchristos void print_xml_feature::visit_post (const target_desc *e)
4257d62b00eSchristos {
4267d62b00eSchristos   indent (-1);
4277d62b00eSchristos   add_line ("</target>");
4287d62b00eSchristos }
4297d62b00eSchristos 
4307d62b00eSchristos /* See gdbsupport/tdesc.h.  */
4317d62b00eSchristos 
4327d62b00eSchristos void
4337d62b00eSchristos print_xml_feature::add_line (const std::string &str)
4347d62b00eSchristos {
4357d62b00eSchristos   string_appendf (*m_buffer, "%*s", m_depth, "");
4367d62b00eSchristos   string_appendf (*m_buffer, "%s", str.c_str ());
4377d62b00eSchristos   string_appendf (*m_buffer, "\n");
4387d62b00eSchristos }
4397d62b00eSchristos 
4407d62b00eSchristos /* See gdbsupport/tdesc.h.  */
4417d62b00eSchristos 
4427d62b00eSchristos void
4437d62b00eSchristos print_xml_feature::add_line (const char *fmt, ...)
4447d62b00eSchristos {
4457d62b00eSchristos   std::string tmp;
4467d62b00eSchristos 
4477d62b00eSchristos   va_list ap;
4487d62b00eSchristos   va_start (ap, fmt);
4497d62b00eSchristos   string_vappendf (tmp, fmt, ap);
4507d62b00eSchristos   va_end (ap);
4517d62b00eSchristos   add_line (tmp);
4527d62b00eSchristos }
453