~ubuntu-branches/ubuntu/wily/opencollada/wily-proposed

« back to all changes in this revision

Viewing changes to Externals/LibXML/debugXML.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2015-05-14 17:23:27 UTC
  • Revision ID: package-import@ubuntu.com-20150514172327-f862u8envms01fra
Tags: upstream-0.1.0~20140703.ddf8f47+dfsg1
ImportĀ upstreamĀ versionĀ 0.1.0~20140703.ddf8f47+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * debugXML.c : This is a set of routines used for debugging the tree
 
3
 *              produced by the XML parser.
 
4
 *
 
5
 * See Copyright for the status of this software.
 
6
 *
 
7
 * Daniel Veillard <daniel@veillard.com>
 
8
 */
 
9
 
 
10
#define IN_LIBXML
 
11
#include "libxml.h"
 
12
#ifdef LIBXML_DEBUG_ENABLED
 
13
 
 
14
#include <string.h>
 
15
#ifdef HAVE_STDLIB_H
 
16
#include <stdlib.h>
 
17
#endif
 
18
#ifdef HAVE_STRING_H
 
19
#include <string.h>
 
20
#endif
 
21
#include <libxml/xmlmemory.h>
 
22
#include <libxml/tree.h>
 
23
#include <libxml/parser.h>
 
24
#include <libxml/parserInternals.h>
 
25
#include <libxml/valid.h>
 
26
#include <libxml/debugXML.h>
 
27
#include <libxml/HTMLtree.h>
 
28
#include <libxml/HTMLparser.h>
 
29
#include <libxml/xmlerror.h>
 
30
#include <libxml/globals.h>
 
31
#include <libxml/xpathInternals.h>
 
32
#include <libxml/uri.h>
 
33
#ifdef LIBXML_SCHEMAS_ENABLED
 
34
#include <libxml/relaxng.h>
 
35
#endif
 
36
 
 
37
#define DUMP_TEXT_TYPE 1
 
38
 
 
39
typedef struct _xmlDebugCtxt xmlDebugCtxt;
 
40
typedef xmlDebugCtxt *xmlDebugCtxtPtr;
 
41
struct _xmlDebugCtxt {
 
42
    FILE *output;               /* the output file */
 
43
    char shift[101];            /* used for indenting */
 
44
    int depth;                  /* current depth */
 
45
    xmlDocPtr doc;              /* current document */
 
46
    xmlNodePtr node;            /* current node */
 
47
    xmlDictPtr dict;            /* the doc dictionnary */
 
48
    int check;                  /* do just checkings */
 
49
    int errors;                 /* number of errors found */
 
50
    int nodict;                 /* if the document has no dictionnary */
 
51
    int options;                /* options */
 
52
};
 
53
 
 
54
static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
 
55
 
 
56
static void
 
57
xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt)
 
58
{
 
59
    int i;
 
60
 
 
61
    ctxt->depth = 0;
 
62
    ctxt->check = 0;
 
63
    ctxt->errors = 0;
 
64
    ctxt->output = stdout;
 
65
    ctxt->doc = NULL;
 
66
    ctxt->node = NULL;
 
67
    ctxt->dict = NULL;
 
68
    ctxt->nodict = 0;
 
69
    ctxt->options = 0;
 
70
    for (i = 0; i < 100; i++)
 
71
        ctxt->shift[i] = ' ';
 
72
    ctxt->shift[100] = 0;
 
73
}
 
74
 
 
75
static void
 
76
xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED)
 
77
{
 
78
 /* remove the ATTRIBUTE_UNUSED when this is added */
 
79
}
 
80
 
 
81
/**
 
82
 * xmlNsCheckScope:
 
83
 * @node: the node
 
84
 * @ns: the namespace node
 
85
 *
 
86
 * Check that a given namespace is in scope on a node.
 
87
 *
 
88
 * Returns 1 if in scope, -1 in case of argument error, 
 
89
 *         -2 if the namespace is not in scope, and -3 if not on
 
90
 *         an ancestor node.
 
91
 */
 
92
static int
 
93
xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
 
94
{
 
95
    xmlNsPtr cur;
 
96
 
 
97
    if ((node == NULL) || (ns == NULL))
 
98
        return(-1);
 
99
 
 
100
    if ((node->type != XML_ELEMENT_NODE) &&
 
101
        (node->type != XML_ATTRIBUTE_NODE) &&
 
102
        (node->type != XML_DOCUMENT_NODE) &&
 
103
        (node->type != XML_TEXT_NODE) &&
 
104
        (node->type != XML_HTML_DOCUMENT_NODE) &&
 
105
        (node->type != XML_XINCLUDE_START))
 
106
        return(-2);
 
107
 
 
108
    while ((node != NULL) &&
 
109
           ((node->type == XML_ELEMENT_NODE) ||
 
110
            (node->type == XML_ATTRIBUTE_NODE) ||
 
111
            (node->type == XML_TEXT_NODE) ||
 
112
            (node->type == XML_XINCLUDE_START))) {
 
113
        if ((node->type == XML_ELEMENT_NODE) ||
 
114
            (node->type == XML_XINCLUDE_START)) {
 
115
            cur = node->nsDef;
 
116
            while (cur != NULL) {
 
117
                if (cur == ns)
 
118
                    return(1);
 
119
                if (xmlStrEqual(cur->prefix, ns->prefix))
 
120
                    return(-2);
 
121
                cur = cur->next;
 
122
            }
 
123
        }
 
124
        node = node->parent;
 
125
    }
 
126
    /* the xml namespace may be declared on the document node */
 
127
    if ((node != NULL) &&
 
128
        ((node->type == XML_DOCUMENT_NODE) ||
 
129
         (node->type == XML_HTML_DOCUMENT_NODE))) {
 
130
         xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
 
131
         if (oldNs == ns)
 
132
             return(1);
 
133
    }
 
134
    return(-3);
 
135
}
 
136
 
 
137
static void
 
138
xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
 
139
{
 
140
    if (ctxt->check)
 
141
        return;
 
142
    if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
 
143
        if (ctxt->depth < 50)
 
144
            fprintf(ctxt->output, &ctxt->shift[100 - 2 * ctxt->depth]);
 
145
        else
 
146
            fprintf(ctxt->output, ctxt->shift);
 
147
    }
 
148
}
 
149
 
 
150
/**
 
151
 * xmlDebugErr:
 
152
 * @ctxt:  a debug context
 
153
 * @error:  the error code
 
154
 *
 
155
 * Handle a debug error.
 
156
 */
 
157
static void
 
158
xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
 
159
{
 
160
    ctxt->errors++;
 
161
    __xmlRaiseError(NULL, NULL, NULL,
 
162
                    NULL, ctxt->node, XML_FROM_CHECK,
 
163
                    error, XML_ERR_ERROR, NULL, 0,
 
164
                    NULL, NULL, NULL, 0, 0,
 
165
                    msg);
 
166
}
 
167
static void
 
168
xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
 
169
{
 
170
    ctxt->errors++;
 
171
    __xmlRaiseError(NULL, NULL, NULL,
 
172
                    NULL, ctxt->node, XML_FROM_CHECK,
 
173
                    error, XML_ERR_ERROR, NULL, 0,
 
174
                    NULL, NULL, NULL, 0, 0,
 
175
                    msg, extra);
 
176
}
 
177
static void
 
178
xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
 
179
{
 
180
    ctxt->errors++;
 
181
    __xmlRaiseError(NULL, NULL, NULL,
 
182
                    NULL, ctxt->node, XML_FROM_CHECK,
 
183
                    error, XML_ERR_ERROR, NULL, 0,
 
184
                    NULL, NULL, NULL, 0, 0,
 
185
                    msg, extra);
 
186
}
 
187
 
 
188
/**
 
189
 * xmlCtxtNsCheckScope:
 
190
 * @ctxt: the debugging context
 
191
 * @node: the node
 
192
 * @ns: the namespace node
 
193
 *
 
194
 * Report if a given namespace is is not in scope.
 
195
 */
 
196
static void
 
197
xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns)
 
198
{
 
199
    int ret;
 
200
 
 
201
    ret = xmlNsCheckScope(node, ns);
 
202
    if (ret == -2) {
 
203
        if (ns->prefix == NULL)
 
204
            xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
 
205
                        "Reference to default namespace not in scope\n");
 
206
        else
 
207
            xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
 
208
                         "Reference to namespace '%s' not in scope\n",
 
209
                         (char *) ns->prefix);
 
210
    }
 
211
    if (ret == -3) {
 
212
        if (ns->prefix == NULL)
 
213
            xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
 
214
                        "Reference to default namespace not on ancestor\n");
 
215
        else
 
216
            xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
 
217
                         "Reference to namespace '%s' not on ancestor\n",
 
218
                         (char *) ns->prefix);
 
219
    }
 
220
}
 
221
 
 
222
/**
 
223
 * xmlCtxtCheckString:
 
224
 * @ctxt: the debug context
 
225
 * @str: the string
 
226
 *
 
227
 * Do debugging on the string, currently it just checks the UTF-8 content
 
228
 */
 
229
static void
 
230
xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
 
231
{
 
232
    if (str == NULL) return;
 
233
    if (ctxt->check) {
 
234
        if (!xmlCheckUTF8(str)) {
 
235
            xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8,
 
236
                         "String is not UTF-8 %s", (const char *) str);
 
237
        }
 
238
    }
 
239
}
 
240
 
 
241
/**
 
242
 * xmlCtxtCheckName:
 
243
 * @ctxt: the debug context
 
244
 * @name: the name
 
245
 *
 
246
 * Do debugging on the name, for example the dictionnary status and
 
247
 * conformance to the Name production.
 
248
 */
 
249
static void
 
250
xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name)
 
251
{
 
252
    if (ctxt->check) {
 
253
        if (name == NULL) {
 
254
            xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL");
 
255
            return;
 
256
        }
 
257
        if (xmlValidateName(name, 0)) {
 
258
            xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME,
 
259
                         "Name is not an NCName '%s'", (const char *) name);
 
260
        }
 
261
        if ((ctxt->dict != NULL) &&
 
262
            (!xmlDictOwns(ctxt->dict, name))) {
 
263
            xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
 
264
                         "Name is not from the document dictionnary '%s'",
 
265
                         (const char *) name);
 
266
        }
 
267
    }
 
268
}
 
269
 
 
270
static void
 
271
xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
 
272
    xmlDocPtr doc;
 
273
    xmlDictPtr dict;
 
274
 
 
275
    doc = node->doc;
 
276
 
 
277
    if (node->parent == NULL)
 
278
        xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
 
279
                    "Node has no parent\n");
 
280
    if (node->doc == NULL) {
 
281
        xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
 
282
                    "Node has no doc\n");
 
283
        dict = NULL;
 
284
    } else {
 
285
        dict = doc->dict;
 
286
        if ((dict == NULL) && (ctxt->nodict == 0)) {
 
287
#if 0
 
288
            /* desactivated right now as it raises too many errors */
 
289
            if (doc->type == XML_DOCUMENT_NODE)
 
290
                xmlDebugErr(ctxt, XML_CHECK_NO_DICT,
 
291
                            "Document has no dictionnary\n");
 
292
#endif
 
293
            ctxt->nodict = 1;
 
294
        }
 
295
        if (ctxt->doc == NULL)
 
296
            ctxt->doc = doc;
 
297
 
 
298
        if (ctxt->dict == NULL) {
 
299
            ctxt->dict = dict;
 
300
        }
 
301
    }
 
302
    if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
 
303
        (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
 
304
        xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
 
305
                    "Node doc differs from parent's one\n");
 
306
    if (node->prev == NULL) {
 
307
        if (node->type == XML_ATTRIBUTE_NODE) {
 
308
            if ((node->parent != NULL) &&
 
309
                (node != (xmlNodePtr) node->parent->properties))
 
310
                xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
 
311
                    "Attr has no prev and not first of attr list\n");
 
312
                
 
313
        } else if ((node->parent != NULL) && (node->parent->children != node))
 
314
            xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
 
315
                    "Node has no prev and not first of parent list\n");
 
316
    } else {
 
317
        if (node->prev->next != node)
 
318
            xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
 
319
                        "Node prev->next : back link wrong\n");
 
320
    }
 
321
    if (node->next == NULL) {
 
322
        if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
 
323
            (node->parent->last != node) &&
 
324
            (node->parent->type == XML_ELEMENT_NODE))
 
325
            xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
 
326
                    "Node has no next and not last of parent list\n");
 
327
    } else {
 
328
        if (node->next->prev != node)
 
329
            xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
 
330
                    "Node next->prev : forward link wrong\n");
 
331
        if (node->next->parent != node->parent)
 
332
            xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
 
333
                    "Node next->prev : forward link wrong\n");
 
334
    }
 
335
    if (node->type == XML_ELEMENT_NODE) {
 
336
        xmlNsPtr ns;
 
337
 
 
338
        ns = node->nsDef;
 
339
        while (ns != NULL) {
 
340
            xmlCtxtNsCheckScope(ctxt, node, ns);
 
341
            ns = ns->next;
 
342
        }
 
343
        if (node->ns != NULL)
 
344
            xmlCtxtNsCheckScope(ctxt, node, node->ns);
 
345
    } else if (node->type == XML_ATTRIBUTE_NODE) {
 
346
        if (node->ns != NULL)
 
347
            xmlCtxtNsCheckScope(ctxt, node, node->ns);
 
348
    }
 
349
 
 
350
    if ((node->type != XML_ELEMENT_NODE) &&
 
351
        (node->type != XML_ATTRIBUTE_NODE) &&
 
352
        (node->type != XML_ELEMENT_DECL) &&
 
353
        (node->type != XML_ATTRIBUTE_DECL) &&
 
354
        (node->type != XML_DTD_NODE) &&
 
355
        (node->type != XML_ELEMENT_DECL) &&
 
356
        (node->type != XML_HTML_DOCUMENT_NODE) &&
 
357
        (node->type != XML_DOCUMENT_NODE)) {
 
358
        if (node->content != NULL)
 
359
            xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
 
360
    }
 
361
    switch (node->type) {
 
362
        case XML_ELEMENT_NODE:
 
363
        case XML_ATTRIBUTE_NODE:
 
364
            xmlCtxtCheckName(ctxt, node->name);
 
365
            break;
 
366
        case XML_TEXT_NODE:
 
367
            if ((node->name == xmlStringText) ||
 
368
                (node->name == xmlStringTextNoenc))
 
369
                break;
 
370
            /* some case of entity substitution can lead to this */
 
371
            if ((ctxt->dict != NULL) &&
 
372
                (node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
 
373
                                             7)))
 
374
                break;
 
375
 
 
376
            xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
 
377
                         "Text node has wrong name '%s'",
 
378
                         (const char *) node->name);
 
379
            break;
 
380
        case XML_COMMENT_NODE:
 
381
            if (node->name == xmlStringComment)
 
382
                break;
 
383
            xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
 
384
                         "Comment node has wrong name '%s'",
 
385
                         (const char *) node->name);
 
386
            break;
 
387
        case XML_PI_NODE:
 
388
            xmlCtxtCheckName(ctxt, node->name);
 
389
            break;
 
390
        case XML_CDATA_SECTION_NODE:
 
391
            if (node->name == NULL)
 
392
                break;
 
393
            xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL,
 
394
                         "CData section has non NULL name '%s'",
 
395
                         (const char *) node->name);
 
396
            break;
 
397
        case XML_ENTITY_REF_NODE:
 
398
        case XML_ENTITY_NODE:
 
399
        case XML_DOCUMENT_TYPE_NODE:
 
400
        case XML_DOCUMENT_FRAG_NODE:
 
401
        case XML_NOTATION_NODE:
 
402
        case XML_DTD_NODE:
 
403
        case XML_ELEMENT_DECL:
 
404
        case XML_ATTRIBUTE_DECL:
 
405
        case XML_ENTITY_DECL:
 
406
        case XML_NAMESPACE_DECL:
 
407
        case XML_XINCLUDE_START:
 
408
        case XML_XINCLUDE_END:
 
409
#ifdef LIBXML_DOCB_ENABLED
 
410
        case XML_DOCB_DOCUMENT_NODE:
 
411
#endif
 
412
        case XML_DOCUMENT_NODE:
 
413
        case XML_HTML_DOCUMENT_NODE:
 
414
            break;
 
415
    }
 
416
}
 
417
 
 
418
static void
 
419
xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
 
