OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [gdb/] [xml-support.c] - Blame information for rev 850

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

Line No. Rev Author Line
1 330 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
 
564
      error_string = XML_ErrorString (err);
565
    }
566
  else
567
    {
568
      gdb_assert (parser->error.reason < 0);
569
      throw_exception (parser->error);
570
    }
571
 
572
  if (parser->last_line != 0)
573
    warning (_("while parsing %s (at line %d): %s"), parser->name,
574
             parser->last_line, error_string);
575
  else
576
    warning (_("while parsing %s: %s"), parser->name, error_string);
577
 
578
  return -1;
579
}
580
 
581
/* Parse a field VALSTR that we expect to contain an integer value.
582
   The integer is returned in *VALP.  The string is parsed with an
583
   equivalent to strtoul.
584
 
585
   Returns 0 for success, -1 for error.  */
586
 
587
static int
588
xml_parse_unsigned_integer (const char *valstr, ULONGEST *valp)
589
{
590
  const char *endptr;
591
  ULONGEST result;
592
 
593
  if (*valstr == '\0')
594
    return -1;
595
 
596
  result = strtoulst (valstr, &endptr, 0);
597
  if (*endptr != '\0')
598
    return -1;
599
 
600
  *valp = result;
601
  return 0;
602
}
603
 
604
/* Parse an integer string into a ULONGEST and return it, or call
605
   gdb_xml_error if it could not be parsed.  */
606
 
607
ULONGEST
608
gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value)
609
{
610
  ULONGEST result;
611
 
612
  if (xml_parse_unsigned_integer (value, &result) != 0)
613
    gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value);
614
 
615
  return result;
616
}
617
 
618
/* Parse an integer attribute into a ULONGEST.  */
619
 
620
void *
621
gdb_xml_parse_attr_ulongest (struct gdb_xml_parser *parser,
622
                             const struct gdb_xml_attribute *attribute,
623
                             const char *value)
624
{
625
  ULONGEST result;
626
  void *ret;
627
 
628
  if (xml_parse_unsigned_integer (value, &result) != 0)
629
    gdb_xml_error (parser, _("Can't convert %s=\"%s\" to an integer"),
630
                   attribute->name, value);
631
 
632
  ret = xmalloc (sizeof (result));
633
  memcpy (ret, &result, sizeof (result));
634
  return ret;
635
}
636
 
637
/* A handler_data for yes/no boolean values.  */
638
 
639
const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
640
  { "yes", 1 },
641
  { "no", 0 },
642
  { NULL, 0 }
643
};
644
 
645
/* Map NAME to VALUE.  A struct gdb_xml_enum * should be saved as the
646
   value of handler_data when using gdb_xml_parse_attr_enum to parse a
647
   fixed list of possible strings.  The list is terminated by an entry
648
   with NAME == NULL.  */
649
 
650
void *
651
gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
652
                         const struct gdb_xml_attribute *attribute,
653
                         const char *value)
654
{
655
  const struct gdb_xml_enum *enums = attribute->handler_data;
656
  void *ret;
657
 
658
  for (enums = attribute->handler_data; enums->name != NULL; enums++)
659
    if (strcasecmp (enums->name, value) == 0)
660
      break;
661
 
662
  if (enums->name == NULL)
663
    gdb_xml_error (parser, _("Unknown attribute value %s=\"%s\""),
664
                 attribute->name, value);
665
 
666
  ret = xmalloc (sizeof (enums->value));
667
  memcpy (ret, &enums->value, sizeof (enums->value));
668
  return ret;
669
}
670
 
671
 
672
/* XInclude processing.  This is done as a separate step from actually
673
   parsing the document, so that we can produce a single combined XML
674
   document - e.g. to hand to a front end or to simplify comparing two
675
   documents.  We make extensive use of XML_DefaultCurrent, to pass
676
   input text directly into the output without reformatting or
677
   requoting it.
678
 
679
   We output the DOCTYPE declaration for the first document unchanged,
680
   if present, and discard DOCTYPEs from included documents.  Only the
681
   one we pass through here is used when we feed the result back to
682
   expat.  The XInclude standard explicitly does not discuss
683
   validation of the result; we choose to apply the same DTD applied
684
   to the outermost document.
685
 
686
   We can not simply include the external DTD subset in the document
687
   as an internal subset, because <!IGNORE> and <!INCLUDE> are valid
688
   only in external subsets.  But if we do not pass the DTD into the
689
   output at all, default values will not be filled in.
690
 
691
   We don't pass through any <?xml> declaration because we generate
692
   UTF-8, not whatever the input encoding was.  */
