- Makefile.am xmlversion.h.in configure.in include/Makefile.am:
  integrating catalogs
- catalog.[ch] testCatalog.c: adding a small catalo API
  (only SGML catalog support).
- parser.c: restaured xmlKeepBlanksDefault(0) API
Daniel
diff --git a/ChangeLog b/ChangeLog
index df34aa9..01e06eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Thu May 10 16:14:36 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+	* Makefile.am xmlversion.h.in configure.in include/Makefile.am:
+	  integrating catalogs
+	* catalog.[ch] testCatalog.c: adding a small catalo API
+	  (only SGML catalog support).
+	* parser.c: restaured xmlKeepBlanksDefault(0) API
+
 Wed May  9 12:50:15 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
 
 	* tree.c: zb@bisp.com reported an error in xmlNodeGetLang()
diff --git a/Makefile.am b/Makefile.am
index 7dc7017..67dceba 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,7 +4,7 @@
 
 INCLUDES = -I@srcdir@/include -I./include @Z_CFLAGS@ @CORBA_CFLAGS@ 
 
-noinst_PROGRAMS=testSAX testHTML testXPath testURI testDocbook
+noinst_PROGRAMS=testSAX testHTML testXPath testURI testDocbook testCatalog
 
 bin_PROGRAMS = xmllint
 
@@ -20,13 +20,14 @@
 		parser.c tree.c hash.c list.c xmlIO.c xmlmemory.c uri.c  \
 		valid.c xlink.c HTMLparser.c HTMLtree.c debugXML.c xpath.c  \
 		xpointer.c xinclude.c nanohttp.c nanoftp.c DOCBparser.c \
-		strio.c trio.c
+		catalog.c strio.c trio.c
 
 else
 libxml2_la_SOURCES = SAX.c entities.c encoding.c error.c parserInternals.c  \
 		parser.c tree.c hash.c list.c xmlIO.c xmlmemory.c uri.c  \
 		valid.c xlink.c HTMLparser.c HTMLtree.c debugXML.c xpath.c  \
-		xpointer.c xinclude.c nanohttp.c nanoftp.c DOCBparser.c
+		xpointer.c xinclude.c nanohttp.c nanoftp.c DOCBparser.c \
+		catalog.c
 
 endif
 
@@ -58,6 +59,11 @@
 testDocbook_DEPENDENCIES = $(DEPS)
 testDocbook_LDADD= $(LDADDS)
 
+testCatalog_SOURCES=testCatalog.c
+testCatalog_LDFLAGS = 
+testCatalog_DEPENDENCIES = $(DEPS)
+testCatalog_LDADD= $(LDADDS)
+
 testXPath_SOURCES=testXPath.c
 testXPath_LDFLAGS = 
 testXPath_DEPENDENCIES = $(DEPS)
