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