Coverage Report

Created: 2025-07-11 06:13

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