diff --git a/catalog.c b/catalog.c
new file mode 100644
index 0000000..437474a
--- /dev/null
+++ b/catalog.c
@@ -0,0 +1,531 @@
+/**
+ * catalog.c: set of generic Catalog related routines 
+ *
+ * Reference:  SGML Open Technical Resolution TR9401:1997.
+ *             http://www.jclark.com/sp/catalog.htm
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel.Veillard@imag.fr
+ */
+
+#include "libxml.h"
+
+#ifdef LIBXML_CATALOG_ENABLED
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/hash.h>
+#include <libxml/uri.h>
+#include <libxml/parserInternals.h>
+#include <libxml/catalog.h>
+#include <libxml/xmlerror.h>
+
+/************************************************************************
+ *									*
+ *			Types, all private				*
+ *									*
+ ************************************************************************/
+
+typedef enum {
+    XML_CATA_NONE = 0,
+    XML_CATA_SYSTEM,
+    XML_CATA_PUBLIC,
+    XML_CATA_ENTITY,
+    XML_CATA_PENTITY,
+    XML_CATA_DOCTYPE,
+    XML_CATA_LINKTYPE,
+    XML_CATA_NOTATION,
+    XML_CATA_DELEGATE,
+    XML_CATA_BASE,
+    XML_CATA_CATALOG,
+    XML_CATA_DOCUMENT,
+    XML_CATA_SGMLDECL
+} xmlCatalogEntryType;
+
+typedef struct _xmlCatalogEntry xmlCatalogEntry;
+typedef xmlCatalogEntry *xmlCatalogEntryPtr;
+struct _xmlCatalogEntry {
+    xmlCatalogEntryType type;
+    xmlChar *name;
+    xmlChar *value;
+};
+
+static xmlHashTablePtr xmlDefaultCatalog;
+
+/************************************************************************
+ *									*
+ *			alloc or dealloc				*
+ *									*
+ ************************************************************************/
+
+static xmlCatalogEntryPtr
+xmlNewCatalogEntry(int type, xmlChar *name, xmlChar *value) {
+    xmlCatalogEntryPtr ret;
+
+    ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry));
+    if (ret == NULL) {
+	xmlGenericError(xmlGenericErrorContext,
+		"malloc of %d byte failed\n", sizeof(xmlCatalogEntry));
+	return(NULL);
+    }
+    ret->type = type;
+    ret->name = name;
+    ret->value = value;
+    return(ret);
+}
+
+static void
+xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) {
+    if (ret == NULL)
+	return;
+    if (ret->name != NULL)
+	xmlFree(ret->name);
+    if (ret->value != NULL)
+	xmlFree(ret->value);
+    xmlFree(ret);
+}
+
+/************************************************************************
+ *									*
+ *			The parser					*
+ *									*
+ ************************************************************************/
+
+
+#define RAW *cur
+#define NEXT cur++;
+#define SKIP(x) cur += x;
+
+#define SKIP_BLANKS while (IS_BLANK(*cur)) NEXT;
+
+static const xmlChar *
+xmlParseCatalogComment(const xmlChar *cur) {
+    if ((cur[0] != '-') || (cur[1] != '-')) 
+	return(cur);
+    SKIP(2);
+    while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-'))))
+	NEXT;
+    if (cur[0] == 0) {
+	return(NULL);
+    }
+    return(cur);
+}
+
+static const xmlChar *
+xmlParseCatalogPubid(const xmlChar *cur, xmlChar **id) {
+    xmlChar *buf = NULL;
+    int len = 0;
+    int size = 50;
+    xmlChar stop;
+    int count = 0;
+
+    *id = NULL;
+
+    if (RAW == '"') {
+        NEXT;
+	stop = '"';
+    } else if (RAW == '\'') {
+        NEXT;
+	stop = '\'';
+    } else {
+	stop = ' ';
+    }
+    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
+    if (buf == NULL) {
+	xmlGenericError(xmlGenericErrorContext,
+		"malloc of %d byte failed\n", size);
+	return(NULL);
+    }
+    while (xmlIsPubidChar(*cur)) {
+	if ((*cur == stop) && (stop != ' '))
+	    break;
+	if ((stop == ' ') && (IS_BLANK(*cur)))
+	    break;
+	if (len + 1 >= size) {
+	    size *= 2;
+	    buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+	    if (buf == NULL) {
+		xmlGenericError(xmlGenericErrorContext,
+			"realloc of %d byte failed\n", size);
+		return(NULL);
+	    }
+	}
+	buf[len++] = *cur;
+	count++;
+	NEXT;
+    }
+    buf[len] = 0;
+    if (stop == ' ') {
+	if (!IS_BLANK(*cur)) {
+	    xmlFree(buf);
+	    return(NULL);
+	}
+    } else {
+	if (*cur != stop) {
+	    xmlFree(buf);
+	    return(NULL);
+	}
+	NEXT;
+    }
+    *id = buf;
+    return(cur);
+}
+
+static const xmlChar *
+xmlParseCatalogName(const xmlChar *cur, xmlChar **name) {
+    xmlChar buf[XML_MAX_NAMELEN + 5];
+    int len = 0;
+    int c;
+
+    *name = NULL;
+
+    /*
+     * Handler for more complex cases
+     */
+    c = *cur;
+    if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) {
+	return(NULL);
+    }
+
+    while (((IS_LETTER(c)) || (IS_DIGIT(c)) ||
+            (c == '.') || (c == '-') ||
+	    (c == '_') || (c == ':'))) {
+	buf[len++] = c;
+	cur++;
+	c = *cur;
+	if (len >= XML_MAX_NAMELEN)
+	    return(NULL);
+    }
+    *name = xmlStrndup(buf, len);
+    return(cur);
+}
+
+static int
+xmlParseCatalog(const xmlChar *value, const char *file) {
+    const xmlChar *cur = value;
+    xmlChar *base = NULL;
+
+    if ((cur == NULL) || (file == NULL))
+        return(-1);
+    base = xmlStrdup((const xmlChar *) file);
+
+    while ((cur != NULL) && (cur[0] != '0')) {
+	SKIP_BLANKS;
+	if ((cur[0] == '-') && (cur[1] == '-')) {
+	    cur = xmlParseCatalogComment(cur);
+	    if (cur == NULL) {
+		/* error */
+		break;
+	    }
+	} else {
+	    xmlChar *sysid = NULL;
+	    xmlChar *name = NULL;
+	    xmlCatalogEntryType type = XML_CATA_NONE;
+
+	    cur = xmlParseCatalogName(cur, &name);
+	    if (name == NULL) {
+		/* error */
+		break;
+	    }
+	    if (!IS_BLANK(*cur)) {
+		/* error */
+		break;
+	    }
+	    SKIP_BLANKS;
+	    if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
+                type = XML_CATA_SYSTEM;
+	    else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
+                type = XML_CATA_PUBLIC;
+	    else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
+                type = XML_CATA_DELEGATE;
+	    else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
+                type = XML_CATA_ENTITY;
+	    else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
+                type = XML_CATA_DOCTYPE;
+	    else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
+                type = XML_CATA_LINKTYPE;
+	    else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
+                type = XML_CATA_NOTATION;
+	    else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
+                type = XML_CATA_SGMLDECL;
+	    else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
+                type = XML_CATA_DOCUMENT;
+	    else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
+                type = XML_CATA_CATALOG;
+	    else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
+                type = XML_CATA_BASE;
+	    else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
+                type = XML_CATA_DELEGATE;
+	    else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) {
+		xmlFree(name);
+		cur = xmlParseCatalogName(cur, &name);
+		if (name == NULL) {
+		    /* error */
+		    break;
+		}
+		continue;
+	    }
+	    xmlFree(name);
+
+	    switch(type) {
+		case XML_CATA_ENTITY:
+		    if (*cur == '%')
+			type = XML_CATA_PENTITY;
+		case XML_CATA_PENTITY:
+		case XML_CATA_DOCTYPE:
+		case XML_CATA_LINKTYPE:
+		case XML_CATA_NOTATION:
+		    cur = xmlParseCatalogName(cur, &name);
+		    if (cur == NULL) {
+			/* error */
+			break;
+		    }
+		    if (!IS_BLANK(*cur)) {
+			/* error */
+			break;
+		    }
+		    SKIP_BLANKS;
+		    cur = xmlParseCatalogPubid(cur, &sysid);
+		    if (cur == NULL) {
+			/* error */
+			break;
+		    }
+		    break;
+		case XML_CATA_PUBLIC:
+		case XML_CATA_SYSTEM:
+		case XML_CATA_DELEGATE:
+		    cur = xmlParseCatalogPubid(cur, &name);
+		    if (cur == NULL) {
+			/* error */
+			break;
+		    }
+		    if (!IS_BLANK(*cur)) {
+			/* error */
+			break;
+		    }
+		    SKIP_BLANKS;
+		    cur = xmlParseCatalogPubid(cur, &sysid);
+		    if (cur == NULL) {
+			/* error */
+			break;
+		    }
+		    break;
+		case XML_CATA_BASE:
+		case XML_CATA_CATALOG:
+		case XML_CATA_DOCUMENT:
+		case XML_CATA_SGMLDECL:
+		    cur = xmlParseCatalogPubid(cur, &sysid);
+		    if (cur == NULL) {
+			/* error */
+			break;
+		    }
+		    break;
+		default:
+		    break;
+	    }
+	    if (cur == NULL) {
+		if (name != NULL)
+		    xmlFree(name);
+		if (sysid != NULL)
+		    xmlFree(sysid);
+		break;
+	    } else if (type == XML_CATA_BASE) {
+		if (base != NULL)
+		    xmlFree(base);
+		base = sysid;
+	    } else if ((type == XML_CATA_PUBLIC) ||
+		       (type == XML_CATA_SYSTEM)) {
+		xmlChar *filename;
+
+		filename = xmlBuildURI(sysid, base);
+		if (filename != NULL) {
+
+		    xmlHashAddEntry(xmlDefaultCatalog, name,
+		            xmlNewCatalogEntry(type, name, filename));
+		}
+		if (sysid != NULL)
+		    xmlFree(sysid);
+	    } else {
+		/*
+		 * drop anything else we won't handle it
+		 */
+		if (name != NULL)
+		    xmlFree(name);
+		if (sysid != NULL)
+		    xmlFree(sysid);
+	    }
+	}
+    }
+    if (base != NULL)
+	xmlFree(base);
+    if (cur == NULL)
+	return(-1);
+    return(0);
+}
+
+/************************************************************************
+ *									*
+ *			Public interfaces				*
+ *									*
+ ************************************************************************/
+
+/*
+ * xmlLoadCatalog:
+ * @filename:  a file path
+ *
+ * Load the catalog and makes its definition effective for the default
+ * external entity loader.
+ *
+ * Returns 0 in case of success -1 in case of error
+ */
+int
+xmlLoadCatalog(const char *filename) {
+    int fd, len, ret;
+    struct stat info;
+    xmlChar *content;
+
+    if (filename == NULL)
+	return(-1);
+    if (xmlDefaultCatalog == NULL)
+	xmlDefaultCatalog = xmlHashCreate(20);
+    if (xmlDefaultCatalog == NULL)
+	return(-1);
+    
+    if (stat(filename, &info) < 0) 
+	return(-1);
+
+    if ((fd = open(filename, O_RDONLY)) < 0)
+	return(-1);
+
+    content = xmlMalloc(info.st_size + 10);
+    if (content == NULL) {
+	xmlGenericError(xmlGenericErrorContext,
+		"realloc of %d byte failed\n", info.st_size + 10);
+    }
+    len = read(fd, content, info.st_size);
+    if (len < 0) {
+	xmlFree(content);
+	return(-1);
+    }
+    content[len] = 0;
+    close(fd);
+
+    ret = xmlParseCatalog(content, filename);
+    xmlFree(content);
+    return(ret);
+}
+
+/**
+ * xmlCatalogCleanup:
+ *
+ * Free up all the memory associated with catalogs
+ */
+void
+xmlCatalogCleanup(void) {
+    if (xmlDefaultCatalog != NULL)
+	xmlHashFree(xmlDefaultCatalog,
+		    (xmlHashDeallocator) xmlFreeCatalogEntry);
+    xmlDefaultCatalog = NULL;
+}
+
+/**
+ * xmlCatalogDumpEntry:
+ * @entry:  the 
+ * @out:  the file.
+ *
+ * Free up all the memory associated with catalogs
+ */
+static void
+xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) {
+    if ((entry == NULL) || (out == NULL))
+	return;
+    switch (entry->type) {
+	case XML_CATA_ENTITY:
+	    fprintf(out, "ENTITY "); break;
+	case XML_CATA_PENTITY:
+	    fprintf(out, "ENTITY %%"); break;
+	case XML_CATA_DOCTYPE:
+	    fprintf(out, "DOCTYPE "); break;
+	case XML_CATA_LINKTYPE:
+	    fprintf(out, "LINKTYPE "); break;
+	case XML_CATA_NOTATION:
+	    fprintf(out, "NOTATION "); break;
+	case XML_CATA_PUBLIC:
+	    fprintf(out, "PUBLIC "); break;
+	case XML_CATA_SYSTEM:
+	    fprintf(out, "SYSTEM "); break;
+	case XML_CATA_DELEGATE:
+	    fprintf(out, "DELEGATE "); break;
+	case XML_CATA_BASE:
+	    fprintf(out, "BASE "); break;
+	case XML_CATA_CATALOG:
+	    fprintf(out, "CATALOG "); break;
+	case XML_CATA_DOCUMENT:
+	    fprintf(out, "DOCUMENT "); break;
+	case XML_CATA_SGMLDECL:
+	    fprintf(out, "SGMLDECL "); break;
+	default:
+	    return;
+    }
+    switch (entry->type) {
+	case XML_CATA_ENTITY:
+	case XML_CATA_PENTITY:
+	case XML_CATA_DOCTYPE:
+	case XML_CATA_LINKTYPE:
+	case XML_CATA_NOTATION:
+	    fprintf(out, "%s", entry->name); break;
+	case XML_CATA_PUBLIC:
+	case XML_CATA_SYSTEM:
+	case XML_CATA_SGMLDECL:
+	case XML_CATA_DOCUMENT:
+	case XML_CATA_CATALOG:
+	case XML_CATA_BASE:
+	case XML_CATA_DELEGATE:
+	    fprintf(out, "\"%s\"", entry->name); break;
+	default:
+	    break;
+    }
+    switch (entry->type) {
+	case XML_CATA_ENTITY:
+	case XML_CATA_PENTITY:
+	case XML_CATA_DOCTYPE:
+	case XML_CATA_LINKTYPE:
+	case XML_CATA_NOTATION:
+	case XML_CATA_PUBLIC:
+	case XML_CATA_SYSTEM:
+	case XML_CATA_DELEGATE:
+	    fprintf(out, " \"%s\"", entry->value); break;
+	default:
+	    break;
+    }
+    fprintf(out, "\n");
+}
+
+/**
+ * xmlCatalogDump:
+ * @out:  the file.
+ *
+ * Free up all the memory associated with catalogs
+ */
+void
+xmlCatalogDump(FILE *out) {
+    if (out == NULL)
+	return;
+    if (xmlDefaultCatalog != NULL) {
+	xmlHashScan(xmlDefaultCatalog,
+		    (xmlHashScanner) xmlCatalogDumpEntry, out);
+    }
+}
+#endif /* LIBXML_CATALOG_ENABLED */
diff --git a/catalog.h b/catalog.h
new file mode 100644
index 0000000..f91ee94
--- /dev/null
+++ b/catalog.h
@@ -0,0 +1,32 @@
+/**
+ * uri.c: interfaces of the Catalog handling system
+ *
+ * Reference:  SGML Open Technical Resolution TR9401:1997.
+ *             http://www.jclark.com/sp/catalog.htm
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel.Veillard@w3.org
+ */
+
+#ifndef __XML_CATALOG_H__
+#define __XML_CATALOG_H__
+
+#include <stdio.h>
+
+#include <libxml/xmlversion.h>
+#ifdef LIBXML_CATALOG_ENABLED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int	xmlLoadCatalog		(const char *URL);
+void	xmlCatalogCleanup	(void);
+void	xmlCatalogDump		(FILE *out);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* LIBXML_CATALOG_ENABLED */
+#endif /* __XML_CATALOG_H__ */
diff --git a/configure.in b/configure.in
index 3149944..7f5dda9 100644
--- a/configure.in
+++ b/configure.in
@@ -301,6 +301,18 @@
 AC_SUBST(WITH_HTML)
 AC_SUBST(HTML_OBJ)
 