420
{
 
421
    int i;
 
422
 
 
423
    if (ctxt->check) {
 
424
        return;
 
425
    }
 
426
    /* TODO: check UTF8 content of the string */
 
427
    if (str == NULL) {
 
428
        fprintf(ctxt->output, "(NULL)");
 
429
        return;
 
430
    }
 
431
    for (i = 0; i < 40; i++)
 
432
        if (str[i] == 0)
 
433
            return;
 
434
        else if (IS_BLANK_CH(str[i]))
 
435
            fputc(' ', ctxt->output);
 
436
        else if (str[i] >= 0x80)
 
437
            fprintf(ctxt->output, "#%X", str[i]);
 
438
        else
 
439
            fputc(str[i], ctxt->output);
 
440
    fprintf(ctxt->output, "...");
 
441
}
 
442
 
 
443
static void
 
444
xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
 
445
{
 
446
    xmlCtxtDumpSpaces(ctxt);
 
447
 
 
448
    if (dtd == NULL) {
 
449
        if (!ctxt->check)
 
450
            fprintf(ctxt->output, "DTD node is NULL\n");
 
451
        return;
 
452
    }
 
453
 
 
454
    if (dtd->type != XML_DTD_NODE) {
 
455
        xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
 
456
                    "Node is not a DTD");
 
457
        return;
 
458
    }
 
459
    if (!ctxt->check) {
 
460
        if (dtd->name != NULL)
 
461
            fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
 
462
        else
 
463
            fprintf(ctxt->output, "DTD");
 
464
        if (dtd->ExternalID != NULL)
 
465
            fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
 
466
        if (dtd->SystemID != NULL)
 
467
            fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
 
468
        fprintf(ctxt->output, "\n");
 
469
    }
 
470
    /*
 
471
     * Do a bit of checking
 
472
     */
 
473
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
 
474
}
 
475
 
 
476
static void
 
477
xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr)
 
478
{
 
479
    xmlCtxtDumpSpaces(ctxt);
 
480
 
 
481
    if (attr == NULL) {
 
482
        if (!ctxt->check)
 
483
            fprintf(ctxt->output, "Attribute declaration is NULL\n");
 
484
        return;
 
485
    }
 
486
    if (attr->type != XML_ATTRIBUTE_DECL) {
 
487
        xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
 
488
                    "Node is not an attribute declaration");
 
489
        return;
 
490
    }
 
491
    if (attr->name != NULL) {
 
492
        if (!ctxt->check)
 
493
            fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
 
494
    } else
 
495
        xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
 
496
                    "Node attribute declaration has no name");
 
497
    if (attr->elem != NULL) {
 
498
        if (!ctxt->check)
 
499
            fprintf(ctxt->output, " for %s", (char *) attr->elem);
 
500
    } else
 
501
        xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
 
502
                    "Node attribute declaration has no element name");
 
503
    if (!ctxt->check) {
 
504
        switch (attr->atype) {
 
505
            case XML_ATTRIBUTE_CDATA:
 
506
                fprintf(ctxt->output, " CDATA");
 
507
                break;
 
508
            case XML_ATTRIBUTE_ID:
 
509
                fprintf(ctxt->output, " ID");
 
510
                break;
 
511
            case XML_ATTRIBUTE_IDREF:
 
512
                fprintf(ctxt->output, " IDREF");
 
513
                break;
 
514
            case XML_ATTRIBUTE_IDREFS:
 
515
                fprintf(ctxt->output, " IDREFS");
 
516
                break;
 
517
            case XML_ATTRIBUTE_ENTITY:
 
518
                fprintf(ctxt->output, " ENTITY");
 
519
                break;
 
520
            case XML_ATTRIBUTE_ENTITIES:
 
521
                fprintf(ctxt->output, " ENTITIES");
 
522
                break;
 
523
            case XML_ATTRIBUTE_NMTOKEN:
 
524
                fprintf(ctxt->output, " NMTOKEN");
 
525
                break;
 
526
            case XML_ATTRIBUTE_NMTOKENS:
 
527
                fprintf(ctxt->output, " NMTOKENS");
 
528
                break;
 
529
            case XML_ATTRIBUTE_ENUMERATION:
 
530
                fprintf(ctxt->output, " ENUMERATION");
 
531
                break;
 
532
            case XML_ATTRIBUTE_NOTATION:
 
533
                fprintf(ctxt->output, " NOTATION ");
 
534
                break;
 
535
        }
 
536
        if (attr->tree != NULL) {
 
537
            int indx;
 
538
            xmlEnumerationPtr cur = attr->tree;
 
539
 
 
540
            for (indx = 0; indx < 5; indx++) {
 
541
                if (indx != 0)
 
542
                    fprintf(ctxt->output, "|%s", (char *) cur->name);
 
543
                else
 
544
                    fprintf(ctxt->output, " (%s", (char *) cur->name);
 
545
                cur = cur->next;
 
546
                if (cur == NULL)
 
547
                    break;
 
548
            }
 
549
            if (cur == NULL)
 
550
                fprintf(ctxt->output, ")");
 
551
            else
 
552
                fprintf(ctxt->output, "...)");
 
553
        }
 
554
        switch (attr->def) {
 
555
            case XML_ATTRIBUTE_NONE:
 
556
                break;
 
557
            case XML_ATTRIBUTE_REQUIRED:
 
558
                fprintf(ctxt->output, " REQUIRED");
 
559
                break;
 
560
            case XML_ATTRIBUTE_IMPLIED:
 
561
                fprintf(ctxt->output, " IMPLIED");
 
562
                break;
 
563
            case XML_ATTRIBUTE_FIXED:
 
564
                fprintf(ctxt->output, " FIXED");
 
565
                break;
 
566
        }
 
567
        if (attr->defaultValue != NULL) {
 
568
            fprintf(ctxt->output, "\"");
 
569
            xmlCtxtDumpString(ctxt, attr->defaultValue);
 
570
            fprintf(ctxt->output, "\"");
 
571
        }
 
572
        fprintf(ctxt->output, "\n");
 
573
    }
 
574
 
 
575
    /*
 
576
     * Do a bit of checking
 
577
     */
 
578
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
 
579
}
 
580
 
 
581
static void
 
582
xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem)
 
583
{
 
584
    xmlCtxtDumpSpaces(ctxt);
 
585
 
 
586
    if (elem == NULL) {
 
587
        if (!ctxt->check)
 
588
            fprintf(ctxt->output, "Element declaration is NULL\n");
 
589
        return;
 
590
    }
 
591
    if (elem->type != XML_ELEMENT_DECL) {
 
592
        xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
 
593
                    "Node is not an element declaration");
 
594
        return;
 
595
    }
 
596
    if (elem->name != NULL) {
 
597
        if (!ctxt->check) {
 
598
            fprintf(ctxt->output, "ELEMDECL(");
 
599
            xmlCtxtDumpString(ctxt, elem->name);
 
600
            fprintf(ctxt->output, ")");
 
601
        }
 
602
    } else
 
603
        xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
 
604
                    "Element declaration has no name");
 
605
    if (!ctxt->check) {
 
606
        switch (elem->etype) {
 
607
            case XML_ELEMENT_TYPE_UNDEFINED:
 
608
                fprintf(ctxt->output, ", UNDEFINED");
 
609
                break;
 
610
            case XML_ELEMENT_TYPE_EMPTY:
 
611
                fprintf(ctxt->output, ", EMPTY");
 
612
                break;
 
613
            case XML_ELEMENT_TYPE_ANY:
 
614
                fprintf(ctxt->output, ", ANY");
 
615
                break;
 
616
            case XML_ELEMENT_TYPE_MIXED:
 
617
                fprintf(ctxt->output, ", MIXED ");
 
618
                break;
 
619
            case XML_ELEMENT_TYPE_ELEMENT:
 
620
                fprintf(ctxt->output, ", MIXED ");
 
621
                break;
 
622
        }
 
623
        if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) {
 
624
            char buf[5001];
 
625
 
 
626
            buf[0] = 0;
 
627
            xmlSnprintfElementContent(buf, 5000, elem->content, 1);
 
628
            buf[5000] = 0;
 
629
            fprintf(ctxt->output, "%s", buf);
 
630
        }
 
631
        fprintf(ctxt->output, "\n");
 
632
    }
 
633
 
 
634
    /*
 
635
     * Do a bit of checking
 
636
     */
 
637
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
 
638
}
 
639
 
 
640
static void
 
641
xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
 
642
{
 
643
    xmlCtxtDumpSpaces(ctxt);
 
644
 
 
645
    if (ent == NULL) {
 
646
        if (!ctxt->check)
 
647
            fprintf(ctxt->output, "Entity declaration is NULL\n");
 
648
        return;
 
649
    }
 
650
    if (ent->type != XML_ENTITY_DECL) {
 
651
        xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
 
652
                    "Node is not an entity declaration");
 
653
        return;
 
654
    }
 
655
    if (ent->name != NULL) {
 
656
        if (!ctxt->check) {
 
657
            fprintf(ctxt->output, "ENTITYDECL(");
 
658
            xmlCtxtDumpString(ctxt, ent->name);
 
659
            fprintf(ctxt->output, ")");
 
660
        }
 
661
    } else
 
662
        xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
 
663
                    "Entity declaration has no name");
 
664
    if (!ctxt->check) {
 
665
        switch (ent->etype) {
 
666
            case XML_INTERNAL_GENERAL_ENTITY:
 
667
                fprintf(ctxt->output, ", internal\n");
 
668
                break;
 
669
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
 
670
                fprintf(ctxt->output, ", external parsed\n");
 
671
                break;
 
672
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
 
673
                fprintf(ctxt->output, ", unparsed\n");
 
674
                break;
 
675
            case XML_INTERNAL_PARAMETER_ENTITY:
 
676
                fprintf(ctxt->output, ", parameter\n");
 
677
                break;
 
678
            case XML_EXTERNAL_PARAMETER_ENTITY:
 
679
                fprintf(ctxt->output, ", external parameter\n");
 
680
                break;
 
681
            case XML_INTERNAL_PREDEFINED_ENTITY:
 
682
                fprintf(ctxt->output, ", predefined\n");
 
683
                break;
 
684
        }
 
685
        if (ent->ExternalID) {
 
686
            xmlCtxtDumpSpaces(ctxt);
 
687
            fprintf(ctxt->output, " ExternalID=%s\n",
 
688
                    (char *) ent->ExternalID);
 
689
        }
 
690
        if (ent->SystemID) {
 
691
            xmlCtxtDumpSpaces(ctxt);
 
692
            fprintf(ctxt->output, " SystemID=%s\n",
 
693
                    (char *) ent->SystemID);
 
694
        }
 
695
        if (ent->URI != NULL) {
 
696
            xmlCtxtDumpSpaces(ctxt);
 
697
            fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI);
 
698
        }
 
699
        if (ent->content) {
 
700
            xmlCtxtDumpSpaces(ctxt);
 
701
            fprintf(ctxt->output, " content=");
 
702
            xmlCtxtDumpString(ctxt, ent->content);
 
703
            fprintf(ctxt->output, "\n");
 
704
        }
 
705
    }
 
706
 
 
707
    /*
 
708
     * Do a bit of checking
 
709
     */
 
710
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
 
711
}
 
712
 
 
713
static void
 
714
xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
 
715
{
 
716
    xmlCtxtDumpSpaces(ctxt);
 
717
 
 
718
    if (ns == NULL) {
 
719
        if (!ctxt->check)
 
720
            fprintf(ctxt->output, "namespace node is NULL\n");
 
721
        return;
 
722
    }
 
723
    if (ns->type != XML_NAMESPACE_DECL) {
 
724
        xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
 
725
                    "Node is not a namespace declaration");
 
726
        return;
 
727
    }
 
728
    if (ns->href == NULL) {
 
729
        if (ns->prefix != NULL)
 
730
            xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
 
731
                    "Incomplete namespace %s href=NULL\n",
 
732
                    (char *) ns->prefix);
 
733
        else
 
734
            xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
 
735
                    "Incomplete default namespace href=NULL\n");
 
736
    } else {
 
737
        if (!ctxt->check) {
 
738
            if (ns->prefix != NULL)
 
739
                fprintf(ctxt->output, "namespace %s href=",
 
740
                        (char *) ns->prefix);
 
741
            else
 
742
                fprintf(ctxt->output, "default namespace href=");
 
743
 
 
744
            xmlCtxtDumpString(ctxt, ns->href);
 
745
            fprintf(ctxt->output, "\n");
 
746
        }
 
747
    }
 
748
}
 
749
 
 
750
static void
 
751
xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
 
752
{
 
753
    while (ns != NULL) {
 
754
        xmlCtxtDumpNamespace(ctxt, ns);
 
755
        ns = ns->next;
 
756
    }
 
757
}
 
758
 
 
759
static void
 
760
xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
 
761
{
 
762
    xmlCtxtDumpSpaces(ctxt);
 
763
 
 
764
    if (ent == NULL) {
 
765
        if (!ctxt->check)
 
766
            fprintf(ctxt->output, "Entity is NULL\n");
 
767
        return;
 
768
    }
 
769
    if (!ctxt->check) {
 
770
        switch (ent->etype) {
 
771
            case XML_INTERNAL_GENERAL_ENTITY:
 
772
                fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY ");
 
773
                break;
 
774
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
 
775
                fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
 
776
                break;
 
777
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
 
778
                fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
 
779
                break;
 
780
            case XML_INTERNAL_PARAMETER_ENTITY:
 
781
                fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY ");
 
782
                break;
 
783
            case XML_EXTERNAL_PARAMETER_ENTITY:
 
784
                fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY ");
 
785
                break;
 
786
            default:
 
787
                fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype);
 
788
        }
 
789
        fprintf(ctxt->output, "%s\n", ent->name);
 
790
        if (ent->ExternalID) {
 
791
            xmlCtxtDumpSpaces(ctxt);
 
792
            fprintf(ctxt->output, "ExternalID=%s\n",
 
793
                    (char *) ent->ExternalID);
 
794
        }
 
795
        if (ent->SystemID) {
 
796
            xmlCtxtDumpSpaces(ctxt);
 
797
            fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID);
 
798
        }
 
799
        if (ent->URI) {
 
800
            xmlCtxtDumpSpaces(ctxt);
 
801
            fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI);
 
802
        }
 
803
        if (ent->content) {
 
804
            xmlCtxtDumpSpaces(ctxt);
 
805
            fprintf(ctxt->output, "content=");
 
806
            xmlCtxtDumpString(ctxt, ent->content);
 
807
            fprintf(ctxt->output, "\n");
 
808
        }
 
809
    }
 
810
}
 
811
 
 
812
/**
 
813
 * xmlCtxtDumpAttr:
 
814
 * @output:  the FILE * for the output
 
815
 * @attr:  the attribute
 
816
 * @depth:  the indentation level.
 
817
 *
 
818
 * Dumps debug information for the attribute
 
819
 */
 
820
static void
 
821
xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
 
822
{
 
823
    xmlCtxtDumpSpaces(ctxt);
 
824
 
 
825
    if (attr == NULL) {
 
826
        if (!ctxt->check)
 
827
            fprintf(ctxt->output, "Attr is NULL");
 
828
        return;
 
829
    }
 
830
    if (!ctxt->check) {
 
831
        fprintf(ctxt->output, "ATTRIBUTE ");
 
832
        xmlCtxtDumpString(ctxt, attr->name);
 
833
        fprintf(ctxt->output, "\n");
 
834
        if (attr->children != NULL) {
 
835
            ctxt->depth++;
 
836
            xmlCtxtDumpNodeList(ctxt, attr->children);
 
837
            ctxt->depth--;
 
838
        }
 
839
    }
 
840
    if (attr->name == NULL)
 
841
        xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
 
842
                    "Attribute has no name");
 
843
 
 
844
    /*
 
845
     * Do a bit of checking
 
846
     */
 
847
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
 
848
}
 
849
 
 
850
/**
 
851
 * xmlCtxtDumpAttrList:
 
852
 * @output:  the FILE * for the output
 
853
 * @attr:  the attribute list
 
854
 * @depth:  the indentation level.
 
855
 *
 
856
 * Dumps debug information for the attribute list
 
857
 */
 
858
static void
 
859
xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
 
860
{
 
861
    while (attr != NULL) {
 
862
        xmlCtxtDumpAttr(ctxt, attr);
 
863
        attr = attr->next;
 
864
    }
 
865
}
 
