OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [gdb/] [xml-support.c] - Blame information for rev 634

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* 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
 
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
  int ret;
724
 
725
  gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
726
 
727
  if (data->include_depth > MAX_XINCLUDE_DEPTH)
728
    gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
729
                   MAX_XINCLUDE_DEPTH);
730
 
731
  text = data->fetcher (href, data->fetcher_baton);
732
  if (text == NULL)
733
    gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
734
  back_to = make_cleanup (xfree, text);
735
 
736
  output = xml_process_xincludes (parser->name, text, data->fetcher,
737
                                  data->fetcher_baton,
738
                                  data->include_depth + 1);
739
  if (output == NULL)
740
    gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
741
 
742
  obstack_grow (&data->obstack, output, strlen (output));
743
  xfree (output);
744
 
745
  do_cleanups (back_to);
746
 
747
  data->skip_depth++;
748
}
749
 
750
static void
751
xinclude_end_include (struct gdb_xml_parser *parser,
752
                      const struct gdb_xml_element *element,
753
                      void *user_data, const char *body_text)
754
{
755
  struct xinclude_parsing_data *data = user_data;
756
 
757
  data->skip_depth--;
758
}
759
 
760
static void XMLCALL
761
xml_xinclude_default (void *data_, const XML_Char *s, int len)
762
{
763
  struct gdb_xml_parser *parser = data_;
764
  struct xinclude_parsing_data *data = parser->user_data;
765
 
766
  /* If we are inside of e.g. xi:include or the DTD, don't save this
767
     string.  */
768
  if (data->skip_depth)
769
    return;
770
 
771
  /* Otherwise just add it to the end of the document we're building
772
     up.  */
773
  obstack_grow (&data->obstack, s, len);
774
}
775
 
776
static void XMLCALL
777
xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
778
                            const XML_Char *sysid, const XML_Char *pubid,
779
                            int has_internal_subset)
780
{
781
  struct gdb_xml_parser *parser = data_;
782
  struct xinclude_parsing_data *data = parser->user_data;
783
 
784
  /* Don't print out the doctype, or the contents of the DTD internal
785
     subset, if any.  */
786
  data->skip_depth++;
787
}
788
 
789
static void XMLCALL
790
xml_xinclude_end_doctype (void *data_)
791
{
792
  struct gdb_xml_parser *parser = data_;
793
  struct xinclude_parsing_data *data = parser->user_data;
794
 
795
  data->skip_depth--;
796
}
797
 
798
static void XMLCALL
799
xml_xinclude_xml_decl (void *data_, const XML_Char *version,
800
                       const XML_Char *encoding, int standalone)
801
{
802
  /* Do nothing - this function prevents the default handler from
803
     being called, thus suppressing the XML declaration from the
804
     output.  */
805
}
806
 
807
static void
808
xml_xinclude_cleanup (void *data_)
809
{
810
  struct xinclude_parsing_data *data = data_;
811
 
812
  obstack_free (&data->obstack, NULL);
813
  xfree (data);
814
}
815
 
816
const struct gdb_xml_attribute xinclude_attributes[] = {
817
  { "href", GDB_XML_AF_NONE, NULL, NULL },
818
  { NULL, GDB_XML_AF_NONE, NULL, NULL }
819
};
820
 
821
const struct gdb_xml_element xinclude_elements[] = {
822
  { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
823
    GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
824
    xinclude_start_include, xinclude_end_include },
825
  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
826
};
827
 
828
/* The main entry point for <xi:include> processing.  */
829
 
830
char *
831
xml_process_xincludes (const char *name, const char *text,
832
                       xml_fetch_another fetcher, void *fetcher_baton,
833
                       int depth)
