Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/libxml2/debugXML.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * debugXML.c : This is a set of routines used for debugging the tree
3
 *              produced by the XML parser.
4
 *
5
 * See Copyright for the status of this software.
6
 *
7
 * Daniel Veillard <daniel@veillard.com>
8
 */
9
10
#define IN_LIBXML
11
#include "libxml.h"
12
#ifdef LIBXML_DEBUG_ENABLED
13
14
#include <string.h>
15
#include <stdlib.h>
16
17
#include <libxml/debugXML.h>
18
#include <libxml/xmlmemory.h>
19
#include <libxml/tree.h>
20
#include <libxml/parser.h>
21
#include <libxml/parserInternals.h>
22
#include <libxml/HTMLtree.h>
23
#include <libxml/HTMLparser.h>
24
#include <libxml/xmlerror.h>
25
26
#include "private/error.h"
27
28
0
#define DUMP_TEXT_TYPE 1
29
30
typedef struct _xmlDebugCtxt xmlDebugCtxt;
31
typedef xmlDebugCtxt *xmlDebugCtxtPtr;
32
struct _xmlDebugCtxt {
33
    FILE *output;               /* the output file */
34
    char shift[101];            /* used for indenting */
35
    int depth;                  /* current depth */
36
    xmlDocPtr doc;              /* current document */
37
    xmlNodePtr node;    /* current node */
38
    xmlDictPtr dict;    /* the doc dictionary */
39
    int check;                  /* do just checkings */
40
    int errors;                 /* number of errors found */
41
    int nodict;     /* if the document has no dictionary */
42
    int options;    /* options */
43
};
44
45
static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
46
47
static void
48
xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt)
49
0
{
50
0
    int i;
51
52
0
    ctxt->depth = 0;
53
0
    ctxt->check = 0;
54
0
    ctxt->errors = 0;
55
0
    ctxt->output = stdout;
56
0
    ctxt->doc = NULL;
57
0
    ctxt->node = NULL;
58
0
    ctxt->dict = NULL;
59
0
    ctxt->nodict = 0;
60
0
    ctxt->options = 0;
61
0
    for (i = 0; i < 100; i++)
62
0
        ctxt->shift[i] = ' ';
63
0
    ctxt->shift[100] = 0;
64
0
}
65
66
static void
67
xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED)
68
0
{
69
 /* remove the ATTRIBUTE_UNUSED when this is added */
70
0
}
71
72
/**
73
 * xmlNsCheckScope:
74
 * @node: the node
75
 * @ns: the namespace node
76
 *
77
 * Check that a given namespace is in scope on a node.
78
 *
79
 * Returns 1 if in scope, -1 in case of argument error,
80
 *         -2 if the namespace is not in scope, and -3 if not on
81
 *         an ancestor node.
82
 */
83
static int
84
xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
85
0
{
86
0
    xmlNsPtr cur;
87
88
0
    if ((node == NULL) || (ns == NULL))
89
0
        return(-1);
90
91
0
    if ((node->type != XML_ELEMENT_NODE) &&
92
0
  (node->type != XML_ATTRIBUTE_NODE) &&
93
0
  (node->type != XML_DOCUMENT_NODE) &&
94
0
  (node->type != XML_TEXT_NODE) &&
95
0
  (node->type != XML_HTML_DOCUMENT_NODE) &&
96
0
  (node->type != XML_XINCLUDE_START))
97
0
  return(-2);
98
99
0
    while ((node != NULL) &&
100
0
           ((node->type == XML_ELEMENT_NODE) ||
101
0
            (node->type == XML_ATTRIBUTE_NODE) ||
102
0
            (node->type == XML_TEXT_NODE) ||
103
0
      (node->type == XML_XINCLUDE_START))) {
104
0
  if ((node->type == XML_ELEMENT_NODE) ||
105
0
      (node->type == XML_XINCLUDE_START)) {
106
0
      cur = node->nsDef;
107
0
      while (cur != NULL) {
108
0
          if (cur == ns)
109
0
        return(1);
110
0
    if (xmlStrEqual(cur->prefix, ns->prefix))
111
0
        return(-2);
112
0
    cur = cur->next;
113
0
      }
114
0
  }
115
0
  node = node->parent;
116
0
    }
117
    /* the xml namespace may be declared on the document node */
118
0
    if ((node != NULL) &&
119
0
        ((node->type == XML_DOCUMENT_NODE) ||
120
0
   (node->type == XML_HTML_DOCUMENT_NODE))) {
121
0
   xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
122
0
   if (oldNs == ns)
123
0
       return(1);
124
0
    }
125
0
    return(-3);
126
0
}
127
128
static void
129
xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
130
0
{
131
0
    if (ctxt->check)
132
0
        return;
133
0
    if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
134
0
        if (ctxt->depth < 50)
135
0
            fprintf(ctxt->output, "%s", &ctxt->shift[100 - 2 * ctxt->depth]);
136
0
        else
137
0
            fprintf(ctxt->output, "%s", ctxt->shift);
138
0
    }
139
0
}
140
141
/**
142
 * xmlDebugErr:
143
 * @ctxt:  a debug context
144
 * @error:  the error code
145
 *
146
 * Handle a debug error.
147
 */
148
static void
149
xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
150
0
{
151
0
    ctxt->errors++;
152
0
    fprintf(ctxt->output, "ERROR %d: %s", error, msg);
153
0
}
154
static void LIBXML_ATTR_FORMAT(3,0)
155
xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
156
0
{
157
0
    ctxt->errors++;
158
0
    fprintf(ctxt->output, "ERROR %d: ", error);
159
0
    fprintf(ctxt->output, msg, extra);
160
0
}
161
static void LIBXML_ATTR_FORMAT(3,0)
162
xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
163
0
{
164
0
    ctxt->errors++;
165
0
    fprintf(ctxt->output, "ERROR %d: ", error);
166
0
    fprintf(ctxt->output, msg, extra);
167
0
}
168
169
/**
170
 * xmlCtxtNsCheckScope:
171
 * @ctxt: the debugging context
172
 * @node: the node
173
 * @ns: the namespace node
174
 *
175
 * Report if a given namespace is is not in scope.
176
 */
177
static void
178
xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns)
179
0
{
180
0
    int ret;
181
182
0
    ret = xmlNsCheckScope(node, ns);
183
0
    if (ret == -2) {
184
0
        if (ns->prefix == NULL)
185
0
      xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
186
0
      "Reference to default namespace not in scope\n");
187
0
  else
188
0
      xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
189
0
       "Reference to namespace '%s' not in scope\n",
190
0
       (char *) ns->prefix);
191
0
    }
192
0
    if (ret == -3) {
193
0
        if (ns->prefix == NULL)
194
0
      xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
195
0
      "Reference to default namespace not on ancestor\n");
196
0
  else
197
0
      xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
198
0
       "Reference to namespace '%s' not on ancestor\n",
199
0
       (char *) ns->prefix);
200
0
    }
201
0
}
202
203
/**
204
 * xmlCtxtCheckString:
205
 * @ctxt: the debug context
206
 * @str: the string
207
 *
208
 * Do debugging on the string, currently it just checks the UTF-8 content
209
 */