866
 
 
867
/**
 
868
 * xmlCtxtDumpOneNode:
 
869
 * @output:  the FILE * for the output
 
870
 * @node:  the node
 
871
 * @depth:  the indentation level.
 
872
 *
 
873
 * Dumps debug information for the element node, it is not recursive
 
874
 */
 
875
static void
 
876
xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
 
877
{
 
878
    if (node == NULL) {
 
879
        if (!ctxt->check) {
 
880
            xmlCtxtDumpSpaces(ctxt);
 
881
            fprintf(ctxt->output, "node is NULL\n");
 
882
        }
 
883
        return;
 
884
    }
 
885
    ctxt->node = node;
 
886
 
 
887
    switch (node->type) {
 
888
        case XML_ELEMENT_NODE:
 
889
            if (!ctxt->check) {
 
890
                xmlCtxtDumpSpaces(ctxt);
 
891
                fprintf(ctxt->output, "ELEMENT ");
 
892
                if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
 
893
                    xmlCtxtDumpString(ctxt, node->ns->prefix);
 
894
                    fprintf(ctxt->output, ":");
 
895
                }
 
896
                xmlCtxtDumpString(ctxt, node->name);
 
897
                fprintf(ctxt->output, "\n");
 
898
            }
 
899
            break;
 
900
        case XML_ATTRIBUTE_NODE:
 
901
            if (!ctxt->check)
 
902
                xmlCtxtDumpSpaces(ctxt);
 
903
            fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
 
904
            xmlCtxtGenericNodeCheck(ctxt, node);
 
905
            return;
 
906
        case XML_TEXT_NODE:
 
907
            if (!ctxt->check) {
 
908
                xmlCtxtDumpSpaces(ctxt);
 
909
                if (node->name == (const xmlChar *) xmlStringTextNoenc)
 
910
                    fprintf(ctxt->output, "TEXT no enc");
 
911
                else
 
912
                    fprintf(ctxt->output, "TEXT");
 
913
                if (ctxt->options & DUMP_TEXT_TYPE) {
 
914
                    if (node->content == (xmlChar *) &(node->properties))
 
915
                        fprintf(ctxt->output, " compact\n");
 
916
                    else if (xmlDictOwns(ctxt->dict, node->content) == 1)
 
917
                        fprintf(ctxt->output, " interned\n");
 
918
                    else
 
919
                        fprintf(ctxt->output, "\n");
 
920
                } else
 
921
                    fprintf(ctxt->output, "\n");
 
922
            }
 
923
            break;
 
924
        case XML_CDATA_SECTION_NODE:
 
925
            if (!ctxt->check) {
 
926
                xmlCtxtDumpSpaces(ctxt);
 
927
                fprintf(ctxt->output, "CDATA_SECTION\n");
 
928
            }
 
929
            break;
 
930
        case XML_ENTITY_REF_NODE:
 
931
            if (!ctxt->check) {
 
932
                xmlCtxtDumpSpaces(ctxt);
 
933
                fprintf(ctxt->output, "ENTITY_REF(%s)\n",
 
934
                        (char *) node->name);
 
935
            }
 
936
            break;
 
937
        case XML_ENTITY_NODE:
 
938
            if (!ctxt->check) {
 
939
                xmlCtxtDumpSpaces(ctxt);
 
940
                fprintf(ctxt->output, "ENTITY\n");
 
941
            }
 
942
            break;
 
943
        case XML_PI_NODE:
 
944
            if (!ctxt->check) {
 
945
                xmlCtxtDumpSpaces(ctxt);
 
946
                fprintf(ctxt->output, "PI %s\n", (char *) node->name);
 
947
            }
 
948
            break;
 
949
        case XML_COMMENT_NODE:
 
950
            if (!ctxt->check) {
 
951
                xmlCtxtDumpSpaces(ctxt);
 
952
                fprintf(ctxt->output, "COMMENT\n");
 
953
            }
 
954
            break;
 
955
        case XML_DOCUMENT_NODE:
 
956
        case XML_HTML_DOCUMENT_NODE:
 
957
            if (!ctxt->check) {
 
958
                xmlCtxtDumpSpaces(ctxt);
 
959
            }
 
960
            fprintf(ctxt->output, "Error, DOCUMENT found here\n");
 
961
            xmlCtxtGenericNodeCheck(ctxt, node);
 
962
            return;
 
963
        case XML_DOCUMENT_TYPE_NODE:
 
964
            if (!ctxt->check) {
 
965
                xmlCtxtDumpSpaces(ctxt);
 
966
                fprintf(ctxt->output, "DOCUMENT_TYPE\n");
 
967
            }
 
968
            break;
 
969
        case XML_DOCUMENT_FRAG_NODE:
 
970
            if (!ctxt->check) {
 
971
                xmlCtxtDumpSpaces(ctxt);
 
972
                fprintf(ctxt->output, "DOCUMENT_FRAG\n");
 
973
            }
 
974
            break;
 
975
        case XML_NOTATION_NODE:
 
976
            if (!ctxt->check) {
 
977
                xmlCtxtDumpSpaces(ctxt);
 
978
                fprintf(ctxt->output, "NOTATION\n");
 
979
            }
 
980
            break;
 
981
        case XML_DTD_NODE:
 
982
            xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node);
 
983
            return;
 
984
        case XML_ELEMENT_DECL:
 
985
            xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node);
 
986
            return;
 
987
        case XML_ATTRIBUTE_DECL:
 
988
            xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node);
 
989
            return;
 
990
        case XML_ENTITY_DECL:
 
991
            xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node);
 
992
            return;
 
993
        case XML_NAMESPACE_DECL:
 
994
            xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node);
 
995
            return;
 
996
        case XML_XINCLUDE_START:
 
997
            if (!ctxt->check) {
 
998
                xmlCtxtDumpSpaces(ctxt);
 
999
                fprintf(ctxt->output, "INCLUDE START\n");
 
1000
            }
 
1001
            return;
 
1002
        case XML_XINCLUDE_END:
 
1003
            if (!ctxt->check) {
 
1004
                xmlCtxtDumpSpaces(ctxt);
 
1005
                fprintf(ctxt->output, "INCLUDE END\n");
 
1006
            }
 
1007
            return;
 
1008
        default:
 
1009
            if (!ctxt->check)
 
1010
                xmlCtxtDumpSpaces(ctxt);
 
1011
            xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
 
1012
                        "Unknown node type %d\n", node->type);
 
1013
            return;
 
1014
    }
 
1015
    if (node->doc == NULL) {
 
1016
        if (!ctxt->check) {
 
1017
            xmlCtxtDumpSpaces(ctxt);
 
1018
        }
 
1019
        fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
 
1020
    }
 
1021
    ctxt->depth++;
 
1022
    if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL))
 
1023
        xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
 
1024
    if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL))
 
1025
        xmlCtxtDumpAttrList(ctxt, node->properties);
 
1026
    if (node->type != XML_ENTITY_REF_NODE) {
 
1027
        if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
 
1028
            if (!ctxt->check) {
 
1029
                xmlCtxtDumpSpaces(ctxt);
 
1030
                fprintf(ctxt->output, "content=");
 
1031
                xmlCtxtDumpString(ctxt, node->content);
 
1032
                fprintf(ctxt->output, "\n");
 
1033
            }
 
1034
        }
 
1035
    } else {
 
1036
        xmlEntityPtr ent;
 
1037
 
 
1038
        ent = xmlGetDocEntity(node->doc, node->name);
 
1039
        if (ent != NULL)
 
1040
            xmlCtxtDumpEntity(ctxt, ent);
 
1041
    }
 
1042
    ctxt->depth--;
 
1043
 
 
1044
    /*
 
1045
     * Do a bit of checking
 
1046
     */
 
1047
    xmlCtxtGenericNodeCheck(ctxt, node);
 
1048
}
 
1049
 
 
1050
/**
 
1051
 * xmlCtxtDumpNode:
 
1052
 * @output:  the FILE * for the output
 
1053
 * @node:  the node
 
1054
 * @depth:  the indentation level.
 
1055
 *
 
1056
 * Dumps debug information for the element node, it is recursive
 
1057
 */
 
1058
static void
 
1059
xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
 
1060
{
 
1061
    if (node == NULL) {
 
1062
        if (!ctxt->check) {
 
1063
            xmlCtxtDumpSpaces(ctxt);
 
1064
            fprintf(ctxt->output, "node is NULL\n");
 
1065
        }
 
1066
        return;
 
1067
    }
 
1068
    xmlCtxtDumpOneNode(ctxt, node);
 
1069
    if ((node->type != XML_NAMESPACE_DECL) && 
 
1070
        (node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
 
1071
        ctxt->depth++;
 
1072
        xmlCtxtDumpNodeList(ctxt, node->children);
 
1073
        ctxt->depth--;
 
1074
    }
 
1075
}
 
1076
 
 
1077
/**
 
1078
 * xmlCtxtDumpNodeList:
 
1079
 * @output:  the FILE * for the output
 
1080
 * @node:  the node list
 
1081
 * @depth:  the indentation level.
 
1082
 *
 
1083
 * Dumps debug information for the list of element node, it is recursive
 
1084
 */
 
1085
static void
 
1086
xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
 
1087
{
 
1088
    while (node != NULL) {
 
1089
        xmlCtxtDumpNode(ctxt, node);
 
1090
        node = node->next;
 
1091
    }
 
1092
}
 
1093
 
 
1094
static void
 
1095
xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
 
1096
{
 
1097
    if (doc == NULL) {
 
1098
        if (!ctxt->check)
 
1099
            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
 
1100
        return;
 
1101
    }
 
1102
    ctxt->node = (xmlNodePtr) doc;
 
1103
 
 
1104
    switch (doc->type) {
 
1105
        case XML_ELEMENT_NODE:
 
1106
            xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
 
1107
                        "Misplaced ELEMENT node\n");
 
1108
            break;
 
1109
        case XML_ATTRIBUTE_NODE:
 
1110
            xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
 
1111
                        "Misplaced ATTRIBUTE node\n");
 
1112
            break;
 
1113
        case XML_TEXT_NODE:
 
1114
            xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
 
1115
                        "Misplaced TEXT node\n");
 
1116
            break;
 
1117
        case XML_CDATA_SECTION_NODE:
 
1118
            xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
 
1119
                        "Misplaced CDATA node\n");
 
1120
            break;
 
1121
        case XML_ENTITY_REF_NODE:
 
1122
            xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
 
1123
                        "Misplaced ENTITYREF node\n");
 
1124
            break;
 
1125
        case XML_ENTITY_NODE:
 
1126
            xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
 
1127
                        "Misplaced ENTITY node\n");
 
1128
            break;
 
1129
        case XML_PI_NODE:
 
1130
            xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
 
1131
                        "Misplaced PI node\n");
 
1132
            break;
 
1133
        case XML_COMMENT_NODE:
 
1134
            xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
 
1135
                        "Misplaced COMMENT node\n");
 
1136
            break;
 
1137
        case XML_DOCUMENT_NODE:
 
1138
            if (!ctxt->check)
 
1139
                fprintf(ctxt->output, "DOCUMENT\n");
 
1140
            break;
 
1141
        case XML_HTML_DOCUMENT_NODE:
 
1142
            if (!ctxt->check)
 
1143
                fprintf(ctxt->output, "HTML DOCUMENT\n");
 
1144
            break;
 
1145
        case XML_DOCUMENT_TYPE_NODE:
 
1146
            xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
 
1147
                        "Misplaced DOCTYPE node\n");
 
1148
            break;
 
1149
        case XML_DOCUMENT_FRAG_NODE:
 
1150
            xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
 
1151
                        "Misplaced FRAGMENT node\n");
 
1152
            break;
 
1153
        case XML_NOTATION_NODE:
 
1154
            xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
 
1155
                        "Misplaced NOTATION node\n");
 
1156
            break;
 
1157
        default:
 
1158
            xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
 
1159
                        "Unknown node type %d\n", doc->type);
 
1160
    }
 
1161
}
 
1162
 
 
1163
/**
 
1164
 * xmlCtxtDumpDocumentHead:
 
1165
 * @output:  the FILE * for the output
 
1166
 * @doc:  the document
 
1167
 *
 
1168
 * Dumps debug information cncerning the document, not recursive
 
1169
 */
 
1170
static void
 
1171
xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
 
1172
{
 
1173
    if (doc == NULL) return;
 
1174
    xmlCtxtDumpDocHead(ctxt, doc);
 
1175
    if (!ctxt->check) {
 
1176
        if (doc->name != NULL) {
 
1177
            fprintf(ctxt->output, "name=");
 
1178
            xmlCtxtDumpString(ctxt, BAD_CAST doc->name);
 
1179
            fprintf(ctxt->output, "\n");
 
1180
        }
 
1181
        if (doc->version != NULL) {
 
1182
            fprintf(ctxt->output, "version=");
 
1183
            xmlCtxtDumpString(ctxt, doc->version);
 
1184
            fprintf(ctxt->output, "\n");
 
1185
        }
 
1186
        if (doc->encoding != NULL) {
 
1187
            fprintf(ctxt->output, "encoding=");
 
1188
            xmlCtxtDumpString(ctxt, doc->encoding);
 
1189
            fprintf(ctxt->output, "\n");
 
1190
        }
 
1191
        if (doc->URL != NULL) {
 
1192
            fprintf(ctxt->output, "URL=");
 
1193
            xmlCtxtDumpString(ctxt, doc->URL);
 
1194
            fprintf(ctxt->output, "\n");
 
1195
        }
 
1196
        if (doc->standalone)
 
1197
            fprintf(ctxt->output, "standalone=true\n");
 
1198
    }
 
1199
    if (doc->oldNs != NULL)
 
1200
        xmlCtxtDumpNamespaceList(ctxt, doc->oldNs);
 
1201
}
 
1202
 
 
1203
/**
 
1204
 * xmlCtxtDumpDocument:
 
1205
 * @output:  the FILE * for the output
 
1206
 * @doc:  the document
 
1207
 *
 
1208
 * Dumps debug information for the document, it's recursive
 
1209
 */
 
1210
static void
 
1211
xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
 
1212
{
 
1213
    if (doc == NULL) {
 
1214
        if (!ctxt->check)
 
1215
            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
 
1216
        return;
 
1217
    }
 
1218
    xmlCtxtDumpDocumentHead(ctxt, doc);
 
1219
    if (((doc->type == XML_DOCUMENT_NODE) ||
 
1220
         (doc->type == XML_HTML_DOCUMENT_NODE))
 
1221
        && (doc->children != NULL)) {
 
1222
        ctxt->depth++;
 
1223
        xmlCtxtDumpNodeList(ctxt, doc->children);
 
1224
        ctxt->depth--;
 
1225
    }
 
1226
}
 
1227
 
 
1228
static void
 
1229
xmlCtxtDumpEntityCallback(xmlEntityPtr cur, xmlDebugCtxtPtr ctxt)
 
1230
{
 
1231
    if (cur == NULL) {
 
1232
        if (!ctxt->check)
 
1233
            fprintf(ctxt->output, "Entity is NULL");
 
1234
        return;
 
1235
    }
 
1236
    if (!ctxt->check) {
 
1237
        fprintf(ctxt->output, "%s : ", (char *) cur->name);
 
1238
        switch (cur->etype) {
 
1239
            case XML_INTERNAL_GENERAL_ENTITY:
 
1240
                fprintf(ctxt->output, "INTERNAL GENERAL, ");
 
1241
                break;
 
1242
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
 
1243
                fprintf(ctxt->output, "EXTERNAL PARSED, ");
 
1244
                break;
 
1245
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
 
1246
                fprintf(ctxt->output, "EXTERNAL UNPARSED, ");
 
1247
                break;
 
1248
            case XML_INTERNAL_PARAMETER_ENTITY:
 
1249
                fprintf(ctxt->output, "INTERNAL PARAMETER, ");
 
1250
                break;
 
1251
            case XML_EXTERNAL_PARAMETER_ENTITY:
 
1252
                fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
 
1253
                break;
 
1254
            default:
 
1255
                xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
 
1256
                             "Unknown entity type %d\n", cur->etype);
 
1257
        }
 
1258
        if (cur->ExternalID != NULL)
 
1259
            fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
 
1260
        if (cur->SystemID != NULL)
 
1261
            fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID);
 
1262
        if (cur->orig != NULL)
 