834
{
835
  enum XML_Error err;
836
  struct gdb_xml_parser *parser;
837
  struct xinclude_parsing_data *data;
838
  struct cleanup *back_to;
839
  char *result = NULL;
840
 
841
  data = XZALLOC (struct xinclude_parsing_data);
842
  obstack_init (&data->obstack);
843
  back_to = make_cleanup (xml_xinclude_cleanup, data);
844
 
845
  parser = gdb_xml_create_parser_and_cleanup (name, xinclude_elements, data);
846
  parser->is_xinclude = 1;
847
 
848
  data->include_depth = depth;
849
  data->fetcher = fetcher;
850
  data->fetcher_baton = fetcher_baton;
851
 
852
  XML_SetCharacterDataHandler (parser->expat_parser, NULL);
853
  XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
854
 
855
  /* Always discard the XML version declarations; the only important
856
     thing this provides is encoding, and our result will have been
857
     converted to UTF-8.  */
858
  XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
859
 
860
  if (depth > 0)
861
    /* Discard the doctype for included documents.  */
862
    XML_SetDoctypeDeclHandler (parser->expat_parser,
863
                               xml_xinclude_start_doctype,
864
                               xml_xinclude_end_doctype);
865
 
866
  gdb_xml_use_dtd (parser, "xinclude.dtd");
867
 
868
  if (gdb_xml_parse (parser, text) == 0)
869
    {
870
      obstack_1grow (&data->obstack, '\0');
871
      result = xstrdup (obstack_finish (&data->obstack));
872
 
873
      if (depth == 0)
874
        gdb_xml_debug (parser, _("XInclude processing succeeded."));
875
    }
876
  else
877
    result = NULL;
878
 
879
  do_cleanups (back_to);
880
  return result;
881
}
882
#endif /* HAVE_LIBEXPAT */
883
 
884
 
885
/* Return an XML document which was compiled into GDB, from
886
   the given FILENAME, or NULL if the file was not compiled in.  */
887
 
888
const char *
889
fetch_xml_builtin (const char *filename)
890
{
891
  const char *(*p)[2];
892
 
893
  for (p = xml_builtin; (*p)[0]; p++)
894
    if (strcmp ((*p)[0], filename) == 0)
895
      return (*p)[1];
896
 
897
  return NULL;
898
}
899
 
900
/* A to_xfer_partial helper function which reads XML files which were
901
   compiled into GDB.  The target may call this function from its own
902
   to_xfer_partial handler, after converting object and annex to the
903
   appropriate filename.  */
904
 
905
LONGEST
906
xml_builtin_xfer_partial (const char *filename,
907
                          gdb_byte *readbuf, const gdb_byte *writebuf,
908
                          ULONGEST offset, LONGEST len)
909
{
910
  const char *buf;
911
  LONGEST len_avail;
912
 
913
  gdb_assert (readbuf != NULL && writebuf == NULL);
914
  gdb_assert (filename != NULL);
915
 
916
  buf = fetch_xml_builtin (filename);
917
  if (buf == NULL)
918
    return -1;
919
 
920
  len_avail = strlen (buf);
921
  if (offset >= len_avail)
922
    return 0;
923
 
924
  if (len > len_avail - offset)
925
    len = len_avail - offset;
926
  memcpy (readbuf, buf + offset, len);
927
  return len;
928
}
929
 
930
 
931
static void
932
show_debug_xml (struct ui_file *file, int from_tty,
933
                struct cmd_list_element *c, const char *value)
934
{
935
  fprintf_filtered (file, _("XML debugging is %s.\n"), value);
936
}
937
 
938
/* Return a malloc allocated string with special characters from TEXT
939
   replaced by entity references.  */
940
 
941
char *
942
xml_escape_text (const char *text)
943
{
944
  char *result;
945
  int i, special;
946
 
947
  /* Compute the length of the result.  */
948
  for (i = 0, special = 0; text[i] != '\0'; i++)
949
    switch (text[i])
950
      {
951
      case '\'':
952
      case '\"':
953
        special += 5;
954
        break;
955
      case '&':
956
        special += 4;
957
        break;
958
      case '<':
959
      case '>':
960
        special += 3;
961
        break;
962
      default:
963
        break;
964
      }
965
 
966
  /* Expand the result.  */
967
  result = xmalloc (i + special + 1);
968
  for (i = 0, special = 0; text[i] != '\0'; i++)
969
    switch (text[i])
970
      {
971
      case '\'':
972
        strcpy (result + i + special, "&apos;");
973
        special += 5;
974
        break;
975
      case '\"':
976
        strcpy (result + i + special, "&quot;");
977
        special += 5;
978
        break;
979
      case '&':
980
        strcpy (result + i + special, "&amp;");
981
        special += 4;
982
        break;
983
      case '<':
984
        strcpy (result + i + special, "&lt;");
985
        special += 3;
986
        break;
987
      case '>':
988
        strcpy (result + i + special, "&gt;");
989
        special += 3;
990
        break;
991
      default:
992
        result[i + special] = text[i];
993
        break;
994
      }
995
  result[i + special] = '\0';
996
 
997
  return result;
998
}
999
 
