Coverage Report

Created: 2025-06-22 06:55

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