1263
            fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig);
 
1264
        if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL))
 
1265
            fprintf(ctxt->output, "\n content \"%s\"",
 
1266
                    (char *) cur->content);
 
1267
        fprintf(ctxt->output, "\n");
 
1268
    }
 
1269
}
 
1270
 
 
1271
/**
 
1272
 * xmlCtxtDumpEntities:
 
1273
 * @output:  the FILE * for the output
 
1274
 * @doc:  the document
 
1275
 *
 
1276
 * Dumps debug information for all the entities in use by the document
 
1277
 */
 
1278
static void
 
1279
xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
 
1280
{
 
1281
    if (doc == NULL) return;
 
1282
    xmlCtxtDumpDocHead(ctxt, doc);
 
1283
    if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
 
1284
        xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
 
1285
            doc->intSubset->entities;
 
1286
 
 
1287
        if (!ctxt->check)
 
1288
            fprintf(ctxt->output, "Entities in internal subset\n");
 
1289
        xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
 
1290
                    ctxt);
 
1291
    } else
 
1292
        fprintf(ctxt->output, "No entities in internal subset\n");
 
1293
    if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
 
1294
        xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
 
1295
            doc->extSubset->entities;
 
1296
 
 
1297
        if (!ctxt->check)
 
1298
            fprintf(ctxt->output, "Entities in external subset\n");
 
1299
        xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
 
1300
                    ctxt);
 
1301
    } else if (!ctxt->check)
 
1302
        fprintf(ctxt->output, "No entities in external subset\n");
 
1303
}
 
1304
 
 
1305
/**
 
1306
 * xmlCtxtDumpDTD:
 
1307
 * @output:  the FILE * for the output
 
1308
 * @dtd:  the DTD
 
1309
 *
 
1310
 * Dumps debug information for the DTD
 
1311
 */
 
1312
static void
 
1313
xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
 
1314
{
 
1315
    if (dtd == NULL) {
 
1316
        if (!ctxt->check)
 
1317
            fprintf(ctxt->output, "DTD is NULL\n");
 
1318
        return;
 
1319
    }
 
1320
    xmlCtxtDumpDtdNode(ctxt, dtd);
 
1321
    if (dtd->children == NULL)
 
1322
        fprintf(ctxt->output, "    DTD is empty\n");
 
1323
    else {
 
1324
        ctxt->depth++;
 
1325
        xmlCtxtDumpNodeList(ctxt, dtd->children);
 
1326
        ctxt->depth--;
 
1327
    }
 
1328
}
 
1329
 
 
1330
/************************************************************************
 
1331
 *                                                                      *
 
1332
 *                      Public entry points for dump                    *
 
1333
 *                                                                      *
 
1334
 ************************************************************************/
 
1335
 
 
1336
/**
 
1337
 * xmlDebugDumpString:
 
1338
 * @output:  the FILE * for the output
 
1339
 * @str:  the string
 
1340
 *
 
1341
 * Dumps informations about the string, shorten it if necessary
 
1342
 */
 
1343
void
 
1344
xmlDebugDumpString(FILE * output, const xmlChar * str)
 
1345
{
 
1346
    int i;
 
1347
 
 
1348
    if (output == NULL)
 
1349
        output = stdout;
 
1350
    if (str == NULL) {
 
1351
        fprintf(output, "(NULL)");
 
1352
        return;
 
1353
    }
 
1354
    for (i = 0; i < 40; i++)
 
1355
        if (str[i] == 0)
 
1356
            return;
 
1357
        else if (IS_BLANK_CH(str[i]))
 
1358
            fputc(' ', output);
 
1359
        else if (str[i] >= 0x80)
 
1360
            fprintf(output, "#%X", str[i]);
 
1361
        else
 
1362
            fputc(str[i], output);
 
1363
    fprintf(output, "...");
 
1364
}
 
1365
 
 
1366
/**
 
1367
 * xmlDebugDumpAttr:
 
1368
 * @output:  the FILE * for the output
 
1369
 * @attr:  the attribute
 
1370
 * @depth:  the indentation level.
 
1371
 *
 
1372
 * Dumps debug information for the attribute
 
1373
 */
 
1374
void
 
1375
xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
 
1376
    xmlDebugCtxt ctxt;
 
1377
 
 
1378
    if (output == NULL) return;
 
1379
    xmlCtxtDumpInitCtxt(&ctxt);
 
1380
    ctxt.output = output;
 
1381
    ctxt.depth = depth;
 
1382
    xmlCtxtDumpAttr(&ctxt, attr);
 
1383
    xmlCtxtDumpCleanCtxt(&ctxt);
 
1384
}
 
1385
 
 
1386
 
 
1387
/**
 
1388
 * xmlDebugDumpEntities:
 
1389
 * @output:  the FILE * for the output
 
1390
 * @doc:  the document
 
1391
 *
 
1392
 * Dumps debug information for all the entities in use by the document
 
1393
 */
 
1394
void
 
1395
xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
 
1396
{
 
1397
    xmlDebugCtxt ctxt;
 
1398
 
 
1399
    if (output == NULL) return;
 
1400
    xmlCtxtDumpInitCtxt(&ctxt);
 
1401
    ctxt.output = output;
 
1402
    xmlCtxtDumpEntities(&ctxt, doc);
 
1403
    xmlCtxtDumpCleanCtxt(&ctxt);
 
1404
}
 
1405
 
 
1406
/**
 
1407
 * xmlDebugDumpAttrList:
 
1408
 * @output:  the FILE * for the output
 
1409
 * @attr:  the attribute list
 
1410
 * @depth:  the indentation level.
 
1411
 *
 
1412
 * Dumps debug information for the attribute list
 
1413
 */
 
1414
void
 
1415
xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
 
1416
{
 
1417
    xmlDebugCtxt ctxt;
 
1418
 
 
1419
    if (output == NULL) return;
 
1420
    xmlCtxtDumpInitCtxt(&ctxt);
 
1421
    ctxt.output = output;
 
1422
    ctxt.depth = depth;
 
1423
    xmlCtxtDumpAttrList(&ctxt, attr);
 
1424
    xmlCtxtDumpCleanCtxt(&ctxt);
 
1425
}
 
1426
 
 
1427
/**
 
1428
 * xmlDebugDumpOneNode:
 
1429
 * @output:  the FILE * for the output
 
1430
 * @node:  the node
 
1431
 * @depth:  the indentation level.
 
1432
 *
 
1433
 * Dumps debug information for the element node, it is not recursive
 
1434
 */
 
1435
void
 
1436
xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
 
1437
{
 
1438
    xmlDebugCtxt ctxt;
 
1439
 
 
1440
    if (output == NULL) return;
 
1441
    xmlCtxtDumpInitCtxt(&ctxt);
 
1442
    ctxt.output = output;
 
1443
    ctxt.depth = depth;
 
1444
    xmlCtxtDumpOneNode(&ctxt, node);
 
1445
    xmlCtxtDumpCleanCtxt(&ctxt);
 
1446
}
 
1447
 
 
1448
/**
 
1449
 * xmlDebugDumpNode:
 
1450
 * @output:  the FILE * for the output
 
1451
 * @node:  the node
 
1452
 * @depth:  the indentation level.
 
1453
 *
 
1454
 * Dumps debug information for the element node, it is recursive
 
1455
 */
 
1456
void
 
1457
xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
 
1458
{
 
1459
    xmlDebugCtxt ctxt;
 
1460
 
 
1461
    if (output == NULL)
 
1462
        output = stdout;
 
1463
    xmlCtxtDumpInitCtxt(&ctxt);
 
1464
    ctxt.output = output;
 
1465
    ctxt.depth = depth;
 
1466
    xmlCtxtDumpNode(&ctxt, node);
 
1467
    xmlCtxtDumpCleanCtxt(&ctxt);
 
1468
}
 
1469
 
 
1470
/**
 
1471
 * xmlDebugDumpNodeList:
 
1472
 * @output:  the FILE * for the output
 
1473
 * @node:  the node list
 
1474
 * @depth:  the indentation level.
 
1475
 *
 
1476
 * Dumps debug information for the list of element node, it is recursive
 
1477
 */
 
1478
void
 
1479
xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
 
1480
{
 
1481
    xmlDebugCtxt ctxt;
 
1482
 
 
1483
    if (output == NULL)
 
1484
        output = stdout;
 
1485
    xmlCtxtDumpInitCtxt(&ctxt);
 
1486
    ctxt.output = output;
 
1487
    ctxt.depth = depth;
 
1488
    xmlCtxtDumpNodeList(&ctxt, node);
 
1489
    xmlCtxtDumpCleanCtxt(&ctxt);
 
1490
}
 
1491
 
 
1492
/**
 
1493
 * xmlDebugDumpDocumentHead:
 
1494
 * @output:  the FILE * for the output
 
1495
 * @doc:  the document
 
1496
 *
 
1497
 * Dumps debug information cncerning the document, not recursive
 
1498
 */
 
1499
void
 
1500
xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
 
1501
{
 
1502
    xmlDebugCtxt ctxt;
 
1503
 
 
1504
    if (output == NULL)
 
1505
        output = stdout;
 
1506
    xmlCtxtDumpInitCtxt(&ctxt);
 
1507
    ctxt.options |= DUMP_TEXT_TYPE;
 
1508
    ctxt.output = output;
 
1509
    xmlCtxtDumpDocumentHead(&ctxt, doc);
 
1510
    xmlCtxtDumpCleanCtxt(&ctxt);
 
1511
}
 
1512
 
 
1513
/**
 
1514
 * xmlDebugDumpDocument:
 
1515
 * @output:  the FILE * for the output
 
1516
 * @doc:  the document
 
1517
 *
 
1518
 * Dumps debug information for the document, it's recursive
 
1519
 */
 
1520
void
 
1521
xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
 
1522
{
 
1523
    xmlDebugCtxt ctxt;
 
1524
 
 
1525
    if (output == NULL)
 
1526
        output = stdout;
 
1527
    xmlCtxtDumpInitCtxt(&ctxt);
 
1528
    ctxt.options |= DUMP_TEXT_TYPE;
 
1529
    ctxt.output = output;
 
1530
    xmlCtxtDumpDocument(&ctxt, doc);
 
1531
    xmlCtxtDumpCleanCtxt(&ctxt);
 
1532
}
 
1533
 
 
1534
/**
 
1535
 * xmlDebugDumpDTD:
 
1536
 * @output:  the FILE * for the output
 
1537
 * @dtd:  the DTD
 
1538
 *
 
1539
 * Dumps debug information for the DTD
 
1540
 */
 
1541
void
 
1542
xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
 
1543
{
 
1544
    xmlDebugCtxt ctxt;
 
1545
 
 
1546
    if (output == NULL)
 
1547
        output = stdout;
 
1548
    xmlCtxtDumpInitCtxt(&ctxt);
 
1549
    ctxt.options |= DUMP_TEXT_TYPE;
 
1550
    ctxt.output = output;
 
1551
    xmlCtxtDumpDTD(&ctxt, dtd);
 
1552
    xmlCtxtDumpCleanCtxt(&ctxt);
 
1553
}
 
1554
 
 
1555
/************************************************************************
 
1556
 *                                                                      *
 
1557
 *                      Public entry points for checkings               *
 
1558
 *                                                                      *
 
1559
 ************************************************************************/
 
1560
 
 
1561
/**
 
1562
 * xmlDebugCheckDocument:
 
1563
 * @output:  the FILE * for the output
 
1564
 * @doc:  the document
 
1565
 *
 
1566
 * Check the document for potential content problems, and output
 
1567
 * the errors to @output
 
1568
 *
 
1569
 * Returns the number of errors found
 
1570
 */
 
1571
int
 
1572
xmlDebugCheckDocument(FILE * output, xmlDocPtr doc)
 
1573
{
 
1574
    xmlDebugCtxt ctxt;
 
1575
 
 
1576
    if (output == NULL)
 
1577
        output = stdout;
 
1578
    xmlCtxtDumpInitCtxt(&ctxt);
 
1579
    ctxt.output = output;
 
1580
    ctxt.check = 1;
 
1581
    xmlCtxtDumpDocument(&ctxt, doc);
 
1582
    xmlCtxtDumpCleanCtxt(&ctxt);
 
1583
    return(ctxt.errors);
 
1584
}
 
1585
 
 
1586
/************************************************************************
 
1587
 *                                                                      *
 
1588
 *                      Helpers for Shell                               *
 
1589
 *                                                                      *
 
1590
 ************************************************************************/
 
1591
 
 
1592
/**
 
1593
 * xmlLsCountNode:
 
1594
 * @node:  the node to count
 
1595
 *
 
1596
 * Count the children of @node.
 
1597
 *
 
1598
 * Returns the number of children of @node.
 
1599
 */
 
1600
int
 
1601
xmlLsCountNode(xmlNodePtr node) {
 
1602
    int ret = 0;
 
1603
    xmlNodePtr list = NULL;
 
1604
    
 
1605
    if (node == NULL)
 
1606
        return(0);
 
1607
 
 
1608
    switch (node->type) {
 
1609
        case XML_ELEMENT_NODE:
 
1610
            list = node->children;
 
1611
            break;
 
1612
        case XML_DOCUMENT_NODE:
 
1613
        case XML_HTML_DOCUMENT_NODE:
 
1614
#ifdef LIBXML_DOCB_ENABLED
 
1615
        case XML_DOCB_DOCUMENT_NODE:
 
1616
#endif
 
1617
            list = ((xmlDocPtr) node)->children;
 
1618
            break;
 
1619
        case XML_ATTRIBUTE_NODE:
 
1620
            list = ((xmlAttrPtr) node)->children;
 
1621
            break;
 
1622
        case XML_TEXT_NODE:
 
1623
        case XML_CDATA_SECTION_NODE:
 
1624
        case XML_PI_NODE:
 
1625
        case XML_COMMENT_NODE:
 
1626
            if (node->content != NULL) {
 
1627
                ret = xmlStrlen(node->content);
 
1628
            }
 
1629
            break;
 
1630
        case XML_ENTITY_REF_NODE:
 
1631
        case XML_DOCUMENT_TYPE_NODE:
 
1632
        case XML_ENTITY_NODE:
 
1633
        case XML_DOCUMENT_FRAG_NODE:
 
1634
        case XML_NOTATION_NODE:
 
1635
        case XML_DTD_NODE:
 
1636
        case XML_ELEMENT_DECL:
 
1637
        case XML_ATTRIBUTE_DECL:
 
1638
        case XML_ENTITY_DECL:
 
1639
        case XML_NAMESPACE_DECL:
 
1640
        case XML_XINCLUDE_START:
 
1641
        case XML_XINCLUDE_END:
 
1642
            ret = 1;
 
1643
            break;
 
1644
    }
 
1645
    for (;list != NULL;ret++) 
 
1646
        list = list->next;
 
1647
    return(ret);
 
1648
}
 
1649
 
 
1650
/**
 
1651
 * xmlLsOneNode:
 
1652
 * @output:  the FILE * for the output
 
1653
 * @node:  the node to dump
 
1654
 *
 
1655
 * Dump to @output the type and name of @node.
 
1656
 */
 
1657
void
 