210
static void
211
xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
212
0
{
213
0
    if (str == NULL) return;
214
0
    if (ctxt->check) {
215
0
        if (!xmlCheckUTF8(str)) {
216
0
      xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8,
217
0
       "String is not UTF-8 %s", (const char *) str);
218
0
  }
219
0
    }
220
0
}
221
222
/**
223
 * xmlCtxtCheckName:
224
 * @ctxt: the debug context
225
 * @name: the name
226
 *
227
 * Do debugging on the name, for example the dictionary status and
228
 * conformance to the Name production.
229
 */
230
static void
231
xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name)
232
0
{
233
0
    if (ctxt->check) {
234
0
  if (name == NULL) {
235
0
      xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL");
236
0
      return;
237
0
  }
238
0
        if (xmlValidateName(name, 0)) {
239
0
      xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME,
240
0
       "Name is not an NCName '%s'", (const char *) name);
241
0
  }
242
0
  if ((ctxt->dict != NULL) &&
243
0
      (!xmlDictOwns(ctxt->dict, name)) &&
244
0
            ((ctxt->doc == NULL) ||
245
0
             ((ctxt->doc->parseFlags & (XML_PARSE_SAX1 | XML_PARSE_NODICT)) == 0))) {
246
0
      xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
247
0
       "Name is not from the document dictionary '%s'",
248
0
       (const char *) name);
249
0
  }
250
0
    }
251
0
}
252
253
static void
254
0
xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
255
0
    xmlDocPtr doc;
256
0
    xmlDictPtr dict;
257
258
0
    doc = node->doc;
259
260
0
    if (node->parent == NULL)
261
0
        xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
262
0
              "Node has no parent\n");
263
0
    if (node->doc == NULL) {
264
0
        xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
265
0
              "Node has no doc\n");
266
0
        dict = NULL;
267
0
    } else {
268
0
  dict = doc->dict;
269
0
  if ((dict == NULL) && (ctxt->nodict == 0)) {
270
0
      ctxt->nodict = 1;
271
0
  }
272
0
  if (ctxt->doc == NULL)
273
0
      ctxt->doc = doc;
274
275
0
  if (ctxt->dict == NULL) {
276
0
      ctxt->dict = dict;
277
0
  }
278
0
    }
279
0
    if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
280
0
        (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
281
0
        xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
282
0
              "Node doc differs from parent's one\n");
283
0
    if (node->prev == NULL) {
284
0
        if (node->type == XML_ATTRIBUTE_NODE) {
285
0
      if ((node->parent != NULL) &&
286
0
          (node != (xmlNodePtr) node->parent->properties))
287
0
    xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
288
0
                    "Attr has no prev and not first of attr list\n");
289
290
0
        } else if ((node->parent != NULL) && (node->parent->children != node))
291
0
      xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
292
0
                    "Node has no prev and not first of parent list\n");
293
0
    } else {
294
0
        if (node->prev->next != node)
295
0
      xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
296
0
                        "Node prev->next : back link wrong\n");
297
0
    }
298
0
    if (node->next == NULL) {
299
0
  if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
300
0
      (node->parent->last != node) &&
301
0
      (node->parent->type == XML_ELEMENT_NODE))
302
0
      xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
303
0
                    "Node has no next and not last of parent list\n");
304
0
    } else {
305
0
        if (node->next->prev != node)
306
0
      xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
307
0
                    "Node next->prev : forward link wrong\n");
308
0
        if (node->next->parent != node->parent)
309
0
      xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
310
0
                    "Node next->prev : forward link wrong\n");
311
0
    }
312
0
    if (node->type == XML_ELEMENT_NODE) {
313
0
        xmlNsPtr ns;
314
315
0
  ns = node->nsDef;
316
0
  while (ns != NULL) {
317
0
      xmlCtxtNsCheckScope(ctxt, node, ns);
318
0
      ns = ns->next;
319
0
  }
320
0
  if (node->ns != NULL)
321
0
      xmlCtxtNsCheckScope(ctxt, node, node->ns);
322
0
    } else if (node->type == XML_ATTRIBUTE_NODE) {
323
0
  if (node->ns != NULL)
324
0
      xmlCtxtNsCheckScope(ctxt, node, node->ns);
325
0
    }
326
327
0
    if ((node->type != XML_ELEMENT_NODE) &&
328
0
  (node->type != XML_ATTRIBUTE_NODE) &&
329
0
  (node->type != XML_ELEMENT_DECL) &&
330
0
  (node->type != XML_ATTRIBUTE_DECL) &&
331
0
  (node->type != XML_DTD_NODE) &&
332
0
  (node->type != XML_HTML_DOCUMENT_NODE) &&
333
0
  (node->type != XML_DOCUMENT_NODE)) {
334
0
  if (node->content != NULL)
335
0
      xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
336
0
    }
337
0
    switch (node->type) {
338
0
        case XML_ELEMENT_NODE:
339
0
        case XML_ATTRIBUTE_NODE:
340
0
      xmlCtxtCheckName(ctxt, node->name);
341
0
      break;
342
0
        case XML_TEXT_NODE:
343
0
      if ((node->name == xmlStringText) ||
344
0
          (node->name == xmlStringTextNoenc))
345
0
    break;
346
      /* some case of entity substitution can lead to this */
347
0
      if ((ctxt->dict != NULL) &&
348
0
          (node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
349
0
                                 7)))
350
0
    break;
351
352
0
      xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
353
0
       "Text node has wrong name '%s'",
354
0
       (const char *) node->name);
355
0
      break;
356
0
        case XML_COMMENT_NODE:
357
0
      if (node->name == xmlStringComment)
358
0
    break;
359
0
      xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
360
0
       "Comment node has wrong name '%s'",
361
0
       (const char *) node->name);
362
0
      break;
363
0
        case XML_PI_NODE:
364
0
      xmlCtxtCheckName(ctxt, node->name);
365
0
      break;
366
0
        case XML_CDATA_SECTION_NODE:
367
0
      if (node->name == NULL)
368
0
    break;
369
0
      xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL,
370
0
       "CData section has non NULL name '%s'",
371
0
       (const char *) node->name);
372
0
      break;
373
0
        case XML_ENTITY_REF_NODE:
374
0
        case XML_ENTITY_NODE:
375
0
        case XML_DOCUMENT_TYPE_NODE:
376
0
        case XML_DOCUMENT_FRAG_NODE:
377
0
        case XML_NOTATION_NODE:
378
0
        case XML_DTD_NODE:
379
0
        case XML_ELEMENT_DECL:
380
0
        case XML_ATTRIBUTE_DECL:
381
0
        case XML_ENTITY_DECL:
382
0
        case XML_NAMESPACE_DECL:
383
0
        case XML_XINCLUDE_START:
384
0
        case XML_XINCLUDE_END:
385
0
        case XML_DOCUMENT_NODE:
386
0
        case XML_HTML_DOCUMENT_NODE:
387
0
      break;
388
0
    }