+AC_ARG_WITH(catalog, [  --with-catalog          Add the Catalog support (on)])
+if test "$with_catalog" = "no" ; then
+    echo Disabling Catalog support
+    WITH_CATALOG=0
+    CATALOG_OBJ=
+else    
+    WITH_CATALOG=1
+    CATALOG_OBJ="catalog.o"
+fi
+AC_SUBST(WITH_CATALOG)
+AC_SUBST(CATALOG_OBJ)
+
 AC_ARG_WITH(docbook, [  --with-docbook         Add Docbook SGML support (on)])
 if test "$with_docbook" = "no" ; then
     echo Disabling Docbook support
diff --git a/include/Makefile.am b/include/Makefile.am
index 5baa7fe..12d2b1d 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -27,7 +27,8 @@
 		libxml/valid.h \
 		libxml/xlink.h \
 		libxml/xmlversion.h \
-		libxml/DOCBparser.h
+		libxml/DOCBparser.h \
+		libxml/catalog.h
 
 install-exec-hook:
 	$(mkinstalldirs) $(DESTDIR)$(xmlincdir) $(DESTDIR)$(xmlincdir)/libxml
diff --git a/include/libxml/catalog.h b/include/libxml/catalog.h
new file mode 100644
index 0000000..f91ee94
--- /dev/null
+++ b/include/libxml/catalog.h
@@ -0,0 +1,32 @@
+/**
+ * uri.c: interfaces of the Catalog handling system
+ *
+ * Reference:  SGML Open Technical Resolution TR9401:1997.
+ *             http://www.jclark.com/sp/catalog.htm
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel.Veillard@w3.org
+ */
+
+#ifndef __XML_CATALOG_H__
+#define __XML_CATALOG_H__
+
+#include <stdio.h>
+
+#include <libxml/xmlversion.h>
+#ifdef LIBXML_CATALOG_ENABLED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int	xmlLoadCatalog		(const char *URL);
+void	xmlCatalogCleanup	(void);
+void	xmlCatalogDump		(FILE *out);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* LIBXML_CATALOG_ENABLED */
+#endif /* __XML_CATALOG_H__ */
diff --git a/include/libxml/xmlversion.h.in b/include/libxml/xmlversion.h.in
index 6725b84..76b7ae0 100644
--- a/include/libxml/xmlversion.h.in
+++ b/include/libxml/xmlversion.h.in
@@ -62,6 +62,15 @@
 #endif
 
 /*
+ * Whether the Catalog support is configured in
+ */
+#if @WITH_CATALOG@
+#define LIBXML_CATALOG_ENABLED
+#else
+#define LIBXML_CATALOG_DISABLED
+#endif
+
+/*
  * Whether the SGML Docbook support is configured in
  */
 #if @WITH_DOCB@