693
 
694
struct xinclude_parsing_data
695
{
696
  /* The obstack to build the output in.  */
697
  struct obstack obstack;
698
 
699
  /* A count indicating whether we are in an element whose
700
     children should not be copied to the output, and if so,
701
     how deep we are nested.  This is used for anything inside
702
     an xi:include, and for the DTD.  */
703
  int skip_depth;
704
 
705
  /* The number of <xi:include> elements currently being processed,
706
     to detect loops.  */
707
  int include_depth;
708
 
709
  /* A function to call to obtain additional features, and its
710
     baton.  */
711
  xml_fetch_another fetcher;
712
  void *fetcher_baton;
713
};
714
 
715
static void
716
xinclude_start_include (struct gdb_xml_parser *parser,
717
                        const struct gdb_xml_element *element,
718
                        void *user_data, VEC(gdb_xml_value_s) *attributes)
719
{
720
  struct xinclude_parsing_data *data = user_data;
721
  char *href = VEC_index (gdb_xml_value_s, attributes, 0)->value;
722
  struct cleanup *back_to;
723
  char *text, *output;
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
  struct gdb_xml_parser *parser;
836
  struct xinclude_parsing_data *data;
837
  struct cleanup *back_to;
838
  char *result = NULL;
839
 
840
  data = XZALLOC (struct xinclude_parsing_data);
841
  obstack_init (&data->obstack);
842
  back_to = make_cleanup (xml_xinclude_cleanup, data);
843
 
844
  parser = gdb_xml_create_parser_and_cleanup (name, xinclude_elements, data);
845
  parser->is_xinclude = 1;
846
 
847
  data->include_depth = depth;
848
  data->fetcher = fetcher;
849
  data->fetcher_baton = fetcher_baton;
850
 
851
  XML_SetCharacterDataHandler (parser->expat_parser, NULL);
852
  XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
853
 
854
  /* Always discard the XML version declarations; the only important
855
     thing this provides is encoding, and our result will have been
856
     converted to UTF-8.  */
857
  XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
858
 
859
  if (depth > 0)
860
    /* Discard the doctype for included documents.  */
861
    XML_SetDoctypeDeclHandler (parser->expat_parser,
862
                               xml_xinclude_start_doctype,
863
                               xml_xinclude_end_doctype);
864
 
865
  gdb_xml_use_dtd (parser, "xinclude.dtd");
866
 
867
  if (gdb_xml_parse (parser, text) == 0)
868
    {
869
      obstack_1grow (&data->obstack, '\0');
870
      result = xstrdup (obstack_finish (&data->obstack));
871
 
872
      if (depth == 0)
873
        gdb_xml_debug (parser, _("XInclude processing succeeded."));
874
    }
875
  else
876
    result = NULL;
877
 
878
  do_cleanups (back_to);
879
  return result;
880
}
881
#endif /* HAVE_LIBEXPAT */
882
 
883
 
884
/* Return an XML document which was compiled into GDB, from
885
   the given FILENAME, or NULL if the file was not compiled in.  */
886
 
887
const char *
888
fetch_xml_builtin (const char *filename)
889
{
890
  const char *(*p)[2];
891
 
892
  for (p = xml_builtin; (*p)[0]; p++)
893
    if (strcmp ((*p)[0], filename) == 0)
894
      return (*p)[1];
895
 
896
  return NULL;
897
}
898
 
899
/* A to_xfer_partial helper function which reads XML files which were
900
   compiled into GDB.  The target may call this function from its own
901
   to_xfer_partial handler, after converting object and annex to the
902
   appropriate filename.  */
903
 
904
LONGEST
905
xml_builtin_xfer_partial (const char *filename,
906
                          gdb_byte *readbuf, const gdb_byte *writebuf,
907
                          ULONGEST offset, LONGEST len)
908
{
909
  const char *buf;
910
  LONGEST len_avail;
911
 
912
  gdb_assert (readbuf != NULL && writebuf == NULL);
913
  gdb_assert (filename != NULL);
914
 
915
  buf = fetch_xml_builtin (filename);
916
  if (buf == NULL)
917
    return -1;
918
 
919
  len_avail = strlen (buf);
920
  if (offset >= len_avail)
921
    return 0;
922
 
923
  if (len > len_avail - offset)
924
    len = len_avail - offset;
925
  memcpy (readbuf, buf + offset, len);
926
  return len;
927
}
928
 