389
0
}
390
391
static void
392
xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
393
0
{
394
0
    int i;
395
396
0
    if (ctxt->check) {
397
0
        return;
398
0
    }
399
    /* TODO: check UTF8 content of the string */
400
0
    if (str == NULL) {
401
0
        fprintf(ctxt->output, "(NULL)");
402
0
        return;
403
0
    }
404
0
    for (i = 0; i < 40; i++)
405
0
        if (str[i] == 0)
406
0
            return;
407
0
        else if (IS_BLANK_CH(str[i]))
408
0
            fputc(' ', ctxt->output);
409
0
        else if (str[i] >= 0x80)
410
0
            fprintf(ctxt->output, "#%X", str[i]);
411
0
        else
412
0
            fputc(str[i], ctxt->output);
413
0
    fprintf(ctxt->output, "...");
414
0
}
415
416
static void
417
xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
418
0
{
419
0
    xmlCtxtDumpSpaces(ctxt);
420
421
0
    if (dtd == NULL) {
422
0
        if (!ctxt->check)
423
0
            fprintf(ctxt->output, "DTD node is NULL\n");
424
0
        return;
425
0
    }
426
427
0
    if (dtd->type != XML_DTD_NODE) {
428
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
429
0
              "Node is not a DTD");
430
0
        return;
431
0
    }
432
0
    if (!ctxt->check) {
433
0
        if (dtd->name != NULL)
434
0
            fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
435
0
        else
436
0
            fprintf(ctxt->output, "DTD");
437
0
        if (dtd->ExternalID != NULL)
438
0
            fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
439
0
        if (dtd->SystemID != NULL)
440
0
            fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
441
0
        fprintf(ctxt->output, "\n");
442
0
    }
443
    /*
444
     * Do a bit of checking
445
     */
446
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
447
0
}
448
449
static void
450
xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr)
451
0
{
452
0
    xmlCtxtDumpSpaces(ctxt);
453
454
0
    if (attr == NULL) {
455
0
        if (!ctxt->check)
456
0
            fprintf(ctxt->output, "Attribute declaration is NULL\n");
457
0
        return;
458
0
    }
459
0
    if (attr->type != XML_ATTRIBUTE_DECL) {
460
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
461
0
              "Node is not an attribute declaration");
462
0
        return;
463
0
    }
464
0
    if (attr->name != NULL) {
465
0
        if (!ctxt->check)
466
0
            fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
467
0
    } else
468
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
469
0
              "Node attribute declaration has no name");
470
0
    if (attr->elem != NULL) {
471
0
        if (!ctxt->check)
472
0
            fprintf(ctxt->output, " for %s", (char *) attr->elem);
473
0
    } else
474
0
  xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
475
0
              "Node attribute declaration has no element name");
476
0
    if (!ctxt->check) {
477
0
        switch (attr->atype) {
478
0
            case XML_ATTRIBUTE_CDATA:
479
0
                fprintf(ctxt->output, " CDATA");
480
0
                break;
481
0
            case XML_ATTRIBUTE_ID:
482
0
                fprintf(ctxt->output, " ID");
483
0
                break;
484
0
            case XML_ATTRIBUTE_IDREF:
485
0
                fprintf(ctxt->output, " IDREF");
486
0
                break;
487
0
            case XML_ATTRIBUTE_IDREFS:
488
0
                fprintf(ctxt->output, " IDREFS");
489
0
                break;
490
0
            case XML_ATTRIBUTE_ENTITY:
491
0
                fprintf(ctxt->output, " ENTITY");
492
0
                break;
493
0
            case XML_ATTRIBUTE_ENTITIES:
494
0
                fprintf(ctxt->output, " ENTITIES");
495
0
                break;
496
0
            case XML_ATTRIBUTE_NMTOKEN:
497
0
                fprintf(ctxt->output, " NMTOKEN");
498
0
                break;
499
0
            case XML_ATTRIBUTE_NMTOKENS:
500
0
                fprintf(ctxt->output, " NMTOKENS");
501
0
                break;
502
0
            case XML_ATTRIBUTE_ENUMERATION:
503
0
                fprintf(ctxt->output, " ENUMERATION");
504
0
                break;
505
0
            case XML_ATTRIBUTE_NOTATION:
506
0
                fprintf(ctxt->output, " NOTATION ");
507
0
                break;
508
0
        }
509
0
        if (attr->tree != NULL) {
510
0
            int indx;
511
0
            xmlEnumerationPtr cur = attr->tree;
512
513
0
            for (indx = 0; indx < 5; indx++) {
514
0
                if (indx != 0)
515
0
                    fprintf(ctxt->output, "|%s", (char *) cur->name);
516
0
                else
517
0
                    fprintf(ctxt->output, " (%s", (char *) cur->name);
518
0
                cur = cur->next;
519
0
                if (cur == NULL)
520
0
                    break;
521
0
            }
522
0
            if (cur == NULL)
523
0
                fprintf(ctxt->output, ")");
524
0
            else
525
0
                fprintf(ctxt->output, "...)");
526
0
        }
527
0
        switch (attr->def) {
528
0
            case XML_ATTRIBUTE_NONE:
529
0
                break;
530
0
            case XML_ATTRIBUTE_REQUIRED:
531
0
                fprintf(ctxt->output, " REQUIRED");
532
0
                break;
533
0
            case XML_ATTRIBUTE_IMPLIED:
534
0
                fprintf(ctxt->output, " IMPLIED");
535
0
                break;
536
0
            case XML_ATTRIBUTE_FIXED:
537
0
                fprintf(ctxt->output, " FIXED");
538
0
                break;
539
0
        }
540
0
        if (attr->defaultValue != NULL) {
541
0
            fprintf(ctxt->output, "\"");
542
0
            xmlCtxtDumpString(ctxt, attr->defaultValue);
543
0
            fprintf(ctxt->output, "\"");
544
0
        }
545
0
        fprintf(ctxt->output, "\n");
546
0
    }
547
548
    /*
549
     * Do a bit of checking
550
     */
551
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
552
0
}
553
554
static void
555
xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem)
556
0
{
557
0
    xmlCtxtDumpSpaces(ctxt);
558
559
0
    if (elem == NULL) {
560
0
        if (!ctxt->check)
561
0
            fprintf(ctxt->output, "Element declaration is NULL\n");
562
0
        return;
563
0
    }
564
0
    if (elem->type != XML_ELEMENT_DECL) {
565
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
566
0
              "Node is not an element declaration");
567
0
        return;
568
0
    }
569
0
    if (elem->name != NULL) {
570
0
        if (!ctxt->check) {
571
0
            fprintf(ctxt->output, "ELEMDECL(");
572
0
            xmlCtxtDumpString(ctxt, elem->name);
573
0
            fprintf(ctxt->output, ")");
574
0
        }
575
0
    } else
576
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
577
0
              "Element declaration has no name");
