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