929
 
930
static void
931
show_debug_xml (struct ui_file *file, int from_tty,
932
                struct cmd_list_element *c, const char *value)
933
{
934
  fprintf_filtered (file, _("XML debugging is %s.\n"), value);
935
}
936
 
937
/* Return a malloc allocated string with special characters from TEXT
938
   replaced by entity references.  */
939
 
940
char *
941
xml_escape_text (const char *text)
942
{
943
  char *result;
944
  int i, special;
945
 
946
  /* Compute the length of the result.  */
947
  for (i = 0, special = 0; text[i] != '\0'; i++)
948
    switch (text[i])
949
      {
950
      case '\'':
951
      case '\"':
952
        special += 5;
953
        break;
954
      case '&':
955
        special += 4;
956
        break;
957
      case '<':
958
      case '>':
959
        special += 3;
960
        break;
961
      default:
962
        break;
963
      }
964
 
965
  /* Expand the result.  */
966
  result = xmalloc (i + special + 1);
967
  for (i = 0, special = 0; text[i] != '\0'; i++)
968
    switch (text[i])
969
      {
970
      case '\'':
971
        strcpy (result + i + special, "&apos;");
972
        special += 5;
973
        break;
974
      case '\"':
975
        strcpy (result + i + special, "&quot;");
976
        special += 5;
977
        break;
978
      case '&':
979
        strcpy (result + i + special, "&amp;");
980
        special += 4;
981
        break;
982
      case '<':
983
        strcpy (result + i + special, "&lt;");
984
        special += 3;
985
        break;
986
      case '>':
987
        strcpy (result + i + special, "&gt;");
988
        special += 3;
989
        break;
990
      default:
991
        result[i + special] = text[i];
992
        break;
993
      }
994
  result[i + special] = '\0';
995
 
996
  return result;
997
}
998
 
999
void
1000
obstack_xml_printf (struct obstack *obstack, const char *format, ...)
1001
{
1002
  va_list ap;
1003
  const char *f;
1004
  const char *prev;
1005
  int percent = 0;
1006
 
1007
  va_start (ap, format);
1008
 
1009
  prev = format;
1010
  for (f = format; *f; f++)
1011
    {
1012
      if (percent)
1013
       {
1014
         switch (*f)
1015
           {
1016
           case 's':
1017
             {
1018
               char *p;
1019
               char *a = va_arg (ap, char *);
1020
 
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
 
1052
      if (fullname == NULL)
1053
        nomem (0);
1054
      file = fopen (fullname, FOPEN_RT);
1055
      xfree (fullname);
1056
    }
1057
  else
1058
    file = fopen (filename, FOPEN_RT);
1059
 
1060
  if (file == NULL)
1061
    return NULL;
1062
 
1063
  back_to = make_cleanup_fclose (file);
1064
 
1065
  /* Read in the whole file, one chunk at a time.  */
1066
  len = 4096;
1067
  offset = 0;
1068
  text = xmalloc (len);
1069
  make_cleanup (free_current_contents, &text);
1070
  while (1)
1071
    {
1072
      size_t bytes_read;
1073
 
1074
      /* Continue reading where the last read left off.  Leave at least
1075
         one byte so that we can NUL-terminate the result.  */
1076
      bytes_read = fread (text + offset, 1, len - offset - 1, file);
1077
      if (ferror (file))
1078
        {
1079
          warning (_("Read error from \"%s\""), filename);
1080
          do_cleanups (back_to);
1081
          return NULL;
1082
        }
1083
 
1084
      offset += bytes_read;
1085
 
1086
      if (feof (file))
1087
        break;
1088
 
1089
      len = len * 2;
1090
      text = xrealloc (text, len);
1091
    }
1092
 
1093
  fclose (file);
1094
  discard_cleanups (back_to);
1095
 
1096
  text[offset] = '\0';
1097
  return text;
1098
}
1099
 
1100
void _initialize_xml_support (void);
1101
 
1102
void
1103
_initialize_xml_support (void)
1104
{
1105
  add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
1106
                           _("Set XML parser debugging."),
1107
                           _("Show XML parser debugging."),
1108
                           _("When set, debugging messages for XML parsers "
1109
                             "are displayed."),
1110
                           NULL, show_debug_xml,
1111
                           &setdebuglist, &showdebuglist);
1112
}

powered by: WebSVN 2.1.0

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