fix some potential leaks in error cases. added --sax, to allow testing of

* parser.c: fix some potential leaks in error cases.
* xmllint.c: added --sax, to allow testing of --schemas --sax and
  various other combinations.
* xmlschemas.c: fix a couple of tiny problems in
  xmlSchemaValidateStream()
Daniel
diff --git a/ChangeLog b/ChangeLog
index 59fcdef..2c630a4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Fri Jul  8 19:25:26 CEST 2005 Daniel Veillard <daniel@veillard.com>
+
+	* parser.c: fix some potential leaks in error cases.
+	* xmllint.c: added --sax, to allow testing of --schemas --sax and
+	  various other combinations.
+	* xmlschemas.c: fix a couple of tiny problems in
+	  xmlSchemaValidateStream()
+
 Fri Jul  8 18:34:22 CEST 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
 	
 	* xmlschemas.c: Changed xmlSchemaValidateFile() to use
diff --git a/parser.c b/parser.c
index 744fc83..37533f7 100644
--- a/parser.c
+++ b/parser.c
@@ -10410,7 +10410,7 @@
 
     ctxt = xmlNewParserCtxt();
     if (ctxt == NULL) {
-	xmlFree(buf);
+	xmlFreeParserInputBuffer(buf);
 	return(NULL);
     }
     if (sax != NULL) {
@@ -10421,7 +10421,7 @@
 	ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
 	if (ctxt->sax == NULL) {
 	    xmlErrMemory(ctxt, NULL);
-	    xmlFree(ctxt);
+	    xmlFreeParserCtxt(ctxt);
 	    return(NULL);
 	}
 	memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
diff --git a/xmllint.c b/xmllint.c
index dbed44f..dbc5d35 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -190,6 +190,7 @@
 static xmlStreamCtxtPtr patstream = NULL;
 #endif
 static int options = 0;
+static int sax = 0;
 
 /************************************************************************
  *									*
@@ -800,12 +801,893 @@
   }
 }
 
-#ifdef LIBXML_READER_ENABLED
+/************************************************************************
+ *									*
+ *		 	SAX based tests					*
+ *									*
+ ************************************************************************/
+
+/*
+ * empty SAX block
+ */
+xmlSAXHandler emptySAXHandlerStruct = {
+    NULL, /* internalSubset */
+    NULL, /* isStandalone */
+    NULL, /* hasInternalSubset */
+    NULL, /* hasExternalSubset */
+    NULL, /* resolveEntity */
+    NULL, /* getEntity */
+    NULL, /* entityDecl */
+    NULL, /* notationDecl */
+    NULL, /* attributeDecl */
+    NULL, /* elementDecl */
+    NULL, /* unparsedEntityDecl */
+    NULL, /* setDocumentLocator */
+    NULL, /* startDocument */
+    NULL, /* endDocument */
+    NULL, /* startElement */
+    NULL, /* endElement */
+    NULL, /* reference */
+    NULL, /* characters */
+    NULL, /* ignorableWhitespace */
+    NULL, /* processingInstruction */
+    NULL, /* comment */
+    NULL, /* xmlParserWarning */
+    NULL, /* xmlParserError */
+    NULL, /* xmlParserError */
+    NULL, /* getParameterEntity */
+    NULL, /* cdataBlock; */
+    NULL, /* externalSubset; */
+    1,
+    NULL,
+    NULL, /* startElementNs */
+    NULL, /* endElementNs */
+    NULL  /* xmlStructuredErrorFunc */
+};
+
+xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
+extern xmlSAXHandlerPtr debugSAXHandler;
+static int callbacks;
+
+/**
+ * isStandaloneDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Is this document tagged standalone ?
+ *
+ * Returns 1 if true
+ */
+static int
+isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return(0);
+    fprintf(stdout, "SAX.isStandalone()\n");
+    return(0);
+}
+
+/**
+ * hasInternalSubsetDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an internal subset
+ *
+ * Returns 1 if true
+ */
+static int
+hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return(0);
+    fprintf(stdout, "SAX.hasInternalSubset()\n");
+    return(0);
+}
+
+/**
+ * hasExternalSubsetDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an external subset
+ *
+ * Returns 1 if true
+ */
+static int
+hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return(0);
+    fprintf(stdout, "SAX.hasExternalSubset()\n");
+    return(0);
+}
+
+/**
+ * internalSubsetDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an internal subset
+ */
+static void
+internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+	       const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.internalSubset(%s,", name);
+    if (ExternalID == NULL)
+	fprintf(stdout, " ,");
+    else
+	fprintf(stdout, " %s,", ExternalID);
+    if (SystemID == NULL)
+	fprintf(stdout, " )\n");
+    else
+	fprintf(stdout, " %s)\n", SystemID);
+}
+
+/**
+ * externalSubsetDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an external subset
+ */
+static void
+externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+	       const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.externalSubset(%s,", name);
+    if (ExternalID == NULL)
+	fprintf(stdout, " ,");
+    else
+	fprintf(stdout, " %s,", ExternalID);
+    if (SystemID == NULL)
+	fprintf(stdout, " )\n");
+    else
+	fprintf(stdout, " %s)\n", SystemID);
+}
+
+/**
+ * resolveEntityDebug:
+ * @ctxt:  An XML parser context
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * Special entity resolver, better left to the parser, it has
+ * more context than the application layer.
+ * The default behaviour is to NOT resolve the entities, in that case
+ * the ENTITY_REF nodes are built in the structure (and the parameter
+ * values).
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+static xmlParserInputPtr
+resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
+{
+    callbacks++;
+    if (noout)
+	return(NULL);
+    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
+
+    
+    fprintf(stdout, "SAX.resolveEntity(");
+    if (publicId != NULL)
+	fprintf(stdout, "%s", (char *)publicId);
+    else
+	fprintf(stdout, " ");
+    if (systemId != NULL)
+	fprintf(stdout, ", %s)\n", (char *)systemId);
+    else
+	fprintf(stdout, ", )\n");
+    return(NULL);
+}
+
+/**
+ * getEntityDebug:
+ * @ctxt:  An XML parser context
+ * @name: The entity name
+ *
+ * Get an entity by name
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+static xmlEntityPtr
+getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+    callbacks++;
+    if (noout)
+	return(NULL);
+    fprintf(stdout, "SAX.getEntity(%s)\n", name);
+    return(NULL);
+}
+
+/**
+ * getParameterEntityDebug:
+ * @ctxt:  An XML parser context
+ * @name: The entity name
+ *
+ * Get a parameter entity by name
+ *
+ * Returns the xmlParserInputPtr
+ */
+static xmlEntityPtr
+getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+    callbacks++;
+    if (noout)
+	return(NULL);
+    fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
+    return(NULL);
+}
+
+
+/**
+ * entityDeclDebug:
+ * @ctxt:  An XML parser context
+ * @name:  the entity name 
+ * @type:  the entity type 
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @content: the entity value (without processing).
+ *
+ * An entity definition has been parsed
+ */
+static void
+entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
+          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
+{
+const xmlChar *nullstr = BAD_CAST "(null)";
+    /* not all libraries handle printing null pointers nicely */
+    if (publicId == NULL)
+        publicId = nullstr;
+    if (systemId == NULL)
+        systemId = nullstr;
+    if (content == NULL)
+        content = (xmlChar *)nullstr;
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
+            name, type, publicId, systemId, content);
+}
+
+/**
+ * attributeDeclDebug:
+ * @ctxt:  An XML parser context
+ * @name:  the attribute name 
+ * @type:  the attribute type 
+ *
+ * An attribute definition has been parsed
+ */
+static void
+attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
+                   const xmlChar * name, int type, int def,
+                   const xmlChar * defaultValue, xmlEnumerationPtr tree)
+{
+    callbacks++;
+    if (noout)
+        return;
+    if (defaultValue == NULL)
+        fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
+                elem, name, type, def);
+    else
+        fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
+                elem, name, type, def, defaultValue);
+    xmlFreeEnumeration(tree);
+}
+
+/**
+ * elementDeclDebug:
+ * @ctxt:  An XML parser context
+ * @name:  the element name 
+ * @type:  the element type 
+ * @content: the element value (without processing).
+ *
+ * An element definition has been parsed
+ */
+static void
+elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
+	    xmlElementContentPtr content ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
+            name, type);
+}
+
+/**
+ * notationDeclDebug:
+ * @ctxt:  An XML parser context
+ * @name: The name of the notation
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * What to do when a notation declaration has been parsed.
+ */
+static void
+notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+	     const xmlChar *publicId, const xmlChar *systemId)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
+            (char *) name, (char *) publicId, (char *) systemId);
+}
+
+/**
+ * unparsedEntityDeclDebug:
+ * @ctxt:  An XML parser context
+ * @name: The name of the entity
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @notationName: the name of the notation
+ *
+ * What to do when an unparsed entity declaration is parsed
+ */
+static void
+unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+		   const xmlChar *publicId, const xmlChar *systemId,
+		   const xmlChar *notationName)
+{
+const xmlChar *nullstr = BAD_CAST "(null)";
+
+    if (publicId == NULL)
+        publicId = nullstr;
+    if (systemId == NULL)
+        systemId = nullstr;
+    if (notationName == NULL)
+        notationName = nullstr;
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
+            (char *) name, (char *) publicId, (char *) systemId,
+	    (char *) notationName);
+}
+
+/**
+ * setDocumentLocatorDebug:
+ * @ctxt:  An XML parser context
+ * @loc: A SAX Locator
+ *
+ * Receive the document locator at startup, actually xmlDefaultSAXLocator
+ * Everything is available on the context, so this is useless in our case.
+ */
+static void
+setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.setDocumentLocator()\n");
+}
+
+/**
+ * startDocumentDebug:
+ * @ctxt:  An XML parser context
+ *
+ * called when the document start being processed.
+ */
+static void
+startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.startDocument()\n");
+}
+
+/**
+ * endDocumentDebug:
+ * @ctxt:  An XML parser context
+ *
+ * called when the document end has been detected.
+ */
+static void
+endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.endDocument()\n");
+}
+
+/**
+ * startElementDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The element name
+ *
+ * called when an opening tag has been processed.
+ */
+static void
+startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
+{
+    int i;
+
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.startElement(%s", (char *) name);
+    if (atts != NULL) {
+        for (i = 0;(atts[i] != NULL);i++) {
+	    fprintf(stdout, ", %s='", atts[i++]);
+	    if (atts[i] != NULL)
+	        fprintf(stdout, "%s'", atts[i]);
+	}
+    }
+    fprintf(stdout, ")\n");
+}
+
+/**
+ * endElementDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The element name
+ *
+ * called when the end of an element has been detected.
+ */
+static void
+endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
+}
+
+/**
+ * charactersDebug:
+ * @ctxt:  An XML parser context
+ * @ch:  a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some chars from the parser.
+ * Question: how much at a time ???
+ */
+static void
+charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+    char out[40];
+    int i;
+
+    callbacks++;
+    if (noout)
+	return;
+    for (i = 0;(i<len) && (i < 30);i++)
+	out[i] = ch[i];
+    out[i] = 0;
+
+    fprintf(stdout, "SAX.characters(%s, %d)\n", out, len);
+}
+
+/**
+ * referenceDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The entity name
+ *
+ * called when an entity reference is detected. 
+ */
+static void
+referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.reference(%s)\n", name);
+}
+
+/**
+ * ignorableWhitespaceDebug:
+ * @ctxt:  An XML parser context
+ * @ch:  a xmlChar string
+ * @start: the first char in the string
+ * @len: the number of xmlChar
+ *
+ * receiving some ignorable whitespaces from the parser.
+ * Question: how much at a time ???
+ */
+static void
+ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+    char out[40];
+    int i;
+
+    callbacks++;
+    if (noout)
+	return;
+    for (i = 0;(i<len) && (i < 30);i++)
+	out[i] = ch[i];
+    out[i] = 0;
+    fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", out, len);
+}
+
+/**
+ * processingInstructionDebug:
+ * @ctxt:  An XML parser context
+ * @target:  the target name
+ * @data: the PI data's
+ * @len: the number of xmlChar
+ *
+ * A processing instruction has been parsed.
+ */
+static void
+processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
+                      const xmlChar *data)
+{
+    callbacks++;
+    if (noout)
+	return;
+    if (data != NULL)
+	fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
+		(char *) target, (char *) data);
+    else
+	fprintf(stdout, "SAX.processingInstruction(%s, NULL)\n",
+		(char *) target);
+}
+
+/**
+ * cdataBlockDebug:
+ * @ctx: the user data (XML parser context)
+ * @value:  The pcdata content
+ * @len:  the block length
+ *
+ * called when a pcdata block has been parsed
+ */
+static void
+cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.pcdata(%.20s, %d)\n",
+	    (char *) value, len);
+}
+
+/**
+ * commentDebug:
+ * @ctxt:  An XML parser context
+ * @value:  the comment content
+ *
+ * A comment has been parsed.
+ */
+static void
+commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.comment(%s)\n", value);
+}
+
+/**
+ * warningDebug:
+ * @ctxt:  An XML parser context
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ *
+ * Display and format a warning messages, gives file, line, position and
+ * extra parameters.
+ */
+static void
+warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
+{
+    va_list args;
+
+    callbacks++;
+    if (noout)
+	return;
+    va_start(args, msg);
+    fprintf(stdout, "SAX.warning: ");
+    vfprintf(stdout, msg, args);
+    va_end(args);
+}
+
+/**
+ * errorDebug:
+ * @ctxt:  An XML parser context
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ *
+ * Display and format a error messages, gives file, line, position and
+ * extra parameters.
+ */
+static void
+errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
+{
+    va_list args;
+
+    callbacks++;
+    if (noout)
+	return;
+    va_start(args, msg);
+    fprintf(stdout, "SAX.error: ");
+    vfprintf(stdout, msg, args);
+    va_end(args);
+}
+
+/**
+ * fatalErrorDebug:
+ * @ctxt:  An XML parser context
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ *
+ * Display and format a fatalError messages, gives file, line, position and
+ * extra parameters.
+ */
+static void
+fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
+{
+    va_list args;
+
+    callbacks++;
+    if (noout)
+	return;
+    va_start(args, msg);
+    fprintf(stdout, "SAX.fatalError: ");
+    vfprintf(stdout, msg, args);
+    va_end(args);
+}
+
+xmlSAXHandler debugSAXHandlerStruct = {
+    internalSubsetDebug,
+    isStandaloneDebug,
+    hasInternalSubsetDebug,
+    hasExternalSubsetDebug,
+    resolveEntityDebug,
+    getEntityDebug,
+    entityDeclDebug,
+    notationDeclDebug,
+    attributeDeclDebug,
+    elementDeclDebug,
+    unparsedEntityDeclDebug,
+    setDocumentLocatorDebug,
+    startDocumentDebug,
+    endDocumentDebug,
+    startElementDebug,
+    endElementDebug,
+    referenceDebug,
+    charactersDebug,
+    ignorableWhitespaceDebug,
+    processingInstructionDebug,
+    commentDebug,
+    warningDebug,
+    errorDebug,
+    fatalErrorDebug,
+    getParameterEntityDebug,
+    cdataBlockDebug,
+    externalSubsetDebug,
+    1,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
+
+/*
+ * SAX2 specific callbacks
+ */
+/**
+ * startElementNsDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The element name
+ *
+ * called when an opening tag has been processed.
+ */
+static void
+startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
+                    const xmlChar *localname,
+                    const xmlChar *prefix,
+                    const xmlChar *URI,
+		    int nb_namespaces,
+		    const xmlChar **namespaces,
+		    int nb_attributes,
+		    int nb_defaulted,
+		    const xmlChar **attributes)
+{
+    int i;
+
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.startElementNs(%s", (char *) localname);
+    if (prefix == NULL)
+	fprintf(stdout, ", NULL");
+    else
+	fprintf(stdout, ", %s", (char *) prefix);
+    if (URI == NULL)
+	fprintf(stdout, ", NULL");
+    else
+	fprintf(stdout, ", '%s'", (char *) URI);
+    fprintf(stdout, ", %d", nb_namespaces);
+    
+    if (namespaces != NULL) {
+        for (i = 0;i < nb_namespaces * 2;i++) {
+	    fprintf(stdout, ", xmlns");
+	    if (namespaces[i] != NULL)
+	        fprintf(stdout, ":%s", namespaces[i]);
+	    i++;
+	    fprintf(stdout, "='%s'", namespaces[i]);
+	}
+    }
+    fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted);
+    if (attributes != NULL) {
+        for (i = 0;i < nb_attributes * 5;i += 5) {
+	    if (attributes[i + 1] != NULL)
+		fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]);
+	    else
+		fprintf(stdout, ", %s='", attributes[i]);
+	    fprintf(stdout, "%.4s...', %d", attributes[i + 3],
+		    (int)(attributes[i + 4] - attributes[i + 3]));
+	}
+    }
+    fprintf(stdout, ")\n");
+}
+
+/**
+ * endElementDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The element name
+ *
+ * called when the end of an element has been detected.
+ */
+static void
+endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
+                  const xmlChar *localname,
+                  const xmlChar *prefix,
+                  const xmlChar *URI)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.endElementNs(%s", (char *) localname);
+    if (prefix == NULL)
+	fprintf(stdout, ", NULL");
+    else
+	fprintf(stdout, ", %s", (char *) prefix);
+    if (URI == NULL)
+	fprintf(stdout, ", NULL)\n");
+    else
+	fprintf(stdout, ", '%s')\n", (char *) URI);
+}
+
+xmlSAXHandler debugSAX2HandlerStruct = {
+    internalSubsetDebug,
+    isStandaloneDebug,
+    hasInternalSubsetDebug,
+    hasExternalSubsetDebug,
+    resolveEntityDebug,
+    getEntityDebug,
+    entityDeclDebug,
+    notationDeclDebug,
+    attributeDeclDebug,
+    elementDeclDebug,
+    unparsedEntityDeclDebug,
+    setDocumentLocatorDebug,
+    startDocumentDebug,
+    endDocumentDebug,
+    NULL,
+    NULL,
+    referenceDebug,
+    charactersDebug,
+    ignorableWhitespaceDebug,
+    processingInstructionDebug,
+    commentDebug,
+    warningDebug,
+    errorDebug,
+    fatalErrorDebug,
+    getParameterEntityDebug,
+    cdataBlockDebug,
+    externalSubsetDebug,
+    XML_SAX2_MAGIC,
+    NULL,
+    startElementNsDebug,
+    endElementNsDebug,
+    NULL
+};
+
+xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
+
+static void
+testSAX(const char *filename) {
+    xmlSAXHandlerPtr handler;
+    const char *user_data = "user_data"; /* mostly for debugging */
+    xmlParserInputBufferPtr buf = NULL;
+    xmlParserInputPtr inputStream;
+    xmlParserCtxtPtr ctxt = NULL;
+    xmlSAXHandlerPtr old_sax = NULL;
+
+    callbacks = 0;
+
+    if (noout) {
+        handler = emptySAXHandler;
+    } else if (sax1) {
+        handler = debugSAXHandler;
+    } else {
+        handler = debugSAX2Handler;
+    }
+
+    /*
+     * it's not the simplest code but the most generic in term of I/O
+     */
+    buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
+    if (buf == NULL) {
+        goto error;
+    }
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+    if (wxschemas != NULL) {
+        int ret;
+	xmlSchemaValidCtxtPtr vctxt;
+
+	vctxt = xmlSchemaNewValidCtxt(wxschemas);
+	xmlSchemaSetValidErrors(vctxt,
+		(xmlSchemaValidityErrorFunc) fprintf,
+		(xmlSchemaValidityWarningFunc) fprintf,
+		stderr);
+
+	ret = xmlSchemaValidateStream(vctxt, buf, 0, handler, user_data);
+	if (ret == 0) {
+	    fprintf(stderr, "%s validates\n", filename);
+	} else if (ret > 0) {
+	    fprintf(stderr, "%s fails to validate\n", filename);
+	    progresult = XMLLINT_ERR_VALID;
+	} else {
+	    fprintf(stderr, "%s validation generated an internal error\n",
+		   filename);
+	    progresult = XMLLINT_ERR_VALID;
+	}
+	xmlSchemaFreeValidCtxt(vctxt);
+    } else
+#endif
+    {
+	/*
+	 * Create the parser context amd hook the input
+	 */
+	ctxt = xmlNewParserCtxt();
+	if (ctxt == NULL) {
+	    xmlFreeParserInputBuffer(buf);
+	    goto error;
+	}
+	old_sax = ctxt->sax;
+	ctxt->sax = handler;
+	ctxt->userData = (void *) user_data;
+	inputStream = xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE);
+	if (inputStream == NULL) {
+	    xmlFreeParserInputBuffer(buf);
+	    goto error;
+	}
+	inputPush(ctxt, inputStream);
+	
+	/* do the parsing */
+	xmlParseDocument(ctxt);
+
+	if (ctxt->myDoc != NULL) {
+	    fprintf(stderr, "SAX generated a doc !\n");
+	    xmlFreeDoc(ctxt->myDoc);
+	    ctxt->myDoc = NULL;
+	}
+    }
+
+error:
+    if (ctxt != NULL) {
+        ctxt->sax = old_sax;
+        xmlFreeParserCtxt(ctxt);
+    }
+}
+
 /************************************************************************
  * 									*
  * 			Stream Test processing				*
  * 									*
  ************************************************************************/
+#ifdef LIBXML_READER_ENABLED
 static void processNode(xmlTextReaderPtr reader) {
     const xmlChar *name, *value;
     int type, empty;
@@ -2185,6 +3067,10 @@
 	     sax1++;
 	}
 #endif /* LIBXML_SAX1_ENABLED */
+	else if ((!strcmp(argv[i], "-sax")) ||
+	         (!strcmp(argv[i], "--sax"))) {
+	     sax++;
+	}
 	else if ((!strcmp(argv[i], "-chkregister")) ||
 	         (!strcmp(argv[i], "--chkregister"))) {
 	     chkregister++;
@@ -2283,7 +3169,7 @@
     }
 
 #ifdef LIBXML_SCHEMAS_ENABLED
-    if ((relaxng != NULL)
+    if ((relaxng != NULL) && (sax == 0)
 #ifdef LIBXML_READER_ENABLED
         && (stream == 0)
 #endif /* LIBXML_READER_ENABLED */
@@ -2418,9 +3304,13 @@
 			streamFile(argv[i]);
 		    } else {
 #endif /* LIBXML_READER_ENABLED */
-		        if (ctxt == NULL)
-			    ctxt = xmlNewParserCtxt();
-			parseAndPrintFile(argv[i], ctxt);
+                        if (sax) {
+			    testSAX(argv[i]);
+			} else {
+			    if (ctxt == NULL)
+				ctxt = xmlNewParserCtxt();
+			    parseAndPrintFile(argv[i], ctxt);
+			}
 #ifdef LIBXML_READER_ENABLED
 		    }
 #endif /* LIBXML_READER_ENABLED */
@@ -2435,7 +3325,11 @@
 		    streamFile(argv[i]);
 		else
 #endif /* LIBXML_READER_ENABLED */
+                if (sax) {
+		    testSAX(argv[i]);
+		} else {
 		    parseAndPrintFile(argv[i], NULL);
+		}
 
                 if ((chkregister) && (nbregister != 0)) {
 		    fprintf(stderr, "Registration count off: %d\n", nbregister);
diff --git a/xmlschemas.c b/xmlschemas.c
index 0bd6423..7dbada0 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -24402,6 +24402,7 @@
         return (-1);
     old_sax = pctxt->sax;
     pctxt->sax = &schemas_sax;
+    pctxt->userData = &split_block;
 #if 0
     if (options)
         xmlCtxtUseOptions(pctxt, options);
@@ -24409,7 +24410,7 @@
     pctxt->linenumbers = 1;
     pctxt->userData = (void *) ctxt;
 
-    inputStream = xmlNewIOInputStream(pctxt, input, XML_CHAR_ENCODING_NONE);;
+    inputStream = xmlNewIOInputStream(pctxt, input, enc);;
     if (inputStream == NULL) {
         ret = -1;
 	goto done;