text: /*
   * xmllint.c : a small tester program for XML input.
   *
   * See Copyright for the status of this software.
   *
   * daniel@veillard.com
   */
  
  #include "libxml.h"
  
  #include <string.h>
  #include <stdarg.h>
  #include <assert.h>
  
  #if defined (_WIN32) && !defined(__CYGWIN__)
  #if defined (_MSC_VER) || defined(__BORLANDC__)
  #include <winsock2.h>
  #pragma comment(lib, "ws2_32.lib")
  #define gettimeofday(p1,p2)
  #endif /* _MSC_VER */
  #endif /* _WIN32 */
  
  #ifdef HAVE_SYS_TIME_H
  #include <sys/time.h>
  #endif
  #ifdef HAVE_TIME_H
  #include <time.h>
  #endif
  
  #ifdef __MINGW32__
  #define _WINSOCKAPI_
  #include <wsockcompat.h>
  #include <winsock2.h>
  #undef XML_SOCKLEN_T
  #define XML_SOCKLEN_T unsigned int
  #endif
  
  #ifdef HAVE_SYS_TIMEB_H
  #include <sys/timeb.h>
  #endif
  
  #ifdef HAVE_SYS_TYPES_H
  #include <sys/types.h>
  #endif
  #ifdef HAVE_SYS_STAT_H
  #include <sys/stat.h>
  #endif
  #ifdef HAVE_FCNTL_H
  #include <fcntl.h>
  #endif
  #ifdef HAVE_UNISTD_H
  #include <unistd.h>
  #endif
  #ifdef HAVE_SYS_MMAN_H
  #include <sys/mman.h>
  /* seems needed for Solaris */
  #ifndef MAP_FAILED
  #define MAP_FAILED ((void *) -1)
  #endif
  #endif
  #ifdef HAVE_STDLIB_H
  #include <stdlib.h>
  #endif
  #ifdef HAVE_LIBREADLINE
  #include <readline/readline.h>
  #ifdef HAVE_LIBHISTORY
  #include <readline/history.h>
  #endif
  #endif
  
  #include <libxml/xmlmemory.h>
  #include <libxml/parser.h>
  #include <libxml/parserInternals.h>
  #include <libxml/HTMLparser.h>
  #include <libxml/HTMLtree.h>
  #include <libxml/tree.h>
  #include <libxml/xpath.h>
  #include <libxml/debugXML.h>
  #include <libxml/xmlerror.h>
  #ifdef LIBXML_XINCLUDE_ENABLED
  #include <libxml/xinclude.h>
  #endif
  #ifdef LIBXML_CATALOG_ENABLED
  #include <libxml/catalog.h>
  #endif
  #include <libxml/globals.h>
  #include <libxml/xmlreader.h>
  #ifdef LIBXML_SCHEMATRON_ENABLED
  #include <libxml/schematron.h>
  #endif
  #ifdef LIBXML_SCHEMAS_ENABLED
  #include <libxml/relaxng.h>
  #include <libxml/xmlschemas.h>
  #endif
  #ifdef LIBXML_PATTERN_ENABLED
  #include <libxml/pattern.h>
  #endif
  #ifdef LIBXML_C14N_ENABLED
  #include <libxml/c14n.h>
  #endif
  #ifdef LIBXML_OUTPUT_ENABLED
  #include <libxml/xmlsave.h>
  #endif
  
  #ifndef XML_XML_DEFAULT_CATALOG
  #define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
  #endif
  
  typedef enum {
      XMLLINT_RETURN_OK = 0,	/* No error */
      XMLLINT_ERR_UNCLASS = 1,	/* Unclassified */
      XMLLINT_ERR_DTD = 2,	/* Error in DTD */
      XMLLINT_ERR_VALID = 3,	/* Validation error */
      XMLLINT_ERR_RDFILE = 4,	/* CtxtReadFile error */
      XMLLINT_ERR_SCHEMACOMP = 5,	/* Schema compilation */
      XMLLINT_ERR_OUT = 6,	/* Error writing output */
      XMLLINT_ERR_SCHEMAPAT = 7,	/* Error in schema pattern */
      XMLLINT_ERR_RDREGIS = 8,	/* Error in Reader registration */
      XMLLINT_ERR_MEM = 9,	/* Out of memory error */
      XMLLINT_ERR_XPATH = 10	/* XPath evaluation error */
  } xmllintReturnCode;
  #ifdef LIBXML_DEBUG_ENABLED
  static int shell = 0;
  static int debugent = 0;
  #endif
  static int debug = 0;
  static int maxmem = 0;
  #ifdef LIBXML_TREE_ENABLED
  static int copy = 0;
  #endif /* LIBXML_TREE_ENABLED */
  static int recovery = 0;
  static int noent = 0;
  static int noblanks = 0;
  static int noout = 0;
  static int nowrap = 0;
  #ifdef LIBXML_OUTPUT_ENABLED
  static int format = 0;
  static const char *output = NULL;
  static int compress = 0;
  static int oldout = 0;
  #endif /* LIBXML_OUTPUT_ENABLED */
  #ifdef LIBXML_VALID_ENABLED
  static int valid = 0;
  static int postvalid = 0;
  static char * dtdvalid = NULL;
  static char * dtdvalidfpi = NULL;
  #endif
  #ifdef LIBXML_SCHEMAS_ENABLED
  static char * relaxng = NULL;
  static xmlRelaxNGPtr relaxngschemas = NULL;
  static char * schema = NULL;
  static xmlSchemaPtr wxschemas = NULL;
  #endif
  #ifdef LIBXML_SCHEMATRON_ENABLED
  static char * schematron = NULL;
  static xmlSchematronPtr wxschematron = NULL;
  #endif
  static int repeat = 0;
  static int insert = 0;
  #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
  static int html = 0;
  static int xmlout = 0;
  #endif
  static int htmlout = 0;
  #if defined(LIBXML_HTML_ENABLED)
  static int nodefdtd = 0;
  #endif
  #ifdef LIBXML_PUSH_ENABLED
  static int push = 0;
  #endif /* LIBXML_PUSH_ENABLED */
  #ifdef HAVE_SYS_MMAN_H
  static int memory = 0;
  #endif
  static int testIO = 0;
  static char *encoding = NULL;
  #ifdef LIBXML_XINCLUDE_ENABLED
  static int xinclude = 0;
  #endif
  static int dtdattrs = 0;
  static int loaddtd = 0;
  static xmllintReturnCode progresult = XMLLINT_RETURN_OK;
  static int timing = 0;
  static int generate = 0;
  static int dropdtd = 0;
  #ifdef LIBXML_CATALOG_ENABLED
  static int catalogs = 0;
  static int nocatalogs = 0;
  #endif
  #ifdef LIBXML_C14N_ENABLED
  static int canonical = 0;
  static int canonical_11 = 0;
  static int exc_canonical = 0;
  #endif
  #ifdef LIBXML_READER_ENABLED
  static int stream = 0;
  static int walker = 0;
  #endif /* LIBXML_READER_ENABLED */
  static int chkregister = 0;
  static int nbregister = 0;
  #ifdef LIBXML_SAX1_ENABLED
  static int sax1 = 0;
  #endif /* LIBXML_SAX1_ENABLED */
  #ifdef LIBXML_PATTERN_ENABLED
  static const char *pattern = NULL;
  static xmlPatternPtr patternc = NULL;
  static xmlStreamCtxtPtr patstream = NULL;
  #endif
  #ifdef LIBXML_XPATH_ENABLED
  static const char *xpathquery = NULL;
  #endif
  static int options = XML_PARSE_COMPACT;
  static int sax = 0;
  static int oldxml10 = 0;
  
  /************************************************************************
   *									*
   *		 Entity loading control and customization.		*
   *									*
   ************************************************************************/
  #define MAX_PATHS 64
  #ifdef _WIN32
  # define PATH_SEPARATOR ';'
  #else
  # define PATH_SEPARATOR ':'
  #endif
  static xmlChar *paths[MAX_PATHS + 1];
  static int nbpaths = 0;
  static int load_trace = 0;
  
  static
  void parsePath(const xmlChar *path) {
      const xmlChar *cur;
  
      if (path == NULL)
  	return;
      while (*path != 0) {
  	if (nbpaths >= MAX_PATHS) {
  	    fprintf(stderr, "MAX_PATHS reached: too many paths\n");
  	    return;
  	}
  	cur = path;
  	while ((*cur == ' ') || (*cur == PATH_SEPARATOR))
  	    cur++;
  	path = cur;
  	while ((*cur != 0) && (*cur != ' ') && (*cur != PATH_SEPARATOR))
  	    cur++;
  	if (cur != path) {
  	    paths[nbpaths] = xmlStrndup(path, cur - path);
  	    if (paths[nbpaths] != NULL)
  		nbpaths++;
  	    path = cur;
  	}
      }
  }
  
  static xmlExternalEntityLoader defaultEntityLoader = NULL;
  
  static xmlParserInputPtr
  xmllintExternalEntityLoader(const char *URL, const char *ID,
  			     xmlParserCtxtPtr ctxt) {
      xmlParserInputPtr ret;
      warningSAXFunc warning = NULL;
      errorSAXFunc err = NULL;
  
      int i;
      const char *lastsegment = URL;
      const char *iter = URL;
  
      if ((nbpaths > 0) && (iter != NULL)) {
  	while (*iter != 0) {
  	    if (*iter == '/')
  		lastsegment = iter + 1;
  	    iter++;
  	}
      }
  
      if ((ctxt != NULL) && (ctxt->sax != NULL)) {
  	warning = ctxt->sax->warning;
  	err = ctxt->sax->error;
  	ctxt->sax->warning = NULL;
  	ctxt->sax->error = NULL;
      }
  
      if (defaultEntityLoader != NULL) {
  	ret = defaultEntityLoader(URL, ID, ctxt);
  	if (ret != NULL) {
  	    if (warning != NULL)
  		ctxt->sax->warning = warning;
  	    if (err != NULL)
  		ctxt->sax->error = err;
  	    if (load_trace) {
  		fprintf \
  			(stderr,
  			 "Loaded URL=\"%s\" ID=\"%s\"\n",
  			 URL ? URL : "(null)",
  			 ID ? ID : "(null)");
  	    }
  	    return(ret);
  	}
      }
      for (i = 0;i < nbpaths;i++) {
  	xmlChar *newURL;
  
  	newURL = xmlStrdup((const xmlChar *) paths[i]);
  	newURL = xmlStrcat(newURL, (const xmlChar *) "/");
  	newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
  	if (newURL != NULL) {
  	    ret = defaultEntityLoader((const char *)newURL, ID, ctxt);
  	    if (ret != NULL) {
  		if (warning != NULL)
  		    ctxt->sax->warning = warning;
  		if (err != NULL)
  		    ctxt->sax->error = err;
  		if (load_trace) {
  		    fprintf \
  			(stderr,
  			 "Loaded URL=\"%s\" ID=\"%s\"\n",
  			 newURL,
  			 ID ? ID : "(null)");
  		}
  		xmlFree(newURL);
  		return(ret);
  	    }
  	    xmlFree(newURL);
  	}
      }
      if (err != NULL)
          ctxt->sax->error = err;
      if (warning != NULL) {
  	ctxt->sax->warning = warning;
  	if (URL != NULL)
  	    warning(ctxt, "failed to load external entity \"%s\"\n", URL);
  	else if (ID != NULL)
  	    warning(ctxt, "failed to load external entity \"%s\"\n", ID);
      }
      return(NULL);
  }
  /************************************************************************
   *									*
   * Memory allocation consumption debugging				*
   *									*
   ************************************************************************/
  
  static void
  OOM(void)
  {
      fprintf(stderr, "Ran out of memory needs > %d bytes\n", maxmem);
      progresult = XMLLINT_ERR_MEM;
  }
  
  static void
  myFreeFunc(void *mem)
  {
      xmlMemFree(mem);
  }
  static void *
  myMallocFunc(size_t size)
  {
      void *ret;
  
      ret = xmlMemMalloc(size);
      if (ret != NULL) {
          if (xmlMemUsed() > maxmem) {
              OOM();
              xmlMemFree(ret);
              return (NULL);
          }
      }
      return (ret);
  }
  static void *
  myReallocFunc(void *mem, size_t size)
  {
      void *ret;
  
      ret = xmlMemRealloc(mem, size);
      if (ret != NULL) {
          if (xmlMemUsed() > maxmem) {
              OOM();
              xmlMemFree(ret);
              return (NULL);
          }
      }
      return (ret);
  }
  static char *
  myStrdupFunc(const char *str)
  {
      char *ret;
  
      ret = xmlMemoryStrdup(str);
      if (ret != NULL) {
          if (xmlMemUsed() > maxmem) {
              OOM();
              xmlFree(ret);
              return (NULL);
          }
      }
      return (ret);
  }
  /************************************************************************
   *									*
   * Internal timing routines to remove the necessity to have		*
   * unix-specific function calls.					*
   *									*
   ************************************************************************/
  
  #ifndef HAVE_GETTIMEOFDAY
  #ifdef HAVE_SYS_TIMEB_H
  #ifdef HAVE_SYS_TIME_H
  #ifdef HAVE_FTIME
  
  static int
  my_gettimeofday(struct timeval *tvp, void *tzp)
  {
  	struct timeb timebuffer;
  
  	ftime(&timebuffer);
  	if (tvp) {
  		tvp->tv_sec = timebuffer.time;
  		tvp->tv_usec = timebuffer.millitm * 1000L;
  	}
  	return (0);
  }
  #define HAVE_GETTIMEOFDAY 1
  #define gettimeofday my_gettimeofday
  
  #endif /* HAVE_FTIME */
  #endif /* HAVE_SYS_TIME_H */
  #endif /* HAVE_SYS_TIMEB_H */
  #endif /* !HAVE_GETTIMEOFDAY */
  
  #if defined(HAVE_GETTIMEOFDAY)
  static struct timeval begin, end;
  
  /*
   * startTimer: call where you want to start timing
   */
  static void
  startTimer(void)
  {
      gettimeofday(&begin, NULL);
  }
  
  /*
   * endTimer: call where you want to stop timing and to print out a
   *           message about the timing performed; format is a printf
   *           type argument
   */
  static void XMLCDECL
  endTimer(const char *fmt, ...)
  {
      long msec;
      va_list ap;
  
      gettimeofday(&end, NULL);
      msec = end.tv_sec - begin.tv_sec;
      msec *= 1000;
      msec += (end.tv_usec - begin.tv_usec) / 1000;
  
  #ifndef HAVE_STDARG_H
  #error "endTimer required stdarg functions"
  #endif
      va_start(ap, fmt);
      vfprintf(stderr, fmt, ap);
      va_end(ap);
  
      fprintf(stderr, " took %ld ms\n", msec);
  }
  #elif defined(HAVE_TIME_H)
  /*
   * No gettimeofday function, so we have to make do with calling clock.
   * This is obviously less accurate, but there's little we can do about
   * that.
   */
  #ifndef CLOCKS_PER_SEC
  #define CLOCKS_PER_SEC 100
  #endif
  
  static clock_t begin, end;
  static void
  startTimer(void)
  {
      begin = clock();
  }
  static void XMLCDECL
  endTimer(const char *fmt, ...)
  {
      long msec;
      va_list ap;
  
      end = clock();
      msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
  
  #ifndef HAVE_STDARG_H
  #error "endTimer required stdarg functions"
  #endif
      va_start(ap, fmt);
      vfprintf(stderr, fmt, ap);
      va_end(ap);
      fprintf(stderr, " took %ld ms\n", msec);
  }
  #else
  
  /*
   * We don't have a gettimeofday or time.h, so we just don't do timing
   */
  static void
  startTimer(void)
  {
      /*
       * Do nothing
       */
  }
  static void XMLCDECL
  endTimer(char *format, ...)
  {
      /*
       * We cannot do anything because we don't have a timing function
       */
  #ifdef HAVE_STDARG_H
      va_start(ap, format);
      vfprintf(stderr, format, ap);
      va_end(ap);
      fprintf(stderr, " was not timed\n", msec);
  #else
      /* We don't have gettimeofday, time or stdarg.h, what crazy world is
       * this ?!
       */
  #endif
  }
  #endif
  /************************************************************************
   *									*
   *			HTML ouput					*
   *									*
   ************************************************************************/
  static char buffer[50000];
  
  static void
  xmlHTMLEncodeSend(void) {
      char *result;
  
      result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
      if (result) {
  	xmlGenericError(xmlGenericErrorContext, "%s", result);
  	xmlFree(result);
      }
      buffer[0] = 0;
  }
  
  /**
   * xmlHTMLPrintFileInfo:
   * @input:  an xmlParserInputPtr input
   *
   * Displays the associated file and line informations for the current input
   */
  
  static void
  xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
      int len;
      xmlGenericError(xmlGenericErrorContext, "<p>");
  
      len = strlen(buffer);
      if (input != NULL) {
  	if (input->filename) {
  	    snprintf(&buffer[len], sizeof(buffer) - len, "%s:%d: ", input->filename,
  		    input->line);
  	} else {
  	    snprintf(&buffer[len], sizeof(buffer) - len, "Entity: line %d: ", input->line);
  	}
      }
      xmlHTMLEncodeSend();
  }
  
  /**
   * xmlHTMLPrintFileContext:
   * @input:  an xmlParserInputPtr input
   *
   * Displays current context within the input content for error tracking
   */
  
  static void
  xmlHTMLPrintFileContext(xmlParserInputPtr input) {
      const xmlChar *cur, *base;
      int len;
      int n;
  
      if (input == NULL) return;
      xmlGenericError(xmlGenericErrorContext, "<pre>\n");
      cur = input->cur;
      base = input->base;
      while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
  	cur--;
      }
      n = 0;
      while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
          cur--;
      if ((*cur == '\n') || (*cur == '\r')) cur++;
      base = cur;
      n = 0;
      while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
  	len = strlen(buffer);
          snprintf(&buffer[len], sizeof(buffer) - len, "%c",
  		    (unsigned char) *cur++);
  	n++;
      }
      len = strlen(buffer);
      snprintf(&buffer[len], sizeof(buffer) - len, "\n");
      cur = input->cur;
      while ((*cur == '\n') || (*cur == '\r'))
  	cur--;
      n = 0;
      while ((cur != base) && (n++ < 80)) {
  	len = strlen(buffer);
          snprintf(&buffer[len], sizeof(buffer) - len, " ");
          base++;
      }
      len = strlen(buffer);
      snprintf(&buffer[len], sizeof(buffer) - len, "^\n");
      xmlHTMLEncodeSend();
      xmlGenericError(xmlGenericErrorContext, "</pre>");
  }
  
  /**
   * xmlHTMLError:
   * @ctx:  an XML parser context
   * @msg:  the message to display/transmit
   * @...:  extra parameters for the message display
   *
   * Display and format an error messages, gives file, line, position and
   * extra parameters.
   */
  static void XMLCDECL
  xmlHTMLError(void *ctx, const char *msg, ...)
  {
      xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
      xmlParserInputPtr input;
      va_list args;
      int len;
  
      buffer[0] = 0;
      input = ctxt->input;
      if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
          input = ctxt->inputTab[ctxt->inputNr - 2];
      }
  
      xmlHTMLPrintFileInfo(input);
  
      xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
      va_start(args, msg);
      len = strlen(buffer);
      vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
      va_end(args);
      xmlHTMLEncodeSend();
      xmlGenericError(xmlGenericErrorContext, "</p>\n");
  
      xmlHTMLPrintFileContext(input);
      xmlHTMLEncodeSend();
  }
  
  /**
   * xmlHTMLWarning:
   * @ctx:  an XML parser context
   * @msg:  the message to display/transmit
   * @...:  extra parameters for the message display
   *
   * Display and format a warning messages, gives file, line, position and
   * extra parameters.
   */
  static void XMLCDECL
  xmlHTMLWarning(void *ctx, const char *msg, ...)
  {
      xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
      xmlParserInputPtr input;
      va_list args;
      int len;
  
      buffer[0] = 0;
      input = ctxt->input;
      if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
          input = ctxt->inputTab[ctxt->inputNr - 2];
      }
  
  
      xmlHTMLPrintFileInfo(input);
  
      xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
      va_start(args, msg);
      len = strlen(buffer);
      vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
      va_end(args);
      xmlHTMLEncodeSend();
      xmlGenericError(xmlGenericErrorContext, "</p>\n");
  
      xmlHTMLPrintFileContext(input);
      xmlHTMLEncodeSend();
  }
  
  /**
   * xmlHTMLValidityError:
   * @ctx:  an XML parser context
   * @msg:  the message to display/transmit
   * @...:  extra parameters for the message display
   *
   * Display and format an validity error messages, gives file,
   * line, position and extra parameters.
   */
  static void XMLCDECL
  xmlHTMLValidityError(void *ctx, const char *msg, ...)
  {
      xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
      xmlParserInputPtr input;
      va_list args;
      int len;
  
      buffer[0] = 0;
      input = ctxt->input;
      if ((input->filename == NULL) && (ctxt->inputNr > 1))
          input = ctxt->inputTab[ctxt->inputNr - 2];
  
      xmlHTMLPrintFileInfo(input);
  
      xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
      len = strlen(buffer);
      va_start(args, msg);
      vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
      va_end(args);
      xmlHTMLEncodeSend();
      xmlGenericError(xmlGenericErrorContext, "</p>\n");
  
      xmlHTMLPrintFileContext(input);
      xmlHTMLEncodeSend();
      progresult = XMLLINT_ERR_VALID;
  }
  
  /**
   * xmlHTMLValidityWarning:
   * @ctx:  an XML parser context
   * @msg:  the message to display/transmit
   * @...:  extra parameters for the message display
   *
   * Display and format a validity warning messages, gives file, line,
   * position and extra parameters.
   */
  static void XMLCDECL
  xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
  {
      xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
      xmlParserInputPtr input;
      va_list args;
      int len;
  
      buffer[0] = 0;
      input = ctxt->input;
      if ((input->filename == NULL) && (ctxt->inputNr > 1))
          input = ctxt->inputTab[ctxt->inputNr - 2];
  
      xmlHTMLPrintFileInfo(input);
  
      xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
      va_start(args, msg);
      len = strlen(buffer);
      vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
      va_end(args);
      xmlHTMLEncodeSend();
      xmlGenericError(xmlGenericErrorContext, "</p>\n");
  
      xmlHTMLPrintFileContext(input);
      xmlHTMLEncodeSend();
  }
  
  /************************************************************************
   *									*
   *			Shell Interface					*
   *									*
   ************************************************************************/
  #ifdef LIBXML_DEBUG_ENABLED
  #ifdef LIBXML_XPATH_ENABLED
  /**
   * xmlShellReadline:
   * @prompt:  the prompt value
   *
   * Read a string
   *
   * Returns a pointer to it or NULL on EOF the caller is expected to
   *     free the returned string.
   */
  static char *
  xmlShellReadline(char *prompt) {
  #ifdef HAVE_LIBREADLINE
      char *line_read;
  
      /* Get a line from the user. */
      line_read = readline (prompt);
  
      /* If the line has any text in it, save it on the history. */
      if (line_read && *line_read)
  	add_history (line_read);
  
      return (line_read);
  #else
      char line_read[501];
      char *ret;
      int len;
  
      if (prompt != NULL)
  	fprintf(stdout, "%s", prompt);
      if (!fgets(line_read, 500, stdin))
          return(NULL);
      line_read[500] = 0;
      len = strlen(line_read);
      ret = (char *) malloc(len + 1);
      if (ret != NULL) {
  	memcpy (ret, line_read, len + 1);
      }
      return(ret);
  #endif
  }
  #endif /* LIBXML_XPATH_ENABLED */
  #endif /* LIBXML_DEBUG_ENABLED */
  
  /************************************************************************
   *									*
   *			I/O Interfaces					*
   *									*
   ************************************************************************/
  
  static int myRead(FILE *f, char * buf, int len) {
      return(fread(buf, 1, len, f));
  }
  static void myClose(FILE *f) {
    if (f != stdin) {
      fclose(f);
    }
  }
  
  /************************************************************************
   *									*
   *			SAX based tests					*
   *									*
   ************************************************************************/
  
  /*
   * empty SAX block
   */
  static xmlSAXHandler emptySAXHandlerStruct = {
      NULL, /* internalSubset */
      NULL, /* isStandalone */
      NULL, /* hasInternalSubset */
      NULL, /* hasExternalSubset */
      NULL, /* resolveEntity */
      NULL, /* getEntity */
      NULL, /* entityDecl */
      NULL, /* notationDecl */
      NULL, /* attributeDecl */
      NULL, /* elementDecl */
      NULL, /* unparsedEntityDecl */
      NULL, /* setDocumentLocator */
      NULL, /* startDocument */
      NULL, /* endDocument */
      NULL, /* startElement */
      NULL, /* endElement */
      NULL, /* reference */
      NULL, /* characters */
      NULL, /* ignorableWhitespace */
      NULL, /* processingInstruction */
      NULL, /* comment */
      NULL, /* xmlParserWarning */
      NULL, /* xmlParserError */
      NULL, /* xmlParserError */
      NULL, /* getParameterEntity */
      NULL, /* cdataBlock; */
      NULL, /* externalSubset; */
      XML_SAX2_MAGIC,
      NULL,
      NULL, /* startElementNs */
      NULL, /* endElementNs */
      NULL  /* xmlStructuredErrorFunc */
  };
  
  static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
  extern xmlSAXHandlerPtr debugSAXHandler;
  static int callbacks;
  
  /**
   * isStandaloneDebug:
   * @ctxt:  An XML parser context
   *
   * Is this document tagged standalone ?
   *
   * Returns 1 if true
   */
  static int
  isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
  {
      callbacks++;
      if (noout)
  	return(0);
      fprintf(stdout, "SAX.isStandalone()\n");
      return(0);
  }
  
  /**
   * hasInternalSubsetDebug:
   * @ctxt:  An XML parser context
   *
   * Does this document has an internal subset
   *
   * Returns 1 if true
   */
  static int
  hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
  {
      callbacks++;
      if (noout)
  	return(0);
      fprintf(stdout, "SAX.hasInternalSubset()\n");
      return(0);
  }
  
  /**
   * hasExternalSubsetDebug:
   * @ctxt:  An XML parser context
   *
   * Does this document has an external subset
   *
   * Returns 1 if true
   */
  static int
  hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
  {
      callbacks++;
      if (noout)
  	return(0);
      fprintf(stdout, "SAX.hasExternalSubset()\n");
      return(0);
  }
  
  /**
   * internalSubsetDebug:
   * @ctxt:  An XML parser context
   *
   * Does this document has an internal subset
   */
  static void
  internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
  	       const xmlChar *ExternalID, const xmlChar *SystemID)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.internalSubset(%s,", name);
      if (ExternalID == NULL)
  	fprintf(stdout, " ,");
      else
  	fprintf(stdout, " %s,", ExternalID);
      if (SystemID == NULL)
  	fprintf(stdout, " )\n");
      else
  	fprintf(stdout, " %s)\n", SystemID);
  }
  
  /**
   * externalSubsetDebug:
   * @ctxt:  An XML parser context
   *
   * Does this document has an external subset
   */
  static void
  externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
  	       const xmlChar *ExternalID, const xmlChar *SystemID)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.externalSubset(%s,", name);
      if (ExternalID == NULL)
  	fprintf(stdout, " ,");
      else
  	fprintf(stdout, " %s,", ExternalID);
      if (SystemID == NULL)
  	fprintf(stdout, " )\n");
      else
  	fprintf(stdout, " %s)\n", SystemID);
  }
  
  /**
   * resolveEntityDebug:
   * @ctxt:  An XML parser context
   * @publicId: The public ID of the entity
   * @systemId: The system ID of the entity
   *
   * Special entity resolver, better left to the parser, it has
   * more context than the application layer.
   * The default behaviour is to NOT resolve the entities, in that case
   * the ENTITY_REF nodes are built in the structure (and the parameter
   * values).
   *
   * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
   */
  static xmlParserInputPtr
  resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
  {
      callbacks++;
      if (noout)
  	return(NULL);
      /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
  
  
      fprintf(stdout, "SAX.resolveEntity(");
      if (publicId != NULL)
  	fprintf(stdout, "%s", (char *)publicId);
      else
  	fprintf(stdout, " ");
      if (systemId != NULL)
  	fprintf(stdout, ", %s)\n", (char *)systemId);
      else
  	fprintf(stdout, ", )\n");
      return(NULL);
  }
  
  /**
   * getEntityDebug:
   * @ctxt:  An XML parser context
   * @name: The entity name
   *
   * Get an entity by name
   *
   * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
   */
  static xmlEntityPtr
  getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
  {
      callbacks++;
      if (noout)
  	return(NULL);
      fprintf(stdout, "SAX.getEntity(%s)\n", name);
      return(NULL);
  }
  
  /**
   * getParameterEntityDebug:
   * @ctxt:  An XML parser context
   * @name: The entity name
   *
   * Get a parameter entity by name
   *
   * Returns the xmlParserInputPtr
   */
  static xmlEntityPtr
  getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
  {
      callbacks++;
      if (noout)
  	return(NULL);
      fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
      return(NULL);
  }
  
  
  /**
   * entityDeclDebug:
   * @ctxt:  An XML parser context
   * @name:  the entity name
   * @type:  the entity type
   * @publicId: The public ID of the entity
   * @systemId: The system ID of the entity
   * @content: the entity value (without processing).
   *
   * An entity definition has been parsed
   */
  static void
  entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
            const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
  {
  const xmlChar *nullstr = BAD_CAST "(null)";
      /* not all libraries handle printing null pointers nicely */
      if (publicId == NULL)
          publicId = nullstr;
      if (systemId == NULL)
          systemId = nullstr;
      if (content == NULL)
          content = (xmlChar *)nullstr;
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
              name, type, publicId, systemId, content);
  }
  
  /**
   * attributeDeclDebug:
   * @ctxt:  An XML parser context
   * @name:  the attribute name
   * @type:  the attribute type
   *
   * An attribute definition has been parsed
   */
  static void
  attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
                     const xmlChar * name, int type, int def,
                     const xmlChar * defaultValue, xmlEnumerationPtr tree)
  {
      callbacks++;
      if (noout)
          return;
      if (defaultValue == NULL)
          fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
                  elem, name, type, def);
      else
          fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
                  elem, name, type, def, defaultValue);
      xmlFreeEnumeration(tree);
  }
  
  /**
   * elementDeclDebug:
   * @ctxt:  An XML parser context
   * @name:  the element name
   * @type:  the element type
   * @content: the element value (without processing).
   *
   * An element definition has been parsed
   */
  static void
  elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
  	    xmlElementContentPtr content ATTRIBUTE_UNUSED)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
              name, type);
  }
  
  /**
   * notationDeclDebug:
   * @ctxt:  An XML parser context
   * @name: The name of the notation
   * @publicId: The public ID of the entity
   * @systemId: The system ID of the entity
   *
   * What to do when a notation declaration has been parsed.
   */
  static void
  notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
  	     const xmlChar *publicId, const xmlChar *systemId)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
              (char *) name, (char *) publicId, (char *) systemId);
  }
  
  /**
   * unparsedEntityDeclDebug:
   * @ctxt:  An XML parser context
   * @name: The name of the entity
   * @publicId: The public ID of the entity
   * @systemId: The system ID of the entity
   * @notationName: the name of the notation
   *
   * What to do when an unparsed entity declaration is parsed
   */
  static void
  unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
  		   const xmlChar *publicId, const xmlChar *systemId,
  		   const xmlChar *notationName)
  {
  const xmlChar *nullstr = BAD_CAST "(null)";
  
      if (publicId == NULL)
          publicId = nullstr;
      if (systemId == NULL)
          systemId = nullstr;
      if (notationName == NULL)
          notationName = nullstr;
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
              (char *) name, (char *) publicId, (char *) systemId,
  	    (char *) notationName);
  }
  
  /**
   * setDocumentLocatorDebug:
   * @ctxt:  An XML parser context
   * @loc: A SAX Locator
   *
   * Receive the document locator at startup, actually xmlDefaultSAXLocator
   * Everything is available on the context, so this is useless in our case.
   */
  static void
  setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.setDocumentLocator()\n");
  }
  
  /**
   * startDocumentDebug:
   * @ctxt:  An XML parser context
   *
   * called when the document start being processed.
   */
  static void
  startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.startDocument()\n");
  }
  
  /**
   * endDocumentDebug:
   * @ctxt:  An XML parser context
   *
   * called when the document end has been detected.
   */
  static void
  endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.endDocument()\n");
  }
  
  /**
   * startElementDebug:
   * @ctxt:  An XML parser context
   * @name:  The element name
   *
   * called when an opening tag has been processed.
   */
  static void
  startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
  {
      int i;
  
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.startElement(%s", (char *) name);
      if (atts != NULL) {
          for (i = 0;(atts[i] != NULL);i++) {
  	    fprintf(stdout, ", %s='", atts[i++]);
  	    if (atts[i] != NULL)
  	        fprintf(stdout, "%s'", atts[i]);
  	}
      }
      fprintf(stdout, ")\n");
  }
  
  /**
   * endElementDebug:
   * @ctxt:  An XML parser context
   * @name:  The element name
   *
   * called when the end of an element has been detected.
   */
  static void
  endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
  }
  
  /**
   * charactersDebug:
   * @ctxt:  An XML parser context
   * @ch:  a xmlChar string
   * @len: the number of xmlChar
   *
   * receiving some chars from the parser.
   * Question: how much at a time ???
   */
  static void
  charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
  {
      char out[40];
      int i;
  
      callbacks++;
      if (noout)
  	return;
      for (i = 0;(i<len) && (i < 30);i++)
  	out[i] = ch[i];
      out[i] = 0;
  
      fprintf(stdout, "SAX.characters(%s, %d)\n", out, len);
  }
  
  /**
   * referenceDebug:
   * @ctxt:  An XML parser context
   * @name:  The entity name
   *
   * called when an entity reference is detected.
   */
  static void
  referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.reference(%s)\n", name);
  }
  
  /**
   * ignorableWhitespaceDebug:
   * @ctxt:  An XML parser context
   * @ch:  a xmlChar string
   * @start: the first char in the string
   * @len: the number of xmlChar
   *
   * receiving some ignorable whitespaces from the parser.
   * Question: how much at a time ???
   */
  static void
  ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
  {
      char out[40];
      int i;
  
      callbacks++;
      if (noout)
  	return;
      for (i = 0;(i<len) && (i < 30);i++)
  	out[i] = ch[i];
      out[i] = 0;
      fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", out, len);
  }
  
  /**
   * processingInstructionDebug:
   * @ctxt:  An XML parser context
   * @target:  the target name
   * @data: the PI data's
   * @len: the number of xmlChar
   *
   * A processing instruction has been parsed.
   */
  static void
  processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
                        const xmlChar *data)
  {
      callbacks++;
      if (noout)
  	return;
      if (data != NULL)
  	fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
  		(char *) target, (char *) data);
      else
  	fprintf(stdout, "SAX.processingInstruction(%s, NULL)\n",
  		(char *) target);
  }
  
  /**
   * cdataBlockDebug:
   * @ctx: the user data (XML parser context)
   * @value:  The pcdata content
   * @len:  the block length
   *
   * called when a pcdata block has been parsed
   */
  static void
  cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.pcdata(%.20s, %d)\n",
  	    (char *) value, len);
  }
  
  /**
   * commentDebug:
   * @ctxt:  An XML parser context
   * @value:  the comment content
   *
   * A comment has been parsed.
   */
  static void
  commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.comment(%s)\n", value);
  }
  
  /**
   * warningDebug:
   * @ctxt:  An XML parser context
   * @msg:  the message to display/transmit
   * @...:  extra parameters for the message display
   *
   * Display and format a warning messages, gives file, line, position and
   * extra parameters.
   */
  static void XMLCDECL
  warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
  {
      va_list args;
  
      callbacks++;
      if (noout)
  	return;
      va_start(args, msg);
      fprintf(stdout, "SAX.warning: ");
      vfprintf(stdout, msg, args);
      va_end(args);
  }
  
  /**
   * errorDebug:
   * @ctxt:  An XML parser context
   * @msg:  the message to display/transmit
   * @...:  extra parameters for the message display
   *
   * Display and format a error messages, gives file, line, position and
   * extra parameters.
   */
  static void XMLCDECL
  errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
  {
      va_list args;
  
      callbacks++;
      if (noout)
  	return;
      va_start(args, msg);
      fprintf(stdout, "SAX.error: ");
      vfprintf(stdout, msg, args);
      va_end(args);
  }
  
  /**
   * fatalErrorDebug:
   * @ctxt:  An XML parser context
   * @msg:  the message to display/transmit
   * @...:  extra parameters for the message display
   *
   * Display and format a fatalError messages, gives file, line, position and
   * extra parameters.
   */
  static void XMLCDECL
  fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
  {
      va_list args;
  
      callbacks++;
      if (noout)
  	return;
      va_start(args, msg);
      fprintf(stdout, "SAX.fatalError: ");
      vfprintf(stdout, msg, args);
      va_end(args);
  }
  
  static xmlSAXHandler debugSAXHandlerStruct = {
      internalSubsetDebug,
      isStandaloneDebug,
      hasInternalSubsetDebug,
      hasExternalSubsetDebug,
      resolveEntityDebug,
      getEntityDebug,
      entityDeclDebug,
      notationDeclDebug,
      attributeDeclDebug,
      elementDeclDebug,
      unparsedEntityDeclDebug,
      setDocumentLocatorDebug,
      startDocumentDebug,
      endDocumentDebug,
      startElementDebug,
      endElementDebug,
      referenceDebug,
      charactersDebug,
      ignorableWhitespaceDebug,
      processingInstructionDebug,
      commentDebug,
      warningDebug,
      errorDebug,
      fatalErrorDebug,
      getParameterEntityDebug,
      cdataBlockDebug,
      externalSubsetDebug,
      1,
      NULL,
      NULL,
      NULL,
      NULL
  };
  
  xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
  
  /*
   * SAX2 specific callbacks
   */
  /**
   * startElementNsDebug:
   * @ctxt:  An XML parser context
   * @name:  The element name
   *
   * called when an opening tag has been processed.
   */
  static void
  startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
                      const xmlChar *localname,
                      const xmlChar *prefix,
                      const xmlChar *URI,
  		    int nb_namespaces,
  		    const xmlChar **namespaces,
  		    int nb_attributes,
  		    int nb_defaulted,
  		    const xmlChar **attributes)
  {
      int i;
  
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.startElementNs(%s", (char *) localname);
      if (prefix == NULL)
  	fprintf(stdout, ", NULL");
      else
  	fprintf(stdout, ", %s", (char *) prefix);
      if (URI == NULL)
  	fprintf(stdout, ", NULL");
      else
  	fprintf(stdout, ", '%s'", (char *) URI);
      fprintf(stdout, ", %d", nb_namespaces);
  
      if (namespaces != NULL) {
          for (i = 0;i < nb_namespaces * 2;i++) {
  	    fprintf(stdout, ", xmlns");
  	    if (namespaces[i] != NULL)
  	        fprintf(stdout, ":%s", namespaces[i]);
  	    i++;
  	    fprintf(stdout, "='%s'", namespaces[i]);
  	}
      }
      fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted);
      if (attributes != NULL) {
          for (i = 0;i < nb_attributes * 5;i += 5) {
  	    if (attributes[i + 1] != NULL)
  		fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]);
  	    else
  		fprintf(stdout, ", %s='", attributes[i]);
  	    fprintf(stdout, "%.4s...', %d", attributes[i + 3],
  		    (int)(attributes[i + 4] - attributes[i + 3]));
  	}
      }
      fprintf(stdout, ")\n");
  }
  
  /**
   * endElementDebug:
   * @ctxt:  An XML parser context
   * @name:  The element name
   *
   * called when the end of an element has been detected.
   */
  static void
  endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
                    const xmlChar *localname,
                    const xmlChar *prefix,
                    const xmlChar *URI)
  {
      callbacks++;
      if (noout)
  	return;
      fprintf(stdout, "SAX.endElementNs(%s", (char *) localname);
      if (prefix == NULL)
  	fprintf(stdout, ", NULL");
      else
  	fprintf(stdout, ", %s", (char *) prefix);
      if (URI == NULL)
  	fprintf(stdout, ", NULL)\n");
      else
  	fprintf(stdout, ", '%s')\n", (char *) URI);
  }
  
  static xmlSAXHandler debugSAX2HandlerStruct = {
      internalSubsetDebug,
      isStandaloneDebug,
      hasInternalSubsetDebug,
      hasExternalSubsetDebug,
      resolveEntityDebug,
      getEntityDebug,
      entityDeclDebug,
      notationDeclDebug,
      attributeDeclDebug,
      elementDeclDebug,
      unparsedEntityDeclDebug,
      setDocumentLocatorDebug,
      startDocumentDebug,
      endDocumentDebug,
      NULL,
      NULL,
      referenceDebug,
      charactersDebug,
      ignorableWhitespaceDebug,
      processingInstructionDebug,
      commentDebug,
      warningDebug,
      errorDebug,
      fatalErrorDebug,
      getParameterEntityDebug,
      cdataBlockDebug,
      externalSubsetDebug,
      XML_SAX2_MAGIC,
      NULL,
      startElementNsDebug,
      endElementNsDebug,
      NULL
  };
  
  static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
  
  static void
  testSAX(const char *filename) {
      xmlSAXHandlerPtr handler;
      const char *user_data = "user_data"; /* mostly for debugging */
      xmlParserInputBufferPtr buf = NULL;
      xmlParserInputPtr inputStream;
      xmlParserCtxtPtr ctxt = NULL;
      xmlSAXHandlerPtr old_sax = NULL;
  
      callbacks = 0;
  
      if (noout) {
          handler = emptySAXHandler;
  #ifdef LIBXML_SAX1_ENABLED
      } else if (sax1) {
          handler = debugSAXHandler;
  #endif
      } else {
          handler = debugSAX2Handler;
      }
  
      /*
       * it's not the simplest code but the most generic in term of I/O
       */
      buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
      if (buf == NULL) {
          goto error;
      }
  
  #ifdef LIBXML_SCHEMAS_ENABLED
      if (wxschemas != NULL) {
          int ret;
  	xmlSchemaValidCtxtPtr vctxt;
  
  	vctxt = xmlSchemaNewValidCtxt(wxschemas);
  	xmlSchemaSetValidErrors(vctxt,
  		(xmlSchemaValidityErrorFunc) fprintf,
  		(xmlSchemaValidityWarningFunc) fprintf,
  		stderr);
  
  	ret = xmlSchemaValidateStream(vctxt, buf, 0, handler,
  	                              (void *)user_data);
  	if (repeat == 0) {
  	    if (ret == 0) {
  		fprintf(stderr, "%s validates\n", filename);
  	    } else if (ret > 0) {
  		fprintf(stderr, "%s fails to validate\n", filename);
  		progresult = XMLLINT_ERR_VALID;
  	    } else {
  		fprintf(stderr, "%s validation generated an internal error\n",
  		       filename);
  		progresult = XMLLINT_ERR_VALID;
  	    }
  	}
  	xmlSchemaFreeValidCtxt(vctxt);
      } else
  #endif
      {
  	/*
  	 * Create the parser context amd hook the input
  	 */
  	ctxt = xmlNewParserCtxt();
  	if (ctxt == NULL) {
  	    xmlFreeParserInputBuffer(buf);
  	    goto error;
  	}
  	old_sax = ctxt->sax;
  	ctxt->sax = handler;
  	ctxt->userData = (void *) user_data;
  	inputStream = xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE);
  	if (inputStream == NULL) {
  	    xmlFreeParserInputBuffer(buf);
  	    goto error;
  	}
  	inputPush(ctxt, inputStream);
  
  	/* do the parsing */
  	xmlParseDocument(ctxt);
  
  	if (ctxt->myDoc != NULL) {
  	    fprintf(stderr, "SAX generated a doc !\n");
  	    xmlFreeDoc(ctxt->myDoc);
  	    ctxt->myDoc = NULL;
  	}
      }
  
  error:
      if (ctxt != NULL) {
          ctxt->sax = old_sax;
          xmlFreeParserCtxt(ctxt);
      }
  }
  
  /************************************************************************
   *									*
   *			Stream Test processing				*
   *									*
   ************************************************************************/
  #ifdef LIBXML_READER_ENABLED
  static void processNode(xmlTextReaderPtr reader) {
      const xmlChar *name, *value;
      int type, empty;
  
      type = xmlTextReaderNodeType(reader);
      empty = xmlTextReaderIsEmptyElement(reader);
  
      if (debug) {
  	name = xmlTextReaderConstName(reader);
  	if (name == NULL)
  	    name = BAD_CAST "--";
  
  	value = xmlTextReaderConstValue(reader);
  
  
  	printf("%d %d %s %d %d",
  		xmlTextReaderDepth(reader),
  		type,
  		name,
  		empty,
  		xmlTextReaderHasValue(reader));
  	if (value == NULL)
  	    printf("\n");
  	else {
  	    printf(" %s\n", value);
  	}
      }
  #ifdef LIBXML_PATTERN_ENABLED
      if (patternc) {
          xmlChar *path = NULL;
          int match = -1;
  
  	if (type == XML_READER_TYPE_ELEMENT) {
  	    /* do the check only on element start */
  	    match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
  
  	    if (match) {
  #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
  		path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
  		printf("Node %s matches pattern %s\n", path, pattern);
  #else
                  printf("Node %s matches pattern %s\n",
                         xmlTextReaderConstName(reader), pattern);
  #endif
  	    }
  	}
  	if (patstream != NULL) {
  	    int ret;
  
  	    if (type == XML_READER_TYPE_ELEMENT) {
  		ret = xmlStreamPush(patstream,
  		                    xmlTextReaderConstLocalName(reader),
  				    xmlTextReaderConstNamespaceUri(reader));
  		if (ret < 0) {
  		    fprintf(stderr, "xmlStreamPush() failure\n");
                      xmlFreeStreamCtxt(patstream);
  		    patstream = NULL;
  		} else if (ret != match) {
  #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
  		    if (path == NULL) {
  		        path = xmlGetNodePath(
  		                       xmlTextReaderCurrentNode(reader));
  		    }
  #endif
  		    fprintf(stderr,
  		            "xmlPatternMatch and xmlStreamPush disagree\n");
                      if (path != NULL)
                          fprintf(stderr, "  pattern %s node %s\n",
                                  pattern, path);
                      else
  		        fprintf(stderr, "  pattern %s node %s\n",
  			    pattern, xmlTextReaderConstName(reader));
  		}
  
  	    }
  	    if ((type == XML_READER_TYPE_END_ELEMENT) ||
  	        ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
  	        ret = xmlStreamPop(patstream);
  		if (ret < 0) {
  		    fprintf(stderr, "xmlStreamPop() failure\n");
                      xmlFreeStreamCtxt(patstream);
  		    patstream = NULL;
  		}
  	    }
  	}
  	if (path != NULL)
  	    xmlFree(path);
      }
  #endif
  }
  
  static void streamFile(char *filename) {
      xmlTextReaderPtr reader;
      int ret;
  #ifdef HAVE_SYS_MMAN_H
      int fd = -1;
      struct stat info;
      const char *base = NULL;
      xmlParserInputBufferPtr input = NULL;
  
      if (memory) {
  	if (stat(filename, &info) < 0)
  	    return;
  	if ((fd = open(filename, O_RDONLY)) < 0)
  	    return;
  	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
  	if (base == (void *) MAP_FAILED)
  	    return;
  
  	reader = xmlReaderForMemory(base, info.st_size, filename,
  	                            NULL, options);
      } else
  #endif
  	reader = xmlReaderForFile(filename, NULL, options);
  #ifdef LIBXML_PATTERN_ENABLED
      if (pattern != NULL) {
          patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
  	if (patternc == NULL) {
  	    xmlGenericError(xmlGenericErrorContext,
  		    "Pattern %s failed to compile\n", pattern);
              progresult = XMLLINT_ERR_SCHEMAPAT;
  	    pattern = NULL;
  	}
      }
      if (patternc != NULL) {
          patstream = xmlPatternGetStreamCtxt(patternc);
  	if (patstream != NULL) {
  	    ret = xmlStreamPush(patstream, NULL, NULL);
  	    if (ret < 0) {
  		fprintf(stderr, "xmlStreamPush() failure\n");
  		xmlFreeStreamCtxt(patstream);
  		patstream = NULL;
              }
  	}
      }
  #endif
  
  
      if (reader != NULL) {
  #ifdef LIBXML_VALID_ENABLED
  	if (valid)
  	    xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
  	else
  #endif /* LIBXML_VALID_ENABLED */
  	    xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1);
  #ifdef LIBXML_SCHEMAS_ENABLED
  	if (relaxng != NULL) {
  	    if ((timing) && (!repeat)) {
  		startTimer();
  	    }
  	    ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
  	    if (ret < 0) {
  		xmlGenericError(xmlGenericErrorContext,
  			"Relax-NG schema %s failed to compile\n", relaxng);
  		progresult = XMLLINT_ERR_SCHEMACOMP;
  		relaxng = NULL;
  	    }
  	    if ((timing) && (!repeat)) {
  		endTimer("Compiling the schemas");
  	    }
  	}
  	if (schema != NULL) {
  	    if ((timing) && (!repeat)) {
  		startTimer();
  	    }
  	    ret = xmlTextReaderSchemaValidate(reader, schema);
  	    if (ret < 0) {
  		xmlGenericError(xmlGenericErrorContext,
  			"XSD schema %s failed to compile\n", schema);
  		progresult = XMLLINT_ERR_SCHEMACOMP;
  		schema = NULL;
  	    }
  	    if ((timing) && (!repeat)) {
  		endTimer("Compiling the schemas");
  	    }
  	}
  #endif
  
  	/*
  	 * Process all nodes in sequence
  	 */
  	if ((timing) && (!repeat)) {
  	    startTimer();
  	}
  	ret = xmlTextReaderRead(reader);
  	while (ret == 1) {
  	    if ((debug)
  #ifdef LIBXML_PATTERN_ENABLED
  	        || (patternc)
  #endif
  	       )
  		processNode(reader);
  	    ret = xmlTextReaderRead(reader);
  	}
  	if ((timing) && (!repeat)) {
  #ifdef LIBXML_SCHEMAS_ENABLED
  	    if (relaxng != NULL)
  		endTimer("Parsing and validating");
  	    else
  #endif
  #ifdef LIBXML_VALID_ENABLED
  	    if (valid)
  		endTimer("Parsing and validating");
  	    else
  #endif
  	    endTimer("Parsing");
  	}
  
  #ifdef LIBXML_VALID_ENABLED
  	if (valid) {
  	    if (xmlTextReaderIsValid(reader) != 1) {
  		xmlGenericError(xmlGenericErrorContext,
  			"Document %s does not validate\n", filename);
  		progresult = XMLLINT_ERR_VALID;
  	    }
  	}
  #endif /* LIBXML_VALID_ENABLED */
  #ifdef LIBXML_SCHEMAS_ENABLED
  	if ((relaxng != NULL) || (schema != NULL)) {
  	    if (xmlTextReaderIsValid(reader) != 1) {
  		fprintf(stderr, "%s fails to validate\n", filename);
  		progresult = XMLLINT_ERR_VALID;
  	    } else {
  		fprintf(stderr, "%s validates\n", filename);
  	    }
  	}
  #endif
  	/*
  	 * Done, cleanup and status
  	 */
  	xmlFreeTextReader(reader);
  	if (ret != 0) {
  	    fprintf(stderr, "%s : failed to parse\n", filename);
  	    progresult = XMLLINT_ERR_UNCLASS;
  	}
      } else {
  	fprintf(stderr, "Unable to open %s\n", filename);
  	progresult = XMLLINT_ERR_UNCLASS;
      }
  #ifdef LIBXML_PATTERN_ENABLED
      if (patstream != NULL) {
  	xmlFreeStreamCtxt(patstream);
  	patstream = NULL;
      }
  #endif
  #ifdef HAVE_SYS_MMAN_H
      if (memory) {
          xmlFreeParserInputBuffer(input);
  	munmap((char *) base, info.st_size);
  	close(fd);
      }
  #endif
  }
  
  static void walkDoc(xmlDocPtr doc) {
      xmlTextReaderPtr reader;
      int ret;
  
  #ifdef LIBXML_PATTERN_ENABLED
      xmlNodePtr root;
      const xmlChar *namespaces[22];
      int i;
      xmlNsPtr ns;
  
      root = xmlDocGetRootElement(doc);
      for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) {
          namespaces[i++] = ns->href;
          namespaces[i++] = ns->prefix;
      }
      namespaces[i++] = NULL;
      namespaces[i] = NULL;
  
      if (pattern != NULL) {
          patternc = xmlPatterncompile((const xmlChar *) pattern, doc->dict,
  	                             0, &namespaces[0]);
  	if (patternc == NULL) {
  	    xmlGenericError(xmlGenericErrorContext,
  		    "Pattern %s failed to compile\n", pattern);
              progresult = XMLLINT_ERR_SCHEMAPAT;
  	    pattern = NULL;
  	}
      }
      if (patternc != NULL) {
          patstream = xmlPatternGetStreamCtxt(patternc);
  	if (patstream != NULL) {
  	    ret = xmlStreamPush(patstream, NULL, NULL);
  	    if (ret < 0) {
  		fprintf(stderr, "xmlStreamPush() failure\n");
  		xmlFreeStreamCtxt(patstream);
  		patstream = NULL;
              }
  	}
      }
  #endif /* LIBXML_PATTERN_ENABLED */
      reader = xmlReaderWalker(doc);
      if (reader != NULL) {
  	if ((timing) && (!repeat)) {
  	    startTimer();
  	}
  	ret = xmlTextReaderRead(reader);
  	while (ret == 1) {
  	    if ((debug)
  #ifdef LIBXML_PATTERN_ENABLED
  	        || (patternc)
  #endif
  	       )
  		processNode(reader);
  	    ret = xmlTextReaderRead(reader);
  	}
  	if ((timing) && (!repeat)) {
  	    endTimer("walking through the doc");
  	}
  	xmlFreeTextReader(reader);
  	if (ret != 0) {
  	    fprintf(stderr, "failed to walk through the doc\n");
  	    progresult = XMLLINT_ERR_UNCLASS;
  	}
      } else {
  	fprintf(stderr, "Failed to crate a reader from the document\n");
  	progresult = XMLLINT_ERR_UNCLASS;
      }
  #ifdef LIBXML_PATTERN_ENABLED
      if (patstream != NULL) {
  	xmlFreeStreamCtxt(patstream);
  	patstream = NULL;
      }
  #endif
  }
  #endif /* LIBXML_READER_ENABLED */
  
  #ifdef LIBXML_XPATH_ENABLED
  /************************************************************************
   *									*
   *			XPath Query                                     *
   *									*
   ************************************************************************/
  
  static void doXPathDump(xmlXPathObjectPtr cur) {
      switch(cur->type) {
          case XPATH_NODESET: {
              int i;
              xmlNodePtr node;
  #ifdef LIBXML_OUTPUT_ENABLED
              xmlSaveCtxtPtr ctxt;
  
              if (cur->nodesetval->nodeNr <= 0) {
                  fprintf(stderr, "XPath set is empty\n");
                  progresult = XMLLINT_ERR_XPATH;
                  break;
              }
              ctxt = xmlSaveToFd(1, NULL, 0);
              if (ctxt == NULL) {
                  fprintf(stderr, "Out of memory for XPath\n");
                  progresult = XMLLINT_ERR_MEM;
                  return;
              }
              for (i = 0;i < cur->nodesetval->nodeNr;i++) {
                  node = cur->nodesetval->nodeTab[i];
                  xmlSaveTree(ctxt, node);
              }
              xmlSaveClose(ctxt);
  #else
              printf("xpath returned %d nodes\n", cur->nodesetval->nodeNr);
  #endif
  	    break;
          }
          case XPATH_BOOLEAN:
  	    if (cur->boolval) printf("true");
  	    else printf("false");
  	    break;
          case XPATH_NUMBER:
  	    switch (xmlXPathIsInf(cur->floatval)) {
  	    case 1:
  		printf("Infinity");
  		break;
  	    case -1:
  		printf("-Infinity");
  		break;
  	    default:
  		if (xmlXPathIsNaN(cur->floatval)) {
  		    printf("NaN");
  		} else {
  		    printf("%0g", cur->floatval);
  		}
  	    }
  	    break;
          case XPATH_STRING:
  	    printf("%s", (const char *) cur->stringval);
  	    break;
          case XPATH_UNDEFINED:
  	    fprintf(stderr, "XPath Object is uninitialized\n");
              progresult = XMLLINT_ERR_XPATH;
  	    break;
  	default:
  	    fprintf(stderr, "XPath object of unexpected type\n");
              progresult = XMLLINT_ERR_XPATH;
  	    break;
      }
  }
  
  static void doXPathQuery(xmlDocPtr doc, const char *query) {
      xmlXPathContextPtr ctxt;
      xmlXPathObjectPtr res;
  
      ctxt = xmlXPathNewContext(doc);
      if (ctxt == NULL) {
          fprintf(stderr, "Out of memory for XPath\n");
          progresult = XMLLINT_ERR_MEM;
          return;
      }
      ctxt->node = xmlDocGetRootElement(doc);
      res = xmlXPathEval(BAD_CAST query, ctxt);
      xmlXPathFreeContext(ctxt);
  
      if (res == NULL) {
          fprintf(stderr, "XPath evaluation failure\n");
          progresult = XMLLINT_ERR_XPATH;
          return;
      }
      doXPathDump(res);
      xmlXPathFreeObject(res);
  }
  #endif /* LIBXML_XPATH_ENABLED */
  
  /************************************************************************
   *									*
   *			Tree Test processing				*
   *									*
   ************************************************************************/
  static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
      xmlDocPtr doc = NULL;
  #ifdef LIBXML_TREE_ENABLED
      xmlDocPtr tmp;
  #endif /* LIBXML_TREE_ENABLED */
  
      if ((timing) && (!repeat))
  	startTimer();
  
  
  #ifdef LIBXML_TREE_ENABLED
      if (filename == NULL) {
  	if (generate) {
  	    xmlNodePtr n;
  
  	    doc = xmlNewDoc(BAD_CAST "1.0");
  	    n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL);
  	    xmlNodeSetContent(n, BAD_CAST "abc");
  	    xmlDocSetRootElement(doc, n);
  	}
      }
  #endif /* LIBXML_TREE_ENABLED */
  #ifdef LIBXML_HTML_ENABLED
  #ifdef LIBXML_PUSH_ENABLED
      else if ((html) && (push)) {
          FILE *f;
  
  #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
  	f = fopen(filename, "rb");
  #else
  	f = fopen(filename, "r");
  #endif
          if (f != NULL) {
              int res, size = 3;
              char chars[4096];
              htmlParserCtxtPtr ctxt;
  
              /* if (repeat) */
                  size = 4096;
              res = fread(chars, 1, 4, f);
              if (res > 0) {
                  ctxt = htmlCreatePushParserCtxt(NULL, NULL,
                              chars, res, filename, XML_CHAR_ENCODING_NONE);
                  while ((res = fread(chars, 1, size, f)) > 0) {
                      htmlParseChunk(ctxt, chars, res, 0);
                  }
                  htmlParseChunk(ctxt, chars, 0, 1);
                  doc = ctxt->myDoc;
                  htmlFreeParserCtxt(ctxt);
              }
              fclose(f);
          }
      }
  #endif /* LIBXML_PUSH_ENABLED */
  #ifdef HAVE_SYS_MMAN_H
      else if ((html) && (memory)) {
  	int fd;
  	struct stat info;
  	const char *base;
  	if (stat(filename, &info) < 0)
  	    return;
  	if ((fd = open(filename, O_RDONLY)) < 0)
  	    return;
  	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
  	if (base == (void *) MAP_FAILED)
  	    return;
  
  	doc = htmlReadMemory((char *) base, info.st_size, filename,
  	                     NULL, options);
  
  	munmap((char *) base, info.st_size);
  	close(fd);
      }
  #endif
      else if (html) {
  	doc = htmlReadFile(filename, NULL, options);
      }
  #endif /* LIBXML_HTML_ENABLED */
      else {
  #ifdef LIBXML_PUSH_ENABLED
  	/*
  	 * build an XML tree from a string;
  	 */
  	if (push) {
  	    FILE *f;
  
  	    /* '-' Usually means stdin -<sven@zen.org> */
  	    if ((filename[0] == '-') && (filename[1] == 0)) {
  	      f = stdin;
  	    } else {
  #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
  		f = fopen(filename, "rb");
  #else
  		f = fopen(filename, "r");
  #endif
  	    }
  	    if (f != NULL) {
  		int ret;
  	        int res, size = 1024;
  	        char chars[1024];
                  xmlParserCtxtPtr ctxt;
  
  		/* if (repeat) size = 1024; */
  		res = fread(chars, 1, 4, f);
  		if (res > 0) {
  		    ctxt = xmlCreatePushParserCtxt(NULL, NULL,
  		                chars, res, filename);
  		    xmlCtxtUseOptions(ctxt, options);
  		    while ((res = fread(chars, 1, size, f)) > 0) {
  			xmlParseChunk(ctxt, chars, res, 0);
  		    }
  		    xmlParseChunk(ctxt, chars, 0, 1);
  		    doc = ctxt->myDoc;
  		    ret = ctxt->wellFormed;
  		    xmlFreeParserCtxt(ctxt);
  		    if (!ret) {
  			xmlFreeDoc(doc);
  			doc = NULL;
  		    }
  	        }
                  if (f != stdin)
                      fclose(f);
  	    }
  	} else
  #endif /* LIBXML_PUSH_ENABLED */
          if (testIO) {
  	    if ((filename[0] == '-') && (filename[1] == 0)) {
  	        doc = xmlReadFd(0, NULL, NULL, options);
  	    } else {
  	        FILE *f;
  
  #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
  		f = fopen(filename, "rb");
  #else
  		f = fopen(filename, "r");
  #endif
  		if (f != NULL) {
  		    if (rectxt == NULL)
  			doc = xmlReadIO((xmlInputReadCallback) myRead,
  					(xmlInputCloseCallback) myClose, f,
  					filename, NULL, options);
  		    else
  			doc = xmlCtxtReadIO(rectxt,
  			                (xmlInputReadCallback) myRead,
  					(xmlInputCloseCallback) myClose, f,
  					filename, NULL, options);
  		} else
  		    doc = NULL;
  	    }
  	} else if (htmlout) {
  	    xmlParserCtxtPtr ctxt;
  
  	    if (rectxt == NULL)
  		ctxt = xmlNewParserCtxt();
  	    else
  	        ctxt = rectxt;
  	    if (ctxt == NULL) {
  	        doc = NULL;
  	    } else {
  	        ctxt->sax->error = xmlHTMLError;
  	        ctxt->sax->warning = xmlHTMLWarning;
  	        ctxt->vctxt.error = xmlHTMLValidityError;
  	        ctxt->vctxt.warning = xmlHTMLValidityWarning;
  
  		doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
  
  		if (rectxt == NULL)
  		    xmlFreeParserCtxt(ctxt);
  	    }
  #ifdef HAVE_SYS_MMAN_H
  	} else if (memory) {
  	    int fd;
  	    struct stat info;
  	    const char *base;
  	    if (stat(filename, &info) < 0)
  		return;
  	    if ((fd = open(filename, O_RDONLY)) < 0)
  		return;
  	    base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
  	    if (base == (void *) MAP_FAILED)
  	        return;
  
  	    if (rectxt == NULL)
  		doc = xmlReadMemory((char *) base, info.st_size,
  		                    filename, NULL, options);
  	    else
  		doc = xmlCtxtReadMemory(rectxt, (char *) base, info.st_size,
  			                filename, NULL, options);
  
  	    munmap((char *) base, info.st_size);
  	    close(fd);
  #endif
  #ifdef LIBXML_VALID_ENABLED
  	} else if (valid) {
  	    xmlParserCtxtPtr ctxt = NULL;
  
  	    if (rectxt == NULL)
  		ctxt = xmlNewParserCtxt();
  	    else
  	        ctxt = rectxt;
  	    if (ctxt == NULL) {
  	        doc = NULL;
  	    } else {
  		doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
  
  		if (ctxt->valid == 0)
  		    progresult = XMLLINT_ERR_RDFILE;
  		if (rectxt == NULL)
  		    xmlFreeParserCtxt(ctxt);
  	    }
  #endif /* LIBXML_VALID_ENABLED */
  	} else {
  	    if (rectxt != NULL)
  	        doc = xmlCtxtReadFile(rectxt, filename, NULL, options);
  	    else {
  #ifdef LIBXML_SAX1_ENABLED
                  if (sax1)
  		    doc = xmlParseFile(filename);
  		else
  #endif /* LIBXML_SAX1_ENABLED */
  		doc = xmlReadFile(filename, NULL, options);
  	    }
  	}
      }
  
      /*
       * If we don't have a document we might as well give up.  Do we
       * want an error message here?  <sven@zen.org> */
      if (doc == NULL) {
  	progresult = XMLLINT_ERR_UNCLASS;
  	return;
      }
  
      if ((timing) && (!repeat)) {
  	endTimer("Parsing");
      }
  
      /*
       * Remove DOCTYPE nodes
       */
      if (dropdtd) {
  	xmlDtdPtr dtd;
  
  	dtd = xmlGetIntSubset(doc);
  	if (dtd != NULL) {
  	    xmlUnlinkNode((xmlNodePtr)dtd);
  	    xmlFreeDtd(dtd);
  	}
      }
  
  #ifdef LIBXML_XINCLUDE_ENABLED
      if (xinclude) {
  	if ((timing) && (!repeat)) {
  	    startTimer();
  	}
  	if (xmlXIncludeProcessFlags(doc, options) < 0)
  	    progresult = XMLLINT_ERR_UNCLASS;
  	if ((timing) && (!repeat)) {
  	    endTimer("Xinclude processing");
  	}
      }
  #endif
  
  #ifdef LIBXML_XPATH_ENABLED
      if (xpathquery != NULL) {
          doXPathQuery(doc, xpathquery);
      }
  #endif
  
  #ifdef LIBXML_DEBUG_ENABLED
  #ifdef LIBXML_XPATH_ENABLED
      /*
       * shell interaction
       */
      if (shell) {
          xmlXPathOrderDocElems(doc);
          xmlShell(doc, filename, xmlShellReadline, stdout);
      }
  #endif
  #endif
  
  #ifdef LIBXML_TREE_ENABLED
      /*
       * test intermediate copy if needed.
       */
      if (copy) {
          tmp = doc;
  	if (timing) {
  	    startTimer();
  	}
  	doc = xmlCopyDoc(doc, 1);
  	if (timing) {
  	    endTimer("Copying");
  	}
  	if (timing) {
  	    startTimer();
  	}
  	xmlFreeDoc(tmp);
  	if (timing) {
  	    endTimer("Freeing original");
  	}
      }
  #endif /* LIBXML_TREE_ENABLED */
  
  #ifdef LIBXML_VALID_ENABLED
      if ((insert) && (!html)) {
          const xmlChar* list[256];
  	int nb, i;
  	xmlNodePtr node;
  
  	if (doc->children != NULL) {
  	    node = doc->children;
  	    while ((node != NULL) && (node->last == NULL)) node = node->next;
  	    if (node != NULL) {
  		nb = xmlValidGetValidElements(node->last, NULL, list, 256);
  		if (nb < 0) {
  		    fprintf(stderr, "could not get valid list of elements\n");
  		} else if (nb == 0) {
  		    fprintf(stderr, "No element can be inserted under root\n");
  		} else {
  		    fprintf(stderr, "%d element types can be inserted under root:\n",
  		           nb);
  		    for (i = 0;i < nb;i++) {
  			 fprintf(stderr, "%s\n", (char *) list[i]);
  		    }
  		}
  	    }
  	}
      }else
  #endif /* LIBXML_VALID_ENABLED */
  #ifdef LIBXML_READER_ENABLED
      if (walker) {
          walkDoc(doc);
      }
  #endif /* LIBXML_READER_ENABLED */
  #ifdef LIBXML_OUTPUT_ENABLED
      if (noout == 0) {
          int ret;
  
  	/*
  	 * print it.
  	 */
  #ifdef LIBXML_DEBUG_ENABLED
  	if (!debug) {
  #endif
  	    if ((timing) && (!repeat)) {
  		startTimer();
  	    }
  #ifdef LIBXML_HTML_ENABLED
              if ((html) && (!xmlout)) {
  		if (compress) {
  		    htmlSaveFile(output ? output : "-", doc);
  		}
  		else if (encoding != NULL) {
  		    if (format == 1) {
  			htmlSaveFileFormat(output ? output : "-", doc, encoding, 1);
  		    }
  		    else {
  			htmlSaveFileFormat(output ? output : "-", doc, encoding, 0);
  		    }
  		}
  		else if (format == 1) {
  		    htmlSaveFileFormat(output ? output : "-", doc, NULL, 1);
  		}
  		else {
  		    FILE *out;
  		    if (output == NULL)
  			out = stdout;
  		    else {
  			out = fopen(output,"wb");
  		    }
  		    if (out != NULL) {
  			if (htmlDocDump(out, doc) < 0)
  			    progresult = XMLLINT_ERR_OUT;
  
  			if (output != NULL)
  			    fclose(out);
  		    } else {
  			fprintf(stderr, "failed to open %s\n", output);
  			progresult = XMLLINT_ERR_OUT;
  		    }
  		}
  		if ((timing) && (!repeat)) {
  		    endTimer("Saving");
  		}
  	    } else
  #endif
  #ifdef LIBXML_C14N_ENABLED
              if (canonical) {
  	        xmlChar *result = NULL;
  		int size;
  
  		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result);
  		if (size >= 0) {
  		    write(1, result, size);
  		    xmlFree(result);
  		} else {
  		    fprintf(stderr, "Failed to canonicalize\n");
  		    progresult = XMLLINT_ERR_OUT;
  		}
  	    } else if (canonical) {
  	        xmlChar *result = NULL;
  		int size;
  
  		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result);
  		if (size >= 0) {
  		    write(1, result, size);
  		    xmlFree(result);
  		} else {
  		    fprintf(stderr, "Failed to canonicalize\n");
  		    progresult = XMLLINT_ERR_OUT;
  		}
  	    } else
              if (exc_canonical) {
  	        xmlChar *result = NULL;
  		int size;
  
  		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result);
  		if (size >= 0) {
  		    write(1, result, size);
  		    xmlFree(result);
  		} else {
  		    fprintf(stderr, "Failed to canonicalize\n");
  		    progresult = XMLLINT_ERR_OUT;
  		}
  	    } else
  #endif
  #ifdef HAVE_SYS_MMAN_H
  	    if (memory) {
  		xmlChar *result;
  		int len;
  
  		if (encoding != NULL) {
  		    if (format == 1) {
  		        xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
  		    } else {
  			xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
  		    }
  		} else {
  		    if (format == 1)
  			xmlDocDumpFormatMemory(doc, &result, &len, 1);
  		    else
  			xmlDocDumpMemory(doc, &result, &len);
  		}
  		if (result == NULL) {
  		    fprintf(stderr, "Failed to save\n");
  		    progresult = XMLLINT_ERR_OUT;
  		} else {
  		    write(1, result, len);
  		    xmlFree(result);
  		}
  
  	    } else
  #endif /* HAVE_SYS_MMAN_H */
  	    if (compress) {
  		xmlSaveFile(output ? output : "-", doc);
  	    } else if (oldout) {
  	        if (encoding != NULL) {
  		    if (format == 1) {
  			ret = xmlSaveFormatFileEnc(output ? output : "-", doc,
  						   encoding, 1);
  		    }
  		    else {
  			ret = xmlSaveFileEnc(output ? output : "-", doc,
  			                     encoding);
  		    }
  		    if (ret < 0) {
  			fprintf(stderr, "failed save to %s\n",
  				output ? output : "-");
  			progresult = XMLLINT_ERR_OUT;
  		    }
  		} else if (format == 1) {
  		    ret = xmlSaveFormatFile(output ? output : "-", doc, 1);
  		    if (ret < 0) {
  			fprintf(stderr, "failed save to %s\n",
  				output ? output : "-");
  			progresult = XMLLINT_ERR_OUT;
  		    }
  		} else {
  		    FILE *out;
  		    if (output == NULL)
  			out = stdout;
  		    else {
  			out = fopen(output,"wb");
  		    }
  		    if (out != NULL) {
  			if (xmlDocDump(out, doc) < 0)
  			    progresult = XMLLINT_ERR_OUT;
  
  			if (output != NULL)
  			    fclose(out);
  		    } else {
  			fprintf(stderr, "failed to open %s\n", output);
  			progresult = XMLLINT_ERR_OUT;
  		    }
  		}
  	    } else {
  	        xmlSaveCtxtPtr ctxt;
  		int saveOpts = 0;
  
                  if (format == 1)
  		    saveOpts |= XML_SAVE_FORMAT;
                  else if (format == 2)
                      saveOpts |= XML_SAVE_WSNONSIG;
  
  #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
                  if (xmlout)
                      saveOpts |= XML_SAVE_AS_XML;
  #endif
  
  		if (output == NULL)
  		    ctxt = xmlSaveToFd(1, encoding, saveOpts);
  		else
  		    ctxt = xmlSaveToFilename(output, encoding, saveOpts);
  
  		if (ctxt != NULL) {
  		    if (xmlSaveDoc(ctxt, doc) < 0) {
  			fprintf(stderr, "failed save to %s\n",
  				output ? output : "-");
  			progresult = XMLLINT_ERR_OUT;
  		    }
  		    xmlSaveClose(ctxt);
  		} else {
  		    progresult = XMLLINT_ERR_OUT;
  		}
  	    }
  	    if ((timing) && (!repeat)) {
  		endTimer("Saving");
  	    }
  #ifdef LIBXML_DEBUG_ENABLED
  	} else {
  	    FILE *out;
  	    if (output == NULL)
  	        out = stdout;
  	    else {
  		out = fopen(output,"wb");
  	    }
  	    if (out != NULL) {
  		xmlDebugDumpDocument(out, doc);
  
  		if (output != NULL)
  		    fclose(out);
  	    } else {
  		fprintf(stderr, "failed to open %s\n", output);
  		progresult = XMLLINT_ERR_OUT;
  	    }
  	}
  #endif
      }
  #endif /* LIBXML_OUTPUT_ENABLED */
  
  #ifdef LIBXML_VALID_ENABLED
      /*
       * A posteriori validation test
       */
      if ((dtdvalid != NULL) || (dtdvalidfpi != NULL)) {
  	xmlDtdPtr dtd;
  
  	if ((timing) && (!repeat)) {
  	    startTimer();
  	}
  	if (dtdvalid != NULL)
  	    dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
  	else
  	    dtd = xmlParseDTD((const xmlChar *)dtdvalidfpi, NULL);
  	if ((timing) && (!repeat)) {
  	    endTimer("Parsing DTD");
  	}
  	if (dtd == NULL) {
  	    if (dtdvalid != NULL)
  		xmlGenericError(xmlGenericErrorContext,
  			"Could not parse DTD %s\n", dtdvalid);
  	    else
  		xmlGenericError(xmlGenericErrorContext,
  			"Could not parse DTD %s\n", dtdvalidfpi);
  	    progresult = XMLLINT_ERR_DTD;
  	} else {
  	    xmlValidCtxtPtr cvp;
  
  	    if ((cvp = xmlNewValidCtxt()) == NULL) {
  		xmlGenericError(xmlGenericErrorContext,
  			"Couldn't allocate validation context\n");
  		exit(-1);
  	    }
  	    cvp->userData = (void *) stderr;
  	    cvp->error    = (xmlValidityErrorFunc) fprintf;
  	    cvp->warning  = (xmlValidityWarningFunc) fprintf;
  
  	    if ((timing) && (!repeat)) {
  		startTimer();
  	    }
  	    if (!xmlValidateDtd(cvp, doc, dtd)) {
  		if (dtdvalid != NULL)
  		    xmlGenericError(xmlGenericErrorContext,
  			    "Document %s does not validate against %s\n",
  			    filename, dtdvalid);
  		else
  		    xmlGenericError(xmlGenericErrorContext,
  			    "Document %s does not validate against %s\n",
  			    filename, dtdvalidfpi);
  		progresult = XMLLINT_ERR_VALID;
  	    }
  	    if ((timing) && (!repeat)) {
  		endTimer("Validating against DTD");
  	    }
  	    xmlFreeValidCtxt(cvp);
  	    xmlFreeDtd(dtd);
  	}
      } else if (postvalid) {
  	xmlValidCtxtPtr cvp;
  
  	if ((cvp = xmlNewValidCtxt()) == NULL) {
  	    xmlGenericError(xmlGenericErrorContext,
  		    "Couldn't allocate validation context\n");
  	    exit(-1);
  	}
  
  	if ((timing) && (!repeat)) {
  	    startTimer();
  	}
  	cvp->userData = (void *) stderr;
  	cvp->error    = (xmlValidityErrorFunc) fprintf;
  	cvp->warning  = (xmlValidityWarningFunc) fprintf;
  	if (!xmlValidateDocument(cvp, doc)) {
  	    xmlGenericError(xmlGenericErrorContext,
  		    "Document %s does not validate\n", filename);
  	    progresult = XMLLINT_ERR_VALID;
  	}
  	if ((timing) && (!repeat)) {
  	    endTimer("Validating");
  	}
  	xmlFreeValidCtxt(cvp);
      }
  #endif /* LIBXML_VALID_ENABLED */
  #ifdef LIBXML_SCHEMATRON_ENABLED
      if (wxschematron != NULL) {
  	xmlSchematronValidCtxtPtr ctxt;
  	int ret;
  	int flag;
  
  	if ((timing) && (!repeat)) {
  	    startTimer();
  	}
  
  	if (debug)
  	    flag = XML_SCHEMATRON_OUT_XML;
  	else
  	    flag = XML_SCHEMATRON_OUT_TEXT;
  	if (noout)
  	    flag |= XML_SCHEMATRON_OUT_QUIET;
  	ctxt = xmlSchematronNewValidCtxt(wxschematron, flag);
  #if 0
  	xmlSchematronSetValidErrors(ctxt,
  		(xmlSchematronValidityErrorFunc) fprintf,
  		(xmlSchematronValidityWarningFunc) fprintf,
  		stderr);
  #endif
  	ret = xmlSchematronValidateDoc(ctxt, doc);
  	if (ret == 0) {
  	    fprintf(stderr, "%s validates\n", filename);
  	} else if (ret > 0) {
  	    fprintf(stderr, "%s fails to validate\n", filename);
  	    progresult = XMLLINT_ERR_VALID;
  	} else {
  	    fprintf(stderr, "%s validation generated an internal error\n",
  		   filename);
  	    progresult = XMLLINT_ERR_VALID;
  	}
  	xmlSchematronFreeValidCtxt(ctxt);
  	if ((timing) && (!repeat)) {
  	    endTimer("Validating");
  	}
      }
  #endif
  #ifdef LIBXML_SCHEMAS_ENABLED
      if (relaxngschemas != NULL) {
  	xmlRelaxNGValidCtxtPtr ctxt;
  	int ret;
  
  	if ((timing) && (!repeat)) {
  	    startTimer();
  	}
  
  	ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
  	xmlRelaxNGSetValidErrors(ctxt,
  		(xmlRelaxNGValidityErrorFunc) fprintf,
  		(xmlRelaxNGValidityWarningFunc) fprintf,
  		stderr);
  	ret = xmlRelaxNGValidateDoc(ctxt, doc);
  	if (ret == 0) {
  	    fprintf(stderr, "%s validates\n", filename);
  	} else if (ret > 0) {
  	    fprintf(stderr, "%s fails to validate\n", filename);
  	    progresult = XMLLINT_ERR_VALID;
  	} else {
  	    fprintf(stderr, "%s validation generated an internal error\n",
  		   filename);
  	    progresult = XMLLINT_ERR_VALID;
  	}
  	xmlRelaxNGFreeValidCtxt(ctxt);
  	if ((timing) && (!repeat)) {
  	    endTimer("Validating");
  	}
      } else if (wxschemas != NULL) {
  	xmlSchemaValidCtxtPtr ctxt;
  	int ret;
  
  	if ((timing) && (!repeat)) {
  	    startTimer();
  	}
  
  	ctxt = xmlSchemaNewValidCtxt(wxschemas);
  	xmlSchemaSetValidErrors(ctxt,
  		(xmlSchemaValidityErrorFunc) fprintf,
  		(xmlSchemaValidityWarningFunc) fprintf,
  		stderr);
  	ret = xmlSchemaValidateDoc(ctxt, doc);
  	if (ret == 0) {
  	    fprintf(stderr, "%s validates\n", filename);
  	} else if (ret > 0) {
  	    fprintf(stderr, "%s fails to validate\n", filename);
  	    progresult = XMLLINT_ERR_VALID;
  	} else {
  	    fprintf(stderr, "%s validation generated an internal error\n",
  		   filename);
  	    progresult = XMLLINT_ERR_VALID;
  	}
  	xmlSchemaFreeValidCtxt(ctxt);
  	if ((timing) && (!repeat)) {
  	    endTimer("Validating");
  	}
      }
  #endif
  
  #ifdef LIBXML_DEBUG_ENABLED
  #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
      if ((debugent) && (!html))
  	xmlDebugDumpEntities(stderr, doc);
  #endif
  #endif
  
      /*
       * free it.
       */
      if ((timing) && (!repeat)) {
  	startTimer();
      }
      xmlFreeDoc(doc);
      if ((timing) && (!repeat)) {
  	endTimer("Freeing");
      }
  }
  
  /************************************************************************
   *									*
   *			Usage and Main					*
   *									*
   ************************************************************************/
  
  static void showVersion(const char *name) {
      fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion);
      fprintf(stderr, "   compiled with: ");
      if (xmlHasFeature(XML_WITH_THREAD)) fprintf(stderr, "Threads ");
      if (xmlHasFeature(XML_WITH_TREE)) fprintf(stderr, "Tree ");
      if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(stderr, "Output ");
      if (xmlHasFeature(XML_WITH_PUSH)) fprintf(stderr, "Push ");
      if (xmlHasFeature(XML_WITH_READER)) fprintf(stderr, "Reader ");
      if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(stderr, "Patterns ");
      if (xmlHasFeature(XML_WITH_WRITER)) fprintf(stderr, "Writer ");
      if (xmlHasFeature(XML_WITH_SAX1)) fprintf(stderr, "SAXv1 ");
      if (xmlHasFeature(XML_WITH_FTP)) fprintf(stderr, "FTP ");
      if (xmlHasFeature(XML_WITH_HTTP)) fprintf(stderr, "HTTP ");
      if (xmlHasFeature(XML_WITH_VALID)) fprintf(stderr, "DTDValid ");
      if (xmlHasFeature(XML_WITH_HTML)) fprintf(stderr, "HTML ");
      if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(stderr, "Legacy ");
      if (xmlHasFeature(XML_WITH_C14N)) fprintf(stderr, "C14N ");
      if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(stderr, "Catalog ");
      if (xmlHasFeature(XML_WITH_XPATH)) fprintf(stderr, "XPath ");
      if (xmlHasFeature(XML_WITH_XPTR)) fprintf(stderr, "XPointer ");
      if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(stderr, "XInclude ");
      if (xmlHasFeature(XML_WITH_ICONV)) fprintf(stderr, "Iconv ");
      if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(stderr, "ISO8859X ");
      if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(stderr, "Unicode ");
      if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(stderr, "Regexps ");
      if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(stderr, "Automata ");
      if (xmlHasFeature(XML_WITH_EXPR)) fprintf(stderr, "Expr ");
      if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(stderr, "Schemas ");
      if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(stderr, "Schematron ");
      if (xmlHasFeature(XML_WITH_MODULES)) fprintf(stderr, "Modules ");
      if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(stderr, "Debug ");
      if (xmlHasFeature(XML_WITH_DEBUG_MEM)) fprintf(stderr, "MemDebug ");
      if (xmlHasFeature(XML_WITH_DEBUG_RUN)) fprintf(stderr, "RunDebug ");
      if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(stderr, "Zlib ");
      fprintf(stderr, "\n");
  }
  
  static void usage(const char *name) {
      printf("Usage : %s [options] XMLfiles ...\n", name);
  #ifdef LIBXML_OUTPUT_ENABLED
      printf("\tParse the XML files and output the result of the parsing\n");
  #else
      printf("\tParse the XML files\n");
  #endif /* LIBXML_OUTPUT_ENABLED */
      printf("\t--version : display the version of the XML library used\n");
  #ifdef LIBXML_DEBUG_ENABLED
      printf("\t--debug : dump a debug tree of the in-memory document\n");
      printf("\t--shell : run a navigating shell\n");
      printf("\t--debugent : debug the entities defined in the document\n");
  #else
  #ifdef LIBXML_READER_ENABLED
      printf("\t--debug : dump the nodes content when using --stream\n");
  #endif /* LIBXML_READER_ENABLED */
  #endif
  #ifdef LIBXML_TREE_ENABLED
      printf("\t--copy : used to test the internal copy implementation\n");
  #endif /* LIBXML_TREE_ENABLED */
      printf("\t--recover : output what was parsable on broken XML documents\n");
      printf("\t--huge : remove any internal arbitrary parser limits\n");
      printf("\t--noent : substitute entity references by their value\n");
      printf("\t--noout : don't output the result tree\n");
      printf("\t--path 'paths': provide a set of paths for resources\n");
      printf("\t--load-trace : print trace of all external entites loaded\n");
      printf("\t--nonet : refuse to fetch DTDs or entities over network\n");
      printf("\t--nocompact : do not generate compact text nodes\n");
      printf("\t--htmlout : output results as HTML\n");
      printf("\t--nowrap : do not put HTML doc wrapper\n");
  #ifdef LIBXML_VALID_ENABLED
      printf("\t--valid : validate the document in addition to std well-formed check\n");
      printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
      printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
      printf("\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n");
  #endif /* LIBXML_VALID_ENABLED */
      printf("\t--timing : print some timings\n");
      printf("\t--output file or -o file: save to a given file\n");
      printf("\t--repeat : repeat 100 times, for timing or profiling\n");
      printf("\t--insert : ad-hoc test for valid insertions\n");
  #ifdef LIBXML_OUTPUT_ENABLED
  #ifdef HAVE_ZLIB_H
      printf("\t--compress : turn on gzip compression of output\n");
  #endif
  #endif /* LIBXML_OUTPUT_ENABLED */
  #ifdef LIBXML_HTML_ENABLED
      printf("\t--html : use the HTML parser\n");
      printf("\t--xmlout : force to use the XML serializer when using --html\n");
      printf("\t--nodefdtd : do not default HTML doctype\n");
  #endif
  #ifdef LIBXML_PUSH_ENABLED
      printf("\t--push : use the push mode of the parser\n");
  #endif /* LIBXML_PUSH_ENABLED */
  #ifdef HAVE_SYS_MMAN_H
      printf("\t--memory : parse from memory\n");
  #endif
      printf("\t--maxmem nbbytes : limits memory allocation to nbbytes bytes\n");
      printf("\t--nowarning : do not emit warnings from parser/validator\n");
      printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
      printf("\t--nocdata : replace cdata section with text nodes\n");
  #ifdef LIBXML_OUTPUT_ENABLED
      printf("\t--format : reformat/reindent the input\n");
      printf("\t--encode encoding : output in the given encoding\n");
      printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
      printf("\t--pretty STYLE : pretty-print in a particular style\n");
      printf("\t                 0 Do not pretty print\n");
      printf("\t                 1 Format the XML content, as --format\n");
      printf("\t                 2 Add whitespace inside tags, preserving content\n");
  #endif /* LIBXML_OUTPUT_ENABLED */
      printf("\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
      printf("\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
      printf("\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
  #ifdef LIBXML_C14N_ENABLED
  #endif /* LIBXML_C14N_ENABLED */
      printf("\t--nsclean : remove redundant namespace declarations\n");
      printf("\t--testIO : test user I/O support\n");
  #ifdef LIBXML_CATALOG_ENABLED
      printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
      printf("\t             otherwise XML Catalogs starting from \n");
      printf("\t         %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
      printf("\t--nocatalogs: deactivate all catalogs\n");
  #endif
      printf("\t--auto : generate a small doc on the fly\n");
  #ifdef LIBXML_XINCLUDE_ENABLED
      printf("\t--xinclude : do XInclude processing\n");
      printf("\t--noxincludenode : same but do not generate XInclude nodes\n");
      printf("\t--nofixup-base-uris : do not fixup xml:base uris\n");
  #endif
      printf("\t--loaddtd : fetch external DTD\n");
      printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
  #ifdef LIBXML_READER_ENABLED
      printf("\t--stream : use the streaming interface to process very large files\n");
      printf("\t--walker : create a reader and walk though the resulting doc\n");
  #endif /* LIBXML_READER_ENABLED */
  #ifdef LIBXML_PATTERN_ENABLED
      printf("\t--pattern pattern_value : test the pattern support\n");
  #endif
      printf("\t--chkregister : verify the node registration code\n");
  #ifdef LIBXML_SCHEMAS_ENABLED
      printf("\t--relaxng schema : do RelaxNG validation against the schema\n");
      printf("\t--schema schema : do validation against the WXS schema\n");
  #endif
  #ifdef LIBXML_SCHEMATRON_ENABLED
      printf("\t--schematron schema : do validation against a schematron\n");
  #endif
  #ifdef LIBXML_SAX1_ENABLED
      printf("\t--sax1: use the old SAX1 interfaces for processing\n");
  #endif
      printf("\t--sax: do not build a tree but work just at the SAX level\n");
      printf("\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
  #ifdef LIBXML_XPATH_ENABLED
      printf("\t--xpath expr: evaluate the XPath expression, inply --noout\n");
  #endif
  
      printf("\nLibxml project home page: http://xmlsoft.org/\n");
      printf("To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
  }
  
  static void registerNode(xmlNodePtr node)
  {
      node->_private = malloc(sizeof(long));
      *(long*)node->_private = (long) 0x81726354;
      nbregister++;
  }
  
  static void deregisterNode(xmlNodePtr node)
  {
      assert(node->_private != NULL);
      assert(*(long*)node->_private == (long) 0x81726354);
      free(node->_private);
      nbregister--;
  }
  
  int
  main(int argc, char **argv) {
      int i, acount;
      int files = 0;
      int version = 0;
      const char* indent;
  
      if (argc <= 1) {
  	usage(argv[0]);
  	return(1);
      }
      LIBXML_TEST_VERSION
      for (i = 1; i < argc ; i++) {
  	if (!strcmp(argv[i], "-"))
  	    break;
  
  	if (argv[i][0] != '-')
  	    continue;
  	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
  	    debug++;
  	else
  #ifdef LIBXML_DEBUG_ENABLED
  	if ((!strcmp(argv[i], "-shell")) ||
  	         (!strcmp(argv[i], "--shell"))) {
  	    shell++;
              noout = 1;
          } else
  #endif
  #ifdef LIBXML_TREE_ENABLED
  	if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
  	    copy++;
  	else
  #endif /* LIBXML_TREE_ENABLED */
  	if ((!strcmp(argv[i], "-recover")) ||
  	         (!strcmp(argv[i], "--recover"))) {
  	    recovery++;
  	    options |= XML_PARSE_RECOVER;
  	} else if ((!strcmp(argv[i], "-huge")) ||
  	         (!strcmp(argv[i], "--huge"))) {
  	    options |= XML_PARSE_HUGE;
  	} else if ((!strcmp(argv[i], "-noent")) ||
  	         (!strcmp(argv[i], "--noent"))) {
  	    noent++;
  	    options |= XML_PARSE_NOENT;
  	} else if ((!strcmp(argv[i], "-nsclean")) ||
  	         (!strcmp(argv[i], "--nsclean"))) {
  	    options |= XML_PARSE_NSCLEAN;
  	} else if ((!strcmp(argv[i], "-nocdata")) ||
  	         (!strcmp(argv[i], "--nocdata"))) {
  	    options |= XML_PARSE_NOCDATA;
  	} else if ((!strcmp(argv[i], "-nodict")) ||
  	         (!strcmp(argv[i], "--nodict"))) {
  	    options |= XML_PARSE_NODICT;
  	} else if ((!strcmp(argv[i], "-version")) ||
  	         (!strcmp(argv[i], "--version"))) {
  	    showVersion(argv[0]);
  	    version = 1;
  	} else if ((!strcmp(argv[i], "-noout")) ||
  	         (!strcmp(argv[i], "--noout")))
  	    noout++;
  #ifdef LIBXML_OUTPUT_ENABLED
  	else if ((!strcmp(argv[i], "-o")) ||
  	         (!strcmp(argv[i], "-output")) ||
  	         (!strcmp(argv[i], "--output"))) {
  	    i++;
  	    output = argv[i];
  	}
  #endif /* LIBXML_OUTPUT_ENABLED */
  	else if ((!strcmp(argv[i], "-htmlout")) ||
  	         (!strcmp(argv[i], "--htmlout")))
  	    htmlout++;
  	else if ((!strcmp(argv[i], "-nowrap")) ||
  	         (!strcmp(argv[i], "--nowrap")))
  	    nowrap++;
  #ifdef LIBXML_HTML_ENABLED
  	else if ((!strcmp(argv[i], "-html")) ||
  	         (!strcmp(argv[i], "--html"))) {
  	    html++;
          }
  	else if ((!strcmp(argv[i], "-xmlout")) ||
  	         (!strcmp(argv[i], "--xmlout"))) {
  	    xmlout++;
  	} else if ((!strcmp(argv[i], "-nodefdtd")) ||
  	         (!strcmp(argv[i], "--nodefdtd"))) {
              nodefdtd++;
  	    options |= HTML_PARSE_NODEFDTD;
          }
  #endif /* LIBXML_HTML_ENABLED */
  	else if ((!strcmp(argv[i], "-loaddtd")) ||
  	         (!strcmp(argv[i], "--loaddtd"))) {
  	    loaddtd++;
  	    options |= XML_PARSE_DTDLOAD;
  	} else if ((!strcmp(argv[i], "-dtdattr")) ||
  	         (!strcmp(argv[i], "--dtdattr"))) {
  	    loaddtd++;
  	    dtdattrs++;
  	    options |= XML_PARSE_DTDATTR;
  	}
  #ifdef LIBXML_VALID_ENABLED
  	else if ((!strcmp(argv[i], "-valid")) ||
  	         (!strcmp(argv[i], "--valid"))) {
  	    valid++;
  	    options |= XML_PARSE_DTDVALID;
  	} else if ((!strcmp(argv[i], "-postvalid")) ||
  	         (!strcmp(argv[i], "--postvalid"))) {
  	    postvalid++;
  	    loaddtd++;
  	    options |= XML_PARSE_DTDLOAD;
  	} else if ((!strcmp(argv[i], "-dtdvalid")) ||
  	         (!strcmp(argv[i], "--dtdvalid"))) {
  	    i++;
  	    dtdvalid = argv[i];
  	    loaddtd++;
  	    options |= XML_PARSE_DTDLOAD;
  	} else if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
  	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
  	    i++;
  	    dtdvalidfpi = argv[i];
  	    loaddtd++;
  	    options |= XML_PARSE_DTDLOAD;
          }
  #endif /* LIBXML_VALID_ENABLED */
  	else if ((!strcmp(argv[i], "-dropdtd")) ||
  	         (!strcmp(argv[i], "--dropdtd")))
  	    dropdtd++;
  	else if ((!strcmp(argv[i], "-insert")) ||
  	         (!strcmp(argv[i], "--insert")))
  	    insert++;
  	else if ((!strcmp(argv[i], "-timing")) ||
  	         (!strcmp(argv[i], "--timing")))
  	    timing++;
  	else if ((!strcmp(argv[i], "-auto")) ||
  	         (!strcmp(argv[i], "--auto")))
  	    generate++;
  	else if ((!strcmp(argv[i], "-repeat")) ||
  	         (!strcmp(argv[i], "--repeat"))) {
  	    if (repeat)
  	        repeat *= 10;
  	    else
  	        repeat = 100;
  	}
  #ifdef LIBXML_PUSH_ENABLED
  	else if ((!strcmp(argv[i], "-push")) ||
  	         (!strcmp(argv[i], "--push")))
  	    push++;
  #endif /* LIBXML_PUSH_ENABLED */
  #ifdef HAVE_SYS_MMAN_H
  	else if ((!strcmp(argv[i], "-memory")) ||
  	         (!strcmp(argv[i], "--memory")))
  	    memory++;
  #endif
  	else if ((!strcmp(argv[i], "-testIO")) ||
  	         (!strcmp(argv[i], "--testIO")))
  	    testIO++;
  #ifdef LIBXML_XINCLUDE_ENABLED
  	else if ((!strcmp(argv[i], "-xinclude")) ||
  	         (!strcmp(argv[i], "--xinclude"))) {
  	    xinclude++;
  	    options |= XML_PARSE_XINCLUDE;
  	}
  	else if ((!strcmp(argv[i], "-noxincludenode")) ||
  	         (!strcmp(argv[i], "--noxincludenode"))) {
  	    xinclude++;
  	    options |= XML_PARSE_XINCLUDE;
  	    options |= XML_PARSE_NOXINCNODE;
  	}
  	else if ((!strcmp(argv[i], "-nofixup-base-uris")) ||
  	         (!strcmp(argv[i], "--nofixup-base-uris"))) {
  	    xinclude++;
  	    options |= XML_PARSE_XINCLUDE;
  	    options |= XML_PARSE_NOBASEFIX;
  	}
  #endif
  #ifdef LIBXML_OUTPUT_ENABLED
  #ifdef HAVE_ZLIB_H
  	else if ((!strcmp(argv[i], "-compress")) ||
  	         (!strcmp(argv[i], "--compress"))) {
  	    compress++;
  	    xmlSetCompressMode(9);
          }
  #endif
  #endif /* LIBXML_OUTPUT_ENABLED */
  	else if ((!strcmp(argv[i], "-nowarning")) ||
  	         (!strcmp(argv[i], "--nowarning"))) {
  	    xmlGetWarningsDefaultValue = 0;
  	    xmlPedanticParserDefault(0);
  	    options |= XML_PARSE_NOWARNING;
          }
  	else if ((!strcmp(argv[i], "-pedantic")) ||
  	         (!strcmp(argv[i], "--pedantic"))) {
  	    xmlGetWarningsDefaultValue = 1;
  	    xmlPedanticParserDefault(1);
  	    options |= XML_PARSE_PEDANTIC;
          }
  #ifdef LIBXML_DEBUG_ENABLED
  	else if ((!strcmp(argv[i], "-debugent")) ||
  		 (!strcmp(argv[i], "--debugent"))) {
  	    debugent++;
  	    xmlParserDebugEntities = 1;
  	}
  #endif
  #ifdef LIBXML_C14N_ENABLED
  	else if ((!strcmp(argv[i], "-c14n")) ||
  		 (!strcmp(argv[i], "--c14n"))) {
  	    canonical++;
  	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
  	}
  	else if ((!strcmp(argv[i], "-c14n11")) ||
  		 (!strcmp(argv[i], "--c14n11"))) {
  	    canonical_11++;
  	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
  	}
  	else if ((!strcmp(argv[i], "-exc-c14n")) ||
  		 (!strcmp(argv[i], "--exc-c14n"))) {
  	    exc_canonical++;
  	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
  	}
  #endif
  #ifdef LIBXML_CATALOG_ENABLED
  	else if ((!strcmp(argv[i], "-catalogs")) ||
  		 (!strcmp(argv[i], "--catalogs"))) {
  	    catalogs++;
  	} else if ((!strcmp(argv[i], "-nocatalogs")) ||
  		 (!strcmp(argv[i], "--nocatalogs"))) {
  	    nocatalogs++;
  	}
  #endif
  	else if ((!strcmp(argv[i], "-encode")) ||
  	         (!strcmp(argv[i], "--encode"))) {
  	    i++;
  	    encoding = argv[i];
  	    /*
  	     * OK it's for testing purposes
  	     */
  	    xmlAddEncodingAlias("UTF-8", "DVEnc");
          }
  	else if ((!strcmp(argv[i], "-noblanks")) ||
  	         (!strcmp(argv[i], "--noblanks"))) {
  	     noblanks++;
  	     xmlKeepBlanksDefault(0);
          }
  	else if ((!strcmp(argv[i], "-maxmem")) ||
  	         (!strcmp(argv[i], "--maxmem"))) {
  	     i++;
  	     if (sscanf(argv[i], "%d", &maxmem) == 1) {
  	         xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc,
  		             myStrdupFunc);
  	     } else {
  	         maxmem = 0;
  	     }
          }
  	else if ((!strcmp(argv[i], "-format")) ||
  	         (!strcmp(argv[i], "--format"))) {
  	     noblanks++;
  #ifdef LIBXML_OUTPUT_ENABLED
  	     format = 1;
  #endif /* LIBXML_OUTPUT_ENABLED */
  	     xmlKeepBlanksDefault(0);
  	}
  	else if ((!strcmp(argv[i], "-pretty")) ||
  	         (!strcmp(argv[i], "--pretty"))) {
  	     i++;
  #ifdef LIBXML_OUTPUT_ENABLED
  	     format = atoi(argv[i]);
  #endif /* LIBXML_OUTPUT_ENABLED */
  	     if (format == 1) {
  	         noblanks++;
  	         xmlKeepBlanksDefault(0);
  	     }
  	}
  #ifdef LIBXML_READER_ENABLED
  	else if ((!strcmp(argv[i], "-stream")) ||
  	         (!strcmp(argv[i], "--stream"))) {
  	     stream++;
  	}
  	else if ((!strcmp(argv[i], "-walker")) ||
  	         (!strcmp(argv[i], "--walker"))) {
  	     walker++;
               noout++;
  	}
  #endif /* LIBXML_READER_ENABLED */
  #ifdef LIBXML_SAX1_ENABLED
  	else if ((!strcmp(argv[i], "-sax1")) ||
  	         (!strcmp(argv[i], "--sax1"))) {
  	    sax1++;
  	    options |= XML_PARSE_SAX1;
  	}
  #endif /* LIBXML_SAX1_ENABLED */
  	else if ((!strcmp(argv[i], "-sax")) ||
  	         (!strcmp(argv[i], "--sax"))) {
  	    sax++;
  	}
  	else if ((!strcmp(argv[i], "-chkregister")) ||
  	         (!strcmp(argv[i], "--chkregister"))) {
  	    chkregister++;
  #ifdef LIBXML_SCHEMAS_ENABLED
  	} else if ((!strcmp(argv[i], "-relaxng")) ||
  	         (!strcmp(argv[i], "--relaxng"))) {
  	    i++;
  	    relaxng = argv[i];
  	    noent++;
  	    options |= XML_PARSE_NOENT;
  	} else if ((!strcmp(argv[i], "-schema")) ||
  	         (!strcmp(argv[i], "--schema"))) {
  	    i++;
  	    schema = argv[i];
  	    noent++;
  #endif
  #ifdef LIBXML_SCHEMATRON_ENABLED
  	} else if ((!strcmp(argv[i], "-schematron")) ||
  	         (!strcmp(argv[i], "--schematron"))) {
  	    i++;
  	    schematron = argv[i];
  	    noent++;
  #endif
          } else if ((!strcmp(argv[i], "-nonet")) ||
                     (!strcmp(argv[i], "--nonet"))) {
  	    options |= XML_PARSE_NONET;
  	    xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
          } else if ((!strcmp(argv[i], "-nocompact")) ||
                     (!strcmp(argv[i], "--nocompact"))) {
  	    options &= ~XML_PARSE_COMPACT;
  	} else if ((!strcmp(argv[i], "-load-trace")) ||
  	           (!strcmp(argv[i], "--load-trace"))) {
  	    load_trace++;
          } else if ((!strcmp(argv[i], "-path")) ||
                     (!strcmp(argv[i], "--path"))) {
  	    i++;
  	    parsePath(BAD_CAST argv[i]);
  #ifdef LIBXML_PATTERN_ENABLED
          } else if ((!strcmp(argv[i], "-pattern")) ||
                     (!strcmp(argv[i], "--pattern"))) {
  	    i++;
  	    pattern = argv[i];
  #endif
  #ifdef LIBXML_XPATH_ENABLED
          } else if ((!strcmp(argv[i], "-xpath")) ||
                     (!strcmp(argv[i], "--xpath"))) {
  	    i++;
  	    noout++;
  	    xpathquery = argv[i];
  #endif
  	} else if ((!strcmp(argv[i], "-oldxml10")) ||
  	           (!strcmp(argv[i], "--oldxml10"))) {
  	    oldxml10++;
  	    options |= XML_PARSE_OLD10;
  	} else {
  	    fprintf(stderr, "Unknown option %s\n", argv[i]);
  	    usage(argv[0]);
  	    return(1);
  	}
      }
  
  #ifdef LIBXML_CATALOG_ENABLED
      if (nocatalogs == 0) {
  	if (catalogs) {
  	    const char *catal;
  
  	    catal = getenv("SGML_CATALOG_FILES");
  	    if (catal != NULL) {
  		xmlLoadCatalogs(catal);
  	    } else {
  		fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
  	    }
  	}
      }
  #endif
  
  #ifdef LIBXML_SAX1_ENABLED
      if (sax1)
          xmlSAXDefaultVersion(1);
      else
          xmlSAXDefaultVersion(2);
  #endif /* LIBXML_SAX1_ENABLED */
  
      if (chkregister) {
  	xmlRegisterNodeDefault(registerNode);
  	xmlDeregisterNodeDefault(deregisterNode);
      }
  
      indent = getenv("XMLLINT_INDENT");
      if(indent != NULL) {
  	xmlTreeIndentString = indent;
      }
  
  
      defaultEntityLoader = xmlGetExternalEntityLoader();
      xmlSetExternalEntityLoader(xmllintExternalEntityLoader);
  
      xmlLineNumbersDefault(1);
      if (loaddtd != 0)
  	xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
      if (dtdattrs)
  	xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
      if (noent != 0) xmlSubstituteEntitiesDefault(1);
  #ifdef LIBXML_VALID_ENABLED
      if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
  #endif /* LIBXML_VALID_ENABLED */
      if ((htmlout) && (!nowrap)) {
  	xmlGenericError(xmlGenericErrorContext,
           "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
  	xmlGenericError(xmlGenericErrorContext,
  		"\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
  	xmlGenericError(xmlGenericErrorContext,
  	 "<html><head><title>%s output</title></head>\n",
  		argv[0]);
  	xmlGenericError(xmlGenericErrorContext,
  	 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
  		argv[0]);
      }
  
  #ifdef LIBXML_SCHEMATRON_ENABLED
      if ((schematron != NULL) && (sax == 0)
  #ifdef LIBXML_READER_ENABLED
          && (stream == 0)
  #endif /* LIBXML_READER_ENABLED */
  	) {
  	xmlSchematronParserCtxtPtr ctxt;
  
          /* forces loading the DTDs */
          xmlLoadExtDtdDefaultValue |= 1;
  	options |= XML_PARSE_DTDLOAD;
  	if (timing) {
  	    startTimer();
  	}
  	ctxt = xmlSchematronNewParserCtxt(schematron);
  #if 0
  	xmlSchematronSetParserErrors(ctxt,
  		(xmlSchematronValidityErrorFunc) fprintf,
  		(xmlSchematronValidityWarningFunc) fprintf,
  		stderr);
  #endif
  	wxschematron = xmlSchematronParse(ctxt);
  	if (wxschematron == NULL) {
  	    xmlGenericError(xmlGenericErrorContext,
  		    "Schematron schema %s failed to compile\n", schematron);
              progresult = XMLLINT_ERR_SCHEMACOMP;
  	    schematron = NULL;
  	}
  	xmlSchematronFreeParserCtxt(ctxt);
  	if (timing) {
  	    endTimer("Compiling the schemas");
  	}
      }
  #endif
  #ifdef LIBXML_SCHEMAS_ENABLED
      if ((relaxng != NULL) && (sax == 0)
  #ifdef LIBXML_READER_ENABLED
          && (stream == 0)
  #endif /* LIBXML_READER_ENABLED */
  	) {
  	xmlRelaxNGParserCtxtPtr ctxt;
  
          /* forces loading the DTDs */
          xmlLoadExtDtdDefaultValue |= 1;
  	options |= XML_PARSE_DTDLOAD;
  	if (timing) {
  	    startTimer();
  	}
  	ctxt = xmlRelaxNGNewParserCtxt(relaxng);
  	xmlRelaxNGSetParserErrors(ctxt,
  		(xmlRelaxNGValidityErrorFunc) fprintf,
  		(xmlRelaxNGValidityWarningFunc) fprintf,
  		stderr);
  	relaxngschemas = xmlRelaxNGParse(ctxt);
  	if (relaxngschemas == NULL) {
  	    xmlGenericError(xmlGenericErrorContext,
  		    "Relax-NG schema %s failed to compile\n", relaxng);
              progresult = XMLLINT_ERR_SCHEMACOMP;
  	    relaxng = NULL;
  	}
  	xmlRelaxNGFreeParserCtxt(ctxt);
  	if (timing) {
  	    endTimer("Compiling the schemas");
  	}
      } else if ((schema != NULL)
  #ifdef LIBXML_READER_ENABLED
  		&& (stream == 0)
  #endif
  	) {
  	xmlSchemaParserCtxtPtr ctxt;
  
  	if (timing) {
  	    startTimer();
  	}
  	ctxt = xmlSchemaNewParserCtxt(schema);
  	xmlSchemaSetParserErrors(ctxt,
  		(xmlSchemaValidityErrorFunc) fprintf,
  		(xmlSchemaValidityWarningFunc) fprintf,
  		stderr);
  	wxschemas = xmlSchemaParse(ctxt);
  	if (wxschemas == NULL) {
  	    xmlGenericError(xmlGenericErrorContext,
  		    "WXS schema %s failed to compile\n", schema);
              progresult = XMLLINT_ERR_SCHEMACOMP;
  	    schema = NULL;
  	}
  	xmlSchemaFreeParserCtxt(ctxt);
  	if (timing) {
  	    endTimer("Compiling the schemas");
  	}
      }
  #endif /* LIBXML_SCHEMAS_ENABLED */
  #ifdef LIBXML_PATTERN_ENABLED
      if ((pattern != NULL)
  #ifdef LIBXML_READER_ENABLED
          && (walker == 0)
  #endif
  	) {
          patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
  	if (patternc == NULL) {
  	    xmlGenericError(xmlGenericErrorContext,
  		    "Pattern %s failed to compile\n", pattern);
              progresult = XMLLINT_ERR_SCHEMAPAT;
  	    pattern = NULL;
  	}
      }
  #endif /* LIBXML_PATTERN_ENABLED */
      for (i = 1; i < argc ; i++) {
  	if ((!strcmp(argv[i], "-encode")) ||
  	         (!strcmp(argv[i], "--encode"))) {
  	    i++;
  	    continue;
          } else if ((!strcmp(argv[i], "-o")) ||
                     (!strcmp(argv[i], "-output")) ||
                     (!strcmp(argv[i], "--output"))) {
              i++;
  	    continue;
          }
  #ifdef LIBXML_VALID_ENABLED
  	if ((!strcmp(argv[i], "-dtdvalid")) ||
  	         (!strcmp(argv[i], "--dtdvalid"))) {
  	    i++;
  	    continue;
          }
  	if ((!strcmp(argv[i], "-path")) ||
                     (!strcmp(argv[i], "--path"))) {
              i++;
  	    continue;
          }
  	if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
  	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
  	    i++;
  	    continue;
          }
  #endif /* LIBXML_VALID_ENABLED */
  	if ((!strcmp(argv[i], "-relaxng")) ||
  	         (!strcmp(argv[i], "--relaxng"))) {
  	    i++;
  	    continue;
          }
  	if ((!strcmp(argv[i], "-maxmem")) ||
  	         (!strcmp(argv[i], "--maxmem"))) {
  	    i++;
  	    continue;
          }
  	if ((!strcmp(argv[i], "-pretty")) ||
  	         (!strcmp(argv[i], "--pretty"))) {
  	    i++;
  	    continue;
          }
  	if ((!strcmp(argv[i], "-schema")) ||
  	         (!strcmp(argv[i], "--schema"))) {
  	    i++;
  	    continue;
          }
  	if ((!strcmp(argv[i], "-schematron")) ||
  	         (!strcmp(argv[i], "--schematron"))) {
  	    i++;
  	    continue;
          }
  #ifdef LIBXML_PATTERN_ENABLED
          if ((!strcmp(argv[i], "-pattern")) ||
  	    (!strcmp(argv[i], "--pattern"))) {
  	    i++;
  	    continue;
  	}
  #endif
  #ifdef LIBXML_XPATH_ENABLED
          if ((!strcmp(argv[i], "-xpath")) ||
  	    (!strcmp(argv[i], "--xpath"))) {
  	    i++;
  	    continue;
  	}
  #endif
  	if ((timing) && (repeat))
  	    startTimer();
  	/* Remember file names.  "-" means stdin.  <sven@zen.org> */
  	if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
  	    if (repeat) {
  		xmlParserCtxtPtr ctxt = NULL;
  
  		for (acount = 0;acount < repeat;acount++) {
  #ifdef LIBXML_READER_ENABLED
  		    if (stream != 0) {
  			streamFile(argv[i]);
  		    } else {
  #endif /* LIBXML_READER_ENABLED */
                          if (sax) {
  			    testSAX(argv[i]);
  			} else {
  			    if (ctxt == NULL)
  				ctxt = xmlNewParserCtxt();
  			    parseAndPrintFile(argv[i], ctxt);
  			}
  #ifdef LIBXML_READER_ENABLED
  		    }
  #endif /* LIBXML_READER_ENABLED */
  		}
  		if (ctxt != NULL)
  		    xmlFreeParserCtxt(ctxt);
  	    } else {
  		nbregister = 0;
  
  #ifdef LIBXML_READER_ENABLED
  		if (stream != 0)
  		    streamFile(argv[i]);
  		else
  #endif /* LIBXML_READER_ENABLED */
                  if (sax) {
  		    testSAX(argv[i]);
  		} else {
  		    parseAndPrintFile(argv[i], NULL);
  		}
  
                  if ((chkregister) && (nbregister != 0)) {
  		    fprintf(stderr, "Registration count off: %d\n", nbregister);
  		    progresult = XMLLINT_ERR_RDREGIS;
  		}
  	    }
  	    files ++;
  	    if ((timing) && (repeat)) {
  		endTimer("%d iterations", repeat);
  	    }
  	}
      }
      if (generate)
  	parseAndPrintFile(NULL, NULL);
      if ((htmlout) && (!nowrap)) {
  	xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
      }
      if ((files == 0) && (!generate) && (version == 0)) {
  	usage(argv[0]);
      }
  #ifdef LIBXML_SCHEMATRON_ENABLED
      if (wxschematron != NULL)
  	xmlSchematronFree(wxschematron);
  #endif
  #ifdef LIBXML_SCHEMAS_ENABLED
      if (relaxngschemas != NULL)
  	xmlRelaxNGFree(relaxngschemas);
      if (wxschemas != NULL)
  	xmlSchemaFree(wxschemas);
      xmlRelaxNGCleanupTypes();
  #endif
  #ifdef LIBXML_PATTERN_ENABLED
      if (patternc != NULL)
          xmlFreePattern(patternc);
  #endif
      xmlCleanupParser();
      xmlMemoryDump();
  
      return(progresult);
  }
  
  