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