578
0
    if (!ctxt->check) {
579
0
        switch (elem->etype) {
580
0
            case XML_ELEMENT_TYPE_UNDEFINED:
581
0
                fprintf(ctxt->output, ", UNDEFINED");
582
0
                break;
583
0
            case XML_ELEMENT_TYPE_EMPTY:
584
0
                fprintf(ctxt->output, ", EMPTY");
585
0
                break;
586
0
            case XML_ELEMENT_TYPE_ANY:
587
0
                fprintf(ctxt->output, ", ANY");
588
0
                break;
589
0
            case XML_ELEMENT_TYPE_MIXED:
590
0
                fprintf(ctxt->output, ", MIXED ");
591
0
                break;
592
0
            case XML_ELEMENT_TYPE_ELEMENT:
593
0
                fprintf(ctxt->output, ", MIXED ");
594
0
                break;
595
0
        }
596
0
        if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) {
597
0
            char buf[5001];
598
599
0
            buf[0] = 0;
600
0
            xmlSnprintfElementContent(buf, 5000, elem->content, 1);
601
0
            buf[5000] = 0;
602
0
            fprintf(ctxt->output, "%s", buf);
603
0
        }
604
0
        fprintf(ctxt->output, "\n");
605
0
    }
606
607
    /*
608
     * Do a bit of checking
609
     */
610
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
611
0
}
612
613
static void
614
xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
615
0
{
616
0
    xmlCtxtDumpSpaces(ctxt);
617
618
0
    if (ent == NULL) {
619
0
        if (!ctxt->check)
620
0
            fprintf(ctxt->output, "Entity declaration is NULL\n");
621
0
        return;
622
0
    }
623
0
    if (ent->type != XML_ENTITY_DECL) {
624
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
625
0
              "Node is not an entity declaration");
626
0
        return;
627
0
    }
628
0
    if (ent->name != NULL) {
629
0
        if (!ctxt->check) {
630
0
            fprintf(ctxt->output, "ENTITYDECL(");
631
0
            xmlCtxtDumpString(ctxt, ent->name);
632
0
            fprintf(ctxt->output, ")");
633
0
        }
634
0
    } else
635
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
636
0
              "Entity declaration has no name");
637
0
    if (!ctxt->check) {
638
0
        switch (ent->etype) {
639
0
            case XML_INTERNAL_GENERAL_ENTITY:
640
0
                fprintf(ctxt->output, ", internal\n");
641
0
                break;
642
0
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
643
0
                fprintf(ctxt->output, ", external parsed\n");
644
0
                break;
645
0
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
646
0
                fprintf(ctxt->output, ", unparsed\n");
647
0
                break;
648
0
            case XML_INTERNAL_PARAMETER_ENTITY:
649
0
                fprintf(ctxt->output, ", parameter\n");
650
0
                break;
651
0
            case XML_EXTERNAL_PARAMETER_ENTITY:
652
0
                fprintf(ctxt->output, ", external parameter\n");
653
0
                break;
654
0
            case XML_INTERNAL_PREDEFINED_ENTITY:
655
0
                fprintf(ctxt->output, ", predefined\n");
656
0
                break;
657
0
        }
658
0
        if (ent->ExternalID) {
659
0
            xmlCtxtDumpSpaces(ctxt);
660
0
            fprintf(ctxt->output, " ExternalID=%s\n",
661
0
                    (char *) ent->ExternalID);
662
0
        }
663
0
        if (ent->SystemID) {
664
0
            xmlCtxtDumpSpaces(ctxt);
665
0
            fprintf(ctxt->output, " SystemID=%s\n",
666
0
                    (char *) ent->SystemID);
667
0
        }
668
0
        if (ent->URI != NULL) {
669
0
            xmlCtxtDumpSpaces(ctxt);
670
0
            fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI);
671
0
        }
672
0
        if (ent->content) {
673
0
            xmlCtxtDumpSpaces(ctxt);
674
0
            fprintf(ctxt->output, " content=");
675
0
            xmlCtxtDumpString(ctxt, ent->content);
676
0
            fprintf(ctxt->output, "\n");
677
0
        }
678
0
    }
679
680
    /*
681
     * Do a bit of checking
682
     */
683
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
684
0
}
685
686
static void
687
xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
688
0
{
689
0
    xmlCtxtDumpSpaces(ctxt);
690
691
0
    if (ns == NULL) {
692
0
        if (!ctxt->check)
693
0
            fprintf(ctxt->output, "namespace node is NULL\n");
694
0
        return;
695
0
    }
696
0
    if (ns->type != XML_NAMESPACE_DECL) {
697
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
698
0
              "Node is not a namespace declaration");
699
0
        return;
700
0
    }
701
0
    if (ns->href == NULL) {
702
0
        if (ns->prefix != NULL)
703
0
      xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
704
0
                    "Incomplete namespace %s href=NULL\n",
705
0
                    (char *) ns->prefix);
706
0
        else
707
0
      xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
708
0
                    "Incomplete default namespace href=NULL\n");
709
0
    } else {
710
0
        if (!ctxt->check) {
711
0
            if (ns->prefix != NULL)
712
0
                fprintf(ctxt->output, "namespace %s href=",
713
0
                        (char *) ns->prefix);
714
0
            else
715
0
                fprintf(ctxt->output, "default namespace href=");
716
717
0
            xmlCtxtDumpString(ctxt, ns->href);
718
0
            fprintf(ctxt->output, "\n");
719
0
        }
720
0
    }
721
0
}
722
723
static void
724
xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
725
0
{
726
0
    while (ns != NULL) {
727
0
        xmlCtxtDumpNamespace(ctxt, ns);
728
0
        ns = ns->next;
729
0
    }
730
0
}
731
732
static void
733
xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
734
0
{
735
0
    xmlCtxtDumpSpaces(ctxt);
736
737
0
    if (ent == NULL) {
738
0
        if (!ctxt->check)
739
0
            fprintf(ctxt->output, "Entity is NULL\n");
740
0
        return;
741
0
    }
742
0
    if (!ctxt->check) {
743
0
        switch (ent->etype) {
744
0
            case XML_INTERNAL_GENERAL_ENTITY:
745
0
                fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY ");
746
0
                break;
747
0
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
748
0
                fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
749
0
                break;
750
0
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
751
0
                fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
752
0
                break;
753
0
            case XML_INTERNAL_PARAMETER_ENTITY:
754
0
                fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY ");
755
0
                break;
756
0
            case XML_EXTERNAL_PARAMETER_ENTITY:
757
0
                fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY ");
758
0
                break;
759
0
            default:
760
0
                fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype);
761
0
        }
762
0
        fprintf(ctxt->output, "%s\n", ent->name);
763
0
        if (ent->ExternalID) {
764
0
            xmlCtxtDumpSpaces(ctxt);
765
0
            fprintf(ctxt->output, "ExternalID=%s\n",
766
0
                    (char *) ent->ExternalID);
767
0
        }
768
0
        if (ent->SystemID) {
769
0
            xmlCtxtDumpSpaces(ctxt);
770
0
            fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID);
771
0
        }
772
0
        if (ent->URI) {
773
0
            xmlCtxtDumpSpaces(ctxt);
774
0
            fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI);
775
0
        }
776
0
        if (ent->content) {
777
0
            xmlCtxtDumpSpaces(ctxt);
778
0
            fprintf(ctxt->output, "content=");
779
0
            xmlCtxtDumpString(ctxt, ent->content);
780
0
            fprintf(ctxt->output, "\n");
781
0
        }
782
0
    }