1000
void
1001
obstack_xml_printf (struct obstack *obstack, const char *format, ...)
1002
{
1003
  va_list ap;
1004
  const char *f;
1005
  const char *prev;
1006
  int percent = 0;
1007
 
1008
  va_start (ap, format);
1009
 
1010
  prev = format;
1011
  for (f = format; *f; f++)
1012
    {
1013
      if (percent)
1014
       {
1015
         switch (*f)
1016
           {
1017
           case 's':
1018
             {
1019
               char *p;
1020
               char *a = va_arg (ap, char *);
1021
               obstack_grow (obstack, prev, f - prev - 1);
1022
               p = xml_escape_text (a);
1023
               obstack_grow_str (obstack, p);
1024
               xfree (p);
1025
               prev = f + 1;
1026
             }
1027
             break;
1028
           }
1029
         percent = 0;
1030
       }
1031
      else if (*f == '%')
1032
       percent = 1;
1033
    }
1034
 
1035
  obstack_grow_str (obstack, prev);
1036
  va_end (ap);
1037
}
1038
 
1039
char *
1040
xml_fetch_content_from_file (const char *filename, void *baton)
1041
{
1042
  const char *dirname = baton;
1043
  FILE *file;
1044
  struct cleanup *back_to;
1045
  char *text;
1046
  size_t len, offset;
1047
 
1048
  if (dirname && *dirname)
1049
    {
1050
      char *fullname = concat (dirname, "/", filename, (char *) NULL);
1051
      if (fullname == NULL)
1052
        nomem (0);
1053
      file = fopen (fullname, FOPEN_RT);
1054
      xfree (fullname);
1055
    }
1056
  else
1057
    file = fopen (filename, FOPEN_RT);
1058
 
1059
  if (file == NULL)
1060
    return NULL;
1061
 
1062
  back_to = make_cleanup_fclose (file);
1063
 
1064
  /* Read in the whole file, one chunk at a time.  */
1065
  len = 4096;
1066
  offset = 0;
1067
  text = xmalloc (len);
1068
  make_cleanup (free_current_contents, &text);
1069
  while (1)
1070
    {
1071
      size_t bytes_read;
1072
 
1073
      /* Continue reading where the last read left off.  Leave at least
1074
         one byte so that we can NUL-terminate the result.  */
1075
      bytes_read = fread (text + offset, 1, len - offset - 1, file);
1076
      if (ferror (file))
1077
        {
1078
          warning (_("Read error from \"%s\""), filename);
1079
          do_cleanups (back_to);
1080
          return NULL;
1081
        }
1082
 
1083
      offset += bytes_read;
1084
 
1085
      if (feof (file))
1086
        break;
1087
 
1088
      len = len * 2;
1089
      text = xrealloc (text, len);
1090
    }
1091
 
1092
  fclose (file);
1093
  discard_cleanups (back_to);
1094
 
1095
  text[offset] = '\0';
1096
  return text;
1097
}
1098
 
1099
void _initialize_xml_support (void);
1100
 
1101
void
1102
_initialize_xml_support (void)
1103
{
1104
  add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
1105
                           _("Set XML parser debugging."),
1106
                           _("Show XML parser debugging."),
1107
                           _("When set, debugging messages for XML parsers "
1108
                             "are displayed."),
1109
                           NULL, show_debug_xml,
1110
                           &setdebuglist, &showdebuglist);
1111
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.