source: trunk/third/libxml2/debugXML.c @ 17096

Revision 17096, 69.6 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17095, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * debugXML.c : This is a set of routines used for debugging the tree
3 *              produced by the XML parser.
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <daniel@veillard.com>
8 */
9
10#include "libxml.h"
11#ifdef LIBXML_DEBUG_ENABLED
12
13#include <string.h>
14#ifdef HAVE_STDLIB_H
15#include <stdlib.h>
16#endif
17#ifdef HAVE_STRING_H
18#include <string.h>
19#endif
20#include <libxml/xmlmemory.h>
21#include <libxml/tree.h>
22#include <libxml/parser.h>
23#include <libxml/parserInternals.h>
24#include <libxml/valid.h>
25#include <libxml/debugXML.h>
26#include <libxml/HTMLtree.h>
27#include <libxml/HTMLparser.h>
28#include <libxml/xmlerror.h>
29#include <libxml/globals.h>
30#include <libxml/xpathInternals.h>
31
32/**
33 * xmlDebugDumpString:
34 * @output:  the FILE * for the output
35 * @str:  the string
36 *
37 * Dumps informations about the string, shorten it if necessary
38 */
39void
40xmlDebugDumpString(FILE * output, const xmlChar * str)
41{
42    int i;
43
44    if (output == NULL)
45        output = stdout;
46    if (str == NULL) {
47        fprintf(output, "(NULL)");
48        return;
49    }
50    for (i = 0; i < 40; i++)
51        if (str[i] == 0)
52            return;
53        else if (IS_BLANK(str[i]))
54            fputc(' ', output);
55        else if (str[i] >= 0x80)
56            fprintf(output, "#%X", str[i]);
57        else
58            fputc(str[i], output);
59    fprintf(output, "...");
60}
61
62static void
63xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
64    int i;
65    char shift[100];
66
67    for (i = 0;((i < depth) && (i < 25));i++)
68        shift[2 * i] = shift[2 * i + 1] = ' ';
69    shift[2 * i] = shift[2 * i + 1] = 0;
70
71    fprintf(output, shift);
72
73    if (dtd == NULL) {
74        fprintf(output, "DTD node is NULL\n");
75        return;
76    }
77
78    if (dtd->type != XML_DTD_NODE) {
79        fprintf(output, "PBM: not a DTD\n");
80        return;
81    }
82    if (dtd->name != NULL)
83        fprintf(output, "DTD(%s)", dtd->name);
84    else
85        fprintf(output, "DTD");
86    if (dtd->ExternalID != NULL)
87        fprintf(output, ", PUBLIC %s", dtd->ExternalID);
88    if (dtd->SystemID != NULL)
89        fprintf(output, ", SYSTEM %s", dtd->SystemID);
90    fprintf(output, "\n");
91    /*
92     * Do a bit of checking
93     */
94    if (dtd->parent == NULL)
95        fprintf(output, "PBM: DTD has no parent\n");
96    if (dtd->doc == NULL)
97        fprintf(output, "PBM: DTD has no doc\n");
98    if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
99        fprintf(output, "PBM: DTD doc differs from parent's one\n");
100    if (dtd->prev == NULL) {
101        if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
102            fprintf(output, "PBM: DTD has no prev and not first of list\n");
103    } else {
104        if (dtd->prev->next != (xmlNodePtr) dtd)
105            fprintf(output, "PBM: DTD prev->next : back link wrong\n");
106    }
107    if (dtd->next == NULL) {
108        if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
109            fprintf(output, "PBM: DTD has no next and not last of list\n");
110    } else {
111        if (dtd->next->prev != (xmlNodePtr) dtd)
112            fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
113    }
114}
115
116static void
117xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
118    int i;
119    char shift[100];
120
121    for (i = 0;((i < depth) && (i < 25));i++)
122        shift[2 * i] = shift[2 * i + 1] = ' ';
123    shift[2 * i] = shift[2 * i + 1] = 0;
124
125    fprintf(output, shift);
126
127    if (attr == NULL) {
128        fprintf(output, "Attribute declaration is NULL\n");
129        return;
130    }
131    if (attr->type != XML_ATTRIBUTE_DECL) {
132        fprintf(output, "PBM: not a Attr\n");
133        return;
134    }
135    if (attr->name != NULL)
136        fprintf(output, "ATTRDECL(%s)", attr->name);
137    else
138        fprintf(output, "PBM ATTRDECL noname!!!");
139    if (attr->elem != NULL)
140        fprintf(output, " for %s", attr->elem);
141    else
142        fprintf(output, " PBM noelem!!!");
143    switch (attr->atype) {
144        case XML_ATTRIBUTE_CDATA:
145            fprintf(output, " CDATA");
146            break;
147        case XML_ATTRIBUTE_ID:
148            fprintf(output, " ID");
149            break;
150        case XML_ATTRIBUTE_IDREF:
151            fprintf(output, " IDREF");
152            break;
153        case XML_ATTRIBUTE_IDREFS:
154            fprintf(output, " IDREFS");
155            break;
156        case XML_ATTRIBUTE_ENTITY:
157            fprintf(output, " ENTITY");
158            break;
159        case XML_ATTRIBUTE_ENTITIES:
160            fprintf(output, " ENTITIES");
161            break;
162        case XML_ATTRIBUTE_NMTOKEN:
163            fprintf(output, " NMTOKEN");
164            break;
165        case XML_ATTRIBUTE_NMTOKENS:
166            fprintf(output, " NMTOKENS");
167            break;
168        case XML_ATTRIBUTE_ENUMERATION:
169            fprintf(output, " ENUMERATION");
170            break;
171        case XML_ATTRIBUTE_NOTATION:
172            fprintf(output, " NOTATION ");
173            break;
174    }
175    if (attr->tree != NULL) {
176        int indx;
177        xmlEnumerationPtr cur = attr->tree;
178
179        for (indx = 0;indx < 5; indx++) {
180            if (indx != 0)
181                fprintf(output, "|%s", cur->name);
182            else
183                fprintf(output, " (%s", cur->name);
184            cur = cur->next;
185            if (cur == NULL) break;
186        }
187        if (cur == NULL)
188            fprintf(output, ")");
189        else
190            fprintf(output, "...)");
191    }
192    switch (attr->def) {
193        case XML_ATTRIBUTE_NONE:
194            break;
195        case XML_ATTRIBUTE_REQUIRED:
196            fprintf(output, " REQUIRED");
197            break;
198        case XML_ATTRIBUTE_IMPLIED:
199            fprintf(output, " IMPLIED");
200            break;
201        case XML_ATTRIBUTE_FIXED:
202            fprintf(output, " FIXED");
203            break;
204    }
205    if (attr->defaultValue != NULL) {
206        fprintf(output, "\"");
207        xmlDebugDumpString(output, attr->defaultValue);
208        fprintf(output, "\"");
209    }
210    fprintf(output, "\n");
211
212    /*
213     * Do a bit of checking
214     */
215    if (attr->parent == NULL)
216        fprintf(output, "PBM: Attr has no parent\n");
217    if (attr->doc == NULL)
218        fprintf(output, "PBM: Attr has no doc\n");
219    if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
220        fprintf(output, "PBM: Attr doc differs from parent's one\n");
221    if (attr->prev == NULL) {
222        if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
223            fprintf(output, "PBM: Attr has no prev and not first of list\n");
224    } else {
225        if (attr->prev->next != (xmlNodePtr) attr)
226            fprintf(output, "PBM: Attr prev->next : back link wrong\n");
227    }
228    if (attr->next == NULL) {
229        if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
230            fprintf(output, "PBM: Attr has no next and not last of list\n");
231    } else {
232        if (attr->next->prev != (xmlNodePtr) attr)
233            fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
234    }
235}
236
237static void
238xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
239    int i;
240    char shift[100];
241
242    for (i = 0;((i < depth) && (i < 25));i++)
243        shift[2 * i] = shift[2 * i + 1] = ' ';
244    shift[2 * i] = shift[2 * i + 1] = 0;
245
246    fprintf(output, shift);
247
248    if (elem == NULL) {
249        fprintf(output, "Element declaration is NULL\n");
250        return;
251    }
252    if (elem->type != XML_ELEMENT_DECL) {
253        fprintf(output, "PBM: not a Elem\n");
254        return;
255    }
256    if (elem->name != NULL) {
257        fprintf(output, "ELEMDECL(");
258        xmlDebugDumpString(output, elem->name);
259        fprintf(output, ")");
260    } else
261        fprintf(output, "PBM ELEMDECL noname!!!");
262    switch (elem->etype) {
263        case XML_ELEMENT_TYPE_UNDEFINED:
264            fprintf(output, ", UNDEFINED");
265            break;
266        case XML_ELEMENT_TYPE_EMPTY:
267            fprintf(output, ", EMPTY");
268            break;
269        case XML_ELEMENT_TYPE_ANY:
270            fprintf(output, ", ANY");
271            break;
272        case XML_ELEMENT_TYPE_MIXED:
273            fprintf(output, ", MIXED ");
274            break;
275        case XML_ELEMENT_TYPE_ELEMENT:
276            fprintf(output, ", MIXED ");
277            break;
278    }
279    if ((elem->type != XML_ELEMENT_NODE) &&
280        (elem->content != NULL)) {
281        char buf[5001];
282
283        buf[0] = 0;
284        xmlSnprintfElementContent(buf, 5000, elem->content, 1);
285        buf[5000] = 0;
286        fprintf(output, "%s", buf);
287    }
288    fprintf(output, "\n");
289
290    /*
291     * Do a bit of checking
292     */
293    if (elem->parent == NULL)
294        fprintf(output, "PBM: Elem has no parent\n");
295    if (elem->doc == NULL)
296        fprintf(output, "PBM: Elem has no doc\n");
297    if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
298        fprintf(output, "PBM: Elem doc differs from parent's one\n");
299    if (elem->prev == NULL) {
300        if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
301            fprintf(output, "PBM: Elem has no prev and not first of list\n");
302    } else {
303        if (elem->prev->next != (xmlNodePtr) elem)
304            fprintf(output, "PBM: Elem prev->next : back link wrong\n");
305    }
306    if (elem->next == NULL) {
307        if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
308            fprintf(output, "PBM: Elem has no next and not last of list\n");
309    } else {
310        if (elem->next->prev != (xmlNodePtr) elem)
311            fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
312    }
313}
314
315static void
316xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
317    int i;
318    char shift[100];
319
320    for (i = 0;((i < depth) && (i < 25));i++)
321        shift[2 * i] = shift[2 * i + 1] = ' ';
322    shift[2 * i] = shift[2 * i + 1] = 0;
323
324    fprintf(output, shift);
325
326    if (ent == NULL) {
327        fprintf(output, "Entity declaration is NULL\n");
328        return;
329    }
330    if (ent->type != XML_ENTITY_DECL) {
331        fprintf(output, "PBM: not a Entity decl\n");
332        return;
333    }
334    if (ent->name != NULL) {
335        fprintf(output, "ENTITYDECL(");
336        xmlDebugDumpString(output, ent->name);
337        fprintf(output, ")");
338    } else
339        fprintf(output, "PBM ENTITYDECL noname!!!");
340    switch (ent->etype) {
341        case XML_INTERNAL_GENERAL_ENTITY:
342            fprintf(output, ", internal\n");
343            break;
344        case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
345            fprintf(output, ", external parsed\n");
346            break;
347        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
348            fprintf(output, ", unparsed\n");
349            break;
350        case XML_INTERNAL_PARAMETER_ENTITY:
351            fprintf(output, ", parameter\n");
352            break;
353        case XML_EXTERNAL_PARAMETER_ENTITY:
354            fprintf(output, ", external parameter\n");
355            break;
356        case XML_INTERNAL_PREDEFINED_ENTITY:
357            fprintf(output, ", predefined\n");
358            break;
359    }
360    if (ent->ExternalID) {
361        fprintf(output, shift);
362        fprintf(output, " ExternalID=%s\n", ent->ExternalID);
363    }
364    if (ent->SystemID) {
365        fprintf(output, shift);
366        fprintf(output, " SystemID=%s\n", ent->SystemID);
367    }
368    if (ent->URI != NULL) {
369        fprintf(output, shift);
370        fprintf(output, " URI=%s\n", ent->URI);
371    }
372    if (ent->content) {
373        fprintf(output, shift);
374        fprintf(output, " content=");
375        xmlDebugDumpString(output, ent->content);
376        fprintf(output, "\n");
377    }
378
379    /*
380     * Do a bit of checking
381     */
382    if (ent->parent == NULL)
383        fprintf(output, "PBM: Ent has no parent\n");
384    if (ent->doc == NULL)
385        fprintf(output, "PBM: Ent has no doc\n");
386    if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
387        fprintf(output, "PBM: Ent doc differs from parent's one\n");
388    if (ent->prev == NULL) {
389        if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
390            fprintf(output, "PBM: Ent has no prev and not first of list\n");
391    } else {
392        if (ent->prev->next != (xmlNodePtr) ent)
393            fprintf(output, "PBM: Ent prev->next : back link wrong\n");
394    }
395    if (ent->next == NULL) {
396        if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
397            fprintf(output, "PBM: Ent has no next and not last of list\n");
398    } else {
399        if (ent->next->prev != (xmlNodePtr) ent)
400            fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
401    }
402}
403
404static void
405xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
406    int i;
407    char shift[100];
408
409    for (i = 0;((i < depth) && (i < 25));i++)
410        shift[2 * i] = shift[2 * i + 1] = ' ';
411    shift[2 * i] = shift[2 * i + 1] = 0;
412
413    fprintf(output, shift);
414
415    if (ns == NULL) {
416        fprintf(output, "namespace node is NULL\n");
417        return;
418    }
419    if (ns->type != XML_NAMESPACE_DECL) {
420        fprintf(output, "invalid namespace node %d\n", ns->type);
421        return;
422    }
423    if (ns->href == NULL) {
424        if (ns->prefix != NULL)
425            fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
426        else
427            fprintf(output, "incomplete default namespace href=NULL\n");
428    } else {
429        if (ns->prefix != NULL)
430            fprintf(output, "namespace %s href=", ns->prefix);
431        else
432            fprintf(output, "default namespace href=");
433
434        xmlDebugDumpString(output, ns->href);
435        fprintf(output, "\n");
436    }
437}
438
439static void
440xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
441    while (ns != NULL) {
442        xmlDebugDumpNamespace(output, ns, depth);
443        ns = ns->next;
444    }
445}
446
447static void
448xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
449    int i;
450    char shift[100];
451
452    for (i = 0;((i < depth) && (i < 25));i++)
453        shift[2 * i] = shift[2 * i + 1] = ' ';
454    shift[2 * i] = shift[2 * i + 1] = 0;
455
456    fprintf(output, shift);
457   
458    if (ent == NULL) {
459        fprintf(output, "Entity is NULL\n");
460        return;
461    }
462    switch (ent->etype) {
463        case XML_INTERNAL_GENERAL_ENTITY:
464            fprintf(output, "INTERNAL_GENERAL_ENTITY ");
465            break;
466        case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
467            fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
468            break;
469        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
470            fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
471            break;
472        case XML_INTERNAL_PARAMETER_ENTITY:
473            fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
474            break;
475        case XML_EXTERNAL_PARAMETER_ENTITY:
476            fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
477            break;
478        default:
479            fprintf(output, "ENTITY_%d ! ", ent->etype);
480    }
481    fprintf(output, "%s\n", ent->name);
482    if (ent->ExternalID) {
483        fprintf(output, shift);
484        fprintf(output, "ExternalID=%s\n", ent->ExternalID);
485    }
486    if (ent->SystemID) {
487        fprintf(output, shift);
488        fprintf(output, "SystemID=%s\n", ent->SystemID);
489    }
490    if (ent->URI) {
491        fprintf(output, shift);
492        fprintf(output, "URI=%s\n", ent->URI);
493    }
494    if (ent->content) {
495        fprintf(output, shift);
496        fprintf(output, "content=");
497        xmlDebugDumpString(output, ent->content);
498        fprintf(output, "\n");
499    }
500}
501
502/**
503 * xmlDebugDumpAttr:
504 * @output:  the FILE * for the output
505 * @attr:  the attribute
506 * @depth:  the indentation level.
507 *
508 * Dumps debug information for the attribute
509 */
510void
511xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
512    int i;
513    char shift[100];
514
515    for (i = 0;((i < depth) && (i < 25));i++)
516        shift[2 * i] = shift[2 * i + 1] = ' ';
517    shift[2 * i] = shift[2 * i + 1] = 0;
518
519    fprintf(output, shift);
520   
521    if (attr == NULL) {
522        fprintf(output, "Attr is NULL");
523        return;
524    }
525    fprintf(output, "ATTRIBUTE ");
526    xmlDebugDumpString(output, attr->name);
527    fprintf(output, "\n");
528    if (attr->children != NULL)
529        xmlDebugDumpNodeList(output, attr->children, depth + 1);
530
531    /*
532     * Do a bit of checking
533     */
534    if (attr->parent == NULL)
535        fprintf(output, "PBM: Attr has no parent\n");
536    if (attr->doc == NULL)
537        fprintf(output, "PBM: Attr has no doc\n");
538    if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
539        fprintf(output, "PBM: Attr doc differs from parent's one\n");
540    if (attr->prev == NULL) {
541        if ((attr->parent != NULL) && (attr->parent->properties != attr))
542            fprintf(output, "PBM: Attr has no prev and not first of list\n");
543    } else {
544        if (attr->prev->next != attr)
545            fprintf(output, "PBM: Attr prev->next : back link wrong\n");
546    }
547    if (attr->next != NULL) {
548        if (attr->next->prev != attr)
549            fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
550    }
551}
552
553/**
554 * xmlDebugDumpAttrList:
555 * @output:  the FILE * for the output
556 * @attr:  the attribute list
557 * @depth:  the indentation level.
558 *
559 * Dumps debug information for the attribute list
560 */
561void
562xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
563{
564    if (output == NULL)
565        output = stdout;
566    while (attr != NULL) {
567        xmlDebugDumpAttr(output, attr, depth);
568        attr = attr->next;
569    }
570}
571
572/**
573 * xmlDebugDumpOneNode:
574 * @output:  the FILE * for the output
575 * @node:  the node
576 * @depth:  the indentation level.
577 *
578 * Dumps debug information for the element node, it is not recursive
579 */
580void
581xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
582{
583    int i;
584    char shift[100];
585
586    if (output == NULL)
587        output = stdout;
588    for (i = 0; ((i < depth) && (i < 25)); i++)
589        shift[2 * i] = shift[2 * i + 1] = ' ';
590    shift[2 * i] = shift[2 * i + 1] = 0;
591
592    if (node == NULL) {
593        fprintf(output, shift);
594        fprintf(output, "node is NULL\n");
595        return;
596    }
597    switch (node->type) {
598        case XML_ELEMENT_NODE:
599            fprintf(output, shift);
600            fprintf(output, "ELEMENT ");
601            if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
602                xmlDebugDumpString(output, node->ns->prefix);
603                fprintf(output, ":");
604            }
605            xmlDebugDumpString(output, node->name);
606            fprintf(output, "\n");
607            break;
608        case XML_ATTRIBUTE_NODE:
609            fprintf(output, shift);
610            fprintf(output, "Error, ATTRIBUTE found here\n");
611            break;
612        case XML_TEXT_NODE:
613            fprintf(output, shift);
614            if (node->name == (const xmlChar *) xmlStringTextNoenc)
615                fprintf(output, "TEXT no enc\n");
616            else
617                fprintf(output, "TEXT\n");
618            break;
619        case XML_CDATA_SECTION_NODE:
620            fprintf(output, shift);
621            fprintf(output, "CDATA_SECTION\n");
622            break;
623        case XML_ENTITY_REF_NODE:
624            fprintf(output, shift);
625            fprintf(output, "ENTITY_REF(%s)\n", node->name);
626            break;
627        case XML_ENTITY_NODE:
628            fprintf(output, shift);
629            fprintf(output, "ENTITY\n");
630            break;
631        case XML_PI_NODE:
632            fprintf(output, shift);
633            fprintf(output, "PI %s\n", node->name);
634            break;
635        case XML_COMMENT_NODE:
636            fprintf(output, shift);
637            fprintf(output, "COMMENT\n");
638            break;
639        case XML_DOCUMENT_NODE:
640        case XML_HTML_DOCUMENT_NODE:
641            fprintf(output, shift);
642            fprintf(output, "Error, DOCUMENT found here\n");
643            break;
644        case XML_DOCUMENT_TYPE_NODE:
645            fprintf(output, shift);
646            fprintf(output, "DOCUMENT_TYPE\n");
647            break;
648        case XML_DOCUMENT_FRAG_NODE:
649            fprintf(output, shift);
650            fprintf(output, "DOCUMENT_FRAG\n");
651            break;
652        case XML_NOTATION_NODE:
653            fprintf(output, shift);
654            fprintf(output, "NOTATION\n");
655            break;
656        case XML_DTD_NODE:
657            xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
658            return;
659        case XML_ELEMENT_DECL:
660            xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
661            return;
662        case XML_ATTRIBUTE_DECL:
663            xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
664            return;
665        case XML_ENTITY_DECL:
666            xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
667            return;
668        case XML_NAMESPACE_DECL:
669            xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
670            return;
671        case XML_XINCLUDE_START:
672            fprintf(output, shift);
673            fprintf(output, "INCLUDE START\n");
674            return;
675        case XML_XINCLUDE_END:
676            fprintf(output, shift);
677            fprintf(output, "INCLUDE END\n");
678            return;
679        default:
680            fprintf(output, shift);
681            fprintf(output, "NODE_%d !!!\n", node->type);
682            return;
683    }
684    if (node->doc == NULL) {
685        fprintf(output, shift);
686        fprintf(output, "doc == NULL !!!\n");
687    }
688    if (node->nsDef != NULL)
689        xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
690    if (node->properties != NULL)
691        xmlDebugDumpAttrList(output, node->properties, depth + 1);
692    if (node->type != XML_ENTITY_REF_NODE) {
693        if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
694            shift[2 * i] = shift[2 * i + 1] = ' ';
695            shift[2 * i + 2] = shift[2 * i + 3] = 0;
696            fprintf(output, shift);
697            fprintf(output, "content=");
698#ifndef XML_USE_BUFFER_CONTENT
699            xmlDebugDumpString(output, node->content);
700#else
701            xmlDebugDumpString(output, xmlBufferContent(node->content));
702#endif
703            fprintf(output, "\n");
704        }
705    } else {
706        xmlEntityPtr ent;
707
708        ent = xmlGetDocEntity(node->doc, node->name);
709        if (ent != NULL)
710            xmlDebugDumpEntity(output, ent, depth + 1);
711    }
712    /*
713     * Do a bit of checking
714     */
715    if (node->parent == NULL)
716        fprintf(output, "PBM: Node has no parent\n");
717    if (node->doc == NULL)
718        fprintf(output, "PBM: Node has no doc\n");
719    if ((node->parent != NULL) && (node->doc != node->parent->doc))
720        fprintf(output, "PBM: Node doc differs from parent's one\n");
721    if (node->prev == NULL) {
722        if ((node->parent != NULL) && (node->parent->children != node))
723            fprintf(output,
724                    "PBM: Node has no prev and not first of list\n");
725    } else {
726        if (node->prev->next != node)
727            fprintf(output, "PBM: Node prev->next : back link wrong\n");
728    }
729    if (node->next == NULL) {
730        if ((node->parent != NULL) && (node->parent->last != node))
731            fprintf(output,
732                    "PBM: Node has no next and not last of list\n");
733    } else {
734        if (node->next->prev != node)
735            fprintf(output, "PBM: Node next->prev : forward link wrong\n");
736    }
737}
738
739/**
740 * xmlDebugDumpNode:
741 * @output:  the FILE * for the output
742 * @node:  the node
743 * @depth:  the indentation level.
744 *
745 * Dumps debug information for the element node, it is recursive
746 */
747void
748xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
749{
750    if (output == NULL)
751        output = stdout;
752    if (node == NULL) {
753        int i;
754        char shift[100];
755       
756        for (i = 0; ((i < depth) && (i < 25)); i++)
757            shift[2 * i] = shift[2 * i + 1] = ' ';
758        shift[2 * i] = shift[2 * i + 1] = 0;
759       
760        fprintf(output, shift);
761        fprintf(output, "node is NULL\n");
762        return;
763    }   
764    xmlDebugDumpOneNode(output, node, depth);
765    if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
766        xmlDebugDumpNodeList(output, node->children, depth + 1);
767}
768
769/**
770 * xmlDebugDumpNodeList:
771 * @output:  the FILE * for the output
772 * @node:  the node list
773 * @depth:  the indentation level.
774 *
775 * Dumps debug information for the list of element node, it is recursive
776 */
777void
778xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
779{
780    if (output == NULL)
781        output = stdout;
782    while (node != NULL) {
783        xmlDebugDumpNode(output, node, depth);
784        node = node->next;
785    }
786}
787
788
789/**
790 * xmlDebugDumpDocumentHead:
791 * @output:  the FILE * for the output
792 * @doc:  the document
793 *
794 * Dumps debug information cncerning the document, not recursive
795 */
796void
797xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
798{
799    if (output == NULL)
800        output = stdout;
801    if (doc == NULL) {
802        fprintf(output, "DOCUMENT == NULL !\n");
803        return;
804    }
805
806    switch (doc->type) {
807        case XML_ELEMENT_NODE:
808            fprintf(output, "Error, ELEMENT found here ");
809            break;
810        case XML_ATTRIBUTE_NODE:
811            fprintf(output, "Error, ATTRIBUTE found here\n");
812            break;
813        case XML_TEXT_NODE:
814            fprintf(output, "Error, TEXT\n");
815            break;
816        case XML_CDATA_SECTION_NODE:
817            fprintf(output, "Error, CDATA_SECTION\n");
818            break;
819        case XML_ENTITY_REF_NODE:
820            fprintf(output, "Error, ENTITY_REF\n");
821            break;
822        case XML_ENTITY_NODE:
823            fprintf(output, "Error, ENTITY\n");
824            break;
825        case XML_PI_NODE:
826            fprintf(output, "Error, PI\n");
827            break;
828        case XML_COMMENT_NODE:
829            fprintf(output, "Error, COMMENT\n");
830            break;
831        case XML_DOCUMENT_NODE:
832            fprintf(output, "DOCUMENT\n");
833            break;
834        case XML_HTML_DOCUMENT_NODE:
835            fprintf(output, "HTML DOCUMENT\n");
836            break;
837        case XML_DOCUMENT_TYPE_NODE:
838            fprintf(output, "Error, DOCUMENT_TYPE\n");
839            break;
840        case XML_DOCUMENT_FRAG_NODE:
841            fprintf(output, "Error, DOCUMENT_FRAG\n");
842            break;
843        case XML_NOTATION_NODE:
844            fprintf(output, "Error, NOTATION\n");
845            break;
846        default:
847            fprintf(output, "NODE_%d\n", doc->type);
848    }
849    if (doc->name != NULL) {
850        fprintf(output, "name=");
851        xmlDebugDumpString(output, BAD_CAST doc->name);
852        fprintf(output, "\n");
853    }
854    if (doc->version != NULL) {
855        fprintf(output, "version=");
856        xmlDebugDumpString(output, doc->version);
857        fprintf(output, "\n");
858    }
859    if (doc->encoding != NULL) {
860        fprintf(output, "encoding=");
861        xmlDebugDumpString(output, doc->encoding);
862        fprintf(output, "\n");
863    }
864    if (doc->URL != NULL) {
865        fprintf(output, "URL=");
866        xmlDebugDumpString(output, doc->URL);
867        fprintf(output, "\n");
868    }
869    if (doc->standalone)
870        fprintf(output, "standalone=true\n");
871    if (doc->oldNs != NULL)
872        xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
873}
874
875/**
876 * xmlDebugDumpDocument:
877 * @output:  the FILE * for the output
878 * @doc:  the document
879 *
880 * Dumps debug information for the document, it's recursive
881 */
882void
883xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
884{
885    if (output == NULL)
886        output = stdout;
887    if (doc == NULL) {
888        fprintf(output, "DOCUMENT == NULL !\n");
889        return;
890    }
891    xmlDebugDumpDocumentHead(output, doc);
892    if (((doc->type == XML_DOCUMENT_NODE) ||
893         (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
894        xmlDebugDumpNodeList(output, doc->children, 1);
895}
896
897/**
898 * xmlDebugDumpDTD:
899 * @output:  the FILE * for the output
900 * @dtd:  the DTD
901 *
902 * Dumps debug information for the DTD
903 */
904void
905xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
906{
907    if (output == NULL)
908        output = stdout;
909    if (dtd == NULL) {
910        fprintf(output, "DTD is NULL\n");
911        return;
912    }
913    if (dtd->type != XML_DTD_NODE) {
914        fprintf(output, "PBM: not a DTD\n");
915        return;
916    }
917    if (dtd->name != NULL)
918        fprintf(output, "DTD(%s)", dtd->name);
919    else
920        fprintf(output, "DTD");
921    if (dtd->ExternalID != NULL)
922        fprintf(output, ", PUBLIC %s", dtd->ExternalID);
923    if (dtd->SystemID != NULL)
924        fprintf(output, ", SYSTEM %s", dtd->SystemID);
925    fprintf(output, "\n");
926    /*
927     * Do a bit of checking
928     */
929    if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
930        fprintf(output, "PBM: DTD doc differs from parent's one\n");
931    if (dtd->prev == NULL) {
932        if ((dtd->parent != NULL)
933            && (dtd->parent->children != (xmlNodePtr) dtd))
934            fprintf(output,
935                    "PBM: DTD has no prev and not first of list\n");
936    } else {
937        if (dtd->prev->next != (xmlNodePtr) dtd)
938            fprintf(output, "PBM: DTD prev->next : back link wrong\n");
939    }
940    if (dtd->next == NULL) {
941        if ((dtd->parent != NULL)
942            && (dtd->parent->last != (xmlNodePtr) dtd))
943            fprintf(output, "PBM: DTD has no next and not last of list\n");
944    } else {
945        if (dtd->next->prev != (xmlNodePtr) dtd)
946            fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
947    }
948    if (dtd->children == NULL)
949        fprintf(output, "    DTD is empty\n");
950    else
951        xmlDebugDumpNodeList(output, dtd->children, 1);
952}
953
954static void
955xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
956    if (cur == NULL) {
957        fprintf(output, "Entity is NULL");
958        return;
959    }
960    fprintf(output, "%s : ", cur->name);
961    switch (cur->etype) {
962        case XML_INTERNAL_GENERAL_ENTITY:
963            fprintf(output, "INTERNAL GENERAL, ");
964            break;
965        case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
966            fprintf(output, "EXTERNAL PARSED, ");
967            break;
968        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
969            fprintf(output, "EXTERNAL UNPARSED, ");
970            break;
971        case XML_INTERNAL_PARAMETER_ENTITY:
972            fprintf(output, "INTERNAL PARAMETER, ");
973            break;
974        case XML_EXTERNAL_PARAMETER_ENTITY:
975            fprintf(output, "EXTERNAL PARAMETER, ");
976            break;
977        default:
978            fprintf(output, "UNKNOWN TYPE %d",
979                    cur->etype);
980    }
981    if (cur->ExternalID != NULL)
982        fprintf(output, "ID \"%s\"", cur->ExternalID);
983    if (cur->SystemID != NULL)
984        fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
985    if (cur->orig != NULL)
986        fprintf(output, "\n orig \"%s\"", cur->orig);
987    if ((cur->type != XML_ELEMENT_NODE) &&
988        (cur->content != NULL))
989        fprintf(output, "\n content \"%s\"", cur->content);
990    fprintf(output, "\n");     
991}
992
993/**
994 * xmlDebugDumpEntities:
995 * @output:  the FILE * for the output
996 * @doc:  the document
997 *
998 * Dumps debug information for all the entities in use by the document
999 */
1000void
1001xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1002{
1003    if (output == NULL)
1004        output = stdout;
1005    if (doc == NULL) {
1006        fprintf(output, "DOCUMENT == NULL !\n");
1007        return;
1008    }
1009
1010    switch (doc->type) {
1011        case XML_ELEMENT_NODE:
1012            fprintf(output, "Error, ELEMENT found here ");
1013            break;
1014        case XML_ATTRIBUTE_NODE:
1015            fprintf(output, "Error, ATTRIBUTE found here\n");
1016            break;
1017        case XML_TEXT_NODE:
1018            fprintf(output, "Error, TEXT\n");
1019            break;
1020        case XML_CDATA_SECTION_NODE:
1021            fprintf(output, "Error, CDATA_SECTION\n");
1022            break;
1023        case XML_ENTITY_REF_NODE:
1024            fprintf(output, "Error, ENTITY_REF\n");
1025            break;
1026        case XML_ENTITY_NODE:
1027            fprintf(output, "Error, ENTITY\n");
1028            break;
1029        case XML_PI_NODE:
1030            fprintf(output, "Error, PI\n");
1031            break;
1032        case XML_COMMENT_NODE:
1033            fprintf(output, "Error, COMMENT\n");
1034            break;
1035        case XML_DOCUMENT_NODE:
1036            fprintf(output, "DOCUMENT\n");
1037            break;
1038        case XML_HTML_DOCUMENT_NODE:
1039            fprintf(output, "HTML DOCUMENT\n");
1040            break;
1041        case XML_DOCUMENT_TYPE_NODE:
1042            fprintf(output, "Error, DOCUMENT_TYPE\n");
1043            break;
1044        case XML_DOCUMENT_FRAG_NODE:
1045            fprintf(output, "Error, DOCUMENT_FRAG\n");
1046            break;
1047        case XML_NOTATION_NODE:
1048            fprintf(output, "Error, NOTATION\n");
1049            break;
1050        default:
1051            fprintf(output, "NODE_%d\n", doc->type);
1052    }
1053    if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1054        xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1055            doc->intSubset->entities;
1056
1057        fprintf(output, "Entities in internal subset\n");
1058        xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1059                    output);
1060    } else
1061        fprintf(output, "No entities in internal subset\n");
1062    if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1063        xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1064            doc->extSubset->entities;
1065
1066        fprintf(output, "Entities in external subset\n");
1067        xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1068                    output);
1069    } else
1070        fprintf(output, "No entities in external subset\n");
1071}
1072
1073/**
1074 * xmlLsCountNode:
1075 * @node:  the node to count
1076 *
1077 * Count the children of @node.
1078 *
1079 * Returns the number of children of @node.
1080 */
1081int
1082xmlLsCountNode(xmlNodePtr node) {
1083    int ret = 0;
1084    xmlNodePtr list = NULL;
1085   
1086    if (node == NULL)
1087        return(0);
1088
1089    switch (node->type) {
1090        case XML_ELEMENT_NODE:
1091            list = node->children;
1092            break;
1093        case XML_DOCUMENT_NODE:
1094        case XML_HTML_DOCUMENT_NODE:
1095#ifdef LIBXML_DOCB_ENABLED
1096        case XML_DOCB_DOCUMENT_NODE:
1097#endif
1098            list = ((xmlDocPtr) node)->children;
1099            break;
1100        case XML_ATTRIBUTE_NODE:
1101            list = ((xmlAttrPtr) node)->children;
1102            break;
1103        case XML_TEXT_NODE:
1104        case XML_CDATA_SECTION_NODE:
1105        case XML_PI_NODE:
1106        case XML_COMMENT_NODE:
1107            if (node->content != NULL) {
1108#ifndef XML_USE_BUFFER_CONTENT     
1109                ret = xmlStrlen(node->content);
1110#else
1111                ret = xmlBufferLength(node->content);
1112#endif
1113            }
1114            break;
1115        case XML_ENTITY_REF_NODE:
1116        case XML_DOCUMENT_TYPE_NODE:
1117        case XML_ENTITY_NODE:
1118        case XML_DOCUMENT_FRAG_NODE:
1119        case XML_NOTATION_NODE:
1120        case XML_DTD_NODE:
1121        case XML_ELEMENT_DECL:
1122        case XML_ATTRIBUTE_DECL:
1123        case XML_ENTITY_DECL:
1124        case XML_NAMESPACE_DECL:
1125        case XML_XINCLUDE_START:
1126        case XML_XINCLUDE_END:
1127            ret = 1;
1128            break;
1129    }
1130    for (;list != NULL;ret++)
1131        list = list->next;
1132    return(ret);
1133}
1134
1135/**
1136 * xmlLsOneNode:
1137 * @output:  the FILE * for the output
1138 * @node:  the node to dump
1139 *
1140 * Dump to @output the type and name of @node.
1141 */
1142void
1143xmlLsOneNode(FILE *output, xmlNodePtr node) {
1144    if (node == NULL) {
1145        fprintf(output, "NULL\n");
1146        return;
1147    }
1148    switch (node->type) {
1149        case XML_ELEMENT_NODE:
1150            fprintf(output, "-");
1151            break;
1152        case XML_ATTRIBUTE_NODE:
1153            fprintf(output, "a");
1154            break;
1155        case XML_TEXT_NODE:
1156            fprintf(output, "t");
1157            break;
1158        case XML_CDATA_SECTION_NODE:
1159            fprintf(output, "c");
1160            break;
1161        case XML_ENTITY_REF_NODE:
1162            fprintf(output, "e");
1163            break;
1164        case XML_ENTITY_NODE:
1165            fprintf(output, "E");
1166            break;
1167        case XML_PI_NODE:
1168            fprintf(output, "p");
1169            break;
1170        case XML_COMMENT_NODE:
1171            fprintf(output, "c");
1172            break;
1173        case XML_DOCUMENT_NODE:
1174            fprintf(output, "d");
1175            break;
1176        case XML_HTML_DOCUMENT_NODE:
1177            fprintf(output, "h");
1178            break;
1179        case XML_DOCUMENT_TYPE_NODE:
1180            fprintf(output, "T");
1181            break;
1182        case XML_DOCUMENT_FRAG_NODE:
1183            fprintf(output, "F");
1184            break;
1185        case XML_NOTATION_NODE:
1186            fprintf(output, "N");
1187            break;
1188        case XML_NAMESPACE_DECL:
1189            fprintf(output, "n");
1190            break;
1191        default:
1192            fprintf(output, "?");
1193    }
1194    if (node->type != XML_NAMESPACE_DECL) {
1195        if (node->properties != NULL)
1196            fprintf(output, "a");
1197        else   
1198            fprintf(output, "-");
1199        if (node->nsDef != NULL)
1200            fprintf(output, "n");
1201        else   
1202            fprintf(output, "-");
1203    }
1204
1205    fprintf(output, " %8d ", xmlLsCountNode(node));
1206
1207    switch (node->type) {
1208        case XML_ELEMENT_NODE:
1209            if (node->name != NULL)
1210                fprintf(output, "%s", node->name);
1211            break;
1212        case XML_ATTRIBUTE_NODE:
1213            if (node->name != NULL)
1214                fprintf(output, "%s", node->name);
1215            break;
1216        case XML_TEXT_NODE:
1217            if (node->content != NULL) {
1218#ifndef XML_USE_BUFFER_CONTENT     
1219                xmlDebugDumpString(output, node->content);
1220#else
1221                xmlDebugDumpString(output, xmlBufferContent(node->content));
1222#endif
1223            }
1224            break;
1225        case XML_CDATA_SECTION_NODE:
1226            break;
1227        case XML_ENTITY_REF_NODE:
1228            if (node->name != NULL)
1229                fprintf(output, "%s", node->name);
1230            break;
1231        case XML_ENTITY_NODE:
1232            if (node->name != NULL)
1233                fprintf(output, "%s", node->name);
1234            break;
1235        case XML_PI_NODE:
1236            if (node->name != NULL)
1237                fprintf(output, "%s", node->name);
1238            break;
1239        case XML_COMMENT_NODE:
1240            break;
1241        case XML_DOCUMENT_NODE:
1242            break;
1243        case XML_HTML_DOCUMENT_NODE:
1244            break;
1245        case XML_DOCUMENT_TYPE_NODE:
1246            break;
1247        case XML_DOCUMENT_FRAG_NODE:
1248            break;
1249        case XML_NOTATION_NODE:
1250            break;
1251        case XML_NAMESPACE_DECL: {
1252            xmlNsPtr ns = (xmlNsPtr) node;
1253
1254            if (ns->prefix == NULL)
1255                fprintf(output, "default -> %s", ns->href);
1256            else
1257                fprintf(output, "%s -> %s", ns->prefix, ns->href);
1258            break;
1259        }
1260        default:
1261            if (node->name != NULL)
1262                fprintf(output, "%s", node->name);
1263    }
1264    fprintf(output, "\n");
1265}
1266
1267/**
1268 * xmlBoolToText:
1269 * @boolval: a bool to turn into text
1270 *
1271 * Convenient way to turn bool into text
1272 *
1273 * Returns a pointer to either "True" or "False"
1274 */
1275const char *
1276xmlBoolToText(int boolval)
1277{
1278    if (boolval)
1279        return("True");
1280    else
1281        return("False");
1282}
1283
1284/****************************************************************
1285 *                                                              *
1286 *              The XML shell related functions                 *
1287 *                                                              *
1288 ****************************************************************/
1289
1290
1291
1292/*
1293 * TODO: Improvement/cleanups for the XML shell
1294 *     - allow to shell out an editor on a subpart
1295 *     - cleanup function registrations (with help) and calling
1296 *     - provide registration routines
1297 */
1298
1299/**
1300 * xmlShellPrintXPathError:
1301 * @errorType: valid xpath error id
1302 * @arg: the argument that cause xpath to fail
1303 *
1304 * Print the xpath error to libxml default error channel
1305 */
1306void
1307xmlShellPrintXPathError(int errorType, const char *arg)
1308{
1309    const char *default_arg = "Result";
1310
1311    if (!arg)
1312        arg = default_arg;
1313
1314    switch (errorType) {
1315        case XPATH_UNDEFINED:
1316            xmlGenericError(xmlGenericErrorContext,
1317                            "%s: no such node\n", arg);
1318            break;
1319
1320        case XPATH_BOOLEAN:
1321            xmlGenericError(xmlGenericErrorContext,
1322                            "%s is a Boolean\n", arg);
1323            break;
1324        case XPATH_NUMBER:
1325            xmlGenericError(xmlGenericErrorContext,
1326                            "%s is a number\n", arg);
1327            break;
1328        case XPATH_STRING:
1329            xmlGenericError(xmlGenericErrorContext,
1330                            "%s is a string\n", arg);
1331            break;
1332        case XPATH_POINT:
1333            xmlGenericError(xmlGenericErrorContext,
1334                            "%s is a point\n", arg);
1335            break;
1336        case XPATH_RANGE:
1337            xmlGenericError(xmlGenericErrorContext,
1338                            "%s is a range\n", arg);
1339            break;
1340        case XPATH_LOCATIONSET:
1341            xmlGenericError(xmlGenericErrorContext,
1342                            "%s is a range\n", arg);
1343            break;
1344        case XPATH_USERS:
1345            xmlGenericError(xmlGenericErrorContext,
1346                            "%s is user-defined\n", arg);
1347            break;
1348        case XPATH_XSLT_TREE:
1349            xmlGenericError(xmlGenericErrorContext,
1350                            "%s is an XSLT value tree\n", arg);
1351            break;
1352    }
1353    xmlGenericError(xmlGenericErrorContext,
1354                    "Try casting the result string function (xpath builtin)\n",
1355                    arg);
1356}
1357
1358
1359/**
1360 * xmlShellPrintNode:
1361 * @node : a non-null node to print to stdout
1362 *
1363 * Print node to stdout
1364 */
1365void
1366xmlShellPrintNode(xmlNodePtr node)
1367{
1368    if (!node)
1369        return;
1370
1371    if (node->type == XML_DOCUMENT_NODE)
1372        xmlDocDump(stdout, (xmlDocPtr) node);
1373    else if (node->type == XML_ATTRIBUTE_NODE)
1374        xmlDebugDumpAttrList(stdout, (xmlAttrPtr) node, 0);
1375    else
1376        xmlElemDump(stdout, node->doc, node);
1377
1378    fprintf(stdout, "\n");
1379}
1380
1381
1382/**
1383 * xmlShellPrintXPathResult:
1384 * @list: a valid result generated by an xpath evaluation
1385 *
1386 * Prints result to stdout
1387 */
1388void
1389xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1390{
1391    int i = 0;
1392
1393    if (list != NULL) {
1394        switch (list->type) {
1395            case XPATH_NODESET:{
1396                    int indx;
1397
1398                    if (list->nodesetval) {
1399                        for (indx = 0; indx < list->nodesetval->nodeNr;
1400                             indx++) {
1401                            if (i > 0)
1402                                fprintf(stderr, " -------\n");
1403                            xmlShellPrintNode(list->nodesetval->
1404                                              nodeTab[indx]);
1405                        }
1406                    } else {
1407                        xmlGenericError(xmlGenericErrorContext,
1408                                        "Empty node set\n");
1409                    }
1410                    break;
1411                }
1412            case XPATH_BOOLEAN:
1413                xmlGenericError(xmlGenericErrorContext,
1414                                "Is a Boolean:%s\n",
1415                                xmlBoolToText(list->boolval));
1416                break;
1417            case XPATH_NUMBER:
1418                xmlGenericError(xmlGenericErrorContext,
1419                                "Is a number:%0g\n", list->floatval);
1420                break;
1421            case XPATH_STRING:
1422                xmlGenericError(xmlGenericErrorContext,
1423                                "Is a string:%s\n", list->stringval);
1424                break;
1425
1426            default:
1427                xmlShellPrintXPathError(list->type, NULL);
1428        }
1429    }
1430}
1431
1432/**
1433 * xmlShellList:
1434 * @ctxt:  the shell context
1435 * @arg:  unused
1436 * @node:  a node
1437 * @node2:  unused
1438 *
1439 * Implements the XML shell function "ls"
1440 * Does an Unix like listing of the given node (like a directory)
1441 *
1442 * Returns 0
1443 */
1444int
1445xmlShellList(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1446             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1447             xmlNodePtr node2 ATTRIBUTE_UNUSED)
1448{
1449    xmlNodePtr cur;
1450    if (node == NULL) {
1451        fprintf(stdout, "NULL\n");
1452        return (0);
1453    }
1454    if ((node->type == XML_DOCUMENT_NODE) ||
1455        (node->type == XML_HTML_DOCUMENT_NODE)) {
1456        cur = ((xmlDocPtr) node)->children;
1457    } else if (node->type == XML_NAMESPACE_DECL) {
1458        xmlLsOneNode(stdout, node);
1459        return (0);
1460    } else if (node->children != NULL) {
1461        cur = node->children;
1462    } else {
1463        xmlLsOneNode(stdout, node);
1464        return (0);
1465    }
1466    while (cur != NULL) {
1467        xmlLsOneNode(stdout, cur);
1468        cur = cur->next;
1469    }
1470    return (0);
1471}
1472
1473/**
1474 * xmlShellBase:
1475 * @ctxt:  the shell context
1476 * @arg:  unused
1477 * @node:  a node
1478 * @node2:  unused
1479 *
1480 * Implements the XML shell function "base"
1481 * dumps the current XML base of the node
1482 *
1483 * Returns 0
1484 */
1485int
1486xmlShellBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1487             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1488             xmlNodePtr node2 ATTRIBUTE_UNUSED)
1489{
1490    xmlChar *base;
1491    if (node == NULL) {
1492        fprintf(stdout, "NULL\n");
1493        return (0);
1494    }   
1495
1496    base = xmlNodeGetBase(node->doc, node);
1497
1498    if (base == NULL) {
1499        fprintf(stdout, " No base found !!!\n");
1500    } else {
1501        fprintf(stdout, "%s\n", base);
1502        xmlFree(base);
1503    }
1504    return (0);
1505}
1506
1507/**
1508 * xmlShellSetBase:
1509 * @ctxt:  the shell context
1510 * @arg:  the new base
1511 * @node:  a node
1512 * @node2:  unused
1513 *
1514 * Implements the XML shell function "setbase"
1515 * change the current XML base of the node
1516 *
1517 * Returns 0
1518 */
1519static int
1520xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1521             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1522             xmlNodePtr node2 ATTRIBUTE_UNUSED)
1523{
1524    xmlNodeSetBase(node, (xmlChar*) arg);
1525    return (0);
1526}
1527
1528/**
1529 * xmlShellDir:
1530 * @ctxt:  the shell context
1531 * @arg:  unused
1532 * @node:  a node
1533 * @node2:  unused
1534 *
1535 * Implements the XML shell function "dir"
1536 * dumps informations about the node (namespace, attributes, content).
1537 *
1538 * Returns 0
1539 */
1540int
1541xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1542            char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1543            xmlNodePtr node2 ATTRIBUTE_UNUSED)
1544{
1545    if (node == NULL) {
1546        fprintf(stdout, "NULL\n");
1547        return (0);
1548    }   
1549    if ((node->type == XML_DOCUMENT_NODE) ||
1550        (node->type == XML_HTML_DOCUMENT_NODE)) {
1551        xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
1552    } else if (node->type == XML_ATTRIBUTE_NODE) {
1553        xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
1554    } else {
1555        xmlDebugDumpOneNode(stdout, node, 0);
1556    }
1557    return (0);
1558}
1559
1560/**
1561 * xmlShellCat:
1562 * @ctxt:  the shell context
1563 * @arg:  unused
1564 * @node:  a node
1565 * @node2:  unused
1566 *
1567 * Implements the XML shell function "cat"
1568 * dumps the serialization node content (XML or HTML).
1569 *
1570 * Returns 0
1571 */
1572int
1573xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1574            xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1575{
1576    if (node == NULL) {
1577        fprintf(stdout, "NULL\n");
1578        return (0);
1579    }   
1580    if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1581#ifdef LIBXML_HTML_ENABLED
1582        if (node->type == XML_HTML_DOCUMENT_NODE)
1583            htmlDocDump(stdout, (htmlDocPtr) node);
1584        else
1585            htmlNodeDumpFile(stdout, ctxt->doc, node);
1586#else
1587        if (node->type == XML_DOCUMENT_NODE)
1588            xmlDocDump(stdout, (xmlDocPtr) node);
1589        else
1590            xmlElemDump(stdout, ctxt->doc, node);
1591#endif /* LIBXML_HTML_ENABLED */
1592    } else {
1593        if (node->type == XML_DOCUMENT_NODE)
1594            xmlDocDump(stdout, (xmlDocPtr) node);
1595        else
1596            xmlElemDump(stdout, ctxt->doc, node);
1597    }
1598    fprintf(stdout, "\n");
1599    return (0);
1600}
1601
1602/**
1603 * xmlShellLoad:
1604 * @ctxt:  the shell context
1605 * @filename:  the file name
1606 * @node:  unused
1607 * @node2:  unused
1608 *
1609 * Implements the XML shell function "load"
1610 * loads a new document specified by the filename
1611 *
1612 * Returns 0 or -1 if loading failed
1613 */
1614int
1615xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1616             xmlNodePtr node ATTRIBUTE_UNUSED,
1617             xmlNodePtr node2 ATTRIBUTE_UNUSED)
1618{
1619    xmlDocPtr doc;
1620    int html = 0;
1621
1622    if (ctxt->doc != NULL)
1623        html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
1624
1625    if (html) {
1626#ifdef LIBXML_HTML_ENABLED
1627        doc = htmlParseFile(filename, NULL);
1628#else
1629        fprintf(stdout, "HTML support not compiled in\n");
1630        doc = NULL;
1631#endif /* LIBXML_HTML_ENABLED */
1632    } else {
1633        doc = xmlParseFile(filename);
1634    }
1635    if (doc != NULL) {
1636        if (ctxt->loaded == 1) {
1637            xmlFreeDoc(ctxt->doc);
1638        }
1639        ctxt->loaded = 1;
1640#ifdef LIBXML_XPATH_ENABLED
1641        xmlXPathFreeContext(ctxt->pctxt);
1642#endif /* LIBXML_XPATH_ENABLED */
1643        xmlFree(ctxt->filename);
1644        ctxt->doc = doc;
1645        ctxt->node = (xmlNodePtr) doc;
1646#ifdef LIBXML_XPATH_ENABLED
1647        ctxt->pctxt = xmlXPathNewContext(doc);
1648#endif /* LIBXML_XPATH_ENABLED */
1649        ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1650    } else
1651        return (-1);
1652    return (0);
1653}
1654
1655/**
1656 * xmlShellWrite:
1657 * @ctxt:  the shell context
1658 * @filename:  the file name
1659 * @node:  a node in the tree
1660 * @node2:  unused
1661 *
1662 * Implements the XML shell function "write"
1663 * Write the current node to the filename, it saves the serialization
1664 * of the subtree under the @node specified
1665 *
1666 * Returns 0 or -1 in case of error
1667 */
1668int
1669xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1670              xmlNodePtr node2 ATTRIBUTE_UNUSED)
1671{
1672    if (node == NULL)
1673        return (-1);
1674    if ((filename == NULL) || (filename[0] == 0)) {
1675        xmlGenericError(xmlGenericErrorContext,
1676                        "Write command requires a filename argument\n");
1677        return (-1);
1678    }
1679#ifdef W_OK
1680    if (access((char *) filename, W_OK)) {
1681        xmlGenericError(xmlGenericErrorContext,
1682                        "Cannot write to %s\n", filename);
1683        return (-1);
1684    }
1685#endif
1686    switch (node->type) {
1687        case XML_DOCUMENT_NODE:
1688            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1689                xmlGenericError(xmlGenericErrorContext,
1690                                "Failed to write to %s\n", filename);
1691                return (-1);
1692            }
1693            break;
1694        case XML_HTML_DOCUMENT_NODE:
1695#ifdef LIBXML_HTML_ENABLED
1696            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1697                xmlGenericError(xmlGenericErrorContext,
1698                                "Failed to write to %s\n", filename);
1699                return (-1);
1700            }
1701#else
1702            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1703                xmlGenericError(xmlGenericErrorContext,
1704                                "Failed to write to %s\n", filename);
1705                return (-1);
1706            }
1707#endif /* LIBXML_HTML_ENABLED */
1708            break;
1709        default:{
1710                FILE *f;
1711
1712                f = fopen((char *) filename, "w");
1713                if (f == NULL) {
1714                    xmlGenericError(xmlGenericErrorContext,
1715                                    "Failed to write to %s\n", filename);
1716                    return (-1);
1717                }
1718                xmlElemDump(f, ctxt->doc, node);
1719                fclose(f);
1720            }
1721    }
1722    return (0);
1723}
1724
1725/**
1726 * xmlShellSave:
1727 * @ctxt:  the shell context
1728 * @filename:  the file name (optional)
1729 * @node:  unused
1730 * @node2:  unused
1731 *
1732 * Implements the XML shell function "save"
1733 * Write the current document to the filename, or it's original name
1734 *
1735 * Returns 0 or -1 in case of error
1736 */
1737int
1738xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1739             xmlNodePtr node ATTRIBUTE_UNUSED,
1740             xmlNodePtr node2 ATTRIBUTE_UNUSED)
1741{
1742    if (ctxt->doc == NULL)
1743        return (-1);
1744    if ((filename == NULL) || (filename[0] == 0))
1745        filename = ctxt->filename;
1746#ifdef W_OK
1747    if (access((char *) filename, W_OK)) {
1748        xmlGenericError(xmlGenericErrorContext,
1749                        "Cannot save to %s\n", filename);
1750        return (-1);
1751    }
1752#endif
1753    switch (ctxt->doc->type) {
1754        case XML_DOCUMENT_NODE:
1755            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1756                xmlGenericError(xmlGenericErrorContext,
1757                                "Failed to save to %s\n", filename);
1758            }
1759            break;
1760        case XML_HTML_DOCUMENT_NODE:
1761#ifdef LIBXML_HTML_ENABLED
1762            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1763                xmlGenericError(xmlGenericErrorContext,
1764                                "Failed to save to %s\n", filename);
1765            }
1766#else
1767            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1768                xmlGenericError(xmlGenericErrorContext,
1769                                "Failed to save to %s\n", filename);
1770            }
1771#endif /* LIBXML_HTML_ENABLED */
1772            break;
1773        default:
1774            xmlGenericError(xmlGenericErrorContext,
1775            "To save to subparts of a document use the 'write' command\n");
1776            return (-1);
1777
1778    }
1779    return (0);
1780}
1781
1782/**
1783 * xmlShellValidate:
1784 * @ctxt:  the shell context
1785 * @dtd:  the DTD URI (optional)
1786 * @node:  unused
1787 * @node2:  unused
1788 *
1789 * Implements the XML shell function "validate"
1790 * Validate the document, if a DTD path is provided, then the validation
1791 * is done against the given DTD.
1792 *
1793 * Returns 0 or -1 in case of error
1794 */
1795int
1796xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1797                 xmlNodePtr node ATTRIBUTE_UNUSED,
1798                 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1799{
1800    xmlValidCtxt vctxt;
1801    int res = -1;
1802
1803    vctxt.userData = stderr;
1804    vctxt.error = (xmlValidityErrorFunc) fprintf;
1805    vctxt.warning = (xmlValidityWarningFunc) fprintf;
1806
1807    if ((dtd == NULL) || (dtd[0] == 0)) {
1808        res = xmlValidateDocument(&vctxt, ctxt->doc);
1809    } else {
1810        xmlDtdPtr subset;
1811
1812        subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1813        if (subset != NULL) {
1814            res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1815
1816            xmlFreeDtd(subset);
1817        }
1818    }
1819    return (res);
1820}
1821
1822/**
1823 * xmlShellDu:
1824 * @ctxt:  the shell context
1825 * @arg:  unused
1826 * @tree:  a node defining a subtree
1827 * @node2:  unused
1828 *
1829 * Implements the XML shell function "du"
1830 * show the structure of the subtree under node @tree
1831 * If @tree is null, the command works on the current node.
1832 *
1833 * Returns 0 or -1 in case of error
1834 */
1835int
1836xmlShellDu(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1837           char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1838           xmlNodePtr node2 ATTRIBUTE_UNUSED)
1839{
1840    xmlNodePtr node;
1841    int indent = 0, i;
1842
1843    if (tree == NULL)
1844        return (-1);
1845    node = tree;
1846    while (node != NULL) {
1847        if ((node->type == XML_DOCUMENT_NODE) ||
1848            (node->type == XML_HTML_DOCUMENT_NODE)) {
1849            fprintf(stdout, "/\n");
1850        } else if (node->type == XML_ELEMENT_NODE) {
1851            for (i = 0; i < indent; i++)
1852                fprintf(stdout, "  ");
1853            fprintf(stdout, "%s\n", node->name);
1854        } else {
1855        }
1856
1857        /*
1858         * Browse the full subtree, deep first
1859         */
1860
1861        if ((node->type == XML_DOCUMENT_NODE) ||
1862            (node->type == XML_HTML_DOCUMENT_NODE)) {
1863            node = ((xmlDocPtr) node)->children;
1864        } else if ((node->children != NULL)
1865                   && (node->type != XML_ENTITY_REF_NODE)) {
1866            /* deep first */
1867            node = node->children;
1868            indent++;
1869        } else if ((node != tree) && (node->next != NULL)) {
1870            /* then siblings */
1871            node = node->next;
1872        } else if (node != tree) {
1873            /* go up to parents->next if needed */
1874            while (node != tree) {
1875                if (node->parent != NULL) {
1876                    node = node->parent;
1877                    indent--;
1878                }
1879                if ((node != tree) && (node->next != NULL)) {
1880                    node = node->next;
1881                    break;
1882                }
1883                if (node->parent == NULL) {
1884                    node = NULL;
1885                    break;
1886                }
1887                if (node == tree) {
1888                    node = NULL;
1889                    break;
1890                }
1891            }
1892            /* exit condition */
1893            if (node == tree)
1894                node = NULL;
1895        } else
1896            node = NULL;
1897    }
1898    return (0);
1899}
1900
1901/**
1902 * xmlShellPwd:
1903 * @ctxt:  the shell context
1904 * @buffer:  the output buffer
1905 * @node:  a node
1906 * @node2:  unused
1907 *
1908 * Implements the XML shell function "pwd"
1909 * Show the full path from the root to the node, if needed building
1910 * thumblers when similar elements exists at a given ancestor level.
1911 * The output is compatible with XPath commands.
1912 *
1913 * Returns 0 or -1 in case of error
1914 */
1915int
1916xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
1917            xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1918{
1919    xmlChar *path;
1920
1921    if (node == NULL)
1922        return (-1);
1923
1924    path = xmlGetNodePath(node);
1925    if (path == NULL)
1926        return (-1);
1927
1928    /*
1929     * This test prevents buffer overflow, because this routine
1930     * is only called by xmlShell, in which the second argument is
1931     * 500 chars long.
1932     * It is a dirty hack before a cleaner solution is found.
1933     * Documentation should mention that the second argument must
1934     * be at least 500 chars long, and could be stripped if too long.
1935     */
1936    snprintf(buffer, 499, "%s", path);
1937    buffer[499] = '0';
1938    xmlFree(path);
1939
1940    return (0);
1941}
1942
1943/**
1944 * xmlShell
1945 * @doc:  the initial document
1946 * @filename:  the output buffer
1947 * @input:  the line reading function
1948 * @output:  the output FILE*
1949 *
1950 * Implements the XML shell
1951 * This allow to load, validate, view, modify and save a document
1952 * using a environment similar to a UNIX commandline.
1953 */
1954void
1955xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
1956         FILE * output)
1957{
1958    char prompt[500] = "/ > ";
1959    char *cmdline = NULL, *cur;
1960    int nbargs;
1961    char command[100];
1962    char arg[400];
1963    int i;
1964    xmlShellCtxtPtr ctxt;
1965    xmlXPathObjectPtr list;
1966
1967    if (doc == NULL)
1968        return;
1969    if (filename == NULL)
1970        return;
1971    if (input == NULL)
1972        return;
1973    if (output == NULL)
1974        return;
1975    ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
1976    if (ctxt == NULL)
1977        return;
1978    ctxt->loaded = 0;
1979    ctxt->doc = doc;
1980    ctxt->input = input;
1981    ctxt->output = output;
1982    ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1983    ctxt->node = (xmlNodePtr) ctxt->doc;
1984
1985#ifdef LIBXML_XPATH_ENABLED
1986    ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1987    if (ctxt->pctxt == NULL) {
1988        xmlFree(ctxt);
1989        return;
1990    }
1991#endif /* LIBXML_XPATH_ENABLED */
1992    while (1) {
1993        if (ctxt->node == (xmlNodePtr) ctxt->doc)
1994            sprintf(prompt, "%s > ", "/");
1995        else if (ctxt->node->name)
1996            snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
1997        else
1998            sprintf(prompt, "? > ");
1999        prompt[sizeof(prompt) - 1] = 0;
2000
2001        /*
2002         * Get a new command line
2003         */
2004        cmdline = ctxt->input(prompt);
2005        if (cmdline == NULL)
2006            break;
2007
2008        /*
2009         * Parse the command itself
2010         */
2011        cur = cmdline;
2012        nbargs = 0;
2013        while ((*cur == ' ') || (*cur == '\t'))
2014            cur++;
2015        i = 0;
2016        while ((*cur != ' ') && (*cur != '\t') &&
2017               (*cur != '\n') && (*cur != '\r')) {
2018            if (*cur == 0)
2019                break;
2020            command[i++] = *cur++;
2021        }
2022        command[i] = 0;
2023        if (i == 0)
2024            continue;
2025        nbargs++;
2026
2027        /*
2028         * Parse the argument
2029         */
2030        while ((*cur == ' ') || (*cur == '\t'))
2031            cur++;
2032        i = 0;
2033        while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2034            if (*cur == 0)
2035                break;
2036            arg[i++] = *cur++;
2037        }
2038        arg[i] = 0;
2039        if (i != 0)
2040            nbargs++;
2041
2042        /*
2043         * start interpreting the command
2044         */
2045        if (!strcmp(command, "exit"))
2046            break;
2047        if (!strcmp(command, "quit"))
2048            break;
2049        if (!strcmp(command, "bye"))
2050            break;
2051                if (!strcmp(command, "help")) {
2052                  fprintf(stdout, "\tbase         display XML base of the node\n");
2053                  fprintf(stdout, "\tsetbase URI  change the XML base of the node\n");
2054                  fprintf(stdout, "\tbye          leave shell\n");
2055                  fprintf(stdout, "\tcat [node]   display node or current node\n");
2056                  fprintf(stdout, "\tcd [path]    change directory to path or to root\n");
2057                  fprintf(stdout, "\tdir [path]   dumps informations about the node (namespace, attributes, content)\n");
2058                  fprintf(stdout, "\tdu [path]    show the structure of the subtree under path or the current node\n");
2059                  fprintf(stdout, "\texit         leave shell\n");
2060                  fprintf(stdout, "\thelp         display this help\n");
2061                  fprintf(stdout, "\tfree         display memory usage\n");
2062                  fprintf(stdout, "\tload [name]  load a new document with name\n");
2063                  fprintf(stdout, "\tls [path]    list contents of path or the current directory\n");
2064#ifdef LIBXML_XPATH_ENABLED
2065                  fprintf(stdout, "\txpath expr   evaluate the XPath expression in that context and print the result\n");
2066#endif /* LIBXML_XPATH_ENABLED */
2067                  fprintf(stdout, "\tpwd          display current working directory\n");
2068                  fprintf(stdout, "\tquit         leave shell\n");
2069                  fprintf(stdout, "\tsave [name]  save this document to name or the original name\n");
2070                  fprintf(stdout, "\tvalidate     check the document for errors\n");
2071                  fprintf(stdout, "\twrite [name] write the current node to the filename\n");
2072        } else if (!strcmp(command, "validate")) {
2073            xmlShellValidate(ctxt, arg, NULL, NULL);
2074        } else if (!strcmp(command, "load")) {
2075            xmlShellLoad(ctxt, arg, NULL, NULL);
2076        } else if (!strcmp(command, "save")) {
2077            xmlShellSave(ctxt, arg, NULL, NULL);
2078        } else if (!strcmp(command, "write")) {
2079            xmlShellWrite(ctxt, arg, NULL, NULL);
2080        } else if (!strcmp(command, "free")) {
2081            if (arg[0] == 0) {
2082                xmlMemShow(stdout, 0);
2083            } else {
2084                int len = 0;
2085
2086                sscanf(arg, "%d", &len);
2087                xmlMemShow(stdout, len);
2088            }
2089        } else if (!strcmp(command, "pwd")) {
2090            char dir[500];
2091
2092            if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
2093                fprintf(stdout, "%s\n", dir);
2094        } else if (!strcmp(command, "du")) {
2095            xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2096        } else if (!strcmp(command, "base")) {
2097            xmlShellBase(ctxt, NULL, ctxt->node, NULL);
2098#ifdef LIBXML_XPATH_ENABLED
2099        } else if (!strcmp(command, "xpath")) {
2100            if (arg[0] == 0) {
2101                xmlGenericError(xmlGenericErrorContext,
2102                                "xpath: expression required\n");
2103            } else {
2104                ctxt->pctxt->node = ctxt->node;
2105                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2106                xmlXPathDebugDumpObject(stdout, list, 0);
2107                xmlXPathFreeObject(list);
2108            }
2109#endif /* LIBXML_XPATH_ENABLED */
2110        } else if (!strcmp(command, "setbase")) {
2111            xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
2112        } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2113            int dir = (!strcmp(command, "dir"));
2114
2115            if (arg[0] == 0) {
2116                if (dir)
2117                    xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2118                else
2119                    xmlShellList(ctxt, NULL, ctxt->node, NULL);
2120            } else {
2121                ctxt->pctxt->node = ctxt->node;
2122#ifdef LIBXML_XPATH_ENABLED
2123                ctxt->pctxt->node = ctxt->node;
2124                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2125#else
2126                list = NULL;
2127#endif /* LIBXML_XPATH_ENABLED */
2128                if (list != NULL) {
2129                    switch (list->type) {
2130                        case XPATH_UNDEFINED:
2131                            xmlGenericError(xmlGenericErrorContext,
2132                                            "%s: no such node\n", arg);
2133                            break;
2134                        case XPATH_NODESET:{
2135                                int indx;
2136
2137                                if (list->nodesetval == NULL)
2138                                    break;
2139
2140                                for (indx = 0;
2141                                     indx < list->nodesetval->nodeNr;
2142                                     indx++) {
2143                                    if (dir)
2144                                        xmlShellDir(ctxt, NULL,
2145                                                    list->nodesetval->
2146                                                    nodeTab[indx], NULL);
2147                                    else
2148                                        xmlShellList(ctxt, NULL,
2149                                                     list->nodesetval->
2150                                                     nodeTab[indx], NULL);
2151                                }
2152                                break;
2153                            }
2154                        case XPATH_BOOLEAN:
2155                            xmlGenericError(xmlGenericErrorContext,
2156                                            "%s is a Boolean\n", arg);
2157                            break;
2158                        case XPATH_NUMBER:
2159                            xmlGenericError(xmlGenericErrorContext,
2160                                            "%s is a number\n", arg);
2161                            break;
2162                        case XPATH_STRING:
2163                            xmlGenericError(xmlGenericErrorContext,
2164                                            "%s is a string\n", arg);
2165                            break;
2166                        case XPATH_POINT:
2167                            xmlGenericError(xmlGenericErrorContext,
2168                                            "%s is a point\n", arg);
2169                            break;
2170                        case XPATH_RANGE:
2171                            xmlGenericError(xmlGenericErrorContext,
2172                                            "%s is a range\n", arg);
2173                            break;
2174                        case XPATH_LOCATIONSET:
2175                            xmlGenericError(xmlGenericErrorContext,
2176                                            "%s is a range\n", arg);
2177                            break;
2178                        case XPATH_USERS:
2179                            xmlGenericError(xmlGenericErrorContext,
2180                                            "%s is user-defined\n", arg);
2181                            break;
2182                        case XPATH_XSLT_TREE:
2183                            xmlGenericError(xmlGenericErrorContext,
2184                                            "%s is an XSLT value tree\n",
2185                                            arg);
2186                            break;
2187                    }
2188#ifdef LIBXML_XPATH_ENABLED
2189                    xmlXPathFreeObject(list);
2190#endif
2191                } else {
2192                    xmlGenericError(xmlGenericErrorContext,
2193                                    "%s: no such node\n", arg);
2194                }
2195                ctxt->pctxt->node = NULL;
2196            }
2197        } else if (!strcmp(command, "cd")) {
2198            if (arg[0] == 0) {
2199                ctxt->node = (xmlNodePtr) ctxt->doc;
2200            } else {
2201#ifdef LIBXML_XPATH_ENABLED
2202                ctxt->pctxt->node = ctxt->node;
2203                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2204#else
2205                list = NULL;
2206#endif /* LIBXML_XPATH_ENABLED */
2207                if (list != NULL) {
2208                    switch (list->type) {
2209                        case XPATH_UNDEFINED:
2210                            xmlGenericError(xmlGenericErrorContext,
2211                                            "%s: no such node\n", arg);
2212                            break;
2213                        case XPATH_NODESET:
2214                            if (list->nodesetval != NULL) {
2215                                if (list->nodesetval->nodeNr == 1) {
2216                                    ctxt->node = list->nodesetval->nodeTab[0];
2217                                } else
2218                                    xmlGenericError(xmlGenericErrorContext,
2219                                                    "%s is a %d Node Set\n",
2220                                                    arg,
2221                                                    list->nodesetval->nodeNr);
2222                            } else
2223                                xmlGenericError(xmlGenericErrorContext,
2224                                                "%s is an empty Node Set\n",
2225                                                arg);
2226                            break;
2227                        case XPATH_BOOLEAN:
2228                            xmlGenericError(xmlGenericErrorContext,
2229                                            "%s is a Boolean\n", arg);
2230                            break;
2231                        case XPATH_NUMBER:
2232                            xmlGenericError(xmlGenericErrorContext,
2233                                            "%s is a number\n", arg);
2234                            break;
2235                        case XPATH_STRING:
2236                            xmlGenericError(xmlGenericErrorContext,
2237                                            "%s is a string\n", arg);
2238                            break;
2239                        case XPATH_POINT:
2240                            xmlGenericError(xmlGenericErrorContext,
2241                                            "%s is a point\n", arg);
2242                            break;
2243                        case XPATH_RANGE:
2244                            xmlGenericError(xmlGenericErrorContext,
2245                                            "%s is a range\n", arg);
2246                            break;
2247                        case XPATH_LOCATIONSET:
2248                            xmlGenericError(xmlGenericErrorContext,
2249                                            "%s is a range\n", arg);
2250                            break;
2251                        case XPATH_USERS:
2252                            xmlGenericError(xmlGenericErrorContext,
2253                                            "%s is user-defined\n", arg);
2254                            break;
2255                        case XPATH_XSLT_TREE:
2256                            xmlGenericError(xmlGenericErrorContext,
2257                                            "%s is an XSLT value tree\n",
2258                                            arg);
2259                            break;
2260                    }
2261#ifdef LIBXML_XPATH_ENABLED
2262                    xmlXPathFreeObject(list);
2263#endif
2264                } else {
2265                    xmlGenericError(xmlGenericErrorContext,
2266                                    "%s: no such node\n", arg);
2267                }
2268                ctxt->pctxt->node = NULL;
2269            }
2270        } else if (!strcmp(command, "cat")) {
2271            if (arg[0] == 0) {
2272                xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2273            } else {
2274                ctxt->pctxt->node = ctxt->node;
2275#ifdef LIBXML_XPATH_ENABLED
2276                ctxt->pctxt->node = ctxt->node;
2277                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2278#else
2279                list = NULL;
2280#endif /* LIBXML_XPATH_ENABLED */
2281                if (list != NULL) {
2282                    switch (list->type) {
2283                        case XPATH_UNDEFINED:
2284                            xmlGenericError(xmlGenericErrorContext,
2285                                            "%s: no such node\n", arg);
2286                            break;
2287                        case XPATH_NODESET:{
2288                                int indx;
2289
2290                                if (list->nodesetval == NULL)
2291                                    break;
2292
2293                                for (indx = 0;
2294                                     indx < list->nodesetval->nodeNr;
2295                                     indx++) {
2296                                    if (i > 0)
2297                                        fprintf(stdout, " -------\n");
2298                                    xmlShellCat(ctxt, NULL,
2299                                                list->nodesetval->
2300                                                nodeTab[indx], NULL);
2301                                }
2302                                break;
2303                            }
2304                        case XPATH_BOOLEAN:
2305                            xmlGenericError(xmlGenericErrorContext,
2306                                            "%s is a Boolean\n", arg);
2307                            break;
2308                        case XPATH_NUMBER:
2309                            xmlGenericError(xmlGenericErrorContext,
2310                                            "%s is a number\n", arg);
2311                            break;
2312                        case XPATH_STRING:
2313                            xmlGenericError(xmlGenericErrorContext,
2314                                            "%s is a string\n", arg);
2315                            break;
2316                        case XPATH_POINT:
2317                            xmlGenericError(xmlGenericErrorContext,
2318                                            "%s is a point\n", arg);
2319                            break;
2320                        case XPATH_RANGE:
2321                            xmlGenericError(xmlGenericErrorContext,
2322                                            "%s is a range\n", arg);
2323                            break;
2324                        case XPATH_LOCATIONSET:
2325                            xmlGenericError(xmlGenericErrorContext,
2326                                            "%s is a range\n", arg);
2327                            break;
2328                        case XPATH_USERS:
2329                            xmlGenericError(xmlGenericErrorContext,
2330                                            "%s is user-defined\n", arg);
2331                            break;
2332                        case XPATH_XSLT_TREE:
2333                            xmlGenericError(xmlGenericErrorContext,
2334                                            "%s is an XSLT value tree\n",
2335                                            arg);
2336                            break;
2337                    }
2338#ifdef LIBXML_XPATH_ENABLED
2339                    xmlXPathFreeObject(list);
2340#endif
2341                } else {
2342                    xmlGenericError(xmlGenericErrorContext,
2343                                    "%s: no such node\n", arg);
2344                }
2345                ctxt->pctxt->node = NULL;
2346            }
2347        } else {
2348            xmlGenericError(xmlGenericErrorContext,
2349                            "Unknown command %s\n", command);
2350        }
2351        free(cmdline);          /* not xmlFree here ! */
2352    }
2353#ifdef LIBXML_XPATH_ENABLED
2354    xmlXPathFreeContext(ctxt->pctxt);
2355#endif /* LIBXML_XPATH_ENABLED */
2356    if (ctxt->loaded) {
2357        xmlFreeDoc(ctxt->doc);
2358    }
2359    if (ctxt->filename != NULL)
2360        xmlFree(ctxt->filename);
2361    xmlFree(ctxt);
2362    if (cmdline != NULL)
2363        free(cmdline);          /* not xmlFree here ! */
2364}
2365
2366#endif /* LIBXML_DEBUG_ENABLED */
Note: See TracBrowser for help on using the repository browser.