783
0
}
784
785
/**
786
 * xmlCtxtDumpAttr:
787
 * @output:  the FILE * for the output
788
 * @attr:  the attribute
789
 * @depth:  the indentation level.
790
 *
791
 * Dumps debug information for the attribute
792
 */
793
static void
794
xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
795
0
{
796
0
    xmlCtxtDumpSpaces(ctxt);
797
798
0
    if (attr == NULL) {
799
0
        if (!ctxt->check)
800
0
            fprintf(ctxt->output, "Attr is NULL");
801
0
        return;
802
0
    }
803
0
    if (!ctxt->check) {
804
0
        fprintf(ctxt->output, "ATTRIBUTE ");
805
0
  xmlCtxtDumpString(ctxt, attr->name);
806
0
        fprintf(ctxt->output, "\n");
807
0
        if (attr->children != NULL) {
808
0
            ctxt->depth++;
809
0
            xmlCtxtDumpNodeList(ctxt, attr->children);
810
0
            ctxt->depth--;
811
0
        }
812
0
    }
813
0
    if (attr->name == NULL)
814
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
815
0
              "Attribute has no name");
816
817
    /*
818
     * Do a bit of checking
819
     */
820
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
821
0
}
822
823
/**
824
 * xmlCtxtDumpAttrList:
825
 * @output:  the FILE * for the output
826
 * @attr:  the attribute list
827
 * @depth:  the indentation level.
828
 *
829
 * Dumps debug information for the attribute list
830
 */
831
static void
832
xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
833
0
{
834
0
    while (attr != NULL) {
835
0
        xmlCtxtDumpAttr(ctxt, attr);
836
0
        attr = attr->next;
837
0
    }
838
0
}
839
840
/**
841
 * xmlCtxtDumpOneNode:
842
 * @output:  the FILE * for the output
843
 * @node:  the node
844
 * @depth:  the indentation level.
845
 *
846
 * Dumps debug information for the element node, it is not recursive
847
 */
848
static void
849
xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
850
0
{
851
0
    if (node == NULL) {
852
0
        if (!ctxt->check) {
853
0
            xmlCtxtDumpSpaces(ctxt);
854
0
            fprintf(ctxt->output, "node is NULL\n");
855
0
        }
856
0
        return;
857
0
    }
858
0
    ctxt->node = node;
859
860
0
    switch (node->type) {
861
0
        case XML_ELEMENT_NODE:
862
0
            if (!ctxt->check) {
863
0
                xmlCtxtDumpSpaces(ctxt);
864
0
                fprintf(ctxt->output, "ELEMENT ");
865
0
                if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
866
0
                    xmlCtxtDumpString(ctxt, node->ns->prefix);
867
0
                    fprintf(ctxt->output, ":");
868
0
                }
869
0
                xmlCtxtDumpString(ctxt, node->name);
870
0
                fprintf(ctxt->output, "\n");
871
0
            }
872
0
            break;
873
0
        case XML_ATTRIBUTE_NODE:
874
0
            if (!ctxt->check)
875
0
                xmlCtxtDumpSpaces(ctxt);
876
0
            fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
877
0
            xmlCtxtGenericNodeCheck(ctxt, node);
878
0
            return;
879
0
        case XML_TEXT_NODE:
880
0
            if (!ctxt->check) {
881
0
                xmlCtxtDumpSpaces(ctxt);
882
0
                if (node->name == (const xmlChar *) xmlStringTextNoenc)
883
0
                    fprintf(ctxt->output, "TEXT no enc");
884
0
                else
885
0
                    fprintf(ctxt->output, "TEXT");
886
0
    if (ctxt->options & DUMP_TEXT_TYPE) {
887
0
        if (node->content == (xmlChar *) &(node->properties))
888
0
      fprintf(ctxt->output, " compact\n");
889
0
        else if (xmlDictOwns(ctxt->dict, node->content) == 1)
890
0
      fprintf(ctxt->output, " interned\n");
891
0
        else
892
0
      fprintf(ctxt->output, "\n");
893
0
    } else
894
0
        fprintf(ctxt->output, "\n");
895
0
            }
896
0
            break;
897
0
        case XML_CDATA_SECTION_NODE:
898
0
            if (!ctxt->check) {
899
0
                xmlCtxtDumpSpaces(ctxt);
900
0
                fprintf(ctxt->output, "CDATA_SECTION\n");
901
0
            }
902
0
            break;
903
0
        case XML_ENTITY_REF_NODE:
904
0
            if (!ctxt->check) {
905
0
                xmlCtxtDumpSpaces(ctxt);
906
0
                fprintf(ctxt->output, "ENTITY_REF(%s)\n",
907
0
                        (char *) node->name);
908
0
            }
909
0
            break;
910
0
        case XML_ENTITY_NODE:
911
0
            if (!ctxt->check) {
912
0
                xmlCtxtDumpSpaces(ctxt);
913
0
                fprintf(ctxt->output, "ENTITY\n");
914
0
            }
915
0
            break;
916
0
        case XML_PI_NODE:
917
0
            if (!ctxt->check) {
918
0
                xmlCtxtDumpSpaces(ctxt);
919
0
                fprintf(ctxt->output, "PI %s\n", (char *) node->name);
920
0
            }
921
0
            break;
922
0
        case XML_COMMENT_NODE:
923
0
            if (!ctxt->check) {
924
0
                xmlCtxtDumpSpaces(ctxt);
925
0
                fprintf(ctxt->output, "COMMENT\n");
926
0
            }
927
0
            break;
928
0
        case XML_DOCUMENT_NODE:
929
0
        case XML_HTML_DOCUMENT_NODE:
930
0
            if (!ctxt->check) {
931
0
                xmlCtxtDumpSpaces(ctxt);
932
0
            }
933
0
            fprintf(ctxt->output, "Error, DOCUMENT found here\n");
934
0
            xmlCtxtGenericNodeCheck(ctxt, node);
935
0
            return;
936
0
        case XML_DOCUMENT_TYPE_NODE:
937
0
            if (!ctxt->check) {
938
0
                xmlCtxtDumpSpaces(ctxt);
939
0
                fprintf(ctxt->output, "DOCUMENT_TYPE\n");
940
0
            }
941
0
            break;
942
0
        case XML_DOCUMENT_FRAG_NODE:
943
0
            if (!ctxt->check) {
944
0
                xmlCtxtDumpSpaces(ctxt);
945
0
                fprintf(ctxt->output, "DOCUMENT_FRAG\n");
946
0
            }
947
0
            break;
948
0
        case XML_NOTATION_NODE:
949
0
            if (!ctxt->check) {
950
0
                xmlCtxtDumpSpaces(ctxt);
951
0
                fprintf(ctxt->output, "NOTATION\n");
952
0
            }
953
0
            break;
954
0
        case XML_DTD_NODE:
955
0
            xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node);
956
0
            return;
957
0
        case XML_ELEMENT_DECL:
958
0
            xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node);
959
0
            return;
960
0
        case XML_ATTRIBUTE_DECL:
961
0
            xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node);
962
0
            return;
963
0
        case XML_ENTITY_DECL:
964
0
            xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node);
965
0
            return;
966
0
        case XML_NAMESPACE_DECL:
967
0
            xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node);
968
0
            return;
969
0
        case XML_XINCLUDE_START:
