XML feature description support.
[deliverable/binutils-gdb.git] / gdb / xml-tdesc.c
1 /* XML target description support for GDB.
2
3 Copyright (C) 2006
4 Free Software Foundation, Inc.
5
6 Contributed by CodeSourcery.
7
8 This file is part of GDB.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA. */
24
25 #include "defs.h"
26 #include "target.h"
27 #include "target-descriptions.h"
28 #include "xml-support.h"
29 #include "xml-tdesc.h"
30
31 #include "gdb_assert.h"
32
33 #if !defined(HAVE_LIBEXPAT)
34
35 /* Parse DOCUMENT into a target description. Or don't, since we don't have
36 an XML parser. */
37
38 static struct target_desc *
39 tdesc_parse_xml (const char *document)
40 {
41 static int have_warned;
42
43 if (!have_warned)
44 {
45 have_warned = 1;
46 warning (_("Can not parse XML target description; XML support was "
47 "disabled at compile time"));
48 }
49
50 return NULL;
51 }
52
53 #else /* HAVE_LIBEXPAT */
54
55 /* Callback data for target description parsing. */
56
57 struct tdesc_parsing_data
58 {
59 /* The target description we are building. */
60 struct target_desc *tdesc;
61 };
62
63 /* Handle the end of an <architecture> element and its value. */
64
65 static void
66 tdesc_end_arch (struct gdb_xml_parser *parser,
67 const struct gdb_xml_element *element,
68 void *user_data, const char *body_text)
69 {
70 struct tdesc_parsing_data *data = user_data;
71 const struct bfd_arch_info *arch;
72
73 arch = bfd_scan_arch (body_text);
74 if (arch == NULL)
75 gdb_xml_error (parser, _("Target description specified unknown "
76 "architecture \"%s\""), body_text);
77 set_tdesc_architecture (data->tdesc, arch);
78 }
79
80 /* The elements and attributes of an XML target description. */
81
82 const struct gdb_xml_element target_children[] = {
83 { "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
84 NULL, tdesc_end_arch },
85 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
86 };
87
88 const struct gdb_xml_element tdesc_elements[] = {
89 { "target", NULL, target_children, GDB_XML_EF_NONE,
90 NULL, NULL },
91 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
92 };
93
94 /* Parse DOCUMENT into a target description and return it. */
95
96 static struct target_desc *
97 tdesc_parse_xml (const char *document)
98 {
99 struct cleanup *back_to, *result_cleanup;
100 struct gdb_xml_parser *parser;
101 struct tdesc_parsing_data data;
102
103 memset (&data, 0, sizeof (struct tdesc_parsing_data));
104
105 back_to = make_cleanup (null_cleanup, NULL);
106 parser = gdb_xml_create_parser_and_cleanup (_("target description"),
107 tdesc_elements, &data);
108
109 data.tdesc = allocate_target_description ();
110 result_cleanup = make_cleanup_free_target_description (data.tdesc);
111
112 if (gdb_xml_parse (parser, document) == 0)
113 {
114 /* Parsed successfully. */
115 discard_cleanups (result_cleanup);
116 do_cleanups (back_to);
117 return data.tdesc;
118 }
119 else
120 {
121 warning (_("Could not load XML target description; ignoring"));
122 do_cleanups (back_to);
123 return NULL;
124 }
125 }
126
127 #endif /* HAVE_LIBEXPAT */
128 \f
129
130 /* Close FILE. */
131
132 static void
133 do_cleanup_fclose (void *file)
134 {
135 fclose (file);
136 }
137
138 /* Open FILENAME, read all its text into memory, close it, and return
139 the text. If something goes wrong, return NULL and warn. */
140
141 static char *
142 fetch_xml_from_file (const char *filename)
143 {
144 FILE *file;
145 struct cleanup *back_to;
146 char *text;
147 size_t len, offset;
148
149 file = fopen (filename, FOPEN_RT);
150 if (file == NULL)
151 {
152 warning (_("Could not open \"%s\""), filename);
153 return NULL;
154 }
155 back_to = make_cleanup (do_cleanup_fclose, file);
156
157 /* Read in the whole file, one chunk at a time. */
158 len = 4096;
159 offset = 0;
160 text = xmalloc (len);
161 make_cleanup (free_current_contents, &text);
162 while (1)
163 {
164 size_t bytes_read;
165
166 /* Continue reading where the last read left off. Leave at least
167 one byte so that we can NUL-terminate the result. */
168 bytes_read = fread (text + offset, 1, len - offset - 1, file);
169 if (ferror (file))
170 {
171 warning (_("Read error from \"%s\""), filename);
172 do_cleanups (back_to);
173 return NULL;
174 }
175
176 offset += bytes_read;
177
178 if (feof (file))
179 break;
180
181 len = len * 2;
182 text = xrealloc (text, len);
183 }
184
185 fclose (file);
186 discard_cleanups (back_to);
187
188 text[offset] = '\0';
189 return text;
190 }
191
192 /* Read an XML target description from FILENAME. Parse it, and return
193 the parsed description. */
194
195 const struct target_desc *
196 file_read_description_xml (const char *filename)
197 {
198 struct target_desc *tdesc;
199 char *tdesc_str;
200 struct cleanup *back_to;
201
202 tdesc_str = fetch_xml_from_file (filename);
203 if (tdesc_str == NULL)
204 return NULL;
205
206 back_to = make_cleanup (xfree, tdesc_str);
207 tdesc = tdesc_parse_xml (tdesc_str);
208 do_cleanups (back_to);
209
210 return tdesc;
211 }
212
213 /* Read an XML target description using OPS. Parse it, and return the
214 parsed description. */
215
216 const struct target_desc *
217 target_read_description_xml (struct target_ops *ops)
218 {
219 struct target_desc *tdesc;
220 char *tdesc_str;
221 struct cleanup *back_to;
222
223 tdesc_str = target_read_stralloc (ops, TARGET_OBJECT_AVAILABLE_FEATURES,
224 "target.xml");
225 if (tdesc_str == NULL)
226 return NULL;
227
228 back_to = make_cleanup (xfree, tdesc_str);
229 tdesc = tdesc_parse_xml (tdesc_str);
230 do_cleanups (back_to);
231
232 return tdesc;
233 }
This page took 0.035246 seconds and 5 git commands to generate.