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