970
0
            if (!ctxt->check) {
971
0
                xmlCtxtDumpSpaces(ctxt);
972
0
                fprintf(ctxt->output, "INCLUDE START\n");
973
0
            }
974
0
            return;
975
0
        case XML_XINCLUDE_END:
976
0
            if (!ctxt->check) {
977
0
                xmlCtxtDumpSpaces(ctxt);
978
0
                fprintf(ctxt->output, "INCLUDE END\n");
979
0
            }
980
0
            return;
981
0
        default:
982
0
            if (!ctxt->check)
983
0
                xmlCtxtDumpSpaces(ctxt);
984
0
      xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
985
0
                  "Unknown node type %d\n", node->type);
986
0
            return;
987
0
    }
988
0
    if (node->doc == NULL) {
989
0
        if (!ctxt->check) {
990
0
            xmlCtxtDumpSpaces(ctxt);
991
0
        }
992
0
        fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
993
0
    }
994
0
    ctxt->depth++;
995
0
    if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL))
996
0
        xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
997
0
    if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL))
998
0
        xmlCtxtDumpAttrList(ctxt, node->properties);
999
0
    if (node->type != XML_ENTITY_REF_NODE) {
1000
0
        if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
1001
0
            if (!ctxt->check) {
1002
0
                xmlCtxtDumpSpaces(ctxt);
1003
0
                fprintf(ctxt->output, "content=");
1004
0
                xmlCtxtDumpString(ctxt, node->content);
1005
0
                fprintf(ctxt->output, "\n");
1006
0
            }
1007
0
        }
1008
0
    } else {
1009
0
        xmlEntityPtr ent;
1010
1011
0
        ent = xmlGetDocEntity(node->doc, node->name);
1012
0
        if (ent != NULL)
1013
0
            xmlCtxtDumpEntity(ctxt, ent);
1014
0
    }
1015
0
    ctxt->depth--;
1016
1017
    /*
1018
     * Do a bit of checking
1019
     */
1020
0
    xmlCtxtGenericNodeCheck(ctxt, node);
1021
0
}
1022
1023
/**
1024
 * xmlCtxtDumpNode:
1025
 * @output:  the FILE * for the output
1026
 * @node:  the node
1027
 * @depth:  the indentation level.
1028
 *
1029
 * Dumps debug information for the element node, it is recursive
1030
 */
1031
static void
1032
xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
1033
0
{
1034
0
    if (node == NULL) {
1035
0
        if (!ctxt->check) {
1036
0
            xmlCtxtDumpSpaces(ctxt);
1037
0
            fprintf(ctxt->output, "node is NULL\n");
1038
0
        }
1039
0
        return;
1040
0
    }
1041
0
    xmlCtxtDumpOneNode(ctxt, node);
1042
0
    if ((node->type != XML_NAMESPACE_DECL) &&
1043
0
        (node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1044
0
        ctxt->depth++;
1045
0
        xmlCtxtDumpNodeList(ctxt, node->children);
1046
0
        ctxt->depth--;
1047
0
    }
1048
0
}
1049
1050
/**
1051
 * xmlCtxtDumpNodeList:
1052
 * @output:  the FILE * for the output
1053
 * @node:  the node list
1054
 * @depth:  the indentation level.
1055
 *
1056
 * Dumps debug information for the list of element node, it is recursive
1057
 */
1058
static void
1059
xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
1060
0
{
1061
0
    while (node != NULL) {
1062
0
        xmlCtxtDumpNode(ctxt, node);
1063
0
        node = node->next;
1064
0
    }
1065
0
}
1066
1067
static void
1068
xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1069
0
{
1070
0
    if (doc == NULL) {
1071
0
        if (!ctxt->check)
1072
0
            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1073
0
        return;
1074
0
    }
1075
0
    ctxt->node = (xmlNodePtr) doc;
1076
1077
0
    switch (doc->type) {
1078
0
        case XML_ELEMENT_NODE:
1079
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
1080
0
                  "Misplaced ELEMENT node\n");
1081
0
            break;
1082
0
        case XML_ATTRIBUTE_NODE:
1083
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
1084
0
                  "Misplaced ATTRIBUTE node\n");
1085
0
            break;
1086
0
        case XML_TEXT_NODE:
1087
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
1088
0
                  "Misplaced TEXT node\n");
1089
0
            break;
1090
0
        case XML_CDATA_SECTION_NODE:
1091
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
1092
0
                  "Misplaced CDATA node\n");
1093
0
            break;
1094
0
        case XML_ENTITY_REF_NODE:
1095
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
1096
0
                  "Misplaced ENTITYREF node\n");
1097
0
            break;
1098
0
        case XML_ENTITY_NODE:
1099
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
1100
0
                  "Misplaced ENTITY node\n");
1101
0
            break;
1102
0
        case XML_PI_NODE:
1103
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
1104
0
                  "Misplaced PI node\n");
1105
0
            break;
1106
0
        case XML_COMMENT_NODE:
1107
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
1108
0
                  "Misplaced COMMENT node\n");
1109
0
            break;
1110
0
        case XML_DOCUMENT_NODE:
1111
0
      if (!ctxt->check)
1112
0
    fprintf(ctxt->output, "DOCUMENT\n");
1113
0
            break;
1114
0
        case XML_HTML_DOCUMENT_NODE:
1115
0
      if (!ctxt->check)
1116
0
    fprintf(ctxt->output, "HTML DOCUMENT\n");
1117
0
            break;
1118
0
        case XML_DOCUMENT_TYPE_NODE:
1119
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
1120
0
                  "Misplaced DOCTYPE node\n");
1121
0
            break;
1122
0
        case XML_DOCUMENT_FRAG_NODE:
1123
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
1124
0
                  "Misplaced FRAGMENT node\n");
1125
0
            break;
1126
0
        case XML_NOTATION_NODE:
1127
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
1128
0
                  "Misplaced NOTATION node\n");
1129
0
            break;
1130
0
        default:
1131
0
      xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1132
0
                  "Unknown node type %d\n", doc->type);
1133
0
    }
1134
0
}
1135
1136
/**
1137
 * xmlCtxtDumpDocumentHead:
1138
 * @output:  the FILE * for the output
1139
 * @doc:  the document
1140
 *
1141
 * Dumps debug information concerning the document, not recursive
1142
 */