1658
xmlLsOneNode(FILE *output, xmlNodePtr node) {
 
1659
    if (output == NULL) return;
 
1660
    if (node == NULL) {
 
1661
        fprintf(output, "NULL\n");
 
1662
        return;
 
1663
    }
 
1664
    switch (node->type) {
 
1665
        case XML_ELEMENT_NODE:
 
1666
            fprintf(output, "-");
 
1667
            break;
 
1668
        case XML_ATTRIBUTE_NODE:
 
1669
            fprintf(output, "a");
 
1670
            break;
 
1671
        case XML_TEXT_NODE:
 
1672
            fprintf(output, "t");
 
1673
            break;
 
1674
        case XML_CDATA_SECTION_NODE:
 
1675
            fprintf(output, "C");
 
1676
            break;
 
1677
        case XML_ENTITY_REF_NODE:
 
1678
            fprintf(output, "e");
 
1679
            break;
 
1680
        case XML_ENTITY_NODE:
 
1681
            fprintf(output, "E");
 
1682
            break;
 
1683
        case XML_PI_NODE:
 
1684
            fprintf(output, "p");
 
1685
            break;
 
1686
        case XML_COMMENT_NODE:
 
1687
            fprintf(output, "c");
 
1688
            break;
 
1689
        case XML_DOCUMENT_NODE:
 
1690
            fprintf(output, "d");
 
1691
            break;
 
1692
        case XML_HTML_DOCUMENT_NODE:
 
1693
            fprintf(output, "h");
 
1694
            break;
 
1695
        case XML_DOCUMENT_TYPE_NODE:
 
1696
            fprintf(output, "T");
 
1697
            break;
 
1698
        case XML_DOCUMENT_FRAG_NODE:
 
1699
            fprintf(output, "F");
 
1700
            break;
 
1701
        case XML_NOTATION_NODE:
 
1702
            fprintf(output, "N");
 
1703
            break;
 
1704
        case XML_NAMESPACE_DECL:
 
1705
            fprintf(output, "n");
 
1706
            break;
 
1707
        default:
 
1708
            fprintf(output, "?");
 
1709
    }
 
1710
    if (node->type != XML_NAMESPACE_DECL) {
 
1711
        if (node->properties != NULL)
 
1712
            fprintf(output, "a");
 
1713
        else    
 
1714
            fprintf(output, "-");
 
1715
        if (node->nsDef != NULL) 
 
1716
            fprintf(output, "n");
 
1717
        else    
 
1718
            fprintf(output, "-");
 
1719
    }
 
1720
 
 
1721
    fprintf(output, " %8d ", xmlLsCountNode(node));
 
1722
 
 
1723
    switch (node->type) {
 
1724
        case XML_ELEMENT_NODE:
 
1725
            if (node->name != NULL)
 
1726
                fprintf(output, "%s", (const char *) node->name);
 
1727
            break;
 
1728
        case XML_ATTRIBUTE_NODE:
 
1729
            if (node->name != NULL)
 
1730
                fprintf(output, "%s", (const char *) node->name);
 
1731
            break;
 
1732
        case XML_TEXT_NODE:
 
1733
            if (node->content != NULL) {
 
1734
                xmlDebugDumpString(output, node->content);
 
1735
            }
 
1736
            break;
 
1737
        case XML_CDATA_SECTION_NODE:
 
1738
            break;
 
1739
        case XML_ENTITY_REF_NODE:
 
1740
            if (node->name != NULL)
 
1741
                fprintf(output, "%s", (const char *) node->name);
 
1742
            break;
 
1743
        case XML_ENTITY_NODE:
 
1744
            if (node->name != NULL)
 
1745
                fprintf(output, "%s", (const char *) node->name);
 
1746
            break;
 
1747
        case XML_PI_NODE:
 
1748
            if (node->name != NULL)
 
1749
                fprintf(output, "%s", (const char *) node->name);
 
1750
            break;
 
1751
        case XML_COMMENT_NODE:
 
1752
            break;
 
1753
        case XML_DOCUMENT_NODE:
 
1754
            break;
 
1755
        case XML_HTML_DOCUMENT_NODE:
 
1756
            break;
 
1757
        case XML_DOCUMENT_TYPE_NODE:
 
1758
            break;
 
1759
        case XML_DOCUMENT_FRAG_NODE:
 
1760
            break;
 
1761
        case XML_NOTATION_NODE:
 
1762
            break;
 
1763
        case XML_NAMESPACE_DECL: {
 
1764
            xmlNsPtr ns = (xmlNsPtr) node;
 
1765
 
 
1766
            if (ns->prefix == NULL)
 
1767
                fprintf(output, "default -> %s", (char *)ns->href);
 
1768
            else
 
1769
                fprintf(output, "%s -> %s", (char *)ns->prefix,
 
1770
                        (char *)ns->href);
 
1771
            break;
 
1772
        }
 
1773
        default:
 
1774
            if (node->name != NULL)
 
1775
                fprintf(output, "%s", (const char *) node->name);
 
1776
    }
 
1777
    fprintf(output, "\n");
 
1778
}
 
1779
 
 
1780
/**
 
1781
 * xmlBoolToText:
 
1782
 * @boolval: a bool to turn into text
 
1783
 *
 
1784
 * Convenient way to turn bool into text 
 
1785
 *
 
1786
 * Returns a pointer to either "True" or "False"
 
1787
 */
 
1788
const char *
 
1789
xmlBoolToText(int boolval)
 
1790
{
 
1791
    if (boolval)
 
1792
        return("True");
 
1793
    else
 
1794
        return("False");
 
1795
}
 
1796
 
 
1797
#ifdef LIBXML_XPATH_ENABLED
 
1798
/****************************************************************
 
1799
 *                                                              *
 
1800
 *              The XML shell related functions                 *
 
1801
 *                                                              *
 
1802
 ****************************************************************/
 
1803
 
 
1804
 
 
1805
 
 
1806
/*
 
1807
 * TODO: Improvement/cleanups for the XML shell
 
1808
 *     - allow to shell out an editor on a subpart
 
1809
 *     - cleanup function registrations (with help) and calling
 
1810
 *     - provide registration routines
 
1811
 */
 
1812
 
 
1813
/**
 
1814
 * xmlShellPrintXPathError:
 
1815
 * @errorType: valid xpath error id
 
1816
 * @arg: the argument that cause xpath to fail
 
1817
 *
 
1818
 * Print the xpath error to libxml default error channel
 
1819
 */
 
1820
void
 
1821
xmlShellPrintXPathError(int errorType, const char *arg)
 
1822
{
 
1823
    const char *default_arg = "Result";
 
1824
 
 
1825
    if (!arg)
 
1826
        arg = default_arg;
 
1827
 
 
1828
    switch (errorType) {
 
1829
        case XPATH_UNDEFINED:
 
1830
            xmlGenericError(xmlGenericErrorContext,
 
1831
                            "%s: no such node\n", arg);
 
1832
            break;
 
1833
 
 
1834
        case XPATH_BOOLEAN:
 
1835
            xmlGenericError(xmlGenericErrorContext,
 
1836
                            "%s is a Boolean\n", arg);
 
1837
            break;
 
1838
        case XPATH_NUMBER:
 
1839
            xmlGenericError(xmlGenericErrorContext,
 
1840
                            "%s is a number\n", arg);
 
1841
            break;
 
1842
        case XPATH_STRING:
 
1843
            xmlGenericError(xmlGenericErrorContext,
 
1844
                            "%s is a string\n", arg);
 
1845
            break;
 
1846
        case XPATH_POINT:
 
1847
            xmlGenericError(xmlGenericErrorContext,
 
1848
                            "%s is a point\n", arg);
 
1849
            break;
 
1850
        case XPATH_RANGE:
 
1851
            xmlGenericError(xmlGenericErrorContext,
 
1852
                            "%s is a range\n", arg);
 
1853
            break;
 
1854
        case XPATH_LOCATIONSET:
 
1855
            xmlGenericError(xmlGenericErrorContext,
 
1856
                            "%s is a range\n", arg);
 
1857
            break;
 
1858
        case XPATH_USERS:
 
1859
            xmlGenericError(xmlGenericErrorContext,
 
1860
                            "%s is user-defined\n", arg);
 
1861
            break;
 
1862
        case XPATH_XSLT_TREE:
 
1863
            xmlGenericError(xmlGenericErrorContext,
 
1864
                            "%s is an XSLT value tree\n", arg);
 
1865
            break;
 
1866
    }
 
1867
#if 0
 
1868
    xmlGenericError(xmlGenericErrorContext,
 
1869
                    "Try casting the result string function (xpath builtin)\n",
 
1870
                    arg);
 
1871
#endif
 
1872
}
 
1873
 
 
1874
 
 
1875
#ifdef LIBXML_OUTPUT_ENABLED
 
1876
/**
 
1877
 * xmlShellPrintNodeCtxt:
 
1878
 * @ctxt : a non-null shell context
 
1879
 * @node : a non-null node to print to the output FILE
 
1880
 *
 
1881
 * Print node to the output FILE
 
1882
 */
 
1883
static void
 
1884
xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
 
1885
{
 
1886
    FILE *fp;
 
1887
 
 
1888
    if (!node)
 
1889
        return;
 
1890
    if (ctxt == NULL)
 
1891
        fp = stdout;
 
1892
    else
 
1893
        fp = ctxt->output;
 
1894
 
 
1895
    if (node->type == XML_DOCUMENT_NODE)
 
1896
        xmlDocDump(fp, (xmlDocPtr) node);
 
1897
    else if (node->type == XML_ATTRIBUTE_NODE)
 
1898
        xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
 
1899
    else
 
1900
        xmlElemDump(fp, node->doc, node);
 
1901
 
 
1902
    fprintf(fp, "\n");
 
1903
}
 
1904
 
 
1905
/**
 
1906
 * xmlShellPrintNode:
 
1907
 * @node : a non-null node to print to the output FILE
 
1908
 *
 
1909
 * Print node to the output FILE
 
1910
 */
 
1911
void
 
1912
xmlShellPrintNode(xmlNodePtr node)
 
1913
{
 
1914
    xmlShellPrintNodeCtxt(NULL, node);
 
1915
}
 
1916
#endif /* LIBXML_OUTPUT_ENABLED */
 
1917
 
 
1918
/**
 
1919
 * xmlShellPrintXPathResultCtxt:
 
1920
 * @ctxt: a valid shell context
 
1921
 * @list: a valid result generated by an xpath evaluation
 
1922
 *
 
1923
 * Prints result to the output FILE
 
1924
 */
 
1925
static void
 
1926
xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
 
1927
{
 
1928
    if (!ctxt)
 
1929
       return;
 
1930
 
 
1931
    if (list != NULL) {
 
1932
        switch (list->type) {
 
1933
            case XPATH_NODESET:{
 
1934
#ifdef LIBXML_OUTPUT_ENABLED
 
1935
                    int indx;
 
1936
 
 
1937
                    if (list->nodesetval) {
 
1938
                        for (indx = 0; indx < list->nodesetval->nodeNr;
 
1939
                             indx++) {
 
1940
                            xmlShellPrintNodeCtxt(ctxt,
 
1941
                                    list->nodesetval->nodeTab[indx]);
 
1942
                        }
 
1943
                    } else {
 
1944
                        xmlGenericError(xmlGenericErrorContext,
 
1945
                                        "Empty node set\n");
 
1946
                    }
 
1947
                    break;
 
1948
#else
 
1949
                    xmlGenericError(xmlGenericErrorContext,
 
1950
                                    "Node set\n");
 
1951
#endif /* LIBXML_OUTPUT_ENABLED */
 
1952
                }
 
1953
            case XPATH_BOOLEAN:
 
1954
                xmlGenericError(xmlGenericErrorContext,
 
1955
                                "Is a Boolean:%s\n",
 
1956
                                xmlBoolToText(list->boolval));
 
1957
                break;
 
1958
            case XPATH_NUMBER:
 
1959
                xmlGenericError(xmlGenericErrorContext,
 
1960
                                "Is a number:%0g\n", list->floatval);
 
1961
                break;
 
1962
            case XPATH_STRING:
 
1963
                xmlGenericError(xmlGenericErrorContext,
 
1964
                                "Is a string:%s\n", list->stringval);
 
1965
                break;
 
1966
 
 
1967
            default:
 
1968
                xmlShellPrintXPathError(list->type, NULL);
 
1969
        }
 
1970
    }
 
1971
}
 
1972
 
 
1973
/**
 
1974
 * xmlShellPrintXPathResult:
 
1975
 * @list: a valid result generated by an xpath evaluation
 
1976
 *
 
1977
 * Prints result to the output FILE
 
1978
 */
 
1979
void
 
1980
xmlShellPrintXPathResult(xmlXPathObjectPtr list)
 
1981
{
 
1982
    xmlShellPrintXPathResultCtxt(NULL, list);
 
1983
}
 
1984
 
 
1985
/**
 
1986
 * xmlShellList:
 
1987
 * @ctxt:  the shell context
 
1988
 * @arg:  unused
 
1989
 * @node:  a node
 
1990
 * @node2:  unused
 
1991
 *
 
1992
 * Implements the XML shell function "ls"
 
1993
 * Does an Unix like listing of the given node (like a directory)
 
1994
 *
 
1995
 * Returns 0
 
1996
 */
 
1997
int
 
