a8dbc519ae8b23384203238d28055c690d2af153
[deliverable/binutils-gdb.git] / gdb / xml-support.c
1 /* Helper routines for parsing XML using Expat.
2
3 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21 #include "gdbcmd.h"
22 #include "exceptions.h"
23 #include "xml-support.h"
24
25 #include "gdb_string.h"
26 #include "safe-ctype.h"
27
28 /* Debugging flag. */
29 static int debug_xml;
30
31 /* The contents of this file are only useful if XML support is
32 available. */
33 #ifdef HAVE_LIBEXPAT
34
35 #include "gdb_expat.h"
36
37 /* The maximum depth of <xi:include> nesting. No need to be miserly,
38 we just want to avoid running out of stack on loops. */
39 #define MAX_XINCLUDE_DEPTH 30
40
41 /* Simplified XML parser infrastructure. */
42
43 /* A parsing level -- used to keep track of the current element
44 nesting. */
45 struct scope_level
46 {
47 /* Elements we allow at this level. */
48 const struct gdb_xml_element *elements;
49
50 /* The element which we are within. */
51 const struct gdb_xml_element *element;
52
53 /* Mask of which elements we've seen at this level (used for
54 optional and repeatable checking). */
55 unsigned int seen;
56
57 /* Body text accumulation. */
58 struct obstack *body;
59 };
60 typedef struct scope_level scope_level_s;
61 DEF_VEC_O(scope_level_s);
62
63 /* The parser itself, and our additional state. */
64 struct gdb_xml_parser
65 {
66 XML_Parser expat_parser; /* The underlying expat parser. */
67
68 const char *name; /* Name of this parser. */
69 void *user_data; /* The user's callback data, for handlers. */
70
71 VEC(scope_level_s) *scopes; /* Scoping stack. */
72
73 struct gdb_exception error; /* A thrown error, if any. */
74 int last_line; /* The line of the thrown error, or 0. */
75
76 const char *dtd_name; /* The name of the expected / default DTD,
77 if specified. */
78 int is_xinclude; /* Are we the special <xi:include> parser? */
79 };
80
81 /* Process some body text. We accumulate the text for later use; it's
82 wrong to do anything with it immediately, because a single block of
83 text might be broken up into multiple calls to this function. */
84
85 static void
86 gdb_xml_body_text (void *data, const XML_Char *text, int length)
87 {
88 struct gdb_xml_parser *parser = data;
89 struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
90
91 if (parser->error.reason < 0)
92 return;
93
94 if (scope->body == NULL)
95 {
96 scope->body = XZALLOC (struct obstack);
97 obstack_init (scope->body);
98 }
99
100 obstack_grow (scope->body, text, length);
101 }
102
103 /* Issue a debugging message from one of PARSER's handlers. */
104
105 void
106 gdb_xml_debug (struct gdb_xml_parser *parser, const char *format, ...)
107 {
108 int line = XML_GetCurrentLineNumber (parser->expat_parser);
109 va_list ap;
110 char *message;
111
112 if (!debug_xml)
113 return;
114
115 va_start (ap, format);
116 message = xstrvprintf (format, ap);
117 if (line)
118 fprintf_unfiltered (gdb_stderr, "%s (line %d): %s\n",
119 parser->name, line, message);
120 else
121 fprintf_unfiltered (gdb_stderr, "%s: %s\n",
122 parser->name, message);
123 xfree (message);
124 }
125
126 /* Issue an error message from one of PARSER's handlers, and stop
127 parsing. */
128
129 void
130 gdb_xml_error (struct gdb_xml_parser *parser, const char *format, ...)
131 {
132 int line = XML_GetCurrentLineNumber (parser->expat_parser);
133 va_list ap;
134
135 parser->last_line = line;
136 va_start (ap, format);
137 throw_verror (XML_PARSE_ERROR, format, ap);
138 }
139
140 /* Clean up a vector of parsed attribute values. */
141
142 static void
143 gdb_xml_values_cleanup (void *data)
144 {
145 VEC(gdb_xml_value_s) **values = data;
146 struct gdb_xml_value *value;
147 int ix;
148
149 for (ix = 0; VEC_iterate (gdb_xml_value_s, *values, ix, value); ix++)
150 xfree (value->value);
151 VEC_free (gdb_xml_value_s, *values);
152 }
153
154 /* Handle the start of an element. DATA is our local XML parser, NAME
155 is the element, and ATTRS are the names and values of this
156 element's attributes. */
157
158 static void
159 gdb_xml_start_element (void *data, const XML_Char *name,
160 const XML_Char **attrs)
161 {
162 struct gdb_xml_parser *parser = data;
163 struct scope_level *scope;
164 struct scope_level new_scope;
165 const struct gdb_xml_element *element;
166 const struct gdb_xml_attribute *attribute;
167 VEC(gdb_xml_value_s) *attributes = NULL;
168 unsigned int seen;
169 struct cleanup *back_to;
170
171 /* Push an error scope. If we return or throw an exception before
172 filling this in, it will tell us to ignore children of this
173 element. */
174 VEC_reserve (scope_level_s, parser->scopes, 1);
175 scope = VEC_last (scope_level_s, parser->scopes);
176 memset (&new_scope, 0, sizeof (new_scope));
177 VEC_quick_push (scope_level_s, parser->scopes, &new_scope);
178
179 gdb_xml_debug (parser, _("Entering element <%s>"), name);
180
181 /* Find this element in the list of the current scope's allowed
182 children. Record that we've seen it. */
183
184 seen = 1;
185 for (element = scope->elements; element && element->name;
186 element++, seen <<= 1)
187 if (strcmp (element->name, name) == 0)
188 break;
189
190 if (element == NULL || element->name == NULL)
191 {
192 /* If we're working on XInclude, <xi:include> can be the child
193 of absolutely anything. Copy the previous scope's element
194 list into the new scope even if there was no match. */
195 if (parser->is_xinclude)
196 {
197 struct scope_level *unknown_scope;
198
199 XML_DefaultCurrent (parser->expat_parser);
200
201 unknown_scope = VEC_last (scope_level_s, parser->scopes);
202 unknown_scope->elements = scope->elements;
203 return;
204 }
205
206 gdb_xml_debug (parser, _("Element <%s> unknown"), name);
207 return;
208 }
209
210 if (!(element->flags & GDB_XML_EF_REPEATABLE) && (seen & scope->seen))
211 gdb_xml_error (parser, _("Element <%s> only expected once"), name);
212
213 scope->seen |= seen;
214
215 back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
216
217 for (attribute = element->attributes;
218 attribute != NULL && attribute->name != NULL;
219 attribute++)
220 {
221 const char *val = NULL;
222 const XML_Char **p;
223 void *parsed_value;
224 struct gdb_xml_value new_value;
225
226 for (p = attrs; *p != NULL; p += 2)
227 if (!strcmp (attribute->name, p[0]))
228 {
229 val = p[1];
230 break;
231 }
232
233 if (*p != NULL && val == NULL)
234 {
235 gdb_xml_debug (parser, _("Attribute \"%s\" missing a value"),
236 attribute->name);
237 continue;
238 }
239
240 if (*p == NULL && !(attribute->flags & GDB_XML_AF_OPTIONAL))
241 {
242 gdb_xml_error (parser, _("Required attribute \"%s\" of "
243 "<%s> not specified"),
244 attribute->name, element->name);
245 continue;
246 }
247
248 if (*p == NULL)
249 continue;
250
251 gdb_xml_debug (parser, _("Parsing attribute %s=\"%s\""),
252 attribute->name, val);
253
254 if (attribute->handler)
255 parsed_value = attribute->handler (parser, attribute, val);
256 else
257 parsed_value = xstrdup (val);
258
259 new_value.name = attribute->name;
260 new_value.value = parsed_value;
261 VEC_safe_push (gdb_xml_value_s, attributes, &new_value);
262 }
263
264 /* Check for unrecognized attributes. */
265 if (debug_xml)
266 {
267 const XML_Char **p;
268
269 for (p = attrs; *p != NULL; p += 2)
270 {
271 for (attribute = element->attributes;
272 attribute != NULL && attribute->name != NULL;
273 attribute++)
274 if (strcmp (attribute->name, *p) == 0)
275 break;
276
277 if (attribute == NULL || attribute->name == NULL)
278 gdb_xml_debug (parser, _("Ignoring unknown attribute %s"), *p);
279 }
280 }
281
282 /* Call the element handler if there is one. */
283 if (element->start_handler)
284 element->start_handler (parser, element, parser->user_data, attributes);
285
286 /* Fill in a new scope level. */
287 scope = VEC_last (scope_level_s, parser->scopes);
288 scope->element = element;
289 scope->elements = element->children;
290
291 do_cleanups (back_to);
292 }
293
294 /* Wrapper for gdb_xml_start_element, to prevent throwing exceptions
295 through expat. */
296
297 static void
298 gdb_xml_start_element_wrapper (void *data, const XML_Char *name,
299 const XML_Char **attrs)
300 {
301 struct gdb_xml_parser *parser = data;
302 volatile struct gdb_exception ex;
303
304 if (parser->error.reason < 0)
305 return;
306
307 TRY_CATCH (ex, RETURN_MASK_ALL)
308 {
309 gdb_xml_start_element (data, name, attrs);
310 }
311 if (ex.reason < 0)
312 {
313 parser->error = ex;
314 #ifdef HAVE_XML_STOPPARSER
315 XML_StopParser (parser->expat_parser, XML_FALSE);
316 #endif
317 }
318 }
319
320 /* Handle the end of an element. DATA is our local XML parser, and
321 NAME is the current element. */
322
323 static void
324 gdb_xml_end_element (void *data, const XML_Char *name)
325 {
326 struct gdb_xml_parser *parser = data;
327 struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
328 const struct gdb_xml_element *element;
329 unsigned int seen;
330
331 gdb_xml_debug (parser, _("Leaving element <%s>"), name);
332
333 for (element = scope->elements, seen = 1;
334 element != NULL && element->name != NULL;
335 element++, seen <<= 1)
336 if ((scope->seen & seen) == 0
337 && (element->flags & GDB_XML_EF_OPTIONAL) == 0)
338 gdb_xml_error (parser, _("Required element <%s> is missing"),
339 element->name);
340
341 /* Call the element processor. */
342 if (scope->element != NULL && scope->element->end_handler)
343 {
344 char *body;
345
346 if (scope->body == NULL)
347 body = "";
348 else
349 {
350 int length;
351
352 length = obstack_object_size (scope->body);
353 obstack_1grow (scope->body, '\0');
354 body = obstack_finish (scope->body);
355
356 /* Strip leading and trailing whitespace. */
357 while (length > 0 && ISSPACE (body[length-1]))
358 body[--length] = '\0';
359 while (*body && ISSPACE (*body))
360 body++;
361 }
362
363 scope->element->end_handler (parser, scope->element, parser->user_data,
364 body);
365 }
366 else if (scope->element == NULL)
367 XML_DefaultCurrent (parser->expat_parser);
368
369 /* Pop the scope level. */
370 if (scope->body)
371 {
372 obstack_free (scope->body, NULL);
373 xfree (scope->body);
374 }
375 VEC_pop (scope_level_s, parser->scopes);
376 }
377
378 /* Wrapper for gdb_xml_end_element, to prevent throwing exceptions
379 through expat. */
380
381 static void
382 gdb_xml_end_element_wrapper (void *data, const XML_Char *name)
383 {
384 struct gdb_xml_parser *parser = data;
385 volatile struct gdb_exception ex;
386
387 if (parser->error.reason < 0)
388 return;
389
390 TRY_CATCH (ex, RETURN_MASK_ALL)
391 {
392 gdb_xml_end_element (data, name);
393 }
394 if (ex.reason < 0)
395 {
396 parser->error = ex;
397 #ifdef HAVE_XML_STOPPARSER
398 XML_StopParser (parser->expat_parser, XML_FALSE);
399 #endif
400 }
401 }
402
403 /* Free a parser and all its associated state. */
404
405 static void
406 gdb_xml_cleanup (void *arg)
407 {
408 struct gdb_xml_parser *parser = arg;
409 struct scope_level *scope;
410 int ix;
411
412 XML_ParserFree (parser->expat_parser);
413
414 /* Clean up the scopes. */
415 for (ix = 0; VEC_iterate (scope_level_s, parser->scopes, ix, scope); ix++)
416 if (scope->body)
417 {
418 obstack_free (scope->body, NULL);
419 xfree (scope->body);
420 }
421 VEC_free (scope_level_s, parser->scopes);
422
423 xfree (parser);
424 }
425
426 /* Initialize and return a parser. Register a cleanup to destroy the
427 parser. */
428
429 struct gdb_xml_parser *
430 gdb_xml_create_parser_and_cleanup (const char *name,
431 const struct gdb_xml_element *elements,
432 void *user_data)
433 {
434 struct gdb_xml_parser *parser;
435 struct scope_level start_scope;
436
437 /* Initialize the parser. */
438 parser = XZALLOC (struct gdb_xml_parser);
439 parser->expat_parser = XML_ParserCreateNS (NULL, '!');
440 if (parser->expat_parser == NULL)
441 {
442 xfree (parser);
443 nomem (0);
444 }
445
446 parser->name = name;
447
448 parser->user_data = user_data;
449 XML_SetUserData (parser->expat_parser, parser);
450
451 /* Set the callbacks. */
452 XML_SetElementHandler (parser->expat_parser, gdb_xml_start_element_wrapper,
453 gdb_xml_end_element_wrapper);
454 XML_SetCharacterDataHandler (parser->expat_parser, gdb_xml_body_text);
455
456 /* Initialize the outer scope. */
457 memset (&start_scope, 0, sizeof (start_scope));
458 start_scope.elements = elements;
459 VEC_safe_push (scope_level_s, parser->scopes, &start_scope);
460
461 make_cleanup (gdb_xml_cleanup, parser);
462
463 return parser;
464 }
465
466 /* External entity handler. The only external entities we support
467 are those compiled into GDB (we do not fetch entities from the
468 target). */
469
470 static int XMLCALL
471 gdb_xml_fetch_external_entity (XML_Parser expat_parser,
472 const XML_Char *context,
473 const XML_Char *base,
474 const XML_Char *systemId,
475 const XML_Char *publicId)
476 {
477 struct gdb_xml_parser *parser = XML_GetUserData (expat_parser);
478 XML_Parser entity_parser;
479 const char *text;
480 enum XML_Status status;
481
482 if (systemId == NULL)
483 {
484 text = fetch_xml_builtin (parser->dtd_name);
485 if (text == NULL)
486 internal_error (__FILE__, __LINE__, "could not locate built-in DTD %s",
487 parser->dtd_name);
488 }
489 else
490 {
491 text = fetch_xml_builtin (systemId);
492 if (text == NULL)
493 return XML_STATUS_ERROR;
494 }
495
496 entity_parser = XML_ExternalEntityParserCreate (expat_parser, context, NULL);
497
498 /* Don't use our handlers for the contents of the DTD. Just let expat
499 process it. */
500 XML_SetElementHandler (entity_parser, NULL, NULL);
501 XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL);
502 XML_SetXmlDeclHandler (entity_parser, NULL);
503 XML_SetDefaultHandler (entity_parser, NULL);
504 XML_SetUserData (entity_parser, NULL);
505
506 status = XML_Parse (entity_parser, text, strlen (text), 1);
507
508 XML_ParserFree (entity_parser);
509 return status;
510 }
511
512 /* Associate DTD_NAME, which must be the name of a compiled-in DTD,
513 with PARSER. */
514
515 void
516 gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name)
517 {
518 enum XML_Error err;
519
520 parser->dtd_name = dtd_name;
521
522 XML_SetParamEntityParsing (parser->expat_parser,
523 XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
524 XML_SetExternalEntityRefHandler (parser->expat_parser,
525 gdb_xml_fetch_external_entity);
526
527 /* Even if no DTD is provided, use the built-in DTD anyway. */
528 err = XML_UseForeignDTD (parser->expat_parser, XML_TRUE);
529 if (err != XML_ERROR_NONE)
530 internal_error (__FILE__, __LINE__,
531 "XML_UseForeignDTD failed: %s", XML_ErrorString (err));
532 }
533
534 /* Invoke PARSER on BUFFER. BUFFER is the data to parse, which
535 should be NUL-terminated.
536
537 The return value is 0 for success or -1 for error. It may throw,
538 but only if something unexpected goes wrong during parsing; parse
539 errors will be caught, warned about, and reported as failure. */
540
541 int
542 gdb_xml_parse (struct gdb_xml_parser *parser, const char *buffer)
543 {
544 enum XML_Status status;
545 const char *error_string;
546
547 gdb_xml_debug (parser, _("Starting:\n%s"), buffer);
548
549 status = XML_Parse (parser->expat_parser, buffer, strlen (buffer), 1);
550
551 if (status == XML_STATUS_OK && parser->error.reason == 0)
552 return 0;
553
554 if (parser->error.reason == RETURN_ERROR
555 && parser->error.error == XML_PARSE_ERROR)
556 {
557 gdb_assert (parser->error.message != NULL);
558 error_string = parser->error.message;
559 }
560 else if (status == XML_STATUS_ERROR)
561 {
562 enum XML_Error err = XML_GetErrorCode (parser->expat_parser);
563 error_string = XML_ErrorString (err);
564 }
565 else
566 {
567 gdb_assert (parser->error.reason < 0);
568 throw_exception (parser->error);
569 }
570
571 if (parser->last_line != 0)
572 warning (_("while parsing %s (at line %d): %s"), parser->name,
573 parser->last_line, error_string);
574 else
575 warning (_("while parsing %s: %s"), parser->name, error_string);
576
577 return -1;
578 }
579
580 /* Parse a field VALSTR that we expect to contain an integer value.
581 The integer is returned in *VALP. The string is parsed with an
582 equivalent to strtoul.
583
584 Returns 0 for success, -1 for error. */
585
586 static int
587 xml_parse_unsigned_integer (const char *valstr, ULONGEST *valp)
588 {
589 const char *endptr;
590 ULONGEST result;
591
592 if (*valstr == '\0')
593 return -1;
594
595 result = strtoulst (valstr, &endptr, 0);
596 if (*endptr != '\0')
597 return -1;
598
599 *valp = result;
600 return 0;
601 }
602
603 /* Parse an integer string into a ULONGEST and return it, or call
604 gdb_xml_error if it could not be parsed. */
605
606 ULONGEST
607 gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value)
608 {
609 ULONGEST result;
610
611 if (xml_parse_unsigned_integer (value, &result) != 0)
612 gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value);
613
614 return result;
615 }
616
617 /* Parse an integer attribute into a ULONGEST. */
618
619 void *
620 gdb_xml_parse_attr_ulongest (struct gdb_xml_parser *parser,
621 const struct gdb_xml_attribute *attribute,
622 const char *value)
623 {
624 ULONGEST result;
625 void *ret;
626
627 if (xml_parse_unsigned_integer (value, &result) != 0)
628 gdb_xml_error (parser, _("Can't convert %s=\"%s\" to an integer"),
629 attribute->name, value);
630
631 ret = xmalloc (sizeof (result));
632 memcpy (ret, &result, sizeof (result));
633 return ret;
634 }
635
636 /* A handler_data for yes/no boolean values. */
637
638 const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
639 { "yes", 1 },
640 { "no", 0 },
641 { NULL, 0 }
642 };
643
644 /* Map NAME to VALUE. A struct gdb_xml_enum * should be saved as the
645 value of handler_data when using gdb_xml_parse_attr_enum to parse a
646 fixed list of possible strings. The list is terminated by an entry
647 with NAME == NULL. */
648
649 void *
650 gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
651 const struct gdb_xml_attribute *attribute,
652 const char *value)
653 {
654 const struct gdb_xml_enum *enums = attribute->handler_data;
655 void *ret;
656
657 for (enums = attribute->handler_data; enums->name != NULL; enums++)
658 if (strcasecmp (enums->name, value) == 0)
659 break;
660
661 if (enums->name == NULL)
662 gdb_xml_error (parser, _("Unknown attribute value %s=\"%s\""),
663 attribute->name, value);
664
665 ret = xmalloc (sizeof (enums->value));
666 memcpy (ret, &enums->value, sizeof (enums->value));
667 return ret;
668 }
669 \f
670
671 /* XInclude processing. This is done as a separate step from actually
672 parsing the document, so that we can produce a single combined XML
673 document - e.g. to hand to a front end or to simplify comparing two
674 documents. We make extensive use of XML_DefaultCurrent, to pass
675 input text directly into the output without reformatting or
676 requoting it.
677
678 We output the DOCTYPE declaration for the first document unchanged,
679 if present, and discard DOCTYPEs from included documents. Only the
680 one we pass through here is used when we feed the result back to
681 expat. The XInclude standard explicitly does not discuss
682 validation of the result; we choose to apply the same DTD applied
683 to the outermost document.
684
685 We can not simply include the external DTD subset in the document
686 as an internal subset, because <!IGNORE> and <!INCLUDE> are valid
687 only in external subsets. But if we do not pass the DTD into the
688 output at all, default values will not be filled in.
689
690 We don't pass through any <?xml> declaration because we generate
691 UTF-8, not whatever the input encoding was. */
692
693 struct xinclude_parsing_data
694 {
695 /* The obstack to build the output in. */
696 struct obstack obstack;
697
698 /* A count indicating whether we are in an element whose
699 children should not be copied to the output, and if so,
700 how deep we are nested. This is used for anything inside
701 an xi:include, and for the DTD. */
702 int skip_depth;
703
704 /* The number of <xi:include> elements currently being processed,
705 to detect loops. */
706 int include_depth;
707
708 /* A function to call to obtain additional features, and its
709 baton. */
710 xml_fetch_another fetcher;
711 void *fetcher_baton;
712 };
713
714 static void
715 xinclude_start_include (struct gdb_xml_parser *parser,
716 const struct gdb_xml_element *element,
717 void *user_data, VEC(gdb_xml_value_s) *attributes)
718 {
719 struct xinclude_parsing_data *data = user_data;
720 char *href = VEC_index (gdb_xml_value_s, attributes, 0)->value;
721 struct cleanup *back_to;
722 char *text, *output;
723
724 gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
725
726 if (data->include_depth > MAX_XINCLUDE_DEPTH)
727 gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
728 MAX_XINCLUDE_DEPTH);
729
730 text = data->fetcher (href, data->fetcher_baton);
731 if (text == NULL)
732 gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
733 back_to = make_cleanup (xfree, text);
734
735 output = xml_process_xincludes (parser->name, text, data->fetcher,
736 data->fetcher_baton,
737 data->include_depth + 1);
738 if (output == NULL)
739 gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
740
741 obstack_grow (&data->obstack, output, strlen (output));
742 xfree (output);
743
744 do_cleanups (back_to);
745
746 data->skip_depth++;
747 }
748
749 static void
750 xinclude_end_include (struct gdb_xml_parser *parser,
751 const struct gdb_xml_element *element,
752 void *user_data, const char *body_text)
753 {
754 struct xinclude_parsing_data *data = user_data;
755
756 data->skip_depth--;
757 }
758
759 static void XMLCALL
760 xml_xinclude_default (void *data_, const XML_Char *s, int len)
761 {
762 struct gdb_xml_parser *parser = data_;
763 struct xinclude_parsing_data *data = parser->user_data;
764
765 /* If we are inside of e.g. xi:include or the DTD, don't save this
766 string. */
767 if (data->skip_depth)
768 return;
769
770 /* Otherwise just add it to the end of the document we're building
771 up. */
772 obstack_grow (&data->obstack, s, len);
773 }
774
775 static void XMLCALL
776 xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
777 const XML_Char *sysid, const XML_Char *pubid,
778 int has_internal_subset)
779 {
780 struct gdb_xml_parser *parser = data_;
781 struct xinclude_parsing_data *data = parser->user_data;
782
783 /* Don't print out the doctype, or the contents of the DTD internal
784 subset, if any. */
785 data->skip_depth++;
786 }
787
788 static void XMLCALL
789 xml_xinclude_end_doctype (void *data_)
790 {
791 struct gdb_xml_parser *parser = data_;
792 struct xinclude_parsing_data *data = parser->user_data;
793
794 data->skip_depth--;
795 }
796
797 static void XMLCALL
798 xml_xinclude_xml_decl (void *data_, const XML_Char *version,
799 const XML_Char *encoding, int standalone)
800 {
801 /* Do nothing - this function prevents the default handler from
802 being called, thus suppressing the XML declaration from the
803 output. */
804 }
805
806 static void
807 xml_xinclude_cleanup (void *data_)
808 {
809 struct xinclude_parsing_data *data = data_;
810
811 obstack_free (&data->obstack, NULL);
812 xfree (data);
813 }
814
815 const struct gdb_xml_attribute xinclude_attributes[] = {
816 { "href", GDB_XML_AF_NONE, NULL, NULL },
817 { NULL, GDB_XML_AF_NONE, NULL, NULL }
818 };
819
820 const struct gdb_xml_element xinclude_elements[] = {
821 { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
822 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
823 xinclude_start_include, xinclude_end_include },
824 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
825 };
826
827 /* The main entry point for <xi:include> processing. */
828
829 char *
830 xml_process_xincludes (const char *name, const char *text,
831 xml_fetch_another fetcher, void *fetcher_baton,
832 int depth)
833 {
834 struct gdb_xml_parser *parser;
835 struct xinclude_parsing_data *data;
836 struct cleanup *back_to;
837 char *result = NULL;
838
839 data = XZALLOC (struct xinclude_parsing_data);
840 obstack_init (&data->obstack);
841 back_to = make_cleanup (xml_xinclude_cleanup, data);
842
843 parser = gdb_xml_create_parser_and_cleanup (name, xinclude_elements, data);
844 parser->is_xinclude = 1;
845
846 data->include_depth = depth;
847 data->fetcher = fetcher;
848 data->fetcher_baton = fetcher_baton;
849
850 XML_SetCharacterDataHandler (parser->expat_parser, NULL);
851 XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
852
853 /* Always discard the XML version declarations; the only important
854 thing this provides is encoding, and our result will have been
855 converted to UTF-8. */
856 XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
857
858 if (depth > 0)
859 /* Discard the doctype for included documents. */
860 XML_SetDoctypeDeclHandler (parser->expat_parser,
861 xml_xinclude_start_doctype,
862 xml_xinclude_end_doctype);
863
864 gdb_xml_use_dtd (parser, "xinclude.dtd");
865
866 if (gdb_xml_parse (parser, text) == 0)
867 {
868 obstack_1grow (&data->obstack, '\0');
869 result = xstrdup (obstack_finish (&data->obstack));
870
871 if (depth == 0)
872 gdb_xml_debug (parser, _("XInclude processing succeeded."));
873 }
874 else
875 result = NULL;
876
877 do_cleanups (back_to);
878 return result;
879 }
880 #endif /* HAVE_LIBEXPAT */
881 \f
882
883 /* Return an XML document which was compiled into GDB, from
884 the given FILENAME, or NULL if the file was not compiled in. */
885
886 const char *
887 fetch_xml_builtin (const char *filename)
888 {
889 const char *(*p)[2];
890
891 for (p = xml_builtin; (*p)[0]; p++)
892 if (strcmp ((*p)[0], filename) == 0)
893 return (*p)[1];
894
895 return NULL;
896 }
897
898 /* A to_xfer_partial helper function which reads XML files which were
899 compiled into GDB. The target may call this function from its own
900 to_xfer_partial handler, after converting object and annex to the
901 appropriate filename. */
902
903 LONGEST
904 xml_builtin_xfer_partial (const char *filename,
905 gdb_byte *readbuf, const gdb_byte *writebuf,
906 ULONGEST offset, LONGEST len)
907 {
908 const char *buf;
909 LONGEST len_avail;
910
911 gdb_assert (readbuf != NULL && writebuf == NULL);
912 gdb_assert (filename != NULL);
913
914 buf = fetch_xml_builtin (filename);
915 if (buf == NULL)
916 return -1;
917
918 len_avail = strlen (buf);
919 if (offset >= len_avail)
920 return 0;
921
922 if (len > len_avail - offset)
923 len = len_avail - offset;
924 memcpy (readbuf, buf + offset, len);
925 return len;
926 }
927 \f
928
929 static void
930 show_debug_xml (struct ui_file *file, int from_tty,
931 struct cmd_list_element *c, const char *value)
932 {
933 fprintf_filtered (file, _("XML debugging is %s.\n"), value);
934 }
935
936 /* Return a malloc allocated string with special characters from TEXT
937 replaced by entity references. */
938
939 char *
940 xml_escape_text (const char *text)
941 {
942 char *result;
943 int i, special;
944
945 /* Compute the length of the result. */
946 for (i = 0, special = 0; text[i] != '\0'; i++)
947 switch (text[i])
948 {
949 case '\'':
950 case '\"':
951 special += 5;
952 break;
953 case '&':
954 special += 4;
955 break;
956 case '<':
957 case '>':
958 special += 3;
959 break;
960 default:
961 break;
962 }
963
964 /* Expand the result. */
965 result = xmalloc (i + special + 1);
966 for (i = 0, special = 0; text[i] != '\0'; i++)
967 switch (text[i])
968 {
969 case '\'':
970 strcpy (result + i + special, "&apos;");
971 special += 5;
972 break;
973 case '\"':
974 strcpy (result + i + special, "&quot;");
975 special += 5;
976 break;
977 case '&':
978 strcpy (result + i + special, "&amp;");
979 special += 4;
980 break;
981 case '<':
982 strcpy (result + i + special, "&lt;");
983 special += 3;
984 break;
985 case '>':
986 strcpy (result + i + special, "&gt;");
987 special += 3;
988 break;
989 default:
990 result[i + special] = text[i];
991 break;
992 }
993 result[i + special] = '\0';
994
995 return result;
996 }
997
998 void
999 obstack_xml_printf (struct obstack *obstack, const char *format, ...)
1000 {
1001 va_list ap;
1002 const char *f;
1003 const char *prev;
1004 int percent = 0;
1005
1006 va_start (ap, format);
1007
1008 prev = format;
1009 for (f = format; *f; f++)
1010 {
1011 if (percent)
1012 {
1013 switch (*f)
1014 {
1015 case 's':
1016 {
1017 char *p;
1018 char *a = va_arg (ap, char *);
1019 obstack_grow (obstack, prev, f - prev - 1);
1020 p = xml_escape_text (a);
1021 obstack_grow_str (obstack, p);
1022 xfree (p);
1023 prev = f + 1;
1024 }
1025 break;
1026 }
1027 percent = 0;
1028 }
1029 else if (*f == '%')
1030 percent = 1;
1031 }
1032
1033 obstack_grow_str (obstack, prev);
1034 va_end (ap);
1035 }
1036
1037 char *
1038 xml_fetch_content_from_file (const char *filename, void *baton)
1039 {
1040 const char *dirname = baton;
1041 FILE *file;
1042 struct cleanup *back_to;
1043 char *text;
1044 size_t len, offset;
1045
1046 if (dirname && *dirname)
1047 {
1048 char *fullname = concat (dirname, "/", filename, (char *) NULL);
1049 if (fullname == NULL)
1050 nomem (0);
1051 file = fopen (fullname, FOPEN_RT);
1052 xfree (fullname);
1053 }
1054 else
1055 file = fopen (filename, FOPEN_RT);
1056
1057 if (file == NULL)
1058 return NULL;
1059
1060 back_to = make_cleanup_fclose (file);
1061
1062 /* Read in the whole file, one chunk at a time. */
1063 len = 4096;
1064 offset = 0;
1065 text = xmalloc (len);
1066 make_cleanup (free_current_contents, &text);
1067 while (1)
1068 {
1069 size_t bytes_read;
1070
1071 /* Continue reading where the last read left off. Leave at least
1072 one byte so that we can NUL-terminate the result. */
1073 bytes_read = fread (text + offset, 1, len - offset - 1, file);
1074 if (ferror (file))
1075 {
1076 warning (_("Read error from \"%s\""), filename);
1077 do_cleanups (back_to);
1078 return NULL;
1079 }
1080
1081 offset += bytes_read;
1082
1083 if (feof (file))
1084 break;
1085
1086 len = len * 2;
1087 text = xrealloc (text, len);
1088 }
1089
1090 fclose (file);
1091 discard_cleanups (back_to);
1092
1093 text[offset] = '\0';
1094 return text;
1095 }
1096
1097 void _initialize_xml_support (void);
1098
1099 void
1100 _initialize_xml_support (void)
1101 {
1102 add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
1103 _("Set XML parser debugging."),
1104 _("Show XML parser debugging."),
1105 _("When set, debugging messages for XML parsers "
1106 "are displayed."),
1107 NULL, show_debug_xml,
1108 &setdebuglist, &showdebuglist);
1109 }
This page took 0.0516 seconds and 4 git commands to generate.