1143
static void
1144
xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1145
0
{
1146
0
    if (doc == NULL) return;
1147
0
    xmlCtxtDumpDocHead(ctxt, doc);
1148
0
    if (!ctxt->check) {
1149
0
        if (doc->name != NULL) {
1150
0
            fprintf(ctxt->output, "name=");
1151
0
            xmlCtxtDumpString(ctxt, BAD_CAST doc->name);
1152
0
            fprintf(ctxt->output, "\n");
1153
0
        }
1154
0
        if (doc->version != NULL) {
1155
0
            fprintf(ctxt->output, "version=");
1156
0
            xmlCtxtDumpString(ctxt, doc->version);
1157
0
            fprintf(ctxt->output, "\n");
1158
0
        }
1159
0
        if (doc->encoding != NULL) {
1160
0
            fprintf(ctxt->output, "encoding=");
1161
0
            xmlCtxtDumpString(ctxt, doc->encoding);
1162
0
            fprintf(ctxt->output, "\n");
1163
0
        }
1164
0
        if (doc->URL != NULL) {
1165
0
            fprintf(ctxt->output, "URL=");
1166
0
            xmlCtxtDumpString(ctxt, doc->URL);
1167
0
            fprintf(ctxt->output, "\n");
1168
0
        }
1169
0
        if (doc->standalone)
1170
0
            fprintf(ctxt->output, "standalone=true\n");
1171
0
    }
1172
0
    if (doc->oldNs != NULL)
1173
0
        xmlCtxtDumpNamespaceList(ctxt, doc->oldNs);
1174
0
}
1175
1176
/**
1177
 * xmlCtxtDumpDocument:
1178
 * @output:  the FILE * for the output
1179
 * @doc:  the document
1180
 *
1181
 * Dumps debug information for the document, it's recursive
1182
 */
1183
static void
1184
xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1185
0
{
1186
0
    if (doc == NULL) {
1187
0
        if (!ctxt->check)
1188
0
            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1189
0
        return;
1190
0
    }
1191
0
    xmlCtxtDumpDocumentHead(ctxt, doc);
1192
0
    if (((doc->type == XML_DOCUMENT_NODE) ||
1193
0
         (doc->type == XML_HTML_DOCUMENT_NODE))
1194
0
        && (doc->children != NULL)) {
1195
0
        ctxt->depth++;
1196
0
        xmlCtxtDumpNodeList(ctxt, doc->children);
1197
0
        ctxt->depth--;
1198
0
    }
1199
0
}
1200
1201
static void
1202
xmlCtxtDumpEntityCallback(void *payload, void *data,
1203
                          const xmlChar *name ATTRIBUTE_UNUSED)
1204
0
{
1205
0
    xmlEntityPtr cur = (xmlEntityPtr) payload;
1206
0
    xmlDebugCtxtPtr ctxt = (xmlDebugCtxtPtr) data;
1207
0
    if (cur == NULL) {
1208
0
        if (!ctxt->check)
1209
0
            fprintf(ctxt->output, "Entity is NULL");
1210
0
        return;
1211
0
    }
1212
0
    if (!ctxt->check) {
1213
0
        fprintf(ctxt->output, "%s : ", (char *) cur->name);
1214
0
        switch (cur->etype) {
1215
0
            case XML_INTERNAL_GENERAL_ENTITY:
1216
0
                fprintf(ctxt->output, "INTERNAL GENERAL, ");
1217
0
                break;
1218
0
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1219
0
                fprintf(ctxt->output, "EXTERNAL PARSED, ");
1220
0
                break;
1221
0
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1222
0
                fprintf(ctxt->output, "EXTERNAL UNPARSED, ");
1223
0
                break;
1224
0
            case XML_INTERNAL_PARAMETER_ENTITY:
1225
0
                fprintf(ctxt->output, "INTERNAL PARAMETER, ");
1226
0
                break;
1227
0
            case XML_EXTERNAL_PARAMETER_ENTITY:
1228
0
                fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
1229
0
                break;
1230
0
            default:
1231
0
    xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
1232
0
           "Unknown entity type %d\n", cur->etype);
1233
0
        }
1234
0
        if (cur->ExternalID != NULL)
1235
0
            fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
1236
0
        if (cur->SystemID != NULL)
1237
0
            fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID);
1238
0
        if (cur->orig != NULL)
1239
0
            fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig);
1240
0
        if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL))
1241
0
            fprintf(ctxt->output, "\n content \"%s\"",
1242
0
                    (char *) cur->content);
1243
0
        fprintf(ctxt->output, "\n");
1244
0
    }
1245
0
}
1246
1247
/**
1248
 * xmlCtxtDumpEntities:
1249
 * @output:  the FILE * for the output
1250
 * @doc:  the document
1251
 *
1252
 * Dumps debug information for all the entities in use by the document
1253
 */
1254
static void
1255
xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1256
0
{
1257
0
    if (doc == NULL) return;
1258
0
    xmlCtxtDumpDocHead(ctxt, doc);
1259
0
    if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1260
0
        xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1261
0
            doc->intSubset->entities;
1262
1263
0
        if (!ctxt->check)
1264
0
            fprintf(ctxt->output, "Entities in internal subset\n");
1265
0
        xmlHashScan(table, xmlCtxtDumpEntityCallback, ctxt);
1266
0
    } else
1267
0
        fprintf(ctxt->output, "No entities in internal subset\n");
1268
0
    if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1269
0
        xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1270
0
            doc->extSubset->entities;
1271
1272
0
        if (!ctxt->check)
1273
0
            fprintf(ctxt->output, "Entities in external subset\n");
1274
0
        xmlHashScan(table, xmlCtxtDumpEntityCallback, ctxt);
1275
0
    } else if (!ctxt->check)
1276
0
        fprintf(ctxt->output, "No entities in external subset\n");
1277
0
}
1278
1279
/**
1280
 * xmlCtxtDumpDTD:
1281
 * @output:  the FILE * for the output
1282
 * @dtd:  the DTD
1283
 *
1284
 * Dumps debug information for the DTD
1285
 */
1286
static void
1287
xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
1288
0
{
1289
0
    if (dtd == NULL) {
1290
0
        if (!ctxt->check)
1291
0
            fprintf(ctxt->output, "DTD is NULL\n");
1292
0
        return;
1293
0
    }
1294
0
    xmlCtxtDumpDtdNode(ctxt, dtd);
1295
0
    if (dtd->children == NULL)
1296
0
        fprintf(ctxt->output, "    DTD is empty\n");
1297
0
    else {
1298
0
        ctxt->depth++;
1299
0
        xmlCtxtDumpNodeList(ctxt, dtd->children);
1300
0
        ctxt->depth--;
1301
0
    }
1302
0
}
1303
1304
/************************************************************************
1305
 *                  *
1306
 *      Public entry points for dump      *
1307
 *                  *
1308
 ************************************************************************/
1309
1310
/**
1311
 * xmlDebugDumpString:
1312
 * @output:  the FILE * for the output
1313
 * @str:  the string
1314
 *
1315
 * Dumps information about the string, shorten it if necessary
1316
 */
1317
void
1318
xmlDebugDumpString(FILE * output, const xmlChar * str)
1319
0
{
1320
0
    int i;
1321
1322
0
    if (output == NULL)
1323
0
  output = stdout;
1324
0
    if (str == NULL) {
1325
0
        fprintf(output, "(NULL)");
1326
0
        return;
1327
0
    }
1328
0
    for (i = 0; i < 40; i++)
1329
0
        if (str[i] == 0)
1330
0
            return;
1331
0
        else if (IS_BLANK_CH(str[i]))
1332
0
            fputc(' ', output);
1333
0
        else if (str[i] >= 0x80)
1334
0
            fprintf(output, "#%X", str[i]);
1335
0
        else
1336
0
            fputc(str[i], output);
1337
0
    fprintf(output, "...");
1338
0
}
1339
1340
/**
1341
 * xmlDebugDumpAttr:
1342
 * @output:  the FILE * for the output
1343
 * @attr:  the attribute
1344
 * @depth:  the indentation level.
1345
 *
1346
 * Dumps debug information for the attribute
1347
 */
1348
void
1349
0
xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
1350
0
    xmlDebugCtxt ctxt;
1351
1352
0
    if (output == NULL) return;
1353
0
    xmlCtxtDumpInitCtxt(&ctxt);
1354
0
    ctxt.output = output;
1355
0
    ctxt.depth = depth;
1356
0
    xmlCtxtDumpAttr(&ctxt, attr);
1357
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1358
0
}
1359
1360
1361
/**
1362
 * xmlDebugDumpEntities:
1363
 * @output:  the FILE * for the output
1364
 * @doc:  the document
1365
 *
1366
 * Dumps debug information for all the entities in use by the document
1367
 */
1368
void
1369
xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1370
0
{
1371
0
    xmlDebugCtxt ctxt;
1372
1373
0
    if (output == NULL) return;
1374
0
    xmlCtxtDumpInitCtxt(&ctxt);
1375
0
    ctxt.output = output;
1376
0
    xmlCtxtDumpEntities(&ctxt, doc);
1377
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1378
0
}
1379
1380
/**
1381
 * xmlDebugDumpAttrList:
1382
 * @output:  the FILE * for the output
1383
 * @attr:  the attribute list
1384
 * @depth:  the indentation level.
1385
 *
1386
 * Dumps debug information for the attribute list
1387
 */
1388
void
1389
xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
1390
0
{
1391
0
    xmlDebugCtxt ctxt;
1392
1393
0
    if (output == NULL) return;
1394
0
    xmlCtxtDumpInitCtxt(&ctxt);
1395
0
    ctxt.output = output;
1396
0
    ctxt.depth = depth;
1397
0
    xmlCtxtDumpAttrList(&ctxt, attr);
1398
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1399
0
}
1400
1401
/**
1402
 * xmlDebugDumpOneNode:
1403
 * @output:  the FILE * for the output
1404
 * @node:  the node
1405
 * @depth:  the indentation level.
1406
 *
1407
 * Dumps debug information for the element node, it is not recursive
1408
 */
1409
void
1410
xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
1411
0
{
1412
0
    xmlDebugCtxt ctxt;
1413
1414
0
    if (output == NULL) return;
1415
0
    xmlCtxtDumpInitCtxt(&ctxt);
1416
0
    ctxt.output = output;
1417
0
    ctxt.depth = depth;
1418
0
    xmlCtxtDumpOneNode(&ctxt, node);
1419
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1420
0
}
1421
1422
/**
1423
 * xmlDebugDumpNode:
1424
 * @output:  the FILE * for the output
1425
 * @node:  the node
1426
 * @depth:  the indentation level.
1427
 *
1428
 * Dumps debug information for the element node, it is recursive
1429
 */
1430
void
1431
xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
1432
0
{
1433
0
    xmlDebugCtxt ctxt;
1434
1435
0
    if (output == NULL)
1436
0
  output = stdout;
1437
0
    xmlCtxtDumpInitCtxt(&ctxt);
1438
0
    ctxt.output = output;
1439
0
    ctxt.depth = depth;
1440
0
    xmlCtxtDumpNode(&ctxt, node);
1441
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1442
0
}
1443
1444
/**
1445
 * xmlDebugDumpNodeList:
1446
 * @output:  the FILE * for the output
1447
 * @node:  the node list
1448
 * @depth:  the indentation level.
1449
 *
1450
 * Dumps debug information for the list of element node, it is recursive
1451
 */
1452
void
1453
xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
1454
0
{
1455
0
    xmlDebugCtxt ctxt;
1456
1457
0
    if (output == NULL)
1458
0
  output = stdout;
1459
0
    xmlCtxtDumpInitCtxt(&ctxt);
1460
0
    ctxt.output = output;
1461
0
    ctxt.depth = depth;
1462
0
    xmlCtxtDumpNodeList(&ctxt, node);
1463
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1464
0
}
1465
1466
/**
1467
 * xmlDebugDumpDocumentHead:
1468
 * @output:  the FILE * for the output
1469
 * @doc:  the document
1470
 *
1471
 * Dumps debug information concerning the document, not recursive
1472
 */
1473
void
1474
xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
1475
0
{
1476
0
    xmlDebugCtxt ctxt;
1477
1478
0
    if (output == NULL)
1479
0
  output = stdout;
1480
0
    xmlCtxtDumpInitCtxt(&ctxt);
1481
0
    ctxt.options |= DUMP_TEXT_TYPE;
1482
0
    ctxt.output = output;
1483
0
    xmlCtxtDumpDocumentHead(&ctxt, doc);
1484
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1485
0
}
1486
1487
/**
1488
 * xmlDebugDumpDocument:
1489
 * @output:  the FILE * for the output
1490
 * @doc:  the document
1491
 *
1492
 * Dumps debug information for the document, it's recursive
1493
 */
1494
void
1495
xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
1496
0
{
1497
0
    xmlDebugCtxt ctxt;
1498
1499
0
    if (output == NULL)
1500
0
  output = stdout;
1501
0
    xmlCtxtDumpInitCtxt(&ctxt);
1502
0
    ctxt.options |= DUMP_TEXT_TYPE;
1503
0
    ctxt.output = output;
1504
0
    xmlCtxtDumpDocument(&ctxt, doc);
1505
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1506
0
}
1507
1508
/**
1509
 * xmlDebugDumpDTD:
1510
 * @output:  the FILE * for the output
1511
 * @dtd:  the DTD
1512
 *
1513
 * Dumps debug information for the DTD
1514
 */
1515
void
1516
xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
1517
0
{
1518
0
    xmlDebugCtxt ctxt;
1519
1520
0
    if (output == NULL)
1521
0
  output = stdout;
1522
0
    xmlCtxtDumpInitCtxt(&ctxt);
1523
0
    ctxt.options |= DUMP_TEXT_TYPE;
1524
0
    ctxt.output = output;
1525
0
    xmlCtxtDumpDTD(&ctxt, dtd);
1526
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1527
0
}
1528
1529
/************************************************************************
1530
 *                  *
1531
 *      Public entry points for checkings   *
1532
 *                  *
1533
 ************************************************************************/
1534
1535
/**
1536
 * xmlDebugCheckDocument:
1537
 * @output:  the FILE * for the output
1538
 * @doc:  the document
1539
 *
1540
 * Check the document for potential content problems, and output
1541
 * the errors to @output
1542
 *
1543
 * Returns the number of errors found
1544
 */
1545
int
1546
xmlDebugCheckDocument(FILE * output, xmlDocPtr doc)
1547
0
{
1548
0
    xmlDebugCtxt ctxt;
1549
1550
0
    if (output == NULL)
1551
0
  output = stdout;
1552
0
    xmlCtxtDumpInitCtxt(&ctxt);
1553
0
    ctxt.output = output;
1554
0
    ctxt.check = 1;
1555
0
    xmlCtxtDumpDocument(&ctxt, doc);
1556
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1557
0
    return(ctxt.errors);
1558
0
}
1559
1560
#endif /* LIBXML_DEBUG_ENABLED */