1998
xmlShellList(xmlShellCtxtPtr ctxt,
 
1999
             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
 
2000
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2001
{
 
2002
    xmlNodePtr cur;
 
2003
    if (!ctxt)
 
2004
        return (0);
 
2005
    if (node == NULL) {
 
2006
        fprintf(ctxt->output, "NULL\n");
 
2007
        return (0);
 
2008
    }
 
2009
    if ((node->type == XML_DOCUMENT_NODE) ||
 
2010
        (node->type == XML_HTML_DOCUMENT_NODE)) {
 
2011
        cur = ((xmlDocPtr) node)->children;
 
2012
    } else if (node->type == XML_NAMESPACE_DECL) {
 
2013
        xmlLsOneNode(ctxt->output, node);
 
2014
        return (0);
 
2015
    } else if (node->children != NULL) {
 
2016
        cur = node->children;
 
2017
    } else {
 
2018
        xmlLsOneNode(ctxt->output, node);
 
2019
        return (0);
 
2020
    }
 
2021
    while (cur != NULL) {
 
2022
        xmlLsOneNode(ctxt->output, cur);
 
2023
        cur = cur->next;
 
2024
    }
 
2025
    return (0);
 
2026
}
 
2027
 
 
2028
/**
 
2029
 * xmlShellBase:
 
2030
 * @ctxt:  the shell context
 
2031
 * @arg:  unused
 
2032
 * @node:  a node
 
2033
 * @node2:  unused
 
2034
 *
 
2035
 * Implements the XML shell function "base"
 
2036
 * dumps the current XML base of the node
 
2037
 *
 
2038
 * Returns 0
 
2039
 */
 
2040
int
 
2041
xmlShellBase(xmlShellCtxtPtr ctxt,
 
2042
             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
 
2043
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2044
{
 
2045
    xmlChar *base;
 
2046
    if (!ctxt)
 
2047
        return 0;
 
2048
    if (node == NULL) {
 
2049
        fprintf(ctxt->output, "NULL\n");
 
2050
        return (0);
 
2051
    }    
 
2052
 
 
2053
    base = xmlNodeGetBase(node->doc, node);
 
2054
 
 
2055
    if (base == NULL) {
 
2056
        fprintf(ctxt->output, " No base found !!!\n");
 
2057
    } else {
 
2058
        fprintf(ctxt->output, "%s\n", base);
 
2059
        xmlFree(base);
 
2060
    }
 
2061
    return (0);
 
2062
}
 
2063
 
 
2064
#ifdef LIBXML_TREE_ENABLED
 
2065
/**
 
2066
 * xmlShellSetBase:
 
2067
 * @ctxt:  the shell context
 
2068
 * @arg:  the new base
 
2069
 * @node:  a node
 
2070
 * @node2:  unused
 
2071
 *
 
2072
 * Implements the XML shell function "setbase"
 
2073
 * change the current XML base of the node
 
2074
 *
 
2075
 * Returns 0
 
2076
 */
 
2077
static int
 
2078
xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
 
2079
             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
 
2080
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2081
{
 
2082
    xmlNodeSetBase(node, (xmlChar*) arg);
 
2083
    return (0);
 
2084
}
 
2085
#endif
 
2086
 
 
2087
#ifdef LIBXML_XPATH_ENABLED
 
2088
/**
 
2089
 * xmlShellRegisterNamespace:
 
2090
 * @ctxt:  the shell context
 
2091
 * @arg:  a string in prefix=nsuri format
 
2092
 * @node:  unused
 
2093
 * @node2:  unused
 
2094
 *
 
2095
 * Implements the XML shell function "setns"
 
2096
 * register/unregister a prefix=namespace pair
 
2097
 * on the XPath context
 
2098
 *
 
2099
 * Returns 0 on success and a negative value otherwise.
 
2100
 */
 
2101
static int
 
2102
xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg,
 
2103
      xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2104
{
 
2105
    xmlChar* nsListDup;
 
2106
    xmlChar* prefix;
 
2107
    xmlChar* href;
 
2108
    xmlChar* next;
 
2109
 
 
2110
    nsListDup = xmlStrdup((xmlChar *) arg);
 
2111
    next = nsListDup;
 
2112
    while(next != NULL) {
 
2113
        /* skip spaces */
 
2114
        /*while((*next) == ' ') next++;*/
 
2115
        if((*next) == '\0') break;
 
2116
 
 
2117
        /* find prefix */
 
2118
        prefix = next;
 
2119
        next = (xmlChar*)xmlStrchr(next, '=');
 
2120
        if(next == NULL) {
 
2121
            fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
 
2122
            xmlFree(nsListDup);
 
2123
            return(-1);
 
2124
        }
 
2125
        *(next++) = '\0';
 
2126
 
 
2127
        /* find href */
 
2128
        href = next;
 
2129
        next = (xmlChar*)xmlStrchr(next, ' ');
 
2130
        if(next != NULL) {
 
2131
            *(next++) = '\0';
 
2132
        }
 
2133
 
 
2134
        /* do register namespace */
 
2135
        if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
 
2136
            fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
 
2137
            xmlFree(nsListDup);
 
2138
            return(-1);
 
2139
        }
 
2140
    }
 
2141
 
 
2142
    xmlFree(nsListDup);
 
2143
    return(0);
 
2144
}
 
2145
/**
 
2146
 * xmlShellRegisterRootNamespaces:
 
2147
 * @ctxt:  the shell context
 
2148
 * @arg:  unused
 
2149
 * @node:  the root element
 
2150
 * @node2:  unused
 
2151
 *
 
2152
 * Implements the XML shell function "setrootns"
 
2153
 * which registers all namespaces declarations found on the root element.
 
2154
 *
 
2155
 * Returns 0 on success and a negative value otherwise.
 
2156
 */
 
2157
static int
 
2158
xmlShellRegisterRootNamespaces(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
 
2159
      xmlNodePtr root, xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2160
{
 
2161
    xmlNsPtr ns;
 
2162
 
 
2163
    if ((root == NULL) || (root->type != XML_ELEMENT_NODE) ||
 
2164
        (root->nsDef == NULL) || (ctxt == NULL) || (ctxt->pctxt == NULL))
 
2165
        return(-1);
 
2166
    ns = root->nsDef;
 
2167
    while (ns != NULL) {
 
2168
        if (ns->prefix == NULL)
 
2169
            xmlXPathRegisterNs(ctxt->pctxt, BAD_CAST "defaultns", ns->href);
 
2170
        else
 
2171
            xmlXPathRegisterNs(ctxt->pctxt, ns->prefix, ns->href);
 
2172
        ns = ns->next;
 
2173
    }
 
2174
    return(0);
 
2175
}
 
2176
#endif
 
2177
 
 
2178
/**
 
2179
 * xmlShellGrep:
 
2180
 * @ctxt:  the shell context
 
2181
 * @arg:  the string or regular expression to find
 
2182
 * @node:  a node
 
2183
 * @node2:  unused
 
2184
 *
 
2185
 * Implements the XML shell function "grep"
 
2186
 * dumps informations about the node (namespace, attributes, content).
 
2187
 *
 
2188
 * Returns 0
 
2189
 */
 
2190
static int
 
2191
xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
 
2192
            char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2193
{
 
2194
    if (!ctxt)
 
2195
        return (0);
 
2196
    if (node == NULL)
 
2197
        return (0);
 
2198
    if (arg == NULL)
 
2199
        return (0);
 
2200
#ifdef LIBXML_REGEXP_ENABLED
 
2201
    if ((xmlStrchr((xmlChar *) arg, '?')) ||
 
2202
        (xmlStrchr((xmlChar *) arg, '*')) ||
 
2203
        (xmlStrchr((xmlChar *) arg, '.')) ||
 
2204
        (xmlStrchr((xmlChar *) arg, '['))) {
 
2205
    }
 
2206
#endif
 
2207
    while (node != NULL) {
 
2208
        if (node->type == XML_COMMENT_NODE) {
 
2209
            if (xmlStrstr(node->content, (xmlChar *) arg)) {
 
2210
 
 
2211
                fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
 
2212
                xmlShellList(ctxt, NULL, node, NULL);
 
2213
            }
 
2214
        } else if (node->type == XML_TEXT_NODE) {
 
2215
            if (xmlStrstr(node->content, (xmlChar *) arg)) {
 
2216
 
 
2217
                fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
 
2218
                xmlShellList(ctxt, NULL, node->parent, NULL);
 
2219
            }
 
2220
        }
 
2221
 
 
2222
        /*
 
2223
         * Browse the full subtree, deep first
 
2224
         */
 
2225
 
 
2226
        if ((node->type == XML_DOCUMENT_NODE) ||
 
2227
            (node->type == XML_HTML_DOCUMENT_NODE)) {
 
2228
            node = ((xmlDocPtr) node)->children;
 
2229
        } else if ((node->children != NULL)
 
2230
                   && (node->type != XML_ENTITY_REF_NODE)) {
 
2231
            /* deep first */
 
2232
            node = node->children;
 
2233
        } else if (node->next != NULL) {
 
2234
            /* then siblings */
 
2235
            node = node->next;
 
2236
        } else {
 
2237
            /* go up to parents->next if needed */
 
2238
            while (node != NULL) {
 
2239
                if (node->parent != NULL) {
 
2240
                    node = node->parent;
 
2241
                }
 
2242
                if (node->next != NULL) {
 
2243
                    node = node->next;
 
2244
                    break;
 
2245
                }
 
2246
                if (node->parent == NULL) {
 
2247
                    node = NULL;
 
2248
                    break;
 
2249
                }
 
2250
            }
 
2251
        }
 
2252
    }
 
2253
    return (0);
 
2254
}
 
2255
 
 
2256
/**
 
2257
 * xmlShellDir:
 
2258
 * @ctxt:  the shell context
 
2259
 * @arg:  unused
 
2260
 * @node:  a node
 
2261
 * @node2:  unused
 
2262
 *
 
2263
 * Implements the XML shell function "dir"
 
2264
 * dumps informations about the node (namespace, attributes, content).
 
2265
 *
 
2266
 * Returns 0
 
2267
 */
 
2268
int
 
2269
xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
 
2270
            char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
 
2271
            xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2272
{
 
2273
    if (!ctxt)
 
2274
        return (0);
 
2275
    if (node == NULL) {
 
2276
        fprintf(ctxt->output, "NULL\n");
 
2277
        return (0);
 
2278
    }    
 
2279
    if ((node->type == XML_DOCUMENT_NODE) ||
 
2280
        (node->type == XML_HTML_DOCUMENT_NODE)) {
 
2281
        xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
 
2282
    } else if (node->type == XML_ATTRIBUTE_NODE) {
 
2283
        xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
 
2284
    } else {
 
2285
        xmlDebugDumpOneNode(ctxt->output, node, 0);
 
2286
    }
 
2287
    return (0);
 
2288
}
 
2289
 
 
2290
/**
 
2291
 * xmlShellSetContent:
 
2292
 * @ctxt:  the shell context
 
2293
 * @value:  the content as a string
 
2294
 * @node:  a node
 
2295
 * @node2:  unused
 
2296
 *
 
2297
 * Implements the XML shell function "dir"
 
2298
 * dumps informations about the node (namespace, attributes, content).
 
2299
 *
 
2300
 * Returns 0
 
2301
 */
 
2302
static int
 
2303
xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
 
2304
            char *value, xmlNodePtr node,
 
2305
            xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2306
{
 
2307
    xmlNodePtr results;
 
2308
    xmlParserErrors ret;
 
2309
 
 
2310
    if (!ctxt)
 
2311
        return (0);
 
2312
    if (node == NULL) {
 
2313
        fprintf(ctxt->output, "NULL\n");
 
2314
        return (0);
 
2315
    }
 
2316
    if (value == NULL) {
 
2317
        fprintf(ctxt->output, "NULL\n");
 
2318
        return (0);
 
2319
    }
 
2320
 
 
2321
    ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results);
 
2322
    if (ret == XML_ERR_OK) {
 
2323
        if (node->children != NULL) {
 
2324
            xmlFreeNodeList(node->children);
 
2325
            node->children = NULL;
 
2326
            node->last = NULL;
 
2327
        }
 
2328
        xmlAddChildList(node, results);
 
2329
    } else {
 
2330
        fprintf(ctxt->output, "failed to parse content\n");
 
2331
    }
 
2332
    return (0);
 
2333
}
 
2334
 
 
2335
#ifdef LIBXML_SCHEMAS_ENABLED
 
2336
/**
 
2337
 * xmlShellRNGValidate:
 
2338
 * @ctxt:  the shell context
 
2339
 * @schemas:  the path to the Relax-NG schemas
 
2340
 * @node:  a node
 
2341
 * @node2:  unused
 
2342
 *
 
2343
 * Implements the XML shell function "relaxng"
 
2344
 * validating the instance against a Relax-NG schemas
 
2345
 *
 
2346
 * Returns 0
 
2347
 */
 
2348
static int
 
2349
xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
 
2350
            xmlNodePtr node ATTRIBUTE_UNUSED,
 
2351
            xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2352
{
 
2353
    xmlRelaxNGPtr relaxngschemas;
 
2354
    xmlRelaxNGParserCtxtPtr ctxt;
 
2355
    xmlRelaxNGValidCtxtPtr vctxt;
 
2356
    int ret;
 
2357
 
 
2358
    ctxt = xmlRelaxNGNewParserCtxt(schemas);
 
2359
    xmlRelaxNGSetParserErrors(ctxt,
 
2360
            (xmlRelaxNGValidityErrorFunc) fprintf,
 
2361
            (xmlRelaxNGValidityWarningFunc) fprintf,
 
2362
            stderr);
 
2363
    relaxngschemas = xmlRelaxNGParse(ctxt);
 
2364
    xmlRelaxNGFreeParserCtxt(ctxt);
 
2365
    if (relaxngschemas == NULL) {
 
2366
        xmlGenericError(xmlGenericErrorContext,
 
2367
                "Relax-NG schema %s failed to compile\n", schemas);
 
2368
        return(-1);
 
2369
    }
 
2370
    vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
 
2371
    xmlRelaxNGSetValidErrors(vctxt,
 
2372
            (xmlRelaxNGValidityErrorFunc) fprintf,
 
2373
            (xmlRelaxNGValidityWarningFunc) fprintf,
 
2374
            stderr);
 
2375
    ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
 
2376
    if (ret == 0) {
 
2377
        fprintf(stderr, "%s validates\n", sctxt->filename);
 
2378
    } else if (ret > 0) {
 
2379
        fprintf(stderr, "%s fails to validate\n", sctxt->filename);
 
2380
    } else {
 
2381
        fprintf(stderr, "%s validation generated an internal error\n",
 
2382
               sctxt->filename);
 
2383
    }
 
2384
    xmlRelaxNGFreeValidCtxt(vctxt);
 
2385
    if (relaxngschemas != NULL)
 
2386
        xmlRelaxNGFree(relaxngschemas);
 
2387
    return(0);
 
2388
}
 
2389
#endif
 
2390
 
 
2391
#ifdef LIBXML_OUTPUT_ENABLED
 
2392
/**
 
2393
 * xmlShellCat:
 
2394
 * @ctxt:  the shell context
 
2395
 * @arg:  unused
 
2396
 * @node:  a node
 
2397
 * @node2:  unused
 
2398
 *
 
2399
 * Implements the XML shell function "cat"
 
2400
 * dumps the serialization node content (XML or HTML).
 
2401
 *
 
2402
 * Returns 0
 
2403
 */
 
2404
int
 
2405
xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
 
2406
            xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2407
{
 
2408
    if (!ctxt)
 
2409
        return (0);
 
2410
    if (node == NULL) {
 
2411
        fprintf(ctxt->output, "NULL\n");
 
2412
        return (0);
 
2413
    }    
 
2414
    if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
 
2415
#ifdef LIBXML_HTML_ENABLED
 
2416
        if (node->type == XML_HTML_DOCUMENT_NODE)
 
2417
            htmlDocDump(ctxt->output, (htmlDocPtr) node);
 
2418
        else
 
2419
            htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
 
2420
#else
 
2421
        if (node->type == XML_DOCUMENT_NODE)
 
2422
            xmlDocDump(ctxt->output, (xmlDocPtr) node);
 
2423
        else
 
2424
            xmlElemDump(ctxt->output, ctxt->doc, node);
 
2425
#endif /* LIBXML_HTML_ENABLED */
 
2426
    } else {
 
2427
        if (node->type == XML_DOCUMENT_NODE)
 
2428
            xmlDocDump(ctxt->output, (xmlDocPtr) node);
 
2429
        else
 
2430
            xmlElemDump(ctxt->output, ctxt->doc, node);
 
2431
    }
 
2432
    fprintf(ctxt->output, "\n");
 
2433
    return (0);
 
2434
}
 
2435
#endif /* LIBXML_OUTPUT_ENABLED */
 
2436
 
 
2437
/**
 
2438
 * xmlShellLoad:
 
2439
 * @ctxt:  the shell context
 
2440
 * @filename:  the file name
 
2441
 * @node:  unused
 
2442
 * @node2:  unused
 
2443
 *
 
2444
 * Implements the XML shell function "load"
 
2445
 * loads a new document specified by the filename
 
2446
 *
 
2447
 * Returns 0 or -1 if loading failed
 
2448
 */
 
2449
int
 
2450
xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
 
2451
             xmlNodePtr node ATTRIBUTE_UNUSED,
 
2452
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2453
{
 
2454
    xmlDocPtr doc;
 
2455
    int html = 0;
 
2456
 
 
2457
    if ((ctxt == NULL) || (filename == NULL)) return(-1);
 
2458
    if (ctxt->doc != NULL)
 
2459
        html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
 
2460
 
 
2461
    if (html) {
 
2462
#ifdef LIBXML_HTML_ENABLED
 
2463
        doc = htmlParseFile(filename, NULL);
 
2464
#else
 
2465
        fprintf(ctxt->output, "HTML support not compiled in\n");
 
2466
        doc = NULL;
 
2467
#endif /* LIBXML_HTML_ENABLED */
 
2468
    } else {
 
2469
        doc = xmlReadFile(filename,NULL,0);
 
2470
    }
 
2471
    if (doc != NULL) {
 
2472
        if (ctxt->loaded == 1) {
 
2473
            xmlFreeDoc(ctxt->doc);
 
2474
        }
 
2475
        ctxt->loaded = 1;
 
2476
#ifdef LIBXML_XPATH_ENABLED
 
2477
        xmlXPathFreeContext(ctxt->pctxt);
 
2478
#endif /* LIBXML_XPATH_ENABLED */
 
2479
        xmlFree(ctxt->filename);
 
2480
        ctxt->doc = doc;
 
2481
        ctxt->node = (xmlNodePtr) doc;
 
2482
#ifdef LIBXML_XPATH_ENABLED
 
2483
        ctxt->pctxt = xmlXPathNewContext(doc);
 
2484
#endif /* LIBXML_XPATH_ENABLED */
 
2485
        ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
 
2486
    } else
 
2487
        return (-1);
 
2488
    return (0);
 
2489
}
 
2490
 
 
2491
#ifdef LIBXML_OUTPUT_ENABLED
 
2492
/**
 
2493
 * xmlShellWrite:
 
2494
 * @ctxt:  the shell context
 
2495
 * @filename:  the file name
 
2496
 * @node:  a node in the tree
 
2497
 * @node2:  unused
 
2498
 *
 
2499
 * Implements the XML shell function "write"
 
2500
 * Write the current node to the filename, it saves the serialization
 
2501
 * of the subtree under the @node specified
 
2502
 *
 
2503
 * Returns 0 or -1 in case of error
 
2504
 */
 
2505
int
 
2506
xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
 
2507
              xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2508
{
 
2509
    if (node == NULL)
 
2510
        return (-1);
 
2511
    if ((filename == NULL) || (filename[0] == 0)) {
 
2512
        return (-1);
 
2513
    }
 
2514
#ifdef W_OK
 
2515
    if (access((char *) filename, W_OK)) {
 
2516
        xmlGenericError(xmlGenericErrorContext,
 
2517
                        "Cannot write to %s\n", filename);
 
2518
        return (-1);
 
2519
    }
 
2520
#endif
 
2521
    switch (node->type) {
 
2522
        case XML_DOCUMENT_NODE:
 
2523
            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
 
2524
                xmlGenericError(xmlGenericErrorContext,
 
2525
                                "Failed to write to %s\n", filename);
 
2526
                return (-1);
 
2527
            }
 
2528
            break;
 
2529
        case XML_HTML_DOCUMENT_NODE:
 
2530
#ifdef LIBXML_HTML_ENABLED
 
2531
            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
 
2532
                xmlGenericError(xmlGenericErrorContext,
 
2533
                                "Failed to write to %s\n", filename);
 
2534
                return (-1);
 
2535
            }
 
2536
#else
 
2537
            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
 
2538
                xmlGenericError(xmlGenericErrorContext,
 
2539
                                "Failed to write to %s\n", filename);
 
2540
                return (-1);
 
2541
            }
 
2542
#endif /* LIBXML_HTML_ENABLED */
 
2543
            break;
 
2544
        default:{
 
2545
                FILE *f;
 
2546
 
 
2547
                f = fopen((char *) filename, "w");
 
2548
                if (f == NULL) {
 
2549
                    xmlGenericError(xmlGenericErrorContext,
 
2550
                                    "Failed to write to %s\n", filename);
 
2551
                    return (-1);
 
2552
                }
 
2553
                xmlElemDump(f, ctxt->doc, node);
 
2554
                fclose(f);
 
2555
            }
 
2556
    }
 
2557
    return (0);
 
2558
}
 
2559
 
 
2560
/**
 
2561
 * xmlShellSave:
 
2562
 * @ctxt:  the shell context
 
2563
 * @filename:  the file name (optional)
 
2564
 * @node:  unused
 
2565
 * @node2:  unused
 
2566
 *
 
2567
 * Implements the XML shell function "save"
 
2568
 * Write the current document to the filename, or it's original name
 
2569
 *
 
2570
 * Returns 0 or -1 in case of error
 
2571
 */
 
2572
int
 
2573
xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
 
2574
             xmlNodePtr node ATTRIBUTE_UNUSED,
 
2575
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2576
{
 
2577
    if ((ctxt == NULL) || (ctxt->doc == NULL))
 
2578
        return (-1);
 
2579
    if ((filename == NULL) || (filename[0] == 0))
 
2580
        filename = ctxt->filename;
 
2581
    if (filename == NULL)
 
2582
        return (-1);
 
2583
#ifdef W_OK
 
2584
    if (access((char *) filename, W_OK)) {
 
2585
        xmlGenericError(xmlGenericErrorContext,
 
2586
                        "Cannot save to %s\n", filename);
 
2587
        return (-1);
 
2588
    }
 
2589
#endif
 
2590
    switch (ctxt->doc->type) {
 
2591
        case XML_DOCUMENT_NODE:
 
2592
            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
 
2593
                xmlGenericError(xmlGenericErrorContext,
 
2594
                                "Failed to save to %s\n", filename);
 
2595
            }
 
2596
            break;
 
2597
        case XML_HTML_DOCUMENT_NODE:
 
2598
#ifdef LIBXML_HTML_ENABLED
 
2599
            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
 
2600
                xmlGenericError(xmlGenericErrorContext,
 
2601
                                "Failed to save to %s\n", filename);
 
2602
            }
 
2603
#else
 
2604
            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
 
2605
                xmlGenericError(xmlGenericErrorContext,
 
2606
                                "Failed to save to %s\n", filename);
 
2607
            }
 
2608
#endif /* LIBXML_HTML_ENABLED */
 
2609
            break;
 
2610
        default:
 
2611
            xmlGenericError(xmlGenericErrorContext,
 
2612
            "To save to subparts of a document use the 'write' command\n");
 
2613
            return (-1);
 
2614
 
 
2615
    }
 
2616
    return (0);
 
2617
}
 
2618
#endif /* LIBXML_OUTPUT_ENABLED */
 
2619
 
 
2620
#ifdef LIBXML_VALID_ENABLED
 
2621
/**
 
2622
 * xmlShellValidate:
 
2623
 * @ctxt:  the shell context
 
2624
 * @dtd:  the DTD URI (optional)
 
2625
 * @node:  unused
 
2626
 * @node2:  unused
 
2627
 *
 
2628
 * Implements the XML shell function "validate"
 
2629
 * Validate the document, if a DTD path is provided, then the validation
 
2630
 * is done against the given DTD.
 
2631
 *
 
2632
 * Returns 0 or -1 in case of error
 
2633
 */
 
2634
int
 
2635
xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
 
2636
                 xmlNodePtr node ATTRIBUTE_UNUSED,
 
2637
                 xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2638
{
 
2639
    xmlValidCtxt vctxt;
 
2640
    int res = -1;
 
2641
 
 
2642
    if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1);
 
2643
    vctxt.userData = stderr;
 
2644
    vctxt.error = (xmlValidityErrorFunc) fprintf;
 
2645
    vctxt.warning = (xmlValidityWarningFunc) fprintf;
 
2646
 
 
2647
    if ((dtd == NULL) || (dtd[0] == 0)) {
 
2648
        res = xmlValidateDocument(&vctxt, ctxt->doc);
 
2649
    } else {
 
2650
        xmlDtdPtr subset;
 
2651
 
 
2652
        subset = xmlParseDTD(NULL, (xmlChar *) dtd);
 
2653
        if (subset != NULL) {
 
2654
            res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
 
2655
 
 
2656
            xmlFreeDtd(subset);
 
2657
        }
 
2658
    }
 
2659
    return (res);
 
2660
}
 
2661
#endif /* LIBXML_VALID_ENABLED */
 
2662
 
 
2663
/**
 
2664
 * xmlShellDu:
 
2665
 * @ctxt:  the shell context
 
2666
 * @arg:  unused
 
2667
 * @tree:  a node defining a subtree
 
2668
 * @node2:  unused
 
2669
 *
 
2670
 * Implements the XML shell function "du"
 
2671
 * show the structure of the subtree under node @tree
 
2672
 * If @tree is null, the command works on the current node.
 
2673
 *
 
2674
 * Returns 0 or -1 in case of error
 
2675
 */
 
2676
int
 
2677
xmlShellDu(xmlShellCtxtPtr ctxt,
 
2678
           char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
 
2679
           xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2680
{
 
2681
    xmlNodePtr node;
 
2682
    int indent = 0, i;
 
2683
 
 
2684
    if (!ctxt)
 
2685
        return (-1);
 
2686
 
 
2687
    if (tree == NULL)
 
2688
        return (-1);
 
2689
    node = tree;
 
2690
    while (node != NULL) {
 
2691
        if ((node->type == XML_DOCUMENT_NODE) ||
 
2692
            (node->type == XML_HTML_DOCUMENT_NODE)) {
 
2693
            fprintf(ctxt->output, "/\n");
 
2694
        } else if (node->type == XML_ELEMENT_NODE) {
 
2695
            for (i = 0; i < indent; i++)
 
2696
                fprintf(ctxt->output, "  ");
 
2697
            fprintf(ctxt->output, "%s\n", node->name);
 
2698
        } else {
 
2699
        }
 
2700
 
 
2701
        /*
 
2702
         * Browse the full subtree, deep first
 
2703
         */
 
2704
 
 
2705
        if ((node->type == XML_DOCUMENT_NODE) ||
 
2706
            (node->type == XML_HTML_DOCUMENT_NODE)) {
 
2707
            node = ((xmlDocPtr) node)->children;
 
2708
        } else if ((node->children != NULL)
 
2709
                   && (node->type != XML_ENTITY_REF_NODE)) {
 
2710
            /* deep first */
 
2711
            node = node->children;
 
2712
            indent++;
 
2713
        } else if ((node != tree) && (node->next != NULL)) {
 
2714
            /* then siblings */
 
2715
            node = node->next;
 
2716
        } else if (node != tree) {
 
2717
            /* go up to parents->next if needed */
 
2718
            while (node != tree) {
 
2719
                if (node->parent != NULL) {
 
2720
                    node = node->parent;
 
2721
                    indent--;
 
2722
                }
 
2723
                if ((node != tree) && (node->next != NULL)) {
 
2724
                    node = node->next;
 
2725
                    break;
 
2726
                }
 
2727
                if (node->parent == NULL) {
 
2728
                    node = NULL;
 
2729
                    break;
 
2730
                }
 
2731
                if (node == tree) {
 
2732
                    node = NULL;
 
2733
                    break;
 
2734
                }
 
2735
            }
 
2736
            /* exit condition */
 
2737
            if (node == tree)
 
2738
                node = NULL;
 
2739
        } else
 
2740
            node = NULL;
 
2741
    }
 
2742
    return (0);
 
2743
}
 
2744
 
 
2745
/**
 
2746
 * xmlShellPwd:
 
2747
 * @ctxt:  the shell context
 
2748
 * @buffer:  the output buffer
 
2749
 * @node:  a node 
 
2750
 * @node2:  unused
 
2751
 *
 
2752
 * Implements the XML shell function "pwd"
 
2753
 * Show the full path from the root to the node, if needed building
 
2754
 * thumblers when similar elements exists at a given ancestor level.
 
2755
 * The output is compatible with XPath commands.
 
2756
 *
 
2757
 * Returns 0 or -1 in case of error
 
2758
 */
 
2759
int
 
2760
xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
 
2761
            xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
 
2762
{
 
2763
    xmlChar *path;
 
2764
 
 
2765
    if ((node == NULL) || (buffer == NULL))
 
2766
        return (-1);
 
2767
 
 
2768
    path = xmlGetNodePath(node);
 
2769
    if (path == NULL)
 
2770
        return (-1);
 
2771
 
 
2772
    /*
 
2773
     * This test prevents buffer overflow, because this routine
 
2774
     * is only called by xmlShell, in which the second argument is
 
2775
     * 500 chars long.
 
2776
     * It is a dirty hack before a cleaner solution is found.
 
2777
     * Documentation should mention that the second argument must
 
2778
     * be at least 500 chars long, and could be stripped if too long.
 
2779
     */
 
2780
    snprintf(buffer, 499, "%s", path);
 
2781
    buffer[499] = '0';
 
2782
    xmlFree(path);
 
2783
 
 
2784
    return (0);
 
2785
}
 
2786
 
 
2787
/**
 
2788
 * xmlShell:
 
2789
 * @doc:  the initial document
 
2790
 * @filename:  the output buffer
 
2791
 * @input:  the line reading function
 
2792
 * @output:  the output FILE*, defaults to stdout if NULL
 
2793
 *
 
2794
 * Implements the XML shell 
 
2795
 * This allow to load, validate, view, modify and save a document
 
2796
 * using a environment similar to a UNIX commandline.
 
2797
 */
 
2798
void
 
2799
xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
 
2800
         FILE * output)
 
2801
{
 
2802
    char prompt[500] = "/ > ";
 
2803
    char *cmdline = NULL, *cur;
 
2804
    int nbargs;
 
2805
    char command[100];
 
2806
    char arg[400];
 
2807
    int i;
 
2808
    xmlShellCtxtPtr ctxt;
 
2809
    xmlXPathObjectPtr list;
 
2810
 
 
2811
    if (doc == NULL)
 
2812
        return;
 
2813
    if (filename == NULL)
 
2814
        return;
 
2815
    if (input == NULL)
 
2816
        return;
 
2817
    if (output == NULL)
 
2818
        output = stdout;
 
2819
    ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
 
2820
    if (ctxt == NULL)
 
2821
        return;
 
2822
    ctxt->loaded = 0;
 
2823
    ctxt->doc = doc;
 
2824
    ctxt->input = input;
 
2825
    ctxt->output = output;
 
2826
    ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
 
2827
    ctxt->node = (xmlNodePtr) ctxt->doc;
 
2828
 
 
2829
#ifdef LIBXML_XPATH_ENABLED
 
2830
    ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
 
2831
    if (ctxt->pctxt == NULL) {
 
2832
        xmlFree(ctxt);
 
2833
        return;
 
2834
    }
 
2835
#endif /* LIBXML_XPATH_ENABLED */
 
2836
    while (1) {
 
2837
        if (ctxt->node == (xmlNodePtr) ctxt->doc)
 
2838
            snprintf(prompt, sizeof(prompt), "%s > ", "/");
 
2839
        else if ((ctxt->node != NULL) && (ctxt->node->name))
 
2840
            snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
 
2841
        else
 
2842
            snprintf(prompt, sizeof(prompt), "? > ");
 
2843
        prompt[sizeof(prompt) - 1] = 0;
 
2844
 
 
2845
        /*
 
2846
         * Get a new command line
 
2847
         */
 
2848
        cmdline = ctxt->input(prompt);
 
2849
        if (cmdline == NULL)
 
2850
            break;
 
2851
 
 
2852
        /*
 
2853
         * Parse the command itself
 
2854
         */
 
2855
        cur = cmdline;
 
2856
        nbargs = 0;
 
2857
        while ((*cur == ' ') || (*cur == '\t'))
 
2858
            cur++;
 
2859
        i = 0;
 
2860
        while ((*cur != ' ') && (*cur != '\t') &&
 
2861
               (*cur != '\n') && (*cur != '\r')) {
 
2862
            if (*cur == 0)
 
2863
                break;
 
2864
            command[i++] = *cur++;
 
2865
        }
 
2866
        command[i] = 0;
 
2867
        if (i == 0)
 
2868
            continue;
 
2869
        nbargs++;
 
2870
 
 
2871
        /*
 
2872
         * Parse the argument
 
2873
         */
 
2874
        while ((*cur == ' ') || (*cur == '\t'))
 
2875
            cur++;
 
2876
        i = 0;
 
2877
        while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
 
2878
            if (*cur == 0)
 
2879
                break;
 
2880
            arg[i++] = *cur++;
 
2881
        }
 
2882
        arg[i] = 0;
 
2883
        if (i != 0)
 
2884
            nbargs++;
 
2885
 
 
2886
        /*
 
2887
         * start interpreting the command
 
2888
         */
 
2889
        if (!strcmp(command, "exit"))
 
2890
            break;
 
2891
        if (!strcmp(command, "quit"))
 
2892
            break;
 
2893
        if (!strcmp(command, "bye"))
 
2894
            break;
 
2895
                if (!strcmp(command, "help")) {
 
2896
                  fprintf(ctxt->output, "\tbase         display XML base of the node\n");
 
2897
                  fprintf(ctxt->output, "\tsetbase URI  change the XML base of the node\n");
 
2898
                  fprintf(ctxt->output, "\tbye          leave shell\n");
 
2899
                  fprintf(ctxt->output, "\tcat [node]   display node or current node\n");
 
2900
                  fprintf(ctxt->output, "\tcd [path]    change directory to path or to root\n");
 
2901
                  fprintf(ctxt->output, "\tdir [path]   dumps informations about the node (namespace, attributes, content)\n");
 
2902
                  fprintf(ctxt->output, "\tdu [path]    show the structure of the subtree under path or the current node\n");
 
2903
                  fprintf(ctxt->output, "\texit         leave shell\n");
 
2904
                  fprintf(ctxt->output, "\thelp         display this help\n");
 
2905
                  fprintf(ctxt->output, "\tfree         display memory usage\n");
 
2906
                  fprintf(ctxt->output, "\tload [name]  load a new document with name\n");
 
2907
                  fprintf(ctxt->output, "\tls [path]    list contents of path or the current directory\n");
 
2908
                  fprintf(ctxt->output, "\tset xml_fragment replace the current node content with the fragment parsed in context\n");
 
2909
#ifdef LIBXML_XPATH_ENABLED
 
2910
                  fprintf(ctxt->output, "\txpath expr   evaluate the XPath expression in that context and print the result\n");
 
2911
                  fprintf(ctxt->output, "\tsetns nsreg  register a namespace to a prefix in the XPath evaluation context\n");
 
2912
                  fprintf(ctxt->output, "\t             format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
 
2913
                  fprintf(ctxt->output, "\tsetrootns    register all namespace found on the root element\n");
 
2914
                  fprintf(ctxt->output, "\t             the default namespace if any uses 'defaultns' prefix\n");
 
2915
#endif /* LIBXML_XPATH_ENABLED */
 
2916
                  fprintf(ctxt->output, "\tpwd          display current working directory\n");
 
2917
                  fprintf(ctxt->output, "\tquit         leave shell\n");
 
2918
#ifdef LIBXML_OUTPUT_ENABLED
 
2919
                  fprintf(ctxt->output, "\tsave [name]  save this document to name or the original name\n");
 
2920
                  fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
 
2921
#endif /* LIBXML_OUTPUT_ENABLED */
 
2922
#ifdef LIBXML_VALID_ENABLED
 
2923
                  fprintf(ctxt->output, "\tvalidate     check the document for errors\n");
 
2924
#endif /* LIBXML_VALID_ENABLED */
 
2925
#ifdef LIBXML_SCHEMAS_ENABLED
 
2926
                  fprintf(ctxt->output, "\trelaxng rng  validate the document agaisnt the Relax-NG schemas\n");
 
2927
#endif
 
2928
                  fprintf(ctxt->output, "\tgrep string  search for a string in the subtree\n");
 
2929
#ifdef LIBXML_VALID_ENABLED
 
2930
        } else if (!strcmp(command, "validate")) {
 
2931
            xmlShellValidate(ctxt, arg, NULL, NULL);
 
2932
#endif /* LIBXML_VALID_ENABLED */
 
2933
        } else if (!strcmp(command, "load")) {
 
2934
            xmlShellLoad(ctxt, arg, NULL, NULL);
 
2935
#ifdef LIBXML_SCHEMAS_ENABLED
 
2936
        } else if (!strcmp(command, "relaxng")) {
 
2937
            xmlShellRNGValidate(ctxt, arg, NULL, NULL);
 
2938
#endif
 
2939
#ifdef LIBXML_OUTPUT_ENABLED
 
2940
        } else if (!strcmp(command, "save")) {
 
2941
            xmlShellSave(ctxt, arg, NULL, NULL);
 
2942
        } else if (!strcmp(command, "write")) {
 
2943
            if ((arg == NULL) || (arg[0] == 0))
 
2944
                xmlGenericError(xmlGenericErrorContext,
 
2945
                        "Write command requires a filename argument\n");
 
2946
            else
 
2947
                xmlShellWrite(ctxt, arg, NULL, NULL);
 
2948
#endif /* LIBXML_OUTPUT_ENABLED */
 
2949
        } else if (!strcmp(command, "grep")) {
 
2950
            xmlShellGrep(ctxt, arg, ctxt->node, NULL);
 
2951
        } else if (!strcmp(command, "free")) {
 
2952
            if (arg[0] == 0) {
 
2953
                xmlMemShow(ctxt->output, 0);
 
2954
            } else {
 
2955
                int len = 0;
 
2956
 
 
2957
                sscanf(arg, "%d", &len);
 
2958
                xmlMemShow(ctxt->output, len);
 
2959
            }
 
2960
        } else if (!strcmp(command, "pwd")) {
 
2961
            char dir[500];
 
2962
 
 
2963
            if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
 
2964
                fprintf(ctxt->output, "%s\n", dir);
 
2965
        } else if (!strcmp(command, "du")) {
 
2966
            xmlShellDu(ctxt, NULL, ctxt->node, NULL);
 
2967
        } else if (!strcmp(command, "base")) {
 
2968
            xmlShellBase(ctxt, NULL, ctxt->node, NULL);
 
2969
        } else if (!strcmp(command, "set")) {
 
2970
            xmlShellSetContent(ctxt, arg, ctxt->node, NULL);
 
2971
#ifdef LIBXML_XPATH_ENABLED
 
2972
        } else if (!strcmp(command, "setns")) {
 
2973
            if (arg[0] == 0) {
 
2974
                xmlGenericError(xmlGenericErrorContext,
 
2975
                                "setns: prefix=[nsuri] required\n");
 
2976
            } else {
 
2977
                xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
 
2978
            }
 
2979
        } else if (!strcmp(command, "setrootns")) {
 
2980
            xmlNodePtr root;
 
2981
 
 
2982
            root = xmlDocGetRootElement(ctxt->doc);
 
2983
            xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL);
 
2984
        } else if (!strcmp(command, "xpath")) {
 
2985
            if (arg[0] == 0) {
 
2986
                xmlGenericError(xmlGenericErrorContext,
 
2987
                                "xpath: expression required\n");
 
2988
            } else {
 
2989
                ctxt->pctxt->node = ctxt->node;
 
2990
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
 
2991
                xmlXPathDebugDumpObject(ctxt->output, list, 0);
 
2992
                xmlXPathFreeObject(list);
 
2993
            }
 
2994
#endif /* LIBXML_XPATH_ENABLED */
 
2995
#ifdef LIBXML_TREE_ENABLED
 
2996
        } else if (!strcmp(command, "setbase")) {
 
2997
            xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
 
2998
#endif
 
2999
        } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
 
3000
            int dir = (!strcmp(command, "dir"));
 
3001
 
 
3002
            if (arg[0] == 0) {
 
3003
                if (dir)
 
3004
                    xmlShellDir(ctxt, NULL, ctxt->node, NULL);
 
3005
                else
 
3006
                    xmlShellList(ctxt, NULL, ctxt->node, NULL);
 
3007
            } else {
 
3008
                ctxt->pctxt->node = ctxt->node;
 
3009
#ifdef LIBXML_XPATH_ENABLED
 
3010
                ctxt->pctxt->node = ctxt->node;
 
3011
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
 
3012
#else
 
3013
                list = NULL;
 
3014
#endif /* LIBXML_XPATH_ENABLED */
 
3015
                if (list != NULL) {
 
3016
                    switch (list->type) {
 
3017
                        case XPATH_UNDEFINED:
 
3018
                            xmlGenericError(xmlGenericErrorContext,
 
3019
                                            "%s: no such node\n", arg);
 
3020
                            break;
 
3021
                        case XPATH_NODESET:{
 
3022
                                int indx;
 
3023
 
 
3024
                                if (list->nodesetval == NULL)
 
3025
                                    break;
 
3026
 
 
3027
                                for (indx = 0;
 
3028
                                     indx < list->nodesetval->nodeNr;
 
3029
                                     indx++) {
 
3030
                                    if (dir)
 
3031
                                        xmlShellDir(ctxt, NULL,
 
3032
                                                    list->nodesetval->
 
3033
                                                    nodeTab[indx], NULL);
 
3034
                                    else
 
3035
                                        xmlShellList(ctxt, NULL,
 
3036
                                                     list->nodesetval->
 
3037
                                                     nodeTab[indx], NULL);
 
3038
                                }
 
3039
                                break;
 
3040
                            }
 
3041
                        case XPATH_BOOLEAN:
 
3042
                            xmlGenericError(xmlGenericErrorContext,
 
3043
                                            "%s is a Boolean\n", arg);
 
3044
                            break;
 
3045
                        case XPATH_NUMBER:
 
3046
                            xmlGenericError(xmlGenericErrorContext,
 
3047
                                            "%s is a number\n", arg);
 
3048
                            break;
 
3049
                        case XPATH_STRING:
 
3050
                            xmlGenericError(xmlGenericErrorContext,
 
3051
                                            "%s is a string\n", arg);
 
3052
                            break;
 
3053
                        case XPATH_POINT:
 
3054
                            xmlGenericError(xmlGenericErrorContext,
 
3055
                                            "%s is a point\n", arg);
 
3056
                            break;
 
3057
                        case XPATH_RANGE:
 
3058
                            xmlGenericError(xmlGenericErrorContext,
 
3059
                                            "%s is a range\n", arg);
 
3060
                            break;
 
3061
                        case XPATH_LOCATIONSET:
 
3062
                            xmlGenericError(xmlGenericErrorContext,
 
3063
                                            "%s is a range\n", arg);
 
3064
                            break;
 
3065
                        case XPATH_USERS:
 
3066
                            xmlGenericError(xmlGenericErrorContext,
 
3067
                                            "%s is user-defined\n", arg);
 
3068
                            break;
 
3069
                        case XPATH_XSLT_TREE:
 
3070
                            xmlGenericError(xmlGenericErrorContext,
 
3071
                                            "%s is an XSLT value tree\n",
 
3072
                                            arg);
 
3073
                            break;
 
3074
                    }
 
3075
#ifdef LIBXML_XPATH_ENABLED
 
3076
                    xmlXPathFreeObject(list);
 
3077
#endif
 
3078
                } else {
 
3079
                    xmlGenericError(xmlGenericErrorContext,
 
3080
                                    "%s: no such node\n", arg);
 
3081
                }
 
3082
                ctxt->pctxt->node = NULL;
 
3083
            }
 
3084
        } else if (!strcmp(command, "cd")) {
 
3085
            if (arg[0] == 0) {
 
3086
                ctxt->node = (xmlNodePtr) ctxt->doc;
 
3087
            } else {
 
3088
#ifdef LIBXML_XPATH_ENABLED
 
3089
                ctxt->pctxt->node = ctxt->node;
 
3090
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
 
3091
#else
 
3092
                list = NULL;
 
3093
#endif /* LIBXML_XPATH_ENABLED */
 
3094
                if (list != NULL) {
 
3095
                    switch (list->type) {
 
3096
                        case XPATH_UNDEFINED:
 
3097
                            xmlGenericError(xmlGenericErrorContext,
 
3098
                                            "%s: no such node\n", arg);
 
3099
                            break;
 
3100
                        case XPATH_NODESET:
 
3101
                            if (list->nodesetval != NULL) {
 
3102
                                if (list->nodesetval->nodeNr == 1) {
 
3103
                                    ctxt->node = list->nodesetval->nodeTab[0];
 
3104
                                    if ((ctxt->node != NULL) &&
 
3105
                                        (ctxt->node->type ==
 
3106
                                         XML_NAMESPACE_DECL)) {
 
3107
                                        xmlGenericError(xmlGenericErrorContext,
 
3108
                                                    "cannot cd to namespace\n");
 
3109
                                        ctxt->node = NULL;
 
3110
                                    }
 
3111
                                } else
 
3112
                                    xmlGenericError(xmlGenericErrorContext,
 
3113
                                                    "%s is a %d Node Set\n",
 
3114
                                                    arg,
 
3115
                                                    list->nodesetval->nodeNr);
 
3116
                            } else
 
3117
                                xmlGenericError(xmlGenericErrorContext,
 
3118
                                                "%s is an empty Node Set\n",
 
3119
                                                arg);
 
3120
                            break;
 
3121
                        case XPATH_BOOLEAN:
 
3122
                            xmlGenericError(xmlGenericErrorContext,
 
3123
                                            "%s is a Boolean\n", arg);
 
3124
                            break;
 
3125
                        case XPATH_NUMBER:
 
3126
                            xmlGenericError(xmlGenericErrorContext,
 
3127
                                            "%s is a number\n", arg);
 
3128
                            break;
 
3129
                        case XPATH_STRING:
 
3130
                            xmlGenericError(xmlGenericErrorContext,
 
3131
                                            "%s is a string\n", arg);
 
3132
                            break;
 
3133
                        case XPATH_POINT:
 
3134
                            xmlGenericError(xmlGenericErrorContext,
 
3135
                                            "%s is a point\n", arg);
 
3136
                            break;
 
3137
                        case XPATH_RANGE:
 
3138
                            xmlGenericError(xmlGenericErrorContext,
 
3139
                                            "%s is a range\n", arg);
 
3140
                            break;
 
3141
                        case XPATH_LOCATIONSET:
 
3142
                            xmlGenericError(xmlGenericErrorContext,
 
3143
                                            "%s is a range\n", arg);
 
3144
                            break;
 
3145
                        case XPATH_USERS:
 
3146
                            xmlGenericError(xmlGenericErrorContext,
 
3147
                                            "%s is user-defined\n", arg);
 
3148
                            break;
 
3149
                        case XPATH_XSLT_TREE:
 
3150
                            xmlGenericError(xmlGenericErrorContext,
 
3151
                                            "%s is an XSLT value tree\n",
 
3152
                                            arg);
 
3153
                            break;
 
3154
                    }
 
3155
#ifdef LIBXML_XPATH_ENABLED
 
3156
                    xmlXPathFreeObject(list);
 
3157
#endif
 
3158
                } else {
 
3159
                    xmlGenericError(xmlGenericErrorContext,
 
3160
                                    "%s: no such node\n", arg);
 
3161
                }
 
3162
                ctxt->pctxt->node = NULL;
 
3163
            }
 
3164
#ifdef LIBXML_OUTPUT_ENABLED
 
3165
        } else if (!strcmp(command, "cat")) {
 
3166
            if (arg[0] == 0) {
 
3167
                xmlShellCat(ctxt, NULL, ctxt->node, NULL);
 
3168
            } else {
 
3169
                ctxt->pctxt->node = ctxt->node;
 
3170
#ifdef LIBXML_XPATH_ENABLED
 
3171
                ctxt->pctxt->node = ctxt->node;
 
3172
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
 
3173
#else
 
3174
                list = NULL;
 
3175
#endif /* LIBXML_XPATH_ENABLED */
 
3176
                if (list != NULL) {
 
3177
                    switch (list->type) {
 
3178
                        case XPATH_UNDEFINED:
 
3179
                            xmlGenericError(xmlGenericErrorContext,
 
3180
                                            "%s: no such node\n", arg);
 
3181
                            break;
 
3182
                        case XPATH_NODESET:{
 
3183
                                int indx;
 
3184
 
 
3185
                                if (list->nodesetval == NULL)
 
3186
                                    break;
 
3187
 
 
3188
                                for (indx = 0;
 
3189
                                     indx < list->nodesetval->nodeNr;
 
3190
                                     indx++) {
 
3191
                                    if (i > 0)
 
3192
                                        fprintf(ctxt->output, " -------\n");
 
3193
                                    xmlShellCat(ctxt, NULL,
 
3194
                                                list->nodesetval->
 
3195
                                                nodeTab[indx], NULL);
 
3196
                                }
 
3197
                                break;
 
3198
                            }
 
3199
                        case XPATH_BOOLEAN:
 
3200
                            xmlGenericError(xmlGenericErrorContext,
 
3201
                                            "%s is a Boolean\n", arg);
 
3202
                            break;
 
3203
                        case XPATH_NUMBER:
 
3204
                            xmlGenericError(xmlGenericErrorContext,
 
3205
                                            "%s is a number\n", arg);
 
3206
                            break;
 
3207
                        case XPATH_STRING:
 
3208
                            xmlGenericError(xmlGenericErrorContext,
 
3209
                                            "%s is a string\n", arg);
 
3210
                            break;
 
3211
                        case XPATH_POINT:
 
3212
                            xmlGenericError(xmlGenericErrorContext,
 
3213
                                            "%s is a point\n", arg);
 
3214
                            break;
 
3215
                        case XPATH_RANGE:
 
3216
                            xmlGenericError(xmlGenericErrorContext,
 
3217
                                            "%s is a range\n", arg);
 
3218
                            break;
 
3219
                        case XPATH_LOCATIONSET:
 
3220
                            xmlGenericError(xmlGenericErrorContext,
 
3221
                                            "%s is a range\n", arg);
 
3222
                            break;
 
3223
                        case XPATH_USERS:
 
3224
                            xmlGenericError(xmlGenericErrorContext,
 
3225
                                            "%s is user-defined\n", arg);
 
3226
                            break;
 
3227
                        case XPATH_XSLT_TREE:
 
3228
                            xmlGenericError(xmlGenericErrorContext,
 
3229
                                            "%s is an XSLT value tree\n",
 
3230
                                            arg);
 
3231
                            break;
 
3232
                    }
 
3233
#ifdef LIBXML_XPATH_ENABLED
 
3234
                    xmlXPathFreeObject(list);
 
3235
#endif
 
3236
                } else {
 
3237
                    xmlGenericError(xmlGenericErrorContext,
 
3238
                                    "%s: no such node\n", arg);
 
3239
                }
 
3240
                ctxt->pctxt->node = NULL;
 
3241
            }
 
3242
#endif /* LIBXML_OUTPUT_ENABLED */
 
3243
        } else {
 
3244
            xmlGenericError(xmlGenericErrorContext,
 
3245
                            "Unknown command %s\n", command);
 
3246
        }
 
3247
        free(cmdline);          /* not xmlFree here ! */
 
3248
        cmdline = NULL;
 
3249
    }
 
3250
#ifdef LIBXML_XPATH_ENABLED
 
3251
    xmlXPathFreeContext(ctxt->pctxt);
 
3252
#endif /* LIBXML_XPATH_ENABLED */
 
3253
    if (ctxt->loaded) {
 
3254
        xmlFreeDoc(ctxt->doc);
 
3255
    }
 
3256
    if (ctxt->filename != NULL)
 
3257
        xmlFree(ctxt->filename);
 
3258
    xmlFree(ctxt);
 
3259
    if (cmdline != NULL)
 
3260
        free(cmdline);          /* not xmlFree here ! */
 
3261
}
 
3262
 
 
3263
#endif /* LIBXML_XPATH_ENABLED */
 
3264
#define bottom_debugXML
 
3265
#include "elfgcchack.h"
 
3266
#endif /* LIBXML_DEBUG_ENABLED */