Home | History | Annotate | Download | only in libxml2
      1 /*
      2  * xmllint.c : a small tester program for XML input.
      3  *
      4  * See Copyright for the status of this software.
      5  *
      6  * daniel (at) veillard.com
      7  */
      8 
      9 #include "libxml.h"
     10 
     11 #include <string.h>
     12 #include <stdarg.h>
     13 #include <assert.h>
     14 
     15 #ifdef HAVE_SYS_TIME_H
     16 #include <sys/time.h>
     17 #endif
     18 #ifdef HAVE_TIME_H
     19 #include <time.h>
     20 #endif
     21 
     22 #ifdef HAVE_SYS_TIMEB_H
     23 #include <sys/timeb.h>
     24 #endif
     25 
     26 #ifdef HAVE_SYS_TYPES_H
     27 #include <sys/types.h>
     28 #endif
     29 #ifdef HAVE_SYS_STAT_H
     30 #include <sys/stat.h>
     31 #endif
     32 #ifdef HAVE_FCNTL_H
     33 #include <fcntl.h>
     34 #endif
     35 #ifdef HAVE_UNISTD_H
     36 #include <unistd.h>
     37 #endif
     38 #ifdef HAVE_SYS_MMAN_H
     39 #include <sys/mman.h>
     40 /* seems needed for Solaris */
     41 #ifndef MAP_FAILED
     42 #define MAP_FAILED ((void *) -1)
     43 #endif
     44 #endif
     45 #ifdef HAVE_STDLIB_H
     46 #include <stdlib.h>
     47 #endif
     48 #ifdef HAVE_LIBREADLINE
     49 #include <readline/readline.h>
     50 #ifdef HAVE_LIBHISTORY
     51 #include <readline/history.h>
     52 #endif
     53 #endif
     54 
     55 #include <libxml/xmlmemory.h>
     56 #include <libxml/parser.h>
     57 #include <libxml/parserInternals.h>
     58 #include <libxml/HTMLparser.h>
     59 #include <libxml/HTMLtree.h>
     60 #include <libxml/tree.h>
     61 #include <libxml/xpath.h>
     62 #include <libxml/debugXML.h>
     63 #include <libxml/xmlerror.h>
     64 #ifdef LIBXML_XINCLUDE_ENABLED
     65 #include <libxml/xinclude.h>
     66 #endif
     67 #ifdef LIBXML_CATALOG_ENABLED
     68 #include <libxml/catalog.h>
     69 #endif
     70 #include <libxml/globals.h>
     71 #include <libxml/xmlreader.h>
     72 #ifdef LIBXML_SCHEMATRON_ENABLED
     73 #include <libxml/schematron.h>
     74 #endif
     75 #ifdef LIBXML_SCHEMAS_ENABLED
     76 #include <libxml/relaxng.h>
     77 #include <libxml/xmlschemas.h>
     78 #endif
     79 #ifdef LIBXML_PATTERN_ENABLED
     80 #include <libxml/pattern.h>
     81 #endif
     82 #ifdef LIBXML_C14N_ENABLED
     83 #include <libxml/c14n.h>
     84 #endif
     85 #ifdef LIBXML_OUTPUT_ENABLED
     86 #include <libxml/xmlsave.h>
     87 #endif
     88 
     89 #ifndef XML_XML_DEFAULT_CATALOG
     90 #define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
     91 #endif
     92 
     93 typedef enum {
     94     XMLLINT_RETURN_OK = 0,	/* No error */
     95     XMLLINT_ERR_UNCLASS = 1,	/* Unclassified */
     96     XMLLINT_ERR_DTD = 2,	/* Error in DTD */
     97     XMLLINT_ERR_VALID = 3,	/* Validation error */
     98     XMLLINT_ERR_RDFILE = 4,	/* CtxtReadFile error */
     99     XMLLINT_ERR_SCHEMACOMP = 5,	/* Schema compilation */
    100     XMLLINT_ERR_OUT = 6,	/* Error writing output */
    101     XMLLINT_ERR_SCHEMAPAT = 7,	/* Error in schema pattern */
    102     XMLLINT_ERR_RDREGIS = 8,	/* Error in Reader registration */
    103     XMLLINT_ERR_MEM = 9,	/* Out of memory error */
    104     XMLLINT_ERR_XPATH = 10	/* XPath evaluation error */
    105 } xmllintReturnCode;
    106 #ifdef LIBXML_DEBUG_ENABLED
    107 static int shell = 0;
    108 static int debugent = 0;
    109 #endif
    110 static int debug = 0;
    111 static int maxmem = 0;
    112 #ifdef LIBXML_TREE_ENABLED
    113 static int copy = 0;
    114 #endif /* LIBXML_TREE_ENABLED */
    115 static int recovery = 0;
    116 static int noent = 0;
    117 static int noenc = 0;
    118 static int noblanks = 0;
    119 static int noout = 0;
    120 static int nowrap = 0;
    121 #ifdef LIBXML_OUTPUT_ENABLED
    122 static int format = 0;
    123 static const char *output = NULL;
    124 static int compress = 0;
    125 static int oldout = 0;
    126 #endif /* LIBXML_OUTPUT_ENABLED */
    127 #ifdef LIBXML_VALID_ENABLED
    128 static int valid = 0;
    129 static int postvalid = 0;
    130 static char * dtdvalid = NULL;
    131 static char * dtdvalidfpi = NULL;
    132 #endif
    133 #ifdef LIBXML_SCHEMAS_ENABLED
    134 static char * relaxng = NULL;
    135 static xmlRelaxNGPtr relaxngschemas = NULL;
    136 static char * schema = NULL;
    137 static xmlSchemaPtr wxschemas = NULL;
    138 #endif
    139 #ifdef LIBXML_SCHEMATRON_ENABLED
    140 static char * schematron = NULL;
    141 static xmlSchematronPtr wxschematron = NULL;
    142 #endif
    143 static int repeat = 0;
    144 static int insert = 0;
    145 #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
    146 static int html = 0;
    147 static int xmlout = 0;
    148 #endif
    149 static int htmlout = 0;
    150 #if defined(LIBXML_HTML_ENABLED)
    151 static int nodefdtd = 0;
    152 #endif
    153 #ifdef LIBXML_PUSH_ENABLED
    154 static int push = 0;
    155 static int pushsize = 4096;
    156 #endif /* LIBXML_PUSH_ENABLED */
    157 #ifdef HAVE_MMAP
    158 static int memory = 0;
    159 #endif
    160 static int testIO = 0;
    161 static char *encoding = NULL;
    162 #ifdef LIBXML_XINCLUDE_ENABLED
    163 static int xinclude = 0;
    164 #endif
    165 static int dtdattrs = 0;
    166 static int loaddtd = 0;
    167 static xmllintReturnCode progresult = XMLLINT_RETURN_OK;
    168 static int timing = 0;
    169 static int generate = 0;
    170 static int dropdtd = 0;
    171 #ifdef LIBXML_CATALOG_ENABLED
    172 static int catalogs = 0;
    173 static int nocatalogs = 0;
    174 #endif
    175 #ifdef LIBXML_C14N_ENABLED
    176 static int canonical = 0;
    177 static int canonical_11 = 0;
    178 static int exc_canonical = 0;
    179 #endif
    180 #ifdef LIBXML_READER_ENABLED
    181 static int stream = 0;
    182 static int walker = 0;
    183 #endif /* LIBXML_READER_ENABLED */
    184 static int chkregister = 0;
    185 static int nbregister = 0;
    186 #ifdef LIBXML_SAX1_ENABLED
    187 static int sax1 = 0;
    188 #endif /* LIBXML_SAX1_ENABLED */
    189 #ifdef LIBXML_PATTERN_ENABLED
    190 static const char *pattern = NULL;
    191 static xmlPatternPtr patternc = NULL;
    192 static xmlStreamCtxtPtr patstream = NULL;
    193 #endif
    194 #ifdef LIBXML_XPATH_ENABLED
    195 static const char *xpathquery = NULL;
    196 #endif
    197 static int options = XML_PARSE_COMPACT | XML_PARSE_BIG_LINES;
    198 static int sax = 0;
    199 static int oldxml10 = 0;
    200 
    201 /************************************************************************
    202  *									*
    203  *		 Entity loading control and customization.		*
    204  *									*
    205  ************************************************************************/
    206 #define MAX_PATHS 64
    207 #ifdef _WIN32
    208 # define PATH_SEPARATOR ';'
    209 #else
    210 # define PATH_SEPARATOR ':'
    211 #endif
    212 static xmlChar *paths[MAX_PATHS + 1];
    213 static int nbpaths = 0;
    214 static int load_trace = 0;
    215 
    216 static
    217 void parsePath(const xmlChar *path) {
    218     const xmlChar *cur;
    219 
    220     if (path == NULL)
    221 	return;
    222     while (*path != 0) {
    223 	if (nbpaths >= MAX_PATHS) {
    224 	    fprintf(stderr, "MAX_PATHS reached: too many paths\n");
    225 	    return;
    226 	}
    227 	cur = path;
    228 	while ((*cur == ' ') || (*cur == PATH_SEPARATOR))
    229 	    cur++;
    230 	path = cur;
    231 	while ((*cur != 0) && (*cur != ' ') && (*cur != PATH_SEPARATOR))
    232 	    cur++;
    233 	if (cur != path) {
    234 	    paths[nbpaths] = xmlStrndup(path, cur - path);
    235 	    if (paths[nbpaths] != NULL)
    236 		nbpaths++;
    237 	    path = cur;
    238 	}
    239     }
    240 }
    241 
    242 static xmlExternalEntityLoader defaultEntityLoader = NULL;
    243 
    244 static xmlParserInputPtr
    245 xmllintExternalEntityLoader(const char *URL, const char *ID,
    246 			     xmlParserCtxtPtr ctxt) {
    247     xmlParserInputPtr ret;
    248     warningSAXFunc warning = NULL;
    249     errorSAXFunc err = NULL;
    250 
    251     int i;
    252     const char *lastsegment = URL;
    253     const char *iter = URL;
    254 
    255     if ((nbpaths > 0) && (iter != NULL)) {
    256 	while (*iter != 0) {
    257 	    if (*iter == '/')
    258 		lastsegment = iter + 1;
    259 	    iter++;
    260 	}
    261     }
    262 
    263     if ((ctxt != NULL) && (ctxt->sax != NULL)) {
    264 	warning = ctxt->sax->warning;
    265 	err = ctxt->sax->error;
    266 	ctxt->sax->warning = NULL;
    267 	ctxt->sax->error = NULL;
    268     }
    269 
    270     if (defaultEntityLoader != NULL) {
    271 	ret = defaultEntityLoader(URL, ID, ctxt);
    272 	if (ret != NULL) {
    273 	    if (warning != NULL)
    274 		ctxt->sax->warning = warning;
    275 	    if (err != NULL)
    276 		ctxt->sax->error = err;
    277 	    if (load_trace) {
    278 		fprintf \
    279 			(stderr,
    280 			 "Loaded URL=\"%s\" ID=\"%s\"\n",
    281 			 URL ? URL : "(null)",
    282 			 ID ? ID : "(null)");
    283 	    }
    284 	    return(ret);
    285 	}
    286     }
    287     for (i = 0;i < nbpaths;i++) {
    288 	xmlChar *newURL;
    289 
    290 	newURL = xmlStrdup((const xmlChar *) paths[i]);
    291 	newURL = xmlStrcat(newURL, (const xmlChar *) "/");
    292 	newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
    293 	if (newURL != NULL) {
    294 	    ret = defaultEntityLoader((const char *)newURL, ID, ctxt);
    295 	    if (ret != NULL) {
    296 		if (warning != NULL)
    297 		    ctxt->sax->warning = warning;
    298 		if (err != NULL)
    299 		    ctxt->sax->error = err;
    300 		if (load_trace) {
    301 		    fprintf \
    302 			(stderr,
    303 			 "Loaded URL=\"%s\" ID=\"%s\"\n",
    304 			 newURL,
    305 			 ID ? ID : "(null)");
    306 		}
    307 		xmlFree(newURL);
    308 		return(ret);
    309 	    }
    310 	    xmlFree(newURL);
    311 	}
    312     }
    313     if (err != NULL)
    314         ctxt->sax->error = err;
    315     if (warning != NULL) {
    316 	ctxt->sax->warning = warning;
    317 	if (URL != NULL)
    318 	    warning(ctxt, "failed to load external entity \"%s\"\n", URL);
    319 	else if (ID != NULL)
    320 	    warning(ctxt, "failed to load external entity \"%s\"\n", ID);
    321     }
    322     return(NULL);
    323 }
    324 /************************************************************************
    325  *									*
    326  * Memory allocation consumption debugging				*
    327  *									*
    328  ************************************************************************/
    329 
    330 static void
    331 OOM(void)
    332 {
    333     fprintf(stderr, "Ran out of memory needs > %d bytes\n", maxmem);
    334     progresult = XMLLINT_ERR_MEM;
    335 }
    336 
    337 static void
    338 myFreeFunc(void *mem)
    339 {
    340     xmlMemFree(mem);
    341 }
    342 static void *
    343 myMallocFunc(size_t size)
    344 {
    345     void *ret;
    346 
    347     ret = xmlMemMalloc(size);
    348     if (ret != NULL) {
    349         if (xmlMemUsed() > maxmem) {
    350             OOM();
    351             xmlMemFree(ret);
    352             return (NULL);
    353         }
    354     }
    355     return (ret);
    356 }
    357 static void *
    358 myReallocFunc(void *mem, size_t size)
    359 {
    360     void *ret;
    361 
    362     ret = xmlMemRealloc(mem, size);
    363     if (ret != NULL) {
    364         if (xmlMemUsed() > maxmem) {
    365             OOM();
    366             xmlMemFree(ret);
    367             return (NULL);
    368         }
    369     }
    370     return (ret);
    371 }
    372 static char *
    373 myStrdupFunc(const char *str)
    374 {
    375     char *ret;
    376 
    377     ret = xmlMemoryStrdup(str);
    378     if (ret != NULL) {
    379         if (xmlMemUsed() > maxmem) {
    380             OOM();
    381             xmlFree(ret);
    382             return (NULL);
    383         }
    384     }
    385     return (ret);
    386 }
    387 /************************************************************************
    388  *									*
    389  * Internal timing routines to remove the necessity to have		*
    390  * unix-specific function calls.					*
    391  *									*
    392  ************************************************************************/
    393 
    394 #ifndef HAVE_GETTIMEOFDAY
    395 #ifdef HAVE_SYS_TIMEB_H
    396 #ifdef HAVE_SYS_TIME_H
    397 #ifdef HAVE_FTIME
    398 
    399 static int
    400 my_gettimeofday(struct timeval *tvp, void *tzp)
    401 {
    402 	struct timeb timebuffer;
    403 
    404 	ftime(&timebuffer);
    405 	if (tvp) {
    406 		tvp->tv_sec = timebuffer.time;
    407 		tvp->tv_usec = timebuffer.millitm * 1000L;
    408 	}
    409 	return (0);
    410 }
    411 #define HAVE_GETTIMEOFDAY 1
    412 #define gettimeofday my_gettimeofday
    413 
    414 #endif /* HAVE_FTIME */
    415 #endif /* HAVE_SYS_TIME_H */
    416 #endif /* HAVE_SYS_TIMEB_H */
    417 #endif /* !HAVE_GETTIMEOFDAY */
    418 
    419 #if defined(HAVE_GETTIMEOFDAY)
    420 static struct timeval begin, end;
    421 
    422 /*
    423  * startTimer: call where you want to start timing
    424  */
    425 static void
    426 startTimer(void)
    427 {
    428     gettimeofday(&begin, NULL);
    429 }
    430 
    431 /*
    432  * endTimer: call where you want to stop timing and to print out a
    433  *           message about the timing performed; format is a printf
    434  *           type argument
    435  */
    436 static void XMLCDECL LIBXML_ATTR_FORMAT(1,2)
    437 endTimer(const char *fmt, ...)
    438 {
    439     long msec;
    440     va_list ap;
    441 
    442     gettimeofday(&end, NULL);
    443     msec = end.tv_sec - begin.tv_sec;
    444     msec *= 1000;
    445     msec += (end.tv_usec - begin.tv_usec) / 1000;
    446 
    447 #ifndef HAVE_STDARG_H
    448 #error "endTimer required stdarg functions"
    449 #endif
    450     va_start(ap, fmt);
    451     vfprintf(stderr, fmt, ap);
    452     va_end(ap);
    453 
    454     fprintf(stderr, " took %ld ms\n", msec);
    455 }
    456 #elif defined(HAVE_TIME_H)
    457 /*
    458  * No gettimeofday function, so we have to make do with calling clock.
    459  * This is obviously less accurate, but there's little we can do about
    460  * that.
    461  */
    462 #ifndef CLOCKS_PER_SEC
    463 #define CLOCKS_PER_SEC 100
    464 #endif
    465 
    466 static clock_t begin, end;
    467 static void
    468 startTimer(void)
    469 {
    470     begin = clock();
    471 }
    472 static void XMLCDECL LIBXML_ATTR_FORMAT(1,2)
    473 endTimer(const char *fmt, ...)
    474 {
    475     long msec;
    476     va_list ap;
    477 
    478     end = clock();
    479     msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
    480 
    481 #ifndef HAVE_STDARG_H
    482 #error "endTimer required stdarg functions"
    483 #endif
    484     va_start(ap, fmt);
    485     vfprintf(stderr, fmt, ap);
    486     va_end(ap);
    487     fprintf(stderr, " took %ld ms\n", msec);
    488 }
    489 #else
    490 
    491 /*
    492  * We don't have a gettimeofday or time.h, so we just don't do timing
    493  */
    494 static void
    495 startTimer(void)
    496 {
    497     /*
    498      * Do nothing
    499      */
    500 }
    501 static void XMLCDECL LIBXML_ATTR_FORMAT(1,2)
    502 endTimer(char *format, ...)
    503 {
    504     /*
    505      * We cannot do anything because we don't have a timing function
    506      */
    507 #ifdef HAVE_STDARG_H
    508     va_list ap;
    509     va_start(ap, format);
    510     vfprintf(stderr, format, ap);
    511     va_end(ap);
    512     fprintf(stderr, " was not timed\n");
    513 #else
    514     /* We don't have gettimeofday, time or stdarg.h, what crazy world is
    515      * this ?!
    516      */
    517 #endif
    518 }
    519 #endif
    520 /************************************************************************
    521  *									*
    522  *			HTML ouput					*
    523  *									*
    524  ************************************************************************/
    525 static char buffer[50000];
    526 
    527 static void
    528 xmlHTMLEncodeSend(void) {
    529     char *result;
    530 
    531     result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
    532     if (result) {
    533 	xmlGenericError(xmlGenericErrorContext, "%s", result);
    534 	xmlFree(result);
    535     }
    536     buffer[0] = 0;
    537 }
    538 
    539 /**
    540  * xmlHTMLPrintFileInfo:
    541  * @input:  an xmlParserInputPtr input
    542  *
    543  * Displays the associated file and line informations for the current input
    544  */
    545 
    546 static void
    547 xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
    548     int len;
    549     xmlGenericError(xmlGenericErrorContext, "<p>");
    550 
    551     len = strlen(buffer);
    552     if (input != NULL) {
    553 	if (input->filename) {
    554 	    snprintf(&buffer[len], sizeof(buffer) - len, "%s:%d: ", input->filename,
    555 		    input->line);
    556 	} else {
    557 	    snprintf(&buffer[len], sizeof(buffer) - len, "Entity: line %d: ", input->line);
    558 	}
    559     }
    560     xmlHTMLEncodeSend();
    561 }
    562 
    563 /**
    564  * xmlHTMLPrintFileContext:
    565  * @input:  an xmlParserInputPtr input
    566  *
    567  * Displays current context within the input content for error tracking
    568  */
    569 
    570 static void
    571 xmlHTMLPrintFileContext(xmlParserInputPtr input) {
    572     const xmlChar *cur, *base;
    573     int len;
    574     int n;
    575 
    576     if (input == NULL) return;
    577     xmlGenericError(xmlGenericErrorContext, "<pre>\n");
    578     cur = input->cur;
    579     base = input->base;
    580     while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
    581 	cur--;
    582     }
    583     n = 0;
    584     while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
    585         cur--;
    586     if ((*cur == '\n') || (*cur == '\r')) cur++;
    587     base = cur;
    588     n = 0;
    589     while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
    590 	len = strlen(buffer);
    591         snprintf(&buffer[len], sizeof(buffer) - len, "%c",
    592 		    (unsigned char) *cur++);
    593 	n++;
    594     }
    595     len = strlen(buffer);
    596     snprintf(&buffer[len], sizeof(buffer) - len, "\n");
    597     cur = input->cur;
    598     while ((*cur == '\n') || (*cur == '\r'))
    599 	cur--;
    600     n = 0;
    601     while ((cur != base) && (n++ < 80)) {
    602 	len = strlen(buffer);
    603         snprintf(&buffer[len], sizeof(buffer) - len, " ");
    604         base++;
    605     }
    606     len = strlen(buffer);
    607     snprintf(&buffer[len], sizeof(buffer) - len, "^\n");
    608     xmlHTMLEncodeSend();
    609     xmlGenericError(xmlGenericErrorContext, "</pre>");
    610 }
    611 
    612 /**
    613  * xmlHTMLError:
    614  * @ctx:  an XML parser context
    615  * @msg:  the message to display/transmit
    616  * @...:  extra parameters for the message display
    617  *
    618  * Display and format an error messages, gives file, line, position and
    619  * extra parameters.
    620  */
    621 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
    622 xmlHTMLError(void *ctx, const char *msg, ...)
    623 {
    624     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    625     xmlParserInputPtr input;
    626     va_list args;
    627     int len;
    628 
    629     buffer[0] = 0;
    630     input = ctxt->input;
    631     if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
    632         input = ctxt->inputTab[ctxt->inputNr - 2];
    633     }
    634 
    635     xmlHTMLPrintFileInfo(input);
    636 
    637     xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
    638     va_start(args, msg);
    639     len = strlen(buffer);
    640     vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
    641     va_end(args);
    642     xmlHTMLEncodeSend();
    643     xmlGenericError(xmlGenericErrorContext, "</p>\n");
    644 
    645     xmlHTMLPrintFileContext(input);
    646     xmlHTMLEncodeSend();
    647 }
    648 
    649 /**
    650  * xmlHTMLWarning:
    651  * @ctx:  an XML parser context
    652  * @msg:  the message to display/transmit
    653  * @...:  extra parameters for the message display
    654  *
    655  * Display and format a warning messages, gives file, line, position and
    656  * extra parameters.
    657  */
    658 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
    659 xmlHTMLWarning(void *ctx, const char *msg, ...)
    660 {
    661     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    662     xmlParserInputPtr input;
    663     va_list args;
    664     int len;
    665 
    666     buffer[0] = 0;
    667     input = ctxt->input;
    668     if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
    669         input = ctxt->inputTab[ctxt->inputNr - 2];
    670     }
    671 
    672 
    673     xmlHTMLPrintFileInfo(input);
    674 
    675     xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
    676     va_start(args, msg);
    677     len = strlen(buffer);
    678     vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
    679     va_end(args);
    680     xmlHTMLEncodeSend();
    681     xmlGenericError(xmlGenericErrorContext, "</p>\n");
    682 
    683     xmlHTMLPrintFileContext(input);
    684     xmlHTMLEncodeSend();
    685 }
    686 
    687 /**
    688  * xmlHTMLValidityError:
    689  * @ctx:  an XML parser context
    690  * @msg:  the message to display/transmit
    691  * @...:  extra parameters for the message display
    692  *
    693  * Display and format an validity error messages, gives file,
    694  * line, position and extra parameters.
    695  */
    696 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
    697 xmlHTMLValidityError(void *ctx, const char *msg, ...)
    698 {
    699     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    700     xmlParserInputPtr input;
    701     va_list args;
    702     int len;
    703 
    704     buffer[0] = 0;
    705     input = ctxt->input;
    706     if ((input->filename == NULL) && (ctxt->inputNr > 1))
    707         input = ctxt->inputTab[ctxt->inputNr - 2];
    708 
    709     xmlHTMLPrintFileInfo(input);
    710 
    711     xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
    712     len = strlen(buffer);
    713     va_start(args, msg);
    714     vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
    715     va_end(args);
    716     xmlHTMLEncodeSend();
    717     xmlGenericError(xmlGenericErrorContext, "</p>\n");
    718 
    719     xmlHTMLPrintFileContext(input);
    720     xmlHTMLEncodeSend();
    721     progresult = XMLLINT_ERR_VALID;
    722 }
    723 
    724 /**
    725  * xmlHTMLValidityWarning:
    726  * @ctx:  an XML parser context
    727  * @msg:  the message to display/transmit
    728  * @...:  extra parameters for the message display
    729  *
    730  * Display and format a validity warning messages, gives file, line,
    731  * position and extra parameters.
    732  */
    733 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
    734 xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
    735 {
    736     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    737     xmlParserInputPtr input;
    738     va_list args;
    739     int len;
    740 
    741     buffer[0] = 0;
    742     input = ctxt->input;
    743     if ((input->filename == NULL) && (ctxt->inputNr > 1))
    744         input = ctxt->inputTab[ctxt->inputNr - 2];
    745 
    746     xmlHTMLPrintFileInfo(input);
    747 
    748     xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
    749     va_start(args, msg);
    750     len = strlen(buffer);
    751     vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
    752     va_end(args);
    753     xmlHTMLEncodeSend();
    754     xmlGenericError(xmlGenericErrorContext, "</p>\n");
    755 
    756     xmlHTMLPrintFileContext(input);
    757     xmlHTMLEncodeSend();
    758 }
    759 
    760 /************************************************************************
    761  *									*
    762  *			Shell Interface					*
    763  *									*
    764  ************************************************************************/
    765 #ifdef LIBXML_DEBUG_ENABLED
    766 #ifdef LIBXML_XPATH_ENABLED
    767 /**
    768  * xmlShellReadline:
    769  * @prompt:  the prompt value
    770  *
    771  * Read a string
    772  *
    773  * Returns a pointer to it or NULL on EOF the caller is expected to
    774  *     free the returned string.
    775  */
    776 static char *
    777 xmlShellReadline(char *prompt) {
    778 #ifdef HAVE_LIBREADLINE
    779     char *line_read;
    780 
    781     /* Get a line from the user. */
    782     line_read = readline (prompt);
    783 
    784     /* If the line has any text in it, save it on the history. */
    785     if (line_read && *line_read)
    786 	add_history (line_read);
    787 
    788     return (line_read);
    789 #else
    790     char line_read[501];
    791     char *ret;
    792     int len;
    793 
    794     if (prompt != NULL)
    795 	fprintf(stdout, "%s", prompt);
    796     fflush(stdout);
    797     if (!fgets(line_read, 500, stdin))
    798         return(NULL);
    799     line_read[500] = 0;
    800     len = strlen(line_read);
    801     ret = (char *) malloc(len + 1);
    802     if (ret != NULL) {
    803 	memcpy (ret, line_read, len + 1);
    804     }
    805     return(ret);
    806 #endif
    807 }
    808 #endif /* LIBXML_XPATH_ENABLED */
    809 #endif /* LIBXML_DEBUG_ENABLED */
    810 
    811 /************************************************************************
    812  *									*
    813  *			I/O Interfaces					*
    814  *									*
    815  ************************************************************************/
    816 
    817 static int myRead(void *f, char *buf, int len) {
    818     return(fread(buf, 1, len, (FILE *) f));
    819 }
    820 static int myClose(void *context) {
    821     FILE *f = (FILE *) context;
    822     if (f == stdin)
    823         return(0);
    824     return(fclose(f));
    825 }
    826 
    827 /************************************************************************
    828  *									*
    829  *			SAX based tests					*
    830  *									*
    831  ************************************************************************/
    832 
    833 /*
    834  * empty SAX block
    835  */
    836 static xmlSAXHandler emptySAXHandlerStruct = {
    837     NULL, /* internalSubset */
    838     NULL, /* isStandalone */
    839     NULL, /* hasInternalSubset */
    840     NULL, /* hasExternalSubset */
    841     NULL, /* resolveEntity */
    842     NULL, /* getEntity */
    843     NULL, /* entityDecl */
    844     NULL, /* notationDecl */
    845     NULL, /* attributeDecl */
    846     NULL, /* elementDecl */
    847     NULL, /* unparsedEntityDecl */
    848     NULL, /* setDocumentLocator */
    849     NULL, /* startDocument */
    850     NULL, /* endDocument */
    851     NULL, /* startElement */
    852     NULL, /* endElement */
    853     NULL, /* reference */
    854     NULL, /* characters */
    855     NULL, /* ignorableWhitespace */
    856     NULL, /* processingInstruction */
    857     NULL, /* comment */
    858     NULL, /* xmlParserWarning */
    859     NULL, /* xmlParserError */
    860     NULL, /* xmlParserError */
    861     NULL, /* getParameterEntity */
    862     NULL, /* cdataBlock; */
    863     NULL, /* externalSubset; */
    864     XML_SAX2_MAGIC,
    865     NULL,
    866     NULL, /* startElementNs */
    867     NULL, /* endElementNs */
    868     NULL  /* xmlStructuredErrorFunc */
    869 };
    870 
    871 static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
    872 extern xmlSAXHandlerPtr debugSAXHandler;
    873 static int callbacks;
    874 
    875 /**
    876  * isStandaloneDebug:
    877  * @ctxt:  An XML parser context
    878  *
    879  * Is this document tagged standalone ?
    880  *
    881  * Returns 1 if true
    882  */
    883 static int
    884 isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
    885 {
    886     callbacks++;
    887     if (noout)
    888 	return(0);
    889     fprintf(stdout, "SAX.isStandalone()\n");
    890     return(0);
    891 }
    892 
    893 /**
    894  * hasInternalSubsetDebug:
    895  * @ctxt:  An XML parser context
    896  *
    897  * Does this document has an internal subset
    898  *
    899  * Returns 1 if true
    900  */
    901 static int
    902 hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
    903 {
    904     callbacks++;
    905     if (noout)
    906 	return(0);
    907     fprintf(stdout, "SAX.hasInternalSubset()\n");
    908     return(0);
    909 }
    910 
    911 /**
    912  * hasExternalSubsetDebug:
    913  * @ctxt:  An XML parser context
    914  *
    915  * Does this document has an external subset
    916  *
    917  * Returns 1 if true
    918  */
    919 static int
    920 hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
    921 {
    922     callbacks++;
    923     if (noout)
    924 	return(0);
    925     fprintf(stdout, "SAX.hasExternalSubset()\n");
    926     return(0);
    927 }
    928 
    929 /**
    930  * internalSubsetDebug:
    931  * @ctxt:  An XML parser context
    932  *
    933  * Does this document has an internal subset
    934  */
    935 static void
    936 internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
    937 	       const xmlChar *ExternalID, const xmlChar *SystemID)
    938 {
    939     callbacks++;
    940     if (noout)
    941 	return;
    942     fprintf(stdout, "SAX.internalSubset(%s,", name);
    943     if (ExternalID == NULL)
    944 	fprintf(stdout, " ,");
    945     else
    946 	fprintf(stdout, " %s,", ExternalID);
    947     if (SystemID == NULL)
    948 	fprintf(stdout, " )\n");
    949     else
    950 	fprintf(stdout, " %s)\n", SystemID);
    951 }
    952 
    953 /**
    954  * externalSubsetDebug:
    955  * @ctxt:  An XML parser context
    956  *
    957  * Does this document has an external subset
    958  */
    959 static void
    960 externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
    961 	       const xmlChar *ExternalID, const xmlChar *SystemID)
    962 {
    963     callbacks++;
    964     if (noout)
    965 	return;
    966     fprintf(stdout, "SAX.externalSubset(%s,", name);
    967     if (ExternalID == NULL)
    968 	fprintf(stdout, " ,");
    969     else
    970 	fprintf(stdout, " %s,", ExternalID);
    971     if (SystemID == NULL)
    972 	fprintf(stdout, " )\n");
    973     else
    974 	fprintf(stdout, " %s)\n", SystemID);
    975 }
    976 
    977 /**
    978  * resolveEntityDebug:
    979  * @ctxt:  An XML parser context
    980  * @publicId: The public ID of the entity
    981  * @systemId: The system ID of the entity
    982  *
    983  * Special entity resolver, better left to the parser, it has
    984  * more context than the application layer.
    985  * The default behaviour is to NOT resolve the entities, in that case
    986  * the ENTITY_REF nodes are built in the structure (and the parameter
    987  * values).
    988  *
    989  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
    990  */
    991 static xmlParserInputPtr
    992 resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
    993 {
    994     callbacks++;
    995     if (noout)
    996 	return(NULL);
    997     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
    998 
    999 
   1000     fprintf(stdout, "SAX.resolveEntity(");
   1001     if (publicId != NULL)
   1002 	fprintf(stdout, "%s", (char *)publicId);
   1003     else
   1004 	fprintf(stdout, " ");
   1005     if (systemId != NULL)
   1006 	fprintf(stdout, ", %s)\n", (char *)systemId);
   1007     else
   1008 	fprintf(stdout, ", )\n");
   1009     return(NULL);
   1010 }
   1011 
   1012 /**
   1013  * getEntityDebug:
   1014  * @ctxt:  An XML parser context
   1015  * @name: The entity name
   1016  *
   1017  * Get an entity by name
   1018  *
   1019  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
   1020  */
   1021 static xmlEntityPtr
   1022 getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
   1023 {
   1024     callbacks++;
   1025     if (noout)
   1026 	return(NULL);
   1027     fprintf(stdout, "SAX.getEntity(%s)\n", name);
   1028     return(NULL);
   1029 }
   1030 
   1031 /**
   1032  * getParameterEntityDebug:
   1033  * @ctxt:  An XML parser context
   1034  * @name: The entity name
   1035  *
   1036  * Get a parameter entity by name
   1037  *
   1038  * Returns the xmlParserInputPtr
   1039  */
   1040 static xmlEntityPtr
   1041 getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
   1042 {
   1043     callbacks++;
   1044     if (noout)
   1045 	return(NULL);
   1046     fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
   1047     return(NULL);
   1048 }
   1049 
   1050 
   1051 /**
   1052  * entityDeclDebug:
   1053  * @ctxt:  An XML parser context
   1054  * @name:  the entity name
   1055  * @type:  the entity type
   1056  * @publicId: The public ID of the entity
   1057  * @systemId: The system ID of the entity
   1058  * @content: the entity value (without processing).
   1059  *
   1060  * An entity definition has been parsed
   1061  */
   1062 static void
   1063 entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
   1064           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
   1065 {
   1066 const xmlChar *nullstr = BAD_CAST "(null)";
   1067     /* not all libraries handle printing null pointers nicely */
   1068     if (publicId == NULL)
   1069         publicId = nullstr;
   1070     if (systemId == NULL)
   1071         systemId = nullstr;
   1072     if (content == NULL)
   1073         content = (xmlChar *)nullstr;
   1074     callbacks++;
   1075     if (noout)
   1076 	return;
   1077     fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
   1078             name, type, publicId, systemId, content);
   1079 }
   1080 
   1081 /**
   1082  * attributeDeclDebug:
   1083  * @ctxt:  An XML parser context
   1084  * @name:  the attribute name
   1085  * @type:  the attribute type
   1086  *
   1087  * An attribute definition has been parsed
   1088  */
   1089 static void
   1090 attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
   1091                    const xmlChar * name, int type, int def,
   1092                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
   1093 {
   1094     callbacks++;
   1095     if (noout)
   1096         return;
   1097     if (defaultValue == NULL)
   1098         fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
   1099                 elem, name, type, def);
   1100     else
   1101         fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
   1102                 elem, name, type, def, defaultValue);
   1103     xmlFreeEnumeration(tree);
   1104 }
   1105 
   1106 /**
   1107  * elementDeclDebug:
   1108  * @ctxt:  An XML parser context
   1109  * @name:  the element name
   1110  * @type:  the element type
   1111  * @content: the element value (without processing).
   1112  *
   1113  * An element definition has been parsed
   1114  */
   1115 static void
   1116 elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
   1117 	    xmlElementContentPtr content ATTRIBUTE_UNUSED)
   1118 {
   1119     callbacks++;
   1120     if (noout)
   1121 	return;
   1122     fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
   1123             name, type);
   1124 }
   1125 
   1126 /**
   1127  * notationDeclDebug:
   1128  * @ctxt:  An XML parser context
   1129  * @name: The name of the notation
   1130  * @publicId: The public ID of the entity
   1131  * @systemId: The system ID of the entity
   1132  *
   1133  * What to do when a notation declaration has been parsed.
   1134  */
   1135 static void
   1136 notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
   1137 	     const xmlChar *publicId, const xmlChar *systemId)
   1138 {
   1139     callbacks++;
   1140     if (noout)
   1141 	return;
   1142     fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
   1143             (char *) name, (char *) publicId, (char *) systemId);
   1144 }
   1145 
   1146 /**
   1147  * unparsedEntityDeclDebug:
   1148  * @ctxt:  An XML parser context
   1149  * @name: The name of the entity
   1150  * @publicId: The public ID of the entity
   1151  * @systemId: The system ID of the entity
   1152  * @notationName: the name of the notation
   1153  *
   1154  * What to do when an unparsed entity declaration is parsed
   1155  */
   1156 static void
   1157 unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
   1158 		   const xmlChar *publicId, const xmlChar *systemId,
   1159 		   const xmlChar *notationName)
   1160 {
   1161 const xmlChar *nullstr = BAD_CAST "(null)";
   1162 
   1163     if (publicId == NULL)
   1164         publicId = nullstr;
   1165     if (systemId == NULL)
   1166         systemId = nullstr;
   1167     if (notationName == NULL)
   1168         notationName = nullstr;
   1169     callbacks++;
   1170     if (noout)
   1171 	return;
   1172     fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
   1173             (char *) name, (char *) publicId, (char *) systemId,
   1174 	    (char *) notationName);
   1175 }
   1176 
   1177 /**
   1178  * setDocumentLocatorDebug:
   1179  * @ctxt:  An XML parser context
   1180  * @loc: A SAX Locator
   1181  *
   1182  * Receive the document locator at startup, actually xmlDefaultSAXLocator
   1183  * Everything is available on the context, so this is useless in our case.
   1184  */
   1185 static void
   1186 setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
   1187 {
   1188     callbacks++;
   1189     if (noout)
   1190 	return;
   1191     fprintf(stdout, "SAX.setDocumentLocator()\n");
   1192 }
   1193 
   1194 /**
   1195  * startDocumentDebug:
   1196  * @ctxt:  An XML parser context
   1197  *
   1198  * called when the document start being processed.
   1199  */
   1200 static void
   1201 startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
   1202 {
   1203     callbacks++;
   1204     if (noout)
   1205 	return;
   1206     fprintf(stdout, "SAX.startDocument()\n");
   1207 }
   1208 
   1209 /**
   1210  * endDocumentDebug:
   1211  * @ctxt:  An XML parser context
   1212  *
   1213  * called when the document end has been detected.
   1214  */
   1215 static void
   1216 endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
   1217 {
   1218     callbacks++;
   1219     if (noout)
   1220 	return;
   1221     fprintf(stdout, "SAX.endDocument()\n");
   1222 }
   1223 
   1224 /**
   1225  * startElementDebug:
   1226  * @ctxt:  An XML parser context
   1227  * @name:  The element name
   1228  *
   1229  * called when an opening tag has been processed.
   1230  */
   1231 static void
   1232 startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
   1233 {
   1234     int i;
   1235 
   1236     callbacks++;
   1237     if (noout)
   1238 	return;
   1239     fprintf(stdout, "SAX.startElement(%s", (char *) name);
   1240     if (atts != NULL) {
   1241         for (i = 0;(atts[i] != NULL);i++) {
   1242 	    fprintf(stdout, ", %s='", atts[i++]);
   1243 	    if (atts[i] != NULL)
   1244 	        fprintf(stdout, "%s'", atts[i]);
   1245 	}
   1246     }
   1247     fprintf(stdout, ")\n");
   1248 }
   1249 
   1250 /**
   1251  * endElementDebug:
   1252  * @ctxt:  An XML parser context
   1253  * @name:  The element name
   1254  *
   1255  * called when the end of an element has been detected.
   1256  */
   1257 static void
   1258 endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
   1259 {
   1260     callbacks++;
   1261     if (noout)
   1262 	return;
   1263     fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
   1264 }
   1265 
   1266 /**
   1267  * charactersDebug:
   1268  * @ctxt:  An XML parser context
   1269  * @ch:  a xmlChar string
   1270  * @len: the number of xmlChar
   1271  *
   1272  * receiving some chars from the parser.
   1273  * Question: how much at a time ???
   1274  */
   1275 static void
   1276 charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
   1277 {
   1278     char out[40];
   1279     int i;
   1280 
   1281     callbacks++;
   1282     if (noout)
   1283 	return;
   1284     for (i = 0;(i<len) && (i < 30);i++)
   1285 	out[i] = ch[i];
   1286     out[i] = 0;
   1287 
   1288     fprintf(stdout, "SAX.characters(%s, %d)\n", out, len);
   1289 }
   1290 
   1291 /**
   1292  * referenceDebug:
   1293  * @ctxt:  An XML parser context
   1294  * @name:  The entity name
   1295  *
   1296  * called when an entity reference is detected.
   1297  */
   1298 static void
   1299 referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
   1300 {
   1301     callbacks++;
   1302     if (noout)
   1303 	return;
   1304     fprintf(stdout, "SAX.reference(%s)\n", name);
   1305 }
   1306 
   1307 /**
   1308  * ignorableWhitespaceDebug:
   1309  * @ctxt:  An XML parser context
   1310  * @ch:  a xmlChar string
   1311  * @start: the first char in the string
   1312  * @len: the number of xmlChar
   1313  *
   1314  * receiving some ignorable whitespaces from the parser.
   1315  * Question: how much at a time ???
   1316  */
   1317 static void
   1318 ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
   1319 {
   1320     char out[40];
   1321     int i;
   1322 
   1323     callbacks++;
   1324     if (noout)
   1325 	return;
   1326     for (i = 0;(i<len) && (i < 30);i++)
   1327 	out[i] = ch[i];
   1328     out[i] = 0;
   1329     fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", out, len);
   1330 }
   1331 
   1332 /**
   1333  * processingInstructionDebug:
   1334  * @ctxt:  An XML parser context
   1335  * @target:  the target name
   1336  * @data: the PI data's
   1337  * @len: the number of xmlChar
   1338  *
   1339  * A processing instruction has been parsed.
   1340  */
   1341 static void
   1342 processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
   1343                       const xmlChar *data)
   1344 {
   1345     callbacks++;
   1346     if (noout)
   1347 	return;
   1348     if (data != NULL)
   1349 	fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
   1350 		(char *) target, (char *) data);
   1351     else
   1352 	fprintf(stdout, "SAX.processingInstruction(%s, NULL)\n",
   1353 		(char *) target);
   1354 }
   1355 
   1356 /**
   1357  * cdataBlockDebug:
   1358  * @ctx: the user data (XML parser context)
   1359  * @value:  The pcdata content
   1360  * @len:  the block length
   1361  *
   1362  * called when a pcdata block has been parsed
   1363  */
   1364 static void
   1365 cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
   1366 {
   1367     callbacks++;
   1368     if (noout)
   1369 	return;
   1370     fprintf(stdout, "SAX.pcdata(%.20s, %d)\n",
   1371 	    (char *) value, len);
   1372 }
   1373 
   1374 /**
   1375  * commentDebug:
   1376  * @ctxt:  An XML parser context
   1377  * @value:  the comment content
   1378  *
   1379  * A comment has been parsed.
   1380  */
   1381 static void
   1382 commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
   1383 {
   1384     callbacks++;
   1385     if (noout)
   1386 	return;
   1387     fprintf(stdout, "SAX.comment(%s)\n", value);
   1388 }
   1389 
   1390 /**
   1391  * warningDebug:
   1392  * @ctxt:  An XML parser context
   1393  * @msg:  the message to display/transmit
   1394  * @...:  extra parameters for the message display
   1395  *
   1396  * Display and format a warning messages, gives file, line, position and
   1397  * extra parameters.
   1398  */
   1399 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
   1400 warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
   1401 {
   1402     va_list args;
   1403 
   1404     callbacks++;
   1405     if (noout)
   1406 	return;
   1407     va_start(args, msg);
   1408     fprintf(stdout, "SAX.warning: ");
   1409     vfprintf(stdout, msg, args);
   1410     va_end(args);
   1411 }
   1412 
   1413 /**
   1414  * errorDebug:
   1415  * @ctxt:  An XML parser context
   1416  * @msg:  the message to display/transmit
   1417  * @...:  extra parameters for the message display
   1418  *
   1419  * Display and format a error messages, gives file, line, position and
   1420  * extra parameters.
   1421  */
   1422 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
   1423 errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
   1424 {
   1425     va_list args;
   1426 
   1427     callbacks++;
   1428     if (noout)
   1429 	return;
   1430     va_start(args, msg);
   1431     fprintf(stdout, "SAX.error: ");
   1432     vfprintf(stdout, msg, args);
   1433     va_end(args);
   1434 }
   1435 
   1436 /**
   1437  * fatalErrorDebug:
   1438  * @ctxt:  An XML parser context
   1439  * @msg:  the message to display/transmit
   1440  * @...:  extra parameters for the message display
   1441  *
   1442  * Display and format a fatalError messages, gives file, line, position and
   1443  * extra parameters.
   1444  */
   1445 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
   1446 fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
   1447 {
   1448     va_list args;
   1449 
   1450     callbacks++;
   1451     if (noout)
   1452 	return;
   1453     va_start(args, msg);
   1454     fprintf(stdout, "SAX.fatalError: ");
   1455     vfprintf(stdout, msg, args);
   1456     va_end(args);
   1457 }
   1458 
   1459 static xmlSAXHandler debugSAXHandlerStruct = {
   1460     internalSubsetDebug,
   1461     isStandaloneDebug,
   1462     hasInternalSubsetDebug,
   1463     hasExternalSubsetDebug,
   1464     resolveEntityDebug,
   1465     getEntityDebug,
   1466     entityDeclDebug,
   1467     notationDeclDebug,
   1468     attributeDeclDebug,
   1469     elementDeclDebug,
   1470     unparsedEntityDeclDebug,
   1471     setDocumentLocatorDebug,
   1472     startDocumentDebug,
   1473     endDocumentDebug,
   1474     startElementDebug,
   1475     endElementDebug,
   1476     referenceDebug,
   1477     charactersDebug,
   1478     ignorableWhitespaceDebug,
   1479     processingInstructionDebug,
   1480     commentDebug,
   1481     warningDebug,
   1482     errorDebug,
   1483     fatalErrorDebug,
   1484     getParameterEntityDebug,
   1485     cdataBlockDebug,
   1486     externalSubsetDebug,
   1487     1,
   1488     NULL,
   1489     NULL,
   1490     NULL,
   1491     NULL
   1492 };
   1493 
   1494 xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
   1495 
   1496 /*
   1497  * SAX2 specific callbacks
   1498  */
   1499 /**
   1500  * startElementNsDebug:
   1501  * @ctxt:  An XML parser context
   1502  * @name:  The element name
   1503  *
   1504  * called when an opening tag has been processed.
   1505  */
   1506 static void
   1507 startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
   1508                     const xmlChar *localname,
   1509                     const xmlChar *prefix,
   1510                     const xmlChar *URI,
   1511 		    int nb_namespaces,
   1512 		    const xmlChar **namespaces,
   1513 		    int nb_attributes,
   1514 		    int nb_defaulted,
   1515 		    const xmlChar **attributes)
   1516 {
   1517     int i;
   1518 
   1519     callbacks++;
   1520     if (noout)
   1521 	return;
   1522     fprintf(stdout, "SAX.startElementNs(%s", (char *) localname);
   1523     if (prefix == NULL)
   1524 	fprintf(stdout, ", NULL");
   1525     else
   1526 	fprintf(stdout, ", %s", (char *) prefix);
   1527     if (URI == NULL)
   1528 	fprintf(stdout, ", NULL");
   1529     else
   1530 	fprintf(stdout, ", '%s'", (char *) URI);
   1531     fprintf(stdout, ", %d", nb_namespaces);
   1532 
   1533     if (namespaces != NULL) {
   1534         for (i = 0;i < nb_namespaces * 2;i++) {
   1535 	    fprintf(stdout, ", xmlns");
   1536 	    if (namespaces[i] != NULL)
   1537 	        fprintf(stdout, ":%s", namespaces[i]);
   1538 	    i++;
   1539 	    fprintf(stdout, "='%s'", namespaces[i]);
   1540 	}
   1541     }
   1542     fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted);
   1543     if (attributes != NULL) {
   1544         for (i = 0;i < nb_attributes * 5;i += 5) {
   1545 	    if (attributes[i + 1] != NULL)
   1546 		fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]);
   1547 	    else
   1548 		fprintf(stdout, ", %s='", attributes[i]);
   1549 	    fprintf(stdout, "%.4s...', %d", attributes[i + 3],
   1550 		    (int)(attributes[i + 4] - attributes[i + 3]));
   1551 	}
   1552     }
   1553     fprintf(stdout, ")\n");
   1554 }
   1555 
   1556 /**
   1557  * endElementDebug:
   1558  * @ctxt:  An XML parser context
   1559  * @name:  The element name
   1560  *
   1561  * called when the end of an element has been detected.
   1562  */
   1563 static void
   1564 endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
   1565                   const xmlChar *localname,
   1566                   const xmlChar *prefix,
   1567                   const xmlChar *URI)
   1568 {
   1569     callbacks++;
   1570     if (noout)
   1571 	return;
   1572     fprintf(stdout, "SAX.endElementNs(%s", (char *) localname);
   1573     if (prefix == NULL)
   1574 	fprintf(stdout, ", NULL");
   1575     else
   1576 	fprintf(stdout, ", %s", (char *) prefix);
   1577     if (URI == NULL)
   1578 	fprintf(stdout, ", NULL)\n");
   1579     else
   1580 	fprintf(stdout, ", '%s')\n", (char *) URI);
   1581 }
   1582 
   1583 static xmlSAXHandler debugSAX2HandlerStruct = {
   1584     internalSubsetDebug,
   1585     isStandaloneDebug,
   1586     hasInternalSubsetDebug,
   1587     hasExternalSubsetDebug,
   1588     resolveEntityDebug,
   1589     getEntityDebug,
   1590     entityDeclDebug,
   1591     notationDeclDebug,
   1592     attributeDeclDebug,
   1593     elementDeclDebug,
   1594     unparsedEntityDeclDebug,
   1595     setDocumentLocatorDebug,
   1596     startDocumentDebug,
   1597     endDocumentDebug,
   1598     NULL,
   1599     NULL,
   1600     referenceDebug,
   1601     charactersDebug,
   1602     ignorableWhitespaceDebug,
   1603     processingInstructionDebug,
   1604     commentDebug,
   1605     warningDebug,
   1606     errorDebug,
   1607     fatalErrorDebug,
   1608     getParameterEntityDebug,
   1609     cdataBlockDebug,
   1610     externalSubsetDebug,
   1611     XML_SAX2_MAGIC,
   1612     NULL,
   1613     startElementNsDebug,
   1614     endElementNsDebug,
   1615     NULL
   1616 };
   1617 
   1618 static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
   1619 
   1620 static void
   1621 testSAX(const char *filename) {
   1622     xmlSAXHandlerPtr handler;
   1623     const char *user_data = "user_data"; /* mostly for debugging */
   1624     xmlParserInputBufferPtr buf = NULL;
   1625     xmlParserInputPtr inputStream;
   1626     xmlParserCtxtPtr ctxt = NULL;
   1627     xmlSAXHandlerPtr old_sax = NULL;
   1628 
   1629     callbacks = 0;
   1630 
   1631     if (noout) {
   1632         handler = emptySAXHandler;
   1633 #ifdef LIBXML_SAX1_ENABLED
   1634     } else if (sax1) {
   1635         handler = debugSAXHandler;
   1636 #endif
   1637     } else {
   1638         handler = debugSAX2Handler;
   1639     }
   1640 
   1641     /*
   1642      * it's not the simplest code but the most generic in term of I/O
   1643      */
   1644     buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
   1645     if (buf == NULL) {
   1646         goto error;
   1647     }
   1648 
   1649 #ifdef LIBXML_SCHEMAS_ENABLED
   1650     if (wxschemas != NULL) {
   1651         int ret;
   1652 	xmlSchemaValidCtxtPtr vctxt;
   1653 
   1654 	vctxt = xmlSchemaNewValidCtxt(wxschemas);
   1655 	xmlSchemaSetValidErrors(vctxt,
   1656 		(xmlSchemaValidityErrorFunc) fprintf,
   1657 		(xmlSchemaValidityWarningFunc) fprintf,
   1658 		stderr);
   1659 	xmlSchemaValidateSetFilename(vctxt, filename);
   1660 
   1661 	ret = xmlSchemaValidateStream(vctxt, buf, 0, handler,
   1662 	                              (void *)user_data);
   1663 	if (repeat == 0) {
   1664 	    if (ret == 0) {
   1665 		fprintf(stderr, "%s validates\n", filename);
   1666 	    } else if (ret > 0) {
   1667 		fprintf(stderr, "%s fails to validate\n", filename);
   1668 		progresult = XMLLINT_ERR_VALID;
   1669 	    } else {
   1670 		fprintf(stderr, "%s validation generated an internal error\n",
   1671 		       filename);
   1672 		progresult = XMLLINT_ERR_VALID;
   1673 	    }
   1674 	}
   1675 	xmlSchemaFreeValidCtxt(vctxt);
   1676     } else
   1677 #endif
   1678     {
   1679 	/*
   1680 	 * Create the parser context amd hook the input
   1681 	 */
   1682 	ctxt = xmlNewParserCtxt();
   1683 	if (ctxt == NULL) {
   1684 	    xmlFreeParserInputBuffer(buf);
   1685 	    goto error;
   1686 	}
   1687 	old_sax = ctxt->sax;
   1688 	ctxt->sax = handler;
   1689 	ctxt->userData = (void *) user_data;
   1690 	inputStream = xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE);
   1691 	if (inputStream == NULL) {
   1692 	    xmlFreeParserInputBuffer(buf);
   1693 	    goto error;
   1694 	}
   1695 	inputPush(ctxt, inputStream);
   1696 
   1697 	/* do the parsing */
   1698 	xmlParseDocument(ctxt);
   1699 
   1700 	if (ctxt->myDoc != NULL) {
   1701 	    fprintf(stderr, "SAX generated a doc !\n");
   1702 	    xmlFreeDoc(ctxt->myDoc);
   1703 	    ctxt->myDoc = NULL;
   1704 	}
   1705     }
   1706 
   1707 error:
   1708     if (ctxt != NULL) {
   1709         ctxt->sax = old_sax;
   1710         xmlFreeParserCtxt(ctxt);
   1711     }
   1712 }
   1713 
   1714 /************************************************************************
   1715  *									*
   1716  *			Stream Test processing				*
   1717  *									*
   1718  ************************************************************************/
   1719 #ifdef LIBXML_READER_ENABLED
   1720 static void processNode(xmlTextReaderPtr reader) {
   1721     const xmlChar *name, *value;
   1722     int type, empty;
   1723 
   1724     type = xmlTextReaderNodeType(reader);
   1725     empty = xmlTextReaderIsEmptyElement(reader);
   1726 
   1727     if (debug) {
   1728 	name = xmlTextReaderConstName(reader);
   1729 	if (name == NULL)
   1730 	    name = BAD_CAST "--";
   1731 
   1732 	value = xmlTextReaderConstValue(reader);
   1733 
   1734 
   1735 	printf("%d %d %s %d %d",
   1736 		xmlTextReaderDepth(reader),
   1737 		type,
   1738 		name,
   1739 		empty,
   1740 		xmlTextReaderHasValue(reader));
   1741 	if (value == NULL)
   1742 	    printf("\n");
   1743 	else {
   1744 	    printf(" %s\n", value);
   1745 	}
   1746     }
   1747 #ifdef LIBXML_PATTERN_ENABLED
   1748     if (patternc) {
   1749         xmlChar *path = NULL;
   1750         int match = -1;
   1751 
   1752 	if (type == XML_READER_TYPE_ELEMENT) {
   1753 	    /* do the check only on element start */
   1754 	    match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
   1755 
   1756 	    if (match) {
   1757 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
   1758 		path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
   1759 		printf("Node %s matches pattern %s\n", path, pattern);
   1760 #else
   1761                 printf("Node %s matches pattern %s\n",
   1762                        xmlTextReaderConstName(reader), pattern);
   1763 #endif
   1764 	    }
   1765 	}
   1766 	if (patstream != NULL) {
   1767 	    int ret;
   1768 
   1769 	    if (type == XML_READER_TYPE_ELEMENT) {
   1770 		ret = xmlStreamPush(patstream,
   1771 		                    xmlTextReaderConstLocalName(reader),
   1772 				    xmlTextReaderConstNamespaceUri(reader));
   1773 		if (ret < 0) {
   1774 		    fprintf(stderr, "xmlStreamPush() failure\n");
   1775                     xmlFreeStreamCtxt(patstream);
   1776 		    patstream = NULL;
   1777 		} else if (ret != match) {
   1778 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
   1779 		    if (path == NULL) {
   1780 		        path = xmlGetNodePath(
   1781 		                       xmlTextReaderCurrentNode(reader));
   1782 		    }
   1783 #endif
   1784 		    fprintf(stderr,
   1785 		            "xmlPatternMatch and xmlStreamPush disagree\n");
   1786                     if (path != NULL)
   1787                         fprintf(stderr, "  pattern %s node %s\n",
   1788                                 pattern, path);
   1789                     else
   1790 		        fprintf(stderr, "  pattern %s node %s\n",
   1791 			    pattern, xmlTextReaderConstName(reader));
   1792 		}
   1793 
   1794 	    }
   1795 	    if ((type == XML_READER_TYPE_END_ELEMENT) ||
   1796 	        ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
   1797 	        ret = xmlStreamPop(patstream);
   1798 		if (ret < 0) {
   1799 		    fprintf(stderr, "xmlStreamPop() failure\n");
   1800                     xmlFreeStreamCtxt(patstream);
   1801 		    patstream = NULL;
   1802 		}
   1803 	    }
   1804 	}
   1805 	if (path != NULL)
   1806 	    xmlFree(path);
   1807     }
   1808 #endif
   1809 }
   1810 
   1811 static void streamFile(char *filename) {
   1812     xmlTextReaderPtr reader;
   1813     int ret;
   1814 #ifdef HAVE_MMAP
   1815     int fd = -1;
   1816     struct stat info;
   1817     const char *base = NULL;
   1818     xmlParserInputBufferPtr input = NULL;
   1819 
   1820     if (memory) {
   1821 	if (stat(filename, &info) < 0)
   1822 	    return;
   1823 	if ((fd = open(filename, O_RDONLY)) < 0)
   1824 	    return;
   1825 	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
   1826 	if (base == (void *) MAP_FAILED) {
   1827 	    close(fd);
   1828 	    fprintf(stderr, "mmap failure for file %s\n", filename);
   1829 	    progresult = XMLLINT_ERR_RDFILE;
   1830 	    return;
   1831 	}
   1832 
   1833 	reader = xmlReaderForMemory(base, info.st_size, filename,
   1834 	                            NULL, options);
   1835     } else
   1836 #endif
   1837 	reader = xmlReaderForFile(filename, NULL, options);
   1838 #ifdef LIBXML_PATTERN_ENABLED
   1839     if (pattern != NULL) {
   1840         patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
   1841 	if (patternc == NULL) {
   1842 	    xmlGenericError(xmlGenericErrorContext,
   1843 		    "Pattern %s failed to compile\n", pattern);
   1844             progresult = XMLLINT_ERR_SCHEMAPAT;
   1845 	    pattern = NULL;
   1846 	}
   1847     }
   1848     if (patternc != NULL) {
   1849         patstream = xmlPatternGetStreamCtxt(patternc);
   1850 	if (patstream != NULL) {
   1851 	    ret = xmlStreamPush(patstream, NULL, NULL);
   1852 	    if (ret < 0) {
   1853 		fprintf(stderr, "xmlStreamPush() failure\n");
   1854 		xmlFreeStreamCtxt(patstream);
   1855 		patstream = NULL;
   1856             }
   1857 	}
   1858     }
   1859 #endif
   1860 
   1861 
   1862     if (reader != NULL) {
   1863 #ifdef LIBXML_VALID_ENABLED
   1864 	if (valid)
   1865 	    xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
   1866 	else
   1867 #endif /* LIBXML_VALID_ENABLED */
   1868 	    if (loaddtd)
   1869 		xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1);
   1870 #ifdef LIBXML_SCHEMAS_ENABLED
   1871 	if (relaxng != NULL) {
   1872 	    if ((timing) && (!repeat)) {
   1873 		startTimer();
   1874 	    }
   1875 	    ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
   1876 	    if (ret < 0) {
   1877 		xmlGenericError(xmlGenericErrorContext,
   1878 			"Relax-NG schema %s failed to compile\n", relaxng);
   1879 		progresult = XMLLINT_ERR_SCHEMACOMP;
   1880 		relaxng = NULL;
   1881 	    }
   1882 	    if ((timing) && (!repeat)) {
   1883 		endTimer("Compiling the schemas");
   1884 	    }
   1885 	}
   1886 	if (schema != NULL) {
   1887 	    if ((timing) && (!repeat)) {
   1888 		startTimer();
   1889 	    }
   1890 	    ret = xmlTextReaderSchemaValidate(reader, schema);
   1891 	    if (ret < 0) {
   1892 		xmlGenericError(xmlGenericErrorContext,
   1893 			"XSD schema %s failed to compile\n", schema);
   1894 		progresult = XMLLINT_ERR_SCHEMACOMP;
   1895 		schema = NULL;
   1896 	    }
   1897 	    if ((timing) && (!repeat)) {
   1898 		endTimer("Compiling the schemas");
   1899 	    }
   1900 	}
   1901 #endif
   1902 
   1903 	/*
   1904 	 * Process all nodes in sequence
   1905 	 */
   1906 	if ((timing) && (!repeat)) {
   1907 	    startTimer();
   1908 	}
   1909 	ret = xmlTextReaderRead(reader);
   1910 	while (ret == 1) {
   1911 	    if ((debug)
   1912 #ifdef LIBXML_PATTERN_ENABLED
   1913 	        || (patternc)
   1914 #endif
   1915 	       )
   1916 		processNode(reader);
   1917 	    ret = xmlTextReaderRead(reader);
   1918 	}
   1919 	if ((timing) && (!repeat)) {
   1920 #ifdef LIBXML_SCHEMAS_ENABLED
   1921 	    if (relaxng != NULL)
   1922 		endTimer("Parsing and validating");
   1923 	    else
   1924 #endif
   1925 #ifdef LIBXML_VALID_ENABLED
   1926 	    if (valid)
   1927 		endTimer("Parsing and validating");
   1928 	    else
   1929 #endif
   1930 	    endTimer("Parsing");
   1931 	}
   1932 
   1933 #ifdef LIBXML_VALID_ENABLED
   1934 	if (valid) {
   1935 	    if (xmlTextReaderIsValid(reader) != 1) {
   1936 		xmlGenericError(xmlGenericErrorContext,
   1937 			"Document %s does not validate\n", filename);
   1938 		progresult = XMLLINT_ERR_VALID;
   1939 	    }
   1940 	}
   1941 #endif /* LIBXML_VALID_ENABLED */
   1942 #ifdef LIBXML_SCHEMAS_ENABLED
   1943 	if ((relaxng != NULL) || (schema != NULL)) {
   1944 	    if (xmlTextReaderIsValid(reader) != 1) {
   1945 		fprintf(stderr, "%s fails to validate\n", filename);
   1946 		progresult = XMLLINT_ERR_VALID;
   1947 	    } else {
   1948 		fprintf(stderr, "%s validates\n", filename);
   1949 	    }
   1950 	}
   1951 #endif
   1952 	/*
   1953 	 * Done, cleanup and status
   1954 	 */
   1955 	xmlFreeTextReader(reader);
   1956 	if (ret != 0) {
   1957 	    fprintf(stderr, "%s : failed to parse\n", filename);
   1958 	    progresult = XMLLINT_ERR_UNCLASS;
   1959 	}
   1960     } else {
   1961 	fprintf(stderr, "Unable to open %s\n", filename);
   1962 	progresult = XMLLINT_ERR_UNCLASS;
   1963     }
   1964 #ifdef LIBXML_PATTERN_ENABLED
   1965     if (patstream != NULL) {
   1966 	xmlFreeStreamCtxt(patstream);
   1967 	patstream = NULL;
   1968     }
   1969 #endif
   1970 #ifdef HAVE_MMAP
   1971     if (memory) {
   1972         xmlFreeParserInputBuffer(input);
   1973 	munmap((char *) base, info.st_size);
   1974 	close(fd);
   1975     }
   1976 #endif
   1977 }
   1978 
   1979 static void walkDoc(xmlDocPtr doc) {
   1980     xmlTextReaderPtr reader;
   1981     int ret;
   1982 
   1983 #ifdef LIBXML_PATTERN_ENABLED
   1984     xmlNodePtr root;
   1985     const xmlChar *namespaces[22];
   1986     int i;
   1987     xmlNsPtr ns;
   1988 
   1989     root = xmlDocGetRootElement(doc);
   1990     if (root == NULL ) {
   1991         xmlGenericError(xmlGenericErrorContext,
   1992                 "Document does not have a root element");
   1993         progresult = XMLLINT_ERR_UNCLASS;
   1994         return;
   1995     }
   1996     for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) {
   1997         namespaces[i++] = ns->href;
   1998         namespaces[i++] = ns->prefix;
   1999     }
   2000     namespaces[i++] = NULL;
   2001     namespaces[i] = NULL;
   2002 
   2003     if (pattern != NULL) {
   2004         patternc = xmlPatterncompile((const xmlChar *) pattern, doc->dict,
   2005 	                             0, &namespaces[0]);
   2006 	if (patternc == NULL) {
   2007 	    xmlGenericError(xmlGenericErrorContext,
   2008 		    "Pattern %s failed to compile\n", pattern);
   2009             progresult = XMLLINT_ERR_SCHEMAPAT;
   2010 	    pattern = NULL;
   2011 	}
   2012     }
   2013     if (patternc != NULL) {
   2014         patstream = xmlPatternGetStreamCtxt(patternc);
   2015 	if (patstream != NULL) {
   2016 	    ret = xmlStreamPush(patstream, NULL, NULL);
   2017 	    if (ret < 0) {
   2018 		fprintf(stderr, "xmlStreamPush() failure\n");
   2019 		xmlFreeStreamCtxt(patstream);
   2020 		patstream = NULL;
   2021             }
   2022 	}
   2023     }
   2024 #endif /* LIBXML_PATTERN_ENABLED */
   2025     reader = xmlReaderWalker(doc);
   2026     if (reader != NULL) {
   2027 	if ((timing) && (!repeat)) {
   2028 	    startTimer();
   2029 	}
   2030 	ret = xmlTextReaderRead(reader);
   2031 	while (ret == 1) {
   2032 	    if ((debug)
   2033 #ifdef LIBXML_PATTERN_ENABLED
   2034 	        || (patternc)
   2035 #endif
   2036 	       )
   2037 		processNode(reader);
   2038 	    ret = xmlTextReaderRead(reader);
   2039 	}
   2040 	if ((timing) && (!repeat)) {
   2041 	    endTimer("walking through the doc");
   2042 	}
   2043 	xmlFreeTextReader(reader);
   2044 	if (ret != 0) {
   2045 	    fprintf(stderr, "failed to walk through the doc\n");
   2046 	    progresult = XMLLINT_ERR_UNCLASS;
   2047 	}
   2048     } else {
   2049 	fprintf(stderr, "Failed to crate a reader from the document\n");
   2050 	progresult = XMLLINT_ERR_UNCLASS;
   2051     }
   2052 #ifdef LIBXML_PATTERN_ENABLED
   2053     if (patstream != NULL) {
   2054 	xmlFreeStreamCtxt(patstream);
   2055 	patstream = NULL;
   2056     }
   2057 #endif
   2058 }
   2059 #endif /* LIBXML_READER_ENABLED */
   2060 
   2061 #ifdef LIBXML_XPATH_ENABLED
   2062 /************************************************************************
   2063  *									*
   2064  *			XPath Query                                     *
   2065  *									*
   2066  ************************************************************************/
   2067 
   2068 static void doXPathDump(xmlXPathObjectPtr cur) {
   2069     switch(cur->type) {
   2070         case XPATH_NODESET: {
   2071             int i;
   2072             xmlNodePtr node;
   2073 #ifdef LIBXML_OUTPUT_ENABLED
   2074             xmlSaveCtxtPtr ctxt;
   2075 
   2076             if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr <= 0)) {
   2077                 fprintf(stderr, "XPath set is empty\n");
   2078                 progresult = XMLLINT_ERR_XPATH;
   2079                 break;
   2080             }
   2081             ctxt = xmlSaveToFd(1, NULL, 0);
   2082             if (ctxt == NULL) {
   2083                 fprintf(stderr, "Out of memory for XPath\n");
   2084                 progresult = XMLLINT_ERR_MEM;
   2085                 return;
   2086             }
   2087             for (i = 0;i < cur->nodesetval->nodeNr;i++) {
   2088                 node = cur->nodesetval->nodeTab[i];
   2089                 xmlSaveTree(ctxt, node);
   2090             }
   2091             xmlSaveClose(ctxt);
   2092 #else
   2093             printf("xpath returned %d nodes\n", cur->nodesetval->nodeNr);
   2094 #endif
   2095 	    break;
   2096         }
   2097         case XPATH_BOOLEAN:
   2098 	    if (cur->boolval) printf("true");
   2099 	    else printf("false");
   2100 	    break;
   2101         case XPATH_NUMBER:
   2102 	    switch (xmlXPathIsInf(cur->floatval)) {
   2103 	    case 1:
   2104 		printf("Infinity");
   2105 		break;
   2106 	    case -1:
   2107 		printf("-Infinity");
   2108 		break;
   2109 	    default:
   2110 		if (xmlXPathIsNaN(cur->floatval)) {
   2111 		    printf("NaN");
   2112 		} else {
   2113 		    printf("%0g", cur->floatval);
   2114 		}
   2115 	    }
   2116 	    break;
   2117         case XPATH_STRING:
   2118 	    printf("%s", (const char *) cur->stringval);
   2119 	    break;
   2120         case XPATH_UNDEFINED:
   2121 	    fprintf(stderr, "XPath Object is uninitialized\n");
   2122             progresult = XMLLINT_ERR_XPATH;
   2123 	    break;
   2124 	default:
   2125 	    fprintf(stderr, "XPath object of unexpected type\n");
   2126             progresult = XMLLINT_ERR_XPATH;
   2127 	    break;
   2128     }
   2129 }
   2130 
   2131 static void doXPathQuery(xmlDocPtr doc, const char *query) {
   2132     xmlXPathContextPtr ctxt;
   2133     xmlXPathObjectPtr res;
   2134 
   2135     ctxt = xmlXPathNewContext(doc);
   2136     if (ctxt == NULL) {
   2137         fprintf(stderr, "Out of memory for XPath\n");
   2138         progresult = XMLLINT_ERR_MEM;
   2139         return;
   2140     }
   2141     ctxt->node = (xmlNodePtr) doc;
   2142     res = xmlXPathEval(BAD_CAST query, ctxt);
   2143     xmlXPathFreeContext(ctxt);
   2144 
   2145     if (res == NULL) {
   2146         fprintf(stderr, "XPath evaluation failure\n");
   2147         progresult = XMLLINT_ERR_XPATH;
   2148         return;
   2149     }
   2150     doXPathDump(res);
   2151     xmlXPathFreeObject(res);
   2152 }
   2153 #endif /* LIBXML_XPATH_ENABLED */
   2154 
   2155 /************************************************************************
   2156  *									*
   2157  *			Tree Test processing				*
   2158  *									*
   2159  ************************************************************************/
   2160 static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
   2161     xmlDocPtr doc = NULL;
   2162 #ifdef LIBXML_TREE_ENABLED
   2163     xmlDocPtr tmp;
   2164 #endif /* LIBXML_TREE_ENABLED */
   2165 
   2166     if ((timing) && (!repeat))
   2167 	startTimer();
   2168 
   2169 
   2170 #ifdef LIBXML_TREE_ENABLED
   2171     if (filename == NULL) {
   2172 	if (generate) {
   2173 	    xmlNodePtr n;
   2174 
   2175 	    doc = xmlNewDoc(BAD_CAST "1.0");
   2176 	    n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL);
   2177 	    xmlNodeSetContent(n, BAD_CAST "abc");
   2178 	    xmlDocSetRootElement(doc, n);
   2179 	}
   2180     }
   2181 #endif /* LIBXML_TREE_ENABLED */
   2182 #ifdef LIBXML_HTML_ENABLED
   2183 #ifdef LIBXML_PUSH_ENABLED
   2184     else if ((html) && (push)) {
   2185         FILE *f;
   2186 
   2187 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
   2188 	f = fopen(filename, "rb");
   2189 #elif defined(__OS400__)
   2190 	f = fopen(filename, "rb");
   2191 #else
   2192 	f = fopen(filename, "r");
   2193 #endif
   2194         if (f != NULL) {
   2195             int res;
   2196             char chars[4096];
   2197             htmlParserCtxtPtr ctxt;
   2198 
   2199             res = fread(chars, 1, 4, f);
   2200             if (res > 0) {
   2201                 ctxt = htmlCreatePushParserCtxt(NULL, NULL,
   2202                             chars, res, filename, XML_CHAR_ENCODING_NONE);
   2203                 xmlCtxtUseOptions(ctxt, options);
   2204                 while ((res = fread(chars, 1, pushsize, f)) > 0) {
   2205                     htmlParseChunk(ctxt, chars, res, 0);
   2206                 }
   2207                 htmlParseChunk(ctxt, chars, 0, 1);
   2208                 doc = ctxt->myDoc;
   2209                 htmlFreeParserCtxt(ctxt);
   2210             }
   2211             fclose(f);
   2212         }
   2213     }
   2214 #endif /* LIBXML_PUSH_ENABLED */
   2215 #ifdef HAVE_MMAP
   2216     else if ((html) && (memory)) {
   2217 	int fd;
   2218 	struct stat info;
   2219 	const char *base;
   2220 	if (stat(filename, &info) < 0)
   2221 	    return;
   2222 	if ((fd = open(filename, O_RDONLY)) < 0)
   2223 	    return;
   2224 	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
   2225 	if (base == (void *) MAP_FAILED) {
   2226 	    close(fd);
   2227 	    fprintf(stderr, "mmap failure for file %s\n", filename);
   2228 	    progresult = XMLLINT_ERR_RDFILE;
   2229 	    return;
   2230 	}
   2231 
   2232 	doc = htmlReadMemory((char *) base, info.st_size, filename,
   2233 	                     NULL, options);
   2234 
   2235 	munmap((char *) base, info.st_size);
   2236 	close(fd);
   2237     }
   2238 #endif
   2239     else if (html) {
   2240 	doc = htmlReadFile(filename, NULL, options);
   2241     }
   2242 #endif /* LIBXML_HTML_ENABLED */
   2243     else {
   2244 #ifdef LIBXML_PUSH_ENABLED
   2245 	/*
   2246 	 * build an XML tree from a string;
   2247 	 */
   2248 	if (push) {
   2249 	    FILE *f;
   2250 
   2251 	    /* '-' Usually means stdin -<sven (at) zen.org> */
   2252 	    if ((filename[0] == '-') && (filename[1] == 0)) {
   2253 	      f = stdin;
   2254 	    } else {
   2255 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
   2256 		f = fopen(filename, "rb");
   2257 #elif defined(__OS400__)
   2258 		f = fopen(filename, "rb");
   2259 #else
   2260 		f = fopen(filename, "r");
   2261 #endif
   2262 	    }
   2263 	    if (f != NULL) {
   2264 		int ret;
   2265 	        int res, size = 1024;
   2266 	        char chars[1024];
   2267                 xmlParserCtxtPtr ctxt;
   2268 
   2269 		/* if (repeat) size = 1024; */
   2270 		res = fread(chars, 1, 4, f);
   2271 		if (res > 0) {
   2272 		    ctxt = xmlCreatePushParserCtxt(NULL, NULL,
   2273 		                chars, res, filename);
   2274 		    xmlCtxtUseOptions(ctxt, options);
   2275 		    while ((res = fread(chars, 1, size, f)) > 0) {
   2276 			xmlParseChunk(ctxt, chars, res, 0);
   2277 		    }
   2278 		    xmlParseChunk(ctxt, chars, 0, 1);
   2279 		    doc = ctxt->myDoc;
   2280 		    ret = ctxt->wellFormed;
   2281 		    xmlFreeParserCtxt(ctxt);
   2282 		    if (!ret) {
   2283 			xmlFreeDoc(doc);
   2284 			doc = NULL;
   2285 		    }
   2286 	        }
   2287                 if (f != stdin)
   2288                     fclose(f);
   2289 	    }
   2290 	} else
   2291 #endif /* LIBXML_PUSH_ENABLED */
   2292         if (testIO) {
   2293 	    if ((filename[0] == '-') && (filename[1] == 0)) {
   2294 	        doc = xmlReadFd(0, NULL, NULL, options);
   2295 	    } else {
   2296 	        FILE *f;
   2297 
   2298 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
   2299 		f = fopen(filename, "rb");
   2300 #elif defined(__OS400__)
   2301 		f = fopen(filename, "rb");
   2302 #else
   2303 		f = fopen(filename, "r");
   2304 #endif
   2305 		if (f != NULL) {
   2306 		    if (rectxt == NULL)
   2307 			doc = xmlReadIO(myRead, myClose, f, filename, NULL,
   2308                                         options);
   2309 		    else
   2310 			doc = xmlCtxtReadIO(rectxt, myRead, myClose, f,
   2311 					    filename, NULL, options);
   2312 		} else
   2313 		    doc = NULL;
   2314 	    }
   2315 	} else if (htmlout) {
   2316 	    xmlParserCtxtPtr ctxt;
   2317 
   2318 	    if (rectxt == NULL)
   2319 		ctxt = xmlNewParserCtxt();
   2320 	    else
   2321 	        ctxt = rectxt;
   2322 	    if (ctxt == NULL) {
   2323 	        doc = NULL;
   2324 	    } else {
   2325 	        ctxt->sax->error = xmlHTMLError;
   2326 	        ctxt->sax->warning = xmlHTMLWarning;
   2327 	        ctxt->vctxt.error = xmlHTMLValidityError;
   2328 	        ctxt->vctxt.warning = xmlHTMLValidityWarning;
   2329 
   2330 		doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
   2331 
   2332 		if (rectxt == NULL)
   2333 		    xmlFreeParserCtxt(ctxt);
   2334 	    }
   2335 #ifdef HAVE_MMAP
   2336 	} else if (memory) {
   2337 	    int fd;
   2338 	    struct stat info;
   2339 	    const char *base;
   2340 	    if (stat(filename, &info) < 0)
   2341 		return;
   2342 	    if ((fd = open(filename, O_RDONLY)) < 0)
   2343 		return;
   2344 	    base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
   2345 	    if (base == (void *) MAP_FAILED) {
   2346 	        close(fd);
   2347 	        fprintf(stderr, "mmap failure for file %s\n", filename);
   2348 		progresult = XMLLINT_ERR_RDFILE;
   2349 	        return;
   2350 	    }
   2351 
   2352 	    if (rectxt == NULL)
   2353 		doc = xmlReadMemory((char *) base, info.st_size,
   2354 		                    filename, NULL, options);
   2355 	    else
   2356 		doc = xmlCtxtReadMemory(rectxt, (char *) base, info.st_size,
   2357 			                filename, NULL, options);
   2358 
   2359 	    munmap((char *) base, info.st_size);
   2360 	    close(fd);
   2361 #endif
   2362 #ifdef LIBXML_VALID_ENABLED
   2363 	} else if (valid) {
   2364 	    xmlParserCtxtPtr ctxt = NULL;
   2365 
   2366 	    if (rectxt == NULL)
   2367 		ctxt = xmlNewParserCtxt();
   2368 	    else
   2369 	        ctxt = rectxt;
   2370 	    if (ctxt == NULL) {
   2371 	        doc = NULL;
   2372 	    } else {
   2373 		doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
   2374 
   2375 		if (ctxt->valid == 0)
   2376 		    progresult = XMLLINT_ERR_RDFILE;
   2377 		if (rectxt == NULL)
   2378 		    xmlFreeParserCtxt(ctxt);
   2379 	    }
   2380 #endif /* LIBXML_VALID_ENABLED */
   2381 	} else {
   2382 	    if (rectxt != NULL)
   2383 	        doc = xmlCtxtReadFile(rectxt, filename, NULL, options);
   2384 	    else {
   2385 #ifdef LIBXML_SAX1_ENABLED
   2386                 if (sax1)
   2387 		    doc = xmlParseFile(filename);
   2388 		else
   2389 #endif /* LIBXML_SAX1_ENABLED */
   2390 		doc = xmlReadFile(filename, NULL, options);
   2391 	    }
   2392 	}
   2393     }
   2394 
   2395     /*
   2396      * If we don't have a document we might as well give up.  Do we
   2397      * want an error message here?  <sven (at) zen.org> */
   2398     if (doc == NULL) {
   2399 	progresult = XMLLINT_ERR_UNCLASS;
   2400 	return;
   2401     }
   2402 
   2403     if ((timing) && (!repeat)) {
   2404 	endTimer("Parsing");
   2405     }
   2406 
   2407     /*
   2408      * Remove DOCTYPE nodes
   2409      */
   2410     if (dropdtd) {
   2411 	xmlDtdPtr dtd;
   2412 
   2413 	dtd = xmlGetIntSubset(doc);
   2414 	if (dtd != NULL) {
   2415 	    xmlUnlinkNode((xmlNodePtr)dtd);
   2416 	    xmlFreeDtd(dtd);
   2417 	}
   2418     }
   2419 
   2420 #ifdef LIBXML_XINCLUDE_ENABLED
   2421     if (xinclude) {
   2422 	if ((timing) && (!repeat)) {
   2423 	    startTimer();
   2424 	}
   2425 	if (xmlXIncludeProcessFlags(doc, options) < 0)
   2426 	    progresult = XMLLINT_ERR_UNCLASS;
   2427 	if ((timing) && (!repeat)) {
   2428 	    endTimer("Xinclude processing");
   2429 	}
   2430     }
   2431 #endif
   2432 
   2433 #ifdef LIBXML_XPATH_ENABLED
   2434     if (xpathquery != NULL) {
   2435         doXPathQuery(doc, xpathquery);
   2436     }
   2437 #endif
   2438 
   2439 #ifdef LIBXML_DEBUG_ENABLED
   2440 #ifdef LIBXML_XPATH_ENABLED
   2441     /*
   2442      * shell interaction
   2443      */
   2444     if (shell) {
   2445         xmlXPathOrderDocElems(doc);
   2446         xmlShell(doc, filename, xmlShellReadline, stdout);
   2447     }
   2448 #endif
   2449 #endif
   2450 
   2451 #ifdef LIBXML_TREE_ENABLED
   2452     /*
   2453      * test intermediate copy if needed.
   2454      */
   2455     if (copy) {
   2456         tmp = doc;
   2457 	if (timing) {
   2458 	    startTimer();
   2459 	}
   2460 	doc = xmlCopyDoc(doc, 1);
   2461 	if (timing) {
   2462 	    endTimer("Copying");
   2463 	}
   2464 	if (timing) {
   2465 	    startTimer();
   2466 	}
   2467 	xmlFreeDoc(tmp);
   2468 	if (timing) {
   2469 	    endTimer("Freeing original");
   2470 	}
   2471     }
   2472 #endif /* LIBXML_TREE_ENABLED */
   2473 
   2474 #ifdef LIBXML_VALID_ENABLED
   2475     if ((insert) && (!html)) {
   2476         const xmlChar* list[256];
   2477 	int nb, i;
   2478 	xmlNodePtr node;
   2479 
   2480 	if (doc->children != NULL) {
   2481 	    node = doc->children;
   2482 	    while ((node != NULL) && (node->last == NULL)) node = node->next;
   2483 	    if (node != NULL) {
   2484 		nb = xmlValidGetValidElements(node->last, NULL, list, 256);
   2485 		if (nb < 0) {
   2486 		    fprintf(stderr, "could not get valid list of elements\n");
   2487 		} else if (nb == 0) {
   2488 		    fprintf(stderr, "No element can be inserted under root\n");
   2489 		} else {
   2490 		    fprintf(stderr, "%d element types can be inserted under root:\n",
   2491 		           nb);
   2492 		    for (i = 0;i < nb;i++) {
   2493 			 fprintf(stderr, "%s\n", (char *) list[i]);
   2494 		    }
   2495 		}
   2496 	    }
   2497 	}
   2498     }else
   2499 #endif /* LIBXML_VALID_ENABLED */
   2500 #ifdef LIBXML_READER_ENABLED
   2501     if (walker) {
   2502         walkDoc(doc);
   2503     }
   2504 #endif /* LIBXML_READER_ENABLED */
   2505 #ifdef LIBXML_OUTPUT_ENABLED
   2506     if (noout == 0) {
   2507         int ret;
   2508 
   2509 	/*
   2510 	 * print it.
   2511 	 */
   2512 #ifdef LIBXML_DEBUG_ENABLED
   2513 	if (!debug) {
   2514 #endif
   2515 	    if ((timing) && (!repeat)) {
   2516 		startTimer();
   2517 	    }
   2518 #ifdef LIBXML_HTML_ENABLED
   2519             if ((html) && (!xmlout)) {
   2520 		if (compress) {
   2521 		    htmlSaveFile(output ? output : "-", doc);
   2522 		}
   2523 		else if (encoding != NULL) {
   2524 		    if (format == 1) {
   2525 			htmlSaveFileFormat(output ? output : "-", doc, encoding, 1);
   2526 		    }
   2527 		    else {
   2528 			htmlSaveFileFormat(output ? output : "-", doc, encoding, 0);
   2529 		    }
   2530 		}
   2531 		else if (format == 1) {
   2532 		    htmlSaveFileFormat(output ? output : "-", doc, NULL, 1);
   2533 		}
   2534 		else {
   2535 		    FILE *out;
   2536 		    if (output == NULL)
   2537 			out = stdout;
   2538 		    else {
   2539 			out = fopen(output,"wb");
   2540 		    }
   2541 		    if (out != NULL) {
   2542 			if (htmlDocDump(out, doc) < 0)
   2543 			    progresult = XMLLINT_ERR_OUT;
   2544 
   2545 			if (output != NULL)
   2546 			    fclose(out);
   2547 		    } else {
   2548 			fprintf(stderr, "failed to open %s\n", output);
   2549 			progresult = XMLLINT_ERR_OUT;
   2550 		    }
   2551 		}
   2552 		if ((timing) && (!repeat)) {
   2553 		    endTimer("Saving");
   2554 		}
   2555 	    } else
   2556 #endif
   2557 #ifdef LIBXML_C14N_ENABLED
   2558             if (canonical) {
   2559 	        xmlChar *result = NULL;
   2560 		int size;
   2561 
   2562 		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result);
   2563 		if (size >= 0) {
   2564 		    if (write(1, result, size) == -1) {
   2565 		        fprintf(stderr, "Can't write data\n");
   2566 		    }
   2567 		    xmlFree(result);
   2568 		} else {
   2569 		    fprintf(stderr, "Failed to canonicalize\n");
   2570 		    progresult = XMLLINT_ERR_OUT;
   2571 		}
   2572 	    } else if (canonical_11) {
   2573 	        xmlChar *result = NULL;
   2574 		int size;
   2575 
   2576 		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result);
   2577 		if (size >= 0) {
   2578 		    if (write(1, result, size) == -1) {
   2579 		        fprintf(stderr, "Can't write data\n");
   2580 		    }
   2581 		    xmlFree(result);
   2582 		} else {
   2583 		    fprintf(stderr, "Failed to canonicalize\n");
   2584 		    progresult = XMLLINT_ERR_OUT;
   2585 		}
   2586 	    } else
   2587             if (exc_canonical) {
   2588 	        xmlChar *result = NULL;
   2589 		int size;
   2590 
   2591 		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result);
   2592 		if (size >= 0) {
   2593 		    if (write(1, result, size) == -1) {
   2594 		        fprintf(stderr, "Can't write data\n");
   2595 		    }
   2596 		    xmlFree(result);
   2597 		} else {
   2598 		    fprintf(stderr, "Failed to canonicalize\n");
   2599 		    progresult = XMLLINT_ERR_OUT;
   2600 		}
   2601 	    } else
   2602 #endif
   2603 #ifdef HAVE_MMAP
   2604 	    if (memory) {
   2605 		xmlChar *result;
   2606 		int len;
   2607 
   2608 		if (encoding != NULL) {
   2609 		    if (format == 1) {
   2610 		        xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
   2611 		    } else {
   2612 			xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
   2613 		    }
   2614 		} else {
   2615 		    if (format == 1)
   2616 			xmlDocDumpFormatMemory(doc, &result, &len, 1);
   2617 		    else
   2618 			xmlDocDumpMemory(doc, &result, &len);
   2619 		}
   2620 		if (result == NULL) {
   2621 		    fprintf(stderr, "Failed to save\n");
   2622 		    progresult = XMLLINT_ERR_OUT;
   2623 		} else {
   2624 		    if (write(1, result, len) == -1) {
   2625 		        fprintf(stderr, "Can't write data\n");
   2626 		    }
   2627 		    xmlFree(result);
   2628 		}
   2629 
   2630 	    } else
   2631 #endif /* HAVE_MMAP */
   2632 	    if (compress) {
   2633 		xmlSaveFile(output ? output : "-", doc);
   2634 	    } else if (oldout) {
   2635 	        if (encoding != NULL) {
   2636 		    if (format == 1) {
   2637 			ret = xmlSaveFormatFileEnc(output ? output : "-", doc,
   2638 						   encoding, 1);
   2639 		    }
   2640 		    else {
   2641 			ret = xmlSaveFileEnc(output ? output : "-", doc,
   2642 			                     encoding);
   2643 		    }
   2644 		    if (ret < 0) {
   2645 			fprintf(stderr, "failed save to %s\n",
   2646 				output ? output : "-");
   2647 			progresult = XMLLINT_ERR_OUT;
   2648 		    }
   2649 		} else if (format == 1) {
   2650 		    ret = xmlSaveFormatFile(output ? output : "-", doc, 1);
   2651 		    if (ret < 0) {
   2652 			fprintf(stderr, "failed save to %s\n",
   2653 				output ? output : "-");
   2654 			progresult = XMLLINT_ERR_OUT;
   2655 		    }
   2656 		} else {
   2657 		    FILE *out;
   2658 		    if (output == NULL)
   2659 			out = stdout;
   2660 		    else {
   2661 			out = fopen(output,"wb");
   2662 		    }
   2663 		    if (out != NULL) {
   2664 			if (xmlDocDump(out, doc) < 0)
   2665 			    progresult = XMLLINT_ERR_OUT;
   2666 
   2667 			if (output != NULL)
   2668 			    fclose(out);
   2669 		    } else {
   2670 			fprintf(stderr, "failed to open %s\n", output);
   2671 			progresult = XMLLINT_ERR_OUT;
   2672 		    }
   2673 		}
   2674 	    } else {
   2675 	        xmlSaveCtxtPtr ctxt;
   2676 		int saveOpts = 0;
   2677 
   2678                 if (format == 1)
   2679 		    saveOpts |= XML_SAVE_FORMAT;
   2680                 else if (format == 2)
   2681                     saveOpts |= XML_SAVE_WSNONSIG;
   2682 
   2683 #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
   2684                 if (xmlout)
   2685                     saveOpts |= XML_SAVE_AS_XML;
   2686 #endif
   2687 
   2688 		if (output == NULL)
   2689 		    ctxt = xmlSaveToFd(1, encoding, saveOpts);
   2690 		else
   2691 		    ctxt = xmlSaveToFilename(output, encoding, saveOpts);
   2692 
   2693 		if (ctxt != NULL) {
   2694 		    if (xmlSaveDoc(ctxt, doc) < 0) {
   2695 			fprintf(stderr, "failed save to %s\n",
   2696 				output ? output : "-");
   2697 			progresult = XMLLINT_ERR_OUT;
   2698 		    }
   2699 		    xmlSaveClose(ctxt);
   2700 		} else {
   2701 		    progresult = XMLLINT_ERR_OUT;
   2702 		}
   2703 	    }
   2704 	    if ((timing) && (!repeat)) {
   2705 		endTimer("Saving");
   2706 	    }
   2707 #ifdef LIBXML_DEBUG_ENABLED
   2708 	} else {
   2709 	    FILE *out;
   2710 	    if (output == NULL)
   2711 	        out = stdout;
   2712 	    else {
   2713 		out = fopen(output,"wb");
   2714 	    }
   2715 	    if (out != NULL) {
   2716 		xmlDebugDumpDocument(out, doc);
   2717 
   2718 		if (output != NULL)
   2719 		    fclose(out);
   2720 	    } else {
   2721 		fprintf(stderr, "failed to open %s\n", output);
   2722 		progresult = XMLLINT_ERR_OUT;
   2723 	    }
   2724 	}
   2725 #endif
   2726     }
   2727 #endif /* LIBXML_OUTPUT_ENABLED */
   2728 
   2729 #ifdef LIBXML_VALID_ENABLED
   2730     /*
   2731      * A posteriori validation test
   2732      */
   2733     if ((dtdvalid != NULL) || (dtdvalidfpi != NULL)) {
   2734 	xmlDtdPtr dtd;
   2735 
   2736 	if ((timing) && (!repeat)) {
   2737 	    startTimer();
   2738 	}
   2739 	if (dtdvalid != NULL)
   2740 	    dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
   2741 	else
   2742 	    dtd = xmlParseDTD((const xmlChar *)dtdvalidfpi, NULL);
   2743 	if ((timing) && (!repeat)) {
   2744 	    endTimer("Parsing DTD");
   2745 	}
   2746 	if (dtd == NULL) {
   2747 	    if (dtdvalid != NULL)
   2748 		xmlGenericError(xmlGenericErrorContext,
   2749 			"Could not parse DTD %s\n", dtdvalid);
   2750 	    else
   2751 		xmlGenericError(xmlGenericErrorContext,
   2752 			"Could not parse DTD %s\n", dtdvalidfpi);
   2753 	    progresult = XMLLINT_ERR_DTD;
   2754 	} else {
   2755 	    xmlValidCtxtPtr cvp;
   2756 
   2757 	    if ((cvp = xmlNewValidCtxt()) == NULL) {
   2758 		xmlGenericError(xmlGenericErrorContext,
   2759 			"Couldn't allocate validation context\n");
   2760 		exit(-1);
   2761 	    }
   2762 	    cvp->userData = (void *) stderr;
   2763 	    cvp->error    = (xmlValidityErrorFunc) fprintf;
   2764 	    cvp->warning  = (xmlValidityWarningFunc) fprintf;
   2765 
   2766 	    if ((timing) && (!repeat)) {
   2767 		startTimer();
   2768 	    }
   2769 	    if (!xmlValidateDtd(cvp, doc, dtd)) {
   2770 		if (dtdvalid != NULL)
   2771 		    xmlGenericError(xmlGenericErrorContext,
   2772 			    "Document %s does not validate against %s\n",
   2773 			    filename, dtdvalid);
   2774 		else
   2775 		    xmlGenericError(xmlGenericErrorContext,
   2776 			    "Document %s does not validate against %s\n",
   2777 			    filename, dtdvalidfpi);
   2778 		progresult = XMLLINT_ERR_VALID;
   2779 	    }
   2780 	    if ((timing) && (!repeat)) {
   2781 		endTimer("Validating against DTD");
   2782 	    }
   2783 	    xmlFreeValidCtxt(cvp);
   2784 	    xmlFreeDtd(dtd);
   2785 	}
   2786     } else if (postvalid) {
   2787 	xmlValidCtxtPtr cvp;
   2788 
   2789 	if ((cvp = xmlNewValidCtxt()) == NULL) {
   2790 	    xmlGenericError(xmlGenericErrorContext,
   2791 		    "Couldn't allocate validation context\n");
   2792 	    exit(-1);
   2793 	}
   2794 
   2795 	if ((timing) && (!repeat)) {
   2796 	    startTimer();
   2797 	}
   2798 	cvp->userData = (void *) stderr;
   2799 	cvp->error    = (xmlValidityErrorFunc) fprintf;
   2800 	cvp->warning  = (xmlValidityWarningFunc) fprintf;
   2801 	if (!xmlValidateDocument(cvp, doc)) {
   2802 	    xmlGenericError(xmlGenericErrorContext,
   2803 		    "Document %s does not validate\n", filename);
   2804 	    progresult = XMLLINT_ERR_VALID;
   2805 	}
   2806 	if ((timing) && (!repeat)) {
   2807 	    endTimer("Validating");
   2808 	}
   2809 	xmlFreeValidCtxt(cvp);
   2810     }
   2811 #endif /* LIBXML_VALID_ENABLED */
   2812 #ifdef LIBXML_SCHEMATRON_ENABLED
   2813     if (wxschematron != NULL) {
   2814 	xmlSchematronValidCtxtPtr ctxt;
   2815 	int ret;
   2816 	int flag;
   2817 
   2818 	if ((timing) && (!repeat)) {
   2819 	    startTimer();
   2820 	}
   2821 
   2822 	if (debug)
   2823 	    flag = XML_SCHEMATRON_OUT_XML;
   2824 	else
   2825 	    flag = XML_SCHEMATRON_OUT_TEXT;
   2826 	if (noout)
   2827 	    flag |= XML_SCHEMATRON_OUT_QUIET;
   2828 	ctxt = xmlSchematronNewValidCtxt(wxschematron, flag);
   2829 #if 0
   2830 	xmlSchematronSetValidErrors(ctxt,
   2831 		(xmlSchematronValidityErrorFunc) fprintf,
   2832 		(xmlSchematronValidityWarningFunc) fprintf,
   2833 		stderr);
   2834 #endif
   2835 	ret = xmlSchematronValidateDoc(ctxt, doc);
   2836 	if (ret == 0) {
   2837 	    fprintf(stderr, "%s validates\n", filename);
   2838 	} else if (ret > 0) {
   2839 	    fprintf(stderr, "%s fails to validate\n", filename);
   2840 	    progresult = XMLLINT_ERR_VALID;
   2841 	} else {
   2842 	    fprintf(stderr, "%s validation generated an internal error\n",
   2843 		   filename);
   2844 	    progresult = XMLLINT_ERR_VALID;
   2845 	}
   2846 	xmlSchematronFreeValidCtxt(ctxt);
   2847 	if ((timing) && (!repeat)) {
   2848 	    endTimer("Validating");
   2849 	}
   2850     }
   2851 #endif
   2852 #ifdef LIBXML_SCHEMAS_ENABLED
   2853     if (relaxngschemas != NULL) {
   2854 	xmlRelaxNGValidCtxtPtr ctxt;
   2855 	int ret;
   2856 
   2857 	if ((timing) && (!repeat)) {
   2858 	    startTimer();
   2859 	}
   2860 
   2861 	ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
   2862 	xmlRelaxNGSetValidErrors(ctxt,
   2863 		(xmlRelaxNGValidityErrorFunc) fprintf,
   2864 		(xmlRelaxNGValidityWarningFunc) fprintf,
   2865 		stderr);
   2866 	ret = xmlRelaxNGValidateDoc(ctxt, doc);
   2867 	if (ret == 0) {
   2868 	    fprintf(stderr, "%s validates\n", filename);
   2869 	} else if (ret > 0) {
   2870 	    fprintf(stderr, "%s fails to validate\n", filename);
   2871 	    progresult = XMLLINT_ERR_VALID;
   2872 	} else {
   2873 	    fprintf(stderr, "%s validation generated an internal error\n",
   2874 		   filename);
   2875 	    progresult = XMLLINT_ERR_VALID;
   2876 	}
   2877 	xmlRelaxNGFreeValidCtxt(ctxt);
   2878 	if ((timing) && (!repeat)) {
   2879 	    endTimer("Validating");
   2880 	}
   2881     } else if (wxschemas != NULL) {
   2882 	xmlSchemaValidCtxtPtr ctxt;
   2883 	int ret;
   2884 
   2885 	if ((timing) && (!repeat)) {
   2886 	    startTimer();
   2887 	}
   2888 
   2889 	ctxt = xmlSchemaNewValidCtxt(wxschemas);
   2890 	xmlSchemaSetValidErrors(ctxt,
   2891 		(xmlSchemaValidityErrorFunc) fprintf,
   2892 		(xmlSchemaValidityWarningFunc) fprintf,
   2893 		stderr);
   2894 	ret = xmlSchemaValidateDoc(ctxt, doc);
   2895 	if (ret == 0) {
   2896 	    fprintf(stderr, "%s validates\n", filename);
   2897 	} else if (ret > 0) {
   2898 	    fprintf(stderr, "%s fails to validate\n", filename);
   2899 	    progresult = XMLLINT_ERR_VALID;
   2900 	} else {
   2901 	    fprintf(stderr, "%s validation generated an internal error\n",
   2902 		   filename);
   2903 	    progresult = XMLLINT_ERR_VALID;
   2904 	}
   2905 	xmlSchemaFreeValidCtxt(ctxt);
   2906 	if ((timing) && (!repeat)) {
   2907 	    endTimer("Validating");
   2908 	}
   2909     }
   2910 #endif
   2911 
   2912 #ifdef LIBXML_DEBUG_ENABLED
   2913 #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
   2914     if ((debugent) && (!html))
   2915 	xmlDebugDumpEntities(stderr, doc);
   2916 #endif
   2917 #endif
   2918 
   2919     /*
   2920      * free it.
   2921      */
   2922     if ((timing) && (!repeat)) {
   2923 	startTimer();
   2924     }
   2925     xmlFreeDoc(doc);
   2926     if ((timing) && (!repeat)) {
   2927 	endTimer("Freeing");
   2928     }
   2929 }
   2930 
   2931 /************************************************************************
   2932  *									*
   2933  *			Usage and Main					*
   2934  *									*
   2935  ************************************************************************/
   2936 
   2937 static void showVersion(const char *name) {
   2938     fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion);
   2939     fprintf(stderr, "   compiled with: ");
   2940     if (xmlHasFeature(XML_WITH_THREAD)) fprintf(stderr, "Threads ");
   2941     if (xmlHasFeature(XML_WITH_TREE)) fprintf(stderr, "Tree ");
   2942     if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(stderr, "Output ");
   2943     if (xmlHasFeature(XML_WITH_PUSH)) fprintf(stderr, "Push ");
   2944     if (xmlHasFeature(XML_WITH_READER)) fprintf(stderr, "Reader ");
   2945     if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(stderr, "Patterns ");
   2946     if (xmlHasFeature(XML_WITH_WRITER)) fprintf(stderr, "Writer ");
   2947     if (xmlHasFeature(XML_WITH_SAX1)) fprintf(stderr, "SAXv1 ");
   2948     if (xmlHasFeature(XML_WITH_FTP)) fprintf(stderr, "FTP ");
   2949     if (xmlHasFeature(XML_WITH_HTTP)) fprintf(stderr, "HTTP ");
   2950     if (xmlHasFeature(XML_WITH_VALID)) fprintf(stderr, "DTDValid ");
   2951     if (xmlHasFeature(XML_WITH_HTML)) fprintf(stderr, "HTML ");
   2952     if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(stderr, "Legacy ");
   2953     if (xmlHasFeature(XML_WITH_C14N)) fprintf(stderr, "C14N ");
   2954     if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(stderr, "Catalog ");
   2955     if (xmlHasFeature(XML_WITH_XPATH)) fprintf(stderr, "XPath ");
   2956     if (xmlHasFeature(XML_WITH_XPTR)) fprintf(stderr, "XPointer ");
   2957     if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(stderr, "XInclude ");
   2958     if (xmlHasFeature(XML_WITH_ICONV)) fprintf(stderr, "Iconv ");
   2959     if (xmlHasFeature(XML_WITH_ICU)) fprintf(stderr, "ICU ");
   2960     if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(stderr, "ISO8859X ");
   2961     if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(stderr, "Unicode ");
   2962     if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(stderr, "Regexps ");
   2963     if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(stderr, "Automata ");
   2964     if (xmlHasFeature(XML_WITH_EXPR)) fprintf(stderr, "Expr ");
   2965     if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(stderr, "Schemas ");
   2966     if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(stderr, "Schematron ");
   2967     if (xmlHasFeature(XML_WITH_MODULES)) fprintf(stderr, "Modules ");
   2968     if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(stderr, "Debug ");
   2969     if (xmlHasFeature(XML_WITH_DEBUG_MEM)) fprintf(stderr, "MemDebug ");
   2970     if (xmlHasFeature(XML_WITH_DEBUG_RUN)) fprintf(stderr, "RunDebug ");
   2971     if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(stderr, "Zlib ");
   2972     if (xmlHasFeature(XML_WITH_LZMA)) fprintf(stderr, "Lzma ");
   2973     fprintf(stderr, "\n");
   2974 }
   2975 
   2976 static void usage(FILE *f, const char *name) {
   2977     fprintf(f, "Usage : %s [options] XMLfiles ...\n", name);
   2978 #ifdef LIBXML_OUTPUT_ENABLED
   2979     fprintf(f, "\tParse the XML files and output the result of the parsing\n");
   2980 #else
   2981     fprintf(f, "\tParse the XML files\n");
   2982 #endif /* LIBXML_OUTPUT_ENABLED */
   2983     fprintf(f, "\t--version : display the version of the XML library used\n");
   2984 #ifdef LIBXML_DEBUG_ENABLED
   2985     fprintf(f, "\t--debug : dump a debug tree of the in-memory document\n");
   2986     fprintf(f, "\t--shell : run a navigating shell\n");
   2987     fprintf(f, "\t--debugent : debug the entities defined in the document\n");
   2988 #else
   2989 #ifdef LIBXML_READER_ENABLED
   2990     fprintf(f, "\t--debug : dump the nodes content when using --stream\n");
   2991 #endif /* LIBXML_READER_ENABLED */
   2992 #endif
   2993 #ifdef LIBXML_TREE_ENABLED
   2994     fprintf(f, "\t--copy : used to test the internal copy implementation\n");
   2995 #endif /* LIBXML_TREE_ENABLED */
   2996     fprintf(f, "\t--recover : output what was parsable on broken XML documents\n");
   2997     fprintf(f, "\t--huge : remove any internal arbitrary parser limits\n");
   2998     fprintf(f, "\t--noent : substitute entity references by their value\n");
   2999     fprintf(f, "\t--noenc : ignore any encoding specified inside the document\n");
   3000     fprintf(f, "\t--noout : don't output the result tree\n");
   3001     fprintf(f, "\t--path 'paths': provide a set of paths for resources\n");
   3002     fprintf(f, "\t--load-trace : print trace of all external entities loaded\n");
   3003     fprintf(f, "\t--nonet : refuse to fetch DTDs or entities over network\n");
   3004     fprintf(f, "\t--nocompact : do not generate compact text nodes\n");
   3005     fprintf(f, "\t--htmlout : output results as HTML\n");
   3006     fprintf(f, "\t--nowrap : do not put HTML doc wrapper\n");
   3007 #ifdef LIBXML_VALID_ENABLED
   3008     fprintf(f, "\t--valid : validate the document in addition to std well-formed check\n");
   3009     fprintf(f, "\t--postvalid : do a posteriori validation, i.e after parsing\n");
   3010     fprintf(f, "\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
   3011     fprintf(f, "\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n");
   3012 #endif /* LIBXML_VALID_ENABLED */
   3013     fprintf(f, "\t--timing : print some timings\n");
   3014     fprintf(f, "\t--output file or -o file: save to a given file\n");
   3015     fprintf(f, "\t--repeat : repeat 100 times, for timing or profiling\n");
   3016     fprintf(f, "\t--insert : ad-hoc test for valid insertions\n");
   3017 #ifdef LIBXML_OUTPUT_ENABLED
   3018 #ifdef LIBXML_ZLIB_ENABLED
   3019     fprintf(f, "\t--compress : turn on gzip compression of output\n");
   3020 #endif
   3021 #endif /* LIBXML_OUTPUT_ENABLED */
   3022 #ifdef LIBXML_HTML_ENABLED
   3023     fprintf(f, "\t--html : use the HTML parser\n");
   3024     fprintf(f, "\t--xmlout : force to use the XML serializer when using --html\n");
   3025     fprintf(f, "\t--nodefdtd : do not default HTML doctype\n");
   3026 #endif
   3027 #ifdef LIBXML_PUSH_ENABLED
   3028     fprintf(f, "\t--push : use the push mode of the parser\n");
   3029     fprintf(f, "\t--pushsmall : use the push mode of the parser using tiny increments\n");
   3030 #endif /* LIBXML_PUSH_ENABLED */
   3031 #ifdef HAVE_MMAP
   3032     fprintf(f, "\t--memory : parse from memory\n");
   3033 #endif
   3034     fprintf(f, "\t--maxmem nbbytes : limits memory allocation to nbbytes bytes\n");
   3035     fprintf(f, "\t--nowarning : do not emit warnings from parser/validator\n");
   3036     fprintf(f, "\t--noblanks : drop (ignorable?) blanks spaces\n");
   3037     fprintf(f, "\t--nocdata : replace cdata section with text nodes\n");
   3038 #ifdef LIBXML_OUTPUT_ENABLED
   3039     fprintf(f, "\t--format : reformat/reindent the output\n");
   3040     fprintf(f, "\t--encode encoding : output in the given encoding\n");
   3041     fprintf(f, "\t--dropdtd : remove the DOCTYPE of the input docs\n");
   3042     fprintf(f, "\t--pretty STYLE : pretty-print in a particular style\n");
   3043     fprintf(f, "\t                 0 Do not pretty print\n");
   3044     fprintf(f, "\t                 1 Format the XML content, as --format\n");
   3045     fprintf(f, "\t                 2 Add whitespace inside tags, preserving content\n");
   3046 #endif /* LIBXML_OUTPUT_ENABLED */
   3047     fprintf(f, "\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
   3048     fprintf(f, "\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
   3049     fprintf(f, "\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
   3050 #ifdef LIBXML_C14N_ENABLED
   3051 #endif /* LIBXML_C14N_ENABLED */
   3052     fprintf(f, "\t--nsclean : remove redundant namespace declarations\n");
   3053     fprintf(f, "\t--testIO : test user I/O support\n");
   3054 #ifdef LIBXML_CATALOG_ENABLED
   3055     fprintf(f, "\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
   3056     fprintf(f, "\t             otherwise XML Catalogs starting from \n");
   3057     fprintf(f, "\t         %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
   3058     fprintf(f, "\t--nocatalogs: deactivate all catalogs\n");
   3059 #endif
   3060     fprintf(f, "\t--auto : generate a small doc on the fly\n");
   3061 #ifdef LIBXML_XINCLUDE_ENABLED
   3062     fprintf(f, "\t--xinclude : do XInclude processing\n");
   3063     fprintf(f, "\t--noxincludenode : same but do not generate XInclude nodes\n");
   3064     fprintf(f, "\t--nofixup-base-uris : do not fixup xml:base uris\n");
   3065 #endif
   3066     fprintf(f, "\t--loaddtd : fetch external DTD\n");
   3067     fprintf(f, "\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
   3068 #ifdef LIBXML_READER_ENABLED
   3069     fprintf(f, "\t--stream : use the streaming interface to process very large files\n");
   3070     fprintf(f, "\t--walker : create a reader and walk though the resulting doc\n");
   3071 #endif /* LIBXML_READER_ENABLED */
   3072 #ifdef LIBXML_PATTERN_ENABLED
   3073     fprintf(f, "\t--pattern pattern_value : test the pattern support\n");
   3074 #endif
   3075     fprintf(f, "\t--chkregister : verify the node registration code\n");
   3076 #ifdef LIBXML_SCHEMAS_ENABLED
   3077     fprintf(f, "\t--relaxng schema : do RelaxNG validation against the schema\n");
   3078     fprintf(f, "\t--schema schema : do validation against the WXS schema\n");
   3079 #endif
   3080 #ifdef LIBXML_SCHEMATRON_ENABLED
   3081     fprintf(f, "\t--schematron schema : do validation against a schematron\n");
   3082 #endif
   3083 #ifdef LIBXML_SAX1_ENABLED
   3084     fprintf(f, "\t--sax1: use the old SAX1 interfaces for processing\n");
   3085 #endif
   3086     fprintf(f, "\t--sax: do not build a tree but work just at the SAX level\n");
   3087     fprintf(f, "\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
   3088 #ifdef LIBXML_XPATH_ENABLED
   3089     fprintf(f, "\t--xpath expr: evaluate the XPath expression, imply --noout\n");
   3090 #endif
   3091 
   3092     fprintf(f, "\nLibxml project home page: http://xmlsoft.org/\n");
   3093     fprintf(f, "To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
   3094 }
   3095 
   3096 static void registerNode(xmlNodePtr node)
   3097 {
   3098     node->_private = malloc(sizeof(long));
   3099     if (node->_private == NULL) {
   3100         fprintf(stderr, "Out of memory in xmllint:registerNode()\n");
   3101 	exit(XMLLINT_ERR_MEM);
   3102     }
   3103     *(long*)node->_private = (long) 0x81726354;
   3104     nbregister++;
   3105 }
   3106 
   3107 static void deregisterNode(xmlNodePtr node)
   3108 {
   3109     assert(node->_private != NULL);
   3110     assert(*(long*)node->_private == (long) 0x81726354);
   3111     free(node->_private);
   3112     nbregister--;
   3113 }
   3114 
   3115 int
   3116 main(int argc, char **argv) {
   3117     int i, acount;
   3118     int files = 0;
   3119     int version = 0;
   3120     const char* indent;
   3121 
   3122     if (argc <= 1) {
   3123 	usage(stderr, argv[0]);
   3124 	return(1);
   3125     }
   3126     LIBXML_TEST_VERSION
   3127     for (i = 1; i < argc ; i++) {
   3128 	if (!strcmp(argv[i], "-"))
   3129 	    break;
   3130 
   3131 	if (argv[i][0] != '-')
   3132 	    continue;
   3133 	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
   3134 	    debug++;
   3135 	else
   3136 #ifdef LIBXML_DEBUG_ENABLED
   3137 	if ((!strcmp(argv[i], "-shell")) ||
   3138 	         (!strcmp(argv[i], "--shell"))) {
   3139 	    shell++;
   3140             noout = 1;
   3141         } else
   3142 #endif
   3143 #ifdef LIBXML_TREE_ENABLED
   3144 	if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
   3145 	    copy++;
   3146 	else
   3147 #endif /* LIBXML_TREE_ENABLED */
   3148 	if ((!strcmp(argv[i], "-recover")) ||
   3149 	         (!strcmp(argv[i], "--recover"))) {
   3150 	    recovery++;
   3151 	    options |= XML_PARSE_RECOVER;
   3152 	} else if ((!strcmp(argv[i], "-huge")) ||
   3153 	         (!strcmp(argv[i], "--huge"))) {
   3154 	    options |= XML_PARSE_HUGE;
   3155 	} else if ((!strcmp(argv[i], "-noent")) ||
   3156 	         (!strcmp(argv[i], "--noent"))) {
   3157 	    noent++;
   3158 	    options |= XML_PARSE_NOENT;
   3159 	} else if ((!strcmp(argv[i], "-noenc")) ||
   3160 	         (!strcmp(argv[i], "--noenc"))) {
   3161 	    noenc++;
   3162 	    options |= XML_PARSE_IGNORE_ENC;
   3163 	} else if ((!strcmp(argv[i], "-nsclean")) ||
   3164 	         (!strcmp(argv[i], "--nsclean"))) {
   3165 	    options |= XML_PARSE_NSCLEAN;
   3166 	} else if ((!strcmp(argv[i], "-nocdata")) ||
   3167 	         (!strcmp(argv[i], "--nocdata"))) {
   3168 	    options |= XML_PARSE_NOCDATA;
   3169 	} else if ((!strcmp(argv[i], "-nodict")) ||
   3170 	         (!strcmp(argv[i], "--nodict"))) {
   3171 	    options |= XML_PARSE_NODICT;
   3172 	} else if ((!strcmp(argv[i], "-version")) ||
   3173 	         (!strcmp(argv[i], "--version"))) {
   3174 	    showVersion(argv[0]);
   3175 	    version = 1;
   3176 	} else if ((!strcmp(argv[i], "-noout")) ||
   3177 	         (!strcmp(argv[i], "--noout")))
   3178 	    noout++;
   3179 #ifdef LIBXML_OUTPUT_ENABLED
   3180 	else if ((!strcmp(argv[i], "-o")) ||
   3181 	         (!strcmp(argv[i], "-output")) ||
   3182 	         (!strcmp(argv[i], "--output"))) {
   3183 	    i++;
   3184 	    output = argv[i];
   3185 	}
   3186 #endif /* LIBXML_OUTPUT_ENABLED */
   3187 	else if ((!strcmp(argv[i], "-htmlout")) ||
   3188 	         (!strcmp(argv[i], "--htmlout")))
   3189 	    htmlout++;
   3190 	else if ((!strcmp(argv[i], "-nowrap")) ||
   3191 	         (!strcmp(argv[i], "--nowrap")))
   3192 	    nowrap++;
   3193 #ifdef LIBXML_HTML_ENABLED
   3194 	else if ((!strcmp(argv[i], "-html")) ||
   3195 	         (!strcmp(argv[i], "--html"))) {
   3196 	    html++;
   3197         }
   3198 	else if ((!strcmp(argv[i], "-xmlout")) ||
   3199 	         (!strcmp(argv[i], "--xmlout"))) {
   3200 	    xmlout++;
   3201 	} else if ((!strcmp(argv[i], "-nodefdtd")) ||
   3202 	         (!strcmp(argv[i], "--nodefdtd"))) {
   3203             nodefdtd++;
   3204 	    options |= HTML_PARSE_NODEFDTD;
   3205         }
   3206 #endif /* LIBXML_HTML_ENABLED */
   3207 	else if ((!strcmp(argv[i], "-loaddtd")) ||
   3208 	         (!strcmp(argv[i], "--loaddtd"))) {
   3209 	    loaddtd++;
   3210 	    options |= XML_PARSE_DTDLOAD;
   3211 	} else if ((!strcmp(argv[i], "-dtdattr")) ||
   3212 	         (!strcmp(argv[i], "--dtdattr"))) {
   3213 	    loaddtd++;
   3214 	    dtdattrs++;
   3215 	    options |= XML_PARSE_DTDATTR;
   3216 	}
   3217 #ifdef LIBXML_VALID_ENABLED
   3218 	else if ((!strcmp(argv[i], "-valid")) ||
   3219 	         (!strcmp(argv[i], "--valid"))) {
   3220 	    valid++;
   3221 	    options |= XML_PARSE_DTDVALID;
   3222 	} else if ((!strcmp(argv[i], "-postvalid")) ||
   3223 	         (!strcmp(argv[i], "--postvalid"))) {
   3224 	    postvalid++;
   3225 	    loaddtd++;
   3226 	    options |= XML_PARSE_DTDLOAD;
   3227 	} else if ((!strcmp(argv[i], "-dtdvalid")) ||
   3228 	         (!strcmp(argv[i], "--dtdvalid"))) {
   3229 	    i++;
   3230 	    dtdvalid = argv[i];
   3231 	    loaddtd++;
   3232 	    options |= XML_PARSE_DTDLOAD;
   3233 	} else if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
   3234 	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
   3235 	    i++;
   3236 	    dtdvalidfpi = argv[i];
   3237 	    loaddtd++;
   3238 	    options |= XML_PARSE_DTDLOAD;
   3239         }
   3240 #endif /* LIBXML_VALID_ENABLED */
   3241 	else if ((!strcmp(argv[i], "-dropdtd")) ||
   3242 	         (!strcmp(argv[i], "--dropdtd")))
   3243 	    dropdtd++;
   3244 	else if ((!strcmp(argv[i], "-insert")) ||
   3245 	         (!strcmp(argv[i], "--insert")))
   3246 	    insert++;
   3247 	else if ((!strcmp(argv[i], "-timing")) ||
   3248 	         (!strcmp(argv[i], "--timing")))
   3249 	    timing++;
   3250 	else if ((!strcmp(argv[i], "-auto")) ||
   3251 	         (!strcmp(argv[i], "--auto")))
   3252 	    generate++;
   3253 	else if ((!strcmp(argv[i], "-repeat")) ||
   3254 	         (!strcmp(argv[i], "--repeat"))) {
   3255 	    if (repeat)
   3256 	        repeat *= 10;
   3257 	    else
   3258 	        repeat = 100;
   3259 	}
   3260 #ifdef LIBXML_PUSH_ENABLED
   3261 	else if ((!strcmp(argv[i], "-push")) ||
   3262 	         (!strcmp(argv[i], "--push")))
   3263 	    push++;
   3264 	else if ((!strcmp(argv[i], "-pushsmall")) ||
   3265 	         (!strcmp(argv[i], "--pushsmall"))) {
   3266 	    push++;
   3267             pushsize = 10;
   3268         }
   3269 #endif /* LIBXML_PUSH_ENABLED */
   3270 #ifdef HAVE_MMAP
   3271 	else if ((!strcmp(argv[i], "-memory")) ||
   3272 	         (!strcmp(argv[i], "--memory")))
   3273 	    memory++;
   3274 #endif
   3275 	else if ((!strcmp(argv[i], "-testIO")) ||
   3276 	         (!strcmp(argv[i], "--testIO")))
   3277 	    testIO++;
   3278 #ifdef LIBXML_XINCLUDE_ENABLED
   3279 	else if ((!strcmp(argv[i], "-xinclude")) ||
   3280 	         (!strcmp(argv[i], "--xinclude"))) {
   3281 	    xinclude++;
   3282 	    options |= XML_PARSE_XINCLUDE;
   3283 	}
   3284 	else if ((!strcmp(argv[i], "-noxincludenode")) ||
   3285 	         (!strcmp(argv[i], "--noxincludenode"))) {
   3286 	    xinclude++;
   3287 	    options |= XML_PARSE_XINCLUDE;
   3288 	    options |= XML_PARSE_NOXINCNODE;
   3289 	}
   3290 	else if ((!strcmp(argv[i], "-nofixup-base-uris")) ||
   3291 	         (!strcmp(argv[i], "--nofixup-base-uris"))) {
   3292 	    xinclude++;
   3293 	    options |= XML_PARSE_XINCLUDE;
   3294 	    options |= XML_PARSE_NOBASEFIX;
   3295 	}
   3296 #endif
   3297 #ifdef LIBXML_OUTPUT_ENABLED
   3298 #ifdef LIBXML_ZLIB_ENABLED
   3299 	else if ((!strcmp(argv[i], "-compress")) ||
   3300 	         (!strcmp(argv[i], "--compress"))) {
   3301 	    compress++;
   3302 	    xmlSetCompressMode(9);
   3303         }
   3304 #endif
   3305 #endif /* LIBXML_OUTPUT_ENABLED */
   3306 	else if ((!strcmp(argv[i], "-nowarning")) ||
   3307 	         (!strcmp(argv[i], "--nowarning"))) {
   3308 	    xmlGetWarningsDefaultValue = 0;
   3309 	    xmlPedanticParserDefault(0);
   3310 	    options |= XML_PARSE_NOWARNING;
   3311         }
   3312 	else if ((!strcmp(argv[i], "-pedantic")) ||
   3313 	         (!strcmp(argv[i], "--pedantic"))) {
   3314 	    xmlGetWarningsDefaultValue = 1;
   3315 	    xmlPedanticParserDefault(1);
   3316 	    options |= XML_PARSE_PEDANTIC;
   3317         }
   3318 #ifdef LIBXML_DEBUG_ENABLED
   3319 	else if ((!strcmp(argv[i], "-debugent")) ||
   3320 		 (!strcmp(argv[i], "--debugent"))) {
   3321 	    debugent++;
   3322 	    xmlParserDebugEntities = 1;
   3323 	}
   3324 #endif
   3325 #ifdef LIBXML_C14N_ENABLED
   3326 	else if ((!strcmp(argv[i], "-c14n")) ||
   3327 		 (!strcmp(argv[i], "--c14n"))) {
   3328 	    canonical++;
   3329 	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
   3330 	}
   3331 	else if ((!strcmp(argv[i], "-c14n11")) ||
   3332 		 (!strcmp(argv[i], "--c14n11"))) {
   3333 	    canonical_11++;
   3334 	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
   3335 	}
   3336 	else if ((!strcmp(argv[i], "-exc-c14n")) ||
   3337 		 (!strcmp(argv[i], "--exc-c14n"))) {
   3338 	    exc_canonical++;
   3339 	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
   3340 	}
   3341 #endif
   3342 #ifdef LIBXML_CATALOG_ENABLED
   3343 	else if ((!strcmp(argv[i], "-catalogs")) ||
   3344 		 (!strcmp(argv[i], "--catalogs"))) {
   3345 	    catalogs++;
   3346 	} else if ((!strcmp(argv[i], "-nocatalogs")) ||
   3347 		 (!strcmp(argv[i], "--nocatalogs"))) {
   3348 	    nocatalogs++;
   3349 	}
   3350 #endif
   3351 	else if ((!strcmp(argv[i], "-encode")) ||
   3352 	         (!strcmp(argv[i], "--encode"))) {
   3353 	    i++;
   3354 	    encoding = argv[i];
   3355 	    /*
   3356 	     * OK it's for testing purposes
   3357 	     */
   3358 	    xmlAddEncodingAlias("UTF-8", "DVEnc");
   3359         }
   3360 	else if ((!strcmp(argv[i], "-noblanks")) ||
   3361 	         (!strcmp(argv[i], "--noblanks"))) {
   3362 	    noblanks++;
   3363 	    xmlKeepBlanksDefault(0);
   3364 	    options |= XML_PARSE_NOBLANKS;
   3365         }
   3366 	else if ((!strcmp(argv[i], "-maxmem")) ||
   3367 	         (!strcmp(argv[i], "--maxmem"))) {
   3368 	     i++;
   3369 	     if (sscanf(argv[i], "%d", &maxmem) == 1) {
   3370 	         xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc,
   3371 		             myStrdupFunc);
   3372 	     } else {
   3373 	         maxmem = 0;
   3374 	     }
   3375         }
   3376 	else if ((!strcmp(argv[i], "-format")) ||
   3377 	         (!strcmp(argv[i], "--format"))) {
   3378 	     noblanks++;
   3379 #ifdef LIBXML_OUTPUT_ENABLED
   3380 	     format = 1;
   3381 #endif /* LIBXML_OUTPUT_ENABLED */
   3382 	     xmlKeepBlanksDefault(0);
   3383 	}
   3384 	else if ((!strcmp(argv[i], "-pretty")) ||
   3385 	         (!strcmp(argv[i], "--pretty"))) {
   3386 	     i++;
   3387 #ifdef LIBXML_OUTPUT_ENABLED
   3388        if (argv[i] != NULL) {
   3389 	         format = atoi(argv[i]);
   3390 	         if (format == 1) {
   3391 	             noblanks++;
   3392 	             xmlKeepBlanksDefault(0);
   3393 	         }
   3394        }
   3395 #endif /* LIBXML_OUTPUT_ENABLED */
   3396 	}
   3397 #ifdef LIBXML_READER_ENABLED
   3398 	else if ((!strcmp(argv[i], "-stream")) ||
   3399 	         (!strcmp(argv[i], "--stream"))) {
   3400 	     stream++;
   3401 	}
   3402 	else if ((!strcmp(argv[i], "-walker")) ||
   3403 	         (!strcmp(argv[i], "--walker"))) {
   3404 	     walker++;
   3405              noout++;
   3406 	}
   3407 #endif /* LIBXML_READER_ENABLED */
   3408 #ifdef LIBXML_SAX1_ENABLED
   3409 	else if ((!strcmp(argv[i], "-sax1")) ||
   3410 	         (!strcmp(argv[i], "--sax1"))) {
   3411 	    sax1++;
   3412 	    options |= XML_PARSE_SAX1;
   3413 	}
   3414 #endif /* LIBXML_SAX1_ENABLED */
   3415 	else if ((!strcmp(argv[i], "-sax")) ||
   3416 	         (!strcmp(argv[i], "--sax"))) {
   3417 	    sax++;
   3418 	}
   3419 	else if ((!strcmp(argv[i], "-chkregister")) ||
   3420 	         (!strcmp(argv[i], "--chkregister"))) {
   3421 	    chkregister++;
   3422 #ifdef LIBXML_SCHEMAS_ENABLED
   3423 	} else if ((!strcmp(argv[i], "-relaxng")) ||
   3424 	         (!strcmp(argv[i], "--relaxng"))) {
   3425 	    i++;
   3426 	    relaxng = argv[i];
   3427 	    noent++;
   3428 	    options |= XML_PARSE_NOENT;
   3429 	} else if ((!strcmp(argv[i], "-schema")) ||
   3430 	         (!strcmp(argv[i], "--schema"))) {
   3431 	    i++;
   3432 	    schema = argv[i];
   3433 	    noent++;
   3434 #endif
   3435 #ifdef LIBXML_SCHEMATRON_ENABLED
   3436 	} else if ((!strcmp(argv[i], "-schematron")) ||
   3437 	         (!strcmp(argv[i], "--schematron"))) {
   3438 	    i++;
   3439 	    schematron = argv[i];
   3440 	    noent++;
   3441 #endif
   3442         } else if ((!strcmp(argv[i], "-nonet")) ||
   3443                    (!strcmp(argv[i], "--nonet"))) {
   3444 	    options |= XML_PARSE_NONET;
   3445 	    xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
   3446         } else if ((!strcmp(argv[i], "-nocompact")) ||
   3447                    (!strcmp(argv[i], "--nocompact"))) {
   3448 	    options &= ~XML_PARSE_COMPACT;
   3449 	} else if ((!strcmp(argv[i], "-load-trace")) ||
   3450 	           (!strcmp(argv[i], "--load-trace"))) {
   3451 	    load_trace++;
   3452         } else if ((!strcmp(argv[i], "-path")) ||
   3453                    (!strcmp(argv[i], "--path"))) {
   3454 	    i++;
   3455 	    parsePath(BAD_CAST argv[i]);
   3456 #ifdef LIBXML_PATTERN_ENABLED
   3457         } else if ((!strcmp(argv[i], "-pattern")) ||
   3458                    (!strcmp(argv[i], "--pattern"))) {
   3459 	    i++;
   3460 	    pattern = argv[i];
   3461 #endif
   3462 #ifdef LIBXML_XPATH_ENABLED
   3463         } else if ((!strcmp(argv[i], "-xpath")) ||
   3464                    (!strcmp(argv[i], "--xpath"))) {
   3465 	    i++;
   3466 	    noout++;
   3467 	    xpathquery = argv[i];
   3468 #endif
   3469 	} else if ((!strcmp(argv[i], "-oldxml10")) ||
   3470 	           (!strcmp(argv[i], "--oldxml10"))) {
   3471 	    oldxml10++;
   3472 	    options |= XML_PARSE_OLD10;
   3473 	} else {
   3474 	    fprintf(stderr, "Unknown option %s\n", argv[i]);
   3475 	    usage(stderr, argv[0]);
   3476 	    return(1);
   3477 	}
   3478     }
   3479 
   3480 #ifdef LIBXML_CATALOG_ENABLED
   3481     if (nocatalogs == 0) {
   3482 	if (catalogs) {
   3483 	    const char *catal;
   3484 
   3485 	    catal = getenv("SGML_CATALOG_FILES");
   3486 	    if (catal != NULL) {
   3487 		xmlLoadCatalogs(catal);
   3488 	    } else {
   3489 		fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
   3490 	    }
   3491 	}
   3492     }
   3493 #endif
   3494 
   3495 #ifdef LIBXML_SAX1_ENABLED
   3496     if (sax1)
   3497         xmlSAXDefaultVersion(1);
   3498     else
   3499         xmlSAXDefaultVersion(2);
   3500 #endif /* LIBXML_SAX1_ENABLED */
   3501 
   3502     if (chkregister) {
   3503 	xmlRegisterNodeDefault(registerNode);
   3504 	xmlDeregisterNodeDefault(deregisterNode);
   3505     }
   3506 
   3507     indent = getenv("XMLLINT_INDENT");
   3508     if(indent != NULL) {
   3509 	xmlTreeIndentString = indent;
   3510     }
   3511 
   3512 
   3513     defaultEntityLoader = xmlGetExternalEntityLoader();
   3514     xmlSetExternalEntityLoader(xmllintExternalEntityLoader);
   3515 
   3516     xmlLineNumbersDefault(1);
   3517     if (loaddtd != 0)
   3518 	xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
   3519     if (dtdattrs)
   3520 	xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
   3521     if (noent != 0) xmlSubstituteEntitiesDefault(1);
   3522 #ifdef LIBXML_VALID_ENABLED
   3523     if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
   3524 #endif /* LIBXML_VALID_ENABLED */
   3525     if ((htmlout) && (!nowrap)) {
   3526 	xmlGenericError(xmlGenericErrorContext,
   3527          "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
   3528 	xmlGenericError(xmlGenericErrorContext,
   3529 		"\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
   3530 	xmlGenericError(xmlGenericErrorContext,
   3531 	 "<html><head><title>%s output</title></head>\n",
   3532 		argv[0]);
   3533 	xmlGenericError(xmlGenericErrorContext,
   3534 	 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
   3535 		argv[0]);
   3536     }
   3537 
   3538 #ifdef LIBXML_SCHEMATRON_ENABLED
   3539     if ((schematron != NULL) && (sax == 0)
   3540 #ifdef LIBXML_READER_ENABLED
   3541         && (stream == 0)
   3542 #endif /* LIBXML_READER_ENABLED */
   3543 	) {
   3544 	xmlSchematronParserCtxtPtr ctxt;
   3545 
   3546         /* forces loading the DTDs */
   3547         xmlLoadExtDtdDefaultValue |= 1;
   3548 	options |= XML_PARSE_DTDLOAD;
   3549 	if (timing) {
   3550 	    startTimer();
   3551 	}
   3552 	ctxt = xmlSchematronNewParserCtxt(schematron);
   3553 #if 0
   3554 	xmlSchematronSetParserErrors(ctxt,
   3555 		(xmlSchematronValidityErrorFunc) fprintf,
   3556 		(xmlSchematronValidityWarningFunc) fprintf,
   3557 		stderr);
   3558 #endif
   3559 	wxschematron = xmlSchematronParse(ctxt);
   3560 	if (wxschematron == NULL) {
   3561 	    xmlGenericError(xmlGenericErrorContext,
   3562 		    "Schematron schema %s failed to compile\n", schematron);
   3563             progresult = XMLLINT_ERR_SCHEMACOMP;
   3564 	    schematron = NULL;
   3565 	}
   3566 	xmlSchematronFreeParserCtxt(ctxt);
   3567 	if (timing) {
   3568 	    endTimer("Compiling the schemas");
   3569 	}
   3570     }
   3571 #endif
   3572 #ifdef LIBXML_SCHEMAS_ENABLED
   3573     if ((relaxng != NULL) && (sax == 0)
   3574 #ifdef LIBXML_READER_ENABLED
   3575         && (stream == 0)
   3576 #endif /* LIBXML_READER_ENABLED */
   3577 	) {
   3578 	xmlRelaxNGParserCtxtPtr ctxt;
   3579 
   3580         /* forces loading the DTDs */
   3581         xmlLoadExtDtdDefaultValue |= 1;
   3582 	options |= XML_PARSE_DTDLOAD;
   3583 	if (timing) {
   3584 	    startTimer();
   3585 	}
   3586 	ctxt = xmlRelaxNGNewParserCtxt(relaxng);
   3587 	xmlRelaxNGSetParserErrors(ctxt,
   3588 		(xmlRelaxNGValidityErrorFunc) fprintf,
   3589 		(xmlRelaxNGValidityWarningFunc) fprintf,
   3590 		stderr);
   3591 	relaxngschemas = xmlRelaxNGParse(ctxt);
   3592 	if (relaxngschemas == NULL) {
   3593 	    xmlGenericError(xmlGenericErrorContext,
   3594 		    "Relax-NG schema %s failed to compile\n", relaxng);
   3595             progresult = XMLLINT_ERR_SCHEMACOMP;
   3596 	    relaxng = NULL;
   3597 	}
   3598 	xmlRelaxNGFreeParserCtxt(ctxt);
   3599 	if (timing) {
   3600 	    endTimer("Compiling the schemas");
   3601 	}
   3602     } else if ((schema != NULL)
   3603 #ifdef LIBXML_READER_ENABLED
   3604 		&& (stream == 0)
   3605 #endif
   3606 	) {
   3607 	xmlSchemaParserCtxtPtr ctxt;
   3608 
   3609 	if (timing) {
   3610 	    startTimer();
   3611 	}
   3612 	ctxt = xmlSchemaNewParserCtxt(schema);
   3613 	xmlSchemaSetParserErrors(ctxt,
   3614 		(xmlSchemaValidityErrorFunc) fprintf,
   3615 		(xmlSchemaValidityWarningFunc) fprintf,
   3616 		stderr);
   3617 	wxschemas = xmlSchemaParse(ctxt);
   3618 	if (wxschemas == NULL) {
   3619 	    xmlGenericError(xmlGenericErrorContext,
   3620 		    "WXS schema %s failed to compile\n", schema);
   3621             progresult = XMLLINT_ERR_SCHEMACOMP;
   3622 	    schema = NULL;
   3623 	}
   3624 	xmlSchemaFreeParserCtxt(ctxt);
   3625 	if (timing) {
   3626 	    endTimer("Compiling the schemas");
   3627 	}
   3628     }
   3629 #endif /* LIBXML_SCHEMAS_ENABLED */
   3630 #ifdef LIBXML_PATTERN_ENABLED
   3631     if ((pattern != NULL)
   3632 #ifdef LIBXML_READER_ENABLED
   3633         && (walker == 0)
   3634 #endif
   3635 	) {
   3636         patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
   3637 	if (patternc == NULL) {
   3638 	    xmlGenericError(xmlGenericErrorContext,
   3639 		    "Pattern %s failed to compile\n", pattern);
   3640             progresult = XMLLINT_ERR_SCHEMAPAT;
   3641 	    pattern = NULL;
   3642 	}
   3643     }
   3644 #endif /* LIBXML_PATTERN_ENABLED */
   3645     for (i = 1; i < argc ; i++) {
   3646 	if ((!strcmp(argv[i], "-encode")) ||
   3647 	         (!strcmp(argv[i], "--encode"))) {
   3648 	    i++;
   3649 	    continue;
   3650         } else if ((!strcmp(argv[i], "-o")) ||
   3651                    (!strcmp(argv[i], "-output")) ||
   3652                    (!strcmp(argv[i], "--output"))) {
   3653             i++;
   3654 	    continue;
   3655         }
   3656 #ifdef LIBXML_VALID_ENABLED
   3657 	if ((!strcmp(argv[i], "-dtdvalid")) ||
   3658 	         (!strcmp(argv[i], "--dtdvalid"))) {
   3659 	    i++;
   3660 	    continue;
   3661         }
   3662 	if ((!strcmp(argv[i], "-path")) ||
   3663                    (!strcmp(argv[i], "--path"))) {
   3664             i++;
   3665 	    continue;
   3666         }
   3667 	if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
   3668 	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
   3669 	    i++;
   3670 	    continue;
   3671         }
   3672 #endif /* LIBXML_VALID_ENABLED */
   3673 	if ((!strcmp(argv[i], "-relaxng")) ||
   3674 	         (!strcmp(argv[i], "--relaxng"))) {
   3675 	    i++;
   3676 	    continue;
   3677         }
   3678 	if ((!strcmp(argv[i], "-maxmem")) ||
   3679 	         (!strcmp(argv[i], "--maxmem"))) {
   3680 	    i++;
   3681 	    continue;
   3682         }
   3683 	if ((!strcmp(argv[i], "-pretty")) ||
   3684 	         (!strcmp(argv[i], "--pretty"))) {
   3685 	    i++;
   3686 	    continue;
   3687         }
   3688 	if ((!strcmp(argv[i], "-schema")) ||
   3689 	         (!strcmp(argv[i], "--schema"))) {
   3690 	    i++;
   3691 	    continue;
   3692         }
   3693 	if ((!strcmp(argv[i], "-schematron")) ||
   3694 	         (!strcmp(argv[i], "--schematron"))) {
   3695 	    i++;
   3696 	    continue;
   3697         }
   3698 #ifdef LIBXML_PATTERN_ENABLED
   3699         if ((!strcmp(argv[i], "-pattern")) ||
   3700 	    (!strcmp(argv[i], "--pattern"))) {
   3701 	    i++;
   3702 	    continue;
   3703 	}
   3704 #endif
   3705 #ifdef LIBXML_XPATH_ENABLED
   3706         if ((!strcmp(argv[i], "-xpath")) ||
   3707 	    (!strcmp(argv[i], "--xpath"))) {
   3708 	    i++;
   3709 	    continue;
   3710 	}
   3711 #endif
   3712 	if ((timing) && (repeat))
   3713 	    startTimer();
   3714 	/* Remember file names.  "-" means stdin.  <sven (at) zen.org> */
   3715 	if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
   3716 	    if (repeat) {
   3717 		xmlParserCtxtPtr ctxt = NULL;
   3718 
   3719 		for (acount = 0;acount < repeat;acount++) {
   3720 #ifdef LIBXML_READER_ENABLED
   3721 		    if (stream != 0) {
   3722 			streamFile(argv[i]);
   3723 		    } else {
   3724 #endif /* LIBXML_READER_ENABLED */
   3725                         if (sax) {
   3726 			    testSAX(argv[i]);
   3727 			} else {
   3728 			    if (ctxt == NULL)
   3729 				ctxt = xmlNewParserCtxt();
   3730 			    parseAndPrintFile(argv[i], ctxt);
   3731 			}
   3732 #ifdef LIBXML_READER_ENABLED
   3733 		    }
   3734 #endif /* LIBXML_READER_ENABLED */
   3735 		}
   3736 		if (ctxt != NULL)
   3737 		    xmlFreeParserCtxt(ctxt);
   3738 	    } else {
   3739 		nbregister = 0;
   3740 
   3741 #ifdef LIBXML_READER_ENABLED
   3742 		if (stream != 0)
   3743 		    streamFile(argv[i]);
   3744 		else
   3745 #endif /* LIBXML_READER_ENABLED */
   3746                 if (sax) {
   3747 		    testSAX(argv[i]);
   3748 		} else {
   3749 		    parseAndPrintFile(argv[i], NULL);
   3750 		}
   3751 
   3752                 if ((chkregister) && (nbregister != 0)) {
   3753 		    fprintf(stderr, "Registration count off: %d\n", nbregister);
   3754 		    progresult = XMLLINT_ERR_RDREGIS;
   3755 		}
   3756 	    }
   3757 	    files ++;
   3758 	    if ((timing) && (repeat)) {
   3759 		endTimer("%d iterations", repeat);
   3760 	    }
   3761 	}
   3762     }
   3763     if (generate)
   3764 	parseAndPrintFile(NULL, NULL);
   3765     if ((htmlout) && (!nowrap)) {
   3766 	xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
   3767     }
   3768     if ((files == 0) && (!generate) && (version == 0)) {
   3769 	usage(stderr, argv[0]);
   3770     }
   3771 #ifdef LIBXML_SCHEMATRON_ENABLED
   3772     if (wxschematron != NULL)
   3773 	xmlSchematronFree(wxschematron);
   3774 #endif
   3775 #ifdef LIBXML_SCHEMAS_ENABLED
   3776     if (relaxngschemas != NULL)
   3777 	xmlRelaxNGFree(relaxngschemas);
   3778     if (wxschemas != NULL)
   3779 	xmlSchemaFree(wxschemas);
   3780     xmlRelaxNGCleanupTypes();
   3781 #endif
   3782 #ifdef LIBXML_PATTERN_ENABLED
   3783     if (patternc != NULL)
   3784         xmlFreePattern(patternc);
   3785 #endif
   3786     xmlCleanupParser();
   3787     xmlMemoryDump();
   3788 
   3789     return(progresult);
   3790 }
   3791 
   3792