diff --git a/parser.c b/parser.c
index 95e7c0a..626461a 100644
--- a/parser.c
+++ b/parser.c
@@ -2495,11 +2495,18 @@
 	    }
 	    nbchar = in - ctxt->input->cur;
 	    if (nbchar > 0) {
-		if (IS_BLANK(*ctxt->input->cur) &&
-		    areBlanks(ctxt, ctxt->input->cur, nbchar)) {
-		    if (ctxt->sax->ignorableWhitespace != NULL)
-			ctxt->sax->ignorableWhitespace(ctxt->userData,
-					       ctxt->input->cur, nbchar);
+		if (IS_BLANK(*ctxt->input->cur)) {
+		    const xmlChar *tmp = ctxt->input->cur;
+		    ctxt->input->cur = in;
+		    if (areBlanks(ctxt, tmp, nbchar)) {
+			if (ctxt->sax->ignorableWhitespace != NULL)
+			    ctxt->sax->ignorableWhitespace(ctxt->userData,
+						   tmp, nbchar);
+		    } else {
+			if (ctxt->sax->characters != NULL)
+			    ctxt->sax->characters(ctxt->userData,
+						  tmp, nbchar);
+		    }
 		} else {
 		    if (ctxt->sax->characters != NULL)
 			ctxt->sax->characters(ctxt->userData,
diff --git a/testCatalog.c b/testCatalog.c
new file mode 100644
index 0000000..99f6c66
--- /dev/null
+++ b/testCatalog.c
@@ -0,0 +1,32 @@
+/*
+ * testCatalog.c : a small tester program for Catalog loading
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel.Veillard@w3.org
+ */
+
+#include "libxml.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <libxml/xmlversion.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/uri.h>
+#include <libxml/catalog.h>
+
+int main(int argc, char **argv) {
+#ifdef LIBXML_CATALOG_ENABLED
+    int i;
+
+    for (i = 1; i < argc; i++)
+	xmlLoadCatalog(argv[i]);
+
+    xmlCatalogDump(stdout);
+    xmlCatalogCleanup();
+    xmlMemoryDump();
+#endif
+    return(0);
+}
diff --git a/xmlversion.h.in b/xmlversion.h.in
index 6725b84..76b7ae0 100644
--- a/xmlversion.h.in
+++ b/xmlversion.h.in
@@ -62,6 +62,15 @@
 #endif
 
 /*
+ * Whether the Catalog support is configured in
+ */
+#if @WITH_CATALOG@
+#define LIBXML_CATALOG_ENABLED
+#else
+#define LIBXML_CATALOG_DISABLED
+#endif
+
+/*
  * Whether the SGML Docbook support is configured in
  */
 #if @WITH_DOCB@