diff --git a/CMakeLists.txt b/CMakeLists.txt
index 724f8474579282f23d0ddfa0bca0dad4433df473..cb4e830c7a845bdfd02ea38580cce677a2ef174d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,14 +1,14 @@
 if (FALSE) # XXX(kitware): use VTK's module system
-cmake_minimum_required(VERSION 3.15)
+cmake_minimum_required(VERSION 3.18)
 endif ()
 
 file(STRINGS "configure.ac" CONFIGURE_AC_LINES)
 foreach(line ${CONFIGURE_AC_LINES})
-	if(line MATCHES [[^m4_define\(\[(MAJOR_VERSION|MINOR_VERSION|MICRO_VERSION)\],[ \t]*([0-9]+)\)$]])
-		set(LIBXML_${CMAKE_MATCH_1} ${CMAKE_MATCH_2})
-	elseif(line MATCHES "^(LIBXML_MAJOR_VERSION|LIBXML_MINOR_VERSION|LIBXML_MICRO_VERSION)=([0-9]+)$")
-		set(${CMAKE_MATCH_1} ${CMAKE_MATCH_2})
-	endif()
+    if(line MATCHES [[^m4_define\(\[(MAJOR_VERSION|MINOR_VERSION|MICRO_VERSION)\],[ \t]*([0-9]+)\)$]])
+        set(LIBXML_${CMAKE_MATCH_1} ${CMAKE_MATCH_2})
+    elseif(line MATCHES "^(LIBXML_MAJOR_VERSION|LIBXML_MINOR_VERSION|LIBXML_MICRO_VERSION)=([0-9]+)$")
+        set(${CMAKE_MATCH_1} ${CMAKE_MATCH_2})
+    endif()
 endforeach()
 set(VERSION "${LIBXML_MAJOR_VERSION}.${LIBXML_MINOR_VERSION}.${LIBXML_MICRO_VERSION}")
 
@@ -18,9 +18,13 @@ include(CheckCSourceCompiles)
 include(CheckFunctionExists)
 include(CheckIncludeFiles)
 include(CheckLibraryExists)
+if (FALSE) # XXX(kitware): Requires bumping minimum CMake version to 3.18
+include(CheckLinkerFlag)
+endif()
 include(CheckStructHasMember)
 include(CheckSymbolExists)
 include(CMakePackageConfigHelpers)
+include(FindPkgConfig)
 include(GNUInstallDirs)
 
 if (FALSE) # XXX(kitware): Hardcode settings.
@@ -32,13 +36,12 @@ option(LIBXML2_WITH_DEBUG "Add the debugging module" ON)
 set(LIBXML2_WITH_EXPR ON)
 option(LIBXML2_WITH_FTP "Add the FTP support" OFF)
 option(LIBXML2_WITH_HTML "Add the HTML support" ON)
-option(LIBXML2_WITH_HTTP "Add the HTTP support" ON)
+option(LIBXML2_WITH_HTTP "Add the HTTP support" OFF)
 option(LIBXML2_WITH_ICONV "Add ICONV support" ON)
 option(LIBXML2_WITH_ICU "Add ICU support" OFF)
 option(LIBXML2_WITH_ISO8859X "Add ISO8859X support if no iconv" ON)
 option(LIBXML2_WITH_LEGACY "Add deprecated APIs for compatibility" OFF)
-option(LIBXML2_WITH_LZMA "Use liblzma" ON)
-option(LIBXML2_WITH_MEM_DEBUG "Add the memory debugging module" OFF)
+option(LIBXML2_WITH_LZMA "Use liblzma" OFF)
 option(LIBXML2_WITH_MODULES "Add the dynamic modules support" ON)
 option(LIBXML2_WITH_OUTPUT "Add the serialization support" ON)
 option(LIBXML2_WITH_PATTERN "Add the xmlPattern selection interface" ON)
@@ -47,15 +50,14 @@ option(LIBXML2_WITH_PUSH "Add the PUSH parser interfaces" ON)
 option(LIBXML2_WITH_PYTHON "Build Python bindings" ON)
 option(LIBXML2_WITH_READER "Add the xmlReader parsing interface" ON)
 option(LIBXML2_WITH_REGEXPS "Add Regular Expressions support" ON)
-option(LIBXML2_WITH_RUN_DEBUG "Add the runtime debugging module" OFF)
 option(LIBXML2_WITH_SAX1 "Add the older SAX1 interface" ON)
 option(LIBXML2_WITH_SCHEMAS "Add Relax-NG and Schemas support" ON)
 option(LIBXML2_WITH_SCHEMATRON "Add Schematron support" ON)
 option(LIBXML2_WITH_TESTS "Build tests" ON)
 option(LIBXML2_WITH_THREADS "Add multithread support" ON)
 option(LIBXML2_WITH_THREAD_ALLOC "Add per-thread memory" OFF)
+option(LIBXML2_WITH_TLS "Enable thread-local storage" OFF)
 option(LIBXML2_WITH_TREE "Add the DOM like tree manipulation APIs" ON)
-set(LIBXML2_WITH_TRIO OFF)
 set(LIBXML2_WITH_UNICODE ON)
 option(LIBXML2_WITH_VALID "Add the DTD validation support" ON)
 option(LIBXML2_WITH_WRITER "Add the xmlWriter saving interface" ON)
@@ -63,7 +65,7 @@ option(LIBXML2_WITH_XINCLUDE "Add the XInclude support" ON)
 option(LIBXML2_WITH_XPATH "Add the XPATH support" ON)
 option(LIBXML2_WITH_XPTR "Add the XPointer support" ON)
 option(LIBXML2_WITH_XPTR_LOCS "Add support for XPointer locations" OFF)
-option(LIBXML2_WITH_ZLIB "Use libz" ON)
+option(LIBXML2_WITH_ZLIB "Use libz" OFF)
 set(LIBXML2_XMLCONF_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH "Working directory for XML Conformance Test Suite")
 else ()
 set(LIBXML2_WITH_AUTOMATA ON)
@@ -108,46 +110,21 @@ set(LIBXML2_WITH_ZLIB ON)
 set(LIBXML2_XMLCONF_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR})
 endif ()
 
-if(LIBXML2_WITH_ICONV)
-	find_package(Iconv REQUIRED)
-endif()
-
-if(LIBXML2_WITH_ICU)
-	find_package(ICU REQUIRED COMPONENTS data i18n uc)
-endif()
-
-if(LIBXML2_WITH_LZMA)
-	find_package(LibLZMA REQUIRED)
-endif()
-
 if(LIBXML2_WITH_PYTHON)
-	check_include_files(unistd.h HAVE_UNISTD_H)
-	check_symbol_exists(F_GETFL fcntl.h HAVE_F_GETFL)
-	if(HAVE_UNISTD_H AND HAVE_F_GETFL)
-		find_package(Python COMPONENTS Interpreter Development REQUIRED)
-	else()
-		find_package(Python2 COMPONENTS Interpreter Development REQUIRED)
-		add_library(Python::Python ALIAS Python2::Python)
-		set(Python_EXECUTABLE ${Python2_EXECUTABLE})
-		set(Python_SITEARCH ${Python2_SITEARCH})
-	endif()
-	set(LIBXML2_PYTHON_INSTALL_DIR ${Python_SITEARCH} CACHE PATH "Python bindings install directory")
-endif()
-
-if(LIBXML2_WITH_THREADS)
-	find_package(Threads REQUIRED)
-endif()
-
-if(LIBXML2_WITH_ZLIB)
-	#find_package(ZLIB REQUIRED)
-endif()
-
-foreach(VARIABLE IN ITEMS WITH_AUTOMATA WITH_C14N WITH_CATALOG WITH_DEBUG WITH_EXPR WITH_FTP WITH_HTML WITH_HTTP WITH_ICONV WITH_ICU WITH_ISO8859X WITH_LEGACY WITH_LZMA WITH_MEM_DEBUG WITH_MODULES WITH_OUTPUT WITH_PATTERN WITH_PUSH WITH_READER WITH_REGEXPS WITH_RUN_DEBUG WITH_SAX1 WITH_SCHEMAS WITH_SCHEMATRON WITH_THREADS WITH_THREAD_ALLOC WITH_TREE WITH_TRIO WITH_UNICODE WITH_VALID WITH_WRITER WITH_XINCLUDE WITH_XPATH WITH_XPTR WITH_XPTR_LOCS WITH_ZLIB)
-	if(LIBXML2_${VARIABLE})
-		set(${VARIABLE} 1)
-	else()
-		set(${VARIABLE} 0)
-	endif()
+    check_include_files(unistd.h HAVE_UNISTD_H)
+    check_symbol_exists(F_GETFL fcntl.h HAVE_F_GETFL)
+    find_package(Python COMPONENTS Interpreter Development REQUIRED)
+    #set(LIBXML2_PYTHON_INSTALL_DIR ${Python_SITEARCH} CACHE PATH "Python bindings install directory")
+    set(LIBXML2_PYTHON_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/python"
+        CACHE PATH "Python bindings install directory")
+endif()
+
+foreach(VARIABLE IN ITEMS WITH_AUTOMATA WITH_C14N WITH_CATALOG WITH_DEBUG WITH_EXPR WITH_FTP WITH_HTML WITH_HTTP WITH_ICONV WITH_ICU WITH_ISO8859X WITH_LEGACY WITH_LZMA WITH_MODULES WITH_OUTPUT WITH_PATTERN WITH_PUSH WITH_READER WITH_REGEXPS WITH_SAX1 WITH_SCHEMAS WITH_SCHEMATRON WITH_THREADS WITH_THREAD_ALLOC WITH_TREE WITH_UNICODE WITH_VALID WITH_WRITER WITH_XINCLUDE WITH_XPATH WITH_XPTR WITH_XPTR_LOCS WITH_ZLIB)
+    if(LIBXML2_${VARIABLE})
+        set(${VARIABLE} 1)
+    else()
+        set(${VARIABLE} 0)
+    endif()
 endforeach()
 
 set(LIBXML_VERSION ${VERSION})
@@ -161,132 +138,121 @@ math(EXPR LIBXML_VERSION_NUMBER "
 set(MODULE_EXTENSION "${CMAKE_SHARED_LIBRARY_SUFFIX}")
 
 set(PACKAGE "libxml2")
-set(PACKAGE_BUGREPORT "xml@gnome.org")
 set(PACKAGE_NAME "libxml2")
 set(PACKAGE_STRING "libxml2 ${VERSION}")
 set(PACKAGE_TARNAME "libxml2")
 set(PACKAGE_URL "https://gitlab.gnome.org/GNOME/libxml2")
 set(PACKAGE_VERSION ${VERSION})
 
-if(LIBLZMA_FOUND)
-	list(APPEND CMAKE_REQUIRED_LIBRARIES LibLZMA::LibLZMA)
+if(LIBXML2_WITH_ICONV)
+    find_package(Iconv REQUIRED)
 endif()
 
-if(Threads_FOUND)
-	list(APPEND CMAKE_REQUIRED_LIBRARIES Threads::Threads)
+if(LIBXML2_WITH_ICU)
+    find_package(ICU REQUIRED COMPONENTS data i18n uc)
 endif()
 
-if(FALSE AND ZLIB_FOUND) # XXX(kitware): not needed for any try_compiles
-	list(APPEND CMAKE_REQUIRED_LIBRARIES ZLIB::ZLIB)
+if(LIBXML2_WITH_LZMA)
+    find_package(LibLZMA REQUIRED)
+endif()
+
+if(LIBXML2_WITH_THREADS)
+    find_package(Threads REQUIRED)
+    set(THREAD_LIBS ${CMAKE_THREAD_LIBS_INIT})
+    list(APPEND CMAKE_REQUIRED_LIBRARIES Threads::Threads)
+endif()
+
+if(LIBXML2_WITH_ZLIB)
+  # find_package(ZLIB REQUIRED)
 endif()
 
 if (NOT MSVC)
-	check_c_source_compiles("
-		void __attribute__((destructor))
-		f(void) {}
-		int main(void) { return 0; }
-	" HAVE_ATTRIBUTE_DESTRUCTOR)
-	if(HAVE_ATTRIBUTE_DESTRUCTOR)
-		set(ATTRIBUTE_DESTRUCTOR "__attribute__((destructor))")
-	endif()
-	check_c_source_compiles("
-		#include <netdb.h>
-		int main() { (void) gethostbyname((const char*) \"\"); return 0; }
-	" GETHOSTBYNAME_ARG_CAST_CONST)
-	if(NOT GETHOSTBYNAME_ARG_CAST_CONST)
-		set(GETHOSTBYNAME_ARG_CAST "(char *)")
-	else()
-		set(GETHOSTBYNAME_ARG_CAST "/**/")
-	endif()
-	check_include_files(arpa/inet.h HAVE_ARPA_INET_H)
-	check_include_files(arpa/nameser.h HAVE_ARPA_NAMESER_H)
-	check_struct_has_member("struct sockaddr_storage" ss_family "sys/socket.h;sys/types.h" HAVE_SS_FAMILY)
-	check_struct_has_member("struct sockaddr_storage" __ss_family "sys/socket.h;sys/types.h" HAVE_BROKEN_SS_FAMILY)
-	if(HAVE_BROKEN_SS_FAMILY)
-		set(ss_family __ss_family)
-	endif()
-	check_function_exists(class HAVE_CLASS)
-	check_include_files(dlfcn.h HAVE_DLFCN_H)
-	check_library_exists(dl dlopen "" HAVE_DLOPEN)
-	check_include_files(dl.h HAVE_DL_H)
-	check_include_files(fcntl.h HAVE_FCNTL_H)
-	check_function_exists(fpclass HAVE_FPCLASS)
-	check_function_exists(ftime HAVE_FTIME)
-	check_function_exists(getaddrinfo HAVE_GETADDRINFO)
-	check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
-	check_include_files(inttypes.h HAVE_INTTYPES_H)
-	check_function_exists(isascii HAVE_ISASCII)
-	check_library_exists(history append_history "" HAVE_LIBHISTORY)
-	check_library_exists(readline readline "" HAVE_LIBREADLINE)
-	check_function_exists(mmap HAVE_MMAP)
-	check_function_exists(munmap HAVE_MUNMAP)
-	check_include_files(netdb.h HAVE_NETDB_H)
-	check_include_files(netinet/in.h HAVE_NETINET_IN_H)
-	check_include_files(poll.h HAVE_POLL_H)
-	check_function_exists(putenv HAVE_PUTENV)
-	check_function_exists(rand_r HAVE_RAND_R)
-	check_include_files(resolv.h HAVE_RESOLV_H)
-	check_library_exists(dld shl_load "" HAVE_SHLLOAD)
-	check_function_exists(stat HAVE_STAT)
-	check_include_files(stdint.h HAVE_STDINT_H)
-	check_include_files(sys/mman.h HAVE_SYS_MMAN_H)
-	check_include_files(sys/select.h HAVE_SYS_SELECT_H)
-	check_include_files(sys/socket.h HAVE_SYS_SOCKET_H)
-	check_include_files(sys/stat.h HAVE_SYS_STAT_H)
-	check_include_files(sys/timeb.h HAVE_SYS_TIMEB_H)
-	check_include_files(sys/time.h HAVE_SYS_TIME_H)
-	check_include_files(sys/types.h HAVE_SYS_TYPES_H)
-	check_include_files(unistd.h HAVE_UNISTD_H)
-	check_function_exists(va_copy HAVE_VA_COPY)
-	check_function_exists(__va_copy HAVE___VA_COPY)
-	set(LT_OBJDIR ".libs/")
-	check_c_source_compiles("
-		#include <sys/socket.h>
-		#include <sys/types.h>
-		int main() { (void) send(1, (const char*) \"\", 1, 1); return 0; }
-	" SEND_ARG2_CAST_CONST)
-	if(NOT SEND_ARG2_CAST_CONST)
-		set(SEND_ARG2_CAST "(char *)")
-	else()
-		set(SEND_ARG2_CAST "/**/")
-	endif()
-	check_c_source_compiles("
-		#include <stdarg.h>
-		void a(va_list* ap) {};
-		int main() { va_list ap1, ap2; a(&ap1); ap2 = (va_list) ap1; return 0; }
-	" VA_LIST_IS_ARRAY_TEST)
-	if(VA_LIST_IS_ARRAY_TEST)
-		set(VA_LIST_IS_ARRAY FALSE)
-	else()
-		set(VA_LIST_IS_ARRAY TRUE)
-	endif()
-	check_c_source_compiles("
-		#include <stddef.h>
-		#include <sys/socket.h>
-		#include <sys/types.h>
-		int main() { (void) getsockopt(1, 1, 1, NULL, (socklen_t*) NULL); return 0; }
-	" XML_SOCKLEN_T_SOCKLEN_T)
-	if(XML_SOCKLEN_T_SOCKLEN_T)
-		set(XML_SOCKLEN_T socklen_t)
-	else()
-		check_c_source_compiles("
-			#include <stddef.h>
-			#include <sys/socket.h>
-			#include <sys/types.h>
-			int main() { (void) getsockopt(1, 1, 1, NULL, (size_t*) NULL); return 0; }
-		" XML_SOCKLEN_T_SIZE_T)
-		if(XML_SOCKLEN_T_SIZE_T)
-			set(XML_SOCKLEN_T size_t)
-		else()
-			check_c_source_compiles("
-				#include <stddef.h>
-				#include <sys/socket.h>
-				#include <sys/types.h>
-				int main() { (void) getsockopt (1, 1, 1, NULL, (int*) NULL); return 0; }
-			" XML_SOCKLEN_T_INT)
-			set(XML_SOCKLEN_T int)
-		endif()
-	endif()
+    check_c_source_compiles("
+        void __attribute__((destructor))
+        f(void) {}
+        int main(void) { return 0; }
+    " HAVE_ATTRIBUTE_DESTRUCTOR)
+    if(HAVE_ATTRIBUTE_DESTRUCTOR)
+        set(ATTRIBUTE_DESTRUCTOR "__attribute__((destructor))")
+    endif()
+    check_include_files(arpa/inet.h HAVE_ARPA_INET_H)
+    check_function_exists(class HAVE_CLASS)
+    check_include_files(dlfcn.h HAVE_DLFCN_H)
+    check_library_exists(dl dlopen "" HAVE_DLOPEN)
+    check_include_files(dl.h HAVE_DL_H)
+    check_include_files(fcntl.h HAVE_FCNTL_H)
+    check_function_exists(fpclass HAVE_FPCLASS)
+    check_function_exists(ftime HAVE_FTIME)
+    check_function_exists(getentropy HAVE_GETENTROPY)
+    check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
+    check_library_exists(history append_history "" HAVE_LIBHISTORY)
+    check_library_exists(readline readline "" HAVE_LIBREADLINE)
+    check_function_exists(mmap HAVE_MMAP)
+    check_function_exists(munmap HAVE_MUNMAP)
+    check_include_files(netdb.h HAVE_NETDB_H)
+    check_include_files(netinet/in.h HAVE_NETINET_IN_H)
+    check_include_files(poll.h HAVE_POLL_H)
+    check_library_exists(dld shl_load "" HAVE_SHLLOAD)
+    check_function_exists(stat HAVE_STAT)
+    check_include_files(stdint.h HAVE_STDINT_H)
+    check_include_files(sys/mman.h HAVE_SYS_MMAN_H)
+    check_include_files(sys/random.h HAVE_SYS_RANDOM_H)
+    check_include_files(sys/select.h HAVE_SYS_SELECT_H)
+    check_include_files(sys/socket.h HAVE_SYS_SOCKET_H)
+    check_include_files(sys/stat.h HAVE_SYS_STAT_H)
+    check_include_files(sys/timeb.h HAVE_SYS_TIMEB_H)
+    check_include_files(sys/time.h HAVE_SYS_TIME_H)
+    check_include_files(unistd.h HAVE_UNISTD_H)
+    check_c_source_compiles("
+        #include <stddef.h>
+        #include <sys/socket.h>
+        int main() { (void) getsockopt(1, 1, 1, NULL, (socklen_t*) NULL); return 0; }
+    " XML_SOCKLEN_T_SOCKLEN_T)
+    if(XML_SOCKLEN_T_SOCKLEN_T)
+        set(XML_SOCKLEN_T socklen_t)
+    else()
+        check_c_source_compiles("
+            #include <stddef.h>
+            #include <sys/socket.h>
+            int main() { (void) getsockopt(1, 1, 1, NULL, (size_t*) NULL); return 0; }
+        " XML_SOCKLEN_T_SIZE_T)
+        if(XML_SOCKLEN_T_SIZE_T)
+            set(XML_SOCKLEN_T size_t)
+        else()
+            check_c_source_compiles("
+                #include <stddef.h>
+                #include <sys/socket.h>
+                int main() { (void) getsockopt (1, 1, 1, NULL, (int*) NULL); return 0; }
+            " XML_SOCKLEN_T_INT)
+            set(XML_SOCKLEN_T int)
+        endif()
+    endif()
+endif()
+
+if(LIBXML2_WITH_TLS)
+    check_c_source_compiles(
+        "_Thread_local int v; int main(){return 0;}"
+        XML_THREAD_LOCAL_C11
+    )
+    if (XML_THREAD_LOCAL_C11)
+        set(XML_THREAD_LOCAL "_Thread_local")
+    else()
+        check_c_source_compiles(
+            "__thread int v; int main(){return 0;}"
+            XML_THREAD_LOCAL_THREAD
+        )
+        if (XML_THREAD_LOCAL_THREAD)
+            set(XML_THREAD_LOCAL "__thread")
+        else()
+            check_c_source_compiles(
+                "__declspec(thread) int v; int main(){return 0;}"
+                XML_THREAD_LOCAL_DECLSPEC
+            )
+            if (XML_THREAD_LOCAL_DECLSPEC)
+                set(XML_THREAD_LOCAL "__declspec(thread)")
+            endif()
+        endif()
+    endif()
 endif()
 
 set(
@@ -341,67 +307,63 @@ set(
 )
 
 set(
-	LIBXML2_SRCS
-	buf.c
-	c14n.c
-	catalog.c
-	chvalid.c
-	debugXML.c
-	dict.c
-	encoding.c
-	entities.c
-	error.c
-	globals.c
-	hash.c
-	HTMLparser.c
-	HTMLtree.c
-	legacy.c
-	list.c
-	nanoftp.c
-	nanohttp.c
-	parser.c
-	parserInternals.c
-	pattern.c
-	relaxng.c
-	SAX.c
-	SAX2.c
-	schematron.c
-	threads.c
-	tree.c
-	uri.c
-	valid.c
-	xinclude.c
-	xlink.c
-	xmlIO.c
-	xmlmemory.c
-	xmlmodule.c
-	xmlreader.c
-	xmlregexp.c
-	xmlsave.c
-	xmlschemas.c
-	xmlschemastypes.c
-	xmlstring.c
-	xmlunicode.c
-	xmlwriter.c
-	xpath.c
-	xpointer.c
-	xzlib.c
+    LIBXML2_SRCS
+    buf.c
+    c14n.c
+    catalog.c
+    chvalid.c
+    debugXML.c
+    dict.c
+    encoding.c
+    entities.c
+    error.c
+    globals.c
+    hash.c
+    HTMLparser.c
+    HTMLtree.c
+    legacy.c
+    list.c
+    nanoftp.c
+    nanohttp.c
+    parser.c
+    parserInternals.c
+    pattern.c
+    relaxng.c
+    SAX.c
+    SAX2.c
+    schematron.c
+    threads.c
+    tree.c
+    uri.c
+    valid.c
+    xinclude.c
+    xlink.c
+    xmlIO.c
+    xmlmemory.c
+    xmlmodule.c
+    xmlreader.c
+    xmlregexp.c
+    xmlsave.c
+    xmlschemas.c
+    xmlschemastypes.c
+    xmlstring.c
+    xmlunicode.c
+    xmlwriter.c
+    xpath.c
+    xpointer.c
+    xzlib.c
 )
 
 if(WIN32)
-	list(APPEND LIBXML2_SRCS win32/libxml2.rc)
-	file(
-		WRITE
-		${CMAKE_CURRENT_BINARY_DIR}/rcVersion.h
-		"#define LIBXML_MAJOR_VERSION ${LIBXML_MAJOR_VERSION}\n"
-		"#define LIBXML_MINOR_VERSION ${LIBXML_MINOR_VERSION}\n"
-		"#define LIBXML_MICRO_VERSION ${LIBXML_MICRO_VERSION}\n"
-		"#define LIBXML_DOTTED_VERSION \"${VERSION}\"\n"
-	)
-endif()
-
-if(LIBXML2_WITH_TRIO)
-	list(APPEND LIBXML2_SRCS trio.c triostr.c)
+    list(APPEND LIBXML2_SRCS win32/libxml2.rc)
+    file(
+        WRITE
+        ${CMAKE_CURRENT_BINARY_DIR}/rcVersion.h
+        "#define LIBXML_MAJOR_VERSION ${LIBXML_MAJOR_VERSION}\n"
+        "#define LIBXML_MINOR_VERSION ${LIBXML_MINOR_VERSION}\n"
+        "#define LIBXML_MICRO_VERSION ${LIBXML_MICRO_VERSION}\n"
+        "#define LIBXML_DOTTED_VERSION \"${VERSION}\"\n"
+    )
 endif()
 
 if (FALSE) # XXX(kitware): use VTK's module system
@@ -410,32 +372,18 @@ add_library(LibXml2::LibXml2 ALIAS LibXml2)
 
 target_compile_definitions(LibXml2 PRIVATE SYSCONFDIR="${CMAKE_INSTALL_FULL_SYSCONFDIR}")
 
-if(NOT BUILD_SHARED_LIBS)
-	target_compile_definitions(LibXml2 INTERFACE LIBXML_STATIC)
-	set(XML_CFLAGS "-DLIBXML_STATIC")
-endif()
-
-if(BUILD_SHARED_LIBS AND UNIX AND NOT APPLE)
-	if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")
-		target_link_options(LibXml2 PRIVATE "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libxml2.syms")
-	endif()
-endif()
-
 if(LIBXML2_WITH_THREADS)
-	target_compile_definitions(LibXml2 PRIVATE _REENTRANT)
-	if(WIN32)
-		target_compile_definitions(LibXml2 PRIVATE HAVE_WIN32_THREADS)
-	else()
-		check_include_files(pthread.h HAVE_PTHREAD_H)
-	endif()
+    if(NOT WIN32)
+        check_include_files(pthread.h HAVE_PTHREAD_H)
+    endif()
 endif()
 
 target_include_directories(
-	LibXml2
-	PUBLIC
-	$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
-	$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-	$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}/libxml2>
+    LibXml2
+    PUBLIC
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+    $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}/libxml2>
 )
 else ()
 vtk_module_add_module(VTK::libxml2
@@ -464,219 +412,264 @@ target_include_directories(libxml2
     "$<INSTALL_INTERFACE:${_vtk_build_HEADERS_DESTINATION}/vtklibxml2/include>")
 endif ()
 
-if(HAVE_DLOPEN)
-	#target_link_libraries(LibXml2 PRIVATE dl)
-	#set(MODULE_PLATFORM_LIBS "-ldl")
-	vtk_module_link(VTK::libxml2 PRIVATE dl)
-endif()
+if(LIBXML2_WITH_MODULES)
+    if(HAVE_DLOPEN)
+        # target_link_libraries(LibXml2 PRIVATE dl)
+        # set(MODULE_PLATFORM_LIBS "-ldl")
+        vtk_module_link(VTK::libxml2 PRIVATE dl)
+    endif()
 
-if(HAVE_SHLLOAD)
-	#target_link_libraries(LibXml2 PRIVATE dld)
-	#set(MODULE_PLATFORM_LIBS "-ldld")
-	vtk_module_link(VTK::libxml2 PRIVATE dld)
+    if(HAVE_SHLLOAD)
+        # target_link_libraries(LibXml2 PRIVATE dld)
+        # set(MODULE_PLATFORM_LIBS "-ldld")
+        vtk_module_link(VTK::libxml2 PRIVATE dld)
+    endif()
 endif()
 
 if(UNIX)
-	#target_link_libraries(LibXml2 PRIVATE m)
-	#set(LIBM "-lm")
-	vtk_module_link(VTK::libxml2 PRIVATE m)
+    # target_link_libraries(LibXml2 PRIVATE m)
+    # set(LIBM "-lm")
+    vtk_module_link(VTK::libxml2 PRIVATE m)
 endif()
 
 if(WIN32)
-	#target_link_libraries(LibXml2 PRIVATE ws2_32)
-	#set(WIN32_EXTRA_LIBADD "-lws2_32")
-	vtk_module_link(VTK::libxml2 PRIVATE ws2_32)
+    # target_link_libraries(LibXml2 PRIVATE ws2_32)
+    # set(WINSOCK_LIBS "-lws2_32")
+    vtk_module_link(VTK::libxml2 PRIVATE ws2_32)
+    # target_link_libraries(LibXml2 PRIVATE bcrypt)
+    # set(CRYPTO_LIBS "-lbcrypt")
+    vtk_module_link(VTK::libxml2 PRIVATE bcrypt)
 endif()
 
 if(LIBXML2_WITH_ICONV)
-	target_link_libraries(LibXml2 PUBLIC Iconv::Iconv)
-	if(NOT Iconv_IS_BUILT_IN)
-		set(ICONV_LIBS "-liconv")
-	endif()
+    target_link_libraries(LibXml2 PUBLIC Iconv::Iconv)
+    if(NOT Iconv_IS_BUILT_IN)
+        set(ICONV_LIBS "-liconv")
+    endif()
 endif()
 
 if(LIBXML2_WITH_ICU)
-	target_link_libraries(LibXml2 PRIVATE ICU::data ICU::i18n ICU::uc)
-	if(WIN32)
-		set(ICU_LIBS "-licudt -licuin -licuuc")
-	else()
-		set(ICU_LIBS "-licudata -licui18n -licuuc")
-	endif()
+    target_link_libraries(LibXml2 PRIVATE ICU::data ICU::i18n ICU::uc)
+    if(WIN32)
+        set(ICU_LDFLAGS "-licudt -licuin -licuuc")
+    else()
+        set(ICU_LDFLAGS "-licudata -licui18n -licuuc")
+    endif()
+    list(APPEND XML_PRIVATE_LIBS "${ICU_LDFLAGS}")
+    pkg_check_modules(ICU_PC IMPORTED_TARGET icu-i18n)
+    if(ICU_PC_FOUND)
+        list(APPEND XML_PC_REQUIRES icu-i18n)
+    else()
+        list(APPEND XML_PC_LIBS "${ICU_LDFLAGS}")
+    endif()
 endif()
 
 if(LIBXML2_WITH_LZMA)
-	target_link_libraries(LibXml2 PRIVATE LibLZMA::LibLZMA)
-	set(LZMA_LIBS "-llzma")
+    target_link_libraries(LibXml2 PRIVATE LibLZMA::LibLZMA)
+    set(LibLZMA_LDFLAGS "-llzma")
+    list(APPEND XML_PRIVATE_LIBS "${LibLZMA_LDFLAGS}")
+    pkg_check_modules(LibLZMA_PC IMPORTED_TARGET liblzma)
+    if(LibLZMA_PC_FOUND)
+        list(APPEND XML_PC_REQUIRES liblzma)
+    else()
+        list(APPEND XML_PC_LIBS "${LibLZMA_LDFLAGS}")
+    endif()
 endif()
 
 if(LIBXML2_WITH_THREADS)
-	#target_link_libraries(LibXml2 PRIVATE Threads::Threads)
-	#set(THREAD_LIBS ${CMAKE_THREAD_LIBS_INIT})
+	# target_link_libraries(LibXml2 PRIVATE Threads::Threads)
+	# set(THREAD_LIBS ${CMAKE_THREAD_LIBS_INIT})
 	vtk_module_link(VTK::libxml2 PRIVATE Threads::Threads)
 endif()
 
 if(LIBXML2_WITH_ZLIB)
-	#target_link_libraries(LibXml2 PRIVATE ZLIB::ZLIB)
-	#set(Z_LIBS "-lz")
+	# target_link_libraries(LibXml2 PRIVATE ZLIB::ZLIB)
+	# set(Z_LIBS "-lz")
 	vtk_module_link(VTK::libxml2 PRIVATE VTK::zlib)
+  list(APPEND XML_PRIVATE_LIBS "${ZLIB_LDFLAGS}")
+  pkg_check_modules(ZLIB_PC IMPORTED_TARGET zlib)
+  if(ZLIB_PC_FOUND)
+    list(APPEND XML_PC_REQUIRES zlib)
+  else()
+    list(APPEND XML_PC_LIBS "${ZLIB_LDFLAGS}")
+  endif()
+endif()
+
+if (FALSE) # XXX(kitware): handled by VTK's module system.
+if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")
+  # These compiler flags can break the checks above so keep them here.
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic -Wall -Wextra -Wshadow \
+-Wpointer-arith -Wcast-align -Wwrite-strings \
+-Wstrict-prototypes -Wmissing-prototypes \
+-Wno-long-long -Wno-format-extra-args")
+
+  if(BUILD_SHARED_LIBS AND UNIX AND NOT APPLE)
+    check_linker_flag(C "LINKER:--undefined-version" FLAG_UNDEFINED_VERSION)
+    if (FLAG_UNDEFINED_VERSION)
+      target_link_options(LibXml2 PRIVATE "LINKER:--undefined-version")
+    endif()
+    target_link_options(LibXml2 PRIVATE "LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libxml2.syms")
+  endif()
 endif()
 
-if (FALSE) # XXX(kitware): handled by VTK's moduel system.
 set_target_properties(
-	LibXml2
-	PROPERTIES
-	IMPORT_PREFIX lib
-	OUTPUT_NAME xml2
-	POSITION_INDEPENDENT_CODE ON
-	PREFIX lib
-	VERSION ${PROJECT_VERSION}
+    LibXml2
+    PROPERTIES
+    IMPORT_PREFIX lib
+    OUTPUT_NAME xml2
+    POSITION_INDEPENDENT_CODE ON
+    PREFIX lib
+    VERSION ${PROJECT_VERSION}
+    SOVERSION ${LIBXML_MAJOR_VERSION}
 )
 
 if(MSVC)
-	if(BUILD_SHARED_LIBS)
-		set_target_properties(
-			LibXml2
-			PROPERTIES
-			DEBUG_POSTFIX d
-		)
-	else()
-		set_target_properties(
-			LibXml2
-			PROPERTIES
-			DEBUG_POSTFIX sd
-			MINSIZEREL_POSTFIX s
-			RELEASE_POSTFIX s
-			RELWITHDEBINFO_POSTFIX s
-		)
-	endif()
+    if(BUILD_SHARED_LIBS)
+        set_target_properties(
+            LibXml2
+            PROPERTIES
+            DEBUG_POSTFIX d
+        )
+    else()
+        set_target_properties(
+            LibXml2
+            PROPERTIES
+            DEBUG_POSTFIX sd
+            MINSIZEREL_POSTFIX s
+            RELEASE_POSTFIX s
+            RELWITHDEBINFO_POSTFIX s
+        )
+    endif()
 endif()
 
 install(FILES ${LIBXML2_HDRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libxml2/libxml COMPONENT development)
 
 install(
-	TARGETS	LibXml2
-	EXPORT LibXml2
-	ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT development
-	LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime NAMELINK_COMPONENT development
-	RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
+    TARGETS    LibXml2
+    EXPORT LibXml2
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT development
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime NAMELINK_COMPONENT development
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
 )
 
 if(MSVC AND BUILD_SHARED_LIBS)
-	install(FILES $<TARGET_PDB_FILE:LibXml2> DESTINATION ${CMAKE_INSTALL_BINDIR} CONFIGURATIONS Debug RelWithDebInfo COMPONENT debug)
+    install(FILES $<TARGET_PDB_FILE:LibXml2> DESTINATION ${CMAKE_INSTALL_BINDIR} CONFIGURATIONS Debug RelWithDebInfo COMPONENT debug)
+endif()
 endif()
-endif ()
 
 if(LIBXML2_WITH_PROGRAMS)
-	set(
-		PROGRAMS
-		xmlcatalog
-		xmllint
-	)
-	foreach(PROGRAM ${PROGRAMS})
-		add_executable(${PROGRAM} ${PROGRAM}.c)
-		add_executable(LibXml2::${PROGRAM} ALIAS ${PROGRAM})
-		target_compile_definitions(${PROGRAM} PRIVATE SYSCONFDIR="${CMAKE_INSTALL_FULL_SYSCONFDIR}")
-		target_link_libraries(${PROGRAM} LibXml2)
-		if(HAVE_LIBHISTORY)
-			target_link_libraries(${PROGRAM} history)
-		endif()
-		if(HAVE_LIBREADLINE)
-			target_link_libraries(${PROGRAM} readline)
-		endif()
-		install(TARGETS	${PROGRAM} EXPORT LibXml2 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT programs)
-	endforeach()
+    set(
+        PROGRAMS
+        xmlcatalog
+        xmllint
+    )
+    foreach(PROGRAM ${PROGRAMS})
+        add_executable(${PROGRAM} ${PROGRAM}.c)
+        add_executable(LibXml2::${PROGRAM} ALIAS ${PROGRAM})
+        target_compile_definitions(${PROGRAM} PRIVATE SYSCONFDIR="${CMAKE_INSTALL_FULL_SYSCONFDIR}")
+        target_link_libraries(${PROGRAM} LibXml2)
+        if(HAVE_LIBHISTORY)
+            target_link_libraries(${PROGRAM} history)
+        endif()
+        if(HAVE_LIBREADLINE)
+            target_link_libraries(${PROGRAM} readline)
+        endif()
+        install(TARGETS    ${PROGRAM} EXPORT LibXml2 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT programs)
+    endforeach()
 endif()
 
 if(LIBXML2_WITH_TESTS)
-	enable_testing()
-	set(
-		TESTS
-		runtest
-		runxmlconf
-		runsuite
-		testapi
-		testAutomata
-		testchar
-		testdict
-		testModule
-		testlimits
-		testrecurse
-		testThreads
-	)
-	foreach(TEST ${TESTS})
-		add_executable(${TEST} ${TEST}.c)
-		target_compile_definitions(${TEST} PRIVATE SYSCONFDIR="${CMAKE_INSTALL_FULL_SYSCONFDIR}")
-		target_link_libraries(${TEST} LibXml2)
-	endforeach()
-	if(Threads_FOUND)
-		foreach(TEST runtest testThreads)
-			if(WIN32)
-				target_compile_definitions(${TEST} PRIVATE HAVE_WIN32_THREADS)
-			endif()
-			target_link_libraries(${TEST} Threads::Threads)
-		endforeach()
-	endif()
-	add_test(NAME runtest COMMAND runtest --out ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
-	if(EXISTS ${LIBXML2_XMLCONF_WORKING_DIR}/xmlconf/xmlconf.xml)
-		add_test(NAME runxmlconf COMMAND runxmlconf WORKING_DIRECTORY ${LIBXML2_XMLCONF_WORKING_DIR})
-	endif()
-	if(NOT WIN32)
-		add_test(NAME testapi COMMAND testapi)
-	endif()
-	add_test(NAME testchar COMMAND testchar)
-	add_test(NAME testdict COMMAND testdict)
-	add_test(NAME testrecurse COMMAND testrecurse WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
-	add_test(NAME testThreads COMMAND testThreads WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+    enable_testing()
+    set(
+        TESTS
+        runtest
+        runxmlconf
+        runsuite
+        testapi
+        testchar
+        testdict
+        testModule
+        testlimits
+        testparser
+        testrecurse
+        testThreads
+    )
+    foreach(TEST ${TESTS})
+        add_executable(${TEST} ${TEST}.c)
+        target_compile_definitions(${TEST} PRIVATE SYSCONFDIR="${CMAKE_INSTALL_FULL_SYSCONFDIR}")
+        target_link_libraries(${TEST} LibXml2)
+    endforeach()
+    if(Threads_FOUND)
+        foreach(TEST runtest testThreads)
+            target_link_libraries(${TEST} Threads::Threads)
+        endforeach()
+    endif()
+    add_test(NAME runtest COMMAND runtest --out ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+    add_test(NAME runsuite COMMAND runsuite WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+    if(EXISTS ${LIBXML2_XMLCONF_WORKING_DIR}/xmlconf/xmlconf.xml)
+        add_test(NAME runxmlconf COMMAND runxmlconf WORKING_DIRECTORY ${LIBXML2_XMLCONF_WORKING_DIR})
+    endif()
+    if(NOT WIN32)
+        add_test(NAME testapi COMMAND testapi)
+    endif()
+    add_test(NAME testchar COMMAND testchar)
+    add_test(NAME testdict COMMAND testdict)
+    add_test(NAME testparser COMMAND testparser WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+    add_test(NAME testrecurse COMMAND testrecurse WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+    add_test(NAME testThreads COMMAND testThreads WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
 endif()
 
 if(LIBXML2_WITH_PYTHON)
-	execute_process(
-		COMMAND
-		${Python_EXECUTABLE}
-		${CMAKE_CURRENT_SOURCE_DIR}/python/generator.py
-		${CMAKE_CURRENT_SOURCE_DIR}/doc/libxml2-api.xml
-		${CMAKE_CURRENT_SOURCE_DIR}/python/libxml2-python-api.xml
-		WORKING_DIRECTORY
-		${CMAKE_CURRENT_BINARY_DIR}
-	)
-	file(READ python/libxml.py LIBXML_PY)
-	file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/libxml2.py.in "${LIBXML_PY}")
-	file(READ ${CMAKE_CURRENT_BINARY_DIR}/libxml2class.py LIBXML2CLASS_PY)
-	file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/libxml2.py.in "${LIBXML2CLASS_PY}")
-	configure_file(${CMAKE_CURRENT_BINARY_DIR}/libxml2.py.in libxml2.py COPYONLY)
-	add_library(
-		LibXml2Mod
-		libxml2-py.c
-		libxml2-py.h
-		python/libxml.c
-		python/libxml_wrap.h
-		python/types.c
-	)
-	target_include_directories(
-		LibXml2Mod
-		PUBLIC
-		$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/python>
-	)
-	target_link_libraries(LibXml2Mod LibXml2 Python::Python)
-	set_target_properties(
-		LibXml2Mod
-		PROPERTIES
-		IMPORT_PREFIX lib
-		OUTPUT_NAME xml2mod
-		PREFIX lib
-		VERSION ${PROJECT_VERSION}
-	)
-	install(
-		TARGETS	LibXml2Mod
-		ARCHIVE DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} COMPONENT development
-		LIBRARY DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} COMPONENT runtime NAMELINK_COMPONENT development
-		RUNTIME DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} COMPONENT runtime
-	)
-	if(MSVC AND BUILD_SHARED_LIBS)
-		install(FILES $<TARGET_PDB_FILE:LibXml2Mod> DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} CONFIGURATIONS Debug RelWithDebInfo COMPONENT debug)
-	endif()
-	install(FILES python/drv_libxml2.py DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} COMPONENT runtime)
-	install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libxml2.py DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} COMPONENT runtime)
+    execute_process(
+        COMMAND
+        ${Python_EXECUTABLE}
+        ${CMAKE_CURRENT_SOURCE_DIR}/python/generator.py
+        ${CMAKE_CURRENT_SOURCE_DIR}/doc/libxml2-api.xml
+        ${CMAKE_CURRENT_SOURCE_DIR}/python/libxml2-python-api.xml
+        WORKING_DIRECTORY
+        ${CMAKE_CURRENT_BINARY_DIR}
+    )
+    file(READ python/libxml.py LIBXML_PY)
+    file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/libxml2.py.in "${LIBXML_PY}")
+    file(READ ${CMAKE_CURRENT_BINARY_DIR}/libxml2class.py LIBXML2CLASS_PY)
+    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/libxml2.py.in "${LIBXML2CLASS_PY}")
+    configure_file(${CMAKE_CURRENT_BINARY_DIR}/libxml2.py.in libxml2.py COPYONLY)
+    add_library(
+        LibXml2Mod
+        libxml2-py.c
+        libxml2-py.h
+        python/libxml.c
+        python/libxml_wrap.h
+        python/types.c
+    )
+    target_include_directories(
+        LibXml2Mod
+        PUBLIC
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/python>
+    )
+    target_link_libraries(LibXml2Mod LibXml2 Python::Python)
+    set_target_properties(
+        LibXml2Mod
+        PROPERTIES
+        IMPORT_PREFIX lib
+        OUTPUT_NAME xml2mod
+        PREFIX lib
+        VERSION ${PROJECT_VERSION}
+    )
+    if (WIN32)
+        set_target_properties(LibXml2Mod PROPERTIES SUFFIX ".pyd")
+    endif()
+    install(
+        TARGETS    LibXml2Mod
+        ARCHIVE DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} COMPONENT development
+        LIBRARY DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} COMPONENT runtime NAMELINK_COMPONENT development
+        RUNTIME DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} COMPONENT runtime
+    )
+    if(MSVC AND BUILD_SHARED_LIBS)
+        install(FILES $<TARGET_PDB_FILE:LibXml2Mod> DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} CONFIGURATIONS Debug RelWithDebInfo COMPONENT debug)
+    endif()
+    install(FILES python/drv_libxml2.py DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} COMPONENT runtime)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libxml2.py DESTINATION ${LIBXML2_PYTHON_INSTALL_DIR} COMPONENT runtime)
 endif()
 
 if (FALSE) # XXX(kitware): mask installation rules
@@ -684,49 +677,49 @@ install(FILES doc/xml2-config.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 COMPONE
 install(FILES doc/xmlcatalog.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 COMPONENT documentation)
 install(FILES doc/xmllint.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 COMPONENT documentation)
 install(DIRECTORY doc/ DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT documentation
-	PATTERN "Makefile.*" EXCLUDE
-	PATTERN "*.1" EXCLUDE
-	PATTERN "*.py" EXCLUDE
-	PATTERN "*.res" EXCLUDE
-	PATTERN "*.xml" EXCLUDE
-	PATTERN "*.xsl" EXCLUDE)
+    PATTERN "Makefile.*" EXCLUDE
+    PATTERN "*.1" EXCLUDE
+    PATTERN "*.py" EXCLUDE
+    PATTERN "*.res" EXCLUDE
+    PATTERN "*.xml" EXCLUDE
+    PATTERN "*.xsl" EXCLUDE)
 
 configure_package_config_file(
-	libxml2-config.cmake.cmake.in libxml2-config.cmake
-	INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libxml2-${PROJECT_VERSION}
+    libxml2-config.cmake.cmake.in libxml2-config.cmake
+    INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libxml2-${PROJECT_VERSION}
 )
 
 install(
-	FILES ${CMAKE_CURRENT_BINARY_DIR}/libxml2-config.cmake
-	DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libxml2-${PROJECT_VERSION}
-	COMPONENT development
+    FILES ${CMAKE_CURRENT_BINARY_DIR}/libxml2-config.cmake
+    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libxml2-${PROJECT_VERSION}
+    COMPONENT development
 )
 
 write_basic_package_version_file(
-	${CMAKE_CURRENT_BINARY_DIR}/libxml2-config-version.cmake
-	VERSION ${PROJECT_VERSION}
-	COMPATIBILITY ExactVersion
+    ${CMAKE_CURRENT_BINARY_DIR}/libxml2-config-version.cmake
+    VERSION ${PROJECT_VERSION}
+    COMPATIBILITY ExactVersion
 )
 
 install(
-	FILES ${CMAKE_CURRENT_BINARY_DIR}/libxml2-config-version.cmake
-	DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libxml2-${PROJECT_VERSION}
-	COMPONENT development
+    FILES ${CMAKE_CURRENT_BINARY_DIR}/libxml2-config-version.cmake
+    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libxml2-${PROJECT_VERSION}
+    COMPONENT development
 )
 
 install(
-	EXPORT LibXml2
-	DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libxml2-${PROJECT_VERSION}
-	NAMESPACE LibXml2::
-	FILE libxml2-export.cmake
-	COMPONENT development
+    EXPORT LibXml2
+    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libxml2-${PROJECT_VERSION}
+    NAMESPACE LibXml2::
+    FILE libxml2-export.cmake
+    COMPONENT development
 )
 endif ()
 
 if(MSVC)
-	configure_file(include/win32config.h include/config.h COPYONLY)
+    configure_file(include/win32config.h include/config.h COPYONLY)
 else()
-	configure_file(config.h.cmake.in include/config.h)
+    configure_file(config.h.cmake.in include/config.h)
 endif()
 configure_file(include/libxml/xmlversion.h.in include/libxml/xmlversion.h)
 if (FALSE) # XXX(kitware): mask installation rules
@@ -734,23 +727,42 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libxml/xmlversion.h DESTINATION ${CMAK
 endif ()
 
 if(LIBXML2_WITH_PYTHON)
-	set(prefix "${CMAKE_INSTALL_PREFIX}")
-	configure_file(python/setup.py.in setup.py @ONLY)
+    set(prefix "${CMAKE_INSTALL_PREFIX}")
+    configure_file(python/setup.py.in setup.py @ONLY)
 endif()
 
+set(NON_PC_LIBS "${THREAD_LIBS} ${ICONV_LIBS} ${LIBM} ${WINSOCK_LIBS} ${CRYPTO_LIBS}")
+list(APPEND XML_PC_LIBS "${NON_PC_LIBS}")
+list(APPEND XML_PRIVATE_LIBS "${NON_PC_LIBS}")
+list(REMOVE_DUPLICATES XML_PC_LIBS)
+list(REMOVE_DUPLICATES XML_PRIVATE_LIBS)
+
+list(JOIN XML_PC_REQUIRES " " XML_PC_REQUIRES)
+list(JOIN XML_PC_LIBS " " XML_PC_LIBS)
+list(JOIN XML_PRIVATE_LIBS " " XML_PRIVATE_LIBS)
+
 if (FALSE) # XXX(kitware): mask installation rules
 set(XML_INCLUDEDIR "-I\${includedir}/libxml2")
 set(XML_LIBDIR "-L\${libdir}")
 set(XML_LIBS "-lxml2")
-set(XML_PRIVATE_LIBS "${Z_LIBS} ${LZMA_LIBS} ${THREAD_LIBS} ${ICONV_LIBS} ${ICU_LIBS} ${LIBM} ${WIN32_EXTRA_LIBADD}")
+
+if(BUILD_SHARED_LIBS)
+    set(XML_PC_PRIVATE ".private")
+    set(XML_PC_LIBS_PRIVATE "
+Libs.private:")
+else()
+    target_compile_definitions(LibXml2 PUBLIC LIBXML_STATIC)
+    set(XML_CFLAGS "-DLIBXML_STATIC")
+    set(XML_PRIVATE_LIBS_NO_SHARED "${XML_PRIVATE_LIBS}")
+endif()
 
 file(RELATIVE_PATH PACKAGE_RELATIVE_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig" "${CMAKE_INSTALL_PREFIX}")
 string(REGEX REPLACE "/$" "" PACKAGE_RELATIVE_PATH "${PACKAGE_RELATIVE_PATH}")
 
 if(WIN32)
-	set(prefix "\${pcfiledir}/${PACKAGE_RELATIVE_PATH}")
+    set(prefix "\${pcfiledir}/${PACKAGE_RELATIVE_PATH}")
 else()
-	set(prefix "${CMAKE_INSTALL_PREFIX}")
+    set(prefix "${CMAKE_INSTALL_PREFIX}")
 endif()
 set(exec_prefix "\${prefix}")
 set(libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
@@ -759,13 +771,13 @@ configure_file(libxml-2.0.pc.in libxml-2.0.pc @ONLY)
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libxml-2.0.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT development)
 
 if(WIN32)
-	set(prefix "\$(cd \"\$(dirname \"\$0\")\"; pwd -P)/..")
+    set(prefix "\$(cd \"\$(dirname \"\$0\")\"; pwd -P)/..")
 endif()
 configure_file(xml2-config.in xml2-config @ONLY)
 install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/xml2-config DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT development)
 
 if(UNIX)
-	install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/libxml.m4 DESTINATION ${CMAKE_INSTALL_DATADIR}/aclocal)
+    install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/libxml.m4 DESTINATION ${CMAKE_INSTALL_DATADIR}/aclocal)
 endif()
 
 set(XML_INCLUDEDIR "-I${CMAKE_INSTALL_FULL_INCLUDEDIR}/libxml2")
@@ -788,7 +800,6 @@ set(CPACK_DEBIAN_RUNTIME_PACKAGE_RECOMMENDS "${PACKAGE_TARNAME}-utils")
 set(CPACK_DEBIAN_RUNTIME_PACKAGE_SECTION "libs")
 set(CPACK_NSIS_PACKAGE_NAME ${PACKAGE_STRING})
 set(CPACK_NSIS_URL_INFO_ABOUT ${PACKAGE_URL})
-set(CPACK_PACKAGE_CONTACT ${PACKAGE_BUGREPORT})
 set(CPACK_PACKAGE_DISPLAY_NAME ${PACKAGE_STRING})
 set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PACKAGE_TARNAME}-${PACKAGE_VERSION}")
 set(CPACK_PACKAGE_NAME ${PACKAGE_TARNAME})
diff --git a/Copyright b/Copyright
index d61318502caf9587516dd9a2cb637ad9c4877f69..f76a86df63f54f2ce47a86716170955e06ef20e4 100644
--- a/Copyright
+++ b/Copyright
@@ -1,6 +1,6 @@
-Except where otherwise noted in the source code (e.g. the files hash.c,
-list.c and the trio files, which are covered by a similar licence but
-with different Copyright notices) all the files are:
+Except where otherwise noted in the source code (e.g. the files dict.c and
+list.c, which are covered by a similar licence but with different Copyright
+notices) all the files are:
 
  Copyright (C) 1998-2012 Daniel Veillard.  All Rights Reserved.
 
diff --git a/HTMLparser.c b/HTMLparser.c
index ba886908e449b54bf2874e62caa070039137525d..221359295653778568f1d42a4de439db8b269755 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -14,30 +14,30 @@
 #include <ctype.h>
 #include <stdlib.h>
 
+#include <libxml/HTMLparser.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
 #include <libxml/xmlerror.h>
-#include <libxml/HTMLparser.h>
 #include <libxml/HTMLtree.h>
 #include <libxml/entities.h>
 #include <libxml/encoding.h>
-#include <libxml/valid.h>
 #include <libxml/xmlIO.h>
-#include <libxml/globals.h>
 #include <libxml/uri.h>
 
-#include "buf.h"
-#include "enc.h"
+#include "private/buf.h"
+#include "private/enc.h"
+#include "private/error.h"
+#include "private/html.h"
+#include "private/io.h"
+#include "private/parser.h"
+#include "private/tree.h"
 
 #define HTML_MAX_NAMELEN 1000
 #define HTML_PARSER_BIG_BUFFER_SIZE 1000
 #define HTML_PARSER_BUFFER_SIZE 100
 
-/* #define DEBUG */
-/* #define DEBUG_PUSH */
-
 static int htmlOmittedDefaultValue = 1;
 
 xmlChar * htmlDecodeEntities(htmlParserCtxtPtr ctxt, int len,
@@ -58,25 +58,9 @@ static void htmlParseComment(htmlParserCtxtPtr ctxt);
  * Handle a redefinition of attribute error
  */
 static void
-htmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra)
+htmlErrMemory(xmlParserCtxtPtr ctxt)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL) {
-        ctxt->errNo = XML_ERR_NO_MEMORY;
-        ctxt->instate = XML_PARSER_EOF;
-        ctxt->disableSAX = 1;
-    }
-    if (extra)
-        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
-                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
-                        NULL, NULL, 0, 0,
-                        "Memory allocation failed : %s\n", extra);
-    else
-        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
-                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
-                        NULL, NULL, 0, 0, "Memory allocation failed\n");
+    xmlCtxtErrMemory(ctxt);
 }
 
 /**
@@ -93,18 +77,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 htmlParseErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
              const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_HTML, error,
-                    XML_ERR_ERROR, NULL, 0,
-		    (const char *) str1, (const char *) str2,
-		    NULL, 0, 0,
-		    msg, str1, str2);
-    if (ctxt != NULL)
-	ctxt->wellFormed = 0;
+    xmlCtxtErr(ctxt, NULL, XML_FROM_HTML, error, XML_ERR_ERROR,
+               str1, str2, NULL, 0, msg, str1, str2);
 }
 
 /**
@@ -120,16 +94,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 htmlParseErrInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
              const char *msg, int val)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_HTML, error,
-                    XML_ERR_ERROR, NULL, 0, NULL, NULL,
-		    NULL, val, 0, msg, val);
-    if (ctxt != NULL)
-	ctxt->wellFormed = 0;
+    xmlCtxtErr(ctxt, NULL, XML_FROM_HTML, error, XML_ERR_ERROR,
+               NULL, NULL, NULL, val, msg, val);
 }
 
 /************************************************************************
@@ -145,7 +111,7 @@ htmlParseErrInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
  *
  * Pushes a new element name on top of the name stack
  *
- * Returns 0 in case of error, the index in the stack otherwise
+ * Returns -1 in case of error, the index in the stack otherwise
  */
 static int
 htmlnamePush(htmlParserCtxtPtr ctxt, const xmlChar * value)
@@ -155,15 +121,17 @@ htmlnamePush(htmlParserCtxtPtr ctxt, const xmlChar * value)
     if ((ctxt->html < 10) && (xmlStrEqual(value, BAD_CAST "body")))
         ctxt->html = 10;
     if (ctxt->nameNr >= ctxt->nameMax) {
-        ctxt->nameMax *= 2;
-        ctxt->nameTab = (const xmlChar * *)
-                         xmlRealloc((xmlChar * *)ctxt->nameTab,
-                                    ctxt->nameMax *
-                                    sizeof(ctxt->nameTab[0]));
-        if (ctxt->nameTab == NULL) {
-            htmlErrMemory(ctxt, NULL);
-            return (0);
+        size_t newSize = ctxt->nameMax * 2;
+        const xmlChar **tmp;
+
+        tmp = xmlRealloc((xmlChar **) ctxt->nameTab,
+                         newSize * sizeof(ctxt->nameTab[0]));
+        if (tmp == NULL) {
+            htmlErrMemory(ctxt);
+            return (-1);
         }
+        ctxt->nameTab = tmp;
+        ctxt->nameMax = newSize;
     }
     ctxt->nameTab[ctxt->nameNr] = value;
     ctxt->name = value;
@@ -217,7 +185,7 @@ htmlNodeInfoPush(htmlParserCtxtPtr ctxt, htmlParserNodeInfo *value)
                                     ctxt->nodeInfoMax *
                                     sizeof(ctxt->nodeInfoTab[0]));
         if (ctxt->nodeInfoTab == NULL) {
-            htmlErrMemory(ctxt, NULL);
+            htmlErrMemory(ctxt);
             return (0);
         }
     }
@@ -270,8 +238,6 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt)
  *
  * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
  *
- *   CURRENT Returns the current char value, with the full decoding of
- *           UTF-8 if we are using this mode. It returns an int.
  *   NEXT    Skip to the next character, this does the proper decoding
  *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
  *   NEXTL(l) Skip the current unicode character of l xmlChars long.
@@ -289,32 +255,32 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt)
 #define CUR_PTR ctxt->input->cur
 #define BASE_PTR ctxt->input->base
 
-#define SHRINK if ((ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
-		   (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
-	xmlParserInputShrink(ctxt->input)
-
-#define GROW if ((ctxt->progressive == 0) &&				\
-		 (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))	\
-	xmlParserInputGrow(ctxt->input, INPUT_CHUNK)
+#define SHRINK \
+    if ((!PARSER_PROGRESSIVE(ctxt)) && \
+        (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
+	(ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
+	xmlParserShrink(ctxt);
 
-#define CURRENT ((int) (*ctxt->input->cur))
+#define GROW \
+    if ((!PARSER_PROGRESSIVE(ctxt)) && \
+        (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \
+	xmlParserGrow(ctxt);
 
 #define SKIP_BLANKS htmlSkipBlankChars(ctxt)
 
 /* Imported from XML */
 
-/* #define CUR (ctxt->token ? ctxt->token : (int) (*ctxt->input->cur)) */
-#define CUR ((int) (*ctxt->input->cur))
+#define CUR (*ctxt->input->cur)
 #define NEXT xmlNextChar(ctxt)
 
-#define RAW (ctxt->token ? -1 : (*ctxt->input->cur))
+#define RAW (*ctxt->input->cur)
 
 
 #define NEXTL(l) do {							\
     if (*(ctxt->input->cur) == '\n') {					\
 	ctxt->input->line++; ctxt->input->col = 1;			\
     } else ctxt->input->col++;						\
-    ctxt->token = 0; ctxt->input->cur += l;				\
+    ctxt->input->cur += l;						\
   } while (0)
 
 /************
@@ -324,10 +290,9 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt)
  ************/
 
 #define CUR_CHAR(l) htmlCurrentChar(ctxt, &l)
-#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
 
 #define COPY_BUF(l,b,i,v)						\
-    if (l == 1) b[i++] = (xmlChar) v;					\
+    if (l == 1) b[i++] = v;						\
     else i += xmlCopyChar(l,&b[i],v)
 
 /**
@@ -347,10 +312,10 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt)
 static xmlChar *
 htmlFindEncoding(xmlParserCtxtPtr ctxt) {
     const xmlChar *start, *cur, *end;
+    xmlChar *ret;
 
     if ((ctxt == NULL) || (ctxt->input == NULL) ||
-        (ctxt->input->encoding != NULL) || (ctxt->input->buf == NULL) ||
-        (ctxt->input->buf->encoder != NULL))
+        (ctxt->input->flags & XML_INPUT_HAS_ENCODING))
         return(NULL);
     if ((ctxt->input->cur == NULL) || (ctxt->input->end == NULL))
         return(NULL);
@@ -379,7 +344,10 @@ htmlFindEncoding(xmlParserCtxtPtr ctxt) {
            cur++;
     if (cur == start)
         return(NULL);
-    return(xmlStrndup(start, cur - start));
+    ret = xmlStrndup(start, cur - start);
+    if (ret == NULL)
+        htmlErrMemory(ctxt);
+    return(ret);
 }
 
 /**
@@ -402,31 +370,31 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
     unsigned char c;
     unsigned int val;
 
-    if (ctxt->instate == XML_PARSER_EOF)
-	return(0);
+    if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)
+        xmlParserGrow(ctxt);
 
-    if (ctxt->token != 0) {
-	*len = 0;
-	return(ctxt->token);
-    }
-    if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
+    if ((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) {
         xmlChar * guess;
-        xmlCharEncodingHandlerPtr handler;
 
         /*
          * Assume it's a fixed length encoding (1) with
          * a compatible encoding for the ASCII set, since
          * HTML constructs only use < 128 chars
          */
-        if ((int) *ctxt->input->cur < 0x80) {
-            *len = 1;
-            if ((*ctxt->input->cur == 0) &&
-                (ctxt->input->cur < ctxt->input->end)) {
-                htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
-                                "Char 0x%X out of allowed range\n", 0);
-                return(' ');
+        if (*ctxt->input->cur < 0x80) {
+            if (*ctxt->input->cur == 0) {
+                if (ctxt->input->cur < ctxt->input->end) {
+                    htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+                                    "Char 0x%X out of allowed range\n", 0);
+                    *len = 1;
+                    return(' ');
+                } else {
+                    *len = 0;
+                    return(0);
+                }
             }
-            return((int) *ctxt->input->cur);
+            *len = 1;
+            return(*ctxt->input->cur);
         }
 
         /*
@@ -436,23 +404,10 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
         if (guess == NULL) {
             xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1);
         } else {
-            if (ctxt->input->encoding != NULL)
-                xmlFree((xmlChar *) ctxt->input->encoding);
-            ctxt->input->encoding = guess;
-            handler = xmlFindCharEncodingHandler((const char *) guess);
-            if (handler != NULL) {
-                /*
-                 * Don't use UTF-8 encoder which isn't required and
-                 * can produce invalid UTF-8.
-                 */
-                if (!xmlStrEqual(BAD_CAST handler->name, BAD_CAST "UTF-8"))
-                    xmlSwitchToEncoding(ctxt, handler);
-            } else {
-                htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
-                             "Unsupported encoding %s", guess, NULL);
-            }
+            xmlSwitchEncodingName(ctxt, (const char *) guess);
+            xmlFree(guess);
         }
-        ctxt->charset = XML_CHAR_ENCODING_UTF8;
+        ctxt->input->flags |= XML_INPUT_HAS_ENCODING;
     }
 
     /*
@@ -469,29 +424,21 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
     cur = ctxt->input->cur;
     c = *cur;
     if (c & 0x80) {
+        size_t avail;
+
         if ((c & 0x40) == 0)
             goto encoding_error;
-        if (cur[1] == 0) {
-            xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-            cur = ctxt->input->cur;
-        }
-        if ((cur[1] & 0xc0) != 0x80)
+
+        avail = ctxt->input->end - ctxt->input->cur;
+
+        if ((avail < 2) || ((cur[1] & 0xc0) != 0x80))
             goto encoding_error;
         if ((c & 0xe0) == 0xe0) {
-
-            if (cur[2] == 0) {
-                xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                cur = ctxt->input->cur;
-            }
-            if ((cur[2] & 0xc0) != 0x80)
+            if ((avail < 3) || ((cur[2] & 0xc0) != 0x80))
                 goto encoding_error;
             if ((c & 0xf0) == 0xf0) {
-                if (cur[3] == 0) {
-                    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                    cur = ctxt->input->cur;
-                }
                 if (((c & 0xf8) != 0xf0) ||
-                    ((cur[3] & 0xc0) != 0x80))
+                    (avail < 4) || ((cur[3] & 0xc0) != 0x80))
                     goto encoding_error;
                 /* 4-byte code */
                 *len = 4;
@@ -524,53 +471,29 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
         }
         return(val);
     } else {
-        if ((*ctxt->input->cur == 0) &&
-            (ctxt->input->cur < ctxt->input->end)) {
-            htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
-                            "Char 0x%X out of allowed range\n", 0);
-            *len = 1;
-            return(' ');
+        if (*ctxt->input->cur == 0) {
+            if (ctxt->input->cur < ctxt->input->end) {
+                htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+                                "Char 0x%X out of allowed range\n", 0);
+                *len = 1;
+                return(' ');
+            } else {
+                *len = 0;
+                return(0);
+            }
         }
         /* 1-byte code */
         *len = 1;
-        return((int) *ctxt->input->cur);
+        return(*ctxt->input->cur);
     }
 
 encoding_error:
-    /*
-     * If we detect an UTF8 error that probably mean that the
-     * input encoding didn't get properly advertised in the
-     * declaration header. Report the error and switch the encoding
-     * to ISO-Latin-1 (if you don't like this policy, just declare the
-     * encoding !)
-     */
-    {
-        char buffer[150];
-
-	if (ctxt->input->end - ctxt->input->cur >= 4) {
-	    snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
-			    ctxt->input->cur[0], ctxt->input->cur[1],
-			    ctxt->input->cur[2], ctxt->input->cur[3]);
-	} else {
-	    snprintf(buffer, 149, "Bytes: 0x%02X\n", ctxt->input->cur[0]);
-	}
-	htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
-		     "Input is not proper UTF-8, indicate encoding !\n",
-		     BAD_CAST buffer, NULL);
-    }
+    xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL);
 
-    /*
-     * Don't switch encodings twice. Note that if there's an encoder, we
-     * shouldn't receive invalid UTF-8 anyway.
-     *
-     * Note that if ctxt->input->buf == NULL, switching encodings is
-     * impossible, see Gitlab issue #34.
-     */
-    if ((ctxt->input->buf != NULL) &&
-        (ctxt->input->buf->encoder == NULL))
+    if ((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0)
         xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1);
     *len = 1;
-    return((int) *ctxt->input->cur);
+    return(*ctxt->input->cur);
 }
 
 /**
@@ -587,17 +510,12 @@ htmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
     int res = 0;
 
     while (IS_BLANK_CH(*(ctxt->input->cur))) {
-	if ((*ctxt->input->cur == 0) &&
-	    (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) {
-		xmlPopInput(ctxt);
-	} else {
-	    if (*(ctxt->input->cur) == '\n') {
-		ctxt->input->line++; ctxt->input->col = 1;
-	    } else ctxt->input->col++;
-	    ctxt->input->cur++;
-	    if (*ctxt->input->cur == 0)
-		xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-	}
+        if (*(ctxt->input->cur) == '\n') {
+            ctxt->input->line++; ctxt->input->col = 1;
+        } else ctxt->input->col++;
+        ctxt->input->cur++;
+        if (*ctxt->input->cur == 0)
+            xmlParserGrow(ctxt);
 	if (res < INT_MAX)
 	    res++;
     }
@@ -1223,7 +1141,6 @@ static const htmlStartCloseEntry htmlStartClose[] = {
     { "menu", "form" },
     { "menu", "ul" },
     { "ol", "form" },
-    { "ol", "ul" },
     { "option", "optgroup" },
     { "option", "option" },
     { "p", "address" },
@@ -1307,7 +1224,6 @@ static const htmlStartCloseEntry htmlStartClose[] = {
     { "ul", "address" },
     { "ul", "form" },
     { "ul", "menu" },
-    { "ul", "ol" },
     { "ul", "pre" },
     { "xmp", "dd" },
     { "xmp", "dl" },
@@ -1395,10 +1311,7 @@ static const elementPriority htmlEndPriority[] = {
 /**
  * htmlInitAutoClose:
  *
- * DEPRECATED: This function will be made private. Call xmlInitParser to
- * initialize the library.
- *
- * This is a no-op now.
+ * DEPRECATED: This is a no-op.
  */
 void
 htmlInitAutoClose(void) {
@@ -1565,20 +1478,11 @@ htmlAutoCloseOnEnd(htmlParserCtxtPtr ctxt)
 static void
 htmlAutoClose(htmlParserCtxtPtr ctxt, const xmlChar * newtag)
 {
-    while ((newtag != NULL) && (ctxt->name != NULL) &&
-           (htmlCheckAutoClose(newtag, ctxt->name))) {
-        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
-            ctxt->sax->endElement(ctxt->userData, ctxt->name);
-	htmlnamePop(ctxt);
-    }
-    if (newtag == NULL) {
-        htmlAutoCloseOnEnd(ctxt);
+    if (newtag == NULL)
         return;
-    }
-    while ((newtag == NULL) && (ctxt->name != NULL) &&
-           ((xmlStrEqual(ctxt->name, BAD_CAST "head")) ||
-            (xmlStrEqual(ctxt->name, BAD_CAST "body")) ||
-            (xmlStrEqual(ctxt->name, BAD_CAST "html")))) {
+
+    while ((ctxt->name != NULL) &&
+           (htmlCheckAutoClose(newtag, ctxt->name))) {
         if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
             ctxt->sax->endElement(ctxt->userData, ctxt->name);
 	htmlnamePop(ctxt);
@@ -2075,9 +1979,9 @@ static const htmlEntityDesc  html40EntitiesTable[] = {
 #define growBuffer(buffer) {						\
     xmlChar *tmp;							\
     buffer##_size *= 2;							\
-    tmp = (xmlChar *) xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
-    if (tmp == NULL) {						\
-	htmlErrMemory(ctxt, "growing buffer\n");			\
+    tmp = (xmlChar *) xmlRealloc(buffer, buffer##_size); 		\
+    if (tmp == NULL) {							\
+	htmlErrMemory(ctxt);			\
 	xmlFree(buffer);						\
 	return(NULL);							\
     }									\
@@ -2107,6 +2011,14 @@ htmlEntityLookup(const xmlChar *name) {
     return(NULL);
 }
 
+static int
+htmlCompareEntityDesc(const void *vkey, const void *vdesc) {
+    const unsigned *key = vkey;
+    const htmlEntityDesc *desc = vdesc;
+
+    return((int) *key - (int) desc->value);
+}
+
 /**
  * htmlEntityValueLookup:
  * @value: the entity's unicode value
@@ -2119,17 +2031,14 @@ htmlEntityLookup(const xmlChar *name) {
  */
 const htmlEntityDesc *
 htmlEntityValueLookup(unsigned int value) {
-    unsigned int i;
+    const htmlEntityDesc *desc;
+    size_t nmemb;
 
-    for (i = 0;i < (sizeof(html40EntitiesTable)/
-                    sizeof(html40EntitiesTable[0]));i++) {
-        if (html40EntitiesTable[i].value >= value) {
-	    if (html40EntitiesTable[i].value > value)
-		break;
-            return((htmlEntityDescPtr) &html40EntitiesTable[i]);
-	}
-    }
-    return(NULL);
+    nmemb = sizeof(html40EntitiesTable) / sizeof(html40EntitiesTable[0]);
+    desc = bsearch(&value, html40EntitiesTable, nmemb, sizeof(htmlEntityDesc),
+                   htmlCompareEntityDesc);
+
+    return(desc);
 }
 
 /**
@@ -2320,7 +2229,7 @@ htmlEncodeEntities(unsigned char* out, int *outlen,
 	    else
 		cp = ent->name;
 	    len = strlen(cp);
-	    if (out + 2 + len > outend)
+	    if (outend - out < len + 2)
 		break;
 	    *out++ = '&';
 	    memcpy(out, cp, len);
@@ -2334,47 +2243,6 @@ htmlEncodeEntities(unsigned char* out, int *outlen,
     return(0);
 }
 
-/************************************************************************
- *									*
- *		Commodity functions to handle streams			*
- *									*
- ************************************************************************/
-
-#ifdef LIBXML_PUSH_ENABLED
-/**
- * htmlNewInputStream:
- * @ctxt:  an HTML parser context
- *
- * Create a new input stream structure
- * Returns the new input stream or NULL
- */
-static htmlParserInputPtr
-htmlNewInputStream(htmlParserCtxtPtr ctxt) {
-    htmlParserInputPtr input;
-
-    input = (xmlParserInputPtr) xmlMalloc(sizeof(htmlParserInput));
-    if (input == NULL) {
-        htmlErrMemory(ctxt, "couldn't allocate a new input stream\n");
-	return(NULL);
-    }
-    memset(input, 0, sizeof(htmlParserInput));
-    input->filename = NULL;
-    input->directory = NULL;
-    input->base = NULL;
-    input->cur = NULL;
-    input->buf = NULL;
-    input->line = 1;
-    input->col = 1;
-    input->buf = NULL;
-    input->free = NULL;
-    input->version = NULL;
-    input->consumed = 0;
-    input->length = 0;
-    return(input);
-}
-#endif
-
-
 /************************************************************************
  *									*
  *		Commodity functions, cleanup needed ?			*
@@ -2480,10 +2348,8 @@ htmlNewDocNoDtD(const xmlChar *URI, const xmlChar *ExternalID) {
      * Allocate a new document and fill the fields.
      */
     cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
-    if (cur == NULL) {
-	htmlErrMemory(NULL, "HTML document creation failed\n");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlDoc));
 
     cur->type = XML_HTML_DOCUMENT_NODE;
@@ -2503,8 +2369,15 @@ htmlNewDocNoDtD(const xmlChar *URI, const xmlChar *ExternalID) {
     cur->charset = XML_CHAR_ENCODING_UTF8;
     cur->properties = XML_DOC_HTML | XML_DOC_USERBUILT;
     if ((ExternalID != NULL) ||
-	(URI != NULL))
-	xmlCreateIntSubset(cur, BAD_CAST "html", ExternalID, URI);
+	(URI != NULL)) {
+        xmlDtdPtr intSubset;
+
+	intSubset = xmlCreateIntSubset(cur, BAD_CAST "html", ExternalID, URI);
+        if (intSubset == NULL) {
+            xmlFree(cur);
+            return(NULL);
+        }
+    }
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
@@ -2552,12 +2425,14 @@ htmlSkipBogusComment(htmlParserCtxtPtr ctxt) {
     htmlParseErr(ctxt, XML_HTML_INCORRECTLY_OPENED_COMMENT,
                  "Incorrectly opened comment\n", NULL, NULL);
 
-    do {
+    while (PARSER_STOPPED(ctxt) == 0) {
         c = CUR;
         if (c == 0)
             break;
         NEXT;
-    } while (c != '>');
+        if (c == '>')
+            break;
+    }
 }
 
 /**
@@ -2572,6 +2447,7 @@ htmlSkipBogusComment(htmlParserCtxtPtr ctxt) {
 
 static const xmlChar *
 htmlParseHTMLName(htmlParserCtxtPtr ctxt) {
+    const xmlChar *ret;
     int i = 0;
     xmlChar loc[HTML_PARSER_BUFFER_SIZE];
 
@@ -2589,7 +2465,11 @@ htmlParseHTMLName(htmlParserCtxtPtr ctxt) {
 	NEXT;
     }
 
-    return(xmlDictLookup(ctxt->dict, loc, i));
+    ret = xmlDictLookup(ctxt->dict, loc, i);
+    if (ret == NULL)
+        htmlErrMemory(ctxt);
+
+    return(ret);
 }
 
 
@@ -2608,6 +2488,7 @@ static const xmlChar *
 htmlParseHTMLName_nonInvasive(htmlParserCtxtPtr ctxt) {
     int i = 0;
     xmlChar loc[HTML_PARSER_BUFFER_SIZE];
+    const xmlChar *ret;
 
     if (!IS_ASCII_LETTER(NXT(1)) && (NXT(1) != '_') &&
         (NXT(1) != ':')) return(NULL);
@@ -2620,7 +2501,11 @@ htmlParseHTMLName_nonInvasive(htmlParserCtxtPtr ctxt) {
 	i++;
     }
 
-    return(xmlDictLookup(ctxt->dict, loc, i));
+    ret = xmlDictLookup(ctxt->dict, loc, i);
+    if (ret == NULL)
+        htmlErrMemory(ctxt);
+
+    return(ret);
 }
 
 
@@ -2662,6 +2547,8 @@ htmlParseName(htmlParserCtxtPtr ctxt) {
 	if ((*in > 0) && (*in < 0x80)) {
 	    count = in - ctxt->input->cur;
 	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
+            if (ret == NULL)
+                htmlErrMemory(ctxt);
 	    ctxt->input->cur = in;
 	    ctxt->input->col += count;
 	    return(ret);
@@ -2674,13 +2561,15 @@ static const xmlChar *
 htmlParseNameComplex(xmlParserCtxtPtr ctxt) {
     int len = 0, l;
     int c;
-    int count = 0;
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_TEXT_LENGTH :
+                    XML_MAX_NAME_LENGTH;
     const xmlChar *base = ctxt->input->base;
+    const xmlChar *ret;
 
     /*
      * Handler for more complex cases
      */
-    GROW;
     c = CUR_CHAR(l);
     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
 	(!IS_LETTER(c) && (c != '_') &&
@@ -2694,11 +2583,11 @@ htmlParseNameComplex(xmlParserCtxtPtr ctxt) {
 	    (c == '_') || (c == ':') ||
 	    (IS_COMBINING(c)) ||
 	    (IS_EXTENDER(c)))) {
-	if (count++ > 100) {
-	    count = 0;
-	    GROW;
-	}
 	len += l;
+        if (len > maxLength) {
+            htmlParseErr(ctxt, XML_ERR_NAME_TOO_LONG, "name too long", NULL, NULL);
+            return(NULL);
+        }
 	NEXTL(l);
 	c = CUR_CHAR(l);
 	if (ctxt->input->base != base) {
@@ -2717,7 +2606,11 @@ htmlParseNameComplex(xmlParserCtxtPtr ctxt) {
         return (NULL);
     }
 
-    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
+    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len);
+    if (ret == NULL)
+        htmlErrMemory(ctxt);
+
+    return(ret);
 }
 
 
@@ -2736,6 +2629,9 @@ static xmlChar *
 htmlParseHTMLAttribute(htmlParserCtxtPtr ctxt, const xmlChar stop) {
     xmlChar *buffer = NULL;
     int buffer_size = 0;
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_HUGE_LENGTH :
+                    XML_MAX_TEXT_LENGTH;
     xmlChar *out = NULL;
     const xmlChar *name = NULL;
     const xmlChar *cur = NULL;
@@ -2745,9 +2641,9 @@ htmlParseHTMLAttribute(htmlParserCtxtPtr ctxt, const xmlChar stop) {
      * allocate a translation buffer.
      */
     buffer_size = HTML_PARSER_BUFFER_SIZE;
-    buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
+    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
     if (buffer == NULL) {
-	htmlErrMemory(ctxt, "buffer allocation failed\n");
+	htmlErrMemory(ctxt);
 	return(NULL);
     }
     out = buffer;
@@ -2755,7 +2651,8 @@ htmlParseHTMLAttribute(htmlParserCtxtPtr ctxt, const xmlChar stop) {
     /*
      * Ok loop until we reach one of the ending chars
      */
-    while ((CUR != 0) && (CUR != stop)) {
+    while ((PARSER_STOPPED(ctxt) == 0) &&
+           (CUR != 0) && (CUR != stop)) {
 	if ((stop == 0) && (CUR == '>')) break;
 	if ((stop == 0) && (IS_BLANK_CH(CUR))) break;
         if (CUR == '&') {
@@ -2853,8 +2750,14 @@ htmlParseHTMLAttribute(htmlParserCtxtPtr ctxt, const xmlChar stop) {
 	    for ( ; bits >= 0; bits-= 6) {
 		*out++  = ((c >> bits) & 0x3F) | 0x80;
 	    }
-	    NEXT;
+	    NEXTL(l);
 	}
+        if (out - buffer > maxLength) {
+            htmlParseErr(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
+                         "attribute value too long\n", NULL, NULL);
+            xmlFree(buffer);
+            return(NULL);
+        }
     }
     *out = 0;
     return(buffer);
@@ -2865,6 +2768,8 @@ htmlParseHTMLAttribute(htmlParserCtxtPtr ctxt, const xmlChar stop) {
  * @ctxt:  an HTML parser context
  * @str:  location to store the entity name
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an HTML ENTITY references
  *
  * [68] EntityRef ::= '&' Name ';'
@@ -2985,7 +2890,8 @@ htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
         return(ret);
     startPosition = CUR_PTR - BASE_PTR;
 
-    while ((CUR != 0) && (CUR != quote)) {
+    while ((PARSER_STOPPED(ctxt) == 0) &&
+           (CUR != 0) && (CUR != quote)) {
         /* TODO: Handle UTF-8 */
         if (!IS_CHAR_CH(CUR)) {
             htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
@@ -2999,9 +2905,14 @@ htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
         htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
                      "Unfinished SystemLiteral\n", NULL, NULL);
     } else {
-        NEXT;
-        if (err == 0)
+        if (err == 0) {
             ret = xmlStrndup((BASE_PTR+startPosition), len);
+            if (ret == NULL) {
+                htmlErrMemory(ctxt);
+                return(NULL);
+            }
+        }
+        NEXT;
     }
 
     return(ret);
@@ -3040,7 +2951,8 @@ htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) {
         return(ret);
     startPosition = CUR_PTR - BASE_PTR;
 
-    while ((CUR != 0) && (CUR != quote)) {
+    while ((PARSER_STOPPED(ctxt) == 0) &&
+           (CUR != 0) && (CUR != quote)) {
         if (!IS_PUBIDCHAR_CH(CUR)) {
             htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
                             "Invalid char in PubidLiteral 0x%X\n", CUR);
@@ -3054,9 +2966,14 @@ htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) {
         htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
                      "Unfinished PubidLiteral\n", NULL, NULL);
     } else {
-        NEXT;
-        if (err == 0)
+        if (err == 0) {
             ret = xmlStrndup((BASE_PTR + startPosition), len);
+            if (ret == NULL) {
+                htmlErrMemory(ctxt);
+                return(NULL);
+            }
+        }
+        NEXT;
     }
 
     return(ret);
@@ -3089,7 +3006,6 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
     int nbchar = 0;
     int cur,l;
 
-    SHRINK;
     cur = CUR_CHAR(l);
     while (cur != 0) {
 	if ((cur == '<') && (NXT(1) == '/')) {
@@ -3128,6 +3044,7 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
             htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
                             "Invalid char in CDATA 0x%X\n", cur);
         }
+	NEXTL(l);
 	if (nbchar >= HTML_PARSER_BIG_BUFFER_SIZE) {
             buf[nbchar] = 0;
 	    if (ctxt->sax->cdataBlock!= NULL) {
@@ -3139,9 +3056,8 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
 		ctxt->sax->characters(ctxt->userData, buf, nbchar);
 	    }
 	    nbchar = 0;
+            SHRINK;
 	}
-	GROW;
-	NEXTL(l);
 	cur = CUR_CHAR(l);
     }
 
@@ -3175,22 +3091,22 @@ htmlParseCharDataInternal(htmlParserCtxtPtr ctxt, int readahead) {
     xmlChar buf[HTML_PARSER_BIG_BUFFER_SIZE + 6];
     int nbchar = 0;
     int cur, l;
-    int chunk = 0;
 
     if (readahead)
         buf[nbchar++] = readahead;
 
-    SHRINK;
     cur = CUR_CHAR(l);
-    while (((cur != '<') || (ctxt->token == '<')) &&
-           ((cur != '&') || (ctxt->token == '&')) &&
-	   (cur != 0)) {
+    while ((cur != '<') &&
+           (cur != '&') &&
+	   (cur != 0) &&
+           (!PARSER_STOPPED(ctxt))) {
 	if (!(IS_CHAR(cur))) {
 	    htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
 	                "Invalid char in CDATA 0x%X\n", cur);
 	} else {
 	    COPY_BUF(l,buf,nbchar,cur);
 	}
+	NEXTL(l);
 	if (nbchar >= HTML_PARSER_BIG_BUFFER_SIZE) {
             buf[nbchar] = 0;
 
@@ -3214,20 +3130,9 @@ htmlParseCharDataInternal(htmlParserCtxtPtr ctxt, int readahead) {
 		}
 	    }
 	    nbchar = 0;
-	}
-	NEXTL(l);
-        chunk++;
-        if (chunk > HTML_PARSER_BUFFER_SIZE) {
-            chunk = 0;
             SHRINK;
-            GROW;
-        }
-	cur = CUR_CHAR(l);
-	if (cur == 0) {
-	    SHRINK;
-	    GROW;
-	    cur = CUR_CHAR(l);
 	}
+	cur = CUR_CHAR(l);
     }
     if (nbchar != 0) {
         buf[nbchar] = 0;
@@ -3251,12 +3156,6 @@ htmlParseCharDataInternal(htmlParserCtxtPtr ctxt, int readahead) {
 		    ctxt->sax->characters(ctxt->userData, buf, nbchar);
 	    }
 	}
-    } else {
-	/*
-	 * Loop detection
-	 */
-	if (cur == 0)
-	    ctxt->instate = XML_PARSER_EOF;
     }
 }
 
@@ -3334,12 +3233,11 @@ htmlParseExternalID(htmlParserCtxtPtr ctxt, xmlChar **publicID) {
 }
 
 /**
- * xmlParsePI:
- * @ctxt:  an XML parser context
- *
- * parse an XML Processing Instruction.
+ * htmlParsePI:
+ * @ctxt:  an HTML parser context
  *
- * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
+ * Parse an XML Processing Instruction. HTML5 doesn't allow processing
+ * instructions, so this will be removed at some point.
  */
 static void
 htmlParsePI(htmlParserCtxtPtr ctxt) {
@@ -3347,9 +3245,11 @@ htmlParsePI(htmlParserCtxtPtr ctxt) {
     int len = 0;
     int size = HTML_PARSER_BUFFER_SIZE;
     int cur, l;
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_HUGE_LENGTH :
+                    XML_MAX_TEXT_LENGTH;
     const xmlChar *target;
     xmlParserInputState state;
-    int count = 0;
 
     if ((RAW == '<') && (NXT(1) == '?')) {
 	state = ctxt->instate;
@@ -3358,7 +3258,6 @@ htmlParsePI(htmlParserCtxtPtr ctxt) {
 	 * this is a Processing Instruction.
 	 */
 	SKIP(2);
-	SHRINK;
 
 	/*
 	 * Parse the target name and check for special support like
@@ -3376,13 +3275,11 @@ htmlParsePI(htmlParserCtxtPtr ctxt) {
 		    (ctxt->sax->processingInstruction != NULL))
 		    ctxt->sax->processingInstruction(ctxt->userData,
 		                                     target, NULL);
-		ctxt->instate = state;
-		return;
+                goto done;
 	    }
-	    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+	    buf = (xmlChar *) xmlMallocAtomic(size);
 	    if (buf == NULL) {
-		htmlErrMemory(ctxt, NULL);
-		ctxt->instate = state;
+		htmlErrMemory(ctxt);
 		return;
 	    }
 	    cur = CUR;
@@ -3397,20 +3294,14 @@ htmlParsePI(htmlParserCtxtPtr ctxt) {
 		    xmlChar *tmp;
 
 		    size *= 2;
-		    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+		    tmp = (xmlChar *) xmlRealloc(buf, size);
 		    if (tmp == NULL) {
-			htmlErrMemory(ctxt, NULL);
+			htmlErrMemory(ctxt);
 			xmlFree(buf);
-			ctxt->instate = state;
 			return;
 		    }
 		    buf = tmp;
 		}
-		count++;
-		if (count > 50) {
-		    GROW;
-		    count = 0;
-		}
                 if (IS_CHAR(cur)) {
 		    COPY_BUF(l,buf,len,cur);
                 } else {
@@ -3418,13 +3309,14 @@ htmlParsePI(htmlParserCtxtPtr ctxt) {
                                     "Invalid char in processing instruction "
                                     "0x%X\n", cur);
                 }
+                if (len > maxLength) {
+                    htmlParseErr(ctxt, XML_ERR_PI_NOT_FINISHED,
+                                 "PI %s too long", target, NULL);
+                    xmlFree(buf);
+                    goto done;
+                }
 		NEXTL(l);
 		cur = CUR_CHAR(l);
-		if (cur == 0) {
-		    SHRINK;
-		    GROW;
-		    cur = CUR_CHAR(l);
-		}
 	    }
 	    buf[len] = 0;
 	    if (cur != '>') {
@@ -3446,6 +3338,8 @@ htmlParsePI(htmlParserCtxtPtr ctxt) {
 	    htmlParseErr(ctxt, XML_ERR_PI_NOT_STARTED,
                          "PI is not started correctly", NULL, NULL);
 	}
+
+done:
 	ctxt->instate = state;
     }
 }
@@ -3454,9 +3348,7 @@ htmlParsePI(htmlParserCtxtPtr ctxt) {
  * htmlParseComment:
  * @ctxt:  an HTML parser context
  *
- * Parse an XML (SGML) comment <!-- .... -->
- *
- * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
+ * Parse an HTML comment
  */
 static void
 htmlParseComment(htmlParserCtxtPtr ctxt) {
@@ -3467,6 +3359,9 @@ htmlParseComment(htmlParserCtxtPtr ctxt) {
     int r, rl;
     int cur, l;
     int next, nl;
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_HUGE_LENGTH :
+                    XML_MAX_TEXT_LENGTH;
     xmlParserInputState state;
 
     /*
@@ -3477,12 +3372,10 @@ htmlParseComment(htmlParserCtxtPtr ctxt) {
 
     state = ctxt->instate;
     ctxt->instate = XML_PARSER_COMMENT;
-    SHRINK;
     SKIP(4);
-    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+    buf = (xmlChar *) xmlMallocAtomic(size);
     if (buf == NULL) {
-        htmlErrMemory(ctxt, "buffer allocation failed\n");
-	ctxt->instate = state;
+        htmlErrMemory(ctxt);
 	return;
     }
     len = 0;
@@ -3511,11 +3404,6 @@ htmlParseComment(htmlParserCtxtPtr ctxt) {
 	    (r != '-') || (q != '-'))) {
 	NEXTL(l);
 	next = CUR_CHAR(nl);
-	if (next == 0) {
-	    SHRINK;
-	    GROW;
-	    next = CUR_CHAR(nl);
-	}
 
 	if ((q == '-') && (r == '-') && (cur == '!') && (next == '>')) {
 	  htmlParseErr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
@@ -3528,11 +3416,10 @@ htmlParseComment(htmlParserCtxtPtr ctxt) {
 	    xmlChar *tmp;
 
 	    size *= 2;
-	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+	    tmp = (xmlChar *) xmlRealloc(buf, size);
 	    if (tmp == NULL) {
 	        xmlFree(buf);
-	        htmlErrMemory(ctxt, "growing buffer failed\n");
-		ctxt->instate = state;
+	        htmlErrMemory(ctxt);
 		return;
 	    }
 	    buf = tmp;
@@ -3543,6 +3430,13 @@ htmlParseComment(htmlParserCtxtPtr ctxt) {
             htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
                             "Invalid char in comment 0x%X\n", q);
         }
+        if (len > maxLength) {
+            htmlParseErr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
+                         "comment too long", NULL, NULL);
+            xmlFree(buf);
+            ctxt->instate = state;
+            return;
+        }
 
 	q = r;
 	ql = rl;
@@ -3573,6 +3467,8 @@ unfinished:
  * htmlParseCharRef:
  * @ctxt:  an HTML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse Reference declarations
  *
  * [66] CharRef ::= '&#' [0-9]+ ';' |
@@ -3584,12 +3480,8 @@ int
 htmlParseCharRef(htmlParserCtxtPtr ctxt) {
     int val = 0;
 
-    if ((ctxt == NULL) || (ctxt->input == NULL)) {
-	htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		     "htmlParseCharRef: context error\n",
-		     NULL, NULL);
+    if ((ctxt == NULL) || (ctxt->input == NULL))
         return(0);
-    }
     if ((CUR == '&') && (NXT(1) == '#') &&
         ((NXT(2) == 'x') || NXT(2) == 'X')) {
 	SKIP(3);
@@ -3701,7 +3593,8 @@ htmlParseDocTypeDecl(htmlParserCtxtPtr ctxt) {
 	htmlParseErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED,
 	             "DOCTYPE improperly terminated\n", NULL, NULL);
         /* Ignore bogus content */
-        while ((CUR != 0) && (CUR != '>'))
+        while ((CUR != 0) && (CUR != '>') &&
+               (PARSER_STOPPED(ctxt) == 0))
             NEXT;
     }
     if (CUR == '>')
@@ -3769,93 +3662,6 @@ htmlParseAttribute(htmlParserCtxtPtr ctxt, xmlChar **value) {
     return(name);
 }
 
-/**
- * htmlCheckEncodingDirect:
- * @ctxt:  an HTML parser context
- * @attvalue: the attribute value
- *
- * Checks an attribute value to detect
- * the encoding
- * If a new encoding is detected the parser is switched to decode
- * it and pass UTF8
- */
-static void
-htmlCheckEncodingDirect(htmlParserCtxtPtr ctxt, const xmlChar *encoding) {
-
-    if ((ctxt == NULL) || (encoding == NULL) ||
-        (ctxt->options & HTML_PARSE_IGNORE_ENC))
-	return;
-
-    /* do not change encoding */
-    if (ctxt->input->encoding != NULL)
-        return;
-
-    if (encoding != NULL) {
-	xmlCharEncoding enc;
-	xmlCharEncodingHandlerPtr handler;
-
-	while ((*encoding == ' ') || (*encoding == '\t')) encoding++;
-
-	if (ctxt->input->encoding != NULL)
-	    xmlFree((xmlChar *) ctxt->input->encoding);
-	ctxt->input->encoding = xmlStrdup(encoding);
-
-	enc = xmlParseCharEncoding((const char *) encoding);
-	/*
-	 * registered set of known encodings
-	 */
-	if (enc != XML_CHAR_ENCODING_ERROR) {
-	    if (((enc == XML_CHAR_ENCODING_UTF16LE) ||
-	         (enc == XML_CHAR_ENCODING_UTF16BE) ||
-		 (enc == XML_CHAR_ENCODING_UCS4LE) ||
-		 (enc == XML_CHAR_ENCODING_UCS4BE)) &&
-		(ctxt->input->buf != NULL) &&
-		(ctxt->input->buf->encoder == NULL)) {
-		htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
-		             "htmlCheckEncoding: wrong encoding meta\n",
-			     NULL, NULL);
-	    } else {
-		xmlSwitchEncoding(ctxt, enc);
-	    }
-	    ctxt->charset = XML_CHAR_ENCODING_UTF8;
-	} else {
-	    /*
-	     * fallback for unknown encodings
-	     */
-	    handler = xmlFindCharEncodingHandler((const char *) encoding);
-	    if (handler != NULL) {
-		xmlSwitchToEncoding(ctxt, handler);
-		ctxt->charset = XML_CHAR_ENCODING_UTF8;
-	    } else {
-		htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
-		             "htmlCheckEncoding: unknown encoding %s\n",
-			     encoding, NULL);
-	    }
-	}
-
-	if ((ctxt->input->buf != NULL) &&
-	    (ctxt->input->buf->encoder != NULL) &&
-	    (ctxt->input->buf->raw != NULL) &&
-	    (ctxt->input->buf->buffer != NULL)) {
-	    int nbchars;
-	    int processed;
-
-	    /*
-	     * convert as much as possible to the parser reading buffer.
-	     */
-	    processed = ctxt->input->cur - ctxt->input->base;
-	    xmlBufShrink(ctxt->input->buf->buffer, processed);
-	    nbchars = xmlCharEncInput(ctxt->input->buf, 1);
-            xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input);
-	    if (nbchars < 0) {
-		htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
-		             "htmlCheckEncoding: encoder error\n",
-			     NULL, NULL);
-	    }
-	}
-    }
-}
-
 /**
  * htmlCheckEncoding:
  * @ctxt:  an HTML parser context
@@ -3869,6 +3675,7 @@ htmlCheckEncodingDirect(htmlParserCtxtPtr ctxt, const xmlChar *encoding) {
 static void
 htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) {
     const xmlChar *encoding;
+    xmlChar *copy;
 
     if (!attvalue)
 	return;
@@ -3884,7 +3691,10 @@ htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) {
 	encoding = xmlStrcasestr(attvalue, BAD_CAST"=");
     if (encoding && *encoding == '=') {
 	encoding ++;
-	htmlCheckEncodingDirect(ctxt, encoding);
+        copy = xmlStrdup(encoding);
+        if (copy == NULL)
+            htmlErrMemory(ctxt);
+	xmlSetDeclaredEncoding(ctxt, copy);
     }
 }
 
@@ -3909,13 +3719,21 @@ htmlCheckMeta(htmlParserCtxtPtr ctxt, const xmlChar **atts) {
     att = atts[i++];
     while (att != NULL) {
 	value = atts[i++];
-	if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"http-equiv"))
-	 && (!xmlStrcasecmp(value, BAD_CAST"Content-Type")))
-	    http = 1;
-	else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"charset")))
-	    htmlCheckEncodingDirect(ctxt, value);
-	else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"content")))
-	    content = value;
+        if (value != NULL) {
+            if ((!xmlStrcasecmp(att, BAD_CAST "http-equiv")) &&
+                (!xmlStrcasecmp(value, BAD_CAST "Content-Type"))) {
+                http = 1;
+            } else if (!xmlStrcasecmp(att, BAD_CAST "charset")) {
+                xmlChar *copy;
+
+                copy = xmlStrdup(value);
+                if (copy == NULL)
+                    htmlErrMemory(ctxt);
+                xmlSetDeclaredEncoding(ctxt, copy);
+            } else if (!xmlStrcasecmp(att, BAD_CAST "content")) {
+                content = value;
+            }
+        }
 	att = atts[i++];
     }
     if ((http) && (content != NULL))
@@ -3955,13 +3773,8 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
     int i;
     int discardtag = 0;
 
-    if ((ctxt == NULL) || (ctxt->input == NULL)) {
-	htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		     "htmlParseStartTag: context error\n", NULL, NULL);
+    if ((ctxt == NULL) || (ctxt->input == NULL))
 	return -1;
-    }
-    if (ctxt->instate == XML_PARSER_EOF)
-        return(-1);
     if (CUR != '<') return -1;
     NEXT;
 
@@ -3976,7 +3789,7 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
 		     NULL, NULL);
 	/* Dump the bogus tag like browsers do */
 	while ((CUR != 0) && (CUR != '>') &&
-               (ctxt->instate != XML_PARSER_EOF))
+               (PARSER_STOPPED(ctxt) == 0))
 	    NEXT;
         return -1;
     }
@@ -4033,7 +3846,8 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
     SKIP_BLANKS;
     while ((CUR != 0) &&
            (CUR != '>') &&
-	   ((CUR != '/') || (NXT(1) != '>'))) {
+	   ((CUR != '/') || (NXT(1) != '>')) &&
+           (PARSER_STOPPED(ctxt) == 0)) {
 	GROW;
 	attname = htmlParseAttribute(ctxt, &attvalue);
         if (attname != NULL) {
@@ -4059,7 +3873,7 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
 	        atts = (const xmlChar **)
 		       xmlMalloc(maxatts * sizeof(xmlChar *));
 		if (atts == NULL) {
-		    htmlErrMemory(ctxt, NULL);
+		    htmlErrMemory(ctxt);
 		    if (attvalue != NULL)
 			xmlFree(attvalue);
 		    goto failed;
@@ -4073,7 +3887,7 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
 	        n = (const xmlChar **) xmlRealloc((void *) atts,
 					     maxatts * sizeof(const xmlChar *));
 		if (n == NULL) {
-		    htmlErrMemory(ctxt, NULL);
+		    htmlErrMemory(ctxt);
 		    if (attvalue != NULL)
 			xmlFree(attvalue);
 		    goto failed;
@@ -4094,7 +3908,8 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
 	     * the end of the tag. */
 	    while ((CUR != 0) &&
 	           !(IS_BLANK_CH(CUR)) && (CUR != '>') &&
-		   ((CUR != '/') || (NXT(1) != '>')))
+		   ((CUR != '/') || (NXT(1) != '>')) &&
+                   (PARSER_STOPPED(ctxt) == 0))
 		NEXT;
 	}
 
@@ -4171,7 +3986,8 @@ htmlParseEndTag(htmlParserCtxtPtr ctxt)
         htmlParseErr(ctxt, XML_ERR_GT_REQUIRED,
 	             "End tag : expected '>'\n", NULL, NULL);
         /* Skip to next '>' */
-        while ((CUR != 0) && (CUR != '>'))
+        while ((PARSER_STOPPED(ctxt) == 0) &&
+               (CUR != 0) && (CUR != '>'))
             NEXT;
     }
     if (CUR == '>')
@@ -4332,12 +4148,9 @@ htmlParseContent(htmlParserCtxtPtr ctxt) {
 
     currentNode = xmlStrdup(ctxt->name);
     depth = ctxt->nameNr;
-    while (1) {
+    while (!PARSER_STOPPED(ctxt)) {
         GROW;
 
-        if (ctxt->instate == XML_PARSER_EOF)
-            break;
-
 	/*
 	 * Our tag or one of it's parent or children is ending.
 	 */
@@ -4461,6 +4274,8 @@ htmlParseContent(htmlParserCtxtPtr ctxt) {
         else {
             htmlParseCharData(ctxt);
         }
+
+        SHRINK;
         GROW;
     }
     if (currentNode != NULL) xmlFree(currentNode);
@@ -4470,6 +4285,8 @@ htmlParseContent(htmlParserCtxtPtr ctxt) {
  * htmlParseElement:
  * @ctxt:  an HTML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an HTML element, this is highly recursive
  * this is kept for compatibility with previous code versions
  *
@@ -4488,14 +4305,8 @@ htmlParseElement(htmlParserCtxtPtr ctxt) {
     int depth;
     const xmlChar *oldptr;
 
-    if ((ctxt == NULL) || (ctxt->input == NULL)) {
-	htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		     "htmlParseElement: context error\n", NULL, NULL);
+    if ((ctxt == NULL) || (ctxt->input == NULL))
 	return;
-    }
-
-    if (ctxt->instate == XML_PARSER_EOF)
-        return;
 
     /* Capture start position */
     if (ctxt->record_info) {
@@ -4635,14 +4446,8 @@ htmlParseElementInternal(htmlParserCtxtPtr ctxt) {
     htmlParserNodeInfo node_info = { NULL, 0, 0, 0, 0 };
     int failed;
 
-    if ((ctxt == NULL) || (ctxt->input == NULL)) {
-	htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		     "htmlParseElementInternal: context error\n", NULL, NULL);
+    if ((ctxt == NULL) || (ctxt->input == NULL))
 	return;
-    }
-
-    if (ctxt->instate == XML_PARSER_EOF)
-        return;
 
     /* Capture start position */
     if (ctxt->record_info) {
@@ -4727,14 +4532,19 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) {
     int depth;
     const xmlChar *name;
 
-    currentNode = xmlStrdup(ctxt->name);
     depth = ctxt->nameNr;
-    while (1) {
+    if (depth <= 0) {
+        currentNode = NULL;
+    } else {
+        currentNode = xmlStrdup(ctxt->name);
+        if (currentNode == NULL) {
+            htmlErrMemory(ctxt);
+            return;
+        }
+    }
+    while (PARSER_STOPPED(ctxt) == 0) {
         GROW;
 
-        if (ctxt->instate == XML_PARSER_EOF)
-            break;
-
 	/*
 	 * Our tag or one of it's parent or children is ending.
 	 */
@@ -4744,8 +4554,16 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) {
 		if (currentNode != NULL)
 		    xmlFree(currentNode);
 
-	        currentNode = xmlStrdup(ctxt->name);
 	        depth = ctxt->nameNr;
+                if (depth <= 0) {
+                    currentNode = NULL;
+                } else {
+                    currentNode = xmlStrdup(ctxt->name);
+                    if (currentNode == NULL) {
+                        htmlErrMemory(ctxt);
+                        break;
+                    }
+                }
 	    }
 	    continue; /* while */
         }
@@ -4766,7 +4584,15 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) {
 	        if (currentNode != NULL)
 	            xmlFree(currentNode);
 
-	        currentNode = xmlStrdup(ctxt->name);
+                if (ctxt->name == NULL) {
+                    currentNode = NULL;
+                } else {
+                    currentNode = xmlStrdup(ctxt->name);
+                    if (currentNode == NULL) {
+                        htmlErrMemory(ctxt);
+                        break;
+                    }
+                }
 	        depth = ctxt->nameNr;
 	        continue;
 	    }
@@ -4789,7 +4615,15 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) {
 	    htmlParserFinishElementParsing(ctxt);
 	    if (currentNode != NULL) xmlFree(currentNode);
 
-	    currentNode = xmlStrdup(ctxt->name);
+            if (ctxt->name == NULL) {
+                currentNode = NULL;
+            } else {
+                currentNode = xmlStrdup(ctxt->name);
+                if (currentNode == NULL) {
+                    htmlErrMemory(ctxt);
+                    break;
+                }
+            }
 	    depth = ctxt->nameNr;
 	    continue;
 	}
@@ -4840,7 +4674,15 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) {
             htmlParseElementInternal(ctxt);
             if (currentNode != NULL) xmlFree(currentNode);
 
-            currentNode = xmlStrdup(ctxt->name);
+            if (ctxt->name == NULL) {
+                currentNode = NULL;
+            } else {
+                currentNode = xmlStrdup(ctxt->name);
+                if (currentNode == NULL) {
+                    htmlErrMemory(ctxt);
+                    break;
+                }
+            }
             depth = ctxt->nameNr;
         }
         else if (CUR == '<') {
@@ -4872,6 +4714,8 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) {
         else {
             htmlParseCharData(ctxt);
         }
+
+        SHRINK;
         GROW;
     }
     if (currentNode != NULL) xmlFree(currentNode);
@@ -4895,53 +4739,34 @@ __htmlParseContent(void *ctxt) {
  * htmlParseDocument:
  * @ctxt:  an HTML parser context
  *
- * parse an HTML document (and build a tree if using the standard SAX
- * interface).
+ * Parse an HTML document and invoke the SAX handlers. This is useful
+ * if you're only interested in custom SAX callbacks. If you want a
+ * document tree, use htmlCtxtParseDocument.
  *
- * Returns 0, -1 in case of error. the parser context is augmented
- *                as a result of the parsing.
+ * Returns 0, -1 in case of error.
  */
 
 int
 htmlParseDocument(htmlParserCtxtPtr ctxt) {
-    xmlChar start[4];
-    xmlCharEncoding enc;
     xmlDtdPtr dtd;
 
-    xmlInitParser();
-
-    htmlDefaultSAXHandlerInit();
+    if ((ctxt == NULL) || (ctxt->input == NULL))
+	return(-1);
 
-    if ((ctxt == NULL) || (ctxt->input == NULL)) {
-	htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		     "htmlParseDocument: context error\n", NULL, NULL);
-	return(XML_ERR_INTERNAL_ERROR);
+    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) {
+        ctxt->sax->setDocumentLocator(ctxt->userData,
+                (xmlSAXLocator *) &xmlDefaultSAXLocator);
     }
-    ctxt->html = 1;
-    ctxt->linenumbers = 1;
-    GROW;
-    /*
-     * SAX: beginning of the document processing.
-     */
-    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
-        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
 
-    if ((ctxt->encoding == (const xmlChar *)XML_CHAR_ENCODING_NONE) &&
-        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
-	/*
-	 * Get the 4 first bytes and decode the charset
-	 * if enc != XML_CHAR_ENCODING_NONE
-	 * plug some encoding conversion routines.
-	 */
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(&start[0], 4);
-	if (enc != XML_CHAR_ENCODING_NONE) {
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-    }
+    xmlDetectEncoding(ctxt);
+
+    /*
+     * This is wrong but matches long-standing behavior. In most cases,
+     * a document starting with an XML declaration will specify UTF-8.
+     */
+    if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) &&
+        (xmlStrncmp(ctxt->input->cur, BAD_CAST "<?xm", 4) == 0))
+        xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_UTF8);
 
     /*
      * Wipe out everything which is before the first '<'
@@ -4955,7 +4780,6 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) {
     if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
 	ctxt->sax->startDocument(ctxt->userData);
 
-
     /*
      * Parse possible comments and PIs before any content
      */
@@ -4984,9 +4808,10 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) {
     /*
      * Parse possible comments and PIs before any content
      */
-    while (((CUR == '<') && (NXT(1) == '!') &&
-            (NXT(2) == '-') && (NXT(3) == '-')) ||
-	   ((CUR == '<') && (NXT(1) == '?'))) {
+    while ((PARSER_STOPPED(ctxt) == 0) &&
+           (((CUR == '<') && (NXT(1) == '!') &&
+             (NXT(2) == '-') && (NXT(3) == '-')) ||
+	    ((CUR == '<') && (NXT(1) == '?')))) {
         htmlParseComment(ctxt);
         htmlParsePI(ctxt);
 	SKIP_BLANKS;
@@ -5012,11 +4837,14 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) {
 
     if ((!(ctxt->options & HTML_PARSE_NODEFDTD)) && (ctxt->myDoc != NULL)) {
 	dtd = xmlGetIntSubset(ctxt->myDoc);
-	if (dtd == NULL)
+	if (dtd == NULL) {
 	    ctxt->myDoc->intSubset =
 		xmlCreateIntSubset(ctxt->myDoc, BAD_CAST "html",
 		    BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN",
 		    BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd");
+            if (ctxt->myDoc->intSubset == NULL)
+                htmlErrMemory(ctxt);
+        }
     }
     if (! ctxt->wellFormed) return(-1);
     return(0);
@@ -5032,6 +4860,8 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) {
 /**
  * htmlInitParserCtxt:
  * @ctxt:  an HTML parser context
+ * @sax:  SAX handler
+ * @userData:  user data
  *
  * Initialize a parser context
  *
@@ -5039,35 +4869,34 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) {
  */
 
 static int
-htmlInitParserCtxt(htmlParserCtxtPtr ctxt)
+htmlInitParserCtxt(htmlParserCtxtPtr ctxt, const htmlSAXHandler *sax,
+                   void *userData)
 {
-    htmlSAXHandler *sax;
-
     if (ctxt == NULL) return(-1);
     memset(ctxt, 0, sizeof(htmlParserCtxt));
 
     ctxt->dict = xmlDictCreate();
-    if (ctxt->dict == NULL) {
-        htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
+    if (ctxt->dict == NULL)
 	return(-1);
-    }
-    sax = (htmlSAXHandler *) xmlMalloc(sizeof(htmlSAXHandler));
-    if (sax == NULL) {
-        htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
+
+    if (ctxt->sax == NULL)
+        ctxt->sax = (htmlSAXHandler *) xmlMalloc(sizeof(htmlSAXHandler));
+    if (ctxt->sax == NULL)
 	return(-1);
+    if (sax == NULL) {
+        memset(ctxt->sax, 0, sizeof(htmlSAXHandler));
+        xmlSAX2InitHtmlDefaultSAXHandler(ctxt->sax);
+        ctxt->userData = ctxt;
+    } else {
+        memcpy(ctxt->sax, sax, sizeof(htmlSAXHandler));
+        ctxt->userData = userData ? userData : ctxt;
     }
-    memset(sax, 0, sizeof(htmlSAXHandler));
 
     /* Allocate the Input stack */
     ctxt->inputTab = (htmlParserInputPtr *)
                       xmlMalloc(5 * sizeof(htmlParserInputPtr));
-    if (ctxt->inputTab == NULL) {
-        htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
-	ctxt->inputNr = 0;
-	ctxt->inputMax = 0;
-	ctxt->input = NULL;
+    if (ctxt->inputTab == NULL)
 	return(-1);
-    }
     ctxt->inputNr = 0;
     ctxt->inputMax = 5;
     ctxt->input = NULL;
@@ -5078,35 +4907,16 @@ htmlInitParserCtxt(htmlParserCtxtPtr ctxt)
 
     /* Allocate the Node stack */
     ctxt->nodeTab = (htmlNodePtr *) xmlMalloc(10 * sizeof(htmlNodePtr));
-    if (ctxt->nodeTab == NULL) {
-        htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
-	ctxt->nodeNr = 0;
-	ctxt->nodeMax = 0;
-	ctxt->node = NULL;
-	ctxt->inputNr = 0;
-	ctxt->inputMax = 0;
-	ctxt->input = NULL;
+    if (ctxt->nodeTab == NULL)
 	return(-1);
-    }
     ctxt->nodeNr = 0;
     ctxt->nodeMax = 10;
     ctxt->node = NULL;
 
     /* Allocate the Name stack */
     ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *));
-    if (ctxt->nameTab == NULL) {
-        htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
-	ctxt->nameNr = 0;
-	ctxt->nameMax = 0;
-	ctxt->name = NULL;
-	ctxt->nodeNr = 0;
-	ctxt->nodeMax = 0;
-	ctxt->node = NULL;
-	ctxt->inputNr = 0;
-	ctxt->inputMax = 0;
-	ctxt->input = NULL;
+    if (ctxt->nameTab == NULL)
 	return(-1);
-    }
     ctxt->nameNr = 0;
     ctxt->nameMax = 10;
     ctxt->name = NULL;
@@ -5115,10 +4925,6 @@ htmlInitParserCtxt(htmlParserCtxtPtr ctxt)
     ctxt->nodeInfoNr  = 0;
     ctxt->nodeInfoMax = 0;
 
-    ctxt->sax = sax;
-    xmlSAX2InitHtmlDefaultSAXHandler(sax);
-
-    ctxt->userData = ctxt;
     ctxt->myDoc = NULL;
     ctxt->wellFormed = 1;
     ctxt->replaceEntities = 0;
@@ -5154,127 +4960,139 @@ htmlFreeParserCtxt(htmlParserCtxtPtr ctxt)
 /**
  * htmlNewParserCtxt:
  *
- * Allocate and initialize a new parser context.
+ * Allocate and initialize a new HTML parser context.
+ *
+ * This can be used to parse HTML documents into DOM trees with
+ * functions like xmlCtxtReadFile or xmlCtxtReadMemory.
+ *
+ * See htmlCtxtUseOptions for parser options.
+ *
+ * See xmlCtxtSetErrorHandler for advanced error handling.
+ *
+ * See xmlNewInputURL, xmlNewInputMemory, xmlNewInputIO and similar
+ * functions for advanced input control.
+ *
+ * See htmlNewSAXParserCtxt for custom SAX parsers.
  *
  * Returns the htmlParserCtxtPtr or NULL in case of allocation error
  */
 
 htmlParserCtxtPtr
 htmlNewParserCtxt(void)
+{
+    return(htmlNewSAXParserCtxt(NULL, NULL));
+}
+
+/**
+ * htmlNewSAXParserCtxt:
+ * @sax:  SAX handler
+ * @userData:  user data
+ *
+ * Allocate and initialize a new HTML SAX parser context. If userData
+ * is NULL, the parser context will be passed as user data.
+ *
+ * Available since 2.11.0. If you want support older versions,
+ * it's best to invoke htmlNewParserCtxt and set ctxt->sax with
+ * struct assignment.
+ *
+ * Also see htmlNewParserCtxt.
+ *
+ * Returns the htmlParserCtxtPtr or NULL in case of allocation error
+ */
+
+htmlParserCtxtPtr
+htmlNewSAXParserCtxt(const htmlSAXHandler *sax, void *userData)
 {
     xmlParserCtxtPtr ctxt;
 
+    xmlInitParser();
+
     ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
-    if (ctxt == NULL) {
-        htmlErrMemory(NULL, "NewParserCtxt: out of memory\n");
+    if (ctxt == NULL)
 	return(NULL);
-    }
     memset(ctxt, 0, sizeof(xmlParserCtxt));
-    if (htmlInitParserCtxt(ctxt) < 0) {
+    if (htmlInitParserCtxt(ctxt, sax, userData) < 0) {
         htmlFreeParserCtxt(ctxt);
 	return(NULL);
     }
     return(ctxt);
 }
 
-/**
- * htmlCreateMemoryParserCtxt:
- * @buffer:  a pointer to a char array
- * @size:  the size of the array
- *
- * Create a parser context for an HTML in-memory document.
- *
- * Returns the new parser context or NULL
- */
-htmlParserCtxtPtr
-htmlCreateMemoryParserCtxt(const char *buffer, int size) {
+static htmlParserCtxtPtr
+htmlCreateMemoryParserCtxtInternal(const char *url,
+                                   const char *buffer, size_t size,
+                                   const char *encoding) {
     xmlParserCtxtPtr ctxt;
     xmlParserInputPtr input;
-    xmlParserInputBufferPtr buf;
 
     if (buffer == NULL)
 	return(NULL);
-    if (size <= 0)
-	return(NULL);
 
     ctxt = htmlNewParserCtxt();
     if (ctxt == NULL)
 	return(NULL);
 
-    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
-    if (buf == NULL) return(NULL);
-
-    input = xmlNewInputStream(ctxt);
+    input = xmlNewInputMemory(ctxt, url, buffer, size, encoding, 0);
     if (input == NULL) {
-	xmlFreeParserInputBuffer(buf);
 	xmlFreeParserCtxt(ctxt);
-	return(NULL);
+        return(NULL);
     }
 
-    input->filename = NULL;
-    input->buf = buf;
-    xmlBufResetInput(buf->buffer, input);
-
     inputPush(ctxt, input);
+
     return(ctxt);
 }
 
 /**
- * htmlCreateDocParserCtxt:
- * @cur:  a pointer to an array of xmlChar
- * @encoding:  a free form C string describing the HTML document encoding, or NULL
+ * htmlCreateMemoryParserCtxt:
+ * @buffer:  a pointer to a char array
+ * @size:  the size of the array
  *
- * Create a parser context for an HTML document.
+ * DEPRECATED: Use htmlNewParserCtxt and htmlCtxtReadMemory.
  *
- * TODO: check the need to add encoding handling there
+ * Create a parser context for an HTML in-memory document. The input
+ * buffer must not contain any terminating null bytes.
  *
  * Returns the new parser context or NULL
  */
+htmlParserCtxtPtr
+htmlCreateMemoryParserCtxt(const char *buffer, int size) {
+    if (size <= 0)
+	return(NULL);
+
+    return(htmlCreateMemoryParserCtxtInternal(NULL, buffer, size, NULL));
+}
+
+/**
+ * htmlCreateDocParserCtxt:
+ * @str:  a pointer to an array of xmlChar
+ * @encoding:  encoding (optional)
+ *
+ * Create a parser context for a null-terminated string.
+ *
+ * Returns the new parser context or NULL if a memory allocation failed.
+ */
 static htmlParserCtxtPtr
-htmlCreateDocParserCtxt(const xmlChar *cur, const char *encoding) {
-    int len;
-    htmlParserCtxtPtr ctxt;
+htmlCreateDocParserCtxt(const xmlChar *str, const char *url,
+                        const char *encoding) {
+    xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
 
-    if (cur == NULL)
+    if (str == NULL)
 	return(NULL);
-    len = xmlStrlen(cur);
-    ctxt = htmlCreateMemoryParserCtxt((char *)cur, len);
+
+    ctxt = htmlNewParserCtxt();
     if (ctxt == NULL)
 	return(NULL);
 
-    if (encoding != NULL) {
-	xmlCharEncoding enc;
-	xmlCharEncodingHandlerPtr handler;
+    input = xmlNewInputString(ctxt, url, (const char *) str, encoding, 0);
+    if (input == NULL) {
+	xmlFreeParserCtxt(ctxt);
+	return(NULL);
+    }
 
-	if (ctxt->input->encoding != NULL)
-	    xmlFree((xmlChar *) ctxt->input->encoding);
-	ctxt->input->encoding = xmlStrdup((const xmlChar *) encoding);
+    inputPush(ctxt, input);
 
-	enc = xmlParseCharEncoding(encoding);
-	/*
-	 * registered set of known encodings
-	 */
-	if (enc != XML_CHAR_ENCODING_ERROR) {
-	    xmlSwitchEncoding(ctxt, enc);
-	    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
-		htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
-		             "Unsupported encoding %s\n",
-			     (const xmlChar *) encoding, NULL);
-	    }
-	} else {
-	    /*
-	     * fallback for unknown encodings
-	     */
-	    handler = xmlFindCharEncodingHandler((const char *) encoding);
-	    if (handler != NULL) {
-		xmlSwitchToEncoding(ctxt, handler);
-	    } else {
-		htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
-		             "Unsupported encoding %s\n",
-			     (const xmlChar *) encoding, NULL);
-	    }
-	}
-    }
     return(ctxt);
 }
 
@@ -5307,33 +5125,20 @@ static int
 htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
                         xmlChar next, xmlChar third, int ignoreattrval)
 {
-    int base, len;
+    size_t base, len;
     htmlParserInputPtr in;
     const xmlChar *buf;
-    int invalue = 0;
-    char valdellim = 0x0;
+    int quote;
 
     in = ctxt->input;
     if (in == NULL)
         return (-1);
 
-    base = in->cur - in->base;
-    if (base < 0)
-        return (-1);
+    base = ctxt->checkIndex;
+    quote = ctxt->endCheckState;
 
-    if (ctxt->checkIndex > base) {
-        base = ctxt->checkIndex;
-        /* Abuse hasPErefs member to restore current state. */
-        invalue = ctxt->hasPErefs & 1 ? 1 : 0;
-    }
-
-    if (in->buf == NULL) {
-        buf = in->base;
-        len = in->length;
-    } else {
-        buf = xmlBufContent(in->buf->buffer);
-        len = xmlBufUse(in->buf->buffer);
-    }
+    buf = in->cur;
+    len = in->end - in->cur;
 
     /* take into account the sequence length */
     if (third)
@@ -5341,19 +5146,19 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
     else if (next)
         len--;
     for (; base < len; base++) {
+        if (base >= INT_MAX / 2) {
+            ctxt->checkIndex = 0;
+            ctxt->endCheckState = 0;
+            return (base - 2);
+        }
         if (ignoreattrval) {
+            if (quote) {
+                if (buf[base] == quote)
+                    quote = 0;
+                continue;
+            }
             if (buf[base] == '"' || buf[base] == '\'') {
-                if (invalue) {
-                    if (buf[base] == valdellim) {
-                        invalue = 0;
-                        continue;
-                    }
-                } else {
-                    valdellim = buf[base];
-                    invalue = 1;
-                    continue;
-                }
-            } else if (invalue) {
+                quote = buf[base];
                 continue;
             }
         }
@@ -5366,41 +5171,12 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
                     continue;
             }
             ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-            if (next == 0)
-                xmlGenericError(xmlGenericErrorContext,
-                                "HPP: lookup '%c' found at %d\n",
-                                first, base);
-            else if (third == 0)
-                xmlGenericError(xmlGenericErrorContext,
-                                "HPP: lookup '%c%c' found at %d\n",
-                                first, next, base);
-            else
-                xmlGenericError(xmlGenericErrorContext,
-                                "HPP: lookup '%c%c%c' found at %d\n",
-                                first, next, third, base);
-#endif
-            return (base - (in->cur - in->base));
+            ctxt->endCheckState = 0;
+            return (base);
         }
     }
     ctxt->checkIndex = base;
-    /* Abuse hasPErefs member to track current state. */
-    if (invalue)
-        ctxt->hasPErefs |= 1;
-    else
-        ctxt->hasPErefs &= ~1;
-#ifdef DEBUG_PUSH
-    if (next == 0)
-        xmlGenericError(xmlGenericErrorContext,
-                        "HPP: lookup '%c' failed\n", first);
-    else if (third == 0)
-        xmlGenericError(xmlGenericErrorContext,
-                        "HPP: lookup '%c%c' failed\n", first, next);
-    else
-        xmlGenericError(xmlGenericErrorContext,
-                        "HPP: lookup '%c%c%c' failed\n", first, next,
-                        third);
-#endif
+    ctxt->endCheckState = quote;
     return (-1);
 }
 
@@ -5422,16 +5198,23 @@ static int
 htmlParseLookupCommentEnd(htmlParserCtxtPtr ctxt)
 {
     int mark = 0;
-    int cur = CUR_PTR - BASE_PTR;
+    int offset;
 
-    while (mark >= 0) {
+    while (1) {
 	mark = htmlParseLookupSequence(ctxt, '-', '-', 0, 0);
-	if ((mark < 0) ||
-	    (NXT(mark+2) == '>') ||
+	if (mark < 0)
+            break;
+        if ((NXT(mark+2) == '>') ||
 	    ((NXT(mark+2) == '!') && (NXT(mark+3) == '>'))) {
-	    return mark;
+            ctxt->checkIndex = 0;
+	    break;
 	}
-	ctxt->checkIndex = cur + mark + 1;
+        offset = (NXT(mark+2) == '!') ? 3 : 2;
+        if (mark + offset >= ctxt->input->end - ctxt->input->cur) {
+	    ctxt->checkIndex = mark;
+            return(-1);
+        }
+	ctxt->checkIndex = mark + 1;
     }
     return mark;
 }
@@ -5455,68 +5238,11 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 
     htmlParserNodeInfo node_info;
 
-#ifdef DEBUG_PUSH
-    switch (ctxt->instate) {
-	case XML_PARSER_EOF:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try EOF\n"); break;
-	case XML_PARSER_START:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try START\n"); break;
-	case XML_PARSER_MISC:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try MISC\n");break;
-	case XML_PARSER_COMMENT:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try COMMENT\n");break;
-	case XML_PARSER_PROLOG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try PROLOG\n");break;
-	case XML_PARSER_START_TAG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try START_TAG\n");break;
-	case XML_PARSER_CONTENT:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try CONTENT\n");break;
-	case XML_PARSER_CDATA_SECTION:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try CDATA_SECTION\n");break;
-	case XML_PARSER_END_TAG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try END_TAG\n");break;
-	case XML_PARSER_ENTITY_DECL:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try ENTITY_DECL\n");break;
-	case XML_PARSER_ENTITY_VALUE:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try ENTITY_VALUE\n");break;
-	case XML_PARSER_ATTRIBUTE_VALUE:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try ATTRIBUTE_VALUE\n");break;
-	case XML_PARSER_DTD:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try DTD\n");break;
-	case XML_PARSER_EPILOG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try EPILOG\n");break;
-	case XML_PARSER_PI:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try PI\n");break;
-	case XML_PARSER_SYSTEM_LITERAL:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try SYSTEM_LITERAL\n");break;
-    }
-#endif
-
-    while (1) {
+    while (PARSER_STOPPED(ctxt) == 0) {
 
 	in = ctxt->input;
 	if (in == NULL) break;
-	if (in->buf == NULL)
-	    avail = in->length - (in->cur - in->base);
-	else
-	    avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
-                    (in->cur - in->base);
+	avail = in->end - in->cur;
 	if ((avail == 0) && (terminate)) {
 	    htmlAutoCloseOnEnd(ctxt);
 	    if ((ctxt->nameNr == 0) && (ctxt->instate != XML_PARSER_EOF)) {
@@ -5549,21 +5275,28 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		 */
 	        goto done;
             case XML_PARSER_START:
+                /*
+                 * This is wrong but matches long-standing behavior. In most
+                 * cases, a document starting with an XML declaration will
+                 * specify UTF-8.
+                 */
+                if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) &&
+                    (xmlStrncmp(ctxt->input->cur, BAD_CAST "<?xm", 4) == 0)) {
+                    xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_UTF8);
+                }
+
 	        /*
 		 * Very first chars read from the document flow.
 		 */
 		cur = in->cur[0];
 		if (IS_BLANK_CH(cur)) {
 		    SKIP_BLANKS;
-		    if (in->buf == NULL)
-			avail = in->length - (in->cur - in->base);
-		    else
-			avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
-                                (in->cur - in->base);
+                    avail = in->end - in->cur;
 		}
-		if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
-		    ctxt->sax->setDocumentLocator(ctxt->userData,
-						  &xmlDefaultSAXLocator);
+                if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) {
+                    ctxt->sax->setDocumentLocator(ctxt->userData,
+                            (xmlSAXLocator *) &xmlDefaultSAXLocator);
+                }
 		if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 	            (!ctxt->disableSAX))
 		    ctxt->sax->startDocument(ctxt->userData);
@@ -5578,31 +5311,15 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		    if ((!terminate) &&
 		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing internal subset\n");
-#endif
 		    htmlParseDocTypeDecl(ctxt);
 		    ctxt->instate = XML_PARSER_PROLOG;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering PROLOG\n");
-#endif
                 } else {
 		    ctxt->instate = XML_PARSER_MISC;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering MISC\n");
-#endif
 		}
 		break;
             case XML_PARSER_MISC:
 		SKIP_BLANKS;
-		if (in->buf == NULL)
-		    avail = in->length - (in->cur - in->base);
-		else
-		    avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
-                            (in->cur - in->base);
+                avail = in->end - in->cur;
 		/*
 		 * no chars in buffer
 		 */
@@ -5624,20 +5341,12 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		    (in->cur[2] == '-') && (in->cur[3] == '-')) {
 		    if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing Comment\n");
-#endif
 		    htmlParseComment(ctxt);
 		    ctxt->instate = XML_PARSER_MISC;
 	        } else if ((cur == '<') && (next == '?')) {
 		    if ((!terminate) &&
 		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing PI\n");
-#endif
 		    htmlParsePI(ctxt);
 		    ctxt->instate = XML_PARSER_MISC;
 		} else if ((cur == '<') && (next == '!') &&
@@ -5648,34 +5357,18 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		    if ((!terminate) &&
 		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing internal subset\n");
-#endif
 		    htmlParseDocTypeDecl(ctxt);
 		    ctxt->instate = XML_PARSER_PROLOG;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering PROLOG\n");
-#endif
 		} else if ((cur == '<') && (next == '!') &&
 		           (avail < 9)) {
 		    goto done;
 		} else {
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering START_TAG\n");
-#endif
 		}
 		break;
             case XML_PARSER_PROLOG:
 		SKIP_BLANKS;
-		if (in->buf == NULL)
-		    avail = in->length - (in->cur - in->base);
-		else
-		    avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
-                            (in->cur - in->base);
+                avail = in->end - in->cur;
 		if (avail < 2)
 		    goto done;
 		cur = in->cur[0];
@@ -5684,20 +5377,12 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		    (in->cur[2] == '-') && (in->cur[3] == '-')) {
 		    if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing Comment\n");
-#endif
 		    htmlParseComment(ctxt);
 		    ctxt->instate = XML_PARSER_PROLOG;
 	        } else if ((cur == '<') && (next == '?')) {
 		    if ((!terminate) &&
 		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing PI\n");
-#endif
 		    htmlParsePI(ctxt);
 		    ctxt->instate = XML_PARSER_PROLOG;
 		} else if ((cur == '<') && (next == '!') &&
@@ -5705,18 +5390,10 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		    goto done;
 		} else {
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering START_TAG\n");
-#endif
 		}
 		break;
             case XML_PARSER_EPILOG:
-		if (in->buf == NULL)
-		    avail = in->length - (in->cur - in->base);
-		else
-		    avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
-                            (in->cur - in->base);
+                avail = in->end - in->cur;
 		if (avail < 1)
 		    goto done;
 		cur = in->cur[0];
@@ -5731,20 +5408,12 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		    (in->cur[2] == '-') && (in->cur[3] == '-')) {
 		    if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing Comment\n");
-#endif
 		    htmlParseComment(ctxt);
 		    ctxt->instate = XML_PARSER_EPILOG;
 	        } else if ((cur == '<') && (next == '?')) {
 		    if ((!terminate) &&
 		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing PI\n");
-#endif
 		    htmlParsePI(ctxt);
 		    ctxt->instate = XML_PARSER_EPILOG;
 		} else if ((cur == '<') && (next == '!') &&
@@ -5754,10 +5423,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		    ctxt->errNo = XML_ERR_DOCUMENT_END;
 		    ctxt->wellFormed = 0;
 		    ctxt->instate = XML_PARSER_EOF;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering EOF\n");
-#endif
 		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 			ctxt->sax->endDocument(ctxt->userData);
 		    goto done;
@@ -5787,19 +5452,11 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		cur = in->cur[0];
 	        if (cur != '<') {
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering CONTENT\n");
-#endif
 		    break;
 		}
 		if (next == '/') {
 		    ctxt->instate = XML_PARSER_END_TAG;
 		    ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering END_TAG\n");
-#endif
 		    break;
 		}
 		if ((!terminate) &&
@@ -5841,10 +5498,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 			ctxt->sax->endElement(ctxt->userData, name);
 		    htmlnamePop(ctxt);
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering CONTENT\n");
-#endif
 		    break;
 		}
 
@@ -5867,10 +5520,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		        htmlNodeInfoPush(ctxt, &node_info);
 
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering CONTENT\n");
-#endif
 		    break;
 		}
 
@@ -5887,10 +5536,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 	            htmlNodeInfoPush(ctxt, &node_info);
 
 		ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
                 break;
 	    }
             case XML_PARSER_CONTENT: {
@@ -5899,14 +5544,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
                 /*
 		 * Handle preparsed entities and charRef
 		 */
-		if (ctxt->token != 0) {
-		    chr[0] = (xmlChar) ctxt->token;
-		    htmlCheckParagraph(ctxt);
-		    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
-			ctxt->sax->characters(ctxt->userData, chr, 1);
-		    ctxt->token = 0;
-		    ctxt->checkIndex = 0;
-		}
 		if ((avail == 1) && (terminate)) {
 		    cur = in->cur[0];
 		    if ((cur != '<') && (cur != '&')) {
@@ -5929,7 +5566,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 					    ctxt->userData, chr, 1);
 			    }
 			}
-			ctxt->token = 0;
 			ctxt->checkIndex = 0;
 			in->cur++;
 			break;
@@ -5952,20 +5588,24 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 			if (idx < 0)
 			    goto done;
 		        val = in->cur[idx + 2];
-			if (val == 0) /* bad cut of input */
+			if (val == 0) { /* bad cut of input */
+                            /*
+                             * FIXME: htmlParseScript checks for additional
+                             * characters after '</'.
+                             */
+                            ctxt->checkIndex = idx;
 			    goto done;
+                        }
 		    }
 		    htmlParseScript(ctxt);
 		    if ((cur == '<') && (next == '/')) {
 			ctxt->instate = XML_PARSER_END_TAG;
 			ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"HPP: entering END_TAG\n");
-#endif
 			break;
 		    }
 		} else if ((cur == '<') && (next == '!')) {
+                    if (avail < 4)
+                        goto done;
                     /*
                      * Sometimes DOCTYPE arrives in the middle of the document
                      */
@@ -5984,10 +5624,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
                         if ((!terminate) &&
                             (htmlParseLookupCommentEnd(ctxt) < 0))
                             goto done;
-#ifdef DEBUG_PUSH
-                        xmlGenericError(xmlGenericErrorContext,
-                                "HPP: Parsing Comment\n");
-#endif
                         htmlParseComment(ctxt);
                         ctxt->instate = XML_PARSER_CONTENT;
                     } else {
@@ -6000,31 +5636,17 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
                     if ((!terminate) &&
                         (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
                         goto done;
-#ifdef DEBUG_PUSH
-                    xmlGenericError(xmlGenericErrorContext,
-                            "HPP: Parsing PI\n");
-#endif
                     htmlParsePI(ctxt);
                     ctxt->instate = XML_PARSER_CONTENT;
-                } else if ((cur == '<') && (next == '!') && (avail < 4)) {
-                    goto done;
                 } else if ((cur == '<') && (next == '/')) {
                     ctxt->instate = XML_PARSER_END_TAG;
                     ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-                    xmlGenericError(xmlGenericErrorContext,
-                            "HPP: entering END_TAG\n");
-#endif
                     break;
                 } else if ((cur == '<') && IS_ASCII_LETTER(next)) {
                     if ((!terminate) && (next == 0))
                         goto done;
                     ctxt->instate = XML_PARSER_START_TAG;
                     ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-                    xmlGenericError(xmlGenericErrorContext,
-                            "HPP: entering START_TAG\n");
-#endif
                     break;
                 } else if (cur == '<') {
                     if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
@@ -6043,11 +5665,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
                         (htmlParseLookupSequence(ctxt, '<', 0, 0, 0) < 0))
                         goto done;
                     ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-                    xmlGenericError(xmlGenericErrorContext,
-                            "HPP: Parsing char data\n");
-#endif
-                    while ((ctxt->instate != XML_PARSER_EOF) &&
+                    while ((PARSER_STOPPED(ctxt) == 0) &&
                            (cur != '<') && (in->cur < in->end)) {
                         if (cur == '&') {
                             htmlParseReference(ctxt);
@@ -6073,122 +5691,12 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
 		    ctxt->instate = XML_PARSER_CONTENT;
 		}
 		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
 	        break;
-            case XML_PARSER_CDATA_SECTION:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == CDATA\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_DTD:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == DTD\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_COMMENT:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == COMMENT\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_PI:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == PI\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_ENTITY_DECL:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == ENTITY_DECL\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_ENTITY_VALUE:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == ENTITY_VALUE\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering DTD\n");
-#endif
-		break;
-            case XML_PARSER_ATTRIBUTE_VALUE:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == ATTRIBUTE_VALUE\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_START_TAG;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering START_TAG\n");
-#endif
-		break;
-	    case XML_PARSER_SYSTEM_LITERAL:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		    "HPP: internal error, state == XML_PARSER_SYSTEM_LITERAL\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-	    case XML_PARSER_IGNORE:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == XML_PARSER_IGNORE\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-	    case XML_PARSER_PUBLIC_LITERAL:
+	    default:
 		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == XML_PARSER_LITERAL\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
+			     "HPP: internal error\n", NULL, NULL);
+		ctxt->instate = XML_PARSER_EOF;
 		break;
-
 	}
     }
 done:
@@ -6208,85 +5716,62 @@ done:
 	 (ctxt->instate == XML_PARSER_EPILOG))) {
 	xmlDtdPtr dtd;
 	dtd = xmlGetIntSubset(ctxt->myDoc);
-	if (dtd == NULL)
+	if (dtd == NULL) {
 	    ctxt->myDoc->intSubset =
 		xmlCreateIntSubset(ctxt->myDoc, BAD_CAST "html",
 		    BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN",
 		    BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd");
+            if (ctxt->myDoc->intSubset == NULL)
+                htmlErrMemory(ctxt);
+        }
     }
-#ifdef DEBUG_PUSH
-    xmlGenericError(xmlGenericErrorContext, "HPP: done %d\n", ret);
-#endif
     return(ret);
 }
 
 /**
  * htmlParseChunk:
  * @ctxt:  an HTML parser context
- * @chunk:  an char array
- * @size:  the size in byte of the chunk
+ * @chunk:  chunk of memory
+ * @size:  size of chunk in bytes
  * @terminate:  last chunk indicator
  *
- * Parse a Chunk of memory
+ * Parse a chunk of memory in push parser mode.
+ *
+ * Assumes that the parser context was initialized with
+ * htmlCreatePushParserCtxt.
+ *
+ * The last chunk, which will often be empty, must be marked with
+ * the @terminate flag. With the default SAX callbacks, the resulting
+ * document will be available in ctxt->myDoc. This pointer will not
+ * be freed by the library.
+ *
+ * If the document isn't well-formed, ctxt->myDoc is set to NULL.
  *
- * Returns zero if no error, the xmlParserErrors otherwise.
+ * Returns an xmlParserErrors code (0 on success).
  */
 int
 htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size,
               int terminate) {
-    if ((ctxt == NULL) || (ctxt->input == NULL)) {
-	htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		     "htmlParseChunk: context error\n", NULL, NULL);
-	return(XML_ERR_INTERNAL_ERROR);
-    }
+    if ((ctxt == NULL) || (ctxt->input == NULL))
+	return(XML_ERR_ARGUMENT);
+    if (PARSER_STOPPED(ctxt) != 0)
+        return(ctxt->errNo);
     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
-        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
-	size_t cur = ctxt->input->cur - ctxt->input->base;
+        (ctxt->input->buf != NULL))  {
+	size_t pos = ctxt->input->cur - ctxt->input->base;
 	int res;
 
 	res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
+        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
 	if (res < 0) {
-	    ctxt->errNo = XML_PARSER_EOF;
-	    ctxt->disableSAX = 1;
-	    return (XML_PARSER_EOF);
-	}
-#ifdef DEBUG_PUSH
-	xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size);
-#endif
-
-#if 0
-	if ((terminate) || (ctxt->input->buf->buffer->use > 80))
-	    htmlParseTryOrFinish(ctxt, terminate);
-#endif
-    } else if (ctxt->instate != XML_PARSER_EOF) {
-	if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
-	    xmlParserInputBufferPtr in = ctxt->input->buf;
-	    if ((in->encoder != NULL) && (in->buffer != NULL) &&
-		    (in->raw != NULL)) {
-		int nbchars;
-		size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
-		size_t current = ctxt->input->cur - ctxt->input->base;
-
-		nbchars = xmlCharEncInput(in, terminate);
-		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
-		if (nbchars < 0) {
-		    htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
-			         "encoder error\n", NULL, NULL);
-		    return(XML_ERR_INVALID_ENCODING);
-		}
-	    }
+            htmlParseErr(ctxt, ctxt->input->buf->error,
+                         "xmlParserInputBufferPush failed", NULL, NULL);
+            xmlHaltParser(ctxt);
+	    return (ctxt->errNo);
 	}
     }
     htmlParseTryOrFinish(ctxt, terminate);
     if (terminate) {
-	if ((ctxt->instate != XML_PARSER_EOF) &&
-	    (ctxt->instate != XML_PARSER_EPILOG) &&
-	    (ctxt->instate != XML_PARSER_MISC)) {
-	    ctxt->errNo = XML_ERR_DOCUMENT_END;
-	    ctxt->wellFormed = 0;
-	}
 	if (ctxt->instate != XML_PARSER_EOF) {
 	    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 		ctxt->sax->endDocument(ctxt->userData);
@@ -6304,88 +5789,37 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size,
 
 /**
  * htmlCreatePushParserCtxt:
- * @sax:  a SAX handler
- * @user_data:  The user data returned on SAX callbacks
- * @chunk:  a pointer to an array of chars
+ * @sax:  a SAX handler (optional)
+ * @user_data:  The user data returned on SAX callbacks (optional)
+ * @chunk:  a pointer to an array of chars (optional)
  * @size:  number of chars in the array
- * @filename:  an optional file name or URI
- * @enc:  an optional encoding
+ * @filename:  only used for error reporting (optional)
+ * @enc:  encoding (deprecated, pass XML_CHAR_ENCODING_NONE)
  *
- * Create a parser context for using the HTML parser in push mode
- * The value of @filename is used for fetching external entities
- * and error/warning reports.
+ * Create a parser context for using the HTML parser in push mode.
  *
- * Returns the new parser context or NULL
+ * Returns the new parser context or NULL if a memory allocation
+ * failed.
  */
 htmlParserCtxtPtr
 htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data,
                          const char *chunk, int size, const char *filename,
 			 xmlCharEncoding enc) {
     htmlParserCtxtPtr ctxt;
-    htmlParserInputPtr inputStream;
-    xmlParserInputBufferPtr buf;
-
-    xmlInitParser();
-
-    buf = xmlAllocParserInputBuffer(enc);
-    if (buf == NULL) return(NULL);
+    htmlParserInputPtr input;
+    const char *encoding;
 
-    ctxt = htmlNewParserCtxt();
-    if (ctxt == NULL) {
-	xmlFreeParserInputBuffer(buf);
+    ctxt = htmlNewSAXParserCtxt(sax, user_data);
+    if (ctxt == NULL)
 	return(NULL);
-    }
-    if(enc==XML_CHAR_ENCODING_UTF8 || buf->encoder)
-	ctxt->charset=XML_CHAR_ENCODING_UTF8;
-    if (sax != NULL) {
-	if (ctxt->sax != (xmlSAXHandlerPtr) &htmlDefaultSAXHandler)
-	    xmlFree(ctxt->sax);
-	ctxt->sax = (htmlSAXHandlerPtr) xmlMalloc(sizeof(htmlSAXHandler));
-	if (ctxt->sax == NULL) {
-	    xmlFree(buf);
-	    xmlFree(ctxt);
-	    return(NULL);
-	}
-	memcpy(ctxt->sax, sax, sizeof(htmlSAXHandler));
-	if (user_data != NULL)
-	    ctxt->userData = user_data;
-    }
-    if (filename == NULL) {
-	ctxt->directory = NULL;
-    } else {
-        ctxt->directory = xmlParserGetDirectory(filename);
-    }
 
-    inputStream = htmlNewInputStream(ctxt);
-    if (inputStream == NULL) {
-	xmlFreeParserCtxt(ctxt);
-	xmlFree(buf);
+    encoding = xmlGetCharEncodingName(enc);
+    input = xmlNewInputPush(ctxt, filename, chunk, size, encoding);
+    if (input == NULL) {
+	htmlFreeParserCtxt(ctxt);
 	return(NULL);
     }
-
-    if (filename == NULL)
-	inputStream->filename = NULL;
-    else
-	inputStream->filename = (char *)
-	    xmlCanonicPath((const xmlChar *) filename);
-    inputStream->buf = buf;
-    xmlBufResetInput(buf->buffer, inputStream);
-
-    inputPush(ctxt, inputStream);
-
-    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
-        (ctxt->input->buf != NULL))  {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
-	size_t cur = ctxt->input->cur - ctxt->input->base;
-
-	xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
-#ifdef DEBUG_PUSH
-	xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size);
-#endif
-    }
-    ctxt->progressive = 1;
+    inputPush(ctxt, input);
 
     return(ctxt);
 }
@@ -6398,6 +5832,8 @@ htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data,
  * @sax:  the SAX handler block
  * @userData: if using SAX, this pointer will be provided on callbacks.
  *
+ * DEPRECATED: Use htmlNewSAXParserCtxt and htmlCtxtReadDoc.
+ *
  * Parse an HTML in-memory document. If sax is not NULL, use the SAX callbacks
  * to handle parse events. If sax is NULL, fallback to the default DOM
  * behavior and return a tree.
@@ -6412,25 +5848,20 @@ htmlSAXParseDoc(const xmlChar *cur, const char *encoding,
     htmlDocPtr ret;
     htmlParserCtxtPtr ctxt;
 
-    xmlInitParser();
-
-    if (cur == NULL) return(NULL);
+    if (cur == NULL)
+        return(NULL);
 
+    ctxt = htmlCreateDocParserCtxt(cur, NULL, encoding);
+    if (ctxt == NULL)
+        return(NULL);
 
-    ctxt = htmlCreateDocParserCtxt(cur, encoding);
-    if (ctxt == NULL) return(NULL);
     if (sax != NULL) {
-        if (ctxt->sax != NULL) xmlFree (ctxt->sax);
-        ctxt->sax = sax;
+        *ctxt->sax = *sax;
         ctxt->userData = userData;
     }
 
     htmlParseDocument(ctxt);
     ret = ctxt->myDoc;
-    if (sax != NULL) {
-	ctxt->sax = NULL;
-	ctxt->userData = NULL;
-    }
     htmlFreeParserCtxt(ctxt);
 
     return(ret);
@@ -6439,9 +5870,13 @@ htmlSAXParseDoc(const xmlChar *cur, const char *encoding,
 /**
  * htmlParseDoc:
  * @cur:  a pointer to an array of xmlChar
- * @encoding:  a free form C string describing the HTML document encoding, or NULL
+ * @encoding:  the encoding (optional)
+ *
+ * DEPRECATED: Use htmlReadDoc.
  *
- * parse an HTML in-memory document and build a tree.
+ * Parse an HTML in-memory document and build a tree.
+ *
+ * This function uses deprecated global parser options.
  *
  * Returns the resulting document tree
  */
@@ -6455,22 +5890,24 @@ htmlParseDoc(const xmlChar *cur, const char *encoding) {
 /**
  * htmlCreateFileParserCtxt:
  * @filename:  the filename
- * @encoding:  a free form C string describing the HTML document encoding, or NULL
+ * @encoding:  optional encoding
+ *
+ * DEPRECATED: Use htmlNewParserCtxt and htmlCtxtReadFile.
+ *
+ * Create a parser context to read from a file.
+ *
+ * A non-NULL encoding overrides encoding declarations in the document.
  *
- * Create a parser context for a file content.
  * Automatic support for ZLIB/Compress compressed document is provided
  * by default if found at compile-time.
  *
- * Returns the new parser context or NULL
+ * Returns the new parser context or NULL if a memory allocation failed.
  */
 htmlParserCtxtPtr
 htmlCreateFileParserCtxt(const char *filename, const char *encoding)
 {
     htmlParserCtxtPtr ctxt;
-    htmlParserInputPtr inputStream;
-    char *canonicFilename;
-    /* htmlCharEncoding enc; */
-    xmlChar *content, *content_line = (xmlChar *) "charset=";
+    htmlParserInputPtr input;
 
     if (filename == NULL)
         return(NULL);
@@ -6479,40 +5916,13 @@ htmlCreateFileParserCtxt(const char *filename, const char *encoding)
     if (ctxt == NULL) {
 	return(NULL);
     }
-    canonicFilename = (char *) xmlCanonicPath((const xmlChar *) filename);
-    if (canonicFilename == NULL) {
-#ifdef LIBXML_SAX1_ENABLED
-	if (xmlDefaultSAXHandler.error != NULL) {
-	    xmlDefaultSAXHandler.error(NULL, "out of memory\n");
-	}
-#endif
-	xmlFreeParserCtxt(ctxt);
-	return(NULL);
-    }
 
-    inputStream = xmlLoadExternalEntity(canonicFilename, NULL, ctxt);
-    xmlFree(canonicFilename);
-    if (inputStream == NULL) {
+    input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0);
+    if (input == NULL) {
 	xmlFreeParserCtxt(ctxt);
 	return(NULL);
     }
-
-    inputPush(ctxt, inputStream);
-
-    /* set encoding */
-    if (encoding) {
-        size_t l = strlen(encoding);
-
-	if (l < 1000) {
-	    content = xmlMallocAtomic (xmlStrlen(content_line) + l + 1);
-	    if (content) {
-		strcpy ((char *)content, (char *)content_line);
-		strcat ((char *)content, (char *)encoding);
-		htmlCheckEncoding (ctxt, content);
-		xmlFree (content);
-	    }
-	}
-    }
+    inputPush(ctxt, input);
 
     return(ctxt);
 }
@@ -6520,10 +5930,12 @@ htmlCreateFileParserCtxt(const char *filename, const char *encoding)
 /**
  * htmlSAXParseFile:
  * @filename:  the filename
- * @encoding:  a free form C string describing the HTML document encoding, or NULL
+ * @encoding:  encoding (optional)
  * @sax:  the SAX handler block
  * @userData: if using SAX, this pointer will be provided on callbacks.
  *
+ * DEPRECATED: Use htmlNewSAXParserCtxt and htmlCtxtReadFile.
+ *
  * parse an HTML file and build a tree. Automatic support for ZLIB/Compress
  * compressed document is provided by default if found at compile-time.
  * It use the given SAX function block to handle the parsing callback.
@@ -6540,8 +5952,6 @@ htmlSAXParseFile(const char *filename, const char *encoding, htmlSAXHandlerPtr s
     htmlParserCtxtPtr ctxt;
     htmlSAXHandlerPtr oldsax = NULL;
 
-    xmlInitParser();
-
     ctxt = htmlCreateFileParserCtxt(filename, encoding);
     if (ctxt == NULL) return(NULL);
     if (sax != NULL) {
@@ -6565,10 +5975,11 @@ htmlSAXParseFile(const char *filename, const char *encoding, htmlSAXHandlerPtr s
 /**
  * htmlParseFile:
  * @filename:  the filename
- * @encoding:  a free form C string describing the HTML document encoding, or NULL
+ * @encoding:  encoding (optional)
  *
- * parse an HTML file and build a tree. Automatic support for ZLIB/Compress
- * compressed document is provided by default if found at compile-time.
+ * Parse an HTML file and build a tree.
+ *
+ * See xmlNewInputURL for details.
  *
  * Returns the resulting document tree
  */
@@ -6582,6 +5993,8 @@ htmlParseFile(const char *filename, const char *encoding) {
  * htmlHandleOmittedElem:
  * @val:  int 0 or 1
  *
+ * DEPRECATED: Use HTML_PARSE_NOIMPLIED
+ *
  * Set and return the previous value for handling HTML omitted tags.
  *
  * Returns the last value for 0 for no handling, 1 for auto insertion.
@@ -6687,7 +6100,7 @@ htmlAttrAllowed(const htmlElemDesc* elt, const xmlChar* attr, int legacy) {
  *	for other nodes, HTML_NA (no checks performed)
  */
 htmlStatus
-htmlNodeStatus(const htmlNodePtr node, int legacy) {
+htmlNodeStatus(htmlNodePtr node, int legacy) {
   if ( ! node )
     return HTML_INVALID ;
 
@@ -6739,7 +6152,6 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt)
     if (ctxt == NULL)
         return;
 
-    xmlInitParser();
     dict = ctxt->dict;
 
     while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
@@ -6769,12 +6181,16 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt)
     ctxt->version = NULL;
     DICT_FREE(ctxt->encoding);
     ctxt->encoding = NULL;
-    DICT_FREE(ctxt->directory);
-    ctxt->directory = NULL;
     DICT_FREE(ctxt->extSubURI);
     ctxt->extSubURI = NULL;
     DICT_FREE(ctxt->extSubSystem);
     ctxt->extSubSystem = NULL;
+
+    if (ctxt->directory != NULL) {
+        xmlFree(ctxt->directory);
+        ctxt->directory = NULL;
+    }
+
     if (ctxt->myDoc != NULL)
         xmlFreeDoc(ctxt->myDoc);
     ctxt->myDoc = NULL;
@@ -6783,23 +6199,22 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt)
     ctxt->hasExternalSubset = 0;
     ctxt->hasPErefs = 0;
     ctxt->html = 1;
-    ctxt->external = 0;
     ctxt->instate = XML_PARSER_START;
-    ctxt->token = 0;
 
     ctxt->wellFormed = 1;
     ctxt->nsWellFormed = 1;
     ctxt->disableSAX = 0;
     ctxt->valid = 1;
     ctxt->vctxt.userData = ctxt;
+    ctxt->vctxt.flags = XML_VCTXT_USE_PCTXT;
     ctxt->vctxt.error = xmlParserValidityError;
     ctxt->vctxt.warning = xmlParserValidityWarning;
     ctxt->record_info = 0;
     ctxt->checkIndex = 0;
+    ctxt->endCheckState = 0;
     ctxt->inSubset = 0;
     ctxt->errNo = XML_ERR_OK;
     ctxt->depth = 0;
-    ctxt->charset = XML_CHAR_ENCODING_NONE;
     ctxt->catalogs = NULL;
     xmlInitNodeInfoSeq(&ctxt->node_seq);
 
@@ -6811,6 +6226,11 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt)
         xmlHashFree(ctxt->attsSpecial, NULL);
         ctxt->attsSpecial = NULL;
     }
+
+    ctxt->nbErrors = 0;
+    ctxt->nbWarnings = 0;
+    if (ctxt->lastError.code != XML_ERR_OK)
+        xmlResetError(&ctxt->lastError);
 }
 
 /**
@@ -6881,253 +6301,286 @@ htmlCtxtUseOptions(htmlParserCtxtPtr ctxt, int options)
         options -= HTML_PARSE_NOIMPLIED;
     }
     ctxt->dictNames = 0;
+    ctxt->linenumbers = 1;
     return (options);
 }
 
 /**
- * htmlDoRead:
+ * htmlCtxtParseDocument:
  * @ctxt:  an HTML parser context
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
- * @options:  a combination of htmlParserOption(s)
- * @reuse:  keep the context for reuse
+ * @input:  parser input
  *
- * Common front-end for the htmlRead functions
+ * Parse an HTML document and return the resulting document tree.
+ *
+ * Available since 2.13.0.
  *
  * Returns the resulting document tree or NULL
  */
-static htmlDocPtr
-htmlDoRead(htmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
-          int options, int reuse)
+htmlDocPtr
+htmlCtxtParseDocument(htmlParserCtxtPtr ctxt, xmlParserInputPtr input)
 {
     htmlDocPtr ret;
 
-    htmlCtxtUseOptions(ctxt, options);
-    ctxt->html = 1;
-    if (encoding != NULL) {
-        xmlCharEncodingHandlerPtr hdlr;
-
-	hdlr = xmlFindCharEncodingHandler(encoding);
-	if (hdlr != NULL) {
-	    xmlSwitchToEncoding(ctxt, hdlr);
-	    if (ctxt->input->encoding != NULL)
-	      xmlFree((xmlChar *) ctxt->input->encoding);
-            ctxt->input->encoding = xmlStrdup((xmlChar *)encoding);
-        }
+    if ((ctxt == NULL) || (input == NULL))
+        return(NULL);
+
+    /* assert(ctxt->inputNr == 0); */
+    while (ctxt->inputNr > 0)
+        xmlFreeInputStream(inputPop(ctxt));
+
+    if (inputPush(ctxt, input) < 0) {
+        xmlFreeInputStream(input);
+        return(NULL);
     }
-    if ((URL != NULL) && (ctxt->input != NULL) &&
-        (ctxt->input->filename == NULL))
-        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
+
+    ctxt->html = 1;
     htmlParseDocument(ctxt);
-    ret = ctxt->myDoc;
-    ctxt->myDoc = NULL;
-    if (!reuse) {
-        if ((ctxt->dictNames) &&
-	    (ret != NULL) &&
-	    (ret->dict == ctxt->dict))
-	    ctxt->dict = NULL;
-	xmlFreeParserCtxt(ctxt);
+
+    if (ctxt->errNo != XML_ERR_NO_MEMORY) {
+        ret = ctxt->myDoc;
+    } else {
+        ret = NULL;
+        xmlFreeDoc(ctxt->myDoc);
     }
-    return (ret);
+    ctxt->myDoc = NULL;
+
+    /* assert(ctxt->inputNr == 1); */
+    while (ctxt->inputNr > 0)
+        xmlFreeInputStream(inputPop(ctxt));
+
+    return(ret);
 }
 
 /**
  * htmlReadDoc:
- * @cur:  a pointer to a zero terminated string
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
- * @options:  a combination of htmlParserOption(s)
+ * @str:  a pointer to a zero terminated string
+ * @url:  only used for error reporting (optoinal)
+ * @encoding:  the document encoding (optional)
+ * @options:  a combination of htmlParserOptions
  *
- * parse an XML in-memory document and build a tree.
+ * Convenience function to parse an HTML document from a zero-terminated
+ * string.
  *
- * Returns the resulting document tree
+ * See htmlCtxtReadDoc for details.
+ *
+ * Returns the resulting document tree.
  */
 htmlDocPtr
-htmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
+htmlReadDoc(const xmlChar *str, const char *url, const char *encoding,
+            int options)
 {
     htmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
+    htmlDocPtr doc;
 
-    if (cur == NULL)
-        return (NULL);
-
-    xmlInitParser();
-    ctxt = htmlCreateDocParserCtxt(cur, NULL);
+    ctxt = htmlNewParserCtxt();
     if (ctxt == NULL)
-        return (NULL);
-    return (htmlDoRead(ctxt, URL, encoding, options, 0));
+        return(NULL);
+
+    htmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputString(ctxt, url, (const char *) str, encoding,
+                              XML_INPUT_BUF_STATIC);
+
+    doc = htmlCtxtParseDocument(ctxt, input);
+
+    htmlFreeParserCtxt(ctxt);
+    return(doc);
 }
 
 /**
  * htmlReadFile:
  * @filename:  a file or URL
- * @encoding:  the document encoding, or NULL
- * @options:  a combination of htmlParserOption(s)
+ * @encoding:  the document encoding (optional)
+ * @options:  a combination of htmlParserOptions
  *
- * parse an XML file from the filesystem or the network.
+ * Convenience function to parse an HTML file from the filesystem,
+ * the network or a global user-defined resource loader.
  *
- * Returns the resulting document tree
+ * See htmlCtxtReadFile for details.
+ *
+ * Returns the resulting document tree.
  */
 htmlDocPtr
 htmlReadFile(const char *filename, const char *encoding, int options)
 {
     htmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
+    htmlDocPtr doc;
 
-    xmlInitParser();
-    ctxt = htmlCreateFileParserCtxt(filename, encoding);
+    ctxt = htmlNewParserCtxt();
     if (ctxt == NULL)
-        return (NULL);
-    return (htmlDoRead(ctxt, NULL, NULL, options, 0));
+        return(NULL);
+
+    htmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0);
+
+    doc = htmlCtxtParseDocument(ctxt, input);
+
+    htmlFreeParserCtxt(ctxt);
+    return(doc);
 }
 
 /**
  * htmlReadMemory:
  * @buffer:  a pointer to a char array
  * @size:  the size of the array
- * @URL:  the base URL to use for the document
+ * @url:  only used for error reporting (optional)
  * @encoding:  the document encoding, or NULL
  * @options:  a combination of htmlParserOption(s)
  *
- * parse an XML in-memory document and build a tree.
+ * Convenience function to parse an HTML document from memory.
+ * The input buffer must not contain any terminating null bytes.
+ *
+ * See htmlCtxtReadMemory for details.
  *
  * Returns the resulting document tree
  */
 htmlDocPtr
-htmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
+htmlReadMemory(const char *buffer, int size, const char *url,
+               const char *encoding, int options)
 {
     htmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
+    htmlDocPtr doc;
 
-    xmlInitParser();
-    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
+    if (size < 0)
+	return(NULL);
+
+    ctxt = htmlNewParserCtxt();
     if (ctxt == NULL)
-        return (NULL);
-    htmlDefaultSAXHandlerInit();
-    if (ctxt->sax != NULL)
-        memcpy(ctxt->sax, &htmlDefaultSAXHandler, sizeof(xmlSAXHandlerV1));
-    return (htmlDoRead(ctxt, URL, encoding, options, 0));
+        return(NULL);
+
+    htmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputMemory(ctxt, url, buffer, size, encoding,
+                              XML_INPUT_BUF_STATIC);
+
+    doc = htmlCtxtParseDocument(ctxt, input);
+
+    htmlFreeParserCtxt(ctxt);
+    return(doc);
 }
 
 /**
  * htmlReadFd:
  * @fd:  an open file descriptor
- * @URL:  the base URL to use for the document
+ * @url:  only used for error reporting (optional)
  * @encoding:  the document encoding, or NULL
- * @options:  a combination of htmlParserOption(s)
+ * @options:  a combination of htmlParserOptions
+ *
+ * Convenience function to parse an HTML document from a
+ * file descriptor.
  *
- * parse an HTML from a file descriptor and build a tree.
  * NOTE that the file descriptor will not be closed when the
- *      reader is closed or reset.
+ * context is freed or reset.
+ *
+ * See htmlCtxtReadFd for details.
  *
  * Returns the resulting document tree
  */
 htmlDocPtr
-htmlReadFd(int fd, const char *URL, const char *encoding, int options)
+htmlReadFd(int fd, const char *url, const char *encoding, int options)
 {
     htmlParserCtxtPtr ctxt;
-    xmlParserInputBufferPtr input;
-    htmlParserInputPtr stream;
-
-    if (fd < 0)
-        return (NULL);
+    xmlParserInputPtr input;
+    htmlDocPtr doc;
 
-    xmlInitParser();
-    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
-    if (input == NULL)
-        return (NULL);
-    input->closecallback = NULL;
     ctxt = htmlNewParserCtxt();
-    if (ctxt == NULL) {
-        xmlFreeParserInputBuffer(input);
-        return (NULL);
-    }
-    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
-    if (stream == NULL) {
-        xmlFreeParserInputBuffer(input);
-	htmlFreeParserCtxt(ctxt);
-        return (NULL);
-    }
-    inputPush(ctxt, stream);
-    return (htmlDoRead(ctxt, URL, encoding, options, 0));
+    if (ctxt == NULL)
+        return(NULL);
+
+    htmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputFd(ctxt, url, fd, encoding, 0);
+
+    doc = htmlCtxtParseDocument(ctxt, input);
+
+    htmlFreeParserCtxt(ctxt);
+    return(doc);
 }
 
 /**
  * htmlReadIO:
  * @ioread:  an I/O read function
- * @ioclose:  an I/O close function
+ * @ioclose:  an I/O close function (optional)
  * @ioctx:  an I/O handler
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
+ * @url:  only used for error reporting (optional)
+ * @encoding:  the document encoding (optional)
  * @options:  a combination of htmlParserOption(s)
  *
- * parse an HTML document from I/O functions and source and build a tree.
+ * Convenience function to parse an HTML document from I/O functions
+ * and context.
+ *
+ * See htmlCtxtReadIO for details.
  *
  * Returns the resulting document tree
  */
 htmlDocPtr
 htmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
-          void *ioctx, const char *URL, const char *encoding, int options)
+          void *ioctx, const char *url, const char *encoding, int options)
 {
     htmlParserCtxtPtr ctxt;
-    xmlParserInputBufferPtr input;
-    xmlParserInputPtr stream;
-
-    if (ioread == NULL)
-        return (NULL);
-    xmlInitParser();
+    xmlParserInputPtr input;
+    htmlDocPtr doc;
 
-    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
-                                         XML_CHAR_ENCODING_NONE);
-    if (input == NULL) {
-        if (ioclose != NULL)
-            ioclose(ioctx);
-        return (NULL);
-    }
     ctxt = htmlNewParserCtxt();
-    if (ctxt == NULL) {
-        xmlFreeParserInputBuffer(input);
-        return (NULL);
-    }
-    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
-    if (stream == NULL) {
-        xmlFreeParserInputBuffer(input);
-	xmlFreeParserCtxt(ctxt);
+    if (ctxt == NULL)
         return (NULL);
-    }
-    inputPush(ctxt, stream);
-    return (htmlDoRead(ctxt, URL, encoding, options, 0));
+
+    htmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputIO(ctxt, url, ioread, ioclose, ioctx, encoding, 0);
+
+    doc = htmlCtxtParseDocument(ctxt, input);
+
+    htmlFreeParserCtxt(ctxt);
+    return(doc);
 }
 
 /**
  * htmlCtxtReadDoc:
  * @ctxt:  an HTML parser context
- * @cur:  a pointer to a zero terminated string
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
- * @options:  a combination of htmlParserOption(s)
+ * @str:  a pointer to a zero terminated string
+ * @URL:  only used for error reporting (optional)
+ * @encoding:  the document encoding (optional)
+ * @options:  a combination of htmlParserOptions
  *
- * parse an XML in-memory document and build a tree.
- * This reuses the existing @ctxt parser context
+ * Parse an HTML in-memory document and build a tree.
+ *
+ * See htmlCtxtUseOptions for details.
  *
  * Returns the resulting document tree
  */
 htmlDocPtr
-htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar * cur,
-               const char *URL, const char *encoding, int options)
+htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar *str,
+                const char *URL, const char *encoding, int options)
 {
-    if (cur == NULL)
+    xmlParserInputPtr input;
+
+    if (ctxt == NULL)
         return (NULL);
-    return (htmlCtxtReadMemory(ctxt, (const char *) cur, xmlStrlen(cur), URL,
-                               encoding, options));
+
+    htmlCtxtReset(ctxt);
+    htmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputString(ctxt, URL, (const char *) str, encoding, 0);
+
+    return(htmlCtxtParseDocument(ctxt, input));
 }
 
 /**
  * htmlCtxtReadFile:
  * @ctxt:  an HTML parser context
  * @filename:  a file or URL
- * @encoding:  the document encoding, or NULL
- * @options:  a combination of htmlParserOption(s)
+ * @encoding:  the document encoding (optional)
+ * @options:  a combination of htmlParserOptions
+ *
+ * Parse an HTML file from the filesystem, the network or a
+ * user-defined resource loader.
  *
- * parse an XML file from the filesystem or the network.
- * This reuses the existing @ctxt parser context
+ * See xmlNewInputURL and htmlCtxtUseOptions for details.
  *
  * Returns the resulting document tree
  */
@@ -7135,22 +6588,17 @@ htmlDocPtr
 htmlCtxtReadFile(htmlParserCtxtPtr ctxt, const char *filename,
                 const char *encoding, int options)
 {
-    xmlParserInputPtr stream;
+    xmlParserInputPtr input;
 
-    if (filename == NULL)
-        return (NULL);
     if (ctxt == NULL)
         return (NULL);
-    xmlInitParser();
 
     htmlCtxtReset(ctxt);
+    htmlCtxtUseOptions(ctxt, options);
 
-    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
-    if (stream == NULL) {
-        return (NULL);
-    }
-    inputPush(ctxt, stream);
-    return (htmlDoRead(ctxt, NULL, encoding, options, 1));
+    input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0);
+
+    return(htmlCtxtParseDocument(ctxt, input));
 }
 
 /**
@@ -7158,12 +6606,14 @@ htmlCtxtReadFile(htmlParserCtxtPtr ctxt, const char *filename,
  * @ctxt:  an HTML parser context
  * @buffer:  a pointer to a char array
  * @size:  the size of the array
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
- * @options:  a combination of htmlParserOption(s)
+ * @URL:  only used for error reporting (optional)
+ * @encoding:  the document encoding (optinal)
+ * @options:  a combination of htmlParserOptions
  *
- * parse an XML in-memory document and build a tree.
- * This reuses the existing @ctxt parser context
+ * Parse an HTML in-memory document and build a tree. The input buffer must
+ * not contain any terminating null bytes.
+ *
+ * See htmlCtxtUseOptions for details.
  *
  * Returns the resulting document tree
  */
@@ -7171,42 +6621,34 @@ htmlDocPtr
 htmlCtxtReadMemory(htmlParserCtxtPtr ctxt, const char *buffer, int size,
                   const char *URL, const char *encoding, int options)
 {
-    xmlParserInputBufferPtr input;
-    xmlParserInputPtr stream;
+    xmlParserInputPtr input;
 
-    if (ctxt == NULL)
+    if ((ctxt == NULL) || (size < 0))
         return (NULL);
-    if (buffer == NULL)
-        return (NULL);
-    xmlInitParser();
 
     htmlCtxtReset(ctxt);
+    htmlCtxtUseOptions(ctxt, options);
 
-    input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
-    if (input == NULL) {
-	return(NULL);
-    }
-
-    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
-    if (stream == NULL) {
-	xmlFreeParserInputBuffer(input);
-	return(NULL);
-    }
+    input = xmlNewInputMemory(ctxt, URL, buffer, size, encoding,
+                              XML_INPUT_BUF_STATIC);
 
-    inputPush(ctxt, stream);
-    return (htmlDoRead(ctxt, URL, encoding, options, 1));
+    return(htmlCtxtParseDocument(ctxt, input));
 }
 
 /**
  * htmlCtxtReadFd:
  * @ctxt:  an HTML parser context
  * @fd:  an open file descriptor
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
- * @options:  a combination of htmlParserOption(s)
+ * @URL:  only used for error reporting (optional)
+ * @encoding:  the document encoding (optinal)
+ * @options:  a combination of htmlParserOptions
  *
- * parse an XML from a file descriptor and build a tree.
- * This reuses the existing @ctxt parser context
+ * Parse an HTML from a file descriptor and build a tree.
+ *
+ * See htmlCtxtUseOptions for details.
+ *
+ * NOTE that the file descriptor will not be closed when the
+ * context is freed or reset.
  *
  * Returns the resulting document tree
  */
@@ -7214,28 +6656,17 @@ htmlDocPtr
 htmlCtxtReadFd(htmlParserCtxtPtr ctxt, int fd,
               const char *URL, const char *encoding, int options)
 {
-    xmlParserInputBufferPtr input;
-    xmlParserInputPtr stream;
+    xmlParserInputPtr input;
 
-    if (fd < 0)
-        return (NULL);
     if (ctxt == NULL)
-        return (NULL);
-    xmlInitParser();
+        return(NULL);
 
     htmlCtxtReset(ctxt);
+    htmlCtxtUseOptions(ctxt, options);
 
+    input = xmlNewInputFd(ctxt, URL, fd, encoding, 0);
 
-    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
-    if (input == NULL)
-        return (NULL);
-    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
-    if (stream == NULL) {
-        xmlFreeParserInputBuffer(input);
-        return (NULL);
-    }
-    inputPush(ctxt, stream);
-    return (htmlDoRead(ctxt, URL, encoding, options, 1));
+    return(htmlCtxtParseDocument(ctxt, input));
 }
 
 /**
@@ -7248,8 +6679,9 @@ htmlCtxtReadFd(htmlParserCtxtPtr ctxt, int fd,
  * @encoding:  the document encoding, or NULL
  * @options:  a combination of htmlParserOption(s)
  *
- * parse an HTML document from I/O functions and source and build a tree.
- * This reuses the existing @ctxt parser context
+ * Parse an HTML document from I/O functions and source and build a tree.
+ *
+ * See xmlNewInputIO and htmlCtxtUseOptions for details.
  *
  * Returns the resulting document tree
  */
@@ -7259,31 +6691,17 @@ htmlCtxtReadIO(htmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
 	      const char *URL,
               const char *encoding, int options)
 {
-    xmlParserInputBufferPtr input;
-    xmlParserInputPtr stream;
+    xmlParserInputPtr input;
 
-    if (ioread == NULL)
-        return (NULL);
     if (ctxt == NULL)
         return (NULL);
-    xmlInitParser();
 
     htmlCtxtReset(ctxt);
+    htmlCtxtUseOptions(ctxt, options);
 
-    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
-                                         XML_CHAR_ENCODING_NONE);
-    if (input == NULL) {
-        if (ioclose != NULL)
-            ioclose(ioctx);
-        return (NULL);
-    }
-    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
-    if (stream == NULL) {
-        xmlFreeParserInputBuffer(input);
-        return (NULL);
-    }
-    inputPush(ctxt, stream);
-    return (htmlDoRead(ctxt, URL, encoding, options, 1));
+    input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0);
+
+    return(htmlCtxtParseDocument(ctxt, input));
 }
 
 #endif /* LIBXML_HTML_ENABLED */
diff --git a/HTMLtree.c b/HTMLtree.c
index 3dd78a91ebaab141c698fd211f10d1a3362f8c53..8fa022c11b86277b3d029253567d38a4241210c6 100644
--- a/HTMLtree.c
+++ b/HTMLtree.c
@@ -19,13 +19,14 @@
 #include <libxml/HTMLparser.h>
 #include <libxml/HTMLtree.h>
 #include <libxml/entities.h>
-#include <libxml/valid.h>
 #include <libxml/xmlerror.h>
 #include <libxml/parserInternals.h>
-#include <libxml/globals.h>
 #include <libxml/uri.h>
 
-#include "buf.h"
+#include "private/buf.h"
+#include "private/error.h"
+#include "private/io.h"
+#include "private/save.h"
 
 /************************************************************************
  *									*
@@ -328,27 +329,11 @@ htmlIsBooleanAttr(const xmlChar *name)
 }
 
 #ifdef LIBXML_OUTPUT_ENABLED
-/*
- * private routine exported from xmlIO.c
- */
-xmlOutputBufferPtr
-xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
 /************************************************************************
  *									*
  *			Output error handlers				*
  *									*
  ************************************************************************/
-/**
- * htmlSaveErrMemory:
- * @extra:  extra information
- *
- * Handle an out of memory condition
- */
-static void
-htmlSaveErrMemory(const char *extra)
-{
-    __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra);
-}
 
 /**
  * htmlSaveErr:
@@ -362,6 +347,7 @@ static void
 htmlSaveErr(int code, xmlNodePtr node, const char *extra)
 {
     const char *msg = NULL;
+    int res;
 
     switch(code) {
         case XML_SAVE_NOT_UTF8:
@@ -379,7 +365,13 @@ htmlSaveErr(int code, xmlNodePtr node, const char *extra)
 	default:
 	    msg = "unexpected error number\n";
     }
-    __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra);
+
+    res = __xmlRaiseError(NULL, NULL, NULL, NULL, node,
+                          XML_FROM_OUTPUT, code, XML_ERR_ERROR, NULL, 0,
+                          extra, NULL, NULL, 0, 0,
+                          msg, extra);
+    if (res < 0)
+        xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_OUTPUT, NULL);
 }
 
 /************************************************************************
@@ -388,6 +380,27 @@ htmlSaveErr(int code, xmlNodePtr node, const char *extra)
  *									*
  ************************************************************************/
 
+static xmlCharEncodingHandler *
+htmlFindOutputEncoder(const char *encoding) {
+    xmlCharEncodingHandler *handler = NULL;
+
+    if (encoding != NULL) {
+        int res;
+
+        res = xmlOpenCharEncodingHandler(encoding, /* output */ 1,
+                                         &handler);
+        if (res != XML_ERR_OK)
+            htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
+    } else {
+        /*
+         * Fallback to HTML when the encoding is unspecified
+         */
+        xmlOpenCharEncodingHandler("HTML", /* output */ 1, &handler);
+    }
+
+    return(handler);
+}
+
 /**
  * htmlBufNodeDumpFormat:
  * @buf:  the xmlBufPtr output
@@ -403,21 +416,19 @@ static size_t
 htmlBufNodeDumpFormat(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur,
 	           int format) {
     size_t use;
-    int ret;
+    size_t ret;
     xmlOutputBufferPtr outbuf;
 
     if (cur == NULL) {
-	return (-1);
+	return ((size_t) -1);
     }
     if (buf == NULL) {
-	return (-1);
+	return ((size_t) -1);
     }
     outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
-    if (outbuf == NULL) {
-        htmlSaveErrMemory("allocating HTML output buffer");
-	return (-1);
-    }
-    memset(outbuf, 0, (size_t) sizeof(xmlOutputBuffer));
+    if (outbuf == NULL)
+	return ((size_t) -1);
+    memset(outbuf, 0, sizeof(xmlOutputBuffer));
     outbuf->buffer = buf;
     outbuf->encoder = NULL;
     outbuf->writecallback = NULL;
@@ -427,8 +438,11 @@ htmlBufNodeDumpFormat(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur,
 
     use = xmlBufUse(buf);
     htmlNodeDumpFormatOutput(outbuf, doc, cur, NULL, format);
+    if (outbuf->error)
+        ret = (size_t) -1;
+    else
+        ret = xmlBufUse(buf) - use;
     xmlFree(outbuf);
-    ret = xmlBufUse(buf) - use;
     return (ret);
 }
 
@@ -456,6 +470,7 @@ htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur) {
     if (buffer == NULL)
         return(-1);
 
+    xmlBufSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
     ret = htmlBufNodeDumpFormat(buffer, doc, cur, 1);
 
     xmlBufBackToBuffer(buffer);
@@ -483,35 +498,20 @@ int
 htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc,
 	               xmlNodePtr cur, const char *encoding, int format) {
     xmlOutputBufferPtr buf;
-    xmlCharEncodingHandlerPtr handler = NULL;
+    xmlCharEncodingHandlerPtr handler;
     int ret;
 
     xmlInitParser();
 
-    if (encoding != NULL) {
-	xmlCharEncoding enc;
-
-	enc = xmlParseCharEncoding(encoding);
-	if (enc != XML_CHAR_ENCODING_UTF8) {
-	    handler = xmlFindCharEncodingHandler(encoding);
-	    if (handler == NULL)
-		htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
-	}
-    } else {
-        /*
-         * Fallback to HTML or ASCII when the encoding is unspecified
-         */
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("HTML");
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("ascii");
-    }
-
     /*
      * save the content to a temp buffer.
      */
+    handler = htmlFindOutputEncoder(encoding);
     buf = xmlOutputBufferCreateFile(out, handler);
-    if (buf == NULL) return(0);
+    if (buf == NULL) {
+        xmlCharEncCloseFunc(handler);
+        return(0);
+    }
 
     htmlNodeDumpFormatOutput(buf, doc, cur, NULL, format);
 
@@ -553,52 +553,34 @@ htmlDocDumpMemoryFormat(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
 
     if ((mem == NULL) || (size == NULL))
         return;
-    if (cur == NULL) {
-	*mem = NULL;
-	*size = 0;
+    *mem = NULL;
+    *size = 0;
+    if (cur == NULL)
 	return;
-    }
 
     encoding = (const char *) htmlGetMetaEncoding(cur);
-
-    if (encoding != NULL) {
-	xmlCharEncoding enc;
-
-	enc = xmlParseCharEncoding(encoding);
-	if (enc != XML_CHAR_ENCODING_UTF8) {
-	    handler = xmlFindCharEncodingHandler(encoding);
-	    if (handler == NULL)
-                htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
-
-	}
-    } else {
-        /*
-         * Fallback to HTML or ASCII when the encoding is unspecified
-         */
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("HTML");
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("ascii");
-    }
-
+    handler = htmlFindOutputEncoder(encoding);
     buf = xmlAllocOutputBufferInternal(handler);
     if (buf == NULL) {
-	*mem = NULL;
-	*size = 0;
+        xmlCharEncCloseFunc(handler);
 	return;
     }
 
     htmlDocContentDumpFormatOutput(buf, cur, NULL, format);
 
     xmlOutputBufferFlush(buf);
-    if (buf->conv != NULL) {
-	*size = xmlBufUse(buf->conv);
-	*mem = xmlStrndup(xmlBufContent(buf->conv), *size);
-    } else {
-	*size = xmlBufUse(buf->buffer);
-	*mem = xmlStrndup(xmlBufContent(buf->buffer), *size);
+
+    if (!buf->error) {
+        if (buf->conv != NULL) {
+            *size = xmlBufUse(buf->conv);
+            *mem = xmlStrndup(xmlBufContent(buf->conv), *size);
+        } else {
+            *size = xmlBufUse(buf->buffer);
+            *mem = xmlStrndup(xmlBufContent(buf->buffer), *size);
+        }
     }
-    (void)xmlOutputBufferClose(buf);
+
+    xmlOutputBufferClose(buf);
 }
 
 /**
@@ -622,8 +604,6 @@ htmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
  *									*
  ************************************************************************/
 
-void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
-
 /**
  * htmlDtdDumpOutput:
  * @buf:  the HTML buffer output
@@ -647,15 +627,15 @@ htmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
     xmlOutputBufferWriteString(buf, (const char *)cur->name);
     if (cur->ExternalID != NULL) {
 	xmlOutputBufferWriteString(buf, " PUBLIC ");
-	xmlBufWriteQuotedString(buf->buffer, cur->ExternalID);
+	xmlOutputBufferWriteQuotedString(buf, cur->ExternalID);
 	if (cur->SystemID != NULL) {
 	    xmlOutputBufferWriteString(buf, " ");
-	    xmlBufWriteQuotedString(buf->buffer, cur->SystemID);
+	    xmlOutputBufferWriteQuotedString(buf, cur->SystemID);
 	}
     } else if (cur->SystemID != NULL &&
 	       xmlStrcmp(cur->SystemID, BAD_CAST "about:legacy-compat")) {
 	xmlOutputBufferWriteString(buf, " SYSTEM ");
-	xmlBufWriteQuotedString(buf->buffer, cur->SystemID);
+	xmlOutputBufferWriteQuotedString(buf, cur->SystemID);
     }
     xmlOutputBufferWriteString(buf, ">\n");
 }
@@ -705,22 +685,27 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
 		while (IS_BLANK_CH(*tmp)) tmp++;
 
 		/*
-		 * the < and > have already been escaped at the entity level
-		 * And doing so here breaks server side includes
+                 * Angle brackets are technically illegal in URIs, but they're
+                 * used in server side includes, for example. Curly brackets
+                 * are illegal as well and often used in templates.
+                 * Don't escape non-whitespace, printable ASCII chars for
+                 * improved interoperability. Only escape space, control
+                 * and non-ASCII chars.
 		 */
-		escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+<>");
+		escaped = xmlURIEscapeStr(tmp,
+                        BAD_CAST "\"#$%&+,/:;<=>?@[\\]^`{|}");
 		if (escaped != NULL) {
-		    xmlBufWriteQuotedString(buf->buffer, escaped);
+		    xmlOutputBufferWriteQuotedString(buf, escaped);
 		    xmlFree(escaped);
 		} else {
-		    xmlBufWriteQuotedString(buf->buffer, value);
+                    buf->error = XML_ERR_NO_MEMORY;
 		}
 	    } else {
-		xmlBufWriteQuotedString(buf->buffer, value);
+		xmlOutputBufferWriteQuotedString(buf, value);
 	    }
 	    xmlFree(value);
 	} else  {
-	    xmlOutputBufferWriteString(buf, "=\"\"");
+            buf->error = XML_ERR_NO_MEMORY;
 	}
     }
 }
@@ -861,10 +846,12 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
                 xmlChar *buffer;
 
                 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
-                if (buffer != NULL) {
-                    xmlOutputBufferWriteString(buf, (const char *)buffer);
-                    xmlFree(buffer);
+                if (buffer == NULL) {
+                    buf->error = XML_ERR_NO_MEMORY;
+                    return;
                 }
+                xmlOutputBufferWriteString(buf, (const char *)buffer);
+                xmlFree(buffer);
             } else {
                 xmlOutputBufferWriteString(buf, (const char *)cur->content);
             }
@@ -1040,28 +1027,12 @@ htmlDocDump(FILE *f, xmlDocPtr cur) {
     }
 
     encoding = (const char *) htmlGetMetaEncoding(cur);
-
-    if (encoding != NULL) {
-	xmlCharEncoding enc;
-
-	enc = xmlParseCharEncoding(encoding);
-	if (enc != XML_CHAR_ENCODING_UTF8) {
-	    handler = xmlFindCharEncodingHandler(encoding);
-	    if (handler == NULL)
-		htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
-	}
-    } else {
-        /*
-         * Fallback to HTML or ASCII when the encoding is unspecified
-         */
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("HTML");
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("ascii");
-    }
-
+    handler = htmlFindOutputEncoder(encoding);
     buf = xmlOutputBufferCreateFile(f, handler);
-    if (buf == NULL) return(-1);
+    if (buf == NULL) {
+        xmlCharEncCloseFunc(handler);
+        return(-1);
+    }
     htmlDocContentDumpOutput(buf, cur, NULL);
 
     ret = xmlOutputBufferClose(buf);
@@ -1090,31 +1061,12 @@ htmlSaveFile(const char *filename, xmlDocPtr cur) {
     xmlInitParser();
 
     encoding = (const char *) htmlGetMetaEncoding(cur);
-
-    if (encoding != NULL) {
-	xmlCharEncoding enc;
-
-	enc = xmlParseCharEncoding(encoding);
-	if (enc != XML_CHAR_ENCODING_UTF8) {
-	    handler = xmlFindCharEncodingHandler(encoding);
-	    if (handler == NULL)
-		htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
-	}
-    } else {
-        /*
-         * Fallback to HTML or ASCII when the encoding is unspecified
-         */
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("HTML");
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("ascii");
-    }
-
-    /*
-     * save the content to a temp buffer.
-     */
+    handler = htmlFindOutputEncoder(encoding);
     buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
-    if (buf == NULL) return(0);
+    if (buf == NULL) {
+        xmlCharEncCloseFunc(handler);
+        return(0);
+    }
 
     htmlDocContentDumpOutput(buf, cur, NULL);
 
@@ -1145,33 +1097,20 @@ htmlSaveFileFormat(const char *filename, xmlDocPtr cur,
 
     xmlInitParser();
 
-    if (encoding != NULL) {
-	xmlCharEncoding enc;
-
-	enc = xmlParseCharEncoding(encoding);
-	if (enc != XML_CHAR_ENCODING_UTF8) {
-	    handler = xmlFindCharEncodingHandler(encoding);
-	    if (handler == NULL)
-		htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
-	}
-        htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
-    } else {
+    handler = htmlFindOutputEncoder(encoding);
+    if (handler != NULL)
+        htmlSetMetaEncoding(cur, (const xmlChar *) handler->name);
+    else
 	htmlSetMetaEncoding(cur, (const xmlChar *) "UTF-8");
 
-        /*
-         * Fallback to HTML or ASCII when the encoding is unspecified
-         */
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("HTML");
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("ascii");
-    }
-
     /*
      * save the content to a temp buffer.
      */
     buf = xmlOutputBufferCreateFilename(filename, handler, 0);
-    if (buf == NULL) return(0);
+    if (buf == NULL) {
+        xmlCharEncCloseFunc(handler);
+        return(0);
+    }
 
     htmlDocContentDumpFormatOutput(buf, cur, encoding, format);
 
diff --git a/README.md b/README.md
index ad423e686f94dabf6516b21e7c48d27d56a846cc..58c9433f9aac54542872ad7cde8540faad70ad73 100644
--- a/README.md
+++ b/README.md
@@ -3,15 +3,17 @@
 libxml2 is an XML toolkit implemented in C, originally developed for
 the GNOME Project.
 
-Full documentation is available at
-<https://gitlab.gnome.org/GNOME/libxml2/-/wikis>.
+Official releases can be downloaded from
+<https://download.gnome.org/sources/libxml2/>
+
+The git repository is hosted on GNOME's GitLab server:
+<https://gitlab.gnome.org/GNOME/libxml2>
 
 Bugs should be reported at
-<https://gitlab.gnome.org/GNOME/libxml2/-/issues>.
+<https://gitlab.gnome.org/GNOME/libxml2/-/issues>
 
-A mailing list xml@gnome.org is available. You can subscribe at
-<https://mail.gnome.org/mailman/listinfo/xml>. The list archive is at
-<https://mail.gnome.org/archives/xml/>.
+Documentation is available at
+<https://gitlab.gnome.org/GNOME/libxml2/-/wikis>
 
 ## License
 
@@ -19,31 +21,64 @@ This code is released under the MIT License, see the Copyright file.
 
 ## Build instructions
 
-libxml2 can be built with GNU Autotools, CMake, or several other build
-systems in platform-specific subdirectories.
+libxml2 can be built with GNU Autotools, CMake, meson or several other
+build systems in platform-specific subdirectories.
 
 ### Autotools (for POSIX systems like Linux, BSD, macOS)
 
 If you build from a Git tree, you have to install Autotools and start
 by generating the configuration files with:
 
-    ./autogen.sh
+    ./autogen.sh [configuration options]
 
 If you build from a source tarball, extract the archive with:
 
     tar xf libxml2-xxx.tar.gz
     cd libxml2-xxx
 
-To see a list of build options:
-
-    ./configure --help
+Then you can configure and build the library:
 
-Also see the INSTALL file for additional instructions. Then you can
-configure and build the library:
-
-    ./configure [possible options]
+    ./configure [configuration options]
     make
 
+The following options disable or enable code modules and relevant symbols:
+
+    --with-c14n             Canonical XML 1.0 support (on)
+    --with-catalog          XML Catalogs support (on)
+    --with-debug            debugging module and shell (on)
+    --with-history          history support for shell (off)
+    --with-readline[=DIR]   use readline in DIR (for shell history)
+    --with-html             HTML parser (on)
+    --with-http             HTTP support (off)
+    --with-iconv[=DIR]      iconv support (on)
+    --with-icu              ICU support (off)
+    --with-iso8859x         ISO-8859-X support if no iconv (on)
+    --with-lzma[=DIR]       use liblzma in DIR (off)
+    --with-modules          dynamic modules support (on)
+    --with-output           serialization support (on)
+    --with-pattern          xmlPattern selection interface (on)
+    --with-push             push parser interfaces (on)
+    --with-python           Python bindings (on)
+    --with-reader           xmlReader parsing interface (on)
+    --with-regexps          regular expressions support (on)
+    --with-sax1             older SAX1 interface (on)
+    --with-schemas          XML Schemas 1.0 and RELAX NG support (on)
+    --with-schematron       Schematron support (on)
+    --with-threads          multithreading support (on)
+    --with-thread-alloc     per-thread malloc hooks (off)
+    --with-tree             DOM like tree manipulation APIs (on)
+    --with-valid            DTD validation support (on)
+    --with-writer           xmlWriter serialization interface (on)
+    --with-xinclude         XInclude 1.0 support (on)
+    --with-xpath            XPath 1.0 support (on)
+    --with-xptr             XPointer support (on)
+    --with-zlib[=DIR]       use libz in DIR (off)
+
+Other options:
+
+    --with-minimum          build a minimally sized library (off)
+    --with-legacy           maximum ABI compatibility (off)
+
 Note that by default, no optimization options are used. You have to
 enable them manually, for example with:
 
@@ -53,7 +88,7 @@ Now you can run the test suite with:
 
     make check
 
-Please report test failures to the mailing list or bug tracker.
+Please report test failures to the bug tracker.
 
 Then you can install the library:
 
@@ -84,33 +119,46 @@ Common CMake options include:
 You can also open the libxml source directory with its CMakeLists.txt
 directly in various IDEs such as CLion, QtCreator, or Visual Studio.
 
+### Meson
+
+Libxml can also be built with meson. Without option, simply call
+
+meson setup builddir
+ninja -C builddir
+
+To add options, see the meson_options.txt file. For example:
+
+meson setup -Dprefix=$prefix -Dftp=true -Dhistory=true -Dicu=true -Dhttp=true builddir
+
+To install libxml:
+
+ninja -C builddir install
+
+To launch tests:
+
+meson test -C builddir
+
 ## Dependencies
 
 Libxml does not require any other libraries. A platform with somewhat
 recent POSIX support should be sufficient (please report any violation
 to this rule you may find).
 
-However, if found at configuration time, libxml will detect and use
-the following libraries:
+The iconv function is required for conversion of character encodings.
+This function is part of POSIX.1-2001. If your platform doesn't provide
+iconv, you need an external libiconv library, for example
+[GNU libiconv](https://www.gnu.org/software/libiconv/). Alternatively,
+you can use [ICU](https://icu.unicode.org/).
 
-- [libz](https://zlib.net/), a highly portable and widely available
-  compression library.
-- [liblzma](https://tukaani.org/xz/), another compression library.
-- [libiconv](https://www.gnu.org/software/libiconv/), a character encoding
-  conversion library. The iconv function is part of POSIX.1-2001, so
-  libiconv isn't required on modern UNIX-like systems like Linux, BSD or
-  macOS.
-- [ICU](https://icu.unicode.org/), a Unicode library. Mainly useful as an
-  alternative to iconv on Windows. Unnecessary on most other systems.
+If enabled, libxml uses [libz](https://zlib.net/) or
+[liblzma](https://tukaani.org/xz/) to support reading compressed files.
+Use of this feature is discouraged.
 
 ## Contributing
 
 The current version of the code can be found in GNOME's GitLab at 
 at <https://gitlab.gnome.org/GNOME/libxml2>. The best way to get involved
-is by creating issues and merge requests on GitLab. Alternatively, you can
-start discussions and send patches to the mailing list. If you want to
-work with patches, please format them with git-format-patch and use plain
-text attachments.
+is by creating issues and merge requests on GitLab.
 
 All code must conform to C89 and pass the GitLab CI tests. Add regression
 tests if possible.
diff --git a/SAX.c b/SAX.c
index d8e972b84c2d75a7a56b0d38ddb4f32dfab62c6e..7f2f297406c7468b169c8ac8efb883b6ef31dd36 100644
--- a/SAX.c
+++ b/SAX.c
@@ -25,7 +25,6 @@
 #include <libxml/uri.h>
 #include <libxml/valid.h>
 #include <libxml/HTMLtree.h>
-#include <libxml/globals.h>
 #include <libxml/SAX2.h>
 
 #ifdef LIBXML_LEGACY_ENABLED
diff --git a/SAX2.c b/SAX2.c
index ec89046b1d6507dccae3b09adfe23143431aca50..32db6b4c1a44d2124f1a9c36819d659b0eb194a4 100644
--- a/SAX2.c
+++ b/SAX2.c
@@ -13,6 +13,7 @@
 #include <string.h>
 #include <limits.h>
 #include <stddef.h>
+#include <libxml/SAX2.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
 #include <libxml/parser.h>
@@ -22,66 +23,24 @@
 #include <libxml/xmlerror.h>
 #include <libxml/debugXML.h>
 #include <libxml/xmlIO.h>
-#include <libxml/SAX.h>
 #include <libxml/uri.h>
 #include <libxml/valid.h>
 #include <libxml/HTMLtree.h>
-#include <libxml/globals.h>
 
-/* Define SIZE_T_MAX unless defined through <limits.h>. */
-#ifndef SIZE_T_MAX
-# define SIZE_T_MAX     ((size_t)-1)
-#endif /* !SIZE_T_MAX */
+#include "private/error.h"
+#include "private/parser.h"
+#include "private/tree.h"
 
-/* #define DEBUG_SAX2 */
-/* #define DEBUG_SAX2_TREE */
-
-/**
- * TODO:
- *
- * macro to flag unimplemented blocks
- * XML_CATALOG_PREFER user env to select between system/public preferred
- * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
- *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
- *> values "system" and "public".  I have made the default be "system" to
- *> match yours.
- */
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
+#define XML_MAX_URI_LENGTH 2000
 
 /*
  * xmlSAX2ErrMemory:
  * @ctxt:  an XML validation parser context
  * @msg:   a string to accompany the error message
  */
-static void LIBXML_ATTR_FORMAT(2,0)
-xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
-    xmlStructuredErrorFunc schannel = NULL;
-    const char *str1 = "out of memory\n";
-
-    if (ctxt != NULL) {
-	ctxt->errNo = XML_ERR_NO_MEMORY;
-	if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
-	    schannel = ctxt->sax->serror;
-	__xmlRaiseError(schannel,
-			ctxt->vctxt.error, ctxt->vctxt.userData,
-			ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY,
-			XML_ERR_ERROR, NULL, 0, (const char *) str1,
-			NULL, NULL, 0, 0,
-			msg, (const char *) str1, NULL);
-	ctxt->errNo = XML_ERR_NO_MEMORY;
-	ctxt->instate = XML_PARSER_EOF;
-	ctxt->disableSAX = 1;
-    } else {
-	__xmlRaiseError(schannel,
-			NULL, NULL,
-			ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY,
-			XML_ERR_ERROR, NULL, 0, (const char *) str1,
-			NULL, NULL, 0, 0,
-			msg, (const char *) str1, NULL);
-    }
+static void
+xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt) {
+    xmlCtxtErrMemory(ctxt);
 }
 
 /**
@@ -96,32 +55,12 @@ xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
  */
 static void LIBXML_ATTR_FORMAT(3,0)
 xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
-            const char *msg, const char *str1, const char *str2)
+            const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
-    xmlStructuredErrorFunc schannel = NULL;
-
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL) {
-	ctxt->errNo = error;
-	if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
-	    schannel = ctxt->sax->serror;
-	__xmlRaiseError(schannel,
-			ctxt->vctxt.error, ctxt->vctxt.userData,
-			ctxt, NULL, XML_FROM_DTD, error,
-			XML_ERR_ERROR, NULL, 0, (const char *) str1,
-			(const char *) str2, NULL, 0, 0,
-			msg, (const char *) str1, (const char *) str2);
+    xmlCtxtErr(ctxt, NULL, XML_FROM_DTD, error, XML_ERR_ERROR,
+               str1, str2, NULL, 0, msg, str1, str2);
+    if (ctxt != NULL)
 	ctxt->valid = 0;
-    } else {
-	__xmlRaiseError(schannel,
-			NULL, NULL,
-			ctxt, NULL, XML_FROM_DTD, error,
-			XML_ERR_ERROR, NULL, 0, (const char *) str1,
-			(const char *) str2, NULL, 0, 0,
-			msg, (const char *) str1, (const char *) str2);
-    }
 }
 
 /**
@@ -138,21 +77,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
-                    XML_ERR_FATAL, NULL, 0,
-		    (const char *) str1, (const char *) str2,
-		    NULL, 0, 0, msg, str1, str2);
-    if (ctxt != NULL) {
-	ctxt->wellFormed = 0;
-	ctxt->valid = 0;
-	if (ctxt->recovery == 0)
-	    ctxt->disableSAX = 1;
-    }
+    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
+               str1, str2, NULL, 0, msg, str1, str2);
 }
 
 /**
@@ -169,15 +95,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                const char *msg, const xmlChar *str1)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
-                    XML_ERR_WARNING, NULL, 0,
-		    (const char *) str1, NULL,
-		    NULL, 0, 0, msg, str1);
+    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_WARNING,
+               str1, NULL, NULL, 0, msg, str1);
 }
 
 /**
@@ -193,15 +112,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
              const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
-                    XML_ERR_WARNING, NULL, 0,
-		    (const char *) str1, (const char *) str2,
-		    NULL, 0, 0, msg, str1, str2);
+    xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_WARNING,
+               str1, str2, NULL, 0, msg, str1, str2);
 }
 
 /**
@@ -332,11 +244,6 @@ xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlDtdPtr dtd;
     if (ctx == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
-            name, ExternalID, SystemID);
-#endif
 
     if (ctxt->myDoc == NULL)
 	return;
@@ -351,7 +258,7 @@ xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
     ctxt->myDoc->intSubset =
 	xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
     if (ctxt->myDoc->intSubset == NULL)
-        xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
+        xmlSAX2ErrMemory(ctxt);
 }
 
 /**
@@ -369,13 +276,9 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     if (ctx == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
-            name, ExternalID, SystemID);
-#endif
-    if (((ExternalID != NULL) || (SystemID != NULL)) &&
-        (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
+    if ((SystemID != NULL) &&
+        ((ctxt->options & XML_PARSE_NO_XXE) == 0) &&
+        (((ctxt->validate) || (ctxt->loadsubset)) &&
 	 (ctxt->wellFormed && ctxt->myDoc))) {
 	/*
 	 * Try to fetch and parse the external subset.
@@ -385,9 +288,9 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
 	int oldinputMax;
 	xmlParserInputPtr *oldinputTab;
 	xmlParserInputPtr input = NULL;
-	xmlCharEncoding enc;
-	int oldcharset;
 	const xmlChar *oldencoding;
+        unsigned long consumed;
+        size_t buffered;
 
 	/*
 	 * Ask the Entity resolver to load the damn thing
@@ -399,7 +302,11 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
 	    return;
 	}
 
-	xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
+	if (xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID) == NULL) {
+            xmlSAX2ErrMemory(ctxt);
+            xmlFreeInputStream(input);
+            return;
+        }
 
 	/*
 	 * make sure we won't destroy the main document context
@@ -408,19 +315,18 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
 	oldinputNr = ctxt->inputNr;
 	oldinputMax = ctxt->inputMax;
 	oldinputTab = ctxt->inputTab;
-	oldcharset = ctxt->charset;
 	oldencoding = ctxt->encoding;
 	ctxt->encoding = NULL;
 
 	ctxt->inputTab = (xmlParserInputPtr *)
 	                 xmlMalloc(5 * sizeof(xmlParserInputPtr));
 	if (ctxt->inputTab == NULL) {
-	    xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
+	    xmlSAX2ErrMemory(ctxt);
+            xmlFreeInputStream(input);
 	    ctxt->input = oldinput;
 	    ctxt->inputNr = oldinputNr;
 	    ctxt->inputMax = oldinputMax;
 	    ctxt->inputTab = oldinputTab;
-	    ctxt->charset = oldcharset;
 	    ctxt->encoding = oldencoding;
 	    return;
 	}
@@ -429,14 +335,6 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
 	ctxt->input = NULL;
 	xmlPushInput(ctxt, input);
 
-	/*
-	 * On the fly encoding conversion if needed
-	 */
-	if (ctxt->input->length >= 4) {
-	    enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-
 	if (input->filename == NULL)
 	    input->filename = (char *) xmlCanonicPath(SystemID);
 	input->line = 1;
@@ -456,6 +354,18 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
 
 	while (ctxt->inputNr > 1)
 	    xmlPopInput(ctxt);
+
+        consumed = ctxt->input->consumed;
+        buffered = ctxt->input->cur - ctxt->input->base;
+        if (buffered > ULONG_MAX - consumed)
+            consumed = ULONG_MAX;
+        else
+            consumed += buffered;
+        if (consumed > ULONG_MAX - ctxt->sizeentities)
+            ctxt->sizeentities = ULONG_MAX;
+        else
+            ctxt->sizeentities += consumed;
+
 	xmlFreeInputStream(ctxt->input);
         xmlFree(ctxt->inputTab);
 
@@ -466,7 +376,6 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
 	ctxt->inputNr = oldinputNr;
 	ctxt->inputMax = oldinputMax;
 	ctxt->inputTab = oldinputTab;
-	ctxt->charset = oldcharset;
 	if ((ctxt->encoding != NULL) &&
 	    ((ctxt->dict == NULL) ||
 	     (!xmlDictOwns(ctxt->dict, ctxt->encoding))))
@@ -494,27 +403,44 @@ xmlParserInputPtr
 xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlParserInputPtr ret;
+    xmlParserInputPtr ret = NULL;
     xmlChar *URI;
-    const char *base = NULL;
+    const xmlChar *base = NULL;
+    int res;
 
     if (ctx == NULL) return(NULL);
     if (ctxt->input != NULL)
-	base = ctxt->input->filename;
-    if (base == NULL)
-	base = ctxt->directory;
+	base = BAD_CAST ctxt->input->filename;
 
-    URI = xmlBuildURI(systemId, (const xmlChar *) base);
+    /*
+     * We don't really need the 'directory' struct member, but some
+     * users set it manually to a base URI for memory streams.
+     */
+    if (base == NULL)
+        base = BAD_CAST ctxt->directory;
 
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
-#endif
+    if ((xmlStrlen(systemId) > XML_MAX_URI_LENGTH) ||
+        (xmlStrlen(base) > XML_MAX_URI_LENGTH)) {
+        xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, "URI too long");
+        return(NULL);
+    }
+    res = xmlBuildURISafe(systemId, base, &URI);
+    if (URI == NULL) {
+        if (res < 0)
+            xmlSAX2ErrMemory(ctxt);
+        else
+            xmlWarnMsg(ctxt, XML_ERR_INVALID_URI,
+                       "Can't resolve URI: %s\n", systemId);
+        return(NULL);
+    }
+    if (xmlStrlen(URI) > XML_MAX_URI_LENGTH) {
+        xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, "URI too long");
+    } else {
+        ret = xmlLoadExternalEntity((const char *) URI,
+                                    (const char *) publicId, ctxt);
+    }
 
-    ret = xmlLoadExternalEntity((const char *) URI,
-				(const char *) publicId, ctxt);
-    if (URI != NULL)
-	xmlFree(URI);
+    xmlFree(URI);
     return(ret);
 }
 
@@ -534,10 +460,6 @@ xmlSAX2GetEntity(void *ctx, const xmlChar *name)
     xmlEntityPtr ret = NULL;
 
     if (ctx == NULL) return(NULL);
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2GetEntity(%s)\n", name);
-#endif
 
     if (ctxt->inSubset == 0) {
 	ret = xmlGetPredefinedEntity(name);
@@ -584,10 +506,6 @@ xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
     xmlEntityPtr ret;
 
     if (ctx == NULL) return(NULL);
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
-#endif
 
     ret = xmlGetParameterEntity(ctxt->myDoc, name);
     return(ret);
@@ -611,55 +529,80 @@ xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
 {
     xmlEntityPtr ent;
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    int extSubset;
+    int res;
 
-    if (ctx == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
-            name, type, publicId, systemId, content);
-#endif
-    if (ctxt->inSubset == 1) {
-	ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
-		              systemId, content);
-	if ((ent == NULL) && (ctxt->pedantic))
-	    xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
-	     "Entity(%s) already defined in the internal subset\n",
-	               name);
-	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
-	    xmlChar *URI;
-	    const char *base = NULL;
-
-	    if (ctxt->input != NULL)
-		base = ctxt->input->filename;
-	    if (base == NULL)
-		base = ctxt->directory;
-
-	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
-	    ent->URI = URI;
-	}
-    } else if (ctxt->inSubset == 2) {
-	ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
-		              systemId, content);
-	if ((ent == NULL) && (ctxt->pedantic) &&
-	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-	    ctxt->sax->warning(ctxt->userData,
-	     "Entity(%s) already defined in the external subset\n", name);
-	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
-	    xmlChar *URI;
-	    const char *base = NULL;
-
-	    if (ctxt->input != NULL)
-		base = ctxt->input->filename;
-	    if (base == NULL)
-		base = ctxt->directory;
-
-	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
-	    ent->URI = URI;
-	}
-    } else {
-	xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
-	               "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
-		       name, NULL);
+    if ((ctxt == NULL) || (ctxt->myDoc == NULL))
+        return;
+
+    extSubset = ctxt->inSubset == 2;
+    res = xmlAddEntity(ctxt->myDoc, extSubset, name, type, publicId, systemId,
+                       content, &ent);
+    switch (res) {
+        case XML_ERR_OK:
+            break;
+        case XML_ERR_NO_MEMORY:
+            xmlSAX2ErrMemory(ctxt);
+            return;
+        case XML_WAR_ENTITY_REDEFINED:
+            if (ctxt->pedantic) {
+                if (extSubset)
+                    xmlWarnMsg(ctxt, res, "Entity(%s) already defined in the"
+                               " external subset\n", name);
+                else
+                    xmlWarnMsg(ctxt, res, "Entity(%s) already defined in the"
+                               " internal subset\n", name);
+            }
+            return;
+        case XML_ERR_REDECL_PREDEF_ENTITY:
+            /*
+             * Technically an error but it's a common mistake to get double
+             * escaping according to "4.6 Predefined Entities" wrong.
+             */
+            xmlWarnMsg(ctxt, res, "Invalid redeclaration of predefined"
+                       " entity '%s'", name);
+            return;
+        default:
+            xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
+                           "Unexpected error code from xmlAddEntity\n",
+                           NULL, NULL);
+            return;
+    }
+
+    if ((ent->URI == NULL) && (systemId != NULL)) {
+        xmlChar *URI;
+        const char *base = NULL;
+        int i;
+
+        for (i = ctxt->inputNr - 1; i >= 0; i--) {
+            if (ctxt->inputTab[i]->filename != NULL) {
+                base = ctxt->inputTab[i]->filename;
+                break;
+            }
+        }
+
+        /*
+         * We don't really need the 'directory' struct member, but some
+         * users set it manually to a base URI for memory streams.
+         */
+        if (base == NULL)
+            base = ctxt->directory;
+
+        res = xmlBuildURISafe(systemId, (const xmlChar *) base, &URI);
+
+        if (URI == NULL) {
+            if (res < 0) {
+                xmlSAX2ErrMemory(ctxt);
+            } else {
+                xmlWarnMsg(ctxt, XML_ERR_INVALID_URI,
+                           "Can't resolve URI: %s\n", systemId);
+            }
+        } else if (xmlStrlen(URI) > XML_MAX_URI_LENGTH) {
+            xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, "URI too long");
+            xmlFree(URI);
+        } else {
+            ent->URI = URI;
+        }
     }
 }
 
@@ -690,11 +633,6 @@ xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
         return;
 
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
-            elem, fullname, type, def, defaultValue);
-#endif
     if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
         (type != XML_ATTRIBUTE_ID)) {
 	/*
@@ -707,6 +645,8 @@ xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
     }
     /* TODO: optimize name/prefix allocation */
     name = xmlSplitQName(ctxt, fullname, &prefix);
+    if (name == NULL)
+        xmlSAX2ErrMemory(ctxt);
     ctxt->vctxt.valid = 1;
     if (ctxt->inSubset == 1)
 	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
@@ -721,6 +661,7 @@ xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
 	     "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
 	               name, NULL);
 	xmlFree(name);
+	xmlFree(prefix);
 	xmlFreeEnumeration(tree);
 	return;
     }
@@ -760,11 +701,6 @@ xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
         return;
 
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-                    "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
-#endif
-
     if (ctxt->inSubset == 1)
         elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
                                  name, (xmlElementTypeVal) type, content);
@@ -809,11 +745,6 @@ xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
         return;
 
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
-#endif
-
     if ((publicId == NULL) && (systemId == NULL)) {
 	xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
 	     "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
@@ -855,59 +786,8 @@ xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
 		   const xmlChar *publicId, const xmlChar *systemId,
 		   const xmlChar *notationName)
 {
-    xmlEntityPtr ent;
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    if (ctx == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
-            name, publicId, systemId, notationName);
-#endif
-    if (ctxt->inSubset == 1) {
-	ent = xmlAddDocEntity(ctxt->myDoc, name,
-			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
-			publicId, systemId, notationName);
-	if ((ent == NULL) && (ctxt->pedantic) &&
-	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-	    ctxt->sax->warning(ctxt->userData,
-	     "Entity(%s) already defined in the internal subset\n", name);
-	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
-	    xmlChar *URI;
-	    const char *base = NULL;
-
-	    if (ctxt->input != NULL)
-		base = ctxt->input->filename;
-	    if (base == NULL)
-		base = ctxt->directory;
-
-	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
-	    ent->URI = URI;
-	}
-    } else if (ctxt->inSubset == 2) {
-	ent = xmlAddDtdEntity(ctxt->myDoc, name,
-			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
-			publicId, systemId, notationName);
-	if ((ent == NULL) && (ctxt->pedantic) &&
-	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-	    ctxt->sax->warning(ctxt->userData,
-	     "Entity(%s) already defined in the external subset\n", name);
-	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
-	    xmlChar *URI;
-	    const char *base = NULL;
-
-	    if (ctxt->input != NULL)
-		base = ctxt->input->filename;
-	    if (base == NULL)
-		base = ctxt->directory;
-
-	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
-	    ent->URI = URI;
-	}
-    } else {
-        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
-	     "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
-	               name, NULL);
-    }
+    xmlSAX2EntityDecl(ctx, name, XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
+                      publicId, systemId, (xmlChar *) notationName);
 }
 
 /**
@@ -921,11 +801,6 @@ xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
 void
 xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
 {
-    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2SetDocumentLocator()\n");
-#endif
 }
 
 /**
@@ -942,42 +817,28 @@ xmlSAX2StartDocument(void *ctx)
 
     if (ctx == NULL) return;
 
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2StartDocument()\n");
-#endif
-    if (ctxt->html) {
 #ifdef LIBXML_HTML_ENABLED
+    if (ctxt->html) {
 	if (ctxt->myDoc == NULL)
 	    ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
 	if (ctxt->myDoc == NULL) {
-	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
+	    xmlSAX2ErrMemory(ctxt);
 	    return;
 	}
 	ctxt->myDoc->properties = XML_DOC_HTML;
 	ctxt->myDoc->parseFlags = ctxt->options;
-#else
-        xmlGenericError(xmlGenericErrorContext,
-		"libxml2 built without HTML support\n");
-	ctxt->errNo = XML_ERR_INTERNAL_ERROR;
-	ctxt->instate = XML_PARSER_EOF;
-	ctxt->disableSAX = 1;
-	return;
+    } else
 #endif
-    } else {
+    {
 	doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
 	if (doc != NULL) {
 	    doc->properties = 0;
 	    if (ctxt->options & XML_PARSE_OLD10)
 	        doc->properties |= XML_DOC_OLD10;
 	    doc->parseFlags = ctxt->options;
-	    if (ctxt->encoding != NULL)
-		doc->encoding = xmlStrdup(ctxt->encoding);
-	    else
-		doc->encoding = NULL;
 	    doc->standalone = ctxt->standalone;
 	} else {
-	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
+	    xmlSAX2ErrMemory(ctxt);
 	    return;
 	}
 	if ((ctxt->dictNames) && (doc != NULL)) {
@@ -989,7 +850,7 @@ xmlSAX2StartDocument(void *ctx)
 	(ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
 	ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
 	if (ctxt->myDoc->URL == NULL)
-	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
+	    xmlSAX2ErrMemory(ctxt);
     }
 }
 
@@ -1003,10 +864,8 @@ void
 xmlSAX2EndDocument(void *ctx)
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2EndDocument()\n");
-#endif
+    xmlDocPtr doc;
+
     if (ctx == NULL) return;
 #ifdef LIBXML_VALID_ENABLED
     if (ctxt->validate && ctxt->wellFormed &&
@@ -1014,23 +873,51 @@ xmlSAX2EndDocument(void *ctx)
 	ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
 #endif /* LIBXML_VALID_ENABLED */
 
-    /*
-     * Grab the encoding if it was added on-the-fly
-     */
-    if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
-	(ctxt->myDoc->encoding == NULL)) {
-	ctxt->myDoc->encoding = ctxt->encoding;
-	ctxt->encoding = NULL;
+    doc = ctxt->myDoc;
+    if ((doc != NULL) && (doc->encoding == NULL)) {
+        const xmlChar *encoding = xmlGetActualEncoding(ctxt);
+
+        if (encoding != NULL) {
+            doc->encoding = xmlStrdup(encoding);
+            if (doc->encoding == NULL)
+                xmlSAX2ErrMemory(ctxt);
+        }
+    }
+}
+
+static void
+xmlSAX2AppendChild(xmlParserCtxtPtr ctxt, xmlNodePtr node) {
+    xmlNodePtr parent;
+    xmlNodePtr last;
+
+    if (ctxt->inSubset == 1) {
+	parent = (xmlNodePtr) ctxt->myDoc->intSubset;
+    } else if (ctxt->inSubset == 2) {
+	parent = (xmlNodePtr) ctxt->myDoc->extSubset;
+    } else {
+        parent = ctxt->node;
+        if (parent == NULL)
+            parent = (xmlNodePtr) ctxt->myDoc;
     }
-    if ((ctxt->inputTab != NULL) &&
-        (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
-        (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
-	(ctxt->myDoc->encoding == NULL)) {
-	ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
+
+    last = parent->last;
+    if (last == NULL) {
+        parent->children = node;
+    } else {
+        last->next = node;
+        node->prev = last;
     }
-    if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
-	(ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
-	ctxt->myDoc->charset = ctxt->charset;
+
+    parent->last = node;
+    node->parent = parent;
+
+    if ((node->type != XML_TEXT_NODE) &&
+        (ctxt->linenumbers) &&
+	(ctxt->input != NULL)) {
+        if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
+            node->line = ctxt->input->line;
+        else
+            node->line = USHRT_MAX;
     }
 }
 
@@ -1049,15 +936,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
             const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
-                    XML_ERR_ERROR, NULL, 0,
-		    (const char *) str1, (const char *) str2,
-		    NULL, 0, 0, msg, str1, str2);
+    xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_ERROR,
+               str1, str2, NULL, 0, msg, str1, str2);
 }
 
 /**
@@ -1110,7 +990,7 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
 	}
     }
     if (name == NULL) {
-        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
+        xmlSAX2ErrMemory(ctxt);
 	if (ns != NULL)
 	    xmlFree(ns);
 	return;
@@ -1120,6 +1000,8 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
     if ((ctxt->html) &&
         (value == NULL) && (htmlIsBooleanAttr(fullname))) {
             nval = xmlStrdup(fullname);
+            if (nval == NULL)
+                xmlSAX2ErrMemory(ctxt);
             value = (const xmlChar *) nval;
     } else
 #endif
@@ -1157,12 +1039,10 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
         (void) nsret;
 
         if (!ctxt->replaceEntities) {
-	    ctxt->depth++;
-	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
-		                          0,0,0);
-	    ctxt->depth--;
+            /* TODO: normalize if needed */
+	    val = xmlExpandEntitiesInAttValue(ctxt, value, /* normalize */ 0);
 	    if (val == NULL) {
-	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
+	        xmlSAX2ErrMemory(ctxt);
 		if (name != NULL)
 		    xmlFree(name);
                 if (nval != NULL)
@@ -1176,16 +1056,16 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
 	if (val[0] != 0) {
 	    xmlURIPtr uri;
 
-	    uri = xmlParseURI((const char *)val);
+	    if (xmlParseURISafe((const char *)val, &uri) < 0)
+                xmlSAX2ErrMemory(ctxt);
 	    if (uri == NULL) {
-		if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-		    ctxt->sax->warning(ctxt->userData,
-			 "xmlns: %s not a valid URI\n", val);
+                xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
+                             "xmlns:%s: %s not a valid URI\n", name, value);
 	    } else {
 		if (uri->scheme == NULL) {
-		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-			ctxt->sax->warning(ctxt->userData,
-			     "xmlns: URI %s is not absolute\n", val);
+                    xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
+                                 "xmlns:%s: URI %s is not absolute\n",
+                                 name, value);
 		}
 		xmlFreeURI(uri);
 	    }
@@ -1193,16 +1073,19 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
 
 	/* a default namespace definition */
 	nsret = xmlNewNs(ctxt->node, val, NULL);
-
+        if (nsret == NULL) {
+            xmlSAX2ErrMemory(ctxt);
+        }
 #ifdef LIBXML_VALID_ENABLED
 	/*
 	 * Validate also for namespace decls, they are attributes from
 	 * an XML-1.0 perspective
 	 */
-        if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
-	    ctxt->myDoc && ctxt->myDoc->intSubset)
+        else if (ctxt->validate && ctxt->wellFormed &&
+                 ctxt->myDoc && ctxt->myDoc->intSubset) {
 	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
 					   ctxt->node, prefix, nsret, val);
+        }
 #endif /* LIBXML_VALID_ENABLED */
 	if (name != NULL)
 	    xmlFree(name);
@@ -1222,12 +1105,10 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
         (void) nsret;
 
         if (!ctxt->replaceEntities) {
-	    ctxt->depth++;
-	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
-		                          0,0,0);
-	    ctxt->depth--;
+            /* TODO: normalize if needed */
+	    val = xmlExpandEntitiesInAttValue(ctxt, value, /* normalize */ 0);
 	    if (val == NULL) {
-	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
+	        xmlSAX2ErrMemory(ctxt);
 	        xmlFree(ns);
 		if (name != NULL)
 		    xmlFree(name);
@@ -1246,7 +1127,8 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
 	if ((ctxt->pedantic != 0) && (val[0] != 0)) {
 	    xmlURIPtr uri;
 
-	    uri = xmlParseURI((const char *)val);
+	    if (xmlParseURISafe((const char *)val, &uri) < 0)
+                xmlSAX2ErrMemory(ctxt);
 	    if (uri == NULL) {
 	        xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
 			 "xmlns:%s: %s not a valid URI\n", name, value);
@@ -1262,15 +1144,20 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
 	/* a standard namespace definition */
 	nsret = xmlNewNs(ctxt->node, val, name);
 	xmlFree(ns);
+
+        if (nsret == NULL) {
+            xmlSAX2ErrMemory(ctxt);
+        }
 #ifdef LIBXML_VALID_ENABLED
 	/*
 	 * Validate also for namespace decls, they are attributes from
 	 * an XML-1.0 perspective
 	 */
-        if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
-	    ctxt->myDoc && ctxt->myDoc->intSubset)
+        else if (ctxt->validate && ctxt->wellFormed &&
+	         ctxt->myDoc && ctxt->myDoc->intSubset) {
 	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
 					   ctxt->node, prefix, nsret, value);
+        }
 #endif /* LIBXML_VALID_ENABLED */
 	if (name != NULL)
 	    xmlFree(name);
@@ -1282,7 +1169,11 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
     }
 
     if (ns != NULL) {
-	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
+        int res;
+
+	res = xmlSearchNsSafe(ctxt->node, ns, &namespace);
+        if (res < 0)
+            xmlSAX2ErrMemory(ctxt);
 
 	if (namespace == NULL) {
 	    xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
@@ -1297,11 +1188,11 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
                     if ((xmlStrEqual(name, prop->name)) &&
                         ((namespace == prop->ns) ||
                          (xmlStrEqual(namespace->href, prop->ns->href)))) {
-                            xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
-                                    "Attribute %s in %s redefined\n",
-                                             name, namespace->href);
-                        ctxt->wellFormed = 0;
-                        if (ctxt->recovery == 0) ctxt->disableSAX = 1;
+                        xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER,
+                                   XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL,
+                                   name, NULL, NULL, 0,
+                                   "Attribute %s in %s redefined\n",
+                                   name, namespace->href);
                         if (name != NULL)
                             xmlFree(name);
                         goto error;
@@ -1316,25 +1207,22 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
 
     /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
     ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
+    if (ret == NULL) {
+        xmlSAX2ErrMemory(ctxt);
+        goto error;
+    }
 
-    if (ret != NULL) {
-        if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
-	    xmlNodePtr tmp;
-
-	    ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
-	    tmp = ret->children;
-	    while (tmp != NULL) {
-		tmp->parent = (xmlNodePtr) ret;
-		if (tmp->next == NULL)
-		    ret->last = tmp;
-		tmp = tmp->next;
-	    }
-	} else if (value != NULL) {
-	    ret->children = xmlNewDocText(ctxt->myDoc, value);
-	    ret->last = ret->children;
-	    if (ret->children != NULL)
-		ret->children->parent = (xmlNodePtr) ret;
-	}
+    if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
+        if (xmlNodeParseContent((xmlNodePtr) ret, value, INT_MAX) < 0)
+            xmlSAX2ErrMemory(ctxt);
+    } else if (value != NULL) {
+        ret->children = xmlNewDocText(ctxt->myDoc, value);
+        if (ret->children == NULL) {
+            xmlSAX2ErrMemory(ctxt);
+        } else {
+            ret->last = ret->children;
+            ret->children->parent = (xmlNodePtr) ret;
+        }
     }
 
 #ifdef LIBXML_VALID_ENABLED
@@ -1348,10 +1236,8 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
         if (!ctxt->replaceEntities) {
 	    xmlChar *val;
 
-	    ctxt->depth++;
-	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
-		                          0,0,0);
-	    ctxt->depth--;
+            /* TODO: normalize if needed */
+	    val = xmlExpandEntitiesInAttValue(ctxt, value, /* normalize */ 0);
 
 	    if (val == NULL)
 		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
@@ -1364,8 +1250,9 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
 		 * It need to be done twice ... it's an extra burden related
 		 * to the ability to keep xmlSAX2References in attributes
 		 */
-		nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
-					    ctxt->node, fullname, val);
+                nvalnorm = xmlValidCtxtNormalizeAttributeValue(
+                                 &ctxt->vctxt, ctxt->myDoc,
+                                 ctxt->node, fullname, val);
 		if (nvalnorm != NULL) {
 		    xmlFree(val);
 		    val = nvalnorm;
@@ -1382,8 +1269,7 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
     } else
 #endif /* LIBXML_VALID_ENABLED */
            if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
-	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
-	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) &&
+               (ctxt->input->entity == NULL) &&
                /* Don't create IDs containing entity references */
                (ret->children != NULL) &&
                (ret->children->type == XML_TEXT_NODE) &&
@@ -1401,14 +1287,20 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
 	     */
 	    if (xmlValidateNCName(content, 1) != 0) {
 	        xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
-		      "xml:id : attribute value %s is not an NCName\n",
-			    (const char *) content, NULL);
+		            "xml:id : attribute value %s is not an NCName\n",
+		            content, NULL);
 	    }
 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
-	} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
-	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
-	else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
-	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
+	} else {
+            int res = xmlIsID(ctxt->myDoc, ctxt->node, ret);
+
+            if (res < 0)
+                xmlCtxtErrMemory(ctxt);
+            else if (res > 0)
+                xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
+            else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
+                xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
+        }
     }
 
 error:
@@ -1460,13 +1352,15 @@ process_external_subset:
 
 		    if (attr->prefix != NULL) {
 			fulln = xmlStrdup(attr->prefix);
-			fulln = xmlStrcat(fulln, BAD_CAST ":");
-			fulln = xmlStrcat(fulln, attr->name);
+                        if (fulln != NULL)
+			    fulln = xmlStrcat(fulln, BAD_CAST ":");
+                        if (fulln != NULL)
+			    fulln = xmlStrcat(fulln, attr->name);
 		    } else {
 			fulln = xmlStrdup(attr->name);
 		    }
                     if (fulln == NULL) {
-                        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
+                        xmlSAX2ErrMemory(ctxt);
                         break;
                     }
 
@@ -1488,8 +1382,8 @@ process_external_subset:
 		    if (att == NULL) {
 		        xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
       "standalone: attribute %s on %s defaulted from external subset\n",
-				    (const char *)fulln,
-				    (const char *)attr->elem);
+				    fulln,
+				    attr->elem);
 		    }
                     xmlFree(fulln);
 		}
@@ -1532,7 +1426,7 @@ process_external_subset:
 
                         fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
 			if (fulln == NULL) {
-			    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
+			    xmlSAX2ErrMemory(ctxt);
 			    return;
 			}
 
@@ -1593,11 +1487,6 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
     int i;
 
     if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
-    parent = ctxt->node;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2StartElement(%s)\n", fullname);
-#endif
 
     /*
      * First check on validity:
@@ -1613,12 +1502,19 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
 	ctxt->validate = 0;
     }
 
-
-    /*
-     * Split the full name into a namespace prefix and the tag name
-     */
-    name = xmlSplitQName(ctxt, fullname, &prefix);
-
+    if (ctxt->html) {
+        prefix = NULL;
+        name = xmlStrdup(fullname);
+    } else {
+        /*
+         * Split the full name into a namespace prefix and the tag name
+         */
+        name = xmlSplitQName(ctxt, fullname, &prefix);
+        if (name == NULL) {
+            xmlSAX2ErrMemory(ctxt);
+            return;
+        }
+    }
 
     /*
      * Note : the namespace resolution is deferred until the end of the
@@ -1627,35 +1523,25 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
      */
     ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
     if (ret == NULL) {
-        if (prefix != NULL)
-	    xmlFree(prefix);
-	xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
+	xmlFree(prefix);
+	xmlSAX2ErrMemory(ctxt);
         return;
     }
-    if (ctxt->myDoc->children == NULL) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
-#endif
-        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
-    } else if (parent == NULL) {
-        parent = ctxt->myDoc->children;
-    }
     ctxt->nodemem = -1;
-    if (ctxt->linenumbers) {
-	if (ctxt->input != NULL) {
-	    if (ctxt->input->line < USHRT_MAX)
-		ret->line = (unsigned short) ctxt->input->line;
-	    else
-	        ret->line = USHRT_MAX;
-	}
-    }
+
+    /* Initialize parent before pushing node */
+    parent = ctxt->node;
+    if (parent == NULL)
+        parent = (xmlNodePtr) ctxt->myDoc;
+
+    /*
+     * Link the child element
+     */
+    xmlSAX2AppendChild(ctxt, ret);
 
     /*
      * We are parsing a new node.
      */
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
-#endif
     if (nodePush(ctxt, ret) < 0) {
         xmlUnlinkNode(ret);
         xmlFreeNode(ret);
@@ -1664,27 +1550,9 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
         return;
     }
 
-    /*
-     * Link the child element
-     */
-    if (parent != NULL) {
-        if (parent->type == XML_ELEMENT_NODE) {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "adding child %s to %s\n", name, parent->name);
-#endif
-	    xmlAddChild(parent, ret);
-	} else {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "adding sibling %s to ", name);
-	    xmlDebugDumpOneNode(stderr, parent, 0);
-#endif
-	    xmlAddSibling(parent, ret);
-	}
-    }
-
     if (!ctxt->html) {
+        int res;
+
         /*
          * Insert all the defaulted attributes from the DTD especially
          * namespaces
@@ -1715,14 +1583,21 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
          * Search the namespace, note that since the attributes have been
          * processed, the local namespaces are available.
          */
-        ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
-        if ((ns == NULL) && (parent != NULL))
-            ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
+        res = xmlSearchNsSafe(ret, prefix, &ns);
+        if (res < 0)
+            xmlSAX2ErrMemory(ctxt);
+        if ((ns == NULL) && (parent != NULL)) {
+            res = xmlSearchNsSafe(parent, prefix, &ns);
+            if (res < 0)
+                xmlSAX2ErrMemory(ctxt);
+        }
         if ((prefix != NULL) && (ns == NULL)) {
-            ns = xmlNewNs(ret, NULL, prefix);
             xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
                          "Namespace prefix %s is not defined\n",
                          prefix, NULL);
+            ns = xmlNewNs(ret, NULL, prefix);
+            if (ns == NULL)
+                xmlSAX2ErrMemory(ctxt);
         }
 
         /*
@@ -1797,40 +1672,22 @@ void
 xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNodePtr cur;
 
     if (ctx == NULL) return;
-    cur = ctxt->node;
-#ifdef DEBUG_SAX
-    if (name == NULL)
-        xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
-    else
-	xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
-#endif
 
-    /* Capture end position and add node */
-    if (cur != NULL && ctxt->record_info) {
-      ctxt->nodeInfo->end_pos = ctxt->input->cur - ctxt->input->base;
-      ctxt->nodeInfo->end_line = ctxt->input->line;
-      ctxt->nodeInfo->node = cur;
-      xmlParserAddNodeInfo(ctxt, ctxt->nodeInfo);
-    }
     ctxt->nodemem = -1;
 
 #ifdef LIBXML_VALID_ENABLED
     if (ctxt->validate && ctxt->wellFormed &&
         ctxt->myDoc && ctxt->myDoc->intSubset)
         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
-					     cur);
+					     ctxt->node);
 #endif /* LIBXML_VALID_ENABLED */
 
 
     /*
      * end of parsing of this node.
      */
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
-#endif
     nodePop(ctxt);
 }
 #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLED || LIBXML_LEGACY_ENABLED */
@@ -1861,7 +1718,7 @@ xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
 	ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
     }
     if (ret == NULL) {
-        xmlErrMemory(ctxt, "xmlSAX2Characters");
+        xmlCtxtErrMemory(ctxt);
 	return(NULL);
     }
     memset(ret, 0, sizeof(xmlNode));
@@ -1882,6 +1739,11 @@ xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
 	} else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
 	    ((cur == '<') && (str[len + 1] != '!')))) {
 	    intern = xmlDictLookup(ctxt->dict, str, len);
+            if (intern == NULL) {
+                xmlSAX2ErrMemory(ctxt);
+                xmlFree(ret);
+                return(NULL);
+            }
 	} else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
 	           (str[len + 1] != '!')) {
 	    int i;
@@ -1890,6 +1752,11 @@ xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
 		if (!IS_BLANK_CH(str[i])) goto skip;
 	    }
 	    intern = xmlDictLookup(ctxt->dict, str, len);
+            if (intern == NULL) {
+                xmlSAX2ErrMemory(ctxt);
+                xmlFree(ret);
+                return(NULL);
+            }
 	}
     }
 skip:
@@ -1899,25 +1766,13 @@ skip:
     if (intern == NULL) {
 	ret->content = xmlStrndup(str, len);
 	if (ret->content == NULL) {
-	    xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
+	    xmlSAX2ErrMemory(ctxt);
 	    xmlFree(ret);
 	    return(NULL);
 	}
     } else
 	ret->content = (xmlChar *) intern;
 
-    if (ctxt->linenumbers) {
-	if (ctxt->input != NULL) {
-	    if (ctxt->input->line < USHRT_MAX)
-		ret->line = (unsigned short) ctxt->input->line;
-	    else {
-	        ret->line = USHRT_MAX;
-		if (ctxt->options & XML_PARSE_BIG_LINES)
-		    ret->psvi = (void *) (ptrdiff_t) ctxt->input->line;
-	    }
-	}
-    }
-
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue(ret);
     return(ret);
@@ -1938,7 +1793,6 @@ static xmlChar *
 xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
                           const xmlChar *end) {
     const xmlChar *in;
-    xmlChar *ret;
 
     in = str;
     while (in < end)
@@ -1946,11 +1800,12 @@ xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
 	    goto decode;
     return(NULL);
 decode:
-    ctxt->depth++;
-    ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
-				     XML_SUBSTITUTE_REF, 0,0,0);
-    ctxt->depth--;
-    return(ret);
+    /*
+     * If the value contains '&', we can be sure it was allocated and is
+     * zero-terminated.
+     */
+    /* TODO: normalize if needed */
+    return(xmlExpandEntitiesInAttValue(ctxt, str, /* normalize */ 0));
 }
 #endif /* LIBXML_VALID_ENABLED */
 
@@ -1967,8 +1822,10 @@ decode:
  * The default handling is to convert the attribute into an
  * DOM subtree and past it in a new xmlAttr element added to
  * the element.
+ *
+ * Returns the new attribute or NULL in case of error.
  */
-static void
+static xmlAttrPtr
 xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
                    const xmlChar * localname,
                    const xmlChar * prefix,
@@ -1982,8 +1839,16 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
     /*
      * Note: if prefix == NULL, the attribute is not in the default namespace
      */
-    if (prefix != NULL)
-	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
+    if (prefix != NULL) {
+	namespace = xmlParserNsLookupSax(ctxt, prefix);
+	if ((namespace == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
+            int res;
+
+	    res = xmlSearchNsSafe(ctxt->node, prefix, &namespace);
+            if (res < 0)
+                xmlSAX2ErrMemory(ctxt);
+	}
+    }
 
     /*
      * allocate the node
@@ -1992,43 +1857,41 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
         ret = ctxt->freeAttrs;
 	ctxt->freeAttrs = ret->next;
 	ctxt->freeAttrsNr--;
-	memset(ret, 0, sizeof(xmlAttr));
-	ret->type = XML_ATTRIBUTE_NODE;
+    } else {
+        ret = xmlMalloc(sizeof(*ret));
+        if (ret == NULL) {
+            xmlSAX2ErrMemory(ctxt);
+            return(NULL);
+        }
+    }
 
-	ret->parent = ctxt->node;
-	ret->doc = ctxt->myDoc;
-	ret->ns = namespace;
+    memset(ret, 0, sizeof(xmlAttr));
+    ret->type = XML_ATTRIBUTE_NODE;
 
-	if (ctxt->dictNames)
-	    ret->name = localname;
-	else
-	    ret->name = xmlStrdup(localname);
+    /*
+     * xmlParseBalancedChunkMemoryRecover had a bug that could result in
+     * a mismatch between ctxt->node->doc and ctxt->myDoc. We use
+     * ctxt->node->doc here, but we should somehow make sure that the
+     * document pointers match.
+     */
 
-        /* link at the end to preserve order, TODO speed up with a last */
-	if (ctxt->node->properties == NULL) {
-	    ctxt->node->properties = ret;
-	} else {
-	    xmlAttrPtr prev = ctxt->node->properties;
+    /* assert(ctxt->node->doc == ctxt->myDoc); */
 
-	    while (prev->next != NULL) prev = prev->next;
-	    prev->next = ret;
-	    ret->prev = prev;
-	}
+    ret->parent = ctxt->node;
+    ret->doc = ctxt->node->doc;
+    ret->ns = namespace;
 
-	if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
-	    xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
+    if (ctxt->dictNames) {
+        ret->name = localname;
     } else {
-	if (ctxt->dictNames)
-	    ret = xmlNewNsPropEatName(ctxt->node, namespace,
-	                              (xmlChar *) localname, NULL);
-	else
-	    ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
-	if (ret == NULL) {
-	    xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
-	    return;
-	}
+        ret->name = xmlStrdup(localname);
+        if (ret->name == NULL)
+            xmlSAX2ErrMemory(ctxt);
     }
 
+    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
+        xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
+
     if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
 	xmlNodePtr tmp;
 
@@ -2045,17 +1908,10 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
 		tmp->doc = ret->doc;
 		tmp->parent = (xmlNodePtr) ret;
 	    }
-	} else {
-	    ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
-						    valueend - value);
-	    tmp = ret->children;
-	    while (tmp != NULL) {
-	        tmp->doc = ret->doc;
-		tmp->parent = (xmlNodePtr) ret;
-		if (tmp->next == NULL)
-		    ret->last = tmp;
-		tmp = tmp->next;
-	    }
+	} else if (valueend > value) {
+            if (xmlNodeParseContent((xmlNodePtr) ret, value,
+                                    valueend - value) < 0)
+                xmlSAX2ErrMemory(ctxt);
 	}
     } else if (value != NULL) {
 	xmlNodePtr tmp;
@@ -2089,6 +1945,8 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
 		     * entry points in the full validation code
 		     */
 		    dup = xmlStrndup(value, valueend - value);
+                    if (dup == NULL)
+                        xmlSAX2ErrMemory(ctxt);
 
 		    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
 				    ctxt->myDoc, ctxt->node, ret, dup);
@@ -2107,7 +1965,9 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
 		    xmlChar *fullname;
 
 		    fullname = xmlBuildQName(localname, prefix, fn, 50);
-		    if (fullname != NULL) {
+                    if (fullname == NULL) {
+                        xmlSAX2ErrMemory(ctxt);
+                    } else {
 			ctxt->vctxt.valid = 1;
 		        nvalnorm = xmlValidCtxtNormalizeAttributeValue(
 			                 &ctxt->vctxt, ctxt->myDoc,
@@ -2133,6 +1993,8 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
 	     * the attribute as passed is already normalized
 	     */
 	    dup = xmlStrndup(value, valueend - value);
+            if (dup == NULL)
+                xmlSAX2ErrMemory(ctxt);
 
 	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
 	                             ctxt->myDoc, ctxt->node, ret, dup);
@@ -2140,8 +2002,7 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
     } else
 #endif /* LIBXML_VALID_ENABLED */
            if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
-	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
-	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) &&
+               (ctxt->input->entity == NULL) &&
                /* Don't create IDs containing entity references */
                (ret->children != NULL) &&
                (ret->children->type == XML_TEXT_NODE) &&
@@ -2159,24 +2020,27 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
 	     *
 	     * Open issue: normalization of the value.
 	     */
-#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
-#ifdef LIBXML_VALID_ENABLED
 	    if (xmlValidateNCName(content, 1) != 0) {
 	        xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
-		      "xml:id : attribute value %s is not an NCName\n",
-			    (const char *) content, NULL);
+                            "xml:id : attribute value %s is not an NCName\n",
+                            content, NULL);
 	    }
-#endif
-#endif
 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
-	} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
-	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
-	} else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
-	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
+	} else {
+            int res = xmlIsID(ctxt->myDoc, ctxt->node, ret);
+
+            if (res < 0)
+                xmlCtxtErrMemory(ctxt);
+            else if (res > 0)
+                xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
+            else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
+                xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
 	}
     }
     if (dup != NULL)
 	xmlFree(dup);
+
+    return(ret);
 }
 
 /**
@@ -2209,14 +2073,12 @@ xmlSAX2StartElementNs(void *ctx,
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlNodePtr ret;
-    xmlNodePtr parent;
     xmlNsPtr last = NULL, ns;
     const xmlChar *uri, *pref;
     xmlChar *lname = NULL;
     int i, j;
 
     if (ctx == NULL) return;
-    parent = ctxt->node;
     /*
      * First check on validity:
      */
@@ -2239,10 +2101,17 @@ xmlSAX2StartElementNs(void *ctx,
 	    const xmlChar *fullname;
 
 	    fullname = xmlDictQLookup(ctxt->dict, prefix, localname);
-	    if (fullname != NULL)
-	        localname = fullname;
+	    if (fullname == NULL) {
+                xmlSAX2ErrMemory(ctxt);
+                return;
+            }
+	    localname = fullname;
 	} else {
 	    lname = xmlBuildQName(localname, prefix, NULL, 0);
+            if (lname == NULL) {
+                xmlSAX2ErrMemory(ctxt);
+                return;
+            }
 	}
     }
     /*
@@ -2264,7 +2133,8 @@ xmlSAX2StartElementNs(void *ctx,
 	    else
 	        ret->name = lname;
 	    if (ret->name == NULL) {
-	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
+	        xmlSAX2ErrMemory(ctxt);
+                xmlFree(ret);
 		return;
 	    }
 	}
@@ -2280,22 +2150,11 @@ xmlSAX2StartElementNs(void *ctx,
 	    ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
 	                               (xmlChar *) lname, NULL);
 	if (ret == NULL) {
-	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
+	    xmlSAX2ErrMemory(ctxt);
 	    return;
 	}
     }
-    if (ctxt->linenumbers) {
-	if (ctxt->input != NULL) {
-	    if (ctxt->input->line < USHRT_MAX)
-		ret->line = (unsigned short) ctxt->input->line;
-	    else
-	        ret->line = USHRT_MAX;
-	}
-    }
 
-    if (parent == NULL) {
-        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
-    }
     /*
      * Build the namespace list
      */
@@ -2313,13 +2172,12 @@ xmlSAX2StartElementNs(void *ctx,
 	    if ((URI != NULL) && (prefix == pref))
 		ret->ns = ns;
 	} else {
-            /*
-             * any out of memory error would already have been raised
-             * but we can't be guaranteed it's the actual error due to the
-             * API, best is to skip in this case
-             */
+            xmlSAX2ErrMemory(ctxt);
 	    continue;
 	}
+
+        xmlParserNsUpdateSax(ctxt, pref, ns);
+
 #ifdef LIBXML_VALID_ENABLED
 	if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
 	    ctxt->myDoc && ctxt->myDoc->intSubset) {
@@ -2330,6 +2188,11 @@ xmlSAX2StartElementNs(void *ctx,
     }
     ctxt->nodemem = -1;
 
+    /*
+     * Link the child element
+     */
+    xmlSAX2AppendChild(ctxt, ret);
+
     /*
      * We are parsing a new node.
      */
@@ -2339,17 +2202,6 @@ xmlSAX2StartElementNs(void *ctx,
         return;
     }
 
-    /*
-     * Link the child element
-     */
-    if (parent != NULL) {
-        if (parent->type == XML_ELEMENT_NODE) {
-	    xmlAddChild(parent, ret);
-	} else {
-	    xmlAddSibling(parent, ret);
-	}
-    }
-
     /*
      * Insert the defaulted attributes from the DTD only if requested:
      */
@@ -2362,15 +2214,19 @@ xmlSAX2StartElementNs(void *ctx,
      * Note that, if prefix is NULL, this searches for the default Ns
      */
     if ((URI != NULL) && (ret->ns == NULL)) {
-        ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
+        ret->ns = xmlParserNsLookupSax(ctxt, prefix);
 	if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
-	    ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
+            int res;
+
+	    res = xmlSearchNsSafe(ret, prefix, &ret->ns);
+            if (res < 0)
+                xmlSAX2ErrMemory(ctxt);
 	}
 	if (ret->ns == NULL) {
 	    ns = xmlNewNs(ret, NULL, prefix);
 	    if (ns == NULL) {
 
-	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
+	        xmlSAX2ErrMemory(ctxt);
 		return;
 	    }
             if (prefix != NULL)
@@ -2388,7 +2244,11 @@ xmlSAX2StartElementNs(void *ctx,
      * process all the other attributes
      */
     if (nb_attributes > 0) {
+        xmlAttrPtr prev = NULL;
+
         for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
+            xmlAttrPtr attr = NULL;
+
 	    /*
 	     * Handle the rare case of an undefined attribute prefix
 	     */
@@ -2398,24 +2258,43 @@ xmlSAX2StartElementNs(void *ctx,
 
 		    fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
 		                              attributes[j]);
-		    if (fullname != NULL) {
-			xmlSAX2AttributeNs(ctxt, fullname, NULL,
-			                   attributes[j+3], attributes[j+4]);
-		        continue;
-		    }
+		    if (fullname == NULL) {
+                        xmlSAX2ErrMemory(ctxt);
+                        return;
+                    }
+                    attr = xmlSAX2AttributeNs(ctxt, fullname, NULL,
+                                              attributes[j+3],
+                                              attributes[j+4]);
+                    goto have_attr;
 		} else {
 		    lname = xmlBuildQName(attributes[j], attributes[j+1],
 		                          NULL, 0);
-		    if (lname != NULL) {
-			xmlSAX2AttributeNs(ctxt, lname, NULL,
-			                   attributes[j+3], attributes[j+4]);
-			xmlFree(lname);
-		        continue;
-		    }
+		    if (lname == NULL) {
+                        xmlSAX2ErrMemory(ctxt);
+                        return;
+                    }
+                    attr = xmlSAX2AttributeNs(ctxt, lname, NULL,
+                                              attributes[j+3],
+                                              attributes[j+4]);
+                    xmlFree(lname);
+                    goto have_attr;
 		}
 	    }
-	    xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
-			       attributes[j+3], attributes[j+4]);
+            attr = xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
+                                      attributes[j+3], attributes[j+4]);
+have_attr:
+            if (attr == NULL)
+                continue;
+
+            /* link at the end to preserve order */
+            if (prev == NULL) {
+                ctxt->node->properties = attr;
+            } else {
+                prev->next = attr;
+                attr->prev = prev;
+            }
+
+            prev = attr;
 	}
     }
 
@@ -2456,24 +2335,15 @@ xmlSAX2EndElementNs(void *ctx,
 		    const xmlChar * URI ATTRIBUTE_UNUSED)
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlParserNodeInfo node_info;
-    xmlNodePtr cur;
 
     if (ctx == NULL) return;
-    cur = ctxt->node;
-    /* Capture end position and add node */
-    if ((ctxt->record_info) && (cur != NULL)) {
-        node_info.end_pos = ctxt->input->cur - ctxt->input->base;
-        node_info.end_line = ctxt->input->line;
-        node_info.node = cur;
-        xmlParserAddNodeInfo(ctxt, &node_info);
-    }
     ctxt->nodemem = -1;
 
 #ifdef LIBXML_VALID_ENABLED
     if (ctxt->validate && ctxt->wellFormed &&
         ctxt->myDoc && ctxt->myDoc->intSubset)
-        ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
+        ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
+                                             ctxt->node);
 #endif /* LIBXML_VALID_ENABLED */
 
     /*
@@ -2496,21 +2366,13 @@ xmlSAX2Reference(void *ctx, const xmlChar *name)
     xmlNodePtr ret;
 
     if (ctx == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2Reference(%s)\n", name);
-#endif
-    if (name[0] == '#')
-	ret = xmlNewCharRef(ctxt->myDoc, name);
-    else
-	ret = xmlNewReference(ctxt->myDoc, name);
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext,
-	    "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
-#endif
-    if (xmlAddChild(ctxt->node, ret) == NULL) {
-        xmlFreeNode(ret);
+    ret = xmlNewReference(ctxt->myDoc, name);
+    if (ret == NULL) {
+        xmlSAX2ErrMemory(ctxt);
+        return;
     }
+
+    xmlSAX2AppendChild(ctxt, ret);
 }
 
 /**
@@ -2529,10 +2391,6 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
     xmlNodePtr lastChild;
 
     if (ctxt == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
-#endif
     /*
      * Handle the data if any. If there is no child
      * add it as content, otherwise if the last child is text,
@@ -2540,17 +2398,9 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
      */
 
     if (ctxt->node == NULL) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"add chars: ctxt->node == NULL !\n");
-#endif
         return;
     }
     lastChild = ctxt->node->last;
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext,
-	    "add chars to %s \n", ctxt->node->name);
-#endif
 
     /*
      * Here we needed an accelerator mechanism in case of very large
@@ -2569,7 +2419,7 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
 	    ctxt->nodelen = len;
 	    ctxt->nodemem = len + 1;
 	} else {
-	    xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
+	    xmlSAX2ErrMemory(ctxt);
 	    return;
 	}
     } else {
@@ -2578,6 +2428,10 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
 	    ((type != XML_TEXT_NODE) ||
              (lastChild->name == xmlStringText));
 	if ((coalesceText) && (ctxt->nodemem != 0)) {
+            int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                            XML_MAX_HUGE_LENGTH :
+                            XML_MAX_TEXT_LENGTH;
+
 	    /*
 	     * The whole point of maintaining nodelen and nodemem,
 	     * xmlTextConcat is too costly, i.e. compute length,
@@ -2593,28 +2447,26 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
 		lastChild->content = xmlStrdup(lastChild->content);
 	    }
 	    if (lastChild->content == NULL) {
-		xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: xmlStrdup returned NULL");
+		xmlSAX2ErrMemory(ctxt);
 		return;
  	    }
-            if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
-                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
+            if ((len > maxLength) || (ctxt->nodelen > maxLength - len)) {
+                xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT,
+                            "Text node too long, try XML_PARSE_HUGE");
+                xmlHaltParser(ctxt);
                 return;
             }
-	    if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
-	        (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
-                xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
-                return;
-	    }
 	    if (ctxt->nodelen + len >= ctxt->nodemem) {
 		xmlChar *newbuf;
-		size_t size;
+		int size;
 
-		size = ctxt->nodemem + len;
-		size *= 2;
+		size = ctxt->nodemem > INT_MAX - len ?
+                       INT_MAX :
+                       ctxt->nodemem + len;
+		size = size > INT_MAX / 2 ? INT_MAX : size * 2;
                 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
 		if (newbuf == NULL) {
-		    xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
+		    xmlSAX2ErrMemory(ctxt);
 		    return;
 		}
 		ctxt->nodemem = size;
@@ -2625,7 +2477,7 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
 	    lastChild->content[ctxt->nodelen] = 0;
 	} else if (coalesceText) {
 	    if (xmlTextConcat(lastChild, ch, len)) {
-		xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
+		xmlSAX2ErrMemory(ctxt);
 	    }
 	    if (ctxt->node->children != NULL) {
 		ctxt->nodelen = xmlStrlen(lastChild->content);
@@ -2635,11 +2487,14 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
 	    /* Mixed content, first time */
             if (type == XML_TEXT_NODE) {
                 lastChild = xmlSAX2TextNode(ctxt, ch, len);
-                lastChild->doc = ctxt->myDoc;
+                if (lastChild != NULL)
+                    lastChild->doc = ctxt->myDoc;
             } else
                 lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
-	    if (lastChild != NULL) {
-		xmlAddChild(ctxt->node, lastChild);
+	    if (lastChild == NULL) {
+                xmlSAX2ErrMemory(ctxt);
+            } else {
+		xmlSAX2AppendChild(ctxt, lastChild);
 		if (ctxt->node->children != NULL) {
 		    ctxt->nodelen = len;
 		    ctxt->nodemem = len + 1;
@@ -2647,6 +2502,19 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
 	    }
 	}
     }
+
+    if ((lastChild != NULL) &&
+        (type == XML_TEXT_NODE) &&
+        (ctxt->linenumbers) &&
+        (ctxt->input != NULL)) {
+        if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
+            lastChild->line = ctxt->input->line;
+        else {
+            lastChild->line = USHRT_MAX;
+            if (ctxt->options & XML_PARSE_BIG_LINES)
+                lastChild->psvi = (void *) (ptrdiff_t) ctxt->input->line;
+        }
+    }
 }
 
 /**
@@ -2675,11 +2543,6 @@ xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
 void
 xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
 {
-    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
-#endif
 }
 
 /**
@@ -2696,55 +2559,16 @@ xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlNodePtr ret;
-    xmlNodePtr parent;
 
     if (ctx == NULL) return;
-    parent = ctxt->node;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
-#endif
 
     ret = xmlNewDocPI(ctxt->myDoc, target, data);
-    if (ret == NULL) return;
-
-    if (ctxt->linenumbers) {
-	if (ctxt->input != NULL) {
-	    if (ctxt->input->line < USHRT_MAX)
-		ret->line = (unsigned short) ctxt->input->line;
-	    else
-	        ret->line = USHRT_MAX;
-	}
-    }
-    if (ctxt->inSubset == 1) {
-	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
-	return;
-    } else if (ctxt->inSubset == 2) {
-	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
-	return;
-    }
-    if (parent == NULL) {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "Setting PI %s as root\n", target);
-#endif
-        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
-	return;
-    }
-    if (parent->type == XML_ELEMENT_NODE) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding PI %s child to %s\n", target, parent->name);
-#endif
-	xmlAddChild(parent, ret);
-    } else {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding PI %s sibling to ", target);
-	xmlDebugDumpOneNode(stderr, parent, 0);
-#endif
-	xmlAddSibling(parent, ret);
+    if (ret == NULL) {
+        xmlSAX2ErrMemory(ctxt);
+        return;
     }
+
+    xmlSAX2AppendChild(ctxt, ret);
 }
 
 /**
@@ -2759,53 +2583,16 @@ xmlSAX2Comment(void *ctx, const xmlChar *value)
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlNodePtr ret;
-    xmlNodePtr parent;
 
     if (ctx == NULL) return;
-    parent = ctxt->node;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
-#endif
+
     ret = xmlNewDocComment(ctxt->myDoc, value);
-    if (ret == NULL) return;
-    if (ctxt->linenumbers) {
-	if (ctxt->input != NULL) {
-	    if (ctxt->input->line < USHRT_MAX)
-		ret->line = (unsigned short) ctxt->input->line;
-	    else
-	        ret->line = USHRT_MAX;
-	}
+    if (ret == NULL) {
+        xmlSAX2ErrMemory(ctxt);
+        return;
     }
 
-    if (ctxt->inSubset == 1) {
-	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
-	return;
-    } else if (ctxt->inSubset == 2) {
-	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
-	return;
-    }
-    if (parent == NULL) {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "Setting xmlSAX2Comment as root\n");
-#endif
-        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
-	return;
-    }
-    if (parent->type == XML_ELEMENT_NODE) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding xmlSAX2Comment child to %s\n", parent->name);
-#endif
-	xmlAddChild(parent, ret);
-    } else {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding xmlSAX2Comment sibling to ");
-	xmlDebugDumpOneNode(stderr, parent, 0);
-#endif
-	xmlAddSibling(parent, ret);
-    }
+    xmlSAX2AppendChild(ctxt, ret);
 }
 
 /**
@@ -2829,6 +2616,8 @@ static int xmlSAX2DefaultVersionValue = 2;
  * xmlSAXDefaultVersion:
  * @version:  the version, 1 or 2
  *
+ * DEPRECATED: Use parser option XML_PARSE_SAX1.
+ *
  * Set the default version of SAX used globally by the library.
  * By default, during initialization the default is set to 2.
  * Note that it is generally a better coding style to use
@@ -2863,20 +2652,23 @@ xmlSAXVersion(xmlSAXHandler *hdlr, int version)
 {
     if (hdlr == NULL) return(-1);
     if (version == 2) {
-	hdlr->startElement = NULL;
-	hdlr->endElement = NULL;
 	hdlr->startElementNs = xmlSAX2StartElementNs;
 	hdlr->endElementNs = xmlSAX2EndElementNs;
 	hdlr->serror = NULL;
 	hdlr->initialized = XML_SAX2_MAGIC;
 #ifdef LIBXML_SAX1_ENABLED
     } else if (version == 1) {
-	hdlr->startElement = xmlSAX2StartElement;
-	hdlr->endElement = xmlSAX2EndElement;
 	hdlr->initialized = 1;
 #endif /* LIBXML_SAX1_ENABLED */
     } else
         return(-1);
+#ifdef LIBXML_SAX1_ENABLED
+    hdlr->startElement = xmlSAX2StartElement;
+    hdlr->endElement = xmlSAX2EndElement;
+#else
+    hdlr->startElement = NULL;
+    hdlr->endElement = NULL;
+#endif /* LIBXML_SAX1_ENABLED */
     hdlr->internalSubset = xmlSAX2InternalSubset;
     hdlr->externalSubset = xmlSAX2ExternalSubset;
     hdlr->isStandalone = xmlSAX2IsStandalone;
@@ -2929,7 +2721,7 @@ xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
 /**
  * xmlDefaultSAXHandlerInit:
  *
- * DEPRECATED: This function will be made private. Call xmlInitParser to
+ * DEPRECATED: This function is a no-op. Call xmlInitParser to
  * initialize the library.
  *
  * Initialize the default SAX2 handler
@@ -2937,9 +2729,6 @@ xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
 void
 xmlDefaultSAXHandlerInit(void)
 {
-#ifdef LIBXML_SAX1_ENABLED
-    xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
-#endif /* LIBXML_SAX1_ENABLED */
 }
 
 #ifdef LIBXML_HTML_ENABLED
@@ -2990,15 +2779,12 @@ xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
 /**
  * htmlDefaultSAXHandlerInit:
  *
- * DEPRECATED: This function will be made private. Call xmlInitParser to
+ * DEPRECATED: This function is a no-op. Call xmlInitParser to
  * initialize the library.
- *
- * Initialize the default SAX handler
  */
 void
 htmlDefaultSAXHandlerInit(void)
 {
-    xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
 }
 
 #endif /* LIBXML_HTML_ENABLED */
diff --git a/buf.c b/buf.c
index 6749d975717b0b341526ee8590ab22f5478023bd..f9f59b26b5127681783d84016f1f9b504288cfc2 100644
--- a/buf.c
+++ b/buf.c
@@ -20,11 +20,11 @@
 #include <ctype.h>
 #include <stdlib.h>
 
-#include <libxml/tree.h>
-#include <libxml/globals.h>
 #include <libxml/tree.h>
 #include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
-#include "buf.h"
+
+#include "private/buf.h"
+#include "private/error.h"
 
 #ifndef SIZE_MAX
 #define SIZE_MAX ((size_t) -1)
@@ -89,10 +89,9 @@ struct _xmlBuf {
  * To be improved...
  */
 static void
-xmlBufMemoryError(xmlBufPtr buf, const char *extra)
+xmlBufMemoryError(xmlBufPtr buf)
 {
-    __xmlSimpleError(XML_FROM_BUFFER, XML_ERR_NO_MEMORY, NULL, NULL, extra);
-    if ((buf) && (buf->error == 0))
+    if (buf->error == 0)
         buf->error = XML_ERR_NO_MEMORY;
 }
 
@@ -104,10 +103,9 @@ xmlBufMemoryError(xmlBufPtr buf, const char *extra)
  * To be improved...
  */
 static void
-xmlBufOverflowError(xmlBufPtr buf, const char *extra)
+xmlBufOverflowError(xmlBufPtr buf)
 {
-    __xmlSimpleError(XML_FROM_BUFFER, XML_BUF_OVERFLOW, NULL, NULL, extra);
-    if ((buf) && (buf->error == 0))
+    if (buf->error == 0)
         buf->error = XML_BUF_OVERFLOW;
 }
 
@@ -123,19 +121,16 @@ xmlBufCreate(void) {
     xmlBufPtr ret;
 
     ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
-    if (ret == NULL) {
-	xmlBufMemoryError(NULL, "creating buffer");
+    if (ret == NULL)
         return(NULL);
-    }
     ret->use = 0;
     ret->error = 0;
     ret->buffer = NULL;
     ret->size = xmlDefaultBufferSize;
     UPDATE_COMPAT(ret);
     ret->alloc = xmlBufferAllocScheme;
-    ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
+    ret->content = (xmlChar *) xmlMallocAtomic(ret->size);
     if (ret->content == NULL) {
-	xmlBufMemoryError(ret, "creating buffer");
 	xmlFree(ret);
         return(NULL);
     }
@@ -158,10 +153,8 @@ xmlBufCreateSize(size_t size) {
     if (size == SIZE_MAX)
         return(NULL);
     ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
-    if (ret == NULL) {
-	xmlBufMemoryError(NULL, "creating buffer");
+    if (ret == NULL)
         return(NULL);
-    }
     ret->use = 0;
     ret->error = 0;
     ret->buffer = NULL;
@@ -169,9 +162,8 @@ xmlBufCreateSize(size_t size) {
     ret->size = (size ? size + 1 : 0);         /* +1 for ending null */
     UPDATE_COMPAT(ret);
     if (ret->size){
-        ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
+        ret->content = (xmlChar *) xmlMallocAtomic(ret->size);
         if (ret->content == NULL) {
-	    xmlBufMemoryError(ret, "creating buffer");
             xmlFree(ret);
             return(NULL);
         }
@@ -198,15 +190,21 @@ xmlBufDetach(xmlBufPtr buf) {
 
     if (buf == NULL)
         return(NULL);
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
-        return(NULL);
     if (buf->buffer != NULL)
         return(NULL);
     if (buf->error)
         return(NULL);
 
-    ret = buf->content;
+    if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
+        (buf->content != buf->contentIO)) {
+        ret = xmlStrndup(buf->content, buf->use);
+        xmlFree(buf->contentIO);
+    } else {
+        ret = buf->content;
+    }
+
     buf->content = NULL;
+    buf->contentIO = NULL;
     buf->size = 0;
     buf->use = 0;
     UPDATE_COMPAT(buf);
@@ -214,40 +212,6 @@ xmlBufDetach(xmlBufPtr buf) {
     return ret;
 }
 
-
-/**
- * xmlBufCreateStatic:
- * @mem: the memory area
- * @size:  the size in byte
- *
- * routine to create an XML buffer from an immutable memory area.
- * The area won't be modified nor copied, and is expected to be
- * present until the end of the buffer lifetime.
- *
- * returns the new structure.
- */
-xmlBufPtr
-xmlBufCreateStatic(void *mem, size_t size) {
-    xmlBufPtr ret;
-
-    if (mem == NULL)
-        return(NULL);
-
-    ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
-    if (ret == NULL) {
-	xmlBufMemoryError(NULL, "creating buffer");
-        return(NULL);
-    }
-    ret->use = size;
-    ret->size = size;
-    UPDATE_COMPAT(ret);
-    ret->alloc = XML_BUFFER_ALLOC_IMMUTABLE;
-    ret->content = (xmlChar *) mem;
-    ret->error = 0;
-    ret->buffer = NULL;
-    return(ret);
-}
-
 /**
  * xmlBufGetAllocationScheme:
  * @buf:  the buffer
@@ -259,10 +223,6 @@ xmlBufCreateStatic(void *mem, size_t size) {
 int
 xmlBufGetAllocationScheme(xmlBufPtr buf) {
     if (buf == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufGetAllocationScheme: buf == NULL\n");
-#endif
         return(-1);
     }
     return(buf->alloc);
@@ -281,19 +241,13 @@ int
 xmlBufSetAllocationScheme(xmlBufPtr buf,
                           xmlBufferAllocationScheme scheme) {
     if ((buf == NULL) || (buf->error != 0)) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufSetAllocationScheme: buf == NULL or in error\n");
-#endif
         return(-1);
     }
-    if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
-        (buf->alloc == XML_BUFFER_ALLOC_IO))
+    if (buf->alloc == XML_BUFFER_ALLOC_IO)
         return(-1);
     if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
         (scheme == XML_BUFFER_ALLOC_EXACT) ||
         (scheme == XML_BUFFER_ALLOC_HYBRID) ||
-        (scheme == XML_BUFFER_ALLOC_IMMUTABLE) ||
 	(scheme == XML_BUFFER_ALLOC_BOUNDED)) {
 	buf->alloc = scheme;
         if (buf->buffer)
@@ -321,18 +275,13 @@ xmlBufSetAllocationScheme(xmlBufPtr buf,
 void
 xmlBufFree(xmlBufPtr buf) {
     if (buf == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufFree: buf == NULL\n");
-#endif
 	return;
     }
 
     if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
         (buf->contentIO != NULL)) {
         xmlFree(buf->contentIO);
-    } else if ((buf->content != NULL) &&
-        (buf->alloc != XML_BUFFER_ALLOC_IMMUTABLE)) {
+    } else if (buf->content != NULL) {
         xmlFree(buf->content);
     }
     xmlFree(buf);
@@ -350,9 +299,7 @@ xmlBufEmpty(xmlBufPtr buf) {
     if (buf->content == NULL) return;
     CHECK_COMPAT(buf)
     buf->use = 0;
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) {
-        buf->content = BAD_CAST "";
-    } else if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
+    if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
                (buf->contentIO != NULL)) {
         size_t start_buf = buf->content - buf->contentIO;
 
@@ -385,8 +332,7 @@ xmlBufShrink(xmlBufPtr buf, size_t len) {
     if (len > buf->use) return(0);
 
     buf->use -= len;
-    if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
-        ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL))) {
+    if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
 	/*
 	 * we just move the content pointer, but also make sure
 	 * the perceived buffer size has shrunk accordingly
@@ -434,11 +380,10 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
     if ((buf == NULL) || (buf->error != 0)) return(0);
     CHECK_COMPAT(buf)
 
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
     if (len < buf->size - buf->use)
         return(buf->size - buf->use - 1);
     if (len >= SIZE_MAX - buf->use) {
-        xmlBufMemoryError(buf, "growing buffer past SIZE_MAX");
+        xmlBufMemoryError(buf);
         return(0);
     }
 
@@ -455,7 +400,7 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
 	 */
         if ((buf->use + len + 1 >= XML_MAX_TEXT_LENGTH) ||
 	    (buf->size >= XML_MAX_TEXT_LENGTH)) {
-	    xmlBufMemoryError(buf, "buffer error: text too long\n");
+	    xmlBufMemoryError(buf);
 	    return(0);
 	}
 	if (size >= XML_MAX_TEXT_LENGTH)
@@ -466,7 +411,7 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
 
 	newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);
 	if (newbuf == NULL) {
-	    xmlBufMemoryError(buf, "growing buffer");
+	    xmlBufMemoryError(buf);
 	    return(0);
 	}
 	buf->contentIO = newbuf;
@@ -474,7 +419,7 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
     } else {
 	newbuf = (xmlChar *) xmlRealloc(buf->content, size);
 	if (newbuf == NULL) {
-	    xmlBufMemoryError(buf, "growing buffer");
+	    xmlBufMemoryError(buf);
 	    return(0);
 	}
 	buf->content = newbuf;
@@ -504,7 +449,7 @@ xmlBufGrow(xmlBufPtr buf, int len) {
     ret = xmlBufGrowInternal(buf, len);
     if (buf->error != 0)
         return(-1);
-    return((int) ret);
+    return(ret > INT_MAX ? INT_MAX : ret);
 }
 
 /**
@@ -520,23 +465,15 @@ xmlBufDump(FILE *file, xmlBufPtr buf) {
     size_t ret;
 
     if ((buf == NULL) || (buf->error != 0)) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufDump: buf == NULL or in error\n");
-#endif
 	return(0);
     }
     if (buf->content == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufDump: buf->content == NULL\n");
-#endif
 	return(0);
     }
     CHECK_COMPAT(buf)
     if (file == NULL)
 	file = stdout;
-    ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
+    ret = fwrite(buf->content, 1, buf->use, file);
     return(ret);
 }
 
@@ -699,13 +636,12 @@ xmlBufResize(xmlBufPtr buf, size_t size)
         return(0);
     CHECK_COMPAT(buf)
 
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
     if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
         /*
 	 * Used to provide parsing limits
 	 */
         if (size >= XML_MAX_TEXT_LENGTH) {
-	    xmlBufMemoryError(buf, "buffer error: text too long\n");
+	    xmlBufMemoryError(buf);
 	    return(0);
 	}
     }
@@ -726,7 +662,7 @@ xmlBufResize(xmlBufPtr buf, size_t size)
             }
 	    while (size > newSize) {
 	        if (newSize > SIZE_MAX / 2) {
-	            xmlBufMemoryError(buf, "growing buffer");
+	            xmlBufMemoryError(buf);
 	            return 0;
 	        }
 	        newSize *= 2;
@@ -742,7 +678,7 @@ xmlBufResize(xmlBufPtr buf, size_t size)
                 newSize = buf->size;
                 while (size > newSize) {
                     if (newSize > SIZE_MAX / 2) {
-                        xmlBufMemoryError(buf, "growing buffer");
+                        xmlBufMemoryError(buf);
                         return 0;
                     }
                     newSize *= 2;
@@ -767,7 +703,7 @@ xmlBufResize(xmlBufPtr buf, size_t size)
 	} else {
 	    rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);
 	    if (rebuf == NULL) {
-		xmlBufMemoryError(buf, "growing buffer");
+		xmlBufMemoryError(buf);
 		return 0;
 	    }
 	    buf->contentIO = rebuf;
@@ -777,7 +713,8 @@ xmlBufResize(xmlBufPtr buf, size_t size)
 	if (buf->content == NULL) {
 	    rebuf = (xmlChar *) xmlMallocAtomic(newSize);
 	    buf->use = 0;
-	    rebuf[buf->use] = 0;
+            if (rebuf != NULL)
+	        rebuf[buf->use] = 0;
 	} else if (buf->size - buf->use < 100) {
 	    rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);
         } else {
@@ -794,7 +731,7 @@ xmlBufResize(xmlBufPtr buf, size_t size)
 	    }
 	}
 	if (rebuf == NULL) {
-	    xmlBufMemoryError(buf, "growing buffer");
+	    xmlBufMemoryError(buf);
 	    return 0;
 	}
 	buf->content = rebuf;
@@ -814,8 +751,7 @@ xmlBufResize(xmlBufPtr buf, size_t size)
  * Add a string range to an XML buffer. if len == -1, the length of
  * str is recomputed.
  *
- * Returns 0 successful, a positive error code number otherwise
- *         and -1 in case of internal or API error.
+ * Returns 0 if successful, -1 in case of error.
  */
 int
 xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
@@ -825,12 +761,7 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
 	return -1;
     CHECK_COMPAT(buf)
 
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
     if (len < -1) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufAdd: len < 0\n");
-#endif
 	return -1;
     }
     if (len == 0) return 0;
@@ -844,7 +775,7 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
     /* Note that both buf->size and buf->use can be zero here. */
     if ((size_t) len >= buf->size - buf->use) {
         if ((size_t) len >= SIZE_MAX - buf->use) {
-            xmlBufMemoryError(buf, "growing buffer past SIZE_MAX");
+            xmlBufMemoryError(buf);
             return(-1);
         }
         needSize = buf->use + len + 1;
@@ -853,17 +784,15 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
 	     * Used to provide parsing limits
 	     */
 	    if (needSize >= XML_MAX_TEXT_LENGTH) {
-		xmlBufMemoryError(buf, "buffer error: text too long\n");
+		xmlBufMemoryError(buf);
 		return(-1);
 	    }
 	}
-        if (!xmlBufResize(buf, needSize)){
-	    xmlBufMemoryError(buf, "growing buffer");
-            return XML_ERR_NO_MEMORY;
-        }
+        if (!xmlBufResize(buf, needSize))
+            return(-1);
     }
 
-    memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
+    memmove(&buf->content[buf->use], str, len);
     buf->use += len;
     buf->content[buf->use] = 0;
     UPDATE_COMPAT(buf)
@@ -885,83 +814,10 @@ xmlBufCat(xmlBufPtr buf, const xmlChar *str) {
     if ((buf == NULL) || (buf->error))
         return(-1);
     CHECK_COMPAT(buf)
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
     if (str == NULL) return -1;
     return xmlBufAdd(buf, str, -1);
 }
 
-/**
- * xmlBufCCat:
- * @buf:  the buffer to dump
- * @str:  the C char string
- *
- * Append a zero terminated C string to an XML buffer.
- *
- * Returns 0 successful, a positive error code number otherwise
- *         and -1 in case of internal or API error.
- */
-int
-xmlBufCCat(xmlBufPtr buf, const char *str) {
-    return xmlBufCat(buf, (const xmlChar *) str);
-}
-
-/**
- * xmlBufWriteQuotedString:
- * @buf:  the XML buffer output
- * @string:  the string to add
- *
- * routine which manage and grows an output buffer. This one writes
- * a quoted or double quoted #xmlChar string, checking first if it holds
- * quote or double-quotes internally
- *
- * Returns 0 if successful, a positive error code number otherwise
- *         and -1 in case of internal or API error.
- */
-int
-xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string) {
-    const xmlChar *cur, *base;
-    if ((buf == NULL) || (buf->error))
-        return(-1);
-    CHECK_COMPAT(buf)
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
-        return(-1);
-    if (xmlStrchr(string, '\"')) {
-        if (xmlStrchr(string, '\'')) {
-#ifdef DEBUG_BUFFER
-	    xmlGenericError(xmlGenericErrorContext,
- "xmlBufWriteQuotedString: string contains quote and double-quotes !\n");
-#endif
-	    xmlBufCCat(buf, "\"");
-            base = cur = string;
-            while(*cur != 0){
-                if(*cur == '"'){
-                    if (base != cur)
-                        xmlBufAdd(buf, base, cur - base);
-                    xmlBufAdd(buf, BAD_CAST "&quot;", 6);
-                    cur++;
-                    base = cur;
-                }
-                else {
-                    cur++;
-                }
-            }
-            if (base != cur)
-                xmlBufAdd(buf, base, cur - base);
-	    xmlBufCCat(buf, "\"");
-	}
-        else{
-	    xmlBufCCat(buf, "\'");
-            xmlBufCat(buf, string);
-	    xmlBufCCat(buf, "\'");
-        }
-    } else {
-        xmlBufCCat(buf, "\"");
-        xmlBufCat(buf, string);
-        xmlBufCCat(buf, "\"");
-    }
-    return(0);
-}
-
 /**
  * xmlBufFromBuffer:
  * @buffer: incoming old buffer to convert to a new one
@@ -982,7 +838,6 @@ xmlBufFromBuffer(xmlBufferPtr buffer) {
 
     ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
     if (ret == NULL) {
-	xmlBufMemoryError(NULL, "creating buffer");
         return(NULL);
     }
     ret->use = buffer->use;
@@ -1016,12 +871,19 @@ xmlBufBackToBuffer(xmlBufPtr buf) {
     if (buf == NULL)
         return(NULL);
     CHECK_COMPAT(buf)
-    if ((buf->error) || (buf->buffer == NULL)) {
+    ret = buf->buffer;
+
+    if ((buf->error) || (ret == NULL)) {
         xmlBufFree(buf);
+        if (ret != NULL) {
+            ret->content = NULL;
+            ret->contentIO = NULL;
+            ret->use = 0;
+            ret->size = 0;
+        }
         return(NULL);
     }
 
-    ret = buf->buffer;
     /*
      * What to do in case of error in the buffer ???
      */
@@ -1031,7 +893,7 @@ xmlBufBackToBuffer(xmlBufPtr buf) {
          * maximum allowed memory for an xmlBuffer on this architecture.
          * Keep the buffer but provide a truncated size value.
          */
-        xmlBufOverflowError(buf, "Used size too big for xmlBuffer");
+        xmlBufOverflowError(buf);
         ret->use = INT_MAX;
         ret->size = INT_MAX;
     } else if (buf->size > INT_MAX) {
@@ -1041,12 +903,12 @@ xmlBufBackToBuffer(xmlBufPtr buf) {
          * limit.
          * Keep the buffer but provide a truncated size value.
          */
-        xmlBufOverflowError(buf, "Allocated size too big for xmlBuffer");
-        ret->use = (int) buf->use;
+        xmlBufOverflowError(buf);
+        ret->use = buf->use;
         ret->size = INT_MAX;
     } else {
-        ret->use = (int) buf->use;
-        ret->size = (int) buf->size;
+        ret->use = buf->use;
+        ret->size = buf->size;
     }
     ret->alloc = buf->alloc;
     ret->content = buf->content;
@@ -1055,32 +917,6 @@ xmlBufBackToBuffer(xmlBufPtr buf) {
     return(ret);
 }
 
-/**
- * xmlBufMergeBuffer:
- * @buf: an xmlBufPtr
- * @buffer: the buffer to consume into @buf
- *
- * The content of @buffer is appended to @buf and @buffer is freed
- *
- * Returns -1 in case of error, 0 otherwise, in any case @buffer is freed
- */
-int
-xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer) {
-    int ret = 0;
-
-    if ((buf == NULL) || (buf->error)) {
-	xmlBufferFree(buffer);
-        return(-1);
-    }
-    CHECK_COMPAT(buf)
-    if ((buffer != NULL) && (buffer->content != NULL) &&
-             (buffer->use > 0)) {
-        ret = xmlBufAdd(buf, buffer->content, buffer->use);
-    }
-    xmlBufferFree(buffer);
-    return(ret);
-}
-
 /**
  * xmlBufResetInput:
  * @buf: an xmlBufPtr
@@ -1092,48 +928,14 @@ xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer) {
  */
 int
 xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input) {
-    if ((input == NULL) || (buf == NULL) || (buf->error))
-        return(-1);
-    CHECK_COMPAT(buf)
-    input->base = input->cur = buf->content;
-    input->end = &buf->content[buf->use];
-    return(0);
-}
-
-/**
- * xmlBufGetInputBase:
- * @buf: an xmlBufPtr
- * @input: an xmlParserInputPtr
- *
- * Get the base of the @input relative to the beginning of the buffer
- *
- * Returns the size_t corresponding to the displacement
- */
-size_t
-xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input) {
-    size_t base;
-
-    if ((input == NULL) || (buf == NULL) || (buf->error))
-        return(-1);
-    CHECK_COMPAT(buf)
-    base = input->base - buf->content;
-    /*
-     * We could do some pointer arithmetic checks but that's probably
-     * sufficient.
-     */
-    if (base > buf->size) {
-        xmlBufOverflowError(buf, "Input reference outside of the buffer");
-        base = 0;
-    }
-    return(base);
+    return(xmlBufUpdateInput(buf, input, 0));
 }
 
 /**
- * xmlBufSetInputBaseCur:
+ * xmlBufUpdateInput:
  * @buf: an xmlBufPtr
  * @input: an xmlParserInputPtr
- * @base: the base value relative to the beginning of the buffer
- * @cur: the cur value relative to the beginning of the buffer
+ * @pos: the cur value relative to the beginning of the buffer
  *
  * Update the input to use the base and cur relative to the buffer
  * after a possible reallocation of its content
@@ -1141,17 +943,12 @@ xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input) {
  * Returns -1 in case of error, 0 otherwise
  */
 int
-xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input,
-                      size_t base, size_t cur) {
-    if (input == NULL)
-        return(-1);
-    if ((buf == NULL) || (buf->error)) {
-        input->base = input->cur = input->end = BAD_CAST "";
+xmlBufUpdateInput(xmlBufPtr buf, xmlParserInputPtr input, size_t pos) {
+    if ((buf == NULL) || (input == NULL))
         return(-1);
-    }
     CHECK_COMPAT(buf)
-    input->base = &buf->content[base];
-    input->cur = input->base + cur;
+    input->base = buf->content;
+    input->cur = input->base + pos;
     input->end = &buf->content[buf->use];
     return(0);
 }
diff --git a/buf.h b/buf.h
deleted file mode 100644
index b7bcf61fe2e39264ddaebe813a81cd91d7de4040..0000000000000000000000000000000000000000
--- a/buf.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Summary: Internal Interfaces for memory buffers in libxml2
- * Description: this module describes most of the new xmlBuf buffer
- *              entry points, those are private routines, with a
- *              few exceptions exported in tree.h. This was added
- *              in 2.9.0.
- *
- * Copy: See Copyright for the status of this software.
- *
- * Author: Daniel Veillard
- */
-
-#ifndef __XML_BUF_H__
-#define __XML_BUF_H__
-
-#include <libxml/tree.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-xmlBufPtr xmlBufCreate(void);
-xmlBufPtr xmlBufCreateSize(size_t size);
-xmlBufPtr xmlBufCreateStatic(void *mem, size_t size);
-
-int xmlBufSetAllocationScheme(xmlBufPtr buf,
-                              xmlBufferAllocationScheme scheme);
-int xmlBufGetAllocationScheme(xmlBufPtr buf);
-
-void xmlBufFree(xmlBufPtr buf);
-void xmlBufEmpty(xmlBufPtr buf);
-
-/* size_t xmlBufShrink(xmlBufPtr buf, size_t len); */
-int xmlBufGrow(xmlBufPtr buf, int len);
-int xmlBufResize(xmlBufPtr buf, size_t len);
-
-int xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len);
-int xmlBufCat(xmlBufPtr buf, const xmlChar *str);
-int xmlBufCCat(xmlBufPtr buf, const char *str);
-int xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string);
-
-size_t xmlBufAvail(const xmlBufPtr buf);
-size_t xmlBufLength(const xmlBufPtr buf);
-/* size_t xmlBufUse(const xmlBufPtr buf); */
-int xmlBufIsEmpty(const xmlBufPtr buf);
-int xmlBufAddLen(xmlBufPtr buf, size_t len);
-
-/* const xmlChar * xmlBufContent(const xmlBuf *buf); */
-/* const xmlChar * xmlBufEnd(xmlBufPtr buf); */
-
-xmlChar * xmlBufDetach(xmlBufPtr buf);
-
-size_t xmlBufDump(FILE *file, xmlBufPtr buf);
-
-xmlBufPtr xmlBufFromBuffer(xmlBufferPtr buffer);
-xmlBufferPtr xmlBufBackToBuffer(xmlBufPtr buf);
-int xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer);
-
-int xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input);
-size_t xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input);
-int xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input,
-                          size_t base, size_t cur);
-#ifdef __cplusplus
-}
-#endif
-#endif /* __XML_BUF_H__ */
-
diff --git a/c14n.c b/c14n.c
index d55729ccc59d5e4c26c81a700a575641d9e4e555..964ac998973b213c865436c9da49375a3d2a6e8f 100644
--- a/c14n.c
+++ b/c14n.c
@@ -12,7 +12,6 @@
 #define IN_LIBXML
 #include "libxml.h"
 #ifdef LIBXML_C14N_ENABLED
-#ifdef LIBXML_OUTPUT_ENABLED
 
 #include <stdlib.h>
 #include <string.h>
@@ -21,11 +20,11 @@
 #include <libxml/parser.h>
 #include <libxml/uri.h>
 #include <libxml/xmlerror.h>
-#include <libxml/globals.h>
 #include <libxml/xpathInternals.h>
 #include <libxml/c14n.h>
 
-#include "buf.h"
+#include "private/error.h"
+#include "private/io.h"
 
 /************************************************************************
  *									*
@@ -73,7 +72,7 @@ typedef struct _xmlC14NCtx {
 
 static xmlC14NVisibleNsStackPtr	xmlC14NVisibleNsStackCreate	(void);
 static void     xmlC14NVisibleNsStackDestroy	(xmlC14NVisibleNsStackPtr cur);
-static void     xmlC14NVisibleNsStackAdd	    (xmlC14NVisibleNsStackPtr cur,
+static int      xmlC14NVisibleNsStackAdd	    (xmlC14NVisibleNsStackPtr cur,
                                                  xmlNsPtr ns,
                                                  xmlNodePtr node);
 static void			xmlC14NVisibleNsStackSave	(xmlC14NVisibleNsStackPtr cur,
@@ -135,87 +134,85 @@ static xmlChar *xmlC11NNormalizeString(const xmlChar * input,
  * Handle a redefinition of memory error
  */
 static void
-xmlC14NErrMemory(const char *extra)
+xmlC14NErrMemory(xmlC14NCtxPtr ctxt)
 {
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
-		    XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra,
-		    NULL, NULL, 0, 0,
-		    "Memory allocation failed : %s\n", extra);
+    if (ctxt != NULL)
+        ctxt->error = XML_ERR_NO_MEMORY;
+
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_C14N, NULL);
 }
 
-/**
- * xmlC14NErrParam:
- * @extra:  extra information
- *
- * Handle a redefinition of param error
- */
 static void
-xmlC14NErrParam(const char *extra)
+xmlC14NErrFull(xmlC14NCtxPtr ctxt, xmlNodePtr node, int code, const char *str1,
+               const char *msg, ...)
 {
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
-		    XML_ERR_INTERNAL_ERROR, XML_ERR_ERROR, NULL, 0, extra,
-		    NULL, NULL, 0, 0,
-		    "Invalid parameter : %s\n", extra);
+    va_list ap;
+    int res;
+
+    if (ctxt != NULL)
+        ctxt->error = code;
+
+    va_start(ap, msg);
+    res = xmlVRaiseError(NULL, NULL, NULL, ctxt, node,
+                         XML_FROM_C14N, code, XML_ERR_ERROR, NULL, 0,
+                         str1, NULL, NULL, 0, 0,
+                         msg, ap);
+    va_end(ap);
+    if (res < 0)
+        xmlC14NErrMemory(ctxt);
 }
 
 /**
- * xmlC14NErrInternal:
+ * xmlC14NErrParam:
  * @extra:  extra information
  *
- * Handle a redefinition of internal error
+ * Handle a param error
  */
 static void
-xmlC14NErrInternal(const char *extra)
+xmlC14NErrParam(xmlC14NCtxPtr ctxt)
 {
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
-		    XML_ERR_INTERNAL_ERROR, XML_ERR_ERROR, NULL, 0, extra,
-		    NULL, NULL, 0, 0,
-		    "Internal error : %s\n", extra);
+    xmlC14NErrFull(ctxt, NULL, XML_ERR_ARGUMENT, NULL,
+		   "Invalid argument\n", NULL);
 }
 
 /**
  * xmlC14NErrInvalidNode:
  * @extra:  extra information
  *
- * Handle a redefinition of invalid node error
+ * Handle an invalid node error
  */
 static void
-xmlC14NErrInvalidNode(const char *node_type, const char *extra)
+xmlC14NErrInvalidNode(xmlC14NCtxPtr ctxt, const char *node_type,
+                      const char *extra)
 {
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
-		    XML_C14N_INVALID_NODE, XML_ERR_ERROR, NULL, 0, extra,
-		    NULL, NULL, 0, 0,
-		    "Node %s is invalid here : %s\n", node_type, extra);
+    xmlC14NErrFull(ctxt, NULL, XML_C14N_INVALID_NODE, extra,
+		   "Node %s is invalid here : %s\n", node_type, extra);
 }
 
 /**
  * xmlC14NErrUnknownNode:
  * @extra:  extra information
  *
- * Handle a redefinition of unknown node error
+ * Handle an unknown node error
  */
 static void
-xmlC14NErrUnknownNode(int node_type, const char *extra)
+xmlC14NErrUnknownNode(xmlC14NCtxPtr ctxt, int node_type, const char *extra)
 {
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
-		    XML_C14N_UNKNOW_NODE, XML_ERR_ERROR, NULL, 0, extra,
-		    NULL, NULL, 0, 0,
-		    "Unknown node type %d found : %s\n", node_type, extra);
+    xmlC14NErrFull(ctxt, NULL, XML_C14N_UNKNOW_NODE, extra,
+		   "Unknown node type %d found : %s\n", node_type, extra);
 }
 
 /**
  * xmlC14NErrRelativeNamespace:
  * @extra:  extra information
  *
- * Handle a redefinition of relative namespace error
+ * Handle a relative namespace error
  */
 static void
-xmlC14NErrRelativeNamespace(const char *ns_uri)
+xmlC14NErrRelativeNamespace(xmlC14NCtxPtr ctxt, const char *ns_uri)
 {
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
-		    XML_C14N_RELATIVE_NAMESPACE, XML_ERR_ERROR, NULL, 0, NULL,
-		    NULL, NULL, 0, 0,
-		    "Relative namespace UR is invalid here : %s\n", ns_uri);
+    xmlC14NErrFull(ctxt, NULL, XML_C14N_RELATIVE_NAMESPACE, ns_uri,
+		   "Relative namespace UR is invalid here : %s\n", ns_uri);
 }
 
 
@@ -228,18 +225,13 @@ xmlC14NErrRelativeNamespace(const char *ns_uri)
  * @msg:  the message
  * @extra:  extra information
  *
- * Handle a redefinition of attribute error
+ * Handle an error
  */
 static void
 xmlC14NErr(xmlC14NCtxPtr ctxt, xmlNodePtr node, int error,
            const char * msg)
 {
-    if (ctxt != NULL)
-        ctxt->error = error;
-    __xmlRaiseError(NULL, NULL, NULL,
-		    ctxt, node, XML_FROM_C14N, error,
-		    XML_ERR_ERROR, NULL, 0,
-		    NULL, NULL, NULL, 0, 0, "%s", msg);
+    xmlC14NErrFull(ctxt, node, error, NULL, "%s", msg);
 }
 
 /************************************************************************
@@ -282,18 +274,16 @@ xmlC14NVisibleNsStackCreate(void) {
     xmlC14NVisibleNsStackPtr ret;
 
     ret = (xmlC14NVisibleNsStackPtr) xmlMalloc(sizeof(xmlC14NVisibleNsStack));
-    if (ret == NULL) {
-        xmlC14NErrMemory("creating namespaces stack");
+    if (ret == NULL)
 	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlC14NVisibleNsStack));
+    memset(ret, 0, sizeof(xmlC14NVisibleNsStack));
     return(ret);
 }
 
 static void
 xmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur) {
     if(cur == NULL) {
-        xmlC14NErrParam("destroying namespaces stack");
+        xmlC14NErrParam(NULL);
         return;
     }
     if(cur->nsTab != NULL) {
@@ -309,22 +299,18 @@ xmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur) {
 
 }
 
-static void
+static int
 xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr node) {
     if((cur == NULL) ||
        ((cur->nsTab == NULL) && (cur->nodeTab != NULL)) ||
-       ((cur->nsTab != NULL) && (cur->nodeTab == NULL))) {
-        xmlC14NErrParam("adding namespace to stack");
-	return;
-    }
+       ((cur->nsTab != NULL) && (cur->nodeTab == NULL)))
+	return (1);
 
     if ((cur->nsTab == NULL) && (cur->nodeTab == NULL)) {
         cur->nsTab = (xmlNsPtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr));
         cur->nodeTab = (xmlNodePtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNodePtr));
-	if ((cur->nsTab == NULL) || (cur->nodeTab == NULL)) {
-	    xmlC14NErrMemory("adding node to stack");
-	    return;
-	}
+	if ((cur->nsTab == NULL) || (cur->nodeTab == NULL))
+	    return (-1);
 	memset(cur->nsTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr));
 	memset(cur->nodeTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNodePtr));
         cur->nsMax = XML_NAMESPACES_DEFAULT;
@@ -334,17 +320,13 @@ xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr n
 
 	tmpSize = 2 * cur->nsMax;
 	tmp = xmlRealloc(cur->nsTab, tmpSize * sizeof(xmlNsPtr));
-	if (tmp == NULL) {
-	    xmlC14NErrMemory("adding node to stack");
-	    return;
-	}
+	if (tmp == NULL)
+	    return (-1);
 	cur->nsTab = (xmlNsPtr*)tmp;
 
 	tmp = xmlRealloc(cur->nodeTab, tmpSize * sizeof(xmlNodePtr));
-	if (tmp == NULL) {
-	    xmlC14NErrMemory("adding node to stack");
-	    return;
-	}
+	if (tmp == NULL)
+	    return (-1);
 	cur->nodeTab = (xmlNodePtr*)tmp;
 
 	cur->nsMax = tmpSize;
@@ -353,12 +335,14 @@ xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr n
     cur->nodeTab[cur->nsCurEnd] = node;
 
     ++cur->nsCurEnd;
+
+    return (0);
 }
 
 static void
 xmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) {
     if((cur == NULL) || (state == NULL)) {
-        xmlC14NErrParam("saving namespaces stack");
+        xmlC14NErrParam(NULL);
 	return;
     }
 
@@ -370,7 +354,7 @@ xmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr
 static void
 xmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) {
     if((cur == NULL) || (state == NULL)) {
-        xmlC14NErrParam("restoring namespaces stack");
+        xmlC14NErrParam(NULL);
 	return;
     }
     cur->nsCurEnd = state->nsCurEnd;
@@ -381,7 +365,7 @@ xmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStack
 static void
 xmlC14NVisibleNsStackShift(xmlC14NVisibleNsStackPtr cur) {
     if(cur == NULL) {
-        xmlC14NErrParam("shifting namespaces stack");
+        xmlC14NErrParam(NULL);
 	return;
     }
     cur->nsPrevStart = cur->nsPrevEnd;
@@ -417,7 +401,7 @@ xmlC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns)
     int has_empty_ns;
 
     if(cur == NULL) {
-        xmlC14NErrParam("searching namespaces stack (c14n)");
+        xmlC14NErrParam(NULL);
         return (0);
     }
 
@@ -450,7 +434,7 @@ xmlExcC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlC14NC
     int has_empty_ns;
 
     if(cur == NULL) {
-        xmlC14NErrParam("searching namespaces stack (exc c14n)");
+        xmlC14NErrParam(ctx);
         return (0);
     }
 
@@ -514,8 +498,8 @@ xmlC14NIsXmlNs(xmlNsPtr ns)
 static int
 xmlC14NNsCompare(const void *data1, const void *data2)
 {
-    const xmlNsPtr ns1 = (const xmlNsPtr) data1;
-    const xmlNsPtr ns2 = (const xmlNsPtr) data2;
+    const xmlNs *ns1 = data1;
+    const xmlNs *ns2 = data2;
     if (ns1 == ns2)
         return (0);
     if (ns1 == NULL)
@@ -537,11 +521,11 @@ xmlC14NNsCompare(const void *data1, const void *data2)
  * Returns 1 on success or 0 on fail.
  */
 static int
-xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx)
+xmlC14NPrintNamespaces(const xmlNs *ns, xmlC14NCtxPtr ctx)
 {
 
     if ((ns == NULL) || (ctx == NULL)) {
-        xmlC14NErrParam("writing namespaces");
+        xmlC14NErrParam(ctx);
         return 0;
     }
 
@@ -553,7 +537,7 @@ xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx)
         xmlOutputBufferWriteString(ctx->buf, " xmlns=");
     }
     if(ns->href != NULL) {
-	xmlBufWriteQuotedString(ctx->buf->buffer, ns->href);
+	xmlOutputBufferWriteQuotedString(ctx->buf, ns->href);
     } else {
     	xmlOutputBufferWriteString(ctx->buf, "\"\"");
     }
@@ -562,7 +546,7 @@ xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx)
 
 static int
 xmlC14NPrintNamespacesWalker(const void *ns, void *ctx) {
-    return xmlC14NPrintNamespaces((const xmlNsPtr) ns, (xmlC14NCtxPtr) ctx);
+    return xmlC14NPrintNamespaces(ns, ctx);
 }
 
 /**
@@ -614,7 +598,7 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
     int has_empty_ns = 0;
 
     if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
-        xmlC14NErrParam("processing namespaces axis (c14n)");
+        xmlC14NErrParam(ctx);
         return (-1);
     }
 
@@ -623,7 +607,7 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
      */
     list = xmlListCreate(NULL, xmlC14NNsCompare);
     if (list == NULL) {
-        xmlC14NErrInternal("creating namespaces list (c14n)");
+        xmlC14NErrMemory(ctx);
         return (-1);
     }
 
@@ -635,7 +619,10 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
 	    if((tmp == ns) && !xmlC14NIsXmlNs(ns) && xmlC14NIsVisible(ctx, ns, cur)) {
 		already_rendered = xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns);
 		if(visible) {
-	    xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur);
+	            if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur) < 0) {
+                        xmlC14NErrMemory(ctx);
+                        goto error;
+                    }
 		}
 		if(!already_rendered) {
 		    xmlListInsert(list, ns);
@@ -674,6 +661,7 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
     /*
      * Cleanup
      */
+error:
     xmlListDelete(list);
     return (0);
 }
@@ -721,12 +709,12 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
     int has_empty_ns_in_inclusive_list = 0;
 
     if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
-        xmlC14NErrParam("processing namespaces axis (exc c14n)");
+        xmlC14NErrParam(ctx);
         return (-1);
     }
 
     if(!xmlC14NIsExclusive(ctx)) {
-        xmlC14NErrParam("processing namespaces axis (exc c14n)");
+        xmlC14NErrParam(ctx);
         return (-1);
 
     }
@@ -736,7 +724,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
      */
     list = xmlListCreate(NULL, xmlC14NNsCompare);
     if (list == NULL) {
-        xmlC14NErrInternal("creating namespaces list (exc c14n)");
+        xmlC14NErrMemory(ctx);
         return (-1);
     }
 
@@ -764,7 +752,10 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
 	    if((ns != NULL) && !xmlC14NIsXmlNs(ns) && xmlC14NIsVisible(ctx, ns, cur)) {
 		already_rendered = xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns);
 		if(visible) {
-		    xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur);
+		    if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur) < 0) {
+                        xmlC14NErrMemory(ctx);
+                        goto error;
+                    }
 		}
 		if(!already_rendered) {
 		    xmlListInsert(list, ns);
@@ -790,7 +781,10 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
 	    }
 	}
 	if(visible) {
-	    xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur);
+	    if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur) < 0) {
+                xmlC14NErrMemory(ctx);
+                goto error;
+            }
 	}
 	if(xmlStrlen(ns->prefix) == 0) {
 	    has_empty_ns = 1;
@@ -807,7 +801,10 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
          */
 	if((attr->ns != NULL) && !xmlC14NIsXmlNs(attr->ns) && xmlC14NIsVisible(ctx, attr, cur)) {
 	    already_rendered = xmlExcC14NVisibleNsStackFind(ctx->ns_rendered, attr->ns, ctx);
-	    xmlC14NVisibleNsStackAdd(ctx->ns_rendered, attr->ns, cur);
+	    if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, attr->ns, cur) < 0) {
+                xmlC14NErrMemory(ctx);
+                goto error;
+            }
 	    if(!already_rendered && visible) {
 		xmlListInsert(list, attr->ns);
 	    }
@@ -851,6 +848,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
     /*
      * Cleanup
      */
+error:
     xmlListDelete(list);
     return (0);
 }
@@ -887,8 +885,8 @@ xmlC14NIsXmlAttr(xmlAttrPtr attr)
 static int
 xmlC14NAttrsCompare(const void *data1, const void *data2)
 {
-    const xmlAttrPtr attr1 = (const xmlAttrPtr) data1;
-    const xmlAttrPtr attr2 = (const xmlAttrPtr) data2;
+    const xmlAttr *attr1 = data1;
+    const xmlAttr *attr2 = data2;
     int ret = 0;
 
     /*
@@ -941,13 +939,13 @@ xmlC14NAttrsCompare(const void *data1, const void *data2)
 static int
 xmlC14NPrintAttrs(const void *data, void *user)
 {
-    const xmlAttrPtr attr = (const xmlAttrPtr) data;
+    const xmlAttr *attr = data;
     xmlC14NCtxPtr ctx = (xmlC14NCtxPtr) user;
     xmlChar *value;
     xmlChar *buffer;
 
     if ((attr == NULL) || (ctx == NULL)) {
-        xmlC14NErrParam("writing attributes");
+        xmlC14NErrParam(ctx);
         return (0);
     }
 
@@ -969,7 +967,7 @@ xmlC14NPrintAttrs(const void *data, void *user)
             xmlOutputBufferWriteString(ctx->buf, (const char *) buffer);
             xmlFree(buffer);
         } else {
-            xmlC14NErrInternal("normalizing attributes axis");
+            xmlC14NErrMemory(ctx);
             return (0);
         }
     }
@@ -1018,20 +1016,22 @@ xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr)
     int tmp_str_len;
 
     if ((ctx == NULL) || (xml_base_attr == NULL) || (xml_base_attr->parent == NULL)) {
-        xmlC14NErrParam("processing xml:base attribute");
+        xmlC14NErrParam(ctx);
         return (NULL);
     }
 
     /* start from current value */
     res = xmlNodeListGetString(ctx->doc, xml_base_attr->children, 1);
     if(res == NULL) {
-        xmlC14NErrInternal("processing xml:base attribute - can't get attr value");
+        xmlC14NErrMemory(ctx);
         return (NULL);
     }
 
     /* go up the stack until we find a node that we rendered already */
     cur = xml_base_attr->parent->parent;
     while((cur != NULL) && (!xmlC14NIsVisible(ctx, cur, cur->parent))) {
+        int code;
+
         attr = xmlHasNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
         if(attr != NULL) {
             /* get attr value */
@@ -1039,7 +1039,7 @@ xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr)
             if(tmp_str == NULL) {
                 xmlFree(res);
 
-                xmlC14NErrInternal("processing xml:base attribute - can't get attr value");
+                xmlC14NErrMemory(ctx);
                 return (NULL);
             }
 
@@ -1052,7 +1052,7 @@ xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr)
                     xmlFree(tmp_str);
                     xmlFree(res);
 
-                    xmlC14NErrInternal("processing xml:base attribute - can't modify uri");
+                    xmlC14NErrMemory(ctx);
                     return (NULL);
                 }
 
@@ -1060,12 +1060,17 @@ xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr)
             }
 
             /* build uri */
-            tmp_str2 = xmlBuildURI(res, tmp_str);
-            if(tmp_str2 == NULL) {
+            code = xmlBuildURISafe(res, tmp_str, &tmp_str2);
+            if (code != 0) {
                 xmlFree(tmp_str);
                 xmlFree(res);
 
-                xmlC14NErrInternal("processing xml:base attribute - can't construct uri");
+                if (code < 0)
+                    xmlC14NErrMemory(ctx);
+                else
+                    xmlC14NErr(ctx, cur, XML_ERR_INVALID_URI,
+                               "processing xml:base attribute - "
+                               "can't construct uri");
                 return (NULL);
             }
 
@@ -1090,7 +1095,7 @@ xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr)
     if(attr == NULL) {
         xmlFree(res);
 
-        xmlC14NErrInternal("processing xml:base attribute - can't construct attribute");
+        xmlC14NErrMemory(ctx);
         return (NULL);
     }
 
@@ -1145,7 +1150,7 @@ xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int parent_visible)
     xmlAttrPtr xml_space_attr = NULL;
 
     if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
-        xmlC14NErrParam("processing attributes axis");
+        xmlC14NErrParam(ctx);
         return (-1);
     }
 
@@ -1154,7 +1159,7 @@ xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int parent_visible)
      */
     list = xmlListCreate(NULL, xmlC14NAttrsCompare);
     if (list == NULL) {
-        xmlC14NErrInternal("creating attributes list");
+        xmlC14NErrMemory(ctx);
         return (-1);
     }
 
@@ -1366,7 +1371,7 @@ xmlC14NCheckForRelativeNamespaces(xmlC14NCtxPtr ctx, xmlNodePtr cur)
     xmlNsPtr ns;
 
     if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
-        xmlC14NErrParam("checking for relative namespaces");
+        xmlC14NErrParam(ctx);
         return (-1);
     }
 
@@ -1374,14 +1379,19 @@ xmlC14NCheckForRelativeNamespaces(xmlC14NCtxPtr ctx, xmlNodePtr cur)
     while (ns != NULL) {
         if (xmlStrlen(ns->href) > 0) {
             xmlURIPtr uri;
+            int code;
 
-            uri = xmlParseURI((const char *) ns->href);
+            code = xmlParseURISafe((const char *) ns->href, &uri);
             if (uri == NULL) {
-                xmlC14NErrInternal("parsing namespace uri");
+                if (code < 0)
+                    xmlC14NErrMemory(ctx);
+                else
+                    xmlC14NErr(ctx, cur, XML_ERR_INVALID_URI,
+                               "parsing namespace uri");
                 return (-1);
             }
             if (xmlStrlen((const xmlChar *) uri->scheme) == 0) {
-                xmlC14NErrRelativeNamespace(uri->scheme);
+                xmlC14NErrRelativeNamespace(ctx, uri->scheme);
                 xmlFreeURI(uri);
                 return (-1);
             }
@@ -1423,7 +1433,7 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
     int parent_is_doc = 0;
 
     if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
-        xmlC14NErrParam("processing element node");
+        xmlC14NErrParam(ctx);
         return (-1);
     }
 
@@ -1432,11 +1442,8 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
      * implementations of XML canonicalization MUST report an operation
      * failure on documents containing relative namespace URIs.
      */
-    if (xmlC14NCheckForRelativeNamespaces(ctx, cur) < 0) {
-        xmlC14NErrInternal("checking for relative namespaces");
+    if (xmlC14NCheckForRelativeNamespaces(ctx, cur) < 0)
         return (-1);
-    }
-
 
     /*
      * Save ns_rendered stack position
@@ -1466,30 +1473,24 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
     } else {
         ret = xmlExcC14NProcessNamespacesAxis(ctx, cur, visible);
     }
-    if (ret < 0) {
-        xmlC14NErrInternal("processing namespaces axis");
+    if (ret < 0)
         return (-1);
-    }
     /* todo: shouldn't this go to "visible only"? */
     if(visible) {
 	xmlC14NVisibleNsStackShift(ctx->ns_rendered);
     }
 
     ret = xmlC14NProcessAttrsAxis(ctx, cur, visible);
-    if (ret < 0) {
-	xmlC14NErrInternal("processing attributes axis");
+    if (ret < 0)
 	return (-1);
-    }
 
     if (visible) {
         xmlOutputBufferWriteString(ctx->buf, ">");
     }
     if (cur->children != NULL) {
         ret = xmlC14NProcessNodeList(ctx, cur->children);
-        if (ret < 0) {
-            xmlC14NErrInternal("processing childrens list");
+        if (ret < 0)
             return (-1);
-        }
     }
     if (visible) {
         xmlOutputBufferWriteString(ctx->buf, "</");
@@ -1530,7 +1531,7 @@ xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
     int visible;
 
     if ((ctx == NULL) || (cur == NULL)) {
-        xmlC14NErrParam("processing node");
+        xmlC14NErrParam(ctx);
         return (-1);
     }
 
@@ -1559,7 +1560,7 @@ xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
                                                (const char *) buffer);
                     xmlFree(buffer);
                 } else {
-                    xmlC14NErrInternal("normalizing text node");
+                    xmlC14NErrMemory(ctx);
                     return (-1);
                 }
             }
@@ -1598,7 +1599,7 @@ xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
                                                    (const char *) buffer);
                         xmlFree(buffer);
                     } else {
-                        xmlC14NErrInternal("normalizing pi node");
+                        xmlC14NErrMemory(ctx);
                         return (-1);
                     }
                 }
@@ -1643,7 +1644,7 @@ xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
                                                    (const char *) buffer);
                         xmlFree(buffer);
                     } else {
-                        xmlC14NErrInternal("normalizing comment node");
+                        xmlC14NErrMemory(ctx);
                         return (-1);
                     }
                 }
@@ -1668,16 +1669,16 @@ xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
             break;
 
         case XML_ATTRIBUTE_NODE:
-            xmlC14NErrInvalidNode("XML_ATTRIBUTE_NODE", "processing node");
+            xmlC14NErrInvalidNode(ctx, "XML_ATTRIBUTE_NODE", "processing node");
             return (-1);
         case XML_NAMESPACE_DECL:
-            xmlC14NErrInvalidNode("XML_NAMESPACE_DECL", "processing node");
+            xmlC14NErrInvalidNode(ctx, "XML_NAMESPACE_DECL", "processing node");
             return (-1);
         case XML_ENTITY_REF_NODE:
-            xmlC14NErrInvalidNode("XML_ENTITY_REF_NODE", "processing node");
+            xmlC14NErrInvalidNode(ctx, "XML_ENTITY_REF_NODE", "processing node");
             return (-1);
         case XML_ENTITY_NODE:
-            xmlC14NErrInvalidNode("XML_ENTITY_NODE", "processing node");
+            xmlC14NErrInvalidNode(ctx, "XML_ENTITY_NODE", "processing node");
             return (-1);
 
         case XML_DOCUMENT_TYPE_NODE:
@@ -1695,7 +1696,7 @@ xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
              */
             break;
         default:
-            xmlC14NErrUnknownNode(cur->type, "processing node");
+            xmlC14NErrUnknownNode(ctx, cur->type, "processing node");
             return (-1);
     }
 
@@ -1717,7 +1718,7 @@ xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur)
     int ret;
 
     if (ctx == NULL) {
-        xmlC14NErrParam("processing node list");
+        xmlC14NErrParam(ctx);
         return (-1);
     }
 
@@ -1739,7 +1740,7 @@ static void
 xmlC14NFreeCtx(xmlC14NCtxPtr ctx)
 {
     if (ctx == NULL) {
-        xmlC14NErrParam("freeing context");
+        xmlC14NErrParam(ctx);
         return;
     }
 
@@ -1779,7 +1780,7 @@ xmlC14NNewCtx(xmlDocPtr doc,
     xmlC14NCtxPtr ctx = NULL;
 
     if ((doc == NULL) || (buf == NULL)) {
-        xmlC14NErrParam("creating new context");
+        xmlC14NErrParam(ctx);
         return (NULL);
     }
 
@@ -1797,7 +1798,7 @@ xmlC14NNewCtx(xmlDocPtr doc,
      */
     ctx = (xmlC14NCtxPtr) xmlMalloc(sizeof(xmlC14NCtx));
     if (ctx == NULL) {
-	xmlC14NErrMemory("creating context");
+	xmlC14NErrMemory(ctx);
         return (NULL);
     }
     memset(ctx, 0, sizeof(xmlC14NCtx));
@@ -1815,8 +1816,7 @@ xmlC14NNewCtx(xmlDocPtr doc,
     ctx->ns_rendered = xmlC14NVisibleNsStackCreate();
 
     if(ctx->ns_rendered == NULL) {
-        xmlC14NErr(ctx, (xmlNodePtr) doc, XML_C14N_CREATE_STACK,
-		   "xmlC14NNewCtx: xmlC14NVisibleNsStackCreate failed\n");
+        xmlC14NErrMemory(ctx);
 	xmlC14NFreeCtx(ctx);
         return (NULL);
     }
@@ -1829,6 +1829,7 @@ xmlC14NNewCtx(xmlDocPtr doc,
     if(xmlC14NIsExclusive(ctx)) {
         ctx->inclusive_ns_prefixes = inclusive_ns_prefixes;
     }
+
     return (ctx);
 }
 
@@ -1865,7 +1866,7 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback,
     int ret;
 
     if ((buf == NULL) || (doc == NULL)) {
-        xmlC14NErrParam("executing c14n");
+        xmlC14NErrParam(NULL);
         return (-1);
     }
 
@@ -1878,7 +1879,7 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback,
          c14n_mode = (xmlC14NMode)mode;
          break;
     default:
-        xmlC14NErrParam("invalid mode for executing c14n");
+        xmlC14NErrParam(NULL);
         return (-1);
     }
 
@@ -1913,7 +1914,6 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback,
     if (doc->children != NULL) {
         ret = xmlC14NProcessNodeList(ctx, doc->children);
         if (ret < 0) {
-            xmlC14NErrInternal("processing docs children list");
             xmlC14NFreeCtx(ctx);
             return (-1);
         }
@@ -1924,7 +1924,7 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback,
      */
     ret = xmlOutputBufferFlush(buf);
     if (ret < 0) {
-        xmlC14NErrInternal("flushing output buffer");
+        xmlC14NErr(ctx, NULL, buf->error, "flushing output buffer");
         xmlC14NFreeCtx(ctx);
         return (-1);
     }
@@ -2001,7 +2001,7 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes,
     xmlOutputBufferPtr buf;
 
     if (doc_txt_ptr == NULL) {
-        xmlC14NErrParam("dumping doc to memory");
+        xmlC14NErrParam(NULL);
         return (-1);
     }
 
@@ -2012,7 +2012,7 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes,
      */
     buf = xmlAllocOutputBuffer(NULL);
     if (buf == NULL) {
-        xmlC14NErrMemory("creating output buffer");
+        xmlC14NErrMemory(NULL);
         return (-1);
     }
 
@@ -2022,7 +2022,6 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes,
     ret = xmlC14NDocSaveTo(doc, nodes, mode, inclusive_ns_prefixes,
                            with_comments, buf);
     if (ret < 0) {
-        xmlC14NErrInternal("saving doc to output buffer");
         (void) xmlOutputBufferClose(buf);
         return (-1);
     }
@@ -2034,7 +2033,7 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes,
     (void) xmlOutputBufferClose(buf);
 
     if ((*doc_txt_ptr == NULL) && (ret >= 0)) {
-        xmlC14NErrMemory("copying canonicalized document");
+        xmlC14NErrMemory(NULL);
         return (-1);
     }
     return (ret);
@@ -2072,7 +2071,7 @@ xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes,
     int ret;
 
     if (filename == NULL) {
-        xmlC14NErrParam("saving doc");
+        xmlC14NErrParam(NULL);
         return (-1);
     }
 #ifdef LIBXML_ZLIB_ENABLED
@@ -2085,7 +2084,7 @@ xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes,
      */
     buf = xmlOutputBufferCreateFilename(filename, NULL, compression);
     if (buf == NULL) {
-        xmlC14NErrInternal("creating temporary filename");
+        xmlC14NErr(NULL, NULL, XML_IO_UNKNOWN, "creating temporary filename");
         return (-1);
     }
 
@@ -2095,7 +2094,6 @@ xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes,
     ret = xmlC14NDocSaveTo(doc, nodes, mode, inclusive_ns_prefixes,
                            with_comments, buf);
     if (ret < 0) {
-        xmlC14NErrInternal("canonize document to buffer");
         (void) xmlOutputBufferClose(buf);
         return (-1);
     }
@@ -2107,21 +2105,6 @@ xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes,
     return (ret);
 }
 
-
-
-/*
- * Macro used to grow the current buffer.
- */
-#define growBufferReentrant() {						\
-    buffer_size *= 2;							\
-    buffer = (xmlChar *)						\
-		xmlRealloc(buffer, buffer_size * sizeof(xmlChar));	\
-    if (buffer == NULL) {						\
-	xmlC14NErrMemory("growing buffer");				\
-	return(NULL);							\
-    }									\
-}
-
 /**
  * xmlC11NNormalizeString:
  * @input:		the input string
@@ -2150,18 +2133,23 @@ xmlC11NNormalizeString(const xmlChar * input,
      * allocate an translation buffer.
      */
     buffer_size = 1000;
-    buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
-    if (buffer == NULL) {
-	xmlC14NErrMemory("allocating buffer");
+    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
+    if (buffer == NULL)
         return (NULL);
-    }
     out = buffer;
 
     while (*cur != '\0') {
         if ((out - buffer) > (buffer_size - 10)) {
+            xmlChar *tmp;
             int indx = out - buffer;
 
-            growBufferReentrant();
+            buffer_size *= 2;
+            tmp = xmlRealloc(buffer, buffer_size);
+            if (tmp == NULL) {
+                xmlFree(buffer);
+                return(NULL);
+            }
+            buffer = tmp;
             out = &buffer[indx];
         }
 
@@ -2223,6 +2211,5 @@ xmlC11NNormalizeString(const xmlChar * input,
     *out = 0;
     return (buffer);
 }
-#endif /* LIBXML_OUTPUT_ENABLED */
 
 #endif /* LIBXML_C14N_ENABLED */
diff --git a/catalog.c b/catalog.c
index b7837e3da755208a449284c4ce9c25a4ee707de0..27af95f47ab6cff24cc298ef7cf5c64f62df5367 100644
--- a/catalog.c
+++ b/catalog.c
@@ -16,16 +16,16 @@
 #include "libxml.h"
 
 #ifdef LIBXML_CATALOG_ENABLED
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#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>
+#elif defined (_WIN32)
+#include <io.h>
 #endif
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
@@ -37,9 +37,9 @@
 #include <libxml/catalog.h>
 #include <libxml/xmlerror.h>
 #include <libxml/threads.h>
-#include <libxml/globals.h>
 
-#include "buf.h"
+#include "private/buf.h"
+#include "private/error.h"
 
 #define MAX_DELEGATE	50
 #define MAX_CATAL_DEPTH	50
@@ -50,21 +50,6 @@
 # define PATH_SEPARATOR ':'
 #endif
 
-/**
- * TODO:
- *
- * macro to flag unimplemented blocks
- * XML_CATALOG_PREFER user env to select between system/public preferred
- * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
- *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
- *> values "system" and "public".  I have made the default be "system" to
- *> match yours.
- */
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
-
 #define XML_URN_PUBID "urn:publicid:"
 #define XML_CATAL_BREAK ((xmlChar *) -1)
 #ifndef XML_XML_DEFAULT_CATALOG
@@ -74,15 +59,6 @@
 #define XML_SGML_DEFAULT_CATALOG "file://" SYSCONFDIR "/sgml/catalog"
 #endif
 
-#if defined(_WIN32) && defined(_MSC_VER)
-#undef XML_XML_DEFAULT_CATALOG
-static char XML_XML_DEFAULT_CATALOG[256] = "file://" SYSCONFDIR "/xml/catalog";
-#if !defined(_WINDOWS_)
-void* __stdcall GetModuleHandleA(const char*);
-unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long);
-#endif
-#endif
-
 static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);
 static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
 
@@ -213,12 +189,9 @@ static int xmlCatalogInitialized = 0;
  * Handle an out of memory condition
  */
 static void
-xmlCatalogErrMemory(const char *extra)
+xmlCatalogErrMemory(void)
 {
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG,
-                    XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0,
-		    extra, NULL, NULL, 0, 0,
-		    "Memory allocation failed : %s\n", extra);
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_CATALOG, NULL);
 }
 
 /**
@@ -235,11 +208,15 @@ xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error,
                const char *msg, const xmlChar *str1, const xmlChar *str2,
 	       const xmlChar *str3)
 {
-    __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG,
-                    error, XML_ERR_ERROR, NULL, 0,
-		    (const char *) str1, (const char *) str2,
-		    (const char *) str3, 0, 0,
-		    msg, str1, str2, str3);
+    int res;
+
+    res = __xmlRaiseError(NULL, NULL, NULL, catal, node,
+                          XML_FROM_CATALOG, error, XML_ERR_ERROR, NULL, 0,
+                          (const char *) str1, (const char *) str2,
+                          (const char *) str3, 0, 0,
+                          msg, str1, str2, str3);
+    if (res < 0)
+        xmlCatalogErrMemory();
 }
 
 
@@ -271,7 +248,7 @@ xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name,
 
     ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry));
     if (ret == NULL) {
-        xmlCatalogErrMemory("allocating catalog entry");
+        xmlCatalogErrMemory();
 	return(NULL);
     }
     ret->next = NULL;
@@ -329,13 +306,13 @@ xmlFreeCatalogEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
 
     if (xmlDebugCatalogs) {
 	if (ret->name != NULL)
-	    xmlGenericError(xmlGenericErrorContext,
+	    fprintf(stderr,
 		    "Free catalog entry %s\n", ret->name);
 	else if (ret->value != NULL)
-	    xmlGenericError(xmlGenericErrorContext,
+	    fprintf(stderr,
 		    "Free catalog entry %s\n", ret->value);
 	else
-	    xmlGenericError(xmlGenericErrorContext,
+	    fprintf(stderr,
 		    "Free catalog entry\n");
     }
 
@@ -409,7 +386,7 @@ xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) {
 
     ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog));
     if (ret == NULL) {
-        xmlCatalogErrMemory("allocating catalog");
+        xmlCatalogErrMemory();
 	return(NULL);
     }
     memset(ret, 0, sizeof(xmlCatalog));
@@ -793,7 +770,7 @@ xmlConvertSGMLCatalog(xmlCatalogPtr catal) {
 	return(-1);
 
     if (xmlDebugCatalogs) {
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"Converting SGML catalog to XML\n");
     }
     xmlHashScan(catal->sgml, xmlCatalogConvertEntry, &catal);
@@ -885,17 +862,12 @@ xmlDocPtr
 xmlParseCatalogFile(const char *filename) {
     xmlDocPtr ret;
     xmlParserCtxtPtr ctxt;
-    char *directory = NULL;
     xmlParserInputPtr inputStream;
     xmlParserInputBufferPtr buf;
 
     ctxt = xmlNewParserCtxt();
     if (ctxt == NULL) {
-#ifdef LIBXML_SAX1_ENABLED
-	if (xmlDefaultSAXHandler.error != NULL) {
-	    xmlDefaultSAXHandler.error(NULL, "out of memory\n");
-	}
-#endif
+        xmlCatalogErrMemory();
 	return(NULL);
     }
 
@@ -917,10 +889,7 @@ xmlParseCatalogFile(const char *filename) {
     xmlBufResetInput(buf->buffer, inputStream);
 
     inputPush(ctxt, inputStream);
-    if (ctxt->directory == NULL)
-        directory = xmlParserGetDirectory(filename);
-    if ((ctxt->directory == NULL) && (directory != NULL))
-        ctxt->directory = directory;
+
     ctxt->valid = 0;
     ctxt->validate = 0;
     ctxt->loadsubset = 0;
@@ -991,7 +960,7 @@ xmlLoadFileContent(const char *filename)
 #endif
     content = (xmlChar*)xmlMallocAtomic(size + 10);
     if (content == NULL) {
-        xmlCatalogErrMemory("allocating catalog data");
+        xmlCatalogErrMemory();
 #ifdef HAVE_STAT
 	close(fd);
 #else
@@ -1176,10 +1145,10 @@ xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
     if (URL != NULL) {
 	if (xmlDebugCatalogs > 1) {
 	    if (nameValue != NULL)
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Found %s: '%s' '%s'\n", name, nameValue, URL);
 	    else
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Found %s: '%s'\n", name, URL);
 	}
 	ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup);
@@ -1348,13 +1317,13 @@ xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) {
     doc = xmlParseCatalogFile((const char *) filename);
     if (doc == NULL) {
 	if (xmlDebugCatalogs)
-	    xmlGenericError(xmlGenericErrorContext,
+	    fprintf(stderr,
 		    "Failed to parse catalog %s\n", filename);
 	return(NULL);
     }
 
     if (xmlDebugCatalogs)
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"%d Parsing catalog %s\n", xmlGetThreadId(), filename);
 
     cur = xmlDocGetRootElement(doc);
@@ -1427,7 +1396,7 @@ xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
 	    xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
 	if (doc != NULL) {
 	    if (xmlDebugCatalogs)
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 		    "Found %s in file hash\n", catal->URL);
 
 	    if (catal->type == XML_CATA_CATALOG)
@@ -1439,7 +1408,7 @@ xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
 	    return(0);
 	}
 	if (xmlDebugCatalogs)
-	    xmlGenericError(xmlGenericErrorContext,
+	    fprintf(stderr,
 		"%s not found in file hash\n", catal->URL);
     }
 
@@ -1466,7 +1435,7 @@ xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
 	xmlCatalogXMLFiles = xmlHashCreate(10);
     if (xmlCatalogXMLFiles != NULL) {
 	if (xmlDebugCatalogs)
-	    xmlGenericError(xmlGenericErrorContext,
+	    fprintf(stderr,
 		"%s added to file hash\n", catal->URL);
 	xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc);
     }
@@ -1512,7 +1481,7 @@ xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
     typ = xmlGetXMLCatalogEntryType(type);
     if (typ == XML_CATA_NONE) {
 	if (xmlDebugCatalogs)
-	    xmlGenericError(xmlGenericErrorContext,
+	    fprintf(stderr,
 		    "Failed to add unknown element %s to catalog\n", type);
 	return(-1);
     }
@@ -1526,7 +1495,7 @@ xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
 	    if ((orig != NULL) && (cur->type == typ) &&
 		(xmlStrEqual(orig, cur->name))) {
 		if (xmlDebugCatalogs)
-		    xmlGenericError(xmlGenericErrorContext,
+		    fprintf(stderr,
 			    "Updating element %s to catalog\n", type);
 		if (cur->value != NULL)
 		    xmlFree(cur->value);
@@ -1542,7 +1511,7 @@ xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
 	}
     }
     if (xmlDebugCatalogs)
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"Adding element %s to catalog\n", type);
     if (cur == NULL)
 	catal->children = xmlNewCatalogEntry(typ, orig, replace,
@@ -1594,10 +1563,10 @@ xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) {
 	    (xmlStrEqual(value, cur->value))) {
 	    if (xmlDebugCatalogs) {
 		if (cur->name != NULL)
-		    xmlGenericError(xmlGenericErrorContext,
+		    fprintf(stderr,
 			    "Removing element %s from catalog\n", cur->name);
 		else
-		    xmlGenericError(xmlGenericErrorContext,
+		    fprintf(stderr,
 			    "Removing element %s from catalog\n", cur->value);
 	    }
 	    cur->type = XML_CATA_REMOVED;
@@ -1653,7 +1622,7 @@ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
 		case XML_CATA_SYSTEM:
 		    if (xmlStrEqual(sysID, cur->name)) {
 			if (xmlDebugCatalogs)
-			    xmlGenericError(xmlGenericErrorContext,
+			    fprintf(stderr,
 				    "Found system match %s, using %s\n",
 				            cur->name, cur->URL);
 			catal->depth--;
@@ -1682,7 +1651,7 @@ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
 	}
 	if (rewrite != NULL) {
 	    if (xmlDebugCatalogs)
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Using rewriting rule %s\n", rewrite->name);
 	    ret = xmlStrdup(rewrite->URL);
 	    if (ret != NULL)
@@ -1717,7 +1686,7 @@ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
 		    }
 		    if (cur->children != NULL) {
 			if (xmlDebugCatalogs)
-			    xmlGenericError(xmlGenericErrorContext,
+			    fprintf(stderr,
 				    "Trying system delegate %s\n", cur->URL);
 			ret = xmlCatalogListXMLResolve(
 				cur->children, NULL, sysID);
@@ -1747,7 +1716,7 @@ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
 		case XML_CATA_PUBLIC:
 		    if (xmlStrEqual(pubID, cur->name)) {
 			if (xmlDebugCatalogs)
-			    xmlGenericError(xmlGenericErrorContext,
+			    fprintf(stderr,
 				    "Found public match %s\n", cur->name);
 			catal->depth--;
 			return(xmlStrdup(cur->URL));
@@ -1796,7 +1765,7 @@ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
 		    }
 		    if (cur->children != NULL) {
 			if (xmlDebugCatalogs)
-			    xmlGenericError(xmlGenericErrorContext,
+			    fprintf(stderr,
 				    "Trying public delegate %s\n", cur->URL);
 			ret = xmlCatalogListXMLResolve(
 				cur->children, pubID, NULL);
@@ -1886,7 +1855,7 @@ xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
 	    case XML_CATA_URI:
 		if (xmlStrEqual(URI, cur->name)) {
 		    if (xmlDebugCatalogs)
-			xmlGenericError(xmlGenericErrorContext,
+			fprintf(stderr,
 				"Found URI match %s\n", cur->name);
 		    return(xmlStrdup(cur->URL));
 		}
@@ -1913,7 +1882,7 @@ xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
     }
     if (rewrite != NULL) {
 	if (xmlDebugCatalogs)
-	    xmlGenericError(xmlGenericErrorContext,
+	    fprintf(stderr,
 		    "Using rewriting rule %s\n", rewrite->name);
 	ret = xmlStrdup(rewrite->URL);
 	if (ret != NULL)
@@ -1948,7 +1917,7 @@ xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
 		}
 		if (cur->children != NULL) {
 		    if (xmlDebugCatalogs)
-			xmlGenericError(xmlGenericErrorContext,
+			fprintf(stderr,
 				"Trying URI delegate %s\n", cur->URL);
 		    ret = xmlCatalogListXMLResolveURI(
 			    cur->children, URI);
@@ -2017,10 +1986,10 @@ xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
 	urnID = xmlCatalogUnWrapURN(pubID);
 	if (xmlDebugCatalogs) {
 	    if (urnID == NULL)
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Public URN ID %s expanded to NULL\n", pubID);
 	    else
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Public URN ID expanded to %s\n", urnID);
 	}
 	ret = xmlCatalogListXMLResolve(catal, urnID, sysID);
@@ -2034,10 +2003,10 @@ xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
 	urnID = xmlCatalogUnWrapURN(sysID);
 	if (xmlDebugCatalogs) {
 	    if (urnID == NULL)
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"System URN ID %s expanded to NULL\n", sysID);
 	    else
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"System URN ID expanded to %s\n", urnID);
 	}
 	if (pubID == NULL)
@@ -2101,10 +2070,10 @@ xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
 	urnID = xmlCatalogUnWrapURN(URI);
 	if (xmlDebugCatalogs) {
 	    if (urnID == NULL)
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"URN ID %s expanded to NULL\n", URI);
 	    else
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"URN ID expanded to %s\n", urnID);
 	}
 	ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
@@ -2177,7 +2146,6 @@ xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
     int len = 0;
     int size = 50;
     xmlChar stop;
-    int count = 0;
 
     *id = NULL;
 
@@ -2190,9 +2158,9 @@ xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
     } else {
 	stop = ' ';
     }
-    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+    buf = (xmlChar *) xmlMallocAtomic(size);
     if (buf == NULL) {
-        xmlCatalogErrMemory("allocating public ID");
+        xmlCatalogErrMemory();
 	return(NULL);
     }
     while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) {
@@ -2202,16 +2170,15 @@ xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
 	    break;
 	if (len + 1 >= size) {
 	    size *= 2;
-	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+	    tmp = (xmlChar *) xmlRealloc(buf, size);
 	    if (tmp == NULL) {
-		xmlCatalogErrMemory("allocating public ID");
+		xmlCatalogErrMemory();
 		xmlFree(buf);
 		return(NULL);
 	    }
 	    buf = tmp;
 	}
 	buf[len++] = *cur;
-	count++;
 	NEXT;
     }
     buf[len] = 0;
@@ -2785,7 +2752,7 @@ xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) {
 	return(NULL);
 
     if (xmlDebugCatalogs)
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"Resolve sysID %s\n", sysID);
 
     if (catal->type == XML_XML_CATALOG_TYPE) {
@@ -2820,7 +2787,7 @@ xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) {
 	return(NULL);
 
     if (xmlDebugCatalogs)
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"Resolve pubID %s\n", pubID);
 
     if (catal->type == XML_XML_CATALOG_TYPE) {
@@ -2859,13 +2826,13 @@ xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID,
 
     if (xmlDebugCatalogs) {
          if ((pubID != NULL) && (sysID != NULL)) {
-             xmlGenericError(xmlGenericErrorContext,
+             fprintf(stderr,
                              "Resolve: pubID %s sysID %s\n", pubID, sysID);
          } else if (pubID != NULL) {
-             xmlGenericError(xmlGenericErrorContext,
+             fprintf(stderr,
                              "Resolve: pubID %s\n", pubID);
          } else {
-             xmlGenericError(xmlGenericErrorContext,
+             fprintf(stderr,
                              "Resolve: sysID %s\n", sysID);
          }
     }
@@ -2902,7 +2869,7 @@ xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) {
 	return(NULL);
 
     if (xmlDebugCatalogs)
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"Resolve URI %s\n", URI);
 
     if (catal->type == XML_XML_CATALOG_TYPE) {
@@ -2975,6 +2942,8 @@ xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type,
 	    if (catal->sgml == NULL)
 		catal->sgml = xmlHashCreate(10);
             res = xmlHashAddEntry(catal->sgml, orig, entry);
+            if (res < 0)
+                xmlFreeCatalogEntry(entry, NULL);
         }
     }
     return (res);
@@ -3117,35 +3086,7 @@ xmlInitializeCatalog(void) {
 
 	catalogs = (const char *) getenv("XML_CATALOG_FILES");
 	if (catalogs == NULL)
-#if defined(_WIN32) && defined(_MSC_VER)
-    {
-		void* hmodule;
-		hmodule = GetModuleHandleA("libxml2.dll");
-		if (hmodule == NULL)
-			hmodule = GetModuleHandleA(NULL);
-		if (hmodule != NULL) {
-			char buf[256];
-			unsigned long len = GetModuleFileNameA(hmodule, buf, 255);
-			if (len != 0) {
-				char* p = &(buf[len]);
-				while (*p != '\\' && p > buf)
-					p--;
-				if (p != buf) {
-					xmlChar* uri;
-					strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf));
-					uri = xmlCanonicPath((const xmlChar*)buf);
-					if (uri != NULL) {
-						strncpy(XML_XML_DEFAULT_CATALOG, uri, 255);
-						xmlFree(uri);
-					}
-				}
-			}
-		}
-		catalogs = XML_XML_DEFAULT_CATALOG;
-    }
-#else
 	    catalogs = XML_XML_DEFAULT_CATALOG;
-#endif
 
 	catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
 		xmlCatalogDefaultPrefer);
@@ -3277,7 +3218,7 @@ xmlCatalogCleanup(void) {
 
     xmlRMutexLock(xmlCatalogMutex);
     if (xmlDebugCatalogs)
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"Catalogs cleanup\n");
     if (xmlCatalogXMLFiles != NULL)
 	xmlHashFree(xmlCatalogXMLFiles, xmlFreeCatalogHashEntryList);
@@ -3505,19 +3446,19 @@ xmlCatalogSetDefaults(xmlCatalogAllow allow) {
     if (xmlDebugCatalogs) {
 	switch (allow) {
 	    case XML_CATA_ALLOW_NONE:
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Disabling catalog usage\n");
 		break;
 	    case XML_CATA_ALLOW_GLOBAL:
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Allowing only global catalogs\n");
 		break;
 	    case XML_CATA_ALLOW_DOCUMENT:
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Allowing only catalogs from the document\n");
 		break;
 	    case XML_CATA_ALLOW_ALL:
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Allowing all catalogs\n");
 		break;
 	}
@@ -3545,11 +3486,11 @@ xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) {
     if (xmlDebugCatalogs) {
 	switch (prefer) {
 	    case XML_CATA_PREFER_PUBLIC:
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Setting catalog preference to PUBLIC\n");
 		break;
 	    case XML_CATA_PREFER_SYSTEM:
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(stderr,
 			"Setting catalog preference to SYSTEM\n");
 		break;
 	    default:
@@ -3625,7 +3566,7 @@ xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) {
 	return(catalogs);
 
     if (xmlDebugCatalogs)
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"Adding document catalog %s\n", URL);
 
     add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL,
@@ -3669,13 +3610,13 @@ xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID,
 
     if (xmlDebugCatalogs) {
         if ((pubID != NULL) && (sysID != NULL)) {
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "Local Resolve: pubID %s sysID %s\n", pubID, sysID);
         } else if (pubID != NULL) {
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "Local Resolve: pubID %s\n", pubID);
         } else {
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "Local Resolve: sysID %s\n", sysID);
         }
     }
@@ -3712,7 +3653,7 @@ xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) {
 	return(NULL);
 
     if (xmlDebugCatalogs)
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"Resolve URI %s\n", URI);
 
     catal = (xmlCatalogEntryPtr) catalogs;
@@ -3748,7 +3689,7 @@ xmlCatalogGetSystem(const xmlChar *sysID) {
 	xmlInitializeCatalog();
 
     if (msg == 0) {
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"Use of deprecated xmlCatalogGetSystem() call\n");
 	msg++;
     }
@@ -3792,7 +3733,7 @@ xmlCatalogGetPublic(const xmlChar *pubID) {
 	xmlInitializeCatalog();
 
     if (msg == 0) {
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(stderr,
 		"Use of deprecated xmlCatalogGetPublic() call\n");
 	msg++;
     }
diff --git a/chvalid.c b/chvalid.c
index f4fa44acbb805aa543b4384895a51ad79632a59e..fb2c715a875cba99920510d87f2d89d5aebcb7f1 100644
--- a/chvalid.c
+++ b/chvalid.c
@@ -14,6 +14,8 @@
 #include "libxml.h"
 #include <libxml/chvalid.h>
 
+#include <stddef.h>
+
 /*
  * The initial tables ({func_name}_tab) are used to validate whether a
  * single-byte character is within the specified group.  Each table
diff --git a/config.h.cmake.in b/config.h.cmake.in
index 1f8be710f535c29bcb4b4bec9748d10592ecb6ba..2f4aeba3b49d0c1326011d9fa0795e50b8eee7db 100644
--- a/config.h.cmake.in
+++ b/config.h.cmake.in
@@ -1,20 +1,11 @@
-/* config.h.  Generated from config.h.in by configure.  */
-/* config.h.in.  Generated from configure.ac by autoheader.  */
-
-/* Define if __attribute__((destructor)) is accepted */
+/* A form that will not confuse apibuild.py */
 #cmakedefine ATTRIBUTE_DESTRUCTOR @ATTRIBUTE_DESTRUCTOR@
 
-/* Type cast for the gethostbyname() argument */
-#cmakedefine GETHOSTBYNAME_ARG_CAST @GETHOSTBYNAME_ARG_CAST@
-
 /* Define to 1 if you have the <arpa/inet.h> header file. */
 #cmakedefine HAVE_ARPA_INET_H 1
 
-/* Define to 1 if you have the <arpa/nameser.h> header file. */
-#cmakedefine HAVE_ARPA_NAMESER_H 1
-
-/* Whether struct sockaddr::__ss_family exists */
-#cmakedefine HAVE_BROKEN_SS_FAMILY 1
+/* Define if __attribute__((destructor)) is accepted */
+#cmakedefine HAVE_ATTRIBUTE_DESTRUCTOR 1
 
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #cmakedefine HAVE_DLFCN_H 1
@@ -31,18 +22,12 @@
 /* Define to 1 if you have the `ftime' function. */
 #cmakedefine HAVE_FTIME 1
 
-/* Define if getaddrinfo is there */
-#cmakedefine HAVE_GETADDRINFO 1
+/* Define to 1 if you have the `getentropy' function. */
+#cmakedefine HAVE_GETENTROPY 1
 
 /* Define to 1 if you have the `gettimeofday' function. */
 #cmakedefine HAVE_GETTIMEOFDAY 1
 
-/* Define to 1 if you have the <inttypes.h> header file. */
-#cmakedefine HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `isascii' function. */
-#cmakedefine HAVE_ISASCII 1
-
 /* Define if history library is there (-lhistory) */
 #cmakedefine HAVE_LIBHISTORY 1
 
@@ -69,18 +54,9 @@
 /* Define to 1 if you have the <poll.h> header file. */
 #cmakedefine HAVE_POLL_H 1
 
-/* Define if <pthread.h> is there */
+/* Define to 1 if you have the <pthread.h> header file. */
 #cmakedefine HAVE_PTHREAD_H 1
 
-/* Define to 1 if you have the `putenv' function. */
-#cmakedefine HAVE_PUTENV 1
-
-/* Define to 1 if you have the `rand_r' function. */
-#cmakedefine HAVE_RAND_R 1
-
-/* Define to 1 if you have the <resolv.h> header file. */
-#cmakedefine HAVE_RESOLV_H 1
-
 /* Have shl_load based dso */
 #cmakedefine HAVE_SHLLOAD 1
 
@@ -93,6 +69,9 @@
 /* Define to 1 if you have the <sys/mman.h> header file. */
 #cmakedefine HAVE_SYS_MMAN_H 1
 
+/* Define to 1 if you have the <sys/random.h> header file. */
+#cmakedefine HAVE_SYS_RANDOM_H 1
+
 /* Define to 1 if you have the <sys/select.h> header file. */
 #cmakedefine HAVE_SYS_SELECT_H 1
 
@@ -108,68 +87,20 @@
 /* Define to 1 if you have the <sys/time.h> header file. */
 #cmakedefine HAVE_SYS_TIME_H 1
 
-/* Define to 1 if you have the <sys/types.h> header file. */
-#cmakedefine HAVE_SYS_TYPES_H 1
-
 /* Define to 1 if you have the <unistd.h> header file. */
 #cmakedefine HAVE_UNISTD_H 1
 
-/* Whether va_copy() is available */
-#cmakedefine HAVE_VA_COPY 1
-
 /* Define to 1 if you have the <zlib.h> header file. */
 #cmakedefine HAVE_ZLIB_H 1
 
-/* Whether __va_copy() is available */
-#cmakedefine HAVE___VA_COPY 1
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#cmakedefine LT_OBJDIR "@LT_OBJDIR@"
-
-/* Name of package */
-#define PACKAGE "@PACKAGE@"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "@PACKAGE_NAME@"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "@PACKAGE_STRING@"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "@PACKAGE_TARNAME@"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL "@PACKAGE_URL@"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "@PACKAGE_VERSION@"
-
-/* Type cast for the send() function 2nd arg */
-#cmakedefine SEND_ARG2_CAST @SEND_ARG2_CAST@
-
 /* Support for IPv6 */
 #cmakedefine SUPPORT_IP6 1
 
-/* Define if va_list is an array type */
-#cmakedefine VA_LIST_IS_ARRAY 1
-
 /* Version number of package */
 #cmakedefine VERSION "@VERSION@"
 
 /* Determine what socket length (socklen_t) data type is */
 #cmakedefine XML_SOCKLEN_T @XML_SOCKLEN_T@
 
-/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-#cmakedefine _UINT32_T @_UINT32_T@
-
-/* ss_family is not defined here, use __ss_family instead */
-#cmakedefine ss_family @ss_family@
-
-/* Define to the type of an unsigned integer type of width exactly 32 bits if
-   such a type exists and the standard includes do not define it. */
-#cmakedefine uint32_t @uint32_t@
+/* TLS specifier */
+#cmakedefine XML_THREAD_LOCAL @XML_THREAD_LOCAL@
diff --git a/configure.ac b/configure.ac
index 4d8e0cb49b1adefda178e20b2daa541a34760251..36e74e4e967253c378cb0770181007a8914536bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,8 +2,8 @@ dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ([2.63])
 
 m4_define([MAJOR_VERSION], 2)
-m4_define([MINOR_VERSION], 10)
-m4_define([MICRO_VERSION], 1)
+m4_define([MINOR_VERSION], 13)
+m4_define([MICRO_VERSION], 4)
 
 AC_INIT([libxml2],[MAJOR_VERSION.MINOR_VERSION.MICRO_VERSION])
 AC_CONFIG_SRCDIR([entities.c])
@@ -21,7 +21,7 @@ LIBXML_VERSION_INFO=`expr $LIBXML_MAJOR_VERSION + $LIBXML_MINOR_VERSION`:$LIBXML
 LIBXML_VERSION_NUMBER=`expr $LIBXML_MAJOR_VERSION \* 10000 + $LIBXML_MINOR_VERSION \* 100 + $LIBXML_MICRO_VERSION`
 
 if test -d .git ; then
-  extra=`git describe 2>/dev/null | sed 's+LIBXML[[0-9.]]*-++'`
+  extra=`git describe 2>/dev/null`
   echo extra=$extra
   if test "$extra" != ""
   then
@@ -39,7 +39,7 @@ AC_SUBST(LIBXML_VERSION_EXTRA)
 
 VERSION=${LIBXML_VERSION}
 
-AM_INIT_AUTOMAKE([1.15 foreign no-dist-gzip dist-xz])
+AM_INIT_AUTOMAKE([1.16.3 foreign no-dist-gzip dist-xz])
 AM_MAINTAINER_MODE([enable])
 AM_SILENT_RULES([yes])
 
@@ -48,542 +48,384 @@ AC_PROG_CC
 AC_PROG_INSTALL
 AC_PROG_LN_S
 AC_PROG_MKDIR_P
-AC_PROG_CPP
-AC_PATH_PROG(MV, mv, /bin/mv)
 AC_PATH_PROG(TAR, tar, /bin/tar)
 AC_PATH_PROG(PERL, perl, /usr/bin/perl)
 AC_PATH_PROG(WGET, wget, /usr/bin/wget)
-AC_PATH_PROG(XMLLINT, xmllint, /usr/bin/xmllint)
 AC_PATH_PROG(XSLTPROC, xsltproc, /usr/bin/xsltproc)
 PKG_PROG_PKG_CONFIG
 
 LT_INIT([disable-static])
 LT_LIB_M
 
-dnl
-dnl if the system support linker version scripts for symbol versioning
-dnl then add it
-dnl
-VERSION_SCRIPT_FLAGS=
-# lt_cv_prog_gnu_ld is from libtool 2.+
-if test "$lt_cv_prog_gnu_ld" = yes; then
-  VERSION_SCRIPT_FLAGS=-Wl,--version-script=
-else
-  case $host in
-  *-*-sunos*) VERSION_SCRIPT_FLAGS="-Wl,-M -Wl,";;
-  esac
-fi
-AC_SUBST(VERSION_SCRIPT_FLAGS)
-AM_CONDITIONAL([USE_VERSION_SCRIPT], [test -n "$VERSION_SCRIPT_FLAGS"])
-
 dnl
 dnl We process the AC_ARG_WITH first so that later we can modify
 dnl some of them to try to prevent impossible combinations.  This
 dnl also allows up so alphabetize the choices
 dnl
 
-dnl
-dnl zlib option might change flags, so we save them initially
-dnl
-_cppflags="${CPPFLAGS}"
-_libs="${LIBS}"
-
 AC_ARG_WITH(c14n,
-[  --with-c14n             add the Canonicalization support (on)])
+[  --with-c14n             Canonical XML 1.0 support (on)])
 AC_ARG_WITH(catalog,
-[  --with-catalog          add the Catalog support (on)])
+[  --with-catalog          XML Catalogs support (on)])
 AC_ARG_WITH(debug,
-[  --with-debug            add the debugging module (on)])
-AC_ARG_WITH(fexceptions,
-[  --with-fexceptions      add GCC flag -fexceptions for C++ exceptions (off)])
+[  --with-debug            debugging module and shell (on)])
 AC_ARG_WITH(ftp,
-[  --with-ftp              add the FTP support (off)])
+[  --with-ftp              FTP support (off)])
 AC_ARG_WITH(history,
-[  --with-history          add history support to xmllint shell(off)])
+[  --with-history          history support for shell (off)])
+AC_ARG_WITH(readline,
+[  --with-readline[[=DIR]]   use readline in DIR (for shell history)])
 AC_ARG_WITH(html,
-[  --with-html             add the HTML support (on)])
+[  --with-html             HTML parser (on)])
 AC_ARG_WITH(http,
-[  --with-http             add the HTTP support (on)])
+[  --with-http             HTTP support (off)])
 AC_ARG_WITH(iconv,
-[  --with-iconv[[=DIR]]      add ICONV support (on)])
+[  --with-iconv[[=DIR]]      iconv support (on)])
 AC_ARG_WITH(icu,
-[  --with-icu                add ICU support (off)])
+[  --with-icu              ICU support (off)])
 AC_ARG_WITH(iso8859x,
-[  --with-iso8859x         add ISO8859X support if no iconv (on)])
-AC_ARG_WITH(legacy,
-[  --with-legacy           add deprecated APIs for compatibility (off)])
-AC_ARG_WITH(mem_debug,
-[  --with-mem-debug        add the memory debugging module (off)])
-AC_ARG_WITH(minimum,
-[  --with-minimum          build a minimally sized library (off)])
+[  --with-iso8859x         ISO-8859-X support if no iconv (on)])
+AC_ARG_WITH(lzma,
+[  --with-lzma[[=DIR]]       use liblzma in DIR (off)])
+AC_ARG_WITH(modules,
+[  --with-modules          dynamic modules support (on)])
 AC_ARG_WITH(output,
-[  --with-output           add the serialization support (on)])
+[  --with-output           serialization support (on)])
 AC_ARG_WITH(pattern,
-[  --with-pattern          add the xmlPattern selection interface (on)])
+[  --with-pattern          xmlPattern selection interface (on)])
 AC_ARG_WITH(push,
-[  --with-push             add the PUSH parser interfaces (on)])
+[  --with-push             push parser interfaces (on)])
 AC_ARG_WITH(python,
-[  --with-python           build Python bindings (on)])
+[  --with-python           Python bindings (on)])
 AC_ARG_WITH(reader,
-[  --with-reader           add the xmlReader parsing interface (on)])
-AC_ARG_WITH(readline,
-[  --with-readline=DIR     use readline in DIR],[
-  if test "$withval" != "no" && test "$withval" != "yes"; then
-    RDL_DIR=$withval
-    CPPFLAGS="${CPPFLAGS} -I$withval/include"
-    LDFLAGS="${LDFLAGS} -L$withval/lib"
-  fi
-])
+[  --with-reader           xmlReader parsing interface (on)])
 AC_ARG_WITH(regexps,
-[  --with-regexps          add Regular Expressions support (on)])
-AC_ARG_WITH(run_debug,
-[  --with-run-debug        add the runtime debugging module (off)])
+[  --with-regexps          regular expressions support (on)])
 AC_ARG_WITH(sax1,
-[  --with-sax1             add the older SAX1 interface (on)])
+[  --with-sax1             older SAX1 interface (on)])
 AC_ARG_WITH(schemas,
-[  --with-schemas          add Relax-NG and Schemas support (on)])
+[  --with-schemas          XML Schemas 1.0 and RELAX NG support (on)])
 AC_ARG_WITH(schematron,
-[  --with-schematron       add Schematron support (on)])
+[  --with-schematron       Schematron support (on)])
 AC_ARG_WITH(threads,
-[  --with-threads          add multithread support(on)])
+[  --with-threads          multithreading support (on)])
 AC_ARG_WITH(thread-alloc,
-[  --with-thread-alloc     add per-thread memory(off)])
+[  --with-thread-alloc     per-thread malloc hooks (off)])
 AC_ARG_WITH(tree,
-[  --with-tree             add the DOM like tree manipulation APIs (on)])
+[  --with-tree             DOM like tree manipulation APIs (on)])
 AC_ARG_WITH(valid,
-[  --with-valid            add the DTD validation support (on)])
+[  --with-valid            DTD validation support (on)])
 AC_ARG_WITH(writer,
-[  --with-writer           add the xmlWriter saving interface (on)])
+[  --with-writer           xmlWriter serialization interface (on)])
 AC_ARG_WITH(xinclude,
-[  --with-xinclude         add the XInclude support (on)])
+[  --with-xinclude         XInclude 1.0 support (on)])
 AC_ARG_WITH(xpath,
-[  --with-xpath            add the XPATH support (on)])
+[  --with-xpath            XPath 1.0 support (on)])
 AC_ARG_WITH(xptr,
-[  --with-xptr             add the XPointer support (on)])
+[  --with-xptr             XPointer support (on)])
 AC_ARG_WITH(xptr-locs,
-[  --with-xptr-locs        add support for XPointer locations (off)])
-AC_ARG_WITH(modules,
-[  --with-modules          add the dynamic modules support (on)])
+[  --with-xptr-locs        XPointer ranges and points (off)])
 AC_ARG_WITH(zlib,
-[  --with-zlib[[=DIR]]       use libz in DIR],[
-  if test "$withval" != "no" && test "$withval" != "yes"; then
-    Z_DIR=$withval
-    CPPFLAGS="${CPPFLAGS} -I$withval/include"
-    LDFLAGS="${LDFLAGS} -L$withval/lib"
-  fi
-])
-AC_ARG_WITH(lzma,
-[  --with-lzma[[=DIR]]       use liblzma in DIR],[
-  if test "$withval" != "no" && test "$withval" != "yes"; then
-    LZMA_DIR=$withval
-    CPPFLAGS="${CPPFLAGS} -I$withval/include"
-    LDFLAGS="${LDFLAGS} -L$withval/lib"
-  fi
-])
-AC_ARG_WITH(coverage,
-[  --with-coverage         build for code coverage with GCC (off)])
+[  --with-zlib[[=DIR]]       use libz in DIR (off)])
+
+AC_ARG_WITH(minimum,
+[  --with-minimum          build a minimally sized library (off)])
+AC_ARG_WITH(legacy,
+[  --with-legacy           maximum ABI compatibility (off)])
+
+AC_ARG_WITH(tls,
+[  --with-tls              thread-local storage (off)])
 
 dnl
-dnl hard dependencies on options
-dnl
-if test "$with_schemas" = "yes"
-then
-    with_pattern=yes
-    with_regexps=yes
-fi
-if test "$with_schematron" = "yes"
-then
-    with_pattern=yes
-    with_tree=yes
-    with_xpath=yes
-fi
-if test "$with_reader" = "yes"
-then
-    with_push=yes
-fi
-if test "$with_xptr_locs" = "yes"
-then
-    with_xptr=yes
-fi
-if test "$with_xptr" = "yes"
-then
-    with_xpath=yes
-fi
-dnl
-dnl option to build a minimal libxml2 library
+dnl Legacy defaults
 dnl
-if test "$with_minimum" = "yes"
-then
-    echo "Configuring for a minimal library"
-    if test "$with_c14n" = ""
-    then
-      with_c14n=no
-    fi
-    if test "$with_catalog" = ""
-    then
-      with_catalog=no
-    fi
-    echo So far so good!
-    if test "$with_debug" = ""
-    then
-      with_debug=no
-    fi
-    if test "$with_fexceptions" = ""
-    then
-      with_fexceptions=no
-    fi
-    if test "$with_history" = ""
-    then
-      with_history=no
-    fi
-    if test "$with_html" = ""
-    then
-      with_html=no
+if test "$with_legacy" = "yes"; then
+    if test "$with_http" = ""; then
+        with_http=yes
     fi
-    if test "$with_http" = ""
-    then
-      with_http=no 
-    fi
-    if test "$with_iconv" = ""
-    then
-      with_iconv=no
-    fi
-    if test "$with_iso8859x" = ""
-    then
-      with_iso8859x=no
-    fi
-    if test "$with_mem_debug" = ""
-    then 
-      with_mem_debug=no
-    fi
-    if test "$with_output" = ""
-    then
-      with_output=no
-    fi
-    if test "$with_pattern" = ""
-    then
-      with_pattern=no
-    fi
-    if test "$with_push" = ""
-    then
-      with_push=no
-    fi
-    if test "$with_python" = ""
-    then
-      with_python=no
-    fi
-    if test "$with_reader" = ""
-    then
-      with_reader=no
+    if test "$with_lzma" = ""; then
+        with_lzma=yes
     fi
-    if test "$with_readline" = ""
-    then
-      with_readline=no
+    if test "$with_zlib" = ""; then
+        with_zlib=yes
     fi
-    if test "$with_regexps" = ""
-    then
-      with_regexps=no
+fi
+
+dnl
+dnl hard dependencies on options
+dnl
+if test "$with_c14n" = "yes"; then
+    if test "$with_output" = "no"; then
+        echo WARNING: --with-c14n overrides --without-output
     fi
-    if test "$with_run_debug" = ""
-    then
-      with_run_debug=no
+    with_output=yes
+    if test "$with_xpath" = "no"; then
+        echo WARNING: --with-c14n overrides --without-xpath
     fi
-    if test "$with_sax1" = ""
-    then
-      with_sax1=no
+    with_xpath=yes
+fi
+if test "$with_schemas" = "yes"; then
+    if test "$with_pattern" = "no"; then
+        echo WARNING: --with-schemas overrides --without-pattern
     fi
-    if test "$with_schemas" = ""
-    then
-      with_schemas=no
+    with_pattern=yes
+    if test "$with_regexps" = "no"; then
+        echo WARNING: --with-schemas overrides --without-regexps
     fi
-    if test "$with_schematron" = ""
-    then
-      with_schematron=no
+    with_regexps=yes
+fi
+if test "$with_schematron" = "yes"; then
+    if test "$with_pattern" = "no"; then
+        echo WARNING: --with-schematron overrides --without-pattern
     fi
-    if test "$with_threads" = ""
-    then
-      with_threads=no
+    with_pattern=yes
+    if test "$with_tree" = "no"; then
+        echo WARNING: --with-schematron overrides --without-tree
     fi
-    if test "$with_thread_alloc" = ""
-    then
-      with_thread_alloc=no
-   fi
-    if test "$with_tree" = ""
-    then
-      with_tree=no
+    with_tree=yes
+    if test "$with_xpath" = "no"; then
+        echo WARNING: --with-schematron overrides --without-xpath
     fi
-    if test "$with_valid" = ""
-    then
-      with_valid=no
+    with_xpath=yes
+fi
+if test "$with_reader" = "yes"; then
+    if test "$with_push" = "no"; then
+        echo WARNING: --with-reader overrides --without-push
     fi
-    if test "$with_writer" = ""
-    then
-      with_writer=no
+    with_push=yes
+    if test "$with_tree" = "no"; then
+        echo WARNING: --with-reader overrides --without-tree
     fi
-    if test "$with_xinclude" = ""
-    then
-      with_xinclude=no
+    with_tree=yes
+fi
+if test "$with_writer" = "yes"; then
+    if test "$with_output" = "no"; then
+        echo WARNING: --with-writer overrides --without-output
     fi
-    if test "$with_xpath" = ""
-    then
-      with_xpath=no
+    with_output=yes
+    if test "$with_push" = "no"; then
+        echo WARNING: --with-writer overrides --without-push
     fi
-    if test "$with_xptr" = ""
-    then
-      with_xptr=no
+    with_push=yes
+fi
+if test "$with_xinclude" = "yes"; then
+    if test "$with_xpath" = "no"; then
+        echo WARNING: --with-xinclude overrides --without-xpath
     fi
-    if test "$with_zlib" = ""
-    then
-      with_zlib=no
+    with_xpath=yes
+fi
+if test "$with_xptr_locs" = "yes"; then
+    if test "$with_xptr" = "no"; then
+        echo WARNING: --with-xptr-locs overrides --without-xptr
     fi
-    if test "$with_modules" = ""
-    then
-      with_modules=no
+    with_xptr=yes
+fi
+if test "$with_xptr" = "yes"; then
+    if test "$with_xpath" = "no"; then
+        echo WARNING: --with-xptr overrides --without-xpath
     fi
+    with_xpath=yes
 fi
 
-echo Checking zlib
-
-dnl Checks for zlib library.
-
-WITH_ZLIB=0
-if test "$with_zlib" = "no"; then
-    echo "Disabling zlib compression support"
+if test "$with_minimum" = "yes"; then
+    dnl
+    dnl option to build a minimal libxml2 library
+    dnl
+    echo "Configuring for a minimal library"
+    test "$with_c14n" = "" && with_c14n=no
+    test "$with_catalog" = "" && with_catalog=no
+    test "$with_debug" = "" && with_debug=no
+    test "$with_history" = "" && with_history=no
+    test "$with_html" = "" && with_html=no
+    test "$with_http" = "" && with_http=no
+    test "$with_iconv" = "" && with_iconv=no
+    test "$with_iso8859x" = "" && with_iso8859x=no
+    test "$with_lzma" = "" && with_lzma=no
+    test "$with_output" = "" && with_output=no
+    test "$with_pattern" = "" && with_pattern=no
+    test "$with_push" = "" && with_push=no
+    test "$with_python" = "" && with_python=no
+    test "$with_reader" = "" && with_reader=no
+    test "$with_readline" = "" && with_readline=no
+    test "$with_regexps" = "" && with_regexps=no
+    test "$with_sax1" = "" && with_sax1=no
+    test "$with_schemas" = "" && with_schemas=no
+    test "$with_schematron" = "" && with_schematron=no
+    test "$with_threads" = "" && with_threads=no
+    test "$with_thread_alloc" = "" && with_thread_alloc=no
+    test "$with_tree" = "" && with_tree=no
+    test "$with_valid" = "" && with_valid=no
+    test "$with_writer" = "" && with_writer=no
+    test "$with_xinclude" = "" && with_xinclude=no
+    test "$with_xpath" = "" && with_xpath=no
+    test "$with_xptr" = "" && with_xptr=no
+    test "$with_zlib" = "" && with_zlib=no
+    test "$with_modules" = "" && with_modules=no
 else
-    # Don't run pkg-config if with_zlib contains a path.
-    if test "x$Z_DIR" = "x"; then
-        # Try pkg-config first so that static linking works.
-        PKG_CHECK_MODULES([Z],[zlib],
-            [WITH_ZLIB=1],
-            [:])
+    dnl
+    dnl Disable dependent modules
+    dnl
+    if test "$with_output" = "no"; then
+        with_c14n=no
+        with_writer=no
     fi
-
-    if test "$WITH_ZLIB" = "0"; then
-        AC_CHECK_HEADERS(zlib.h,
-            AC_CHECK_LIB(z, gzread,[
-                WITH_ZLIB=1
-                if test "x${Z_DIR}" != "x"; then
-                    Z_CFLAGS="-I${Z_DIR}/include"
-                    Z_LIBS="-L${Z_DIR}/lib -lz"
-                    [case ${host} in
-                        *-*-solaris*)
-                            Z_LIBS="-L${Z_DIR}/lib -R${Z_DIR}/lib -lz"
-                            ;;
-                    esac]
-                else
-                    Z_LIBS="-lz"
-                fi])
-            )
+    if test "$with_pattern" = "no"; then
+        with_schemas=no
+        with_schematron=no
     fi
-fi
-
-AC_SUBST(Z_CFLAGS)
-AC_SUBST(Z_LIBS)
-AC_SUBST(WITH_ZLIB)
-
-echo Checking lzma
-
-dnl Checks for lzma library.
-
-WITH_LZMA=0
-if test "$with_lzma" = "no"; then
-    echo "Disabling lzma compression support"
-else
-    # Don't run pkg-config if with_lzma contains a path.
-    if test "x$LZMA_DIR" = "x"; then
-        # Try pkg-config first so that static linking works.
-        PKG_CHECK_MODULES([LZMA],[liblzma],
-            [WITH_LZMA=1],
-            [:])
+    if test "$with_push" = "no"; then
+        with_reader=no
+        with_writer=no
     fi
-
-    # If pkg-config failed, fall back to AC_CHECK_LIB. This
-    # will not pick up the necessary LIBS flags for liblzma's
-    # private dependencies, though, so static linking may fail.
-    if test "$WITH_LZMA" = "0"; then
-        AC_CHECK_HEADERS(lzma.h,
-            AC_CHECK_LIB(lzma, lzma_code,[
-                WITH_LZMA=1
-                if test "x${LZMA_DIR}" != "x"; then
-                    LZMA_CFLAGS="-I${LZMA_DIR}/include"
-                    LZMA_LIBS="-L${LZMA_DIR}/lib -llzma"
-                else
-                    LZMA_LIBS="-llzma"
-                fi])
-            )
+    if test "$with_regexps" = "no"; then
+        with_schemas=no
+    fi
+    if test "$with_tree" = "no"; then
+        with_reader=no
+        with_schematron=no
+    fi
+    if test "$with_xpath" = "no"; then
+        with_c14n=no
+        with_schematron=no
+        with_xinclude=no
+        with_xptr=no
     fi
 fi
 
-AC_SUBST(LZMA_CFLAGS)
-AC_SUBST(LZMA_LIBS)
-AC_SUBST(WITH_LZMA)
-
-CPPFLAGS=${_cppflags}
-LIBS=${_libs}
-
-echo Checking headers
+XML_PRIVATE_LIBS=
+XML_PRIVATE_CFLAGS=
+XML_PC_LIBS=
+XML_PC_REQUIRES=
 
+dnl
 dnl Checks for header files.
-AC_CHECK_HEADERS([fcntl.h])
-AC_CHECK_HEADERS([unistd.h])
-AC_CHECK_HEADERS([sys/stat.h])
-AC_CHECK_HEADERS([sys/types.h])
+dnl
 AC_CHECK_HEADERS([stdint.h])
-AC_CHECK_HEADERS([inttypes.h])
-AC_CHECK_HEADERS([sys/socket.h], [], [],
-[#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-# endif
-])
-AC_CHECK_HEADERS([netinet/in.h], [], [],
-[#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-# endif
-])
-AC_CHECK_HEADERS([arpa/inet.h], [], [],
-[#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-# endif
-#if HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-# endif
-])
-AC_CHECK_HEADERS([netdb.h])
-AC_CHECK_HEADERS([sys/time.h])
-AC_CHECK_HEADERS([sys/select.h])
-AC_CHECK_HEADERS([poll.h])
+AC_CHECK_HEADERS([fcntl.h unistd.h sys/stat.h])
 AC_CHECK_HEADERS([sys/mman.h])
-AC_CHECK_HEADERS([sys/timeb.h])
-AC_CHECK_HEADERS([arpa/nameser.h], [], [],
-[#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-# endif
-])
-AC_CHECK_HEADERS([resolv.h], [], [],
-[#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-# endif
-#if HAVE_NETINET_IN_H
-# include <netinet/in.h>
-# endif
-#if HAVE_ARPA_NAMESER_H
-# include <arpa/nameser.h>
-# endif
-])
-AC_CHECK_HEADERS([dl.h])
-AC_CHECK_HEADERS([dlfcn.h])
-
-
-echo Checking types
-
-AC_TYPE_UINT32_T
-
-
-echo Checking libraries
+AC_CHECK_HEADERS([sys/time.h sys/timeb.h])
+AC_CHECK_HEADERS([sys/random.h])
+AC_CHECK_HEADERS([dl.h dlfcn.h])
+AC_CHECK_HEADERS([glob.h])
+AM_CONDITIONAL(WITH_GLOB, test "$ac_cv_header_glob_h" = "yes")
 
 dnl Checks for library functions.
-AC_CHECK_FUNCS(gettimeofday ftime)
-AC_CHECK_FUNCS(stat)
-AC_CHECK_FUNCS(rand_r)
-AC_CHECK_FUNCS(isascii mmap munmap putenv)
+AC_CHECK_FUNCS([gettimeofday ftime stat mmap munmap])
 
 AH_VERBATIM([HAVE_MUNMAP_AFTER],[/* mmap() is no good without munmap() */
 #if defined(HAVE_MMAP) && !defined(HAVE_MUNMAP)
 #  undef /**/ HAVE_MMAP
 #endif])
 
-dnl Checking for va_copy availability
-AC_MSG_CHECKING([for va_copy])
-AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdarg.h>
-va_list ap1,ap2;]], [[va_copy(ap1,ap2);]])],
-have_va_copy=yes,
-have_va_copy=no)
-AC_MSG_RESULT($have_va_copy)
-if test x"$have_va_copy" = x"yes"; then
-    AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available])
-else
-    AC_MSG_CHECKING([for __va_copy])
-    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdarg.h>
-    va_list ap1,ap2;]], [[__va_copy(ap1,ap2);]])],
-    have___va_copy=yes,
-    have___va_copy=no)
-    AC_MSG_RESULT($have___va_copy)
-    if test x"$have___va_copy" = x"yes"; then
-        AC_DEFINE(HAVE___VA_COPY,1,[Whether __va_copy() is available])
-    fi
-fi
-
-dnl Checking whether va_list is an array type
-AC_MSG_CHECKING([whether va_list is an array type])
-AC_TRY_COMPILE2([
-#include <stdarg.h>
-void a(va_list * ap) {}],[
-va_list ap1, ap2; a(&ap1); ap2 = (va_list) ap1],[
-  AC_MSG_RESULT(no)],[
-  AC_MSG_RESULT(yes)
-  AC_DEFINE([VA_LIST_IS_ARRAY], [1],[Define if va_list is an array type])])
+AC_CHECK_DECL([getentropy],
+              [AC_DEFINE([HAVE_GETENTROPY], [1], [getentropy])], [],
+              [#include <sys/random.h>])
 
-dnl Checks for inet libraries:
-AC_SEARCH_LIBS(gethostent, [nsl])
-AC_SEARCH_LIBS(setsockopt, [socket net network])
-AC_SEARCH_LIBS(connect, [inet])
+dnl
+dnl Checks for inet libraries
+dnl
+if test "$with_http" = "yes" || test "$with_ftp" = "yes"; then
+    AC_CHECK_HEADERS([sys/socket.h netinet/in.h arpa/inet.h netdb.h])
+    AC_CHECK_HEADERS([sys/select.h poll.h])
+
+    case "$host" in
+        *-*-mingw*)
+            dnl AC_SEARCH_LIBS doesn't work because of non-standard calling
+            dnl conventions on 32-bit Windows.
+            NET_LIBS="$NET_LIBS -lws2_32"
+            ;;
+        *)
+            _libs=$LIBS
+            AC_SEARCH_LIBS(gethostbyname, [nsl], [
+                if test "$ac_cv_search_gethostbyname" != "none required"; then
+                    NET_LIBS="$NET_LIBS $ac_cv_search_gethostbyname"
+                fi], [:], [$NET_LIBS])
+            AC_SEARCH_LIBS(connect, [bsd socket inet], [
+                if test "$ac_cv_search_connect" != "none required"; then
+                    NET_LIBS="$NET_LIBS $ac_cv_search_connect"
+                fi], [:], [$NET_LIBS])
+            LIBS=$_libs
+            ;;
+    esac
 
-dnl Determine what socket length (socklen_t) data type is
-AC_MSG_CHECKING([for type of socket length (socklen_t)])
-AC_TRY_COMPILE2([
-#include <stddef.h>
-#include <sys/types.h>
-#include <sys/socket.h>],[
-(void)getsockopt (1, 1, 1, NULL, (socklen_t *)NULL)],[
-  AC_MSG_RESULT(socklen_t *)
-  XML_SOCKLEN_T=socklen_t],[
-  AC_TRY_COMPILE2([
-#include <stddef.h>
-#include <sys/types.h>
-#include <sys/socket.h>],[
-(void)getsockopt (1, 1, 1, NULL, (size_t *)NULL)],[
-    AC_MSG_RESULT(size_t *)
-    XML_SOCKLEN_T=size_t],[
+    dnl Determine what socket length (socklen_t) data type is
+    AC_MSG_CHECKING([for type of socket length (socklen_t)])
     AC_TRY_COMPILE2([
-#include <stddef.h>
-#include <sys/types.h>
-#include <sys/socket.h>],[
-(void)getsockopt (1, 1, 1, NULL, (int *)NULL)],[
-      AC_MSG_RESULT(int *)
-      XML_SOCKLEN_T=int],[
-      AC_MSG_WARN(could not determine)
-      XML_SOCKLEN_T="int"])])])
-AC_DEFINE_UNQUOTED(XML_SOCKLEN_T, $XML_SOCKLEN_T, [Determine what socket length (socklen_t) data type is])
-
-dnl Checking if gethostbyname() argument is const.
-AC_MSG_CHECKING([for const gethostbyname() argument])
-AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <netdb.h>]],
-    [[(void)gethostbyname((const char *)"");]])],
-have_gethostbyname_const_arg=yes,
-have_gethostbyname_const_arg=no)
-AC_MSG_RESULT($have_gethostbyname_const_arg)
-if test x"$have_gethostbyname_const_arg" = x"yes"; then
-    AC_DEFINE([GETHOSTBYNAME_ARG_CAST], [],
-      [Type cast for the gethostbyname() argument])
-else
-    AC_DEFINE([GETHOSTBYNAME_ARG_CAST], [(char *)],
-      [Type cast for the gethostbyname() argument])
+    #include <stddef.h>
+    #ifdef _WIN32
+      #include <ws2tcpip.h>
+    #else
+      #include <sys/socket.h>
+    #endif],[
+    (void)getsockopt (1, 1, 1, NULL, (socklen_t *)NULL)],[
+      AC_MSG_RESULT(socklen_t *)
+      XML_SOCKLEN_T=socklen_t],[
+      AC_TRY_COMPILE2([
+    #include <stddef.h>
+    #include <sys/socket.h>],[
+    (void)getsockopt (1, 1, 1, NULL, (size_t *)NULL)],[
+        AC_MSG_RESULT(size_t *)
+        XML_SOCKLEN_T=size_t],[
+        AC_TRY_COMPILE2([
+    #include <stddef.h>
+    #include <sys/socket.h>],[
+    (void)getsockopt (1, 1, 1, NULL, (int *)NULL)],[
+          AC_MSG_RESULT(int *)
+          XML_SOCKLEN_T=int],[
+          AC_MSG_WARN(could not determine)
+          XML_SOCKLEN_T="int"])])])
+    AC_DEFINE_UNQUOTED(XML_SOCKLEN_T, $XML_SOCKLEN_T, [Determine what socket length (socklen_t) data type is])
+
+    dnl
+    dnl Checking for availability of IPv6
+    dnl
+    AC_ARG_ENABLE(ipv6, [  --enable-ipv6[[=yes/no]]  enables compilation of IPv6 code [[default=yes]]],, enable_ipv6=yes)
+    if test "$with_minimum" = "yes"
+    then
+        enable_ipv6=no
+    fi
+    if test $enable_ipv6 = yes; then
+        AC_MSG_CHECKING([whether to enable IPv6])
+        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+            #ifdef _WIN32
+              #include <winsock2.h>
+            #else
+              #include <sys/socket.h>
+              #ifdef HAVE_NETDB_H
+                #include <netdb.h>
+              #endif
+            #endif
+            ]], [[
+            struct sockaddr_storage ss;
+            socket(AF_INET6, SOCK_STREAM, 0);
+            getaddrinfo(0, 0, 0, 0);
+            ]])], [
+            AC_DEFINE([SUPPORT_IP6], [], [Support for IPv6])
+            AC_MSG_RESULT([yes])], [
+            AC_MSG_RESULT([no])]
+        )
+    fi
 fi
 
-dnl Checking if send() second argument is const.
-AC_MSG_CHECKING([for const send() second argument])
-AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
-#include <sys/socket.h>]],
-    [[(void)send(1,(const char *)"",1,1);]])],
-have_send_const_arg2=yes,
-have_send_const_arg2=no)
-AC_MSG_RESULT($have_send_const_arg2)
-if test x"$have_send_const_arg2" = x"yes"; then
-    AC_DEFINE([SEND_ARG2_CAST], [],
-      [Type cast for the send() function 2nd arg])
-else
-    AC_DEFINE([SEND_ARG2_CAST], [(char *)],
-      [Type cast for the send() function 2nd arg])
+dnl
+dnl Extra flags
+dnl
+XML_LIBDIR='-L${libdir}'
+XML_INCLUDEDIR='-I${includedir}/libxml2'
+XML_CFLAGS=""
+
+dnl Thread-local storage
+if test "$with_tls" = "yes"; then
+    AC_COMPILE_IFELSE([
+        AC_LANG_SOURCE([_Thread_local int v;]) ], [
+        AC_DEFINE([XML_THREAD_LOCAL], [_Thread_local], [TLS specifier]) ], [
+    AC_COMPILE_IFELSE([
+        AC_LANG_SOURCE([__thread int v;]) ], [
+        AC_DEFINE([XML_THREAD_LOCAL], [__thread], [TLS specifier]) ], [
+    AC_COMPILE_IFELSE([
+        AC_LANG_SOURCE([__declspec(thread) int v;]) ], [
+        AC_DEFINE([XML_THREAD_LOCAL], [__declspec(thread)], [TLS specifier]) ], [
+    WARN_NO_TLS=1 ])])])
 fi
 
 dnl Checking whether __attribute__((destructor)) is accepted by the compiler
@@ -596,99 +438,29 @@ f(void) {}], [], [
   AC_DEFINE([ATTRIBUTE_DESTRUCTOR], [__attribute__((destructor))],[A form that will not confuse apibuild.py])],[
   AC_MSG_RESULT(no)])
 
-
-dnl ***********************Checking for availability of IPv6*******************
-
-AC_MSG_CHECKING([whether to enable IPv6])
-AC_ARG_ENABLE(ipv6, [  --enable-ipv6[[=yes/no]]  enables compilation of IPv6 code [[default=yes]]],, enable_ipv6=yes)
-if test "$with_minimum" = "yes"
-then
-    enable_ipv6=no
-fi
-if test $enable_ipv6 = yes; then
-  have_ipv6=no
-  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#   include <sys/types.h>
-#   include <sys/socket.h>
-    ]], [[
-    struct sockaddr_storage ss;
-    socket(AF_INET6, SOCK_STREAM, 0)
-    ]])],
-    have_ipv6=yes,
-    have_ipv6=no
-  )
-  AC_MSG_RESULT($have_ipv6)
-
-  if test $have_ipv6 = yes; then
-    AC_DEFINE([SUPPORT_IP6], [], [Support for IPv6])
-    have_broken_ss_family=no
-
-    dnl *********************************************************************
-    dnl on some platforms (like AIX 5L), the structure sockaddr doesn't have
-    dnl a ss_family member, but rather __ss_family. Let's detect that
-    dnl and define the HAVE_BROKEN_SS_FAMILY when we are on one of these
-    dnl platforms.  However, we should only do this if ss_family is not
-    dnl present.
-    dnl ********************************************************************
-    AC_MSG_CHECKING([struct sockaddr::ss_family])
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#     include <sys/types.h>
-#     include <sys/socket.h>
-      ]], [[
-      struct sockaddr_storage ss ;
-      ss.ss_family = 0 ;
-      ]])],
-      have_ss_family=yes,
-      have_ss_family=no
-    )
-    AC_MSG_RESULT($have_ss_family)
-    if test x$have_ss_family = xno ; then
-      AC_MSG_CHECKING([broken struct sockaddr::ss_family])
-      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#       include <sys/types.h>
-#       include <sys/socket.h>
-        ]], [[
-        struct sockaddr_storage ss ;
-        ss.__ss_family = 0 ;
-        ]])],
-        have_broken_ss_family=yes,
-        have_broken_ss_family=no
-      )
-      AC_MSG_RESULT($have_broken_ss_family)
-      if test x$have_broken_ss_family = xyes ; then
-        AC_DEFINE(HAVE_BROKEN_SS_FAMILY, [],
-	  [Whether struct sockaddr::__ss_family exists]) 
-        AC_DEFINE(ss_family, __ss_family,
-	  [ss_family is not defined here, use __ss_family instead])
-      else
-        AC_MSG_WARN(ss_family and __ss_family not found)
-      fi
-    fi
-
-    have_getaddrinfo=no
-    AC_CHECK_FUNC(getaddrinfo, have_getaddrinfo=yes)
-    if test $have_getaddrinfo != yes; then
-      for lib in bsd socket inet; do
-        AC_CHECK_LIB($lib, getaddrinfo, [LIBS="$LIBS -l$lib";have_getaddrinfo=yes;break])
-      done
-    fi
-
-    if test $have_getaddrinfo = yes; then
-      AC_DEFINE([HAVE_GETADDRINFO], [], [Define if getaddrinfo is there])
-    fi
-  fi
-fi 
-
-dnl ******************************End IPv6 checks******************************
-
-XML_LIBDIR='-L${libdir}'
-XML_INCLUDEDIR='-I${includedir}/libxml2'
-
 dnl
-dnl Extra flags
+dnl Linker version scripts for symbol versioning
 dnl
-XML_CFLAGS=""
-RDL_LIBS=""
+VERSION_SCRIPT_FLAGS=
+# lt_cv_prog_gnu_ld is from libtool 2.+
+if test "$lt_cv_prog_gnu_ld" = yes; then
+  case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-msys* )
+      ;;
+    *)
+      dnl lld 16 defaults to --no-undefined-version but the version script
+      dnl can contain symbols disabled by configuration options.
+      AX_APPEND_LINK_FLAGS([-Wl,--undefined-version], [VERSION_SCRIPT_FLAGS])
+      AX_APPEND_FLAG([-Wl,--version-script=], [VERSION_SCRIPT_FLAGS])
+      ;;
+  esac
+else
+  case $host in
+  *-*-sunos*) VERSION_SCRIPT_FLAGS="-Wl,-M -Wl,";;
+  esac
+fi
+AC_SUBST(VERSION_SCRIPT_FLAGS)
+AM_CONDITIONAL([USE_VERSION_SCRIPT], [test -n "$VERSION_SCRIPT_FLAGS"])
 
 dnl
 dnl Workaround for native compilers
@@ -698,35 +470,26 @@ dnl
 if test "${GCC}" != "yes" ; then
     case "${host}" in
           hppa*-*-hpux* )
-	       EXTRA_CFLAGS="${EXTRA_CFLAGS} -Wp,-H30000"
+	       AM_CFLAGS="${AM_CFLAGS} -Wp,-H30000"
 	       ;;
           *-dec-osf* )
-               EXTRA_CFLAGS="${EXTRA_CFLAGS} -ieee"
+               AM_CFLAGS="${AM_CFLAGS} -ieee"
                ;;
 	  alpha*-*-linux* )
-	       EXTRA_CFLAGS="${EXTRA_CFLAGS} -ieee"
+	       AM_CFLAGS="${AM_CFLAGS} -ieee"
 	       ;;
     esac
 else
-    if test "$with_fexceptions" = "yes"
-    then
-        #
-	# Not activated by default because this inflates the code size
-	# Used to allow propagation of C++ exceptions through the library
-	#
-	EXTRA_CFLAGS="${EXTRA_CFLAGS} -fexceptions"
-    fi
-
     # warnings we'd like to see
-    EXTRA_CFLAGS="${EXTRA_CFLAGS} -pedantic -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wredundant-decls"
+    AM_CFLAGS="${AM_CFLAGS} -pedantic -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes"
     # warnings we'd like to suppress
-    EXTRA_CFLAGS="${EXTRA_CFLAGS} -Wno-long-long -Wno-format-extra-args"
+    AM_CFLAGS="${AM_CFLAGS} -Wno-long-long -Wno-format-extra-args"
     case "${host}" in
           alpha*-*-linux* )
-	       EXTRA_CFLAGS="${EXTRA_CFLAGS} -mieee"
+	       AM_CFLAGS="${AM_CFLAGS} -mieee"
 	       ;;
 	  alpha*-*-osf* )
-	       EXTRA_CFLAGS="${EXTRA_CFLAGS} -mieee"
+	       AM_CFLAGS="${AM_CFLAGS} -mieee"
 	       ;;
     esac
 fi
@@ -734,305 +497,99 @@ case ${host} in
     *-*-solaris*)
         XML_LIBDIR="${XML_LIBDIR} -R${libdir}"
         ;;
-    hppa*-hp-mpeix)
-        NEED_TRIO=1
-	;;
-    *-*-mingw* | *-*-cygwin* | *-*-msvc* )
+    *-*-cygwin* | *-*-mingw* | *-*-msys* )
         # If the host is Windows, and shared libraries are disabled, we
-        # need to add -DLIBXML_STATIC to EXTRA_CFLAGS in order for linking to
+        # need to add -DLIBXML_STATIC to AM_CFLAGS in order for linking to
         # work properly (without it, xmlexports.h would force the use of
         # DLL imports, which obviously aren't present in a static
         # library).
         if test "x$enable_shared" = "xno"; then
             XML_CFLAGS="$XML_CFLAGS -DLIBXML_STATIC"
-            EXTRA_CFLAGS="$EXTRA_CFLAGS -DLIBXML_STATIC"
+            AM_CFLAGS="$AM_CFLAGS -DLIBXML_STATIC"
         fi
         ;;
 esac
 
 
 dnl
-dnl check for python
+dnl Simple API modules
 dnl
 
-PYTHON_TESTS=
-AS_IF([test "x$with_python" != "xno"], [
-    AM_PATH_PYTHON
-    PKG_CHECK_MODULES([PYTHON], [python-${PYTHON_VERSION}])
-])
-AM_CONDITIONAL([WITH_PYTHON], [test "x$with_python" != "xno"])
-
-dnl check for dso support
-WITH_MODULES=0
-
-if test "$with_modules" != "no" ; then
- case "$host" in
-  *-*-cygwin*)
-  MODULE_EXTENSION=".dll"
-  AC_CHECK_LIB(cygwin, dlopen, [
-    WITH_MODULES=1
-    MODULE_PLATFORM_LIBS=
-    AC_DEFINE([HAVE_DLOPEN], [], [Have dlopen based dso])
-  ])
-  ;;
-  *-*-mingw*)
-  MODULE_EXTENSION=".dll"
-  WITH_MODULES=1
-  ;;
-  *)
-  AC_CHECK_FUNC(shl_load, libxml_have_shl_load=yes, [
-    AC_CHECK_LIB(dld, shl_load, [
-      MODULE_PLATFORM_LIBS="-ldld"
-      libxml_have_shl_load=yes], [
-      AC_CHECK_FUNC(dlopen, libxml_have_dlopen=yes, [
-        AC_CHECK_LIB(dl, dlopen, [
-          MODULE_PLATFORM_LIBS="-ldl"
-          libxml_have_dlopen=yes])])])])
-
-  if test "${libxml_have_shl_load}" = "yes"; then
-    MODULE_EXTENSION=".sl"
-    WITH_MODULES=1
-    AC_DEFINE([HAVE_SHLLOAD], [], [Have shl_load based dso])
-  fi
- 
-  if test "${libxml_have_dlopen}" = "yes"; then
-    case "${host}" in
-      *-*-hpux* )
-	MODULE_EXTENSION=".sl"
-	;;
-      * )
-	MODULE_EXTENSION=".so"
-	;;
-    esac
-
-    WITH_MODULES=1
-    AC_DEFINE([HAVE_DLOPEN], [], [Have dlopen based dso])
-  fi
- ;;
- esac
-fi
-
-AC_SUBST(WITH_MODULES)
-AC_SUBST(MODULE_PLATFORM_LIBS)
-AC_SUBST(MODULE_EXTENSION)
-
-dnl
-dnl Check for trio string functions
-dnl
-
-if test "${NEED_TRIO}" = "1" ; then
-    echo Adding trio library for string functions
-    WITH_TRIO=1
-else    
-    WITH_TRIO=0
-fi
-AM_CONDITIONAL(WITH_TRIO_SOURCES, test "${NEED_TRIO}" = "1")
-AC_SUBST(WITH_TRIO)
-
-dnl
-dnl Allow to enable/disable various pieces
-dnl
-echo Checking configuration requirements
-
-dnl
-dnl Thread-related stuff
-dnl
-THREAD_LIBS=""
-BASE_THREAD_LIBS=""
-WITH_THREADS=0
-THREAD_CFLAGS=""
-THREADS_W32=""
-WITH_THREAD_ALLOC=0
-
-if test "$with_threads" = "no" ; then
-    echo Disabling multithreaded support
-else
-    echo Enabling multithreaded support
-
-    dnl Default to native threads on Windows
-    case $host_os in
-       *mingw*) if test "$with_threads" != "pthread" && test "$with_threads" != "no"; then
-               WITH_THREADS="1"
-               THREADS_W32="1"
-               THREAD_CFLAGS="$THREAD_CFLAGS -DHAVE_WIN32_THREADS"
-           fi
-       ;;
-    esac
-
-    dnl Use pthread by default in other cases
-    if test -z "$THREADS_W32"; then
-        if test "$with_threads" = "pthread" || test "$with_threads" = "" || test "$with_threads" = "yes" ; then
-            AC_CHECK_HEADER(pthread.h,
-                AC_CHECK_LIB(pthread, pthread_join,[
-                THREAD_LIBS="-lpthread"
-                AC_DEFINE([HAVE_PTHREAD_H], [], [Define if <pthread.h> is there])
-                WITH_THREADS="1"]))
-        fi
-    fi
-
-    case $host_os in
-       *cygwin*) THREAD_LIBS=""
-       ;;
-       *beos*) WITH_THREADS="1"
-	   THREAD_CFLAGS="$THREAD_CFLAGS -DHAVE_BEOS_THREADS"
-       ;;
-       *linux*)
-           if test "${GCC}" = "yes" ; then
-	       GCC_VERSION=`${CC} --version | head -1 | awk '{print $3}'`
-	       GCC_MAJOR=`echo ${GCC_VERSION} | sed 's+\..*++'`
-	       GCC_MEDIUM=`echo ${GCC_VERSION} | sed 's+[[0-9]]*\.++' | sed 's+\..*++'`
-	       if test "${THREAD_LIBS}" = "-lpthread" ; then
-	           if expr ${GCC_MEDIUM} \> 2 \& ${GCC_MAJOR} = 3 > /dev/null
-		   then
-		       THREAD_LIBS=""
-		       BASE_THREAD_LIBS="-lpthread"
-		   else
-		   if expr ${GCC_MAJOR} \> 3 > /dev/null
-		   then
-		       THREAD_LIBS=""
-		       BASE_THREAD_LIBS="-lpthread"
-		   else
-		       echo old GCC disabling weak symbols for pthread
-		   fi
-		   fi
-	       fi
-	   fi
-       ;;
-    esac
-    if test "$WITH_THREADS" = "1" ; then
-	THREAD_CFLAGS="$THREAD_CFLAGS -D_REENTRANT"
-    fi
-fi
-if test "$with_thread_alloc" = "yes" && test "$WITH_THREADS" = "1" ; then
-    WITH_THREAD_ALLOC=1
-fi
-
-AC_SUBST(THREAD_LIBS)
-AC_SUBST(BASE_THREAD_LIBS)
-AC_SUBST(WITH_THREADS)
-AC_SUBST(THREAD_CFLAGS)
-AC_SUBST(WITH_THREAD_ALLOC)
-AM_CONDITIONAL([THREADS_W32],[test -n "$THREADS_W32"])
-
-dnl
-dnl xmllint shell history
-dnl
-if test "$with_history" = "yes" ; then
-    echo Enabling xmllint shell history
-    dnl check for terminal library. this is a very cool solution
-    dnl from octave's configure.in
-    unset tcap
-    for termlib in ncurses curses termcap terminfo termlib; do
-	AC_CHECK_LIB(${termlib}, tputs, [tcap="-l$termlib"])
-	test -n "$tcap" && break
-    done
-
-    AC_CHECK_HEADER(readline/history.h,
-	AC_CHECK_LIB(history, append_history,[
-	   RDL_LIBS="-lhistory"
-	   AC_DEFINE([HAVE_LIBHISTORY], [], [Define if history library is there (-lhistory)])]))
-    AC_CHECK_HEADER(readline/readline.h,
-	AC_CHECK_LIB(readline, readline,[
-	   RDL_LIBS="-lreadline $RDL_LIBS $tcap"
-	   AC_DEFINE([HAVE_LIBREADLINE], [], [Define if readline library is there (-lreadline)])], , $tcap))
-    if test -n "$RDL_DIR" && test -n "$RDL_LIBS"; then
-	CPPFLAGS="$CPPFLAGS -I${RDL_DIR}/include"
-	RDL_LIBS="-L${RDL_DIR}/lib $RDL_LIBS"
-    fi
-fi
-
-dnl
-dnl Tree functions
-dnl
 if test "$with_tree" = "no" ; then
     echo Disabling DOM like tree manipulation APIs
     WITH_TREE=0
-else    
+else
     WITH_TREE=1
 fi
 AC_SUBST(WITH_TREE)
 
 if test "$with_ftp" != "yes" ; then
-    echo Disabling FTP support
     WITH_FTP=0
-    FTP_OBJ=
-else    
+else
+    echo Enabling FTP support
     WITH_FTP=1
-    FTP_OBJ=nanoftp.o
 fi
 AC_SUBST(WITH_FTP)
-AC_SUBST(FTP_OBJ)
+AM_CONDITIONAL(WITH_FTP_SOURCES, test "$WITH_FTP" = "1")
 
-if test "$with_http" = "no" ; then
-    echo Disabling HTTP support
+if test "$with_http" != "yes" ; then
     WITH_HTTP=0
-    HTTP_OBJ=
-else    
+else
+    echo Enabling HTTP support
     WITH_HTTP=1
-    HTTP_OBJ=nanohttp.o
 fi
 AC_SUBST(WITH_HTTP)
-AC_SUBST(HTTP_OBJ)
+AM_CONDITIONAL(WITH_HTTP_SOURCES, test "$WITH_HTTP" = "1")
 
 if test "$with_legacy" != "yes" ; then
-    echo Disabling deprecated APIs
     WITH_LEGACY=0
-else    
+else
+    echo Enabling deprecated APIs
     WITH_LEGACY=1
 fi
 AC_SUBST(WITH_LEGACY)
+AM_CONDITIONAL(WITH_LEGACY_SOURCES, test "$WITH_LEGACY" = "1")
 
 if test "$with_reader" = "no" ; then
     echo Disabling the xmlReader parsing interface
     WITH_READER=0
-else    
+else
     WITH_READER=1
-    if test "$with_push" = "no" ; then
-        echo xmlReader requires Push interface - enabling it
-	with_push=yes
-    fi
 fi
 AC_SUBST(WITH_READER)
+AM_CONDITIONAL(WITH_READER_SOURCES, test "$WITH_READER" = "1")
 
 if test "$with_writer" = "no" ; then
     echo Disabling the xmlWriter saving interface
     WITH_WRITER=0
-#    WRITER_TEST=
-else    
+else
     WITH_WRITER=1
-#    WRITER_TEST=Writertests
-    if test "$with_push" = "no" ; then
-        echo xmlWriter requires Push interface - enabling it
-	with_push=yes
-    fi
-    if test "$with_output" = "no" ; then
-        echo xmlWriter requires Output interface - enabling it
-	with_output=yes
-    fi
 fi
 AC_SUBST(WITH_WRITER)
-#AC_SUBST(WRITER_TEST)
+AM_CONDITIONAL(WITH_WRITER_SOURCES, test "$WITH_WRITER" = "1")
 
 if test "$with_pattern" = "no" ; then
     echo Disabling the xmlPattern parsing interface
     WITH_PATTERN=0
-else    
+else
     WITH_PATTERN=1
 fi
 AC_SUBST(WITH_PATTERN)
+AM_CONDITIONAL(WITH_PATTERN_SOURCES, test "$WITH_PATTERN" = "1")
 
 if test "$with_sax1" = "no" ; then
     echo Disabling the older SAX1 interface
     WITH_SAX1=0
-else    
+else
     WITH_SAX1=1
 fi
 AC_SUBST(WITH_SAX1)
+AM_CONDITIONAL(WITH_SAX1_SOURCES, test "$WITH_SAX1" = "1")
 
 if test "$with_push" = "no" ; then
     echo Disabling the PUSH parser interfaces
     WITH_PUSH=0
-else    
+else
     WITH_PUSH=1
 fi
 AC_SUBST(WITH_PUSH)
@@ -1040,406 +597,558 @@ AC_SUBST(WITH_PUSH)
 if test "$with_html" = "no" ; then
     echo Disabling HTML support
     WITH_HTML=0
-    HTML_OBJ=
-else    
+else
     WITH_HTML=1
-    HTML_OBJ="HTMLparser.o HTMLtree.o"
 fi
 AC_SUBST(WITH_HTML)
-AC_SUBST(HTML_OBJ)
+AM_CONDITIONAL(WITH_HTML_SOURCES, test "$WITH_HTML" = "1")
 
 if test "$with_valid" = "no" ; then
     echo Disabling DTD validation support
     WITH_VALID=0
-    TEST_VTIME=
-else    
+else
     WITH_VALID=1
-    TEST_VTIME=VTimingtests
 fi
 AC_SUBST(WITH_VALID)
-AC_SUBST(TEST_VALID)
-AC_SUBST(TEST_VTIME)
+AM_CONDITIONAL(WITH_VALID_SOURCES, test "$WITH_VALID" = "1")
 
 if test "$with_catalog" = "no" ; then
     echo Disabling Catalog support
     WITH_CATALOG=0
-    CATALOG_OBJ=
-    TEST_CATALOG=
-else    
+else
     WITH_CATALOG=1
-    CATALOG_OBJ="catalog.o"
-    TEST_CATALOG=Catatests
 fi
 AC_SUBST(WITH_CATALOG)
-AC_SUBST(CATALOG_OBJ)
-AC_SUBST(TEST_CATALOG)
+AM_CONDITIONAL(WITH_CATALOG_SOURCES, test "$WITH_CATALOG" = "1")
 
 if test "$with_xptr" = "no" ; then
     echo Disabling XPointer support
     WITH_XPTR=0
     WITH_XPTR_LOCS=0
-    XPTR_OBJ=
-else    
+else
     WITH_XPTR=1
-    XPTR_OBJ=xpointer.o
-    if test "$with_xpath" = "no" ; then
-        echo XPointer requires XPath support - enabling it
-	with_xpath=yes
-    fi
-    if test "$with_xptr_locs" = "yes" ; then
-        WITH_XPTR_LOCS=1
-    else
-        WITH_XPTR_LOCS=0
-    fi
 fi
 AC_SUBST(WITH_XPTR)
+AM_CONDITIONAL(WITH_XPTR_SOURCES, test "$WITH_XPTR" = "1")
+
+if test "$with_xptr_locs" != "yes" ; then
+    WITH_XPTR_LOCS=0
+else
+    echo Enabling Xpointer locations support
+    WITH_XPTR_LOCS=1
+fi
 AC_SUBST(WITH_XPTR_LOCS)
-AC_SUBST(XPTR_OBJ)
 
 if test "$with_c14n" = "no" ; then
     echo Disabling C14N support
     WITH_C14N=0
-    C14N_OBJ=
-else    
+else
     WITH_C14N=1
-    C14N_OBJ="c14n.c"
-    if test "$with_xpath" = "no" ; then
-        echo C14N requires XPath support - enabling it
-	with_xpath=yes
-    fi
 fi
 AC_SUBST(WITH_C14N)
-AC_SUBST(C14N_OBJ)
+AM_CONDITIONAL(WITH_C14N_SOURCES, test "$WITH_C14N" = "1")
 
 if test "$with_xinclude" = "no" ; then
     echo Disabling XInclude support
     WITH_XINCLUDE=0
-    XINCLUDE_OBJ=
-    with_xinclude="no"
-else    
+else
     WITH_XINCLUDE=1
-    XINCLUDE_OBJ=xinclude.o
-    if test "$with_xpath" = "no" ; then
-        echo XInclude requires XPath support - enabling it
-	with_xpath=yes
-    fi
 fi
 AC_SUBST(WITH_XINCLUDE)
-AC_SUBST(XINCLUDE_OBJ)
-
-if test "$with_xptr" = "" && test "$with_xpath" = "no" ; then
-    with_xptr=no
-fi
-
-if test "$with_schematron" = "" && test "$with_xpath" = "no" ; then
-    with_schematron=no
-fi
+AM_CONDITIONAL(WITH_XINCLUDE_SOURCES, test "$WITH_XINCLUDE" = "1")
 
 if test "$with_schematron" = "no" ; then
     echo "Disabling Schematron support"
     WITH_SCHEMATRON=0
-    TEST_SCHEMATRON=
-else 
-    echo "Enabled Schematron support"
+else
     WITH_SCHEMATRON=1
-    TEST_SCHEMATRON="Schematrontests"
-    with_xpath=yes
-    with_pattern=yes
-    with_schematron=yes
 fi
 AC_SUBST(WITH_SCHEMATRON)
-AC_SUBST(TEST_SCHEMATRON)
+AM_CONDITIONAL(WITH_SCHEMATRON_SOURCES, test "$WITH_SCHEMATRON" = "1")
 
 if test "$with_xpath" = "no" ; then
     echo Disabling XPATH support
     WITH_XPATH=0
-    XPATH_OBJ=
-else    
+else
     WITH_XPATH=1
-    XPATH_OBJ=xpath.o
 fi
 AC_SUBST(WITH_XPATH)
-AC_SUBST(XPATH_OBJ)
+AM_CONDITIONAL(WITH_XPATH_SOURCES, test "$WITH_XPATH" = "1")
 
-dnl
-dnl output functions
-dnl
 if test "$with_output" = "no" ; then
     echo Disabling serialization/saving support
     WITH_OUTPUT=0
-else    
+else
     WITH_OUTPUT=1
 fi
 AC_SUBST(WITH_OUTPUT)
+AM_CONDITIONAL(WITH_OUTPUT_SOURCES, test "$WITH_OUTPUT" = "1")
 
-WITH_ICONV=0
-if test "$with_iconv" = "no" ; then
-    echo Disabling ICONV support
-else
-    if test "$with_iconv" != "yes" && test "$with_iconv" != "" ; then
-	CPPFLAGS="${CPPFLAGS} -I$with_iconv/include"
-	# Export this since our headers include iconv.h
-	XML_INCLUDEDIR="${XML_INCLUDEDIR} -I$with_iconv/include"
-	ICONV_LIBS="-L$with_iconv/lib"
-    fi
-
-    AC_CHECK_HEADER(iconv.h,
-	AC_MSG_CHECKING(for iconv)
-	AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>
-#include <iconv.h>]],[[
-iconv_t cd = iconv_open ("","");
-iconv (cd, NULL, NULL, NULL, NULL);]])],[
-	    AC_MSG_RESULT(yes)
-	    WITH_ICONV=1],[
-	    AC_MSG_RESULT(no)
-	    AC_MSG_CHECKING(for iconv in -liconv)
-
-	    _ldflags="${LDFLAGS}"
-	    _libs="${LIBS}"
-	    LDFLAGS="${LDFLAGS} ${ICONV_LIBS}"
-	    LIBS="${LIBS} -liconv"
-
-	    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>
-#include <iconv.h>]],[[
-iconv_t cd = iconv_open ("","");
-iconv (cd, NULL, NULL, NULL, NULL);]])],[
-		AC_MSG_RESULT(yes)
-		WITH_ICONV=1
-		ICONV_LIBS="${ICONV_LIBS} -liconv"
-		LIBS="${_libs}"
-		LDFLAGS="${_ldflags}"],[
-		AC_MSG_RESULT(no)
-		LIBS="${_libs}"
-		LDFLAGS="${_ldflags}"])]))
-fi
-AC_SUBST(WITH_ICONV)
-
-WITH_ICU=0
-ICU_LIBS=""
-if test "$with_icu" != "yes" ; then
-    echo Disabling ICU support
-else
-    # Try pkg-config first so that static linking works.
-    # If this succeeeds, we ignore the WITH_ICU directory.
-    PKG_CHECK_MODULES([ICU],[icu-i18n],
-        [have_libicu=yes],
-        [have_libicu=no])
-
-    if test "x$have_libicu" = "xyes"; then
-        m4_ifdef([PKG_CHECK_VAR],
-            [PKG_CHECK_VAR([ICU_DEFS], [icu-i18n], [DEFS])])
-        if test "x$ICU_DEFS" != "x"; then
-            CPPFLAGS="$CPPFLAGS $ICU_DEFS"
-        fi
-    fi
-
-    # If pkg-config failed, fall back to AC_CHECK_LIB. This
-    # will not pick up the necessary LIBS flags for liblzma's
-    # private dependencies, though, so static linking may fail.
-    if test "x$have_libicu" = "xno"; then
-        ICU_CONFIG=icu-config
-        if ${ICU_CONFIG} --cflags >/dev/null 2>&1
-        then
-            ICU_LIBS=`${ICU_CONFIG} --ldflags`
-            have_libicu=yes
-            echo Enabling ICU support
-        else
-            if test "$with_icu" != "yes" && test "$with_iconv" != "" ; then
-                CPPFLAGS="${CPPFLAGS} -I$with_icu"
-            fi
-
-            AC_CHECK_HEADER(unicode/ucnv.h,
-            AC_MSG_CHECKING(for icu)
-            AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <unicode/ucnv.h>]], [[
-        UConverter *utf = ucnv_open("UTF-8", NULL);]])],[
-                AC_MSG_RESULT(yes)
-                have_libicu=yes],[
-                AC_MSG_RESULT(no)
-                AC_MSG_CHECKING(for icu in -licucore)
-
-                _ldflags="${LDFLAGS}"
-                _libs="${LIBS}"
-                LDFLAGS="${LDFLAGS} ${ICU_LIBS}"
-                LIBS="${LIBS} -licucore"
-
-                AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <unicode/ucnv.h>]], [[
-        UConverter *utf = ucnv_open("UTF-8", NULL);]])],[
-                    AC_MSG_RESULT(yes)
-                    have_libicu=yes
-                    ICU_LIBS="${ICU_LIBS} -licucore"
-                    LIBS="${_libs}"
-                    LDFLAGS="${_ldflags}"],[
-                    AC_MSG_RESULT(no)
-                    LIBS="${_libs}"
-                LDFLAGS="${_ldflags}"])]))
-        fi
-    fi
-
-    # Found the library via either method?
-    if test "x$have_libicu" = "xyes"; then
-        WITH_ICU=1
-    fi
-fi
-XML_LIBS="-lxml2"
-XML_LIBTOOLLIBS="libxml2.la"
-AC_SUBST(WITH_ICU)
-
-WITH_ISO8859X=1
-if test "$WITH_ICONV" != "1" ; then
-if test "$with_iso8859x" = "no" ; then
+if test "$WITH_ICONV" != "1" && test "$with_iso8859x" = "no" ; then
     echo Disabling ISO8859X support
     WITH_ISO8859X=0
-fi
+else
+    WITH_ISO8859X=1
 fi
 AC_SUBST(WITH_ISO8859X)
 
 if test "$with_schemas" = "no" ; then
     echo "Disabling Schemas/Relax-NG support"
     WITH_SCHEMAS=0
-else    
-    echo "Enabled Schemas/Relax-NG support"
+else
     WITH_SCHEMAS=1
-    AS_IF([test "x$with_python" != "xno"], [
-        PYTHON_TESTS="$PYTHON_TESTS RelaxNGPythonTests SchemasPythonTests"
-    ])
-    with_regexps=yes
 fi
 AC_SUBST(WITH_SCHEMAS)
+AM_CONDITIONAL(WITH_SCHEMAS_SOURCES, test "$WITH_SCHEMAS" = "1")
 
 if test "$with_regexps" = "no" ; then
     echo Disabling Regexps support
     WITH_REGEXPS=0
-    TEST_REGEXPS=
-else    
+else
     WITH_REGEXPS=1
-    TEST_REGEXPS="Automatatests"
 fi
 AC_SUBST(WITH_REGEXPS)
-AC_SUBST(TEST_REGEXPS)
+AM_CONDITIONAL(WITH_REGEXPS_SOURCES, test "$WITH_REGEXPS" = "1")
 
 if test "$with_debug" = "no" ; then
     echo Disabling DEBUG support
     WITH_DEBUG=0
-    DEBUG_OBJ=
-    TEST_DEBUG=
-else    
+else
     WITH_DEBUG=1
-    DEBUG_OBJ=debugXML.o
-    TEST_DEBUG=Scripttests
 fi
 AC_SUBST(WITH_DEBUG)
-AC_SUBST(DEBUG_OBJ)
-AC_SUBST(TEST_DEBUG)
-
-if test "$with_mem_debug" = "yes" ; then
-    if test "$with_thread_alloc" = "yes" ; then
-        echo Disabling memory debug - cannot use mem-debug with thread-alloc!
-	WITH_MEM_DEBUG=0
-    else
-        echo Enabling memory debug support
-        WITH_MEM_DEBUG=1
+AM_CONDITIONAL(WITH_DEBUG_SOURCES, test "$WITH_DEBUG" = "1")
+
+dnl
+dnl Check for Python
+dnl
+
+AS_IF([test "x$with_python" != "xno"], [
+    AM_PATH_PYTHON
+    PKG_CHECK_MODULES([PYTHON], [python-${PYTHON_VERSION}])
+])
+AM_CONDITIONAL([WITH_PYTHON], [test "x$with_python" != "xno"])
+
+dnl
+dnl Extra Python flags for Windows
+dnl
+PYTHON_LDFLAGS=
+if test "${PYTHON}" != ""; then
+    case "$host" in
+        *-*-mingw* )
+            PYTHON_LDFLAGS="-no-undefined -shrext .pyd"
+            ;;
+        *-*-cygwin* |*-*-msys* )
+            PYTHON_LDFLAGS="-no-undefined"
+            ;;
+    esac
+fi
+AC_SUBST(PYTHON_LDFLAGS)
+
+dnl
+dnl Check for DSO support
+dnl
+WITH_MODULES=0
+
+if test "$with_modules" != "no" ; then
+    case "$host" in
+        *-*-cygwin* | *-*-msys* )
+            MODULE_EXTENSION=".dll"
+            ;;
+        *-*-mingw*)
+            MODULE_EXTENSION=".dll"
+            WITH_MODULES=1
+            ;;
+        *-*-hpux*)
+	    MODULE_EXTENSION=".sl"
+	    ;;
+        *)
+	    MODULE_EXTENSION=".so"
+	    ;;
+    esac
+
+    if test "$WITH_MODULES" = "0"; then
+        _libs=$LIBS
+        AC_SEARCH_LIBS([dlopen], [dl], [
+            WITH_MODULES=1
+            if test "$ac_cv_search_dlopen" != "none required"; then
+                MODULE_PLATFORM_LIBS=$ac_cv_search_dlopen
+            fi
+            AC_DEFINE([HAVE_DLOPEN], [], [Have dlopen based dso])], [
+            AC_SEARCH_LIBS([shl_load], [dld], [
+                WITH_MODULES=1
+                if test "$ac_cv_search_shl_load" != "none required"; then
+                    MODULE_PLATFORM_LIBS=$ac_cv_search_shl_load
+                fi
+                AC_DEFINE([HAVE_SHLLOAD], [], [Have shl_load based dso])])])
+        LIBS=$_libs
     fi
-else    
-    WITH_MEM_DEBUG=0
 fi
-AC_SUBST(WITH_MEM_DEBUG)
 
-if test "$with_run_debug" = "yes" ; then
-    echo Enabling runtime debug support
-    WITH_RUN_DEBUG=1
-else    
-    WITH_RUN_DEBUG=0
+AC_SUBST(WITH_MODULES)
+AC_SUBST(MODULE_PLATFORM_LIBS)
+AC_SUBST(MODULE_EXTENSION)
+AM_CONDITIONAL(WITH_MODULES_SOURCES, test "$WITH_MODULES" = "1")
+
+dnl
+dnl Thread-related stuff
+dnl
+THREAD_LIBS=""
+BASE_THREAD_LIBS=""
+WITH_THREADS=0
+WITH_THREAD_ALLOC=0
+
+if test "$with_threads" = "no" ; then
+    echo Disabling multithreaded support
+else
+    case $host_os in
+        *mingw*)
+            dnl Default to native threads on Windows
+            WITH_THREADS="1"
+            ;;
+        *)
+            dnl Use pthread by default in other cases
+            _libs=$LIBS
+            AC_CHECK_HEADERS(pthread.h,
+                AC_SEARCH_LIBS([pthread_create], [pthread], [
+                    WITH_THREADS="1"
+                    if test "$ac_cv_search_pthread_create" != "none required"; then
+                        THREAD_LIBS=$ac_cv_search_pthread_create
+                    fi
+                    AC_DEFINE([HAVE_PTHREAD_H], [],
+                              [Define if <pthread.h> is there])]))
+            LIBS=$_libs
+            ;;
+    esac
+
+    case $host_os in
+        *linux*)
+            if test "${GCC}" = "yes" ; then
+                BASE_THREAD_LIBS="$THREAD_LIBS"
+                THREAD_LIBS=""
+            fi
+            ;;
+    esac
+fi
+if test "$with_thread_alloc" = "yes" && test "$WITH_THREADS" = "1" ; then
+    WITH_THREAD_ALLOC=1
 fi
-AC_SUBST(WITH_RUN_DEBUG)
 
-WIN32_EXTRA_LIBADD=
-WIN32_EXTRA_LDFLAGS=
-CYGWIN_EXTRA_LDFLAGS=
-CYGWIN_EXTRA_PYTHON_LIBADD=
-WIN32_EXTRA_PYTHON_LIBADD=
-case "$host" in
- *-*-mingw*)
- CPPFLAGS="$CPPFLAGS -DWIN32"
- WIN32_EXTRA_LIBADD="-lws2_32"
- WIN32_EXTRA_LDFLAGS="-no-undefined"
- if test "${PYTHON}" != ""
- then
-   case "$host" in
-     *-w64-mingw*)
-       WIN32_EXTRA_PYTHON_LIBADD="-shrext .pyd -L${pythondir}/../../lib -lpython${PYTHON_VERSION}"
-       ;;
-     *)
-       WIN32_EXTRA_PYTHON_LIBADD="-L${pythondir}/../../libs -lpython$(echo ${PYTHON_VERSION} | tr -d .)"
-       ;;
-   esac
- fi
- ;;
- *-*-cygwin*)
- CYGWIN_EXTRA_LDFLAGS="-no-undefined"
- if test "${PYTHON}" != ""
- then
-   CYGWIN_EXTRA_PYTHON_LIBADD="-L/usr/lib/python${PYTHON_VERSION}/config -lpython${PYTHON_VERSION}"
- fi
- ;;
-esac
+AC_SUBST(THREAD_LIBS)
+AC_SUBST(BASE_THREAD_LIBS)
+AC_SUBST(WITH_THREADS)
+AC_SUBST(WITH_THREAD_ALLOC)
+
+dnl
+dnl xmllint shell history
+dnl
+if test "$with_history" = "yes" && test "$with_readline" != "no"; then
+    echo Enabling xmllint shell history
+    dnl check for terminal library. this is a very cool solution
+    dnl from octave's configure.in
+    unset tcap
+    for termlib in ncurses curses termcap terminfo termlib; do
+	AC_CHECK_LIB(${termlib}, tputs, [tcap="-l$termlib"])
+	test -n "$tcap" && break
+    done
+
+    _cppflags=$CPPFLAGS
+    _libs=$LIBS
+    if test "$with_readline" != "" && test "$with_readline" != "yes"; then
+        RDL_DIR=$with_readline
+        CPPFLAGS="${CPPFLAGS} -I$RDL_DIR/include"
+        LIBS="${LIBS} -L$RDL_DIR/lib"
+    fi
+    AC_CHECK_HEADER(readline/history.h,
+	AC_CHECK_LIB(history, append_history,[
+	    RDL_LIBS="-lhistory"
+            if test "x${RDL_DIR}" != "x"; then
+                RDL_CFLAGS="-I$RDL_DIR/include"
+                RDL_LIBS="-L$RDL_DIR/lib $RDL_LIBS"
+            fi
+	    AC_DEFINE([HAVE_LIBHISTORY], [], [Define if history library is there (-lhistory)])]))
+    AC_CHECK_HEADER(readline/readline.h,
+	AC_CHECK_LIB(readline, readline,[
+	    RDL_LIBS="-lreadline $RDL_LIBS $tcap"
+            if test "x$RDL_DIR" != "x"; then
+                RDL_CFLAGS="-I$RDL_DIR/include"
+                RDL_LIBS="-L$RDL_DIR/lib $RDL_LIBS"
+            fi
+	    AC_DEFINE([HAVE_LIBREADLINE], [], [Define if readline library is there (-lreadline)])], , $tcap))
+    CPPFLAGS=$_cppflags
+    LIBS=$_libs
+fi
+AC_SUBST(RDL_CFLAGS)
+AC_SUBST(RDL_LIBS)
+
+dnl
+dnl Checks for zlib library.
+dnl
+WITH_ZLIB=0
+
+if test "$with_zlib" != "no" && test "$with_zlib" != ""; then
+    echo "Enabling zlib compression support"
+
+    if test "$with_zlib" != "yes"; then
+        Z_DIR=$with_zlib
+    fi
 
-XML_PRIVATE_LIBS="$Z_LIBS $LZMA_LIBS $THREAD_LIBS $ICONV_LIBS $ICU_LIBS $LIBM $WIN32_EXTRA_LIBADD"
+    # Don't run pkg-config if with_zlib contains a path.
+    if test "x$Z_DIR" = "x"; then
+        # Try pkg-config first so that static linking works.
+        PKG_CHECK_MODULES([Z],[zlib],
+            [WITH_ZLIB=1; XML_PC_REQUIRES="${XML_PC_REQUIRES} zlib"],
+            [:])
+    fi
+
+    if test "$WITH_ZLIB" = "0"; then
+        _cppflags=$CPPFLAGS
+        _libs=$LIBS
+        if test "x$Z_DIR" != "x"; then
+            CPPFLAGS="${CPPFLAGS} -I$Z_DIR/include"
+            LIBS="${LIBS} -L$Z_DIR/lib"
+        fi
+        AC_CHECK_HEADERS(zlib.h,
+            AC_CHECK_LIB(z, gzread,[
+                WITH_ZLIB=1
+                if test "x${Z_DIR}" != "x"; then
+                    Z_CFLAGS="-I${Z_DIR}/include"
+                    Z_LIBS="-L${Z_DIR}/lib -lz"
+                    [case ${host} in
+                        *-*-solaris*)
+                            Z_LIBS="-L${Z_DIR}/lib -R${Z_DIR}/lib -lz"
+                            ;;
+                    esac]
+                else
+                    Z_LIBS="-lz"
+                fi])
+                XML_PC_LIBS="${XML_PC_LIBS} ${Z_LIBS}"
+            )
+        CPPFLAGS=$_cppflags
+        LIBS=$_libs
+    fi
 
-AC_SUBST(WIN32_EXTRA_LIBADD)
-AC_SUBST(WIN32_EXTRA_LDFLAGS)
-AC_SUBST(WIN32_EXTRA_PYTHON_LIBADD)
-AC_SUBST(CYGWIN_EXTRA_LDFLAGS)
-AC_SUBST(CYGWIN_EXTRA_PYTHON_LIBADD)
+    XML_PRIVATE_CFLAGS="${XML_PRIVATE_CFLAGS} ${Z_CFLAGS}"
+    XML_PRIVATE_LIBS="${XML_PRIVATE_LIBS} ${Z_LIBS}"
+fi
+AC_SUBST(WITH_ZLIB)
 
-dnl Checking the standard string functions availability
 dnl
-dnl Note mingw* has C99 implementation that produce expected xml numbers
-dnl if code use {v}snprintf functions.
-dnl If you like to activate at run-time C99 compatible number output
-dnl see release note for mingw runtime 3.15:
-dnl  http://sourceforge.net/project/shownotes.php?release_id=24832
+dnl Checks for lzma library.
 dnl
-dnl Also *win32*config.h files redefine them for various MSC compilers.
+WITH_LZMA=0
+
+if test "$with_lzma" != "no" && test "$with_lzma" != ""; then
+    echo "Enabling lzma compression support"
+
+    if test "$with_lzma" != "yes"; then
+        LZMA_DIR=$with_lzma
+    fi
+
+    # Don't run pkg-config if with_lzma contains a path.
+    if test "x$LZMA_DIR" = "x"; then
+        # Try pkg-config first so that static linking works.
+        PKG_CHECK_MODULES([LZMA],[liblzma],
+            [WITH_LZMA=1; XML_PC_REQUIRES="${XML_PC_REQUIRES} liblzma"],
+            [:])
+    fi
+
+    # If pkg-config failed, fall back to AC_CHECK_LIB. This
+    # will not pick up the necessary LIBS flags for liblzma's
+    # private dependencies, though, so static linking may fail.
+    if test "$WITH_LZMA" = "0"; then
+        _cppflags=$CPPFLAGS
+        _libs=$LIBS
+        if test "x$LZMA_DIR" != "x"; then
+            CPPFLAGS="${CPPFLAGS} -I$LZMA_DIR/include"
+            LIBS="${LIBS} -L$LZMA_DIR/lib"
+        fi
+        AC_CHECK_HEADERS(lzma.h,
+            AC_CHECK_LIB(lzma, lzma_code,[
+                WITH_LZMA=1
+                if test "x${LZMA_DIR}" != "x"; then
+                    LZMA_CFLAGS="-I${LZMA_DIR}/include"
+                    LZMA_LIBS="-L${LZMA_DIR}/lib -llzma"
+                else
+                    LZMA_LIBS="-llzma"
+                fi])
+                XML_PC_LIBS="${XML_PC_LIBS} ${LZMA_LIBS}"
+            )
+        CPPFLAGS=$_cppflags
+        LIBS=$_libs
+    fi
+
+    XML_PRIVATE_CFLAGS="${XML_PRIVATE_CFLAGS} ${LZMA_CFLAGS}"
+    XML_PRIVATE_LIBS="${XML_PRIVATE_LIBS} ${LZMA_LIBS}"
+fi
+AC_SUBST(WITH_LZMA)
+AM_CONDITIONAL(WITH_LZMA_SOURCES, test "$WITH_LZMA" = "1")
+
 dnl
-dnl So do not redefine {v}snprintf to _{v}snprintf like following:
-dnl  AC_DEFINE([snprintf],[_snprintf],[Win32 Std C name mangling work-around])
-dnl  AC_DEFINE([vsnprintf],[_vsnprintf],[Win32 Std C name mangling work-around])
-dnl and do not redefine those functions is C-source files.
+dnl Checks for iconv library.
 dnl
-AC_CHECK_FUNCS(snprintf vsnprintf,,
-	NEED_TRIO=1)
-
-if test "$with_coverage" = "yes" && test "${GCC}" = "yes"
-then
-    echo Enabling code coverage for GCC
-    EXTRA_CFLAGS="$EXTRA_CFLAGS -fprofile-arcs -ftest-coverage"
-    LDFLAGS="$LDFLAGS -fprofile-arcs -ftest-coverage"
+WITH_ICONV=0
+
+if test "$with_iconv" = "no" ; then
+    echo Disabling ICONV support
 else
-    echo Disabling code coverage for GCC
+    _cppflags=$CPPFLAGS
+    _libs=$LIBS
+    if test "$with_iconv" != "yes" && test "$with_iconv" != "" ; then
+	ICONV_DIR=$with_iconv
+	CPPFLAGS="$CPPFLAGS -I$ICONV_DIR/include"
+	LIBS="$LIBS -L$ICONV_DIR/lib"
+    fi
+    AC_MSG_CHECKING([for libiconv])
+    AC_LINK_IFELSE([
+        AC_LANG_PROGRAM([#include <iconv.h>], [iconv_open(0,0);])
+    ], [
+        WITH_ICONV=1
+        AC_MSG_RESULT([none required])
+    ], [
+        LIBS="$LIBS -liconv"
+        AC_LINK_IFELSE([
+            AC_LANG_PROGRAM([#include <iconv.h>], [iconv_open(0,0);])
+        ], [
+            WITH_ICONV=1
+            ICONV_LIBS="-liconv"
+            AC_MSG_RESULT([yes])
+        ], [
+            AC_MSG_RESULT([no])
+        ])
+    ])
+    if test "$WITH_ICONV" = "1" && test "$ICONV_DIR" != ""; then
+        ICONV_CFLAGS="-I$ICONV_DIR/include"
+        ICONV_LIBS="-L$ICONV_DIR/lib $ICONV_LIBS"
+	# Export this since our headers include iconv.h
+	XML_INCLUDEDIR="$XML_INCLUDEDIR -I$ICONV_DIR/include"
+    fi
+    CPPFLAGS=$_cppflags
+    LIBS=$_libs
 fi
+AC_SUBST(WITH_ICONV)
+AC_SUBST(ICONV_CFLAGS)
+
+dnl
+dnl Checks for ICU library.
+dnl
+WITH_ICU=0
+
+if test "$with_icu" != "no" && test "$with_icu" != "" ; then
+    echo Enabling ICU support
 
-AC_SUBST(EXTRA_CFLAGS)
+    # Try pkg-config first so that static linking works.
+    # If this succeeeds, we ignore the WITH_ICU directory.
+    PKG_CHECK_MODULES([ICU], [icu-i18n], [
+        WITH_ICU=1; XML_PC_REQUIRES="${XML_PC_REQUIRES} icu-i18n"
+        m4_ifdef([PKG_CHECK_VAR],
+            [PKG_CHECK_VAR([ICU_DEFS], [icu-i18n], [DEFS])])
+        if test "x$ICU_DEFS" != "x"; then
+            ICU_CFLAGS="$ICU_CFLAGS $ICU_DEFS"
+        fi],[:])
+
+    if test "$WITH_ICU" = "0"; then
+        ICU_CONFIG=icu-config
+        if ${ICU_CONFIG} --cflags >/dev/null 2>&1
+        then
+            WITH_ICU=1
+            ICU_CFLAGS=`${ICU_CONFIG} --cflags`
+            ICU_LIBS=`${ICU_CONFIG} --ldflags`
+            XML_PC_LIBS="${XML_PC_LIBS} ${ICU_LIBS}"
+        else
+            _cppflags="${CPPFLAGS}"
+            _libs="${LIBS}"
+            if test "$with_icu" != "yes" ; then
+                ICU_DIR=$with_icu
+                CPPFLAGS="${CPPFLAGS} -I$ICU_DIR/include"
+                LIBS="${LIBS} -L$ICU_DIR/lib"
+            fi
+
+            AC_CHECK_HEADER(unicode/ucnv.h, [
+                AC_CHECK_LIB([icucore], [ucnv_open], [
+                    WITH_ICU=1
+                    ICU_LIBS=-licucore
+                    if test "$ICU_DIR" != ""; then
+                        ICU_CFLAGS="-I$ICU_DIR/include"
+                        ICU_LIBS="-L$ICU_DIR/lib $ICU_LIBS"
+                    fi])])
+                    XML_PC_LIBS="${XML_PC_LIBS} ${ICU_LIBS}"
+            CPPFLAGS=$_cppflags
+            LIBS=$_libs
+        fi
+    fi
+
+    XML_PRIVATE_CFLAGS="${XML_PRIVATE_CFLAGS} ${ICU_CFLAGS}"
+    XML_PRIVATE_LIBS="${XML_PRIVATE_LIBS} ${ICU_LIBS}"
+fi
+AC_SUBST(WITH_ICU)
+
+dnl
+dnl Crypto libraries
+dnl
+case "$host" in
+    *-*-mingw*)
+        CRYPTO_LIBS="-lbcrypt"
+        ;;
+esac
+
+XML_LIBS="-lxml2"
+XML_LIBTOOLLIBS="libxml2.la"
+NON_PC_LIBS="${THREAD_LIBS} ${ICONV_LIBS} ${LIBM} ${NET_LIBS} ${CRYPTO_LIBS}"
+XML_PC_LIBS="${XML_PC_LIBS} ${NON_PC_LIBS}"
+XML_PRIVATE_LIBS="${XML_PRIVATE_LIBS} ${NON_PC_LIBS}"
+XML_PRIVATE_CFLAGS="${XML_PRIVATE_CFLAGS} ${ICONV_CFLAGS}"
+
+dnl When static-only:
+dnl * Duplicate xml-config static --libs into --dynamic.
+dnl * Fold pkg-config private fields into main fields.
+if test "x$enable_shared" = "xno"; then
+  XML_PRIVATE_LIBS_NO_SHARED="${XML_PRIVATE_LIBS}"
+  XML_PC_PRIVATE=
+  XML_PC_LIBS_PRIVATE=
+else
+  XML_PRIVATE_LIBS_NO_SHARED=
+  XML_PC_PRIVATE=".private"
+  XML_PC_LIBS_PRIVATE="
+Libs.private:"
+fi
+AC_SUBST(XML_PRIVATE_LIBS_NO_SHARED)
+AC_SUBST(XML_PC_PRIVATE)
+AC_SUBST(XML_PC_LIBS_PRIVATE)
+AM_SUBST_NOTMAKE(XML_PRIVATE_LIBS_NO_SHARED)
+AM_SUBST_NOTMAKE(XML_PC_PRIVATE)
+AM_SUBST_NOTMAKE(XML_PC_LIBS_PRIVATE)
+
+AC_SUBST(XML_PC_LIBS)
+AC_SUBST(XML_PC_REQUIRES)
+AM_SUBST_NOTMAKE(XML_PC_LIBS)
+AM_SUBST_NOTMAKE(XML_PC_REQUIRES)
+
+AC_SUBST(AM_CFLAGS)
+AC_SUBST(AM_LDFLAGS)
 AC_SUBST(XML_CFLAGS)
 
 AC_SUBST(XML_LIBDIR)
 AC_SUBST(XML_LIBS)
 AC_SUBST(XML_PRIVATE_LIBS)
+AC_SUBST(XML_PRIVATE_CFLAGS)
 AC_SUBST(XML_LIBTOOLLIBS)
-AC_SUBST(ICONV_LIBS)
-AC_SUBST(ICU_LIBS)
 AC_SUBST(XML_INCLUDEDIR)
 
-AC_SUBST(RDL_LIBS)
-
 dnl for the spec file
 RELDATE=`date +'%a %b %e %Y'`
 AC_SUBST(RELDATE)
-AC_SUBST(PYTHON_TESTS)
 
 # keep on one line for cygwin c.f. #130896
-AC_CONFIG_FILES([libxml2.spec:libxml.spec.in Makefile include/Makefile include/libxml/Makefile doc/Makefile doc/examples/Makefile doc/devhelp/Makefile example/Makefile fuzz/Makefile python/Makefile python/tests/Makefile xstc/Makefile include/libxml/xmlversion.h libxml-2.0.pc libxml-2.0-uninstalled.pc libxml2-config.cmake])
+AC_CONFIG_FILES([Makefile include/Makefile include/libxml/Makefile include/private/Makefile doc/Makefile doc/devhelp/Makefile example/Makefile fuzz/Makefile python/Makefile python/tests/Makefile xstc/Makefile include/libxml/xmlversion.h libxml-2.0.pc libxml-2.0-uninstalled.pc libxml2-config.cmake])
 AC_CONFIG_FILES([python/setup.py], [chmod +x python/setup.py])
 AC_CONFIG_FILES([xml2-config], [chmod +x xml2-config])
 AC_OUTPUT
 
-echo Done configuring
+if test "$WARN_NO_TLS" != ""; then
+    echo "================================================================"
+    echo "WARNING: Your C compiler appears to not support thread-local"
+    echo "storage. Future versions of libxml2 will require this feature"
+    echo "for multi-threading."
+    echo "================================================================"
+fi
diff --git a/debugXML.c b/debugXML.c
index f451c9d5c41ac778fdce8cd8b81381f90f8dfdb9..ed56b0f882ae22a76b5e57031b9096d8679576d9 100644
--- a/debugXML.c
+++ b/debugXML.c
@@ -18,18 +18,18 @@
 #include <libxml/tree.h>
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
-#include <libxml/valid.h>
 #include <libxml/debugXML.h>
 #include <libxml/HTMLtree.h>
 #include <libxml/HTMLparser.h>
 #include <libxml/xmlerror.h>
-#include <libxml/globals.h>
 #include <libxml/xpathInternals.h>
 #include <libxml/uri.h>
 #ifdef LIBXML_SCHEMAS_ENABLED
 #include <libxml/relaxng.h>
 #endif
 
+#include "private/error.h"
+
 #define DUMP_TEXT_TYPE 1
 
 typedef struct _xmlDebugCtxt xmlDebugCtxt;
@@ -154,31 +154,21 @@ static void
 xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
 {
     ctxt->errors++;
-    __xmlRaiseError(NULL, NULL, NULL,
-		    NULL, ctxt->node, XML_FROM_CHECK,
-		    error, XML_ERR_ERROR, NULL, 0,
-		    NULL, NULL, NULL, 0, 0,
-		    "%s", msg);
+    fprintf(ctxt->output, "ERROR %d: %s", error, msg);
 }
 static void LIBXML_ATTR_FORMAT(3,0)
 xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
 {
     ctxt->errors++;
-    __xmlRaiseError(NULL, NULL, NULL,
-		    NULL, ctxt->node, XML_FROM_CHECK,
-		    error, XML_ERR_ERROR, NULL, 0,
-		    NULL, NULL, NULL, 0, 0,
-		    msg, extra);
+    fprintf(ctxt->output, "ERROR %d: ", error);
+    fprintf(ctxt->output, msg, extra);
 }
 static void LIBXML_ATTR_FORMAT(3,0)
 xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
 {
     ctxt->errors++;
-    __xmlRaiseError(NULL, NULL, NULL,
-		    NULL, ctxt->node, XML_FROM_CHECK,
-		    error, XML_ERR_ERROR, NULL, 0,
-		    NULL, NULL, NULL, 0, 0,
-		    msg, extra);
+    fprintf(ctxt->output, "ERROR %d: ", error);
+    fprintf(ctxt->output, msg, extra);
 }
 
 /**
@@ -1824,47 +1814,47 @@ xmlShellPrintXPathError(int errorType, const char *arg)
 
     switch (errorType) {
         case XPATH_UNDEFINED:
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "%s: no such node\n", arg);
             break;
 
         case XPATH_BOOLEAN:
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "%s is a Boolean\n", arg);
             break;
         case XPATH_NUMBER:
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "%s is a number\n", arg);
             break;
         case XPATH_STRING:
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "%s is a string\n", arg);
             break;
 #ifdef LIBXML_XPTR_LOCS_ENABLED
         case XPATH_POINT:
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "%s is a point\n", arg);
             break;
         case XPATH_RANGE:
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "%s is a range\n", arg);
             break;
         case XPATH_LOCATIONSET:
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "%s is a range\n", arg);
             break;
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
         case XPATH_USERS:
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "%s is user-defined\n", arg);
             break;
         case XPATH_XSLT_TREE:
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(stderr,
                             "%s is an XSLT value tree\n", arg);
             break;
     }
 #if 0
-    xmlGenericError(xmlGenericErrorContext,
+    fprintf(stderr,
                     "Try casting the result string function (xpath builtin)\n",
                     arg);
 #endif
@@ -1940,26 +1930,26 @@ xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
 				    list->nodesetval->nodeTab[indx]);
                         }
                     } else {
-                        xmlGenericError(xmlGenericErrorContext,
+                        fprintf(ctxt->output,
                                         "Empty node set\n");
                     }
                     break;
 #else
-		    xmlGenericError(xmlGenericErrorContext,
+		    fprintf(ctxt->output,
 				    "Node set\n");
 #endif /* LIBXML_OUTPUT_ENABLED */
                 }
             case XPATH_BOOLEAN:
-                xmlGenericError(xmlGenericErrorContext,
+                fprintf(ctxt->output,
                                 "Is a Boolean:%s\n",
                                 xmlBoolToText(list->boolval));
                 break;
             case XPATH_NUMBER:
-                xmlGenericError(xmlGenericErrorContext,
+                fprintf(ctxt->output,
                                 "Is a number:%0g\n", list->floatval);
                 break;
             case XPATH_STRING:
-                xmlGenericError(xmlGenericErrorContext,
+                fprintf(ctxt->output,
                                 "Is a string:%s\n", list->stringval);
                 break;
 
@@ -2331,6 +2321,16 @@ xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
     return (0);
 }
 
+static void
+xmlShellPrintf(void *ctx, const char *msg, ...) {
+    xmlShellCtxtPtr sctxt = ctx;
+    va_list ap;
+
+    va_start(ap, msg);
+    vfprintf(sctxt->output, msg, ap);
+    va_end(ap);
+}
+
 #ifdef LIBXML_SCHEMAS_ENABLED
 /**
  * xmlShellRNGValidate:
@@ -2355,23 +2355,23 @@ xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
     int ret;
 
     ctxt = xmlRelaxNGNewParserCtxt(schemas);
-    xmlRelaxNGSetParserErrors(ctxt, xmlGenericError, xmlGenericError, NULL);
+    xmlRelaxNGSetParserErrors(ctxt, xmlShellPrintf, xmlShellPrintf, sctxt);
     relaxngschemas = xmlRelaxNGParse(ctxt);
     xmlRelaxNGFreeParserCtxt(ctxt);
     if (relaxngschemas == NULL) {
-	xmlGenericError(xmlGenericErrorContext,
+	fprintf(sctxt->output,
 		"Relax-NG schema %s failed to compile\n", schemas);
 	return(-1);
     }
     vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
-    xmlRelaxNGSetValidErrors(vctxt, xmlGenericError, xmlGenericError, NULL);
+    xmlRelaxNGSetValidErrors(vctxt, xmlShellPrintf, xmlShellPrintf, sctxt);
     ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
     if (ret == 0) {
-	fprintf(stderr, "%s validates\n", sctxt->filename);
+	fprintf(sctxt->output, "%s validates\n", sctxt->filename);
     } else if (ret > 0) {
-	fprintf(stderr, "%s fails to validate\n", sctxt->filename);
+	fprintf(sctxt->output, "%s fails to validate\n", sctxt->filename);
     } else {
-	fprintf(stderr, "%s validation generated an internal error\n",
+	fprintf(sctxt->output, "%s validation generated an internal error\n",
 	       sctxt->filename);
     }
     xmlRelaxNGFreeValidCtxt(vctxt);
@@ -2506,7 +2506,7 @@ xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
     }
 #ifdef W_OK
     if (access((char *) filename, W_OK)) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(ctxt->output,
                         "Cannot write to %s\n", filename);
         return (-1);
     }
@@ -2514,7 +2514,7 @@ xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
     switch (node->type) {
         case XML_DOCUMENT_NODE:
             if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
-                xmlGenericError(xmlGenericErrorContext,
+                fprintf(ctxt->output,
                                 "Failed to write to %s\n", filename);
                 return (-1);
             }
@@ -2522,13 +2522,13 @@ xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
         case XML_HTML_DOCUMENT_NODE:
 #ifdef LIBXML_HTML_ENABLED
             if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
-                xmlGenericError(xmlGenericErrorContext,
+                fprintf(ctxt->output,
                                 "Failed to write to %s\n", filename);
                 return (-1);
             }
 #else
             if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
-                xmlGenericError(xmlGenericErrorContext,
+                fprintf(ctxt->output,
                                 "Failed to write to %s\n", filename);
                 return (-1);
             }
@@ -2539,7 +2539,7 @@ xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
 
                 f = fopen((char *) filename, "w");
                 if (f == NULL) {
-                    xmlGenericError(xmlGenericErrorContext,
+                    fprintf(ctxt->output,
                                     "Failed to write to %s\n", filename);
                     return (-1);
                 }
@@ -2575,7 +2575,7 @@ xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
         return (-1);
 #ifdef W_OK
     if (access((char *) filename, W_OK)) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(ctxt->output,
                         "Cannot save to %s\n", filename);
         return (-1);
     }
@@ -2583,25 +2583,25 @@ xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
     switch (ctxt->doc->type) {
         case XML_DOCUMENT_NODE:
             if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
-                xmlGenericError(xmlGenericErrorContext,
+                fprintf(ctxt->output,
                                 "Failed to save to %s\n", filename);
             }
             break;
         case XML_HTML_DOCUMENT_NODE:
 #ifdef LIBXML_HTML_ENABLED
             if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
-                xmlGenericError(xmlGenericErrorContext,
+                fprintf(ctxt->output,
                                 "Failed to save to %s\n", filename);
             }
 #else
             if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
-                xmlGenericError(xmlGenericErrorContext,
+                fprintf(ctxt->output,
                                 "Failed to save to %s\n", filename);
             }
 #endif /* LIBXML_HTML_ENABLED */
             break;
         default:
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(ctxt->output,
 	    "To save to subparts of a document use the 'write' command\n");
             return (-1);
 
@@ -2633,9 +2633,10 @@ xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
     int res = -1;
 
     if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1);
-    vctxt.userData = NULL;
-    vctxt.error = xmlGenericError;
-    vctxt.warning = xmlGenericError;
+    memset(&vctxt, 0, sizeof(vctxt));
+    vctxt.error = xmlShellPrintf;
+    vctxt.warning = xmlShellPrintf;
+    vctxt.userData = ctxt;
 
     if ((dtd == NULL) || (dtd[0] == 0)) {
         res = xmlValidateDocument(&vctxt, ctxt->doc);
@@ -2791,7 +2792,7 @@ xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
  * using a environment similar to a UNIX commandline.
  */
 void
-xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
+xmlShell(xmlDocPtr doc, const char *filename, xmlShellReadlineFunc input,
          FILE * output)
 {
     char prompt[500] = "/ > ";
@@ -2936,22 +2937,13 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
             xmlShellSave(ctxt, arg, NULL, NULL);
         } else if (!strcmp(command, "write")) {
 	    if (arg[0] == 0)
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(ctxt->output,
                         "Write command requires a filename argument\n");
 	    else
 		xmlShellWrite(ctxt, arg, ctxt->node, NULL);
 #endif /* LIBXML_OUTPUT_ENABLED */
         } else if (!strcmp(command, "grep")) {
             xmlShellGrep(ctxt, arg, ctxt->node, NULL);
-        } else if (!strcmp(command, "free")) {
-            if (arg[0] == 0) {
-                xmlMemShow(ctxt->output, 0);
-            } else {
-                int len = 0;
-
-                sscanf(arg, "%d", &len);
-                xmlMemShow(ctxt->output, len);
-            }
         } else if (!strcmp(command, "pwd")) {
             char dir[500];
 
@@ -2971,7 +2963,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                 if (list != NULL) {
                     switch (list->type) {
                         case XPATH_UNDEFINED:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s: no such node\n", arg);
                             break;
                         case XPATH_NODESET:{
@@ -2989,37 +2981,37 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                             break;
                         }
                         case XPATH_BOOLEAN:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a Boolean\n", arg);
                             break;
                         case XPATH_NUMBER:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a number\n", arg);
                             break;
                         case XPATH_STRING:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a string\n", arg);
                             break;
 #ifdef LIBXML_XPTR_LOCS_ENABLED
                         case XPATH_POINT:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a point\n", arg);
                             break;
                         case XPATH_RANGE:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a range\n", arg);
                             break;
                         case XPATH_LOCATIONSET:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a range\n", arg);
                             break;
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
                         case XPATH_USERS:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is user-defined\n", arg);
                             break;
                         case XPATH_XSLT_TREE:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is an XSLT value tree\n",
                                             arg);
                             break;
@@ -3028,7 +3020,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                     xmlXPathFreeObject(list);
 #endif
                 } else {
-                    xmlGenericError(xmlGenericErrorContext,
+                    fprintf(ctxt->output,
                                     "%s: no such node\n", arg);
                 }
                 ctxt->pctxt->node = NULL;
@@ -3040,7 +3032,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
 #ifdef LIBXML_XPATH_ENABLED
         } else if (!strcmp(command, "setns")) {
             if (arg[0] == 0) {
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(ctxt->output,
 				"setns: prefix=[nsuri] required\n");
             } else {
                 xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
@@ -3052,7 +3044,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
 	    xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL);
         } else if (!strcmp(command, "xpath")) {
             if (arg[0] == 0) {
-		xmlGenericError(xmlGenericErrorContext,
+		fprintf(ctxt->output,
 				"xpath: expression required\n");
 	    } else {
                 ctxt->pctxt->node = ctxt->node;
@@ -3084,7 +3076,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                 if (list != NULL) {
                     switch (list->type) {
                         case XPATH_UNDEFINED:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s: no such node\n", arg);
                             break;
                         case XPATH_NODESET:{
@@ -3108,37 +3100,37 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                                 break;
                             }
                         case XPATH_BOOLEAN:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a Boolean\n", arg);
                             break;
                         case XPATH_NUMBER:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a number\n", arg);
                             break;
                         case XPATH_STRING:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a string\n", arg);
                             break;
 #ifdef LIBXML_XPTR_LOCS_ENABLED
                         case XPATH_POINT:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a point\n", arg);
                             break;
                         case XPATH_RANGE:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a range\n", arg);
                             break;
                         case XPATH_LOCATIONSET:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a range\n", arg);
                             break;
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
                         case XPATH_USERS:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is user-defined\n", arg);
                             break;
                         case XPATH_XSLT_TREE:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is an XSLT value tree\n",
                                             arg);
                             break;
@@ -3147,7 +3139,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                     xmlXPathFreeObject(list);
 #endif
                 } else {
-                    xmlGenericError(xmlGenericErrorContext,
+                    fprintf(ctxt->output,
                                     "%s: no such node\n", arg);
                 }
                 ctxt->pctxt->node = NULL;
@@ -3168,7 +3160,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                 if (list != NULL) {
                     switch (list->type) {
                         case XPATH_UNDEFINED:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s: no such node\n", arg);
                             break;
                         case XPATH_NODESET:{
@@ -3187,37 +3179,37 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                                 break;
                             }
                         case XPATH_BOOLEAN:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a Boolean\n", arg);
                             break;
                         case XPATH_NUMBER:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a number\n", arg);
                             break;
                         case XPATH_STRING:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a string\n", arg);
                             break;
 #ifdef LIBXML_XPTR_LOCS_ENABLED
                         case XPATH_POINT:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a point\n", arg);
                             break;
                         case XPATH_RANGE:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a range\n", arg);
                             break;
                         case XPATH_LOCATIONSET:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a range\n", arg);
                             break;
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
                         case XPATH_USERS:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is user-defined\n", arg);
                             break;
                         case XPATH_XSLT_TREE:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is an XSLT value tree\n",
                                             arg);
                             break;
@@ -3226,7 +3218,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                     xmlXPathFreeObject(list);
 #endif
                 } else {
-                    xmlGenericError(xmlGenericErrorContext,
+                    fprintf(ctxt->output,
                                     "%s: no such node\n", arg);
                 }
                 ctxt->pctxt->node = NULL;
@@ -3249,7 +3241,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                 if (list != NULL) {
                     switch (list->type) {
                         case XPATH_UNDEFINED:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s: no such node\n", arg);
                             break;
                         case XPATH_NODESET:
@@ -3259,52 +3251,52 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
 				    if ((ctxt->node != NULL) &&
 				        (ctxt->node->type ==
 					 XML_NAMESPACE_DECL)) {
-					xmlGenericError(xmlGenericErrorContext,
+					fprintf(ctxt->output,
 						    "cannot cd to namespace\n");
 					ctxt->node = NULL;
 				    }
 				} else
-				    xmlGenericError(xmlGenericErrorContext,
+				    fprintf(ctxt->output,
 						    "%s is a %d Node Set\n",
 						    arg,
 						    list->nodesetval->nodeNr);
                             } else
-                                xmlGenericError(xmlGenericErrorContext,
+                                fprintf(ctxt->output,
                                                 "%s is an empty Node Set\n",
                                                 arg);
                             break;
                         case XPATH_BOOLEAN:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a Boolean\n", arg);
                             break;
                         case XPATH_NUMBER:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a number\n", arg);
                             break;
                         case XPATH_STRING:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a string\n", arg);
                             break;
 #ifdef LIBXML_XPTR_LOCS_ENABLED
                         case XPATH_POINT:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a point\n", arg);
                             break;
                         case XPATH_RANGE:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a range\n", arg);
                             break;
                         case XPATH_LOCATIONSET:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a range\n", arg);
                             break;
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
                         case XPATH_USERS:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is user-defined\n", arg);
                             break;
                         case XPATH_XSLT_TREE:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is an XSLT value tree\n",
                                             arg);
                             break;
@@ -3313,7 +3305,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                     xmlXPathFreeObject(list);
 #endif
                 } else {
-                    xmlGenericError(xmlGenericErrorContext,
+                    fprintf(ctxt->output,
                                     "%s: no such node\n", arg);
                 }
                 ctxt->pctxt->node = NULL;
@@ -3333,7 +3325,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                 if (list != NULL) {
                     switch (list->type) {
                         case XPATH_UNDEFINED:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s: no such node\n", arg);
                             break;
                         case XPATH_NODESET:{
@@ -3354,37 +3346,37 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                                 break;
                             }
                         case XPATH_BOOLEAN:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a Boolean\n", arg);
                             break;
                         case XPATH_NUMBER:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a number\n", arg);
                             break;
                         case XPATH_STRING:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a string\n", arg);
                             break;
 #ifdef LIBXML_XPTR_LOCS_ENABLED
                         case XPATH_POINT:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a point\n", arg);
                             break;
                         case XPATH_RANGE:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a range\n", arg);
                             break;
                         case XPATH_LOCATIONSET:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is a range\n", arg);
                             break;
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
                         case XPATH_USERS:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is user-defined\n", arg);
                             break;
                         case XPATH_XSLT_TREE:
-                            xmlGenericError(xmlGenericErrorContext,
+                            fprintf(ctxt->output,
                                             "%s is an XSLT value tree\n",
                                             arg);
                             break;
@@ -3393,14 +3385,14 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                     xmlXPathFreeObject(list);
 #endif
                 } else {
-                    xmlGenericError(xmlGenericErrorContext,
+                    fprintf(ctxt->output,
                                     "%s: no such node\n", arg);
                 }
                 ctxt->pctxt->node = NULL;
             }
 #endif /* LIBXML_OUTPUT_ENABLED */
         } else {
-            xmlGenericError(xmlGenericErrorContext,
+            fprintf(ctxt->output,
                             "Unknown command %s\n", command);
         }
         free(cmdline);          /* not xmlFree here ! */
diff --git a/dict.c b/dict.c
index c29d2af77a771d22758904f5b9247defc7fc6c18..49e1c6bf760d9136ba0275728c5ee80142c33a2c 100644
--- a/dict.c
+++ b/dict.c
@@ -19,81 +19,28 @@
 #define IN_LIBXML
 #include "libxml.h"
 
+#include <errno.h>
 #include <limits.h>
 #include <stdlib.h>
-#include <time.h>
+#include <string.h>
 
-/*
- * Following http://www.ocert.org/advisories/ocert-2011-003.html
- * it seems that having hash randomization might be a good idea
- * when using XML with untrusted data
- * Note1: that it works correctly only if compiled with WITH_BIG_KEY
- *  which is the default.
- * Note2: the fast function used for a small dict won't protect very
- *  well but since the attack is based on growing a very big hash
- *  list we will use the BigKey algo as soon as the hash size grows
- *  over MIN_DICT_SIZE so this actually works
- */
-#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
-#define DICT_RANDOMIZATION
-#endif
+#include "private/dict.h"
+#include "private/globals.h"
+#include "private/threads.h"
 
-#include <string.h>
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#else
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#elif defined(_WIN32)
-typedef unsigned __int32 uint32_t;
-#endif
-#endif
-#include <libxml/tree.h>
+#include <libxml/parser.h>
 #include <libxml/dict.h>
 #include <libxml/xmlmemory.h>
-#include <libxml/xmlerror.h>
-#include <libxml/globals.h>
-
-/* #define DEBUG_GROW */
-/* #define DICT_DEBUG_PATTERNS */
-
-#define MAX_HASH_LEN 3
-#define MIN_DICT_SIZE 128
-#define MAX_DICT_HASH 8 * 2048
-#define WITH_BIG_KEY
-
-#ifdef WITH_BIG_KEY
-#define xmlDictComputeKey(dict, name, len)                              \
-    (((dict)->size == MIN_DICT_SIZE) ?                                  \
-     xmlDictComputeFastKey(name, len, (dict)->seed) :                   \
-     xmlDictComputeBigKey(name, len, (dict)->seed))
-
-#define xmlDictComputeQKey(dict, prefix, plen, name, len)               \
-    (((prefix) == NULL) ?                                               \
-      (xmlDictComputeKey(dict, name, len)) :                             \
-      (((dict)->size == MIN_DICT_SIZE) ?                                \
-       xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) :	\
-       xmlDictComputeBigQKey(prefix, plen, name, len, (dict)->seed)))
-
-#else /* !WITH_BIG_KEY */
-#define xmlDictComputeKey(dict, name, len)                              \
-        xmlDictComputeFastKey(name, len, (dict)->seed)
-#define xmlDictComputeQKey(dict, prefix, plen, name, len)               \
-        xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed)
-#endif /* WITH_BIG_KEY */
+#include <libxml/xmlstring.h>
 
-/*
- * An entry in the dictionary
- */
-typedef struct _xmlDictEntry xmlDictEntry;
-typedef xmlDictEntry *xmlDictEntryPtr;
-struct _xmlDictEntry {
-    struct _xmlDictEntry *next;
-    const xmlChar *name;
-    unsigned int len;
-    int valid;
-    unsigned long okey;
-};
+#ifndef SIZE_MAX
+  #define SIZE_MAX ((size_t) -1)
+#endif
+
+#define MAX_FILL_NUM 7
+#define MAX_FILL_DENOM 8
+#define MIN_HASH_SIZE 8
+#define MAX_HASH_SIZE (1u << 31)
 
 typedef struct _xmlDictStrings xmlDictStrings;
 typedef xmlDictStrings *xmlDictStringsPtr;
@@ -105,20 +52,23 @@ struct _xmlDictStrings {
     size_t nbStrings;
     xmlChar array[1];
 };
+
+typedef xmlHashedString xmlDictEntry;
+
 /*
  * The entire dictionary
  */
 struct _xmlDict {
     int ref_counter;
 
-    struct _xmlDictEntry *dict;
+    xmlDictEntry *table;
     size_t size;
     unsigned int nbElems;
     xmlDictStringsPtr strings;
 
     struct _xmlDict *subdict;
     /* used for randomization */
-    int seed;
+    unsigned seed;
     /* used to impose a limit on size */
     size_t limit;
 };
@@ -127,107 +77,51 @@ struct _xmlDict {
  * A mutex for modifying the reference counter for shared
  * dictionaries.
  */
-static xmlMutexPtr xmlDictMutex = NULL;
-
-/*
- * Whether the dictionary mutex was initialized.
- */
-static int xmlDictInitialized = 0;
-
-#ifdef DICT_RANDOMIZATION
-#ifdef HAVE_RAND_R
-/*
- * Internal data for random function, protected by xmlDictMutex
- */
-static unsigned int rand_seed = 0;
-#endif
-#endif
+static xmlMutex xmlDictMutex;
 
 /**
  * xmlInitializeDict:
  *
- * DEPRECATED: This function will be made private. Call xmlInitParser to
- * initialize the library.
- *
- * Do the dictionary mutex initialization.
+ * DEPRECATED: Alias for xmlInitParser.
  *
- * Returns 0 if initialization was already done, and 1 if that
- * call led to the initialization
+ * Returns 0.
  */
-int xmlInitializeDict(void) {
+int
+xmlInitializeDict(void) {
+    xmlInitParser();
     return(0);
 }
 
 /**
- * __xmlInitializeDict:
- *
- * This function is not public
- * Do the dictionary mutex initialization.
- * this function is not thread safe, initialization should
- * normally be done once at setup when called from xmlOnceInit()
- * we may also land in this code if thread support is not compiled in
+ * xmlInitDictInternal:
  *
- * Returns 0 if initialization was already done, and 1 if that
- * call led to the initialization
+ * Initialize mutex.
  */
-int __xmlInitializeDict(void) {
-    if (xmlDictInitialized)
-        return(1);
-
-    if ((xmlDictMutex = xmlNewMutex()) == NULL)
-        return(0);
-    xmlMutexLock(xmlDictMutex);
-
-#ifdef DICT_RANDOMIZATION
-#ifdef HAVE_RAND_R
-    rand_seed = time(NULL);
-    rand_r(& rand_seed);
-#else
-    srand(time(NULL));
-#endif
-#endif
-    xmlDictInitialized = 1;
-    xmlMutexUnlock(xmlDictMutex);
-    return(1);
-}
-
-#ifdef DICT_RANDOMIZATION
-int __xmlRandom(void) {
-    int ret;
-
-    if (xmlDictInitialized == 0)
-        __xmlInitializeDict();
-
-    xmlMutexLock(xmlDictMutex);
-#ifdef HAVE_RAND_R
-    ret = rand_r(& rand_seed);
-#else
-    ret = rand();
-#endif
-    xmlMutexUnlock(xmlDictMutex);
-    return(ret);
+void
+xmlInitDictInternal(void) {
+    xmlInitMutex(&xmlDictMutex);
 }
-#endif
 
 /**
  * xmlDictCleanup:
  *
- * DEPRECATED: This function will be made private. Call xmlCleanupParser
+ * DEPRECATED: This function is a no-op. Call xmlCleanupParser
  * to free global state but see the warnings there. xmlCleanupParser
  * should be only called once at program exit. In most cases, you don't
  * have call cleanup functions at all.
- *
- * Free the dictionary mutex. Do not call unless sure the library
- * is not in use anymore !
  */
 void
 xmlDictCleanup(void) {
-    if (!xmlDictInitialized)
-        return;
-
-    xmlFreeMutex(xmlDictMutex);
+}
 
-    xmlDictInitialized = 0;
+/**
+ * xmlCleanupDictInternal:
+ *
+ * Free the dictionary mutex.
+ */
+void
+xmlCleanupDictInternal(void) {
+    xmlCleanupMutex(&xmlDictMutex);
 }
 
 /*
@@ -247,9 +141,6 @@ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) {
     size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
     size_t limit = 0;
 
-#ifdef DICT_DEBUG_PATTERNS
-    fprintf(stderr, "-");
-#endif
     pool = dict->strings;
     while (pool != NULL) {
 	if ((size_t)(pool->end - pool->free) > namelen)
@@ -266,10 +157,20 @@ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) {
             return(NULL);
         }
 
-        if (size == 0) size = 1000;
-	else size *= 4; /* exponential growth */
-        if (size < 4 * namelen)
-	    size = 4 * namelen; /* just in case ! */
+        if (size == 0) {
+            size = 1000;
+        } else {
+            if (size < (SIZE_MAX - sizeof(xmlDictStrings)) / 4)
+                size *= 4; /* exponential growth */
+            else
+                size = SIZE_MAX - sizeof(xmlDictStrings);
+        }
+        if (size / 4 < namelen) {
+            if ((size_t) namelen + 0 < (SIZE_MAX - sizeof(xmlDictStrings)) / 4)
+                size = 4 * (size_t) namelen; /* just in case ! */
+            else
+                return(NULL);
+        }
 	pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
 	if (pool == NULL)
 	    return(NULL);
@@ -279,9 +180,6 @@ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) {
 	pool->end = &pool->array[size];
 	pool->next = dict->strings;
 	dict->strings = pool;
-#ifdef DICT_DEBUG_PATTERNS
-        fprintf(stderr, "+");
-#endif
     }
 found_pool:
     ret = pool->free;
@@ -313,11 +211,6 @@ xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, unsigned int plen,
     size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
     size_t limit = 0;
 
-    if (prefix == NULL) return(xmlDictAddString(dict, name, namelen));
-
-#ifdef DICT_DEBUG_PATTERNS
-    fprintf(stderr, "=");
-#endif
     pool = dict->strings;
     while (pool != NULL) {
 	if ((size_t)(pool->end - pool->free) > namelen + plen + 1)
@@ -347,9 +240,6 @@ xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, unsigned int plen,
 	pool->end = &pool->array[size];
 	pool->next = dict->strings;
 	dict->strings = pool;
-#ifdef DICT_DEBUG_PATTERNS
-        fprintf(stderr, "+");
-#endif
     }
 found_pool:
     ret = pool->free;
@@ -363,209 +253,6 @@ found_pool:
     return(ret);
 }
 
-#ifdef WITH_BIG_KEY
-/*
- * xmlDictComputeBigKey:
- *
- * Calculate a hash key using a good hash function that works well for
- * larger hash table sizes.
- *
- * Hash function by "One-at-a-Time Hash" see
- * http://burtleburtle.net/bob/hash/doobs.html
- */
-
-#ifdef __clang__
-ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
-#endif
-static uint32_t
-xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
-    uint32_t hash;
-    int i;
-
-    if (namelen <= 0 || data == NULL) return(0);
-
-    hash = seed;
-
-    for (i = 0;i < namelen; i++) {
-        hash += data[i];
-	hash += (hash << 10);
-	hash ^= (hash >> 6);
-    }
-    hash += (hash << 3);
-    hash ^= (hash >> 11);
-    hash += (hash << 15);
-
-    return hash;
-}
-
-/*
- * xmlDictComputeBigQKey:
- *
- * Calculate a hash key for two strings using a good hash function
- * that works well for larger hash table sizes.
- *
- * Hash function by "One-at-a-Time Hash" see
- * http://burtleburtle.net/bob/hash/doobs.html
- *
- * Neither of the two strings must be NULL.
- */
-#ifdef __clang__
-ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
-#endif
-static unsigned long
-xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
-                      const xmlChar *name, int len, int seed)
-{
-    uint32_t hash;
-    int i;
-
-    hash = seed;
-
-    for (i = 0;i < plen; i++) {
-        hash += prefix[i];
-	hash += (hash << 10);
-	hash ^= (hash >> 6);
-    }
-    hash += ':';
-    hash += (hash << 10);
-    hash ^= (hash >> 6);
-
-    for (i = 0;i < len; i++) {
-        hash += name[i];
-	hash += (hash << 10);
-	hash ^= (hash >> 6);
-    }
-    hash += (hash << 3);
-    hash ^= (hash >> 11);
-    hash += (hash << 15);
-
-    return hash;
-}
-#endif /* WITH_BIG_KEY */
-
-/*
- * xmlDictComputeFastKey:
- *
- * Calculate a hash key using a fast hash function that works well
- * for low hash table fill.
- */
-static unsigned long
-xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
-    unsigned long value = seed;
-
-    if (name == NULL) return(0);
-    value += *name;
-    value <<= 5;
-    if (namelen > 10) {
-        value += name[namelen - 1];
-        namelen = 10;
-    }
-    switch (namelen) {
-        case 10: value += name[9];
-        /* Falls through. */
-        case 9: value += name[8];
-        /* Falls through. */
-        case 8: value += name[7];
-        /* Falls through. */
-        case 7: value += name[6];
-        /* Falls through. */
-        case 6: value += name[5];
-        /* Falls through. */
-        case 5: value += name[4];
-        /* Falls through. */
-        case 4: value += name[3];
-        /* Falls through. */
-        case 3: value += name[2];
-        /* Falls through. */
-        case 2: value += name[1];
-        /* Falls through. */
-        default: break;
-    }
-    return(value);
-}
-
-/*
- * xmlDictComputeFastQKey:
- *
- * Calculate a hash key for two strings using a fast hash function
- * that works well for low hash table fill.
- *
- * Neither of the two strings must be NULL.
- */
-static unsigned long
-xmlDictComputeFastQKey(const xmlChar *prefix, int plen,
-                       const xmlChar *name, int len, int seed)
-{
-    unsigned long value = (unsigned long) seed;
-
-    if (plen == 0)
-	value += 30 * (unsigned long) ':';
-    else
-	value += 30 * (*prefix);
-
-    if (len > 10) {
-        int offset = len - (plen + 1 + 1);
-	if (offset < 0)
-	    offset = len - (10 + 1);
-	value += name[offset];
-        len = 10;
-	if (plen > 10)
-	    plen = 10;
-    }
-    switch (plen) {
-        case 10: value += prefix[9];
-        /* Falls through. */
-        case 9: value += prefix[8];
-        /* Falls through. */
-        case 8: value += prefix[7];
-        /* Falls through. */
-        case 7: value += prefix[6];
-        /* Falls through. */
-        case 6: value += prefix[5];
-        /* Falls through. */
-        case 5: value += prefix[4];
-        /* Falls through. */
-        case 4: value += prefix[3];
-        /* Falls through. */
-        case 3: value += prefix[2];
-        /* Falls through. */
-        case 2: value += prefix[1];
-        /* Falls through. */
-        case 1: value += prefix[0];
-        /* Falls through. */
-        default: break;
-    }
-    len -= plen;
-    if (len > 0) {
-        value += (unsigned long) ':';
-	len--;
-    }
-    switch (len) {
-        case 10: value += name[9];
-        /* Falls through. */
-        case 9: value += name[8];
-        /* Falls through. */
-        case 8: value += name[7];
-        /* Falls through. */
-        case 7: value += name[6];
-        /* Falls through. */
-        case 6: value += name[5];
-        /* Falls through. */
-        case 5: value += name[4];
-        /* Falls through. */
-        case 4: value += name[3];
-        /* Falls through. */
-        case 3: value += name[2];
-        /* Falls through. */
-        case 2: value += name[1];
-        /* Falls through. */
-        case 1: value += name[0];
-        /* Falls through. */
-        default: break;
-    }
-    return(value);
-}
-
 /**
  * xmlDictCreate:
  *
@@ -577,36 +264,24 @@ xmlDictPtr
 xmlDictCreate(void) {
     xmlDictPtr dict;
 
-    if (!xmlDictInitialized)
-        if (!__xmlInitializeDict())
-            return(NULL);
-
-#ifdef DICT_DEBUG_PATTERNS
-    fprintf(stderr, "C");
-#endif
+    xmlInitParser();
 
     dict = xmlMalloc(sizeof(xmlDict));
-    if (dict) {
-        dict->ref_counter = 1;
-        dict->limit = 0;
-
-        dict->size = MIN_DICT_SIZE;
-	dict->nbElems = 0;
-        dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
-	dict->strings = NULL;
-	dict->subdict = NULL;
-        if (dict->dict) {
-	    memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
-#ifdef DICT_RANDOMIZATION
-            dict->seed = __xmlRandom();
-#else
-            dict->seed = 0;
+    if (dict == NULL)
+        return(NULL);
+    dict->ref_counter = 1;
+    dict->limit = 0;
+
+    dict->size = 0;
+    dict->nbElems = 0;
+    dict->table = NULL;
+    dict->strings = NULL;
+    dict->subdict = NULL;
+    dict->seed = xmlRandom();
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    dict->seed = 0;
 #endif
-	    return(dict);
-        }
-        xmlFree(dict);
-    }
-    return(NULL);
+    return(dict);
 }
 
 /**
@@ -625,9 +300,6 @@ xmlDictCreateSub(xmlDictPtr sub) {
     xmlDictPtr dict = xmlDictCreate();
 
     if ((dict != NULL) && (sub != NULL)) {
-#ifdef DICT_DEBUG_PATTERNS
-        fprintf(stderr, "R");
-#endif
         dict->seed = sub->seed;
         dict->subdict = sub;
 	xmlDictReference(dict->subdict);
@@ -645,152 +317,13 @@ xmlDictCreateSub(xmlDictPtr sub) {
  */
 int
 xmlDictReference(xmlDictPtr dict) {
-    if (!xmlDictInitialized)
-        if (!__xmlInitializeDict())
-            return(-1);
-
     if (dict == NULL) return -1;
-    xmlMutexLock(xmlDictMutex);
+    xmlMutexLock(&xmlDictMutex);
     dict->ref_counter++;
-    xmlMutexUnlock(xmlDictMutex);
+    xmlMutexUnlock(&xmlDictMutex);
     return(0);
 }
 
-/**
- * xmlDictGrow:
- * @dict: the dictionary
- * @size: the new size of the dictionary
- *
- * resize the dictionary
- *
- * Returns 0 in case of success, -1 in case of failure
- */
-static int
-xmlDictGrow(xmlDictPtr dict, size_t size) {
-    unsigned long key, okey;
-    size_t oldsize, i;
-    xmlDictEntryPtr iter, next;
-    struct _xmlDictEntry *olddict;
-#ifdef DEBUG_GROW
-    unsigned long nbElem = 0;
-#endif
-    int ret = 0;
-    int keep_keys = 1;
-
-    if (dict == NULL)
-	return(-1);
-    if (size < 8)
-        return(-1);
-    if (size > 8 * 2048)
-	return(-1);
-
-#ifdef DICT_DEBUG_PATTERNS
-    fprintf(stderr, "*");
-#endif
-
-    oldsize = dict->size;
-    olddict = dict->dict;
-    if (olddict == NULL)
-        return(-1);
-    if (oldsize == MIN_DICT_SIZE)
-        keep_keys = 0;
-
-    dict->dict = xmlMalloc(size * sizeof(xmlDictEntry));
-    if (dict->dict == NULL) {
-	dict->dict = olddict;
-	return(-1);
-    }
-    memset(dict->dict, 0, size * sizeof(xmlDictEntry));
-    dict->size = size;
-
-    /*	If the two loops are merged, there would be situations where
-	a new entry needs to allocated and data copied into it from
-	the main dict. It is nicer to run through the array twice, first
-	copying all the elements in the main array (less probability of
-	allocate) and then the rest, so we only free in the second loop.
-    */
-    for (i = 0; i < oldsize; i++) {
-	if (olddict[i].valid == 0)
-	    continue;
-
-	if (keep_keys)
-	    okey = olddict[i].okey;
-	else
-	    okey = xmlDictComputeKey(dict, olddict[i].name, olddict[i].len);
-	key = okey % dict->size;
-
-	if (dict->dict[key].valid == 0) {
-	    memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry));
-	    dict->dict[key].next = NULL;
-	    dict->dict[key].okey = okey;
-	} else {
-	    xmlDictEntryPtr entry;
-
-	    entry = xmlMalloc(sizeof(xmlDictEntry));
-	    if (entry != NULL) {
-		entry->name = olddict[i].name;
-		entry->len = olddict[i].len;
-		entry->okey = okey;
-		entry->next = dict->dict[key].next;
-		entry->valid = 1;
-		dict->dict[key].next = entry;
-	    } else {
-	        /*
-		 * we don't have much ways to alert from here
-		 * result is losing an entry and unicity guarantee
-		 */
-	        ret = -1;
-	    }
-	}
-#ifdef DEBUG_GROW
-	nbElem++;
-#endif
-    }
-
-    for (i = 0; i < oldsize; i++) {
-	iter = olddict[i].next;
-	while (iter) {
-	    next = iter->next;
-
-	    /*
-	     * put back the entry in the new dict
-	     */
-
-	    if (keep_keys)
-		okey = iter->okey;
-	    else
-		okey = xmlDictComputeKey(dict, iter->name, iter->len);
-	    key = okey % dict->size;
-	    if (dict->dict[key].valid == 0) {
-		memcpy(&(dict->dict[key]), iter, sizeof(xmlDictEntry));
-		dict->dict[key].next = NULL;
-		dict->dict[key].valid = 1;
-		dict->dict[key].okey = okey;
-		xmlFree(iter);
-	    } else {
-		iter->next = dict->dict[key].next;
-		iter->okey = okey;
-		dict->dict[key].next = iter;
-	    }
-
-#ifdef DEBUG_GROW
-	    nbElem++;
-#endif
-
-	    iter = next;
-	}
-    }
-
-    xmlFree(olddict);
-
-#ifdef DEBUG_GROW
-    xmlGenericError(xmlGenericErrorContext,
-	    "xmlDictGrow : from %lu to %lu, %u elems\n", oldsize, size, nbElem);
-#endif
-
-    return(ret);
-}
-
 /**
  * xmlDictFree:
  * @dict: the dictionary
@@ -800,49 +333,27 @@ xmlDictGrow(xmlDictPtr dict, size_t size) {
  */
 void
 xmlDictFree(xmlDictPtr dict) {
-    size_t i;
-    xmlDictEntryPtr iter;
-    xmlDictEntryPtr next;
-    int inside_dict = 0;
     xmlDictStringsPtr pool, nextp;
 
     if (dict == NULL)
 	return;
 
-    if (!xmlDictInitialized)
-        if (!__xmlInitializeDict())
-            return;
-
     /* decrement the counter, it may be shared by a parser and docs */
-    xmlMutexLock(xmlDictMutex);
+    xmlMutexLock(&xmlDictMutex);
     dict->ref_counter--;
     if (dict->ref_counter > 0) {
-        xmlMutexUnlock(xmlDictMutex);
+        xmlMutexUnlock(&xmlDictMutex);
         return;
     }
 
-    xmlMutexUnlock(xmlDictMutex);
+    xmlMutexUnlock(&xmlDictMutex);
 
     if (dict->subdict != NULL) {
         xmlDictFree(dict->subdict);
     }
 
-    if (dict->dict) {
-	for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) {
-	    iter = &(dict->dict[i]);
-	    if (iter->valid == 0)
-		continue;
-	    inside_dict = 1;
-	    while (iter) {
-		next = iter->next;
-		if (!inside_dict)
-		    xmlFree(iter);
-		dict->nbElems--;
-		inside_dict = 0;
-		iter = next;
-	    }
-	}
-	xmlFree(dict->dict);
+    if (dict->table) {
+	xmlFree(dict->table);
     }
     pool = dict->strings;
     while (pool != NULL) {
@@ -854,445 +365,685 @@ xmlDictFree(xmlDictPtr dict) {
 }
 
 /**
- * xmlDictLookup:
+ * xmlDictOwns:
  * @dict: the dictionary
- * @name: the name of the userdata
- * @len: the length of the name, if -1 it is recomputed
+ * @str: the string
  *
- * Add the @name to the dictionary @dict if not present.
+ * check if a string is owned by the dictionary
  *
- * Returns the internal copy of the name or NULL in case of internal error
+ * Returns 1 if true, 0 if false and -1 in case of error
+ * -1 in case of error
  */
-const xmlChar *
-xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
-    unsigned long key, okey, nbi = 0;
-    xmlDictEntryPtr entry;
-    xmlDictEntryPtr insert;
-    const xmlChar *ret;
-    unsigned int l;
+int
+xmlDictOwns(xmlDictPtr dict, const xmlChar *str) {
+    xmlDictStringsPtr pool;
 
-    if ((dict == NULL) || (name == NULL))
-	return(NULL);
+    if ((dict == NULL) || (str == NULL))
+	return(-1);
+    pool = dict->strings;
+    while (pool != NULL) {
+        if ((str >= &pool->array[0]) && (str <= pool->free))
+	    return(1);
+	pool = pool->next;
+    }
+    if (dict->subdict)
+        return(xmlDictOwns(dict->subdict, str));
+    return(0);
+}
 
-    if (len < 0)
-        l = strlen((const char *) name);
-    else
-        l = len;
+/**
+ * xmlDictSize:
+ * @dict: the dictionary
+ *
+ * Query the number of elements installed in the hash @dict.
+ *
+ * Returns the number of elements in the dictionary or
+ * -1 in case of error
+ */
+int
+xmlDictSize(xmlDictPtr dict) {
+    if (dict == NULL)
+	return(-1);
+    if (dict->subdict)
+        return(dict->nbElems + dict->subdict->nbElems);
+    return(dict->nbElems);
+}
 
-    if (((dict->limit > 0) && (l >= dict->limit)) ||
-        (l > INT_MAX / 2))
-        return(NULL);
+/**
+ * xmlDictSetLimit:
+ * @dict: the dictionary
+ * @limit: the limit in bytes
+ *
+ * Set a size limit for the dictionary
+ * Added in 2.9.0
+ *
+ * Returns the previous limit of the dictionary or 0
+ */
+size_t
+xmlDictSetLimit(xmlDictPtr dict, size_t limit) {
+    size_t ret;
 
-    /*
-     * Check for duplicate and insertion location.
-     */
-    okey = xmlDictComputeKey(dict, name, l);
-    key = okey % dict->size;
-    if (dict->dict[key].valid == 0) {
-	insert = NULL;
-    } else {
-	for (insert = &(dict->dict[key]); insert->next != NULL;
-	     insert = insert->next) {
-#ifdef __GNUC__
-	    if ((insert->okey == okey) && (insert->len == l)) {
-		if (!memcmp(insert->name, name, l))
-		    return(insert->name);
-	    }
-#else
-	    if ((insert->okey == okey) && (insert->len == l) &&
-	        (!xmlStrncmp(insert->name, name, l)))
-		return(insert->name);
-#endif
-	    nbi++;
-	}
-#ifdef __GNUC__
-	if ((insert->okey == okey) && (insert->len == l)) {
-	    if (!memcmp(insert->name, name, l))
-		return(insert->name);
-	}
-#else
-	if ((insert->okey == okey) && (insert->len == l) &&
-	    (!xmlStrncmp(insert->name, name, l)))
-	    return(insert->name);
-#endif
+    if (dict == NULL)
+	return(0);
+    ret = dict->limit;
+    dict->limit = limit;
+    return(ret);
+}
+
+/**
+ * xmlDictGetUsage:
+ * @dict: the dictionary
+ *
+ * Get how much memory is used by a dictionary for strings
+ * Added in 2.9.0
+ *
+ * Returns the amount of strings allocated
+ */
+size_t
+xmlDictGetUsage(xmlDictPtr dict) {
+    xmlDictStringsPtr pool;
+    size_t limit = 0;
+
+    if (dict == NULL)
+	return(0);
+    pool = dict->strings;
+    while (pool != NULL) {
+        limit += pool->size;
+	pool = pool->next;
     }
+    return(limit);
+}
 
-    if (dict->subdict) {
-        unsigned long skey;
-
-        /* we cannot always reuse the same okey for the subdict */
-        if (((dict->size == MIN_DICT_SIZE) &&
-	     (dict->subdict->size != MIN_DICT_SIZE)) ||
-            ((dict->size != MIN_DICT_SIZE) &&
-	     (dict->subdict->size == MIN_DICT_SIZE)))
-	    skey = xmlDictComputeKey(dict->subdict, name, l);
-	else
-	    skey = okey;
-
-	key = skey % dict->subdict->size;
-	if (dict->subdict->dict[key].valid != 0) {
-	    xmlDictEntryPtr tmp;
-
-	    for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
-		 tmp = tmp->next) {
-#ifdef __GNUC__
-		if ((tmp->okey == skey) && (tmp->len == l)) {
-		    if (!memcmp(tmp->name, name, l))
-			return(tmp->name);
-		}
-#else
-		if ((tmp->okey == skey) && (tmp->len == l) &&
-		    (!xmlStrncmp(tmp->name, name, l)))
-		    return(tmp->name);
-#endif
-		nbi++;
-	    }
-#ifdef __GNUC__
-	    if ((tmp->okey == skey) && (tmp->len == l)) {
-		if (!memcmp(tmp->name, name, l))
-		    return(tmp->name);
-	    }
-#else
-	    if ((tmp->okey == skey) && (tmp->len == l) &&
-		(!xmlStrncmp(tmp->name, name, l)))
-		return(tmp->name);
-#endif
-	}
-	key = okey % dict->size;
+/*****************************************************************
+ *
+ * The code below was rewritten and is additionally licensed under
+ * the main license in file 'Copyright'.
+ *
+ *****************************************************************/
+
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static unsigned
+xmlDictHashName(unsigned seed, const xmlChar* data, size_t maxLen,
+                size_t *plen) {
+    unsigned h1, h2;
+    size_t i;
+
+    HASH_INIT(h1, h2, seed);
+
+    for (i = 0; i < maxLen && data[i]; i++) {
+        HASH_UPDATE(h1, h2, data[i]);
     }
 
-    ret = xmlDictAddString(dict, name, l);
-    if (ret == NULL)
-        return(NULL);
-    if (insert == NULL) {
-	entry = &(dict->dict[key]);
-    } else {
-	entry = xmlMalloc(sizeof(xmlDictEntry));
-	if (entry == NULL)
-	     return(NULL);
+    HASH_FINISH(h1, h2);
+
+    *plen = i;
+    return(h2 | MAX_HASH_SIZE);
+}
+
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static unsigned
+xmlDictHashQName(unsigned seed, const xmlChar *prefix, const xmlChar *name,
+                 size_t *pplen, size_t *plen) {
+    unsigned h1, h2;
+    size_t i;
+
+    HASH_INIT(h1, h2, seed);
+
+    for (i = 0; prefix[i] != 0; i++) {
+        HASH_UPDATE(h1, h2, prefix[i]);
     }
-    entry->name = ret;
-    entry->len = l;
-    entry->next = NULL;
-    entry->valid = 1;
-    entry->okey = okey;
+    *pplen = i;
 
+    HASH_UPDATE(h1, h2, ':');
 
-    if (insert != NULL)
-	insert->next = entry;
+    for (i = 0; name[i] != 0; i++) {
+        HASH_UPDATE(h1, h2, name[i]);
+    }
+    *plen = i;
 
-    dict->nbElems++;
+    HASH_FINISH(h1, h2);
 
-    if ((nbi > MAX_HASH_LEN) &&
-        (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) {
-	if (xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size) != 0)
-	    return(NULL);
+    /*
+     * Always set the upper bit of hash values since 0 means an unoccupied
+     * bucket.
+     */
+    return(h2 | MAX_HASH_SIZE);
+}
+
+/**
+ * xmlDictComputeHash:
+ * @dict:  dictionary
+ * @string:  C string
+ *
+ * Compute the hash value of a C string.
+ *
+ * Returns the hash value.
+ */
+unsigned
+xmlDictComputeHash(const xmlDict *dict, const xmlChar *string) {
+    size_t len;
+    return(xmlDictHashName(dict->seed, string, SIZE_MAX, &len));
+}
+
+#define HASH_ROL31(x,n) ((x) << (n) | ((x) & 0x7FFFFFFF) >> (31 - (n)))
+
+/**
+ * xmlDictCombineHash:
+ * @v1:  first hash value
+ * @v2: second hash value
+ *
+ * Combine two hash values.
+ *
+ * Returns the combined hash value.
+ */
+ATTRIBUTE_NO_SANITIZE_INTEGER
+unsigned
+xmlDictCombineHash(unsigned v1, unsigned v2) {
+    /*
+     * The upper bit of hash values is always set, so we have to operate on
+     * 31-bit hashes here.
+     */
+    v1 ^= v2;
+    v1 += HASH_ROL31(v2, 5);
+
+    return((v1 & 0xFFFFFFFF) | 0x80000000);
+}
+
+/**
+ * xmlDictFindEntry:
+ * @dict: dict
+ * @prefix: optional QName prefix
+ * @name: string
+ * @len: length of string
+ * @hashValue: valid hash value of string
+ * @pfound: result of search
+ *
+ * Try to find a matching hash table entry. If an entry was found, set
+ * @found to 1 and return the entry. Otherwise, set @found to 0 and return
+ * the location where a new entry should be inserted.
+ */
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static xmlDictEntry *
+xmlDictFindEntry(const xmlDict *dict, const xmlChar *prefix,
+                 const xmlChar *name, int len, unsigned hashValue,
+                 int *pfound) {
+    xmlDictEntry *entry;
+    unsigned mask, pos, displ;
+    int found = 0;
+
+    mask = dict->size - 1;
+    pos = hashValue & mask;
+    entry = &dict->table[pos];
+
+    if (entry->hashValue != 0) {
+        /*
+         * Robin hood hashing: abort if the displacement of the entry
+         * is smaller than the displacement of the key we look for.
+         * This also stops at the correct position when inserting.
+         */
+        displ = 0;
+
+        do {
+            if (entry->hashValue == hashValue) {
+                if (prefix == NULL) {
+                    /*
+                     * name is not necessarily null-terminated.
+                     */
+                    if ((strncmp((const char *) entry->name,
+                                 (const char *) name, len) == 0) &&
+                        (entry->name[len] == 0)) {
+                        found = 1;
+                        break;
+                    }
+                } else {
+                    if (xmlStrQEqual(prefix, name, entry->name)) {
+                        found = 1;
+                        break;
+                    }
+                }
+            }
+
+            displ++;
+            pos++;
+            entry++;
+            if ((pos & mask) == 0)
+                entry = dict->table;
+        } while ((entry->hashValue != 0) &&
+                 (((pos - entry->hashValue) & mask) >= displ));
     }
-    /* Note that entry may have been freed at this point by xmlDictGrow */
 
-    return(ret);
+    *pfound = found;
+    return(entry);
 }
 
 /**
- * xmlDictExists:
- * @dict: the dictionary
- * @name: the name of the userdata
- * @len: the length of the name, if -1 it is recomputed
+ * xmlDictGrow:
+ * @dict: dictionary
+ * @size: new size of the dictionary
  *
- * Check if the @name exists in the dictionary @dict.
+ * Resize the dictionary hash table.
  *
- * Returns the internal copy of the name or NULL if not found.
+ * Returns 0 in case of success, -1 if a memory allocation failed.
  */
-const xmlChar *
-xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
-    unsigned long key, okey, nbi = 0;
-    xmlDictEntryPtr insert;
-    unsigned int l;
+static int
+xmlDictGrow(xmlDictPtr dict, unsigned size) {
+    const xmlDictEntry *oldentry, *oldend, *end;
+    xmlDictEntry *table;
+    unsigned oldsize, i;
 
-    if ((dict == NULL) || (name == NULL))
-	return(NULL);
+    /* Add 0 to avoid spurious -Wtype-limits warning on 64-bit GCC */
+    if ((size_t) size + 0 > SIZE_MAX / sizeof(table[0]))
+        return(-1);
+    table = xmlMalloc(size * sizeof(table[0]));
+    if (table == NULL)
+        return(-1);
+    memset(table, 0, size * sizeof(table[0]));
 
-    if (len < 0)
-        l = strlen((const char *) name);
-    else
-        l = len;
-    if (((dict->limit > 0) && (l >= dict->limit)) ||
-        (l > INT_MAX / 2))
-        return(NULL);
+    oldsize = dict->size;
+    if (oldsize == 0)
+        goto done;
+
+    oldend = &dict->table[oldsize];
+    end = &table[size];
 
     /*
-     * Check for duplicate and insertion location.
+     * Robin Hood sorting order is maintained if we
+     *
+     * - compute dict indices with modulo
+     * - resize by an integer factor
+     * - start to copy from the beginning of a probe sequence
      */
-    okey = xmlDictComputeKey(dict, name, l);
-    key = okey % dict->size;
-    if (dict->dict[key].valid == 0) {
-	insert = NULL;
-    } else {
-	for (insert = &(dict->dict[key]); insert->next != NULL;
-	     insert = insert->next) {
-#ifdef __GNUC__
-	    if ((insert->okey == okey) && (insert->len == l)) {
-		if (!memcmp(insert->name, name, l))
-		    return(insert->name);
-	    }
-#else
-	    if ((insert->okey == okey) && (insert->len == l) &&
-	        (!xmlStrncmp(insert->name, name, l)))
-		return(insert->name);
-#endif
-	    nbi++;
-	}
-#ifdef __GNUC__
-	if ((insert->okey == okey) && (insert->len == l)) {
-	    if (!memcmp(insert->name, name, l))
-		return(insert->name);
-	}
-#else
-	if ((insert->okey == okey) && (insert->len == l) &&
-	    (!xmlStrncmp(insert->name, name, l)))
-	    return(insert->name);
-#endif
+    oldentry = dict->table;
+    while (oldentry->hashValue != 0) {
+        if (++oldentry >= oldend)
+            oldentry = dict->table;
     }
 
-    if (dict->subdict) {
-        unsigned long skey;
-
-        /* we cannot always reuse the same okey for the subdict */
-        if (((dict->size == MIN_DICT_SIZE) &&
-	     (dict->subdict->size != MIN_DICT_SIZE)) ||
-            ((dict->size != MIN_DICT_SIZE) &&
-	     (dict->subdict->size == MIN_DICT_SIZE)))
-	    skey = xmlDictComputeKey(dict->subdict, name, l);
-	else
-	    skey = okey;
-
-	key = skey % dict->subdict->size;
-	if (dict->subdict->dict[key].valid != 0) {
-	    xmlDictEntryPtr tmp;
-
-	    for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
-		 tmp = tmp->next) {
-#ifdef __GNUC__
-		if ((tmp->okey == skey) && (tmp->len == l)) {
-		    if (!memcmp(tmp->name, name, l))
-			return(tmp->name);
-		}
-#else
-		if ((tmp->okey == skey) && (tmp->len == l) &&
-		    (!xmlStrncmp(tmp->name, name, l)))
-		    return(tmp->name);
-#endif
-		nbi++;
-	    }
-#ifdef __GNUC__
-	    if ((tmp->okey == skey) && (tmp->len == l)) {
-		if (!memcmp(tmp->name, name, l))
-		    return(tmp->name);
-	    }
-#else
-	    if ((tmp->okey == skey) && (tmp->len == l) &&
-		(!xmlStrncmp(tmp->name, name, l)))
-		return(tmp->name);
-#endif
-	}
+    for (i = 0; i < oldsize; i++) {
+        if (oldentry->hashValue != 0) {
+            xmlDictEntry *entry = &table[oldentry->hashValue & (size - 1)];
+
+            while (entry->hashValue != 0) {
+                if (++entry >= end)
+                    entry = table;
+            }
+            *entry = *oldentry;
+        }
+
+        if (++oldentry >= oldend)
+            oldentry = dict->table;
     }
 
-    /* not found */
-    return(NULL);
+    xmlFree(dict->table);
+
+done:
+    dict->table = table;
+    dict->size = size;
+
+    return(0);
 }
 
 /**
- * xmlDictQLookup:
- * @dict: the dictionary
- * @prefix: the prefix
- * @name: the name
- *
- * Add the QName @prefix:@name to the hash @dict if not present.
+ * xmlDictLookupInternal:
+ * @dict: dict
+ * @prefix: optional QName prefix
+ * @name: string
+ * @maybeLen: length of string or -1 if unknown
+ * @update: whether the string should be added
  *
- * Returns the internal copy of the QName or NULL in case of internal error
+ * Internal lookup and update function.
  */
-const xmlChar *
-xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
-    unsigned long okey, key, nbi = 0;
-    xmlDictEntryPtr entry;
-    xmlDictEntryPtr insert;
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static const xmlDictEntry *
+xmlDictLookupInternal(xmlDictPtr dict, const xmlChar *prefix,
+                      const xmlChar *name, int maybeLen, int update) {
+    xmlDictEntry *entry = NULL;
     const xmlChar *ret;
-    unsigned int len, plen, l;
+    unsigned hashValue;
+    size_t maxLen, len, plen, klen;
+    int found = 0;
 
     if ((dict == NULL) || (name == NULL))
 	return(NULL);
-    if (prefix == NULL)
-        return(xmlDictLookup(dict, name, -1));
 
-    l = len = strlen((const char *) name);
-    plen = strlen((const char *) prefix);
-    len += 1 + plen;
+    maxLen = (maybeLen < 0) ? SIZE_MAX : (size_t) maybeLen;
+
+    if (prefix == NULL) {
+        hashValue = xmlDictHashName(dict->seed, name, maxLen, &len);
+        if (len > INT_MAX / 2)
+            return(NULL);
+        klen = len;
+    } else {
+        hashValue = xmlDictHashQName(dict->seed, prefix, name, &plen, &len);
+        if ((len > INT_MAX / 2) || (plen >= INT_MAX / 2 - len))
+            return(NULL);
+        klen = plen + 1 + len;
+    }
+
+    if ((dict->limit > 0) && (klen >= dict->limit))
+        return(NULL);
 
     /*
-     * Check for duplicate and insertion location.
+     * Check for an existing entry
      */
-    okey = xmlDictComputeQKey(dict, prefix, plen, name, l);
-    key = okey % dict->size;
-    if (dict->dict[key].valid == 0) {
-	insert = NULL;
-    } else {
-	for (insert = &(dict->dict[key]); insert->next != NULL;
-	     insert = insert->next) {
-	    if ((insert->okey == okey) && (insert->len == len) &&
-	        (xmlStrQEqual(prefix, name, insert->name)))
-		return(insert->name);
-	    nbi++;
-	}
-	if ((insert->okey == okey) && (insert->len == len) &&
-	    (xmlStrQEqual(prefix, name, insert->name)))
-	    return(insert->name);
+    if (dict->size > 0)
+        entry = xmlDictFindEntry(dict, prefix, name, klen, hashValue, &found);
+    if (found)
+        return(entry);
+
+    if ((dict->subdict != NULL) && (dict->subdict->size > 0)) {
+        xmlDictEntry *subEntry;
+        unsigned subHashValue;
+
+        if (prefix == NULL)
+            subHashValue = xmlDictHashName(dict->subdict->seed, name, len,
+                                           &len);
+        else
+            subHashValue = xmlDictHashQName(dict->subdict->seed, prefix, name,
+                                            &plen, &len);
+        subEntry = xmlDictFindEntry(dict->subdict, prefix, name, klen,
+                                    subHashValue, &found);
+        if (found)
+            return(subEntry);
     }
 
-    if (dict->subdict) {
-        unsigned long skey;
-
-        /* we cannot always reuse the same okey for the subdict */
-        if (((dict->size == MIN_DICT_SIZE) &&
-	     (dict->subdict->size != MIN_DICT_SIZE)) ||
-            ((dict->size != MIN_DICT_SIZE) &&
-	     (dict->subdict->size == MIN_DICT_SIZE)))
-	    skey = xmlDictComputeQKey(dict->subdict, prefix, plen, name, l);
-	else
-	    skey = okey;
-
-	key = skey % dict->subdict->size;
-	if (dict->subdict->dict[key].valid != 0) {
-	    xmlDictEntryPtr tmp;
-	    for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
-		 tmp = tmp->next) {
-		if ((tmp->okey == skey) && (tmp->len == len) &&
-		    (xmlStrQEqual(prefix, name, tmp->name)))
-		    return(tmp->name);
-		nbi++;
-	    }
-	    if ((tmp->okey == skey) && (tmp->len == len) &&
-		(xmlStrQEqual(prefix, name, tmp->name)))
-		return(tmp->name);
-	}
-	key = okey % dict->size;
+    if (!update)
+        return(NULL);
+
+    /*
+     * Grow the hash table if needed
+     */
+    if (dict->nbElems + 1 > dict->size / MAX_FILL_DENOM * MAX_FILL_NUM) {
+        unsigned newSize, mask, displ, pos;
+
+        if (dict->size == 0) {
+            newSize = MIN_HASH_SIZE;
+        } else {
+            if (dict->size >= MAX_HASH_SIZE)
+                return(NULL);
+            newSize = dict->size * 2;
+        }
+        if (xmlDictGrow(dict, newSize) != 0)
+            return(NULL);
+
+        /*
+         * Find new entry
+         */
+        mask = dict->size - 1;
+        displ = 0;
+        pos = hashValue & mask;
+        entry = &dict->table[pos];
+
+        while ((entry->hashValue != 0) &&
+               ((pos - entry->hashValue) & mask) >= displ) {
+            displ++;
+            pos++;
+            entry++;
+            if ((pos & mask) == 0)
+                entry = dict->table;
+        }
     }
 
-    ret = xmlDictAddQString(dict, prefix, plen, name, l);
+    if (prefix == NULL)
+        ret = xmlDictAddString(dict, name, len);
+    else
+        ret = xmlDictAddQString(dict, prefix, plen, name, len);
     if (ret == NULL)
         return(NULL);
-    if (insert == NULL) {
-	entry = &(dict->dict[key]);
-    } else {
-	entry = xmlMalloc(sizeof(xmlDictEntry));
-	if (entry == NULL)
-	     return(NULL);
+
+    /*
+     * Shift the remainder of the probe sequence to the right
+     */
+    if (entry->hashValue != 0) {
+        const xmlDictEntry *end = &dict->table[dict->size];
+        const xmlDictEntry *cur = entry;
+
+        do {
+            cur++;
+            if (cur >= end)
+                cur = dict->table;
+        } while (cur->hashValue != 0);
+
+        if (cur < entry) {
+            /*
+             * If we traversed the end of the buffer, handle the part
+             * at the start of the buffer.
+             */
+            memmove(&dict->table[1], dict->table,
+                    (char *) cur - (char *) dict->table);
+            cur = end - 1;
+            dict->table[0] = *cur;
+        }
+
+        memmove(&entry[1], entry, (char *) cur - (char *) entry);
     }
-    entry->name = ret;
-    entry->len = len;
-    entry->next = NULL;
-    entry->valid = 1;
-    entry->okey = okey;
 
-    if (insert != NULL)
-	insert->next = entry;
+    /*
+     * Populate entry
+     */
+    entry->hashValue = hashValue;
+    entry->name = ret;
 
     dict->nbElems++;
 
-    if ((nbi > MAX_HASH_LEN) &&
-        (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN)))
-	xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size);
-    /* Note that entry may have been freed at this point by xmlDictGrow */
-
-    return(ret);
+    return(entry);
 }
 
 /**
- * xmlDictOwns:
- * @dict: the dictionary
- * @str: the string
+ * xmlDictLookup:
+ * @dict: dictionary
+ * @name: string key
+ * @len: length of the key, if -1 it is recomputed
  *
- * check if a string is owned by the dictionary
+ * Lookup a string and add it to the dictionary if it wasn't found.
  *
- * Returns 1 if true, 0 if false and -1 in case of error
- * -1 in case of error
+ * Returns the interned copy of the string or NULL if a memory allocation
+ * failed.
  */
-int
-xmlDictOwns(xmlDictPtr dict, const xmlChar *str) {
-    xmlDictStringsPtr pool;
+const xmlChar *
+xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
+    const xmlDictEntry *entry;
 
-    if ((dict == NULL) || (str == NULL))
-	return(-1);
-    pool = dict->strings;
-    while (pool != NULL) {
-        if ((str >= &pool->array[0]) && (str <= pool->free))
-	    return(1);
-	pool = pool->next;
-    }
-    if (dict->subdict)
-        return(xmlDictOwns(dict->subdict, str));
-    return(0);
+    entry = xmlDictLookupInternal(dict, NULL, name, len, 1);
+    if (entry == NULL)
+        return(NULL);
+    return(entry->name);
 }
 
 /**
- * xmlDictSize:
- * @dict: the dictionary
+ * xmlDictLookupHashed:
+ * @dict: dictionary
+ * @name: string key
+ * @len: length of the key, if -1 it is recomputed
  *
- * Query the number of elements installed in the hash @dict.
+ * Lookup a dictionary entry and add the string to the dictionary if
+ * it wasn't found.
  *
- * Returns the number of elements in the dictionary or
- * -1 in case of error
+ * Returns the dictionary entry.
  */
-int
-xmlDictSize(xmlDictPtr dict) {
-    if (dict == NULL)
-	return(-1);
-    if (dict->subdict)
-        return(dict->nbElems + dict->subdict->nbElems);
-    return(dict->nbElems);
+xmlHashedString
+xmlDictLookupHashed(xmlDictPtr dict, const xmlChar *name, int len) {
+    const xmlDictEntry *entry;
+    xmlHashedString ret;
+
+    entry = xmlDictLookupInternal(dict, NULL, name, len, 1);
+
+    if (entry == NULL) {
+        ret.name = NULL;
+        ret.hashValue = 0;
+    } else {
+        ret = *entry;
+    }
+
+    return(ret);
 }
 
 /**
- * xmlDictSetLimit:
+ * xmlDictExists:
  * @dict: the dictionary
- * @limit: the limit in bytes
+ * @name: the name of the userdata
+ * @len: the length of the name, if -1 it is recomputed
  *
- * Set a size limit for the dictionary
- * Added in 2.9.0
+ * Check if a string exists in the dictionary.
  *
- * Returns the previous limit of the dictionary or 0
+ * Returns the internal copy of the name or NULL if not found.
  */
-size_t
-xmlDictSetLimit(xmlDictPtr dict, size_t limit) {
-    size_t ret;
+const xmlChar *
+xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
+    const xmlDictEntry *entry;
 
-    if (dict == NULL)
-	return(0);
-    ret = dict->limit;
-    dict->limit = limit;
-    return(ret);
+    entry = xmlDictLookupInternal(dict, NULL, name, len, 0);
+    if (entry == NULL)
+        return(NULL);
+    return(entry->name);
 }
 
 /**
- * xmlDictGetUsage:
+ * xmlDictQLookup:
  * @dict: the dictionary
+ * @prefix: the prefix
+ * @name: the name
  *
- * Get how much memory is used by a dictionary for strings
- * Added in 2.9.0
+ * Lookup the QName @prefix:@name and add it to the dictionary if
+ * it wasn't found.
  *
- * Returns the amount of strings allocated
+ * Returns the interned copy of the string or NULL if a memory allocation
+ * failed.
  */
-size_t
-xmlDictGetUsage(xmlDictPtr dict) {
-    xmlDictStringsPtr pool;
-    size_t limit = 0;
+const xmlChar *
+xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
+    const xmlDictEntry *entry;
 
-    if (dict == NULL)
-	return(0);
-    pool = dict->strings;
-    while (pool != NULL) {
-        limit += pool->size;
-	pool = pool->next;
+    entry = xmlDictLookupInternal(dict, prefix, name, -1, 1);
+    if (entry == NULL)
+        return(NULL);
+    return(entry->name);
+}
+
+/*
+ * Pseudo-random generator
+ */
+
+#ifdef _WIN32
+  #define WIN32_LEAN_AND_MEAN
+  #include <windows.h>
+  #include <bcrypt.h>
+#elif defined(HAVE_GETENTROPY)
+  #ifdef HAVE_UNISTD_H
+    #include <unistd.h>
+  #endif
+  #ifdef HAVE_SYS_RANDOM_H
+    #include <sys/random.h>
+  #endif
+#else
+  #include <time.h>
+#endif
+
+static xmlMutex xmlRngMutex;
+
+static unsigned globalRngState[2];
+
+/*
+ * xmlInitRandom:
+ *
+ * Initialize the PRNG.
+ */
+ATTRIBUTE_NO_SANITIZE_INTEGER
+void
+xmlInitRandom(void) {
+    xmlInitMutex(&xmlRngMutex);
+
+    {
+#ifdef _WIN32
+        NTSTATUS status;
+
+        status = BCryptGenRandom(NULL, (unsigned char *) globalRngState,
+                                 sizeof(globalRngState),
+                                 BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+        if (!BCRYPT_SUCCESS(status)) {
+            fprintf(stderr, "libxml2: BCryptGenRandom failed with "
+                    "error code %lu\n", GetLastError());
+            abort();
+        }
+#elif defined(HAVE_GETENTROPY)
+        while (1) {
+            if (getentropy(globalRngState, sizeof(globalRngState)) == 0)
+                break;
+
+            if (errno != EINTR) {
+                fprintf(stderr, "libxml2: getentropy failed with "
+                        "error code %d\n", errno);
+                abort();
+            }
+        }
+#else
+        int var;
+
+        globalRngState[0] =
+                (unsigned) time(NULL) ^
+                HASH_ROL((unsigned) ((size_t) &xmlInitRandom & 0xFFFFFFFF), 8);
+        globalRngState[1] =
+                HASH_ROL((unsigned) ((size_t) &xmlRngMutex & 0xFFFFFFFF), 16) ^
+                HASH_ROL((unsigned) ((size_t) &var & 0xFFFFFFFF), 24);
+#endif
     }
-    return(limit);
+}
+
+/*
+ * xmlCleanupRandom:
+ *
+ * Clean up PRNG globals.
+ */
+void
+xmlCleanupRandom(void) {
+    xmlCleanupMutex(&xmlRngMutex);
+}
+
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static unsigned
+xoroshiro64ss(unsigned *s) {
+    unsigned s0 = s[0];
+    unsigned s1 = s[1];
+    unsigned result = HASH_ROL(s0 * 0x9E3779BB, 5) * 5;
+
+    s1 ^= s0;
+    s[0] = HASH_ROL(s0, 26) ^ s1 ^ (s1 << 9);
+    s[1] = HASH_ROL(s1, 13);
+
+    return(result & 0xFFFFFFFF);
+}
+
+/*
+ * xmlGlobalRandom:
+ *
+ * Generate a pseudo-random value using the global PRNG.
+ *
+ * Returns a random value.
+ */
+unsigned
+xmlGlobalRandom(void) {
+    unsigned ret;
+
+    xmlMutexLock(&xmlRngMutex);
+    ret = xoroshiro64ss(globalRngState);
+    xmlMutexUnlock(&xmlRngMutex);
+
+    return(ret);
+}
+
+/*
+ * xmlRandom:
+ *
+ * Generate a pseudo-random value using the thread-local PRNG.
+ *
+ * Returns a random value.
+ */
+unsigned
+xmlRandom(void) {
+#ifdef LIBXML_THREAD_ENABLED
+    return(xoroshiro64ss(xmlGetLocalRngState()));
+#else
+    return(xmlGlobalRandom());
+#endif
 }
 
diff --git a/enc.h b/enc.h
deleted file mode 100644
index a69a5d03c8599b35a5e5c79473c9fd8afec0fa20..0000000000000000000000000000000000000000
--- a/enc.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Summary: Internal Interfaces for encoding in libxml2
- * Description: this module describes a few interfaces which were
- *              added along with the API changes in 2.9.0
- *              those are private routines at this point
- *
- * Copy: See Copyright for the status of this software.
- *
- * Author: Daniel Veillard
- */
-
-#ifndef __XML_ENC_H__
-#define __XML_ENC_H__
-
-#include <libxml/tree.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int xmlCharEncFirstLineInt(xmlCharEncodingHandler *handler, xmlBufferPtr out,
-                           xmlBufferPtr in, int len);
-int xmlCharEncFirstLineInput(xmlParserInputBufferPtr input, int len);
-int xmlCharEncInput(xmlParserInputBufferPtr input, int flush);
-int xmlCharEncOutput(xmlOutputBufferPtr output, int init);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* __XML_ENC_H__ */
-
-
diff --git a/encoding.c b/encoding.c
index 5465359f244a67ab0ec72e0be45c5193ceb6ff4d..14ffafddbc02b0010fd0f9628a7c26710d219341 100644
--- a/encoding.c
+++ b/encoding.c
@@ -34,14 +34,15 @@
 
 #include <libxml/encoding.h>
 #include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
 #ifdef LIBXML_HTML_ENABLED
 #include <libxml/HTMLparser.h>
 #endif
-#include <libxml/globals.h>
 #include <libxml/xmlerror.h>
 
-#include "buf.h"
-#include "enc.h"
+#include "private/buf.h"
+#include "private/enc.h"
+#include "private/error.h"
 
 #ifdef LIBXML_ICU_ENABLED
 #include <unicode/ucnv.h>
@@ -57,9 +58,6 @@ struct _uconv_t {
 };
 #endif
 
-static xmlCharEncodingHandlerPtr xmlUTF16LEHandler = NULL;
-static xmlCharEncodingHandlerPtr xmlUTF16BEHandler = NULL;
-
 typedef struct _xmlCharEncodingAlias xmlCharEncodingAlias;
 typedef xmlCharEncodingAlias *xmlCharEncodingAliasPtr;
 struct _xmlCharEncodingAlias {
@@ -71,96 +69,8 @@ static xmlCharEncodingAliasPtr xmlCharEncodingAliases = NULL;
 static int xmlCharEncodingAliasesNb = 0;
 static int xmlCharEncodingAliasesMax = 0;
 
-#if defined(LIBXML_ICONV_ENABLED) || defined(LIBXML_ICU_ENABLED)
-#if 0
-#define DEBUG_ENCODING  /* Define this to get encoding traces */
-#endif
-#else
-#ifdef LIBXML_ISO8859X_ENABLED
-static void xmlRegisterCharEncodingHandlersISO8859x (void);
-#endif
-#endif
-
 static int xmlLittleEndian = 1;
 
-/**
- * xmlEncodingErrMemory:
- * @extra:  extra information
- *
- * Handle an out of memory condition
- */
-static void
-xmlEncodingErrMemory(const char *extra)
-{
-    __xmlSimpleError(XML_FROM_I18N, XML_ERR_NO_MEMORY, NULL, NULL, extra);
-}
-
-/**
- * xmlErrEncoding:
- * @error:  the error number
- * @msg:  the error message
- *
- * n encoding error
- */
-static void LIBXML_ATTR_FORMAT(2,0)
-xmlEncodingErr(xmlParserErrors error, const char *msg, const char *val)
-{
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL,
-                    XML_FROM_I18N, error, XML_ERR_FATAL,
-                    NULL, 0, val, NULL, NULL, 0, 0, msg, val);
-}
-
-#ifdef LIBXML_ICU_ENABLED
-static uconv_t*
-openIcuConverter(const char* name, int toUnicode)
-{
-  UErrorCode status = U_ZERO_ERROR;
-  uconv_t *conv = (uconv_t *) xmlMalloc(sizeof(uconv_t));
-  if (conv == NULL)
-    return NULL;
-
-  conv->pivot_source = conv->pivot_buf;
-  conv->pivot_target = conv->pivot_buf;
-
-  conv->uconv = ucnv_open(name, &status);
-  if (U_FAILURE(status))
-    goto error;
-
-  status = U_ZERO_ERROR;
-  if (toUnicode) {
-    ucnv_setToUCallBack(conv->uconv, UCNV_TO_U_CALLBACK_STOP,
-                        NULL, NULL, NULL, &status);
-  }
-  else {
-    ucnv_setFromUCallBack(conv->uconv, UCNV_FROM_U_CALLBACK_STOP,
-                        NULL, NULL, NULL, &status);
-  }
-  if (U_FAILURE(status))
-    goto error;
-
-  status = U_ZERO_ERROR;
-  conv->utf8 = ucnv_open("UTF-8", &status);
-  if (U_SUCCESS(status))
-    return conv;
-
-error:
-  if (conv->uconv)
-    ucnv_close(conv->uconv);
-  xmlFree(conv);
-  return NULL;
-}
-
-static void
-closeIcuConverter(uconv_t *conv)
-{
-  if (conv != NULL) {
-    ucnv_close(conv->uconv);
-    ucnv_close(conv->utf8);
-    xmlFree(conv);
-  }
-}
-#endif /* LIBXML_ICU_ENABLED */
-
 /************************************************************************
  *									*
  *		Conversions To/From UTF8 encoding			*
@@ -176,7 +86,9 @@ closeIcuConverter(uconv_t *conv)
  *
  * Take a block of ASCII chars in and try to convert it to an UTF-8
  * block of chars out.
- * Returns 0 if success, or -1 otherwise
+ *
+ * Returns the number of bytes written or an XML_ENC_ERR code.
+ *
  * The value of @inlen after return is the number of octets consumed
  *     if the return value is positive, else unpredictable.
  * The value of @outlen after return is the number of octets produced.
@@ -202,7 +114,7 @@ asciiToUTF8(unsigned char* out, int *outlen,
 	} else {
 	    *outlen = out - outstart;
 	    *inlen = processed - base;
-	    return(-1);
+	    return(XML_ENC_ERR_INPUT);
 	}
 
 	processed = (const unsigned char*) in;
@@ -223,7 +135,8 @@ asciiToUTF8(unsigned char* out, int *outlen,
  * Take a block of UTF-8 chars in and try to convert it to an ASCII
  * block of chars out.
  *
- * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise
+ * Returns the number of bytes written or an XML_ENC_ERR code.
+ *
  * The value of @inlen after return is the number of octets consumed
  *     if the return value is positive, else unpredictable.
  * The value of @outlen after return is the number of octets produced.
@@ -239,7 +152,8 @@ UTF8Toascii(unsigned char* out, int *outlen,
     unsigned int c, d;
     int trailing;
 
-    if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1);
+    if ((out == NULL) || (outlen == NULL) || (inlen == NULL))
+        return(XML_ENC_ERR_INTERNAL);
     if (in == NULL) {
         /*
 	 * initialization nothing to do
@@ -257,7 +171,7 @@ UTF8Toascii(unsigned char* out, int *outlen,
 	    /* trailing byte in leading position */
 	    *outlen = out - outstart;
 	    *inlen = processed - instart;
-	    return(-2);
+	    return(XML_ENC_ERR_INPUT);
         } else if (d < 0xE0)  { c= d & 0x1F; trailing= 1; }
         else if (d < 0xF0)  { c= d & 0x0F; trailing= 2; }
         else if (d < 0xF8)  { c= d & 0x07; trailing= 3; }
@@ -265,7 +179,7 @@ UTF8Toascii(unsigned char* out, int *outlen,
 	    /* no chance for this in Ascii */
 	    *outlen = out - outstart;
 	    *inlen = processed - instart;
-	    return(-2);
+	    return(XML_ENC_ERR_INPUT);
 	}
 
 	if (inend - in < trailing) {
@@ -288,7 +202,7 @@ UTF8Toascii(unsigned char* out, int *outlen,
 	    /* no chance for this in Ascii */
 	    *outlen = out - outstart;
 	    *inlen = processed - instart;
-	    return(-2);
+	    return(XML_ENC_ERR_INPUT);
 	}
 	processed = in;
     }
@@ -307,7 +221,9 @@ UTF8Toascii(unsigned char* out, int *outlen,
  *
  * Take a block of ISO Latin 1 chars in and try to convert it to an UTF-8
  * block of chars out.
- * Returns the number of bytes written if success, or -1 otherwise
+ *
+ * Returns the number of bytes written or an XML_ENC_ERR code.
+ *
  * The value of @inlen after return is the number of octets consumed
  *     if the return value is positive, else unpredictable.
  * The value of @outlen after return is the number of octets produced.
@@ -322,7 +238,7 @@ isolat1ToUTF8(unsigned char* out, int *outlen,
     const unsigned char* instop;
 
     if ((out == NULL) || (in == NULL) || (outlen == NULL) || (inlen == NULL))
-	return(-1);
+	return(XML_ENC_ERR_INTERNAL);
 
     outend = out + *outlen;
     inend = in + (*inlen);
@@ -356,7 +272,8 @@ isolat1ToUTF8(unsigned char* out, int *outlen,
  *
  * No op copy operation for UTF8 handling.
  *
- * Returns the number of bytes written, or -1 if lack of space.
+ * Returns the number of bytes written or an XML_ENC_ERR code.
+ *
  *     The value of *inlen after return is the number of octets consumed
  *     if the return value is positive, else unpredictable.
  */
@@ -367,7 +284,7 @@ UTF8ToUTF8(unsigned char* out, int *outlen,
     int len;
 
     if ((out == NULL) || (outlen == NULL) || (inlenb == NULL))
-	return(-1);
+	return(XML_ENC_ERR_INTERNAL);
     if (inb == NULL) {
         /* inb == NULL means output is initialized. */
         *outlen = 0;
@@ -380,7 +297,7 @@ UTF8ToUTF8(unsigned char* out, int *outlen,
 	len = *outlen;
     }
     if (len < 0)
-	return(-1);
+	return(XML_ENC_ERR_INTERNAL);
 
     /*
      * FIXME: Conversion functions must assure valid UTF-8, so we have
@@ -406,8 +323,8 @@ UTF8ToUTF8(unsigned char* out, int *outlen,
  * Take a block of UTF-8 chars in and try to convert it to an ISO Latin 1
  * block of chars out.
  *
- * Returns the number of bytes written if success, -2 if the transcoding fails,
-           or -1 otherwise
+ * Returns the number of bytes written or an XML_ENC_ERR code.
+ *
  * The value of @inlen after return is the number of octets consumed
  *     if the return value is positive, else unpredictable.
  * The value of @outlen after return is the number of octets produced.
@@ -423,7 +340,8 @@ UTF8Toisolat1(unsigned char* out, int *outlen,
     unsigned int c, d;
     int trailing;
 
-    if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1);
+    if ((out == NULL) || (outlen == NULL) || (inlen == NULL))
+        return(XML_ENC_ERR_INTERNAL);
     if (in == NULL) {
         /*
 	 * initialization nothing to do
@@ -441,7 +359,7 @@ UTF8Toisolat1(unsigned char* out, int *outlen,
 	    /* trailing byte in leading position */
 	    *outlen = out - outstart;
 	    *inlen = processed - instart;
-	    return(-2);
+	    return(XML_ENC_ERR_INPUT);
         } else if (d < 0xE0)  { c= d & 0x1F; trailing= 1; }
         else if (d < 0xF0)  { c= d & 0x0F; trailing= 2; }
         else if (d < 0xF8)  { c= d & 0x07; trailing= 3; }
@@ -449,7 +367,7 @@ UTF8Toisolat1(unsigned char* out, int *outlen,
 	    /* no chance for this in IsoLat1 */
 	    *outlen = out - outstart;
 	    *inlen = processed - instart;
-	    return(-2);
+	    return(XML_ENC_ERR_INPUT);
 	}
 
 	if (inend - in < trailing) {
@@ -462,7 +380,7 @@ UTF8Toisolat1(unsigned char* out, int *outlen,
 	    if (((d= *in++) & 0xC0) != 0x80) {
 		*outlen = out - outstart;
 		*inlen = processed - instart;
-		return(-2);
+		return(XML_ENC_ERR_INPUT);
 	    }
 	    c <<= 6;
 	    c |= d & 0x3F;
@@ -477,7 +395,7 @@ UTF8Toisolat1(unsigned char* out, int *outlen,
 	    /* no chance for this in IsoLat1 */
 	    *outlen = out - outstart;
 	    *inlen = processed - instart;
-	    return(-2);
+	    return(XML_ENC_ERR_INPUT);
 	}
 	processed = in;
     }
@@ -499,10 +417,10 @@ UTF8Toisolat1(unsigned char* out, int *outlen,
  * is the same between the native type of this machine and the
  * inputed one.
  *
- * Returns the number of bytes written, or -1 if lack of space, or -2
- *     if the transcoding fails (if *in is not a valid utf16 string)
- *     The value of *inlen after return is the number of octets consumed
- *     if the return value is positive, else unpredictable.
+ * Returns the number of bytes written or an XML_ENC_ERR code.
+ *
+ * The value of *inlen after return is the number of octets consumed
+ * if the return value is positive, else unpredictable.
  */
 static int
 UTF16LEToUTF8(unsigned char* out, int *outlen,
@@ -511,7 +429,7 @@ UTF16LEToUTF8(unsigned char* out, int *outlen,
     unsigned char* outstart = out;
     const unsigned char* processed = inb;
     unsigned char* outend;
-    unsigned short* in = (unsigned short*) inb;
+    unsigned short* in = (unsigned short *) (void *) inb;
     unsigned short* inend;
     unsigned int c, d, inlen;
     unsigned char *tmp;
@@ -532,7 +450,7 @@ UTF16LEToUTF8(unsigned char* out, int *outlen,
 	} else {
 	    tmp = (unsigned char *) in;
 	    c = *tmp++;
-	    c = c | (((unsigned int)*tmp) << 8);
+	    c = c | (*tmp << 8);
 	    in++;
 	}
         if ((c & 0xFC00) == 0xD800) {    /* surrogates */
@@ -544,7 +462,7 @@ UTF16LEToUTF8(unsigned char* out, int *outlen,
 	    } else {
 		tmp = (unsigned char *) in;
 		d = *tmp++;
-		d = d | (((unsigned int)*tmp) << 8);
+		d = d | (*tmp << 8);
 		in++;
 	    }
             if ((d & 0xFC00) == 0xDC00) {
@@ -556,7 +474,7 @@ UTF16LEToUTF8(unsigned char* out, int *outlen,
             else {
 		*outlen = out - outstart;
 		*inlenb = processed - inb;
-	        return(-2);
+	        return(XML_ENC_ERR_INPUT);
 	    }
         }
 
@@ -591,14 +509,13 @@ UTF16LEToUTF8(unsigned char* out, int *outlen,
  * Take a block of UTF-8 chars in and try to convert it to an UTF-16LE
  * block of chars out.
  *
- * Returns the number of bytes written, or -1 if lack of space, or -2
- *     if the transcoding failed.
+ * Returns the number of bytes written or an XML_ENC_ERR code.
  */
 static int
 UTF8ToUTF16LE(unsigned char* outb, int *outlen,
             const unsigned char* in, int *inlen)
 {
-    unsigned short* out = (unsigned short*) outb;
+    unsigned short* out = (unsigned short *) (void *) outb;
     const unsigned char* processed = in;
     const unsigned char *const instart = in;
     unsigned short* outstart= out;
@@ -610,7 +527,8 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen,
     unsigned short tmp1, tmp2;
 
     /* UTF16LE encoding has no BOM */
-    if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1);
+    if ((out == NULL) || (outlen == NULL) || (inlen == NULL))
+        return(XML_ENC_ERR_INTERNAL);
     if (in == NULL) {
 	*outlen = 0;
 	*inlen = 0;
@@ -625,7 +543,7 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen,
           /* trailing byte in leading position */
 	  *outlen = (out - outstart) * 2;
 	  *inlen = processed - instart;
-	  return(-2);
+	  return(XML_ENC_ERR_INPUT);
       } else if (d < 0xE0)  { c= d & 0x1F; trailing= 1; }
       else if (d < 0xF0)  { c= d & 0x0F; trailing= 2; }
       else if (d < 0xF8)  { c= d & 0x07; trailing= 3; }
@@ -633,7 +551,7 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen,
 	/* no chance for this in UTF-16 */
 	*outlen = (out - outstart) * 2;
 	*inlen = processed - instart;
-	return(-2);
+	return(XML_ENC_ERR_INPUT);
       }
 
       if (inend - in < trailing) {
@@ -655,7 +573,7 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen,
 		*out++ = c;
 	    } else {
 		tmp = (unsigned char *) out;
-		*tmp = c ;
+		*tmp = (unsigned char) c; /* Explicit truncation */
 		*(tmp + 1) = c >> 8 ;
 		out++;
 	    }
@@ -670,13 +588,13 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen,
 	    } else {
 		tmp1 = 0xD800 | (c >> 10);
 		tmp = (unsigned char *) out;
-		*tmp = (unsigned char) tmp1;
+		*tmp = (unsigned char) tmp1; /* Explicit truncation */
 		*(tmp + 1) = tmp1 >> 8;
 		out++;
 
 		tmp2 = 0xDC00 | (c & 0x03FF);
 		tmp = (unsigned char *) out;
-		*tmp  = (unsigned char) tmp2;
+		*tmp  = (unsigned char) tmp2; /* Explicit truncation */
 		*(tmp + 1) = tmp2 >> 8;
 		out++;
 	    }
@@ -700,8 +618,7 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen,
  * Take a block of UTF-8 chars in and try to convert it to an UTF-16
  * block of chars out.
  *
- * Returns the number of bytes written, or -1 if lack of space, or -2
- *     if the transcoding failed.
+ * Returns the number of bytes written or an XML_ENC_ERR code.
  */
 static int
 UTF8ToUTF16(unsigned char* outb, int *outlen,
@@ -716,10 +633,6 @@ UTF8ToUTF16(unsigned char* outb, int *outlen,
 	    outb[1] = 0xFE;
 	    *outlen = 2;
 	    *inlen = 0;
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-		    "Added FFFE Byte Order Mark\n");
-#endif
 	    return(2);
 	}
 	*outlen = 0;
@@ -742,10 +655,10 @@ UTF8ToUTF16(unsigned char* outb, int *outlen,
  * is the same between the native type of this machine and the
  * inputed one.
  *
- * Returns the number of bytes written, or -1 if lack of space, or -2
- *     if the transcoding fails (if *in is not a valid utf16 string)
+ * Returns the number of bytes written or an XML_ENC_ERR code.
+ *
  * The value of *inlen after return is the number of octets consumed
- *     if the return value is positive, else unpredictable.
+ * if the return value is positive, else unpredictable.
  */
 static int
 UTF16BEToUTF8(unsigned char* out, int *outlen,
@@ -754,7 +667,7 @@ UTF16BEToUTF8(unsigned char* out, int *outlen,
     unsigned char* outstart = out;
     const unsigned char* processed = inb;
     unsigned char* outend;
-    unsigned short* in = (unsigned short*) inb;
+    unsigned short* in = (unsigned short *) (void *) inb;
     unsigned short* inend;
     unsigned int c, d, inlen;
     unsigned char *tmp;
@@ -773,7 +686,7 @@ UTF16BEToUTF8(unsigned char* out, int *outlen,
 	if (xmlLittleEndian) {
 	    tmp = (unsigned char *) in;
 	    c = *tmp++;
-	    c = (c << 8) | (unsigned int) *tmp;
+	    c = (c << 8) | *tmp;
 	    in++;
 	} else {
 	    c= *in++;
@@ -785,7 +698,7 @@ UTF16BEToUTF8(unsigned char* out, int *outlen,
 	    if (xmlLittleEndian) {
 		tmp = (unsigned char *) in;
 		d = *tmp++;
-		d = (d << 8) | (unsigned int) *tmp;
+		d = (d << 8) | *tmp;
 		in++;
 	    } else {
 		d= *in++;
@@ -799,7 +712,7 @@ UTF16BEToUTF8(unsigned char* out, int *outlen,
             else {
 		*outlen = out - outstart;
 		*inlenb = processed - inb;
-	        return(-2);
+	        return(XML_ENC_ERR_INPUT);
 	    }
         }
 
@@ -834,14 +747,13 @@ UTF16BEToUTF8(unsigned char* out, int *outlen,
  * Take a block of UTF-8 chars in and try to convert it to an UTF-16BE
  * block of chars out.
  *
- * Returns the number of byte written, or -1 by lack of space, or -2
- *     if the transcoding failed.
+ * Returns the number of bytes written or an XML_ENC_ERR code.
  */
 static int
 UTF8ToUTF16BE(unsigned char* outb, int *outlen,
             const unsigned char* in, int *inlen)
 {
-    unsigned short* out = (unsigned short*) outb;
+    unsigned short* out = (unsigned short *) (void *) outb;
     const unsigned char* processed = in;
     const unsigned char *const instart = in;
     unsigned short* outstart= out;
@@ -853,7 +765,8 @@ UTF8ToUTF16BE(unsigned char* outb, int *outlen,
     unsigned short tmp1, tmp2;
 
     /* UTF-16BE has no BOM */
-    if ((outb == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1);
+    if ((outb == NULL) || (outlen == NULL) || (inlen == NULL))
+        return(XML_ENC_ERR_INTERNAL);
     if (in == NULL) {
 	*outlen = 0;
 	*inlen = 0;
@@ -868,7 +781,7 @@ UTF8ToUTF16BE(unsigned char* outb, int *outlen,
           /* trailing byte in leading position */
 	  *outlen = out - outstart;
 	  *inlen = processed - instart;
-	  return(-2);
+	  return(XML_ENC_ERR_INPUT);
       } else if (d < 0xE0)  { c= d & 0x1F; trailing= 1; }
       else if (d < 0xF0)  { c= d & 0x0F; trailing= 2; }
       else if (d < 0xF8)  { c= d & 0x07; trailing= 3; }
@@ -876,7 +789,7 @@ UTF8ToUTF16BE(unsigned char* outb, int *outlen,
           /* no chance for this in UTF-16 */
 	  *outlen = out - outstart;
 	  *inlen = processed - instart;
-	  return(-2);
+	  return(XML_ENC_ERR_INPUT);
       }
 
       if (inend - in < trailing) {
@@ -895,7 +808,7 @@ UTF8ToUTF16BE(unsigned char* outb, int *outlen,
 	    if (xmlLittleEndian) {
 		tmp = (unsigned char *) out;
 		*tmp = c >> 8;
-		*(tmp + 1) = c;
+		*(tmp + 1) = (unsigned char) c; /* Explicit truncation */
 		out++;
 	    } else {
 		*out++ = c;
@@ -908,13 +821,13 @@ UTF8ToUTF16BE(unsigned char* outb, int *outlen,
 		tmp1 = 0xD800 | (c >> 10);
 		tmp = (unsigned char *) out;
 		*tmp = tmp1 >> 8;
-		*(tmp + 1) = (unsigned char) tmp1;
+		*(tmp + 1) = (unsigned char) tmp1; /* Explicit truncation */
 		out++;
 
 		tmp2 = 0xDC00 | (c & 0x03FF);
 		tmp = (unsigned char *) out;
 		*tmp = tmp2 >> 8;
-		*(tmp + 1) = (unsigned char) tmp2;
+		*(tmp + 1) = (unsigned char) tmp2; /* Explicit truncation */
 		out++;
 	    } else {
 		*out++ = 0xD800 | (c >> 10);
@@ -1047,7 +960,7 @@ xmlGetEncodingAlias(const char *alias) {
 	return(NULL);
 
     for (i = 0;i < 99;i++) {
-        upper[i] = toupper(alias[i]);
+        upper[i] = (char) toupper((unsigned char) alias[i]);
 	if (upper[i] == 0) break;
     }
     upper[i] = 0;
@@ -1077,29 +990,32 @@ int
 xmlAddEncodingAlias(const char *name, const char *alias) {
     int i;
     char upper[100];
+    char *nameCopy, *aliasCopy;
 
     if ((name == NULL) || (alias == NULL))
 	return(-1);
 
     for (i = 0;i < 99;i++) {
-        upper[i] = toupper(alias[i]);
+        upper[i] = (char) toupper((unsigned char) alias[i]);
 	if (upper[i] == 0) break;
     }
     upper[i] = 0;
 
-    if (xmlCharEncodingAliases == NULL) {
-	xmlCharEncodingAliasesNb = 0;
-	xmlCharEncodingAliasesMax = 20;
-	xmlCharEncodingAliases = (xmlCharEncodingAliasPtr)
-	      xmlMalloc(xmlCharEncodingAliasesMax * sizeof(xmlCharEncodingAlias));
-	if (xmlCharEncodingAliases == NULL)
-	    return(-1);
-    } else if (xmlCharEncodingAliasesNb >= xmlCharEncodingAliasesMax) {
-	xmlCharEncodingAliasesMax *= 2;
-	xmlCharEncodingAliases = (xmlCharEncodingAliasPtr)
-	      xmlRealloc(xmlCharEncodingAliases,
-		         xmlCharEncodingAliasesMax * sizeof(xmlCharEncodingAlias));
+    if (xmlCharEncodingAliasesNb >= xmlCharEncodingAliasesMax) {
+        xmlCharEncodingAliasPtr tmp;
+        size_t newSize = xmlCharEncodingAliasesMax ?
+                         xmlCharEncodingAliasesMax * 2 :
+                         20;
+
+        tmp = (xmlCharEncodingAliasPtr)
+              xmlRealloc(xmlCharEncodingAliases,
+                         newSize * sizeof(xmlCharEncodingAlias));
+        if (tmp == NULL)
+            return(-1);
+        xmlCharEncodingAliases = tmp;
+        xmlCharEncodingAliasesMax = newSize;
     }
+
     /*
      * Walk down the list looking for a definition of the alias
      */
@@ -1108,16 +1024,27 @@ xmlAddEncodingAlias(const char *name, const char *alias) {
 	    /*
 	     * Replace the definition.
 	     */
+	    nameCopy = xmlMemStrdup(name);
+            if (nameCopy == NULL)
+                return(-1);
 	    xmlFree((char *) xmlCharEncodingAliases[i].name);
-	    xmlCharEncodingAliases[i].name = xmlMemStrdup(name);
+	    xmlCharEncodingAliases[i].name = nameCopy;
 	    return(0);
 	}
     }
     /*
      * Add the definition
      */
-    xmlCharEncodingAliases[xmlCharEncodingAliasesNb].name = xmlMemStrdup(name);
-    xmlCharEncodingAliases[xmlCharEncodingAliasesNb].alias = xmlMemStrdup(upper);
+    nameCopy = xmlMemStrdup(name);
+    if (nameCopy == NULL)
+        return(-1);
+    aliasCopy = xmlMemStrdup(upper);
+    if (aliasCopy == NULL) {
+        xmlFree(nameCopy);
+        return(-1);
+    }
+    xmlCharEncodingAliases[xmlCharEncodingAliasesNb].name = nameCopy;
+    xmlCharEncodingAliases[xmlCharEncodingAliasesNb].alias = aliasCopy;
     xmlCharEncodingAliasesNb++;
     return(0);
 }
@@ -1184,7 +1111,7 @@ xmlParseCharEncoding(const char* name)
 	name = alias;
 
     for (i = 0;i < 499;i++) {
-        upper[i] = toupper(name[i]);
+        upper[i] = (char) toupper((unsigned char) name[i]);
 	if (upper[i] == 0) break;
     }
     upper[i] = 0;
@@ -1233,9 +1160,6 @@ xmlParseCharEncoding(const char* name)
     if (!strcmp(upper, "SHIFT_JIS")) return(XML_CHAR_ENCODING_SHIFT_JIS);
     if (!strcmp(upper, "EUC-JP")) return(XML_CHAR_ENCODING_EUC_JP);
 
-#ifdef DEBUG_ENCODING
-    xmlGenericError(xmlGenericErrorContext, "Unknown encoding %s\n", name);
-#endif
     return(XML_CHAR_ENCODING_ERROR);
 }
 
@@ -1311,19 +1235,104 @@ xmlGetCharEncodingName(xmlCharEncoding enc) {
  *									*
  ************************************************************************/
 
+#if !defined(LIBXML_ICONV_ENABLED) && !defined(LIBXML_ICU_ENABLED) && \
+    defined(LIBXML_ISO8859X_ENABLED)
+
+#define DECLARE_ISO_FUNCS(n) \
+    static int ISO8859_##n##ToUTF8(unsigned char* out, int *outlen, \
+                                   const unsigned char* in, int *inlen); \
+    static int UTF8ToISO8859_##n(unsigned char* out, int *outlen, \
+                                 const unsigned char* in, int *inlen);
+
+/** DOC_DISABLE */
+DECLARE_ISO_FUNCS(2)
+DECLARE_ISO_FUNCS(3)
+DECLARE_ISO_FUNCS(4)
+DECLARE_ISO_FUNCS(5)
+DECLARE_ISO_FUNCS(6)
+DECLARE_ISO_FUNCS(7)
+DECLARE_ISO_FUNCS(8)
+DECLARE_ISO_FUNCS(9)
+DECLARE_ISO_FUNCS(10)
+DECLARE_ISO_FUNCS(11)
+DECLARE_ISO_FUNCS(13)
+DECLARE_ISO_FUNCS(14)
+DECLARE_ISO_FUNCS(15)
+DECLARE_ISO_FUNCS(16)
+/** DOC_ENABLE */
+
+#endif /* LIBXML_ISO8859X_ENABLED */
+
+#ifdef LIBXML_ICONV_ENABLED
+  #define EMPTY_ICONV , (iconv_t) 0, (iconv_t) 0
+#else
+  #define EMPTY_ICONV
+#endif
+
+#ifdef LIBXML_ICU_ENABLED
+  #define EMPTY_UCONV , NULL, NULL
+#else
+  #define EMPTY_UCONV
+#endif
+
+#define MAKE_HANDLER(name, in, out) \
+    { (char *) name, in, out EMPTY_ICONV EMPTY_UCONV }
+
+static const xmlCharEncodingHandler defaultHandlers[] = {
+#ifdef LIBXML_OUTPUT_ENABLED
+    MAKE_HANDLER("UTF-16LE", UTF16LEToUTF8, UTF8ToUTF16LE)
+    ,MAKE_HANDLER("UTF-16BE", UTF16BEToUTF8, UTF8ToUTF16BE)
+    ,MAKE_HANDLER("UTF-16", UTF16LEToUTF8, UTF8ToUTF16)
+    ,MAKE_HANDLER("ISO-8859-1", isolat1ToUTF8, UTF8Toisolat1)
+    ,MAKE_HANDLER("ASCII", asciiToUTF8, UTF8Toascii)
+    ,MAKE_HANDLER("US-ASCII", asciiToUTF8, UTF8Toascii)
+#ifdef LIBXML_HTML_ENABLED
+    ,MAKE_HANDLER("HTML", NULL, UTF8ToHtml)
+#endif
+#else
+    MAKE_HANDLER("UTF-16LE", UTF16LEToUTF8, NULL)
+    ,MAKE_HANDLER("UTF-16BE", UTF16BEToUTF8, NULL)
+    ,MAKE_HANDLER("UTF-16", UTF16LEToUTF8, NULL)
+    ,MAKE_HANDLER("ISO-8859-1", isolat1ToUTF8, NULL)
+    ,MAKE_HANDLER("ASCII", asciiToUTF8, NULL)
+    ,MAKE_HANDLER("US-ASCII", asciiToUTF8, NULL)
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+#if !defined(LIBXML_ICONV_ENABLED) && !defined(LIBXML_ICU_ENABLED) && \
+    defined(LIBXML_ISO8859X_ENABLED)
+    ,MAKE_HANDLER("ISO-8859-2", ISO8859_2ToUTF8, UTF8ToISO8859_2)
+    ,MAKE_HANDLER("ISO-8859-3", ISO8859_3ToUTF8, UTF8ToISO8859_3)
+    ,MAKE_HANDLER("ISO-8859-4", ISO8859_4ToUTF8, UTF8ToISO8859_4)
+    ,MAKE_HANDLER("ISO-8859-5", ISO8859_5ToUTF8, UTF8ToISO8859_5)
+    ,MAKE_HANDLER("ISO-8859-6", ISO8859_6ToUTF8, UTF8ToISO8859_6)
+    ,MAKE_HANDLER("ISO-8859-7", ISO8859_7ToUTF8, UTF8ToISO8859_7)
+    ,MAKE_HANDLER("ISO-8859-8", ISO8859_8ToUTF8, UTF8ToISO8859_8)
+    ,MAKE_HANDLER("ISO-8859-9", ISO8859_9ToUTF8, UTF8ToISO8859_9)
+    ,MAKE_HANDLER("ISO-8859-10", ISO8859_10ToUTF8, UTF8ToISO8859_10)
+    ,MAKE_HANDLER("ISO-8859-11", ISO8859_11ToUTF8, UTF8ToISO8859_11)
+    ,MAKE_HANDLER("ISO-8859-13", ISO8859_13ToUTF8, UTF8ToISO8859_13)
+    ,MAKE_HANDLER("ISO-8859-14", ISO8859_14ToUTF8, UTF8ToISO8859_14)
+    ,MAKE_HANDLER("ISO-8859-15", ISO8859_15ToUTF8, UTF8ToISO8859_15)
+    ,MAKE_HANDLER("ISO-8859-16", ISO8859_16ToUTF8, UTF8ToISO8859_16)
+#endif
+};
+
+#define NUM_DEFAULT_HANDLERS \
+    (sizeof(defaultHandlers) / sizeof(defaultHandlers[0]))
+
+static const xmlCharEncodingHandler xmlUTF8Handler =
+    MAKE_HANDLER("UTF-8", UTF8ToUTF8, UTF8ToUTF8);
+
+static const xmlCharEncodingHandler *xmlUTF16LEHandler = &defaultHandlers[0];
+static const xmlCharEncodingHandler *xmlUTF16BEHandler = &defaultHandlers[1];
+static const xmlCharEncodingHandler *xmlLatin1Handler = &defaultHandlers[3];
+static const xmlCharEncodingHandler *xmlAsciiHandler = &defaultHandlers[4];
 
 /* the size should be growable, but it's not a big deal ... */
 #define MAX_ENCODING_HANDLERS 50
 static xmlCharEncodingHandlerPtr *handlers = NULL;
 static int nbCharEncodingHandler = 0;
 
-/*
- * The default is UTF-8 for XML, that's also the default used for the
- * parser internals, so the default encoding handler is NULL
- */
-
-static xmlCharEncodingHandlerPtr xmlDefaultCharEncodingHandler = NULL;
-
 /**
  * xmlNewCharEncodingHandler:
  * @name:  the encoding name, in UTF-8 format (ASCII actually)
@@ -1354,21 +1363,16 @@ xmlNewCharEncodingHandler(const char *name,
     /*
      * Keep only the uppercase version of the encoding.
      */
-    if (name == NULL) {
-        xmlEncodingErr(XML_I18N_NO_NAME,
-		       "xmlNewCharEncodingHandler : no name !\n", NULL);
+    if (name == NULL)
 	return(NULL);
-    }
     for (i = 0;i < 499;i++) {
-        upper[i] = toupper(name[i]);
+        upper[i] = (char) toupper((unsigned char) name[i]);
 	if (upper[i] == 0) break;
     }
     upper[i] = 0;
     up = xmlMemStrdup(upper);
-    if (up == NULL) {
-        xmlEncodingErrMemory("xmlNewCharEncodingHandler : out of memory !\n");
+    if (up == NULL)
 	return(NULL);
-    }
 
     /*
      * allocate and fill-up an handler block.
@@ -1377,7 +1381,6 @@ xmlNewCharEncodingHandler(const char *name,
               xmlMalloc(sizeof(xmlCharEncodingHandler));
     if (handler == NULL) {
         xmlFree(up);
-        xmlEncodingErrMemory("xmlNewCharEncodingHandler : out of memory !\n");
 	return(NULL);
     }
     memset(handler, 0, sizeof(xmlCharEncodingHandler));
@@ -1398,74 +1401,31 @@ xmlNewCharEncodingHandler(const char *name,
      * registers and returns the handler.
      */
     xmlRegisterCharEncodingHandler(handler);
-#ifdef DEBUG_ENCODING
-    xmlGenericError(xmlGenericErrorContext,
-	    "Registered encoding handler for %s\n", name);
-#endif
     return(handler);
 }
 
 /**
  * xmlInitCharEncodingHandlers:
  *
- * DEPRECATED: This function will be made private. Call xmlInitParser to
- * initialize the library.
- *
- * Initialize the char encoding support, it registers the default
- * encoding supported.
- * NOTE: while public, this function usually doesn't need to be called
- *       in normal processing.
+ * DEPRECATED: Alias for xmlInitParser.
  */
 void
 xmlInitCharEncodingHandlers(void) {
+    xmlInitParser();
+}
+
+/**
+ * xmlInitEncodingInternal:
+ *
+ * Initialize the char encoding support.
+ */
+void
+xmlInitEncodingInternal(void) {
     unsigned short int tst = 0x1234;
     unsigned char *ptr = (unsigned char *) &tst;
 
-    if (handlers != NULL) return;
-
-    handlers = (xmlCharEncodingHandlerPtr *)
-        xmlMalloc(MAX_ENCODING_HANDLERS * sizeof(xmlCharEncodingHandlerPtr));
-
     if (*ptr == 0x12) xmlLittleEndian = 0;
-    else if (*ptr == 0x34) xmlLittleEndian = 1;
-    else {
-        xmlEncodingErr(XML_ERR_INTERNAL_ERROR,
-	               "Odd problem at endianness detection\n", NULL);
-    }
-
-    if (handlers == NULL) {
-        xmlEncodingErrMemory("xmlInitCharEncodingHandlers : out of memory !\n");
-	return;
-    }
-    xmlNewCharEncodingHandler("UTF-8", UTF8ToUTF8, UTF8ToUTF8);
-#ifdef LIBXML_OUTPUT_ENABLED
-    xmlUTF16LEHandler =
-          xmlNewCharEncodingHandler("UTF-16LE", UTF16LEToUTF8, UTF8ToUTF16LE);
-    xmlUTF16BEHandler =
-          xmlNewCharEncodingHandler("UTF-16BE", UTF16BEToUTF8, UTF8ToUTF16BE);
-    xmlNewCharEncodingHandler("UTF-16", UTF16LEToUTF8, UTF8ToUTF16);
-    xmlNewCharEncodingHandler("ISO-8859-1", isolat1ToUTF8, UTF8Toisolat1);
-    xmlNewCharEncodingHandler("ASCII", asciiToUTF8, UTF8Toascii);
-    xmlNewCharEncodingHandler("US-ASCII", asciiToUTF8, UTF8Toascii);
-#ifdef LIBXML_HTML_ENABLED
-    xmlNewCharEncodingHandler("HTML", NULL, UTF8ToHtml);
-#endif
-#else
-    xmlUTF16LEHandler =
-          xmlNewCharEncodingHandler("UTF-16LE", UTF16LEToUTF8, NULL);
-    xmlUTF16BEHandler =
-          xmlNewCharEncodingHandler("UTF-16BE", UTF16BEToUTF8, NULL);
-    xmlNewCharEncodingHandler("UTF-16", UTF16LEToUTF8, NULL);
-    xmlNewCharEncodingHandler("ISO-8859-1", isolat1ToUTF8, NULL);
-    xmlNewCharEncodingHandler("ASCII", asciiToUTF8, NULL);
-    xmlNewCharEncodingHandler("US-ASCII", asciiToUTF8, NULL);
-#endif /* LIBXML_OUTPUT_ENABLED */
-#if !defined(LIBXML_ICONV_ENABLED) && !defined(LIBXML_ICU_ENABLED)
-#ifdef LIBXML_ISO8859X_ENABLED
-    xmlRegisterCharEncodingHandlersISO8859x ();
-#endif
-#endif
-
+    else xmlLittleEndian = 1;
 }
 
 /**
@@ -1496,7 +1456,6 @@ xmlCleanupCharEncodingHandlers(void) {
     xmlFree(handlers);
     handlers = NULL;
     nbCharEncodingHandler = 0;
-    xmlDefaultCharEncodingHandler = NULL;
 }
 
 /**
@@ -1507,19 +1466,16 @@ xmlCleanupCharEncodingHandlers(void) {
  */
 void
 xmlRegisterCharEncodingHandler(xmlCharEncodingHandlerPtr handler) {
-    if (handlers == NULL) xmlInitCharEncodingHandlers();
-    if ((handler == NULL) || (handlers == NULL)) {
-        xmlEncodingErr(XML_I18N_NO_HANDLER,
-		"xmlRegisterCharEncodingHandler: NULL handler !\n", NULL);
-        goto free_handler;
+    if (handler == NULL)
+        return;
+    if (handlers == NULL) {
+        handlers = xmlMalloc(MAX_ENCODING_HANDLERS * sizeof(handlers[0]));
+        if (handlers == NULL)
+            goto free_handler;
     }
 
-    if (nbCharEncodingHandler >= MAX_ENCODING_HANDLERS) {
-        xmlEncodingErr(XML_I18N_EXCESS_HANDLER,
-	"xmlRegisterCharEncodingHandler: Too many handler registered, see %s\n",
-	               "MAX_ENCODING_HANDLERS");
+    if (nbCharEncodingHandler >= MAX_ENCODING_HANDLERS)
         goto free_handler;
-    }
     handlers[nbCharEncodingHandler++] = handler;
     return;
 
@@ -1532,285 +1488,516 @@ free_handler:
     }
 }
 
+#ifdef LIBXML_ICONV_ENABLED
+static int
+xmlCreateIconvHandler(const char *name, xmlCharEncodingHandler **out) {
+    xmlCharEncodingHandlerPtr enc = NULL;
+    iconv_t icv_in = (iconv_t) -1;
+    iconv_t icv_out = (iconv_t) -1;
+    int ret;
+
+    *out = NULL;
+
+    icv_in = iconv_open("UTF-8", name);
+    if (icv_in == (iconv_t) -1) {
+        if (errno == EINVAL)
+            ret = XML_ERR_UNSUPPORTED_ENCODING;
+        else if (errno == ENOMEM)
+            ret = XML_ERR_NO_MEMORY;
+        else
+            ret = XML_ERR_SYSTEM;
+        goto error;
+    }
+
+    icv_out = iconv_open(name, "UTF-8");
+    if (icv_out == (iconv_t) -1) {
+        if (errno == EINVAL)
+            ret = XML_ERR_UNSUPPORTED_ENCODING;
+        else if (errno == ENOMEM)
+            ret = XML_ERR_NO_MEMORY;
+        else
+            ret = XML_ERR_SYSTEM;
+        goto error;
+    }
+
+    enc = xmlMalloc(sizeof(*enc));
+    if (enc == NULL) {
+        ret = XML_ERR_NO_MEMORY;
+        goto error;
+    }
+    memset(enc, 0, sizeof(*enc));
+
+    enc->name = xmlMemStrdup(name);
+    if (enc->name == NULL) {
+        ret = XML_ERR_NO_MEMORY;
+        goto error;
+    }
+    enc->iconv_in = icv_in;
+    enc->iconv_out = icv_out;
+
+    *out = enc;
+    return(0);
+
+error:
+    if (enc != NULL)
+        xmlFree(enc);
+    if (icv_in != (iconv_t) -1)
+        iconv_close(icv_in);
+    if (icv_out != (iconv_t) -1)
+        iconv_close(icv_out);
+    return(ret);
+}
+#endif /* LIBXML_ICONV_ENABLED */
+
+#ifdef LIBXML_ICU_ENABLED
+static int
+openIcuConverter(const char* name, int toUnicode, uconv_t **out)
+{
+    UErrorCode status;
+    uconv_t *conv;
+
+    *out = NULL;
+
+    conv = (uconv_t *) xmlMalloc(sizeof(uconv_t));
+    if (conv == NULL)
+        return(XML_ERR_NO_MEMORY);
+
+    conv->pivot_source = conv->pivot_buf;
+    conv->pivot_target = conv->pivot_buf;
+
+    status = U_ZERO_ERROR;
+    conv->uconv = ucnv_open(name, &status);
+    if (U_FAILURE(status))
+        goto error;
+
+    status = U_ZERO_ERROR;
+    if (toUnicode) {
+        ucnv_setToUCallBack(conv->uconv, UCNV_TO_U_CALLBACK_STOP,
+                                                NULL, NULL, NULL, &status);
+    }
+    else {
+        ucnv_setFromUCallBack(conv->uconv, UCNV_FROM_U_CALLBACK_STOP,
+                                                NULL, NULL, NULL, &status);
+    }
+    if (U_FAILURE(status))
+        goto error;
+
+    status = U_ZERO_ERROR;
+    conv->utf8 = ucnv_open("UTF-8", &status);
+    if (U_FAILURE(status))
+        goto error;
+
+    *out = conv;
+    return(0);
+
+error:
+    if (conv->uconv)
+        ucnv_close(conv->uconv);
+    xmlFree(conv);
+
+    if (status == U_FILE_ACCESS_ERROR)
+        return(XML_ERR_UNSUPPORTED_ENCODING);
+    if (status == U_MEMORY_ALLOCATION_ERROR)
+        return(XML_ERR_NO_MEMORY);
+    return(XML_ERR_SYSTEM);
+}
+
+static void
+closeIcuConverter(uconv_t *conv)
+{
+    if (conv == NULL)
+        return;
+    ucnv_close(conv->uconv);
+    ucnv_close(conv->utf8);
+    xmlFree(conv);
+}
+
+static int
+xmlCreateUconvHandler(const char *name, xmlCharEncodingHandler **out) {
+    xmlCharEncodingHandlerPtr enc = NULL;
+    uconv_t *ucv_in = NULL;
+    uconv_t *ucv_out = NULL;
+    int ret;
+
+    ret = openIcuConverter(name, 1, &ucv_in);
+    if (ret != 0)
+        goto error;
+    ret = openIcuConverter(name, 0, &ucv_out);
+    if (ret != 0)
+        goto error;
+
+    enc = (xmlCharEncodingHandlerPtr)
+           xmlMalloc(sizeof(xmlCharEncodingHandler));
+    if (enc == NULL) {
+        ret = XML_ERR_NO_MEMORY;
+        goto error;
+    }
+    memset(enc, 0, sizeof(xmlCharEncodingHandler));
+
+    enc->name = xmlMemStrdup(name);
+    if (enc->name == NULL) {
+        ret = XML_ERR_NO_MEMORY;
+        goto error;
+    }
+    enc->input = NULL;
+    enc->output = NULL;
+    enc->uconv_in = ucv_in;
+    enc->uconv_out = ucv_out;
+
+    *out = enc;
+    return(0);
+
+error:
+    if (enc != NULL)
+        xmlFree(enc);
+    if (ucv_in != NULL)
+        closeIcuConverter(ucv_in);
+    if (ucv_out != NULL)
+        closeIcuConverter(ucv_out);
+    return(ret);
+}
+#endif /* LIBXML_ICU_ENABLED */
+
 /**
- * xmlGetCharEncodingHandler:
+ * xmlFindExtraHandler:
+ * @name:  a string describing the char encoding.
+ * @output:  boolean, use handler for output
+ * @out:  pointer to resulting handler
+ *
+ * Search the non-default handlers for an exact match.
+ *
+ * Returns 0 on success, 1 if no handler was found, -1 if a memory
+ * allocation failed.
+ */
+static int
+xmlFindExtraHandler(const char *name, int output,
+                    xmlCharEncodingHandler **out) {
+    int ret;
+    int i;
+
+    (void) ret;
+
+    if (handlers != NULL) {
+        for (i = 0; i < nbCharEncodingHandler; i++) {
+            xmlCharEncodingHandler *handler = handlers[i];
+
+            if (!xmlStrcasecmp((const xmlChar *) name,
+                               (const xmlChar *) handler->name)) {
+                if (output) {
+                    if (handler->output != NULL) {
+                        *out = handler;
+                        return(0);
+                    }
+                } else {
+                    if (handler->input != NULL) {
+                        *out = handler;
+                        return(0);
+                    }
+                }
+            }
+        }
+    }
+
+#ifdef LIBXML_ICONV_ENABLED
+    ret = xmlCreateIconvHandler(name, out);
+    if (*out != NULL)
+        return(0);
+    if (ret != XML_ERR_UNSUPPORTED_ENCODING)
+        return(ret);
+#endif /* LIBXML_ICONV_ENABLED */
+
+#ifdef LIBXML_ICU_ENABLED
+    ret = xmlCreateUconvHandler(name, out);
+    if (*out != NULL)
+        return(0);
+    if (ret != XML_ERR_UNSUPPORTED_ENCODING)
+        return(ret);
+#endif /* LIBXML_ICU_ENABLED */
+
+    return(XML_ERR_UNSUPPORTED_ENCODING);
+}
+
+/**
+ * xmlFindHandler:
+ * @name:  a string describing the char encoding.
+ * @output:  boolean, use handler for output
+ * @out:  pointer to resulting handler
+ *
+ * Search all handlers for an exact match.
+ *
+ * Returns 0 on success, 1 if no handler was found, -1 if a memory
+ * allocation failed.
+ */
+static int
+xmlFindHandler(const char *name, int output, xmlCharEncodingHandler **out) {
+    int i;
+
+    /*
+     * Check for default handlers
+     */
+    for (i = 0; i < (int) NUM_DEFAULT_HANDLERS; i++) {
+        xmlCharEncodingHandler *handler;
+
+        handler = (xmlCharEncodingHandler *) &defaultHandlers[i];
+
+        if (xmlStrcasecmp((const xmlChar *) name,
+                          (const xmlChar *) handler->name) == 0) {
+            if (output) {
+                if (handler->output != NULL) {
+                    *out = handler;
+                    return(0);
+                }
+            } else {
+                if (handler->input != NULL) {
+                    *out = handler;
+                    return(0);
+                }
+            }
+        }
+    }
+
+    /*
+     * Check for other handlers
+     */
+    return(xmlFindExtraHandler(name, output, out));
+}
+
+/**
+ * xmlLookupCharEncodingHandler:
  * @enc:  an xmlCharEncoding value.
+ * @out:  pointer to result
+ *
+ * Find or create a handler matching the encoding. If no default or
+ * registered handler could be found, try to create a handler using
+ * iconv or ICU if supported.
+ *
+ * The handler must be closed with xmlCharEncCloseFunc.
  *
- * Search in the registered set the handler able to read/write that encoding.
+ * Available since 2.13.0.
  *
- * Returns the handler or NULL if not found
+ * Returns an xmlParserErrors error code.
  */
-xmlCharEncodingHandlerPtr
-xmlGetCharEncodingHandler(xmlCharEncoding enc) {
-    xmlCharEncodingHandlerPtr handler;
+int
+xmlLookupCharEncodingHandler(xmlCharEncoding enc,
+                             xmlCharEncodingHandler **out) {
+    const char *name = NULL;
+    static const char *const ebcdicNames[] = {
+        "EBCDIC", "ebcdic", "EBCDIC-US", "IBM-037"
+    };
+    static const char *const ucs4Names[] = {
+        "ISO-10646-UCS-4", "UCS-4", "UCS4"
+    };
+    static const char *const ucs2Names[] = {
+        "ISO-10646-UCS-2", "UCS-2", "UCS2"
+    };
+    static const char *const shiftJisNames[] = {
+        "SHIFT-JIS", "SHIFT_JIS", "Shift_JIS",
+    };
+    const char *const *names = NULL;
+    int numNames = 0;
+    int ret;
+    int i;
+
+    if (out == NULL)
+        return(XML_ERR_ARGUMENT);
+    *out = NULL;
 
-    if (handlers == NULL) xmlInitCharEncodingHandlers();
     switch (enc) {
         case XML_CHAR_ENCODING_ERROR:
-	    return(NULL);
+	    return(XML_ERR_UNSUPPORTED_ENCODING);
         case XML_CHAR_ENCODING_NONE:
-	    return(NULL);
+	    return(0);
         case XML_CHAR_ENCODING_UTF8:
-	    return(NULL);
+	    return(0);
         case XML_CHAR_ENCODING_UTF16LE:
-	    return(xmlUTF16LEHandler);
+	    *out = (xmlCharEncodingHandler *) xmlUTF16LEHandler;
+            return(0);
         case XML_CHAR_ENCODING_UTF16BE:
-	    return(xmlUTF16BEHandler);
+	    *out = (xmlCharEncodingHandler *) xmlUTF16BEHandler;
+            return(0);
         case XML_CHAR_ENCODING_EBCDIC:
-            handler = xmlFindCharEncodingHandler("EBCDIC");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("ebcdic");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("EBCDIC-US");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("IBM-037");
-            if (handler != NULL) return(handler);
+            names = ebcdicNames;
+            numNames = sizeof(ebcdicNames) / sizeof(ebcdicNames[0]);
 	    break;
         case XML_CHAR_ENCODING_UCS4BE:
-            handler = xmlFindCharEncodingHandler("ISO-10646-UCS-4");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("UCS-4");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("UCS4");
-            if (handler != NULL) return(handler);
-	    break;
         case XML_CHAR_ENCODING_UCS4LE:
-            handler = xmlFindCharEncodingHandler("ISO-10646-UCS-4");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("UCS-4");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("UCS4");
-            if (handler != NULL) return(handler);
+            names = ucs4Names;
+            numNames = sizeof(ucs4Names) / sizeof(ucs4Names[0]);
 	    break;
         case XML_CHAR_ENCODING_UCS4_2143:
 	    break;
         case XML_CHAR_ENCODING_UCS4_3412:
 	    break;
         case XML_CHAR_ENCODING_UCS2:
-            handler = xmlFindCharEncodingHandler("ISO-10646-UCS-2");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("UCS-2");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("UCS2");
-            if (handler != NULL) return(handler);
+            names = ucs2Names;
+            numNames = sizeof(ucs2Names) / sizeof(ucs2Names[0]);
 	    break;
 
-	    /*
-	     * We used to keep ISO Latin encodings native in the
-	     * generated data. This led to so many problems that
-	     * this has been removed. One can still change this
-	     * back by registering no-ops encoders for those
-	     */
+        case XML_CHAR_ENCODING_ASCII:
+	    *out = (xmlCharEncodingHandler *) xmlAsciiHandler;
+            return(0);
         case XML_CHAR_ENCODING_8859_1:
-	    handler = xmlFindCharEncodingHandler("ISO-8859-1");
-	    if (handler != NULL) return(handler);
-	    break;
+	    *out = (xmlCharEncodingHandler *) xmlLatin1Handler;
+            return(0);
         case XML_CHAR_ENCODING_8859_2:
-	    handler = xmlFindCharEncodingHandler("ISO-8859-2");
-	    if (handler != NULL) return(handler);
+	    name = "ISO-8859-2";
 	    break;
         case XML_CHAR_ENCODING_8859_3:
-	    handler = xmlFindCharEncodingHandler("ISO-8859-3");
-	    if (handler != NULL) return(handler);
+	    name = "ISO-8859-3";
 	    break;
         case XML_CHAR_ENCODING_8859_4:
-	    handler = xmlFindCharEncodingHandler("ISO-8859-4");
-	    if (handler != NULL) return(handler);
+	    name = "ISO-8859-4";
 	    break;
         case XML_CHAR_ENCODING_8859_5:
-	    handler = xmlFindCharEncodingHandler("ISO-8859-5");
-	    if (handler != NULL) return(handler);
+	    name = "ISO-8859-5";
 	    break;
         case XML_CHAR_ENCODING_8859_6:
-	    handler = xmlFindCharEncodingHandler("ISO-8859-6");
-	    if (handler != NULL) return(handler);
+	    name = "ISO-8859-6";
 	    break;
         case XML_CHAR_ENCODING_8859_7:
-	    handler = xmlFindCharEncodingHandler("ISO-8859-7");
-	    if (handler != NULL) return(handler);
+	    name = "ISO-8859-7";
 	    break;
         case XML_CHAR_ENCODING_8859_8:
-	    handler = xmlFindCharEncodingHandler("ISO-8859-8");
-	    if (handler != NULL) return(handler);
+	    name = "ISO-8859-8";
 	    break;
         case XML_CHAR_ENCODING_8859_9:
-	    handler = xmlFindCharEncodingHandler("ISO-8859-9");
-	    if (handler != NULL) return(handler);
+	    name = "ISO-8859-9";
 	    break;
 
-
         case XML_CHAR_ENCODING_2022_JP:
-            handler = xmlFindCharEncodingHandler("ISO-2022-JP");
-            if (handler != NULL) return(handler);
+            name = "ISO-2022-JP";
 	    break;
         case XML_CHAR_ENCODING_SHIFT_JIS:
-            handler = xmlFindCharEncodingHandler("SHIFT-JIS");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("SHIFT_JIS");
-            if (handler != NULL) return(handler);
-            handler = xmlFindCharEncodingHandler("Shift_JIS");
-            if (handler != NULL) return(handler);
+            names = shiftJisNames;
+            numNames = sizeof(shiftJisNames) / sizeof(shiftJisNames[0]);
 	    break;
         case XML_CHAR_ENCODING_EUC_JP:
-            handler = xmlFindCharEncodingHandler("EUC-JP");
-            if (handler != NULL) return(handler);
+            name = "EUC-JP";
 	    break;
 	default:
 	    break;
     }
 
-#ifdef DEBUG_ENCODING
-    xmlGenericError(xmlGenericErrorContext,
-	    "No handler found for encoding %d\n", enc);
-#endif
-    return(NULL);
+    if (name != NULL)
+        return(xmlFindExtraHandler(name, 0, out));
+
+    if (names != NULL) {
+        for (i = 0; i < numNames; i++) {
+            ret = xmlFindExtraHandler(names[i], 0, out);
+            if (*out != NULL)
+                return(0);
+            if (ret != XML_ERR_UNSUPPORTED_ENCODING)
+                return(ret);
+        }
+    }
+
+    return(XML_ERR_UNSUPPORTED_ENCODING);
 }
 
 /**
- * xmlFindCharEncodingHandler:
- * @name:  a string describing the char encoding.
+ * xmlGetCharEncodingHandler:
+ * @enc:  an xmlCharEncoding value.
  *
- * Search in the registered set the handler able to read/write that encoding.
+ * DEPRECATED: Use xmlLookupCharEncodingHandler which has better error
+ * reporting.
  *
- * Returns the handler or NULL if not found
+ * Returns the handler or NULL if no handler was found or an error
+ * occurred.
  */
 xmlCharEncodingHandlerPtr
-xmlFindCharEncodingHandler(const char *name) {
+xmlGetCharEncodingHandler(xmlCharEncoding enc) {
+    xmlCharEncodingHandler *ret;
+
+    xmlLookupCharEncodingHandler(enc, &ret);
+    return(ret);
+}
+
+/**
+ * xmlOpenCharEncodingHandler:
+ * @name:  a string describing the char encoding.
+ * @output:  boolean, use handler for output
+ * @out:  pointer to result
+ *
+ * Find or create a handler matching the encoding. If no default or
+ * registered handler could be found, try to create a handler using
+ * iconv or ICU if supported.
+ *
+ * The handler must be closed with xmlCharEncCloseFunc.
+ *
+ * If the encoding is UTF-8, a NULL handler and no error code will
+ * be returned.
+ *
+ * Available since 2.13.0.
+ *
+ * Returns an xmlParserErrors error code.
+ */
+int
+xmlOpenCharEncodingHandler(const char *name, int output,
+                           xmlCharEncodingHandler **out) {
     const char *nalias;
     const char *norig;
-    xmlCharEncoding alias;
-#ifdef LIBXML_ICONV_ENABLED
-    xmlCharEncodingHandlerPtr enc;
-    iconv_t icv_in, icv_out;
-#endif /* LIBXML_ICONV_ENABLED */
-#ifdef LIBXML_ICU_ENABLED
-    xmlCharEncodingHandlerPtr encu;
-    uconv_t *ucv_in, *ucv_out;
-#endif /* LIBXML_ICU_ENABLED */
-    char upper[100];
-    int i;
+    xmlCharEncoding enc;
+    int ret;
+
+    if (out == NULL)
+        return(XML_ERR_ARGUMENT);
+    *out = NULL;
+
+    if (name == NULL)
+        return(XML_ERR_ARGUMENT);
 
-    if (handlers == NULL) xmlInitCharEncodingHandlers();
-    if (name == NULL) return(xmlDefaultCharEncodingHandler);
-    if (name[0] == 0) return(xmlDefaultCharEncodingHandler);
+    if ((xmlStrcasecmp(BAD_CAST name, BAD_CAST "UTF-8") == 0) ||
+        (xmlStrcasecmp(BAD_CAST name, BAD_CAST "UTF8") == 0))
+        return(XML_ERR_OK);
 
     /*
      * Do the alias resolution
      */
     norig = name;
     nalias = xmlGetEncodingAlias(name);
-    if (nalias != NULL)
-	name = nalias;
-
-    /*
-     * Check first for directly registered encoding names
-     */
-    for (i = 0;i < 99;i++) {
-        upper[i] = toupper(name[i]);
-	if (upper[i] == 0) break;
-    }
-    upper[i] = 0;
-
-    if (handlers != NULL) {
-        for (i = 0;i < nbCharEncodingHandler; i++) {
-            if (!strcmp(upper, handlers[i]->name)) {
-#ifdef DEBUG_ENCODING
-                xmlGenericError(xmlGenericErrorContext,
-                        "Found registered handler for encoding %s\n", name);
-#endif
-                return(handlers[i]);
-            }
-        }
-    }
-
-#ifdef LIBXML_ICONV_ENABLED
-    /* check whether iconv can handle this */
-    icv_in = iconv_open("UTF-8", name);
-    icv_out = iconv_open(name, "UTF-8");
-    if (icv_in == (iconv_t) -1) {
-        icv_in = iconv_open("UTF-8", upper);
-    }
-    if (icv_out == (iconv_t) -1) {
-	icv_out = iconv_open(upper, "UTF-8");
-    }
-    if ((icv_in != (iconv_t) -1) && (icv_out != (iconv_t) -1)) {
-	    enc = (xmlCharEncodingHandlerPtr)
-	          xmlMalloc(sizeof(xmlCharEncodingHandler));
-	    if (enc == NULL) {
-	        iconv_close(icv_in);
-	        iconv_close(icv_out);
-		return(NULL);
-	    }
-            memset(enc, 0, sizeof(xmlCharEncodingHandler));
-	    enc->name = xmlMemStrdup(name);
-	    enc->input = NULL;
-	    enc->output = NULL;
-	    enc->iconv_in = icv_in;
-	    enc->iconv_out = icv_out;
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-		    "Found iconv handler for encoding %s\n", name);
-#endif
-	    return enc;
-    } else if ((icv_in != (iconv_t) -1) || icv_out != (iconv_t) -1) {
-	    xmlEncodingErr(XML_ERR_INTERNAL_ERROR,
-		    "iconv : problems with filters for '%s'\n", name);
-	    if (icv_in != (iconv_t) -1)
-		iconv_close(icv_in);
-	    else
-		iconv_close(icv_out);
-    }
-#endif /* LIBXML_ICONV_ENABLED */
-#ifdef LIBXML_ICU_ENABLED
-    /* check whether icu can handle this */
-    ucv_in = openIcuConverter(name, 1);
-    ucv_out = openIcuConverter(name, 0);
-    if (ucv_in != NULL && ucv_out != NULL) {
-	    encu = (xmlCharEncodingHandlerPtr)
-	           xmlMalloc(sizeof(xmlCharEncodingHandler));
-	    if (encu == NULL) {
-                closeIcuConverter(ucv_in);
-                closeIcuConverter(ucv_out);
-		return(NULL);
-	    }
-            memset(encu, 0, sizeof(xmlCharEncodingHandler));
-	    encu->name = xmlMemStrdup(name);
-	    encu->input = NULL;
-	    encu->output = NULL;
-	    encu->uconv_in = ucv_in;
-	    encu->uconv_out = ucv_out;
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-		    "Found ICU converter handler for encoding %s\n", name);
-#endif
-	    return encu;
-    } else if (ucv_in != NULL || ucv_out != NULL) {
-            closeIcuConverter(ucv_in);
-            closeIcuConverter(ucv_out);
-	    xmlEncodingErr(XML_ERR_INTERNAL_ERROR,
-		    "ICU converter : problems with filters for '%s'\n", name);
-    }
-#endif /* LIBXML_ICU_ENABLED */
+    if (nalias != NULL)
+	name = nalias;
 
-#ifdef DEBUG_ENCODING
-    xmlGenericError(xmlGenericErrorContext,
-	    "No handler found for encoding %s\n", name);
-#endif
+    ret = xmlFindHandler(name, output, out);
+    if (*out != NULL)
+        return(0);
+    if (ret != XML_ERR_UNSUPPORTED_ENCODING)
+        return(ret);
 
     /*
      * Fallback using the canonical names
+     *
+     * TODO: We should make sure that the name of the returned
+     * handler equals norig.
      */
-    alias = xmlParseCharEncoding(norig);
-    if (alias != XML_CHAR_ENCODING_ERROR) {
-        const char* canon;
-        canon = xmlGetCharEncodingName(alias);
-        if ((canon != NULL) && (strcmp(name, canon))) {
-	    return(xmlFindCharEncodingHandler(canon));
-        }
-    }
+    enc = xmlParseCharEncoding(norig);
+    return(xmlLookupCharEncodingHandler(enc, out));
+}
 
-    /* If "none of the above", give up */
-    return(NULL);
+/**
+ * xmlFindCharEncodingHandler:
+ * @name:  a string describing the char encoding.
+ *
+ * DEPRECATED: Use xmlOpenCharEncodingHandler which has better error
+ * reporting.
+ *
+ * Returns the handler or NULL if no handler was found or an error
+ * occurred.
+ */
+xmlCharEncodingHandlerPtr
+xmlFindCharEncodingHandler(const char *name) {
+    xmlCharEncodingHandler *ret;
+
+    /*
+     * This handler shouldn't be used, but we must return a non-NULL
+     * handler.
+     */
+    if ((xmlStrcasecmp(BAD_CAST name, BAD_CAST "UTF-8") == 0) ||
+        (xmlStrcasecmp(BAD_CAST name, BAD_CAST "UTF8") == 0))
+        return((xmlCharEncodingHandlerPtr) &xmlUTF8Handler);
+
+    xmlOpenCharEncodingHandler(name, 0, &ret);
+    return(ret);
 }
 
 /************************************************************************
@@ -1828,11 +2015,7 @@ xmlFindCharEncodingHandler(const char *name) {
  * @in:  a pointer to an array of input bytes
  * @inlen:  the length of @in
  *
- * Returns 0 if success, or
- *     -1 by lack of space, or
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
- *     -3 if there the last byte can't form a single output char.
+ * Returns an XML_ENC_ERR code.
  *
  * The value of @inlen after return is the number of octets consumed
  *     as the return value is positive, else unpredictable.
@@ -1848,7 +2031,7 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
 
     if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (in == NULL)) {
         if (outlen != NULL) *outlen = 0;
-        return(-1);
+        return(XML_ENC_ERR_INTERNAL);
     }
     icv_inlen = *inlen;
     icv_outlen = *outlen;
@@ -1858,27 +2041,16 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
     ret = iconv(cd, (void *) &icv_in, &icv_inlen, &icv_out, &icv_outlen);
     *inlen -= icv_inlen;
     *outlen -= icv_outlen;
-    if ((icv_inlen != 0) || (ret == (size_t) -1)) {
-#ifdef EILSEQ
-        if (errno == EILSEQ) {
-            return -2;
-        } else
-#endif
-#ifdef E2BIG
-        if (errno == E2BIG) {
-            return -1;
-        } else
-#endif
-#ifdef EINVAL
-        if (errno == EINVAL) {
-            return -3;
-        } else
-#endif
-        {
-            return -3;
-        }
+    if (ret == (size_t) -1) {
+        if (errno == EILSEQ)
+            return(XML_ENC_ERR_INPUT);
+        if (errno == E2BIG)
+            return(XML_ENC_ERR_SPACE);
+        if (errno == EINVAL)
+            return(XML_ENC_ERR_PARTIAL);
+        return(XML_ENC_ERR_INTERNAL);
     }
-    return 0;
+    return(XML_ENC_ERR_SUCCESS);
 }
 #endif /* LIBXML_ICONV_ENABLED */
 
@@ -1897,13 +2069,8 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
  * @outlen:  the length of @out
  * @in:  a pointer to an array of input bytes
  * @inlen:  the length of @in
- * @flush: if true, indicates end of input
  *
- * Returns 0 if success, or
- *     -1 by lack of space, or
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
- *     -3 if there the last byte can't form a single output char.
+ * Returns an XML_ENC_ERR code.
  *
  * The value of @inlen after return is the number of octets consumed
  *     as the return value is positive, else unpredictable.
@@ -1911,42 +2078,53 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
  */
 static int
 xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen,
-                const unsigned char *in, int *inlen, int flush) {
+                const unsigned char *in, int *inlen) {
     const char *ucv_in = (const char *) in;
     char *ucv_out = (char *) out;
     UErrorCode err = U_ZERO_ERROR;
 
     if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (in == NULL)) {
         if (outlen != NULL) *outlen = 0;
-        return(-1);
+        return(XML_ENC_ERR_INTERNAL);
     }
 
+    /*
+     * Note that the ICU API is stateful. It can always consume a certain
+     * amount of input even if the output buffer would overflow. The
+     * remaining input must be processed by calling ucnv_convertEx with a
+     * possibly empty input buffer.
+     *
+     * ucnv_convertEx is always called with reset and flush set to 0,
+     * so we don't mess up the state. This should never generate
+     * U_TRUNCATED_CHAR_FOUND errors.
+     *
+     * This also means that ICU xmlCharEncodingHandlers should never be
+     * reused. It would be a lot nicer if there was a way to emulate the
+     * stateless iconv API.
+     */
     if (toUnicode) {
         /* encoding => UTF-16 => UTF-8 */
         ucnv_convertEx(cd->utf8, cd->uconv, &ucv_out, ucv_out + *outlen,
                        &ucv_in, ucv_in + *inlen, cd->pivot_buf,
                        &cd->pivot_source, &cd->pivot_target,
-                       cd->pivot_buf + ICU_PIVOT_BUF_SIZE, 0, flush, &err);
+                       cd->pivot_buf + ICU_PIVOT_BUF_SIZE, 0, 0, &err);
     } else {
         /* UTF-8 => UTF-16 => encoding */
         ucnv_convertEx(cd->uconv, cd->utf8, &ucv_out, ucv_out + *outlen,
                        &ucv_in, ucv_in + *inlen, cd->pivot_buf,
                        &cd->pivot_source, &cd->pivot_target,
-                       cd->pivot_buf + ICU_PIVOT_BUF_SIZE, 0, flush, &err);
+                       cd->pivot_buf + ICU_PIVOT_BUF_SIZE, 0, 0, &err);
     }
     *inlen = ucv_in - (const char*) in;
     *outlen = ucv_out - (char *) out;
     if (U_SUCCESS(err)) {
-        /* reset pivot buf if this is the last call for input (flush==TRUE) */
-        if (flush)
-            cd->pivot_source = cd->pivot_target = cd->pivot_buf;
-        return 0;
+        return(XML_ENC_ERR_SUCCESS);
     }
     if (err == U_BUFFER_OVERFLOW_ERROR)
-        return -1;
+        return(XML_ENC_ERR_SPACE);
     if (err == U_INVALID_CHAR_FOUND || err == U_ILLEGAL_CHAR_FOUND)
-        return -2;
-    return -3;
+        return(XML_ENC_ERR_INPUT);
+    return(XML_ENC_ERR_PARTIAL);
 }
 #endif /* LIBXML_ICU_ENABLED */
 
@@ -1956,6 +2134,34 @@ xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen,
  *									*
  ************************************************************************/
 
+/**
+ * xmlEncConvertError:
+ * @code:  XML_ENC_ERR code
+ *
+ * Convert XML_ENC_ERR to libxml2 error codes.
+ */
+static int
+xmlEncConvertError(int code) {
+    int ret;
+
+    switch (code) {
+        case XML_ENC_ERR_SUCCESS:
+            ret = XML_ERR_OK;
+            break;
+        case XML_ENC_ERR_INPUT:
+            ret = XML_ERR_INVALID_ENCODING;
+            break;
+        case XML_ENC_ERR_MEMORY:
+            ret = XML_ERR_NO_MEMORY;
+            break;
+        default:
+            ret = XML_ERR_INTERNAL_ERROR;
+            break;
+    }
+
+    return(ret);
+}
+
 /**
  * xmlEncInputChunk:
  * @handler:  encoding handler
@@ -1963,28 +2169,35 @@ xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen,
  * @outlen:  the length of @out
  * @in:  a pointer to an array of input bytes
  * @inlen:  the length of @in
- * @flush:  flush (ICU-related)
- *
- * Returns 0 if success, or
- *     -1 by lack of space, or
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
- *     -3 if there the last byte can't form a single output char.
  *
  * The value of @inlen after return is the number of octets consumed
  *     as the return value is 0, else unpredictable.
  * The value of @outlen after return is the number of octets produced.
+ *
+ * Returns an XML_ENC_ERR code.
  */
-static int
+int
 xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
-                 int *outlen, const unsigned char *in, int *inlen, int flush) {
+                 int *outlen, const unsigned char *in, int *inlen) {
     int ret;
-    (void)flush;
 
     if (handler->input != NULL) {
+        int oldinlen = *inlen;
+
         ret = handler->input(out, outlen, in, inlen);
-        if (ret > 0)
-           ret = 0;
+        if (ret >= 0) {
+            /*
+             * The built-in converters don't signal XML_ENC_ERR_SPACE.
+             */
+            if (*inlen < oldinlen) {
+                if (*outlen > 0)
+                    ret = XML_ENC_ERR_SPACE;
+                else
+                    ret = XML_ENC_ERR_PARTIAL;
+            } else {
+                ret = XML_ENC_ERR_SUCCESS;
+            }
+        }
     }
 #ifdef LIBXML_ICONV_ENABLED
     else if (handler->iconv_in != NULL) {
@@ -1993,16 +2206,19 @@ xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
 #endif /* LIBXML_ICONV_ENABLED */
 #ifdef LIBXML_ICU_ENABLED
     else if (handler->uconv_in != NULL) {
-        ret = xmlUconvWrapper(handler->uconv_in, 1, out, outlen, in, inlen,
-                              flush);
+        ret = xmlUconvWrapper(handler->uconv_in, 1, out, outlen, in, inlen);
     }
 #endif /* LIBXML_ICU_ENABLED */
     else {
         *outlen = 0;
         *inlen = 0;
-        ret = -2;
+        ret = XML_ENC_ERR_INTERNAL;
     }
 
+    /* Ignore partial errors when reading. */
+    if (ret == XML_ENC_ERR_PARTIAL)
+        ret = XML_ENC_ERR_SUCCESS;
+
     return(ret);
 }
 
@@ -2014,12 +2230,7 @@ xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
  * @in:  a pointer to an array of input bytes
  * @inlen:  the length of @in
  *
- * Returns 0 if success, or
- *     -1 by lack of space, or
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
- *     -3 if there the last byte can't form a single output char.
- *     -4 if no output function was found.
+ * Returns an XML_ENC_ERR code.
  *
  * The value of @inlen after return is the number of octets consumed
  *     as the return value is 0, else unpredictable.
@@ -2031,9 +2242,22 @@ xmlEncOutputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
     int ret;
 
     if (handler->output != NULL) {
+        int oldinlen = *inlen;
+
         ret = handler->output(out, outlen, in, inlen);
-        if (ret > 0)
-           ret = 0;
+        if (ret >= 0) {
+            /*
+             * The built-in converters don't signal XML_ENC_ERR_SPACE.
+             */
+            if (*inlen < oldinlen) {
+                if (*outlen > 0)
+                    ret = XML_ENC_ERR_SPACE;
+                else
+                    ret = XML_ENC_ERR_PARTIAL;
+            } else {
+                ret = XML_ENC_ERR_SUCCESS;
+            }
+        }
     }
 #ifdef LIBXML_ICONV_ENABLED
     else if (handler->iconv_out != NULL) {
@@ -2042,328 +2266,110 @@ xmlEncOutputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
 #endif /* LIBXML_ICONV_ENABLED */
 #ifdef LIBXML_ICU_ENABLED
     else if (handler->uconv_out != NULL) {
-        ret = xmlUconvWrapper(handler->uconv_out, 0, out, outlen, in, inlen,
-                              1);
+        ret = xmlUconvWrapper(handler->uconv_out, 0, out, outlen, in, inlen);
     }
 #endif /* LIBXML_ICU_ENABLED */
     else {
         *outlen = 0;
         *inlen = 0;
-        ret = -4;
+        ret = XML_ENC_ERR_INTERNAL;
     }
 
-    return(ret);
-}
-
-/**
- * xmlCharEncFirstLineInt:
- * @handler:	char encoding transformation data structure
- * @out:  an xmlBuffer for the output.
- * @in:  an xmlBuffer for the input
- * @len:  number of bytes to convert for the first line, or -1
- *
- * Front-end for the encoding handler input function, but handle only
- * the very first line, i.e. limit itself to 45 chars.
- *
- * Returns the number of byte written if success, or
- *     -1 general error
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
- */
-int
-xmlCharEncFirstLineInt(xmlCharEncodingHandler *handler, xmlBufferPtr out,
-                       xmlBufferPtr in, int len) {
-    int ret;
-    int written;
-    int toconv;
-
-    if (handler == NULL) return(-1);
-    if (out == NULL) return(-1);
-    if (in == NULL) return(-1);
-
-    /* calculate space available */
-    written = out->size - out->use - 1; /* count '\0' */
-    toconv = in->use;
-    /*
-     * echo '<?xml version="1.0" encoding="UCS4"?>' | wc -c => 38
-     * 45 chars should be sufficient to reach the end of the encoding
-     * declaration without going too far inside the document content.
-     * on UTF-16 this means 90bytes, on UCS4 this means 180
-     * The actual value depending on guessed encoding is passed as @len
-     * if provided
-     */
-    if (len >= 0) {
-        if (toconv > len)
-            toconv = len;
-    } else {
-        if (toconv > 180)
-            toconv = 180;
-    }
-    if (toconv * 2 >= written) {
-        xmlBufferGrow(out, toconv * 2);
-	written = out->size - out->use - 1;
-    }
+    /* We shouldn't generate partial sequences when writing. */
+    if (ret == XML_ENC_ERR_PARTIAL)
+        ret = XML_ENC_ERR_INTERNAL;
 
-    ret = xmlEncInputChunk(handler, &out->content[out->use], &written,
-                           in->content, &toconv, 0);
-    xmlBufferShrink(in, toconv);
-    out->use += written;
-    out->content[out->use] = 0;
-    if (ret == -1) ret = -3;
-
-#ifdef DEBUG_ENCODING
-    switch (ret) {
-        case 0:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "converted %d bytes to %d bytes of input\n",
-	            toconv, written);
-	    break;
-        case -1:
-	    xmlGenericError(xmlGenericErrorContext,"converted %d bytes to %d bytes of input, %d left\n",
-	            toconv, written, in->use);
-	    break;
-        case -2:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "input conversion failed due to input error\n");
-	    break;
-        case -3:
-	    xmlGenericError(xmlGenericErrorContext,"converted %d bytes to %d bytes of input, %d left\n",
-	            toconv, written, in->use);
-	    break;
-	default:
-	    xmlGenericError(xmlGenericErrorContext,"Unknown input conversion failed %d\n", ret);
-    }
-#endif /* DEBUG_ENCODING */
-    /*
-     * Ignore when input buffer is not on a boundary
-     */
-    if (ret == -3) ret = 0;
-    if (ret == -1) ret = 0;
-    return(written ? written : ret);
+    return(ret);
 }
 
 /**
  * xmlCharEncFirstLine:
- * @handler:	char encoding transformation data structure
+ * @handler:   char encoding transformation data structure
  * @out:  an xmlBuffer for the output.
  * @in:  an xmlBuffer for the input
  *
- * Front-end for the encoding handler input function, but handle only
- * the very first line, i.e. limit itself to 45 chars.
+ * DEPERECATED: Don't use.
  *
- * Returns the number of byte written if success, or
- *     -1 general error
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
+ * Returns the number of bytes written or an XML_ENC_ERR code.
  */
 int
 xmlCharEncFirstLine(xmlCharEncodingHandler *handler, xmlBufferPtr out,
-                 xmlBufferPtr in) {
-    return(xmlCharEncFirstLineInt(handler, out, in, -1));
+                    xmlBufferPtr in) {
+    return(xmlCharEncInFunc(handler, out, in));
 }
 
 /**
- * xmlCharEncFirstLineInput:
+ * xmlCharEncInput:
  * @input: a parser input buffer
- * @len:  number of bytes to convert for the first line, or -1
  *
- * Front-end for the encoding handler input function, but handle only
- * the very first line. Point is that this is based on autodetection
- * of the encoding and once that first line is converted we may find
- * out that a different decoder is needed to process the input.
+ * Generic front-end for the encoding handler on parser input
  *
- * Returns the number of byte written if success, or
- *     -1 general error
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
+ * Returns the number of bytes written or an XML_ENC_ERR code.
  */
 int
-xmlCharEncFirstLineInput(xmlParserInputBufferPtr input, int len)
+xmlCharEncInput(xmlParserInputBufferPtr input)
 {
     int ret;
-    size_t written;
+    size_t avail;
     size_t toconv;
     int c_in;
     int c_out;
     xmlBufPtr in;
     xmlBufPtr out;
+    const xmlChar *inData;
+    size_t inTotal = 0;
 
     if ((input == NULL) || (input->encoder == NULL) ||
         (input->buffer == NULL) || (input->raw == NULL))
-        return (-1);
+        return(XML_ENC_ERR_INTERNAL);
     out = input->buffer;
     in = input->raw;
 
     toconv = xmlBufUse(in);
     if (toconv == 0)
         return (0);
-    written = xmlBufAvail(out);
-    /*
-     * echo '<?xml version="1.0" encoding="UCS4"?>' | wc -c => 38
-     * 45 chars should be sufficient to reach the end of the encoding
-     * declaration without going too far inside the document content.
-     * on UTF-16 this means 90bytes, on UCS4 this means 180
-     * The actual value depending on guessed encoding is passed as @len
-     * if provided
-     */
-    if (len >= 0) {
-        if (toconv > (unsigned int) len)
-            toconv = len;
-    } else {
-        if (toconv > 180)
-            toconv = 180;
-    }
-    if (toconv * 2 >= written) {
-        xmlBufGrow(out, toconv * 2);
-        written = xmlBufAvail(out);
-    }
-    if (written > 360)
-        written = 360;
-
-    c_in = toconv;
-    c_out = written;
-    ret = xmlEncInputChunk(input->encoder, xmlBufEnd(out), &c_out,
-                           xmlBufContent(in), &c_in, 0);
-    xmlBufShrink(in, c_in);
-    xmlBufAddLen(out, c_out);
-    if (ret == -1)
-        ret = -3;
-
-    switch (ret) {
-        case 0:
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                            "converted %d bytes to %d bytes of input\n",
-                            c_in, c_out);
-#endif
-            break;
-        case -1:
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                         "converted %d bytes to %d bytes of input, %d left\n",
-                            c_in, c_out, (int)xmlBufUse(in));
-#endif
-            break;
-        case -3:
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                        "converted %d bytes to %d bytes of input, %d left\n",
-                            c_in, c_out, (int)xmlBufUse(in));
-#endif
-            break;
-        case -2: {
-            char buf[50];
-            const xmlChar *content = xmlBufContent(in);
-
-	    snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X",
-		     content[0], content[1],
-		     content[2], content[3]);
-	    buf[49] = 0;
-	    xmlEncodingErr(XML_I18N_CONV_FAILED,
-		    "input conversion failed due to input error, bytes %s\n",
-		           buf);
+    inData = xmlBufContent(in);
+    inTotal = 0;
+
+    do {
+        c_in = toconv > INT_MAX / 2 ? INT_MAX / 2 : toconv;
+
+        avail = xmlBufAvail(out);
+        if (avail > INT_MAX)
+            avail = INT_MAX;
+        if (avail < 4096) {
+            if (xmlBufGrow(out, 4096) < 0) {
+                input->error = XML_ERR_NO_MEMORY;
+                return(XML_ENC_ERR_MEMORY);
+            }
+            avail = xmlBufAvail(out);
         }
-    }
-    /*
-     * Ignore when input buffer is not on a boundary
-     */
-    if (ret == -3) ret = 0;
-    if (ret == -1) ret = 0;
-    return(c_out ? c_out : ret);
-}
 
-/**
- * xmlCharEncInput:
- * @input: a parser input buffer
- * @flush: try to flush all the raw buffer
- *
- * Generic front-end for the encoding handler on parser input
- *
- * Returns the number of byte written if success, or
- *     -1 general error
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
- */
-int
-xmlCharEncInput(xmlParserInputBufferPtr input, int flush)
-{
-    int ret;
-    size_t written;
-    size_t toconv;
-    int c_in;
-    int c_out;
-    xmlBufPtr in;
-    xmlBufPtr out;
+        c_in = toconv;
+        c_out = avail;
+        ret = xmlEncInputChunk(input->encoder, xmlBufEnd(out), &c_out,
+                               inData, &c_in);
+        inTotal += c_in;
+        inData += c_in;
+        toconv -= c_in;
+        xmlBufAddLen(out, c_out);
+    } while (ret == XML_ENC_ERR_SPACE);
 
-    if ((input == NULL) || (input->encoder == NULL) ||
-        (input->buffer == NULL) || (input->raw == NULL))
-        return (-1);
-    out = input->buffer;
-    in = input->raw;
+    xmlBufShrink(in, inTotal);
 
-    toconv = xmlBufUse(in);
-    if (toconv == 0)
-        return (0);
-    if ((toconv > 64 * 1024) && (flush == 0))
-        toconv = 64 * 1024;
-    written = xmlBufAvail(out);
-    if (toconv * 2 >= written) {
-        xmlBufGrow(out, toconv * 2);
-        written = xmlBufAvail(out);
-    }
-    if ((written > 128 * 1024) && (flush == 0))
-        written = 128 * 1024;
+    if (input->rawconsumed > ULONG_MAX - (unsigned long)c_in)
+        input->rawconsumed = ULONG_MAX;
+    else
+        input->rawconsumed += c_in;
 
-    c_in = toconv;
-    c_out = written;
-    ret = xmlEncInputChunk(input->encoder, xmlBufEnd(out), &c_out,
-                           xmlBufContent(in), &c_in, flush);
-    xmlBufShrink(in, c_in);
-    xmlBufAddLen(out, c_out);
-    if (ret == -1)
-        ret = -3;
-
-    switch (ret) {
-        case 0:
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                            "converted %d bytes to %d bytes of input\n",
-                            c_in, c_out);
-#endif
-            break;
-        case -1:
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                         "converted %d bytes to %d bytes of input, %d left\n",
-                            c_in, c_out, (int)xmlBufUse(in));
-#endif
-            break;
-        case -3:
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                        "converted %d bytes to %d bytes of input, %d left\n",
-                            c_in, c_out, (int)xmlBufUse(in));
-#endif
-            break;
-        case -2: {
-            char buf[50];
-            const xmlChar *content = xmlBufContent(in);
-
-	    snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X",
-		     content[0], content[1],
-		     content[2], content[3]);
-	    buf[49] = 0;
-	    xmlEncodingErr(XML_I18N_CONV_FAILED,
-		    "input conversion failed due to input error, bytes %s\n",
-		           buf);
-        }
+    if (((ret != 0) && (c_out == 0)) ||
+        (ret == XML_ENC_ERR_MEMORY)) {
+        if (input->error == 0)
+            input->error = xmlEncConvertError(ret);
+        return(ret);
     }
-    /*
-     * Ignore when input buffer is not on a boundary
-     */
-    if (ret == -3)
-        ret = 0;
-    return (c_out? c_out : ret);
+
+    return (c_out);
 }
 
 /**
@@ -2374,10 +2380,7 @@ xmlCharEncInput(xmlParserInputBufferPtr input, int flush)
  *
  * Generic front-end for the encoding handler input function
  *
- * Returns the number of byte written if success, or
- *     -1 general error
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
+ * Returns the number of bytes written or an XML_ENC_ERR code.
  */
 int
 xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out,
@@ -2388,11 +2391,11 @@ xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out,
     int toconv;
 
     if (handler == NULL)
-        return (-1);
+        return(XML_ENC_ERR_INTERNAL);
     if (out == NULL)
-        return (-1);
+        return(XML_ENC_ERR_INTERNAL);
     if (in == NULL)
-        return (-1);
+        return(XML_ENC_ERR_INTERNAL);
 
     toconv = in->use;
     if (toconv == 0)
@@ -2403,52 +2406,11 @@ xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out,
         written = out->size - out->use - 1;
     }
     ret = xmlEncInputChunk(handler, &out->content[out->use], &written,
-                           in->content, &toconv, 1);
+                           in->content, &toconv);
     xmlBufferShrink(in, toconv);
     out->use += written;
     out->content[out->use] = 0;
-    if (ret == -1)
-        ret = -3;
-
-    switch (ret) {
-        case 0:
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                            "converted %d bytes to %d bytes of input\n",
-                            toconv, written);
-#endif
-            break;
-        case -1:
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                         "converted %d bytes to %d bytes of input, %d left\n",
-                            toconv, written, in->use);
-#endif
-            break;
-        case -3:
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                        "converted %d bytes to %d bytes of input, %d left\n",
-                            toconv, written, in->use);
-#endif
-            break;
-        case -2: {
-            char buf[50];
-
-	    snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X",
-		     in->content[0], in->content[1],
-		     in->content[2], in->content[3]);
-	    buf[49] = 0;
-	    xmlEncodingErr(XML_I18N_CONV_FAILED,
-		    "input conversion failed due to input error, bytes %s\n",
-		           buf);
-        }
-    }
-    /*
-     * Ignore when input buffer is not on a boundary
-     */
-    if (ret == -3)
-        ret = 0;
+
     return (written? written : ret);
 }
 
@@ -2465,10 +2427,7 @@ xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out,
  * In case of UTF8 sequence conversion errors for the given encoder,
  * the content will be automatically remapped to a CharRef sequence.
  *
- * Returns the number of byte written if success, or
- *     -1 general error
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
+ * Returns the number of bytes written or an XML_ENC_ERR code.
  */
 int
 xmlCharEncOutput(xmlOutputBufferPtr output, int init)
@@ -2484,7 +2443,7 @@ xmlCharEncOutput(xmlOutputBufferPtr output, int init)
 
     if ((output == NULL) || (output->encoder == NULL) ||
         (output->buffer == NULL) || (output->conv == NULL))
-        return (-1);
+        return(XML_ENC_ERR_INTERNAL);
     out = output->conv;
     in = output->buffer;
 
@@ -2502,10 +2461,6 @@ retry:
         xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out,
                           NULL, &c_in);
         xmlBufAddLen(out, c_out);
-#ifdef DEBUG_ENCODING
-	xmlGenericError(xmlGenericErrorContext,
-		"initialized encoder\n");
-#endif
         return(c_out);
     }
 
@@ -2513,12 +2468,13 @@ retry:
      * Conversion itself.
      */
     toconv = xmlBufUse(in);
-    if (toconv == 0)
-        return (writtentot);
     if (toconv > 64 * 1024)
         toconv = 64 * 1024;
     if (toconv * 4 >= written) {
-        xmlBufGrow(out, toconv * 4);
+        if (xmlBufGrow(out, toconv * 4) < 0) {
+            ret = XML_ENC_ERR_MEMORY;
+            goto error;
+        }
         written = xmlBufAvail(out);
     }
     if (written > 256 * 1024)
@@ -2531,95 +2487,55 @@ retry:
     xmlBufShrink(in, c_in);
     xmlBufAddLen(out, c_out);
     writtentot += c_out;
-    if (ret == -1) {
-        if (c_out > 0) {
-            /* Can be a limitation of iconv or uconv */
-            goto retry;
-        }
-        ret = -3;
-    }
+
+    if (ret == XML_ENC_ERR_SPACE)
+        goto retry;
 
     /*
      * Attempt to handle error cases
      */
-    switch (ret) {
-        case 0:
-#ifdef DEBUG_ENCODING
-	    xmlGenericError(xmlGenericErrorContext,
-		    "converted %d bytes to %d bytes of output\n",
-	            c_in, c_out);
-#endif
-	    break;
-        case -1:
-#ifdef DEBUG_ENCODING
-	    xmlGenericError(xmlGenericErrorContext,
-		    "output conversion failed by lack of space\n");
-#endif
-	    break;
-        case -3:
-#ifdef DEBUG_ENCODING
-	    xmlGenericError(xmlGenericErrorContext,"converted %d bytes to %d bytes of output %d left\n",
-	            c_in, c_out, (int) xmlBufUse(in));
-#endif
-	    break;
-        case -4:
-            xmlEncodingErr(XML_I18N_NO_OUTPUT,
-                           "xmlCharEncOutFunc: no output function !\n", NULL);
-            ret = -1;
-            break;
-        case -2: {
-	    xmlChar charref[20];
-	    int len = (int) xmlBufUse(in);
-            xmlChar *content = xmlBufContent(in);
-	    int cur, charrefLen;
-
-	    cur = xmlGetUTF8Char(content, &len);
-	    if (cur <= 0)
-                break;
+    if (ret == XML_ENC_ERR_INPUT) {
+        xmlChar charref[20];
+        int len = xmlBufUse(in);
+        xmlChar *content = xmlBufContent(in);
+        int cur, charrefLen;
 
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                    "handling output conversion error\n");
-            xmlGenericError(xmlGenericErrorContext,
-                    "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
-                    content[0], content[1],
-                    content[2], content[3]);
-#endif
-            /*
-             * Removes the UTF8 sequence, and replace it by a charref
-             * and continue the transcoding phase, hoping the error
-             * did not mangle the encoder state.
-             */
-            charrefLen = snprintf((char *) &charref[0], sizeof(charref),
-                             "&#%d;", cur);
-            xmlBufShrink(in, len);
-            xmlBufGrow(out, charrefLen * 4);
-            c_out = xmlBufAvail(out);
-            c_in = charrefLen;
-            ret = xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out,
-                                    charref, &c_in);
-
-	    if ((ret < 0) || (c_in != charrefLen)) {
-		char buf[50];
-
-		snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X",
-			 content[0], content[1],
-			 content[2], content[3]);
-		buf[49] = 0;
-		xmlEncodingErr(XML_I18N_CONV_FAILED,
-		    "output conversion failed due to conv error, bytes %s\n",
-			       buf);
-		if (xmlBufGetAllocationScheme(in) != XML_BUFFER_ALLOC_IMMUTABLE)
-		    content[0] = ' ';
-                break;
-	    }
+        cur = xmlGetUTF8Char(content, &len);
+        if (cur <= 0)
+            goto error;
 
-            xmlBufAddLen(out, c_out);
-            writtentot += c_out;
-            goto retry;
-	}
+        /*
+         * Removes the UTF8 sequence, and replace it by a charref
+         * and continue the transcoding phase, hoping the error
+         * did not mangle the encoder state.
+         */
+        charrefLen = snprintf((char *) &charref[0], sizeof(charref),
+                         "&#%d;", cur);
+        xmlBufGrow(out, charrefLen * 4);
+        c_out = xmlBufAvail(out);
+        c_in = charrefLen;
+        ret = xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out,
+                                charref, &c_in);
+        if ((ret < 0) || (c_in != charrefLen)) {
+            ret = XML_ENC_ERR_INTERNAL;
+            goto error;
+        }
+
+        xmlBufShrink(in, len);
+        xmlBufAddLen(out, c_out);
+        writtentot += c_out;
+        goto retry;
     }
-    return(writtentot ? writtentot : ret);
+
+error:
+    if (((writtentot <= 0) && (ret != 0)) ||
+        (ret == XML_ENC_ERR_MEMORY)) {
+        if (output->error == 0)
+            output->error = xmlEncConvertError(ret);
+        return(ret);
+    }
+
+    return(writtentot);
 }
 #endif
 
@@ -2636,10 +2552,7 @@ retry:
  * In case of UTF8 sequence conversion errors for the given encoder,
  * the content will be automatically remapped to a CharRef sequence.
  *
- * Returns the number of byte written if success, or
- *     -1 general error
- *     -2 if the transcoding fails (for *in is not valid utf8 string or
- *        the result of transformation can't fit into the encoding we want), or
+ * Returns the number of bytes written or an XML_ENC_ERR code.
  */
 int
 xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
@@ -2649,8 +2562,8 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
     int writtentot = 0;
     int toconv;
 
-    if (handler == NULL) return(-1);
-    if (out == NULL) return(-1);
+    if (handler == NULL) return(XML_ENC_ERR_INTERNAL);
+    if (out == NULL) return(XML_ENC_ERR_INTERNAL);
 
 retry:
 
@@ -2669,10 +2582,6 @@ retry:
                           NULL, &toconv);
         out->use += written;
         out->content[out->use] = 0;
-#ifdef DEBUG_ENCODING
-	xmlGenericError(xmlGenericErrorContext,
-		"initialized encoder\n");
-#endif
         return(0);
     }
 
@@ -2680,8 +2589,6 @@ retry:
      * Conversion itself.
      */
     toconv = in->use;
-    if (toconv == 0)
-	return(0);
     if (toconv * 4 >= written) {
         xmlBufferGrow(out, toconv * 4);
 	written = out->size - out->use - 1;
@@ -2692,94 +2599,43 @@ retry:
     out->use += written;
     writtentot += written;
     out->content[out->use] = 0;
-    if (ret == -1) {
-        if (written > 0) {
-            /* Can be a limitation of iconv or uconv */
-            goto retry;
-        }
-        ret = -3;
-    }
+
+    if (ret == XML_ENC_ERR_SPACE)
+        goto retry;
 
     /*
      * Attempt to handle error cases
      */
-    switch (ret) {
-        case 0:
-#ifdef DEBUG_ENCODING
-	    xmlGenericError(xmlGenericErrorContext,
-		    "converted %d bytes to %d bytes of output\n",
-	            toconv, written);
-#endif
-	    break;
-        case -1:
-#ifdef DEBUG_ENCODING
-	    xmlGenericError(xmlGenericErrorContext,
-		    "output conversion failed by lack of space\n");
-#endif
-	    break;
-        case -3:
-#ifdef DEBUG_ENCODING
-	    xmlGenericError(xmlGenericErrorContext,"converted %d bytes to %d bytes of output %d left\n",
-	            toconv, written, in->use);
-#endif
-	    break;
-        case -4:
-	    xmlEncodingErr(XML_I18N_NO_OUTPUT,
-		           "xmlCharEncOutFunc: no output function !\n", NULL);
-	    ret = -1;
-            break;
-        case -2: {
-	    xmlChar charref[20];
-	    int len = in->use;
-	    const xmlChar *utf = (const xmlChar *) in->content;
-	    int cur, charrefLen;
-
-	    cur = xmlGetUTF8Char(utf, &len);
-	    if (cur <= 0)
-                break;
+    if (ret == XML_ENC_ERR_INPUT) {
+        xmlChar charref[20];
+        int len = in->use;
+        const xmlChar *utf = (const xmlChar *) in->content;
+        int cur, charrefLen;
 
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-                    "handling output conversion error\n");
-            xmlGenericError(xmlGenericErrorContext,
-                    "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
-                    in->content[0], in->content[1],
-                    in->content[2], in->content[3]);
-#endif
-            /*
-             * Removes the UTF8 sequence, and replace it by a charref
-             * and continue the transcoding phase, hoping the error
-             * did not mangle the encoder state.
-             */
-            charrefLen = snprintf((char *) &charref[0], sizeof(charref),
-                             "&#%d;", cur);
-            xmlBufferShrink(in, len);
-            xmlBufferGrow(out, charrefLen * 4);
-	    written = out->size - out->use - 1;
-            toconv = charrefLen;
-            ret = xmlEncOutputChunk(handler, &out->content[out->use], &written,
-                                    charref, &toconv);
-
-	    if ((ret < 0) || (toconv != charrefLen)) {
-		char buf[50];
-
-		snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X",
-			 in->content[0], in->content[1],
-			 in->content[2], in->content[3]);
-		buf[49] = 0;
-		xmlEncodingErr(XML_I18N_CONV_FAILED,
-		    "output conversion failed due to conv error, bytes %s\n",
-			       buf);
-		if (in->alloc != XML_BUFFER_ALLOC_IMMUTABLE)
-		    in->content[0] = ' ';
-	        break;
-	    }
+        cur = xmlGetUTF8Char(utf, &len);
+        if (cur <= 0)
+            return(ret);
 
-            out->use += written;
-            writtentot += written;
-            out->content[out->use] = 0;
-            goto retry;
-	}
+        /*
+         * Removes the UTF8 sequence, and replace it by a charref
+         * and continue the transcoding phase, hoping the error
+         * did not mangle the encoder state.
+         */
+        charrefLen = snprintf((char *) &charref[0], sizeof(charref),
+                         "&#%d;", cur);
+        xmlBufferShrink(in, len);
+        xmlBufferGrow(out, charrefLen * 4);
+        written = out->size - out->use - 1;
+        toconv = charrefLen;
+        ret = xmlEncOutputChunk(handler, &out->content[out->use], &written,
+                                charref, &toconv);
+        if ((ret < 0) || (toconv != charrefLen))
+            return(XML_ENC_ERR_INTERNAL);
+
+        out->use += written;
+        writtentot += written;
+        out->content[out->use] = 0;
+        goto retry;
     }
     return(writtentot ? writtentot : ret);
 }
@@ -2796,19 +2652,19 @@ int
 xmlCharEncCloseFunc(xmlCharEncodingHandler *handler) {
     int ret = 0;
     int tofree = 0;
-    int i, handler_in_list = 0;
-
-    /* Avoid unused variable warning if features are disabled. */
-    (void) handler_in_list;
+    int i = 0;
 
     if (handler == NULL) return(-1);
-    if (handler->name == NULL) return(-1);
+
+    for (i = 0; i < (int) NUM_DEFAULT_HANDLERS; i++) {
+        if (handler == &defaultHandlers[i])
+            return(0);
+    }
+
     if (handlers != NULL) {
         for (i = 0;i < nbCharEncodingHandler; i++) {
-            if (handler == handlers[i]) {
-	        handler_in_list = 1;
-		break;
-	    }
+            if (handler == handlers[i])
+                return(0);
 	}
     }
 #ifdef LIBXML_ICONV_ENABLED
@@ -2816,8 +2672,7 @@ xmlCharEncCloseFunc(xmlCharEncodingHandler *handler) {
      * Iconv handlers can be used only once, free the whole block.
      * and the associated icon resources.
      */
-    if ((handler_in_list == 0) &&
-        ((handler->iconv_out != NULL) || (handler->iconv_in != NULL))) {
+    if ((handler->iconv_out != NULL) || (handler->iconv_in != NULL)) {
         tofree = 1;
 	if (handler->iconv_out != NULL) {
 	    if (iconv_close(handler->iconv_out))
@@ -2832,8 +2687,7 @@ xmlCharEncCloseFunc(xmlCharEncodingHandler *handler) {
     }
 #endif /* LIBXML_ICONV_ENABLED */
 #ifdef LIBXML_ICU_ENABLED
-    if ((handler_in_list == 0) &&
-        ((handler->uconv_out != NULL) || (handler->uconv_in != NULL))) {
+    if ((handler->uconv_out != NULL) || (handler->uconv_in != NULL)) {
         tofree = 1;
 	if (handler->uconv_out != NULL) {
 	    closeIcuConverter(handler->uconv_out);
@@ -2852,14 +2706,6 @@ xmlCharEncCloseFunc(xmlCharEncodingHandler *handler) {
         handler->name = NULL;
         xmlFree(handler);
     }
-#ifdef DEBUG_ENCODING
-    if (ret)
-        xmlGenericError(xmlGenericErrorContext,
-		"failed to close the encoding handler\n");
-    else
-        xmlGenericError(xmlGenericErrorContext,
-		"closed the encoding handler\n");
-#endif
 
     return(ret);
 }
@@ -2905,15 +2751,11 @@ xmlByteConsumed(xmlParserCtxtPtr ctxt) {
                 written = 32000;
                 ret = xmlEncOutputChunk(handler, &convbuf[0], &written,
                                         cur, &toconv);
-                if (ret < 0) {
-                    if (written > 0)
-                        ret = -2;
-                    else
-                        return(-1);
-                }
+                if ((ret != XML_ENC_ERR_SUCCESS) && (ret != XML_ENC_ERR_SPACE))
+                    return(-1);
                 unused += written;
                 cur += toconv;
-            } while (ret == -2);
+            } while (ret == XML_ENC_ERR_SPACE);
 	}
 	if (in->buf->rawconsumed < unused)
 	    return(-1);
@@ -2936,9 +2778,10 @@ xmlByteConsumed(xmlParserCtxtPtr ctxt) {
  * Take a block of UTF-8 chars in and try to convert it to an ISO 8859-*
  * block of chars out.
  *
- * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise
+ * Returns the number of bytes written or an XML_ENC_ERR code.
+ *
  * The value of @inlen after return is the number of octets consumed
- *     as the return value is positive, else unpredictable.
+ * as the return value is positive, else unpredictable.
  * The value of @outlen after return is the number of octets consumed.
  */
 static int
@@ -2952,7 +2795,7 @@ UTF8ToISO8859x(unsigned char* out, int *outlen,
 
     if ((out == NULL) || (outlen == NULL) || (inlen == NULL) ||
         (xlattable == NULL))
-	return(-1);
+	return(XML_ENC_ERR_INTERNAL);
     if (in == NULL) {
         /*
         * initialization nothing to do
@@ -2970,21 +2813,21 @@ UTF8ToISO8859x(unsigned char* out, int *outlen,
             /* trailing byte in leading position */
             *outlen = out - outstart;
             *inlen = processed - instart;
-            return(-2);
+            return(XML_ENC_ERR_INPUT);
         } else if (d < 0xE0) {
             unsigned char c;
             if (!(in < inend)) {
                 /* trailing byte not in input buffer */
                 *outlen = out - outstart;
                 *inlen = processed - instart;
-                return(-3);
+                return(XML_ENC_ERR_PARTIAL);
             }
             c = *in++;
             if ((c & 0xC0) != 0x80) {
                 /* not a trailing byte */
                 *outlen = out - outstart;
                 *inlen = processed - instart;
-                return(-2);
+                return(XML_ENC_ERR_INPUT);
             }
             c = c & 0x3F;
             d = d & 0x1F;
@@ -2993,7 +2836,7 @@ UTF8ToISO8859x(unsigned char* out, int *outlen,
                 /* not in character set */
                 *outlen = out - outstart;
                 *inlen = processed - instart;
-                return(-2);
+                return(XML_ENC_ERR_INPUT);
             }
             *out++ = d;
         } else if (d < 0xF0) {
@@ -3003,21 +2846,21 @@ UTF8ToISO8859x(unsigned char* out, int *outlen,
                 /* trailing bytes not in input buffer */
                 *outlen = out - outstart;
                 *inlen = processed - instart;
-                return(-3);
+                return(XML_ENC_ERR_PARTIAL);
             }
             c1 = *in++;
             if ((c1 & 0xC0) != 0x80) {
                 /* not a trailing byte (c1) */
                 *outlen = out - outstart;
                 *inlen = processed - instart;
-                return(-2);
+                return(XML_ENC_ERR_INPUT);
             }
             c2 = *in++;
             if ((c2 & 0xC0) != 0x80) {
                 /* not a trailing byte (c2) */
                 *outlen = out - outstart;
                 *inlen = processed - instart;
-                return(-2);
+                return(XML_ENC_ERR_INPUT);
             }
             c1 = c1 & 0x3F;
             c2 = c2 & 0x3F;
@@ -3028,14 +2871,14 @@ UTF8ToISO8859x(unsigned char* out, int *outlen,
                 /* not in character set */
                 *outlen = out - outstart;
                 *inlen = processed - instart;
-                return(-2);
+                return(XML_ENC_ERR_INPUT);
             }
             *out++ = d;
         } else {
             /* cannot transcode >= U+010000 */
             *outlen = out - outstart;
             *inlen = processed - instart;
-            return(-2);
+            return(XML_ENC_ERR_INPUT);
         }
         processed = in;
     }
@@ -3053,7 +2896,9 @@ UTF8ToISO8859x(unsigned char* out, int *outlen,
  *
  * Take a block of ISO 8859-* chars in and try to convert it to an UTF-8
  * block of chars out.
- * Returns 0 if success, or -1 otherwise
+ *
+ * Returns the number of bytes written or an XML_ENC_ERR code.
+ *
  * The value of @inlen after return is the number of octets consumed
  * The value of @outlen after return is the number of octets produced.
  */
@@ -3070,7 +2915,7 @@ ISO8859xToUTF8(unsigned char* out, int *outlen,
 
     if ((out == NULL) || (outlen == NULL) || (inlen == NULL) ||
         (in == NULL) || (unicodetable == NULL))
-	return(-1);
+	return(XML_ENC_ERR_INTERNAL);
     outend = out + *outlen;
     inend = in + *inlen;
     instop = inend;
@@ -3082,7 +2927,7 @@ ISO8859xToUTF8(unsigned char* out, int *outlen,
                 /* undefined code point */
                 *outlen = out - outstart;
                 *inlen = in - instart;
-                return (-1);
+                return(XML_ENC_ERR_INPUT);
             }
             if (c < 0x800) {
                 *out++ = ((c >>  6) & 0x1F) | 0xC0;
@@ -3115,7 +2960,7 @@ ISO8859xToUTF8(unsigned char* out, int *outlen,
  * Lookup tables for ISO-8859-2..ISO-8859-16 transcoding                *
  ************************************************************************/
 
-static unsigned short const xmlunicodetable_ISO8859_2 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_2 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3164,7 +3009,7 @@ static const unsigned char xmltranscodetable_ISO8859_2 [48 + 6 * 64] = {
     "\x00\x00\x00\xf3\xf4\x00\xf6\xf7\x00\x00\xfa\x00\xfc\xfd\x00\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_3 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_3 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3217,7 +3062,7 @@ static const unsigned char xmltranscodetable_ISO8859_3 [48 + 7 * 64] = {
     "\x00\xf1\xf2\xf3\xf4\x00\xf6\xf7\x00\xf9\xfa\xfb\xfc\x00\x00\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_4 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_4 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3266,7 +3111,7 @@ static const unsigned char xmltranscodetable_ISO8859_4 [48 + 6 * 64] = {
     "\x00\x00\x00\x00\xf4\xf5\xf6\xf7\xf8\x00\xfa\xfb\xfc\x00\x00\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_5 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_5 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3315,7 +3160,7 @@ static const unsigned char xmltranscodetable_ISO8859_5 [48 + 6 * 64] = {
     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_6 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_6 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3360,7 +3205,7 @@ static const unsigned char xmltranscodetable_ISO8859_6 [48 + 5 * 64] = {
     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_7 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_7 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3413,7 +3258,7 @@ static const unsigned char xmltranscodetable_ISO8859_7 [48 + 7 * 64] = {
     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_8 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_8 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3466,7 +3311,7 @@ static const unsigned char xmltranscodetable_ISO8859_8 [48 + 7 * 64] = {
     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_9 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_9 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3511,7 +3356,7 @@ static const unsigned char xmltranscodetable_ISO8859_9 [48 + 5 * 64] = {
     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_10 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_10 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3564,7 +3409,7 @@ static const unsigned char xmltranscodetable_ISO8859_10 [48 + 7 * 64] = {
     "\xf0\x00\x00\xf3\xf4\xf5\xf6\x00\xf8\x00\xfa\xfb\xfc\xfd\xfe\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_11 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_11 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3613,7 +3458,7 @@ static const unsigned char xmltranscodetable_ISO8859_11 [48 + 6 * 64] = {
     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_13 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_13 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3666,7 +3511,7 @@ static const unsigned char xmltranscodetable_ISO8859_13 [48 + 7 * 64] = {
     "\x00\x00\x00\x00\x00\x00\xcd\xed\x00\x00\x00\xcf\xef\x00\x00\x00"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_14 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_14 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3731,7 +3576,7 @@ static const unsigned char xmltranscodetable_ISO8859_14 [48 + 10 * 64] = {
     "\x00\xf1\xf2\xf3\xf4\xf5\xf6\x00\xf8\xf9\xfa\xfb\xfc\xfd\x00\xff"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_15 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_15 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3780,7 +3625,7 @@ static const unsigned char xmltranscodetable_ISO8859_15 [48 + 6 * 64] = {
     "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
 };
 
-static unsigned short const xmlunicodetable_ISO8859_16 [128] = {
+static const unsigned short xmlunicodetable_ISO8859_16 [128] = {
     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
@@ -3972,24 +3817,6 @@ static int UTF8ToISO8859_16 (unsigned char* out, int *outlen,
     return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_16);
 }
 
-static void
-xmlRegisterCharEncodingHandlersISO8859x (void) {
-    xmlNewCharEncodingHandler ("ISO-8859-2", ISO8859_2ToUTF8, UTF8ToISO8859_2);
-    xmlNewCharEncodingHandler ("ISO-8859-3", ISO8859_3ToUTF8, UTF8ToISO8859_3);
-    xmlNewCharEncodingHandler ("ISO-8859-4", ISO8859_4ToUTF8, UTF8ToISO8859_4);
-    xmlNewCharEncodingHandler ("ISO-8859-5", ISO8859_5ToUTF8, UTF8ToISO8859_5);
-    xmlNewCharEncodingHandler ("ISO-8859-6", ISO8859_6ToUTF8, UTF8ToISO8859_6);
-    xmlNewCharEncodingHandler ("ISO-8859-7", ISO8859_7ToUTF8, UTF8ToISO8859_7);
-    xmlNewCharEncodingHandler ("ISO-8859-8", ISO8859_8ToUTF8, UTF8ToISO8859_8);
-    xmlNewCharEncodingHandler ("ISO-8859-9", ISO8859_9ToUTF8, UTF8ToISO8859_9);
-    xmlNewCharEncodingHandler ("ISO-8859-10", ISO8859_10ToUTF8, UTF8ToISO8859_10);
-    xmlNewCharEncodingHandler ("ISO-8859-11", ISO8859_11ToUTF8, UTF8ToISO8859_11);
-    xmlNewCharEncodingHandler ("ISO-8859-13", ISO8859_13ToUTF8, UTF8ToISO8859_13);
-    xmlNewCharEncodingHandler ("ISO-8859-14", ISO8859_14ToUTF8, UTF8ToISO8859_14);
-    xmlNewCharEncodingHandler ("ISO-8859-15", ISO8859_15ToUTF8, UTF8ToISO8859_15);
-    xmlNewCharEncodingHandler ("ISO-8859-16", ISO8859_16ToUTF8, UTF8ToISO8859_16);
-}
-
 #endif
 #endif
 
diff --git a/entities.c b/entities.c
index 84435515f733d346f0abfcf80fb4f725eafb0857..f7792a8138ec1956df5e6ff3240ef4ddb1c79fc3 100644
--- a/entities.c
+++ b/entities.c
@@ -23,10 +23,11 @@
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
 #include <libxml/xmlerror.h>
-#include <libxml/globals.h>
 #include <libxml/dict.h>
+#include <libxml/xmlsave.h>
 
-#include "save.h"
+#include "private/entities.h"
+#include "private/error.h"
 
 /*
  * The XML predefined entities.
@@ -37,83 +38,44 @@ static xmlEntity xmlEntityLt = {
     NULL, NULL, NULL, NULL, NULL, NULL,
     BAD_CAST "<", BAD_CAST "<", 1,
     XML_INTERNAL_PREDEFINED_ENTITY,
-    NULL, NULL, NULL, NULL, 0, 1
+    NULL, NULL, NULL, NULL, 0, 0, 0
 };
 static xmlEntity xmlEntityGt = {
     NULL, XML_ENTITY_DECL, BAD_CAST "gt",
     NULL, NULL, NULL, NULL, NULL, NULL,
     BAD_CAST ">", BAD_CAST ">", 1,
     XML_INTERNAL_PREDEFINED_ENTITY,
-    NULL, NULL, NULL, NULL, 0, 1
+    NULL, NULL, NULL, NULL, 0, 0, 0
 };
 static xmlEntity xmlEntityAmp = {
     NULL, XML_ENTITY_DECL, BAD_CAST "amp",
     NULL, NULL, NULL, NULL, NULL, NULL,
     BAD_CAST "&", BAD_CAST "&", 1,
     XML_INTERNAL_PREDEFINED_ENTITY,
-    NULL, NULL, NULL, NULL, 0, 1
+    NULL, NULL, NULL, NULL, 0, 0, 0
 };
 static xmlEntity xmlEntityQuot = {
     NULL, XML_ENTITY_DECL, BAD_CAST "quot",
     NULL, NULL, NULL, NULL, NULL, NULL,
     BAD_CAST "\"", BAD_CAST "\"", 1,
     XML_INTERNAL_PREDEFINED_ENTITY,
-    NULL, NULL, NULL, NULL, 0, 1
+    NULL, NULL, NULL, NULL, 0, 0, 0
 };
 static xmlEntity xmlEntityApos = {
     NULL, XML_ENTITY_DECL, BAD_CAST "apos",
     NULL, NULL, NULL, NULL, NULL, NULL,
     BAD_CAST "'", BAD_CAST "'", 1,
     XML_INTERNAL_PREDEFINED_ENTITY,
-    NULL, NULL, NULL, NULL, 0, 1
+    NULL, NULL, NULL, NULL, 0, 0, 0
 };
 
-/**
- * xmlEntitiesErrMemory:
- * @extra:  extra information
- *
- * Handle an out of memory condition
- */
-static void
-xmlEntitiesErrMemory(const char *extra)
-{
-    __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra);
-}
-
-/**
- * xmlEntitiesErr:
- * @code:  the error code
- * @msg:  the message
- *
- * Raise an error.
- */
-static void LIBXML_ATTR_FORMAT(2,0)
-xmlEntitiesErr(xmlParserErrors code, const char *msg)
-{
-    __xmlSimpleError(XML_FROM_TREE, code, NULL, msg, NULL);
-}
-
-/**
- * xmlEntitiesWarn:
- * @code:  the error code
- * @msg:  the message
- *
- * Raise a warning.
- */
-static void LIBXML_ATTR_FORMAT(2,0)
-xmlEntitiesWarn(xmlParserErrors code, const char *msg, const xmlChar *str1)
-{
-    __xmlRaiseError(NULL, NULL, NULL,
-                NULL, NULL, XML_FROM_TREE, code,
-                XML_ERR_WARNING, NULL, 0,
-                (const char *)str1, NULL, NULL, 0, 0,
-                msg, (const char *)str1, NULL);
-}
-
 /*
- * xmlFreeEntity : clean-up an entity record.
+ * xmlFreeEntity:
+ * @entity:  an entity
+ *
+ * Frees the entity.
  */
-static void
+void
 xmlFreeEntity(xmlEntityPtr entity)
 {
     xmlDictPtr dict = NULL;
@@ -125,39 +87,22 @@ xmlFreeEntity(xmlEntityPtr entity)
         dict = entity->doc->dict;
 
 
-    if ((entity->children) && (entity->owner == 1) &&
+    if ((entity->children) &&
         (entity == (xmlEntityPtr) entity->children->parent))
         xmlFreeNodeList(entity->children);
-    if (dict != NULL) {
-        if ((entity->name != NULL) && (!xmlDictOwns(dict, entity->name)))
-            xmlFree((char *) entity->name);
-        if ((entity->ExternalID != NULL) &&
-	    (!xmlDictOwns(dict, entity->ExternalID)))
-            xmlFree((char *) entity->ExternalID);
-        if ((entity->SystemID != NULL) &&
-	    (!xmlDictOwns(dict, entity->SystemID)))
-            xmlFree((char *) entity->SystemID);
-        if ((entity->URI != NULL) && (!xmlDictOwns(dict, entity->URI)))
-            xmlFree((char *) entity->URI);
-        if ((entity->content != NULL)
-            && (!xmlDictOwns(dict, entity->content)))
-            xmlFree((char *) entity->content);
-        if ((entity->orig != NULL) && (!xmlDictOwns(dict, entity->orig)))
-            xmlFree((char *) entity->orig);
-    } else {
-        if (entity->name != NULL)
-            xmlFree((char *) entity->name);
-        if (entity->ExternalID != NULL)
-            xmlFree((char *) entity->ExternalID);
-        if (entity->SystemID != NULL)
-            xmlFree((char *) entity->SystemID);
-        if (entity->URI != NULL)
-            xmlFree((char *) entity->URI);
-        if (entity->content != NULL)
-            xmlFree((char *) entity->content);
-        if (entity->orig != NULL)
-            xmlFree((char *) entity->orig);
-    }
+    if ((entity->name != NULL) &&
+        ((dict == NULL) || (!xmlDictOwns(dict, entity->name))))
+        xmlFree((char *) entity->name);
+    if (entity->ExternalID != NULL)
+        xmlFree((char *) entity->ExternalID);
+    if (entity->SystemID != NULL)
+        xmlFree((char *) entity->SystemID);
+    if (entity->URI != NULL)
+        xmlFree((char *) entity->URI);
+    if (entity->content != NULL)
+        xmlFree((char *) entity->content);
+    if (entity->orig != NULL)
+        xmlFree((char *) entity->orig);
     xmlFree(entity);
 }
 
@@ -167,44 +112,43 @@ xmlFreeEntity(xmlEntityPtr entity)
  * internal routine doing the entity node structures allocations
  */
 static xmlEntityPtr
-xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type,
+xmlCreateEntity(xmlDocPtr doc, const xmlChar *name, int type,
 	        const xmlChar *ExternalID, const xmlChar *SystemID,
 	        const xmlChar *content) {
     xmlEntityPtr ret;
 
     ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
-    if (ret == NULL) {
-        xmlEntitiesErrMemory("xmlCreateEntity: malloc failed");
+    if (ret == NULL)
 	return(NULL);
-    }
     memset(ret, 0, sizeof(xmlEntity));
+    ret->doc = doc;
     ret->type = XML_ENTITY_DECL;
-    ret->checked = 0;
 
     /*
      * fill the structure.
      */
     ret->etype = (xmlEntityType) type;
-    if (dict == NULL) {
+    if ((doc == NULL) || (doc->dict == NULL))
 	ret->name = xmlStrdup(name);
-	if (ExternalID != NULL)
-	    ret->ExternalID = xmlStrdup(ExternalID);
-	if (SystemID != NULL)
-	    ret->SystemID = xmlStrdup(SystemID);
-    } else {
-        ret->name = xmlDictLookup(dict, name, -1);
-	if (ExternalID != NULL)
-	    ret->ExternalID = xmlDictLookup(dict, ExternalID, -1);
-	if (SystemID != NULL)
-	    ret->SystemID = xmlDictLookup(dict, SystemID, -1);
+    else
+        ret->name = xmlDictLookup(doc->dict, name, -1);
+    if (ret->name == NULL)
+        goto error;
+    if (ExternalID != NULL) {
+        ret->ExternalID = xmlStrdup(ExternalID);
+        if (ret->ExternalID == NULL)
+            goto error;
+    }
+    if (SystemID != NULL) {
+        ret->SystemID = xmlStrdup(SystemID);
+        if (ret->SystemID == NULL)
+            goto error;
     }
     if (content != NULL) {
         ret->length = xmlStrlen(content);
-	if ((dict != NULL) && (ret->length < 5))
-	    ret->content = (xmlChar *)
-	                   xmlDictLookup(dict, content, ret->length);
-	else
-	    ret->content = xmlStrndup(content, ret->length);
+	ret->content = xmlStrndup(content, ret->length);
+        if (ret->content == NULL)
+            goto error;
      } else {
         ret->length = 0;
         ret->content = NULL;
@@ -212,28 +156,53 @@ xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type,
     ret->URI = NULL; /* to be computed by the layer knowing
 			the defining entity */
     ret->orig = NULL;
-    ret->owner = 0;
 
     return(ret);
+
+error:
+    xmlFreeEntity(ret);
+    return(NULL);
 }
 
-/*
- * xmlAddEntity : register a new entity for an entities table.
+/**
+ * xmlAddEntity:
+ * @doc:  the document
+ * @extSubset:  add to the external or internal subset
+ * @name:  the entity name
+ * @type:  the entity type XML_xxx_yyy_ENTITY
+ * @ExternalID:  the entity external ID if available
+ * @SystemID:  the entity system ID if available
+ * @content:  the entity content
+ * @out:  pointer to resulting entity (optional)
+ *
+ * Register a new entity for this document.
+ *
+ * Available since 2.13.0.
+ *
+ * Returns an xmlParserErrors error code.
  */
-static xmlEntityPtr
-xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
+int
+xmlAddEntity(xmlDocPtr doc, int extSubset, const xmlChar *name, int type,
 	  const xmlChar *ExternalID, const xmlChar *SystemID,
-	  const xmlChar *content) {
+	  const xmlChar *content, xmlEntityPtr *out) {
+    xmlDtdPtr dtd;
     xmlDictPtr dict = NULL;
     xmlEntitiesTablePtr table = NULL;
     xmlEntityPtr ret, predef;
+    int res;
 
-    if (name == NULL)
-	return(NULL);
+    if (out != NULL)
+        *out = NULL;
+    if ((doc == NULL) || (name == NULL))
+	return(XML_ERR_ARGUMENT);
+    dict = doc->dict;
+
+    if (extSubset)
+        dtd = doc->extSubset;
+    else
+        dtd = doc->intSubset;
     if (dtd == NULL)
-	return(NULL);
-    if (dtd->doc != NULL)
-        dict = dtd->doc->dict;
+        return(XML_DTD_NO_DTD);
 
     switch (type) {
         case XML_INTERNAL_GENERAL_ENTITY:
@@ -270,41 +239,60 @@ xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
                         }
                     }
                 }
-                if (!valid) {
-                    xmlEntitiesWarn(XML_ERR_ENTITY_PROCESSING,
-                            "xmlAddEntity: invalid redeclaration of predefined"
-                            " entity '%s'", name);
-                    return(NULL);
-                }
+                if (!valid)
+                    return(XML_ERR_REDECL_PREDEF_ENTITY);
             }
-	    if (dtd->entities == NULL)
+	    if (dtd->entities == NULL) {
 		dtd->entities = xmlHashCreateDict(0, dict);
+                if (dtd->entities == NULL)
+                    return(XML_ERR_NO_MEMORY);
+            }
 	    table = dtd->entities;
 	    break;
         case XML_INTERNAL_PARAMETER_ENTITY:
         case XML_EXTERNAL_PARAMETER_ENTITY:
-	    if (dtd->pentities == NULL)
+	    if (dtd->pentities == NULL) {
 		dtd->pentities = xmlHashCreateDict(0, dict);
+                if (dtd->pentities == NULL)
+                    return(XML_ERR_NO_MEMORY);
+            }
 	    table = dtd->pentities;
 	    break;
-        case XML_INTERNAL_PREDEFINED_ENTITY:
-	    return(NULL);
+        default:
+	    return(XML_ERR_ARGUMENT);
     }
-    if (table == NULL)
-	return(NULL);
-    ret = xmlCreateEntity(dict, name, type, ExternalID, SystemID, content);
+    ret = xmlCreateEntity(dtd->doc, name, type, ExternalID, SystemID, content);
     if (ret == NULL)
-        return(NULL);
-    ret->doc = dtd->doc;
+        return(XML_ERR_NO_MEMORY);
 
-    if (xmlHashAddEntry(table, name, ret)) {
+    res = xmlHashAdd(table, name, ret);
+    if (res < 0) {
+        xmlFreeEntity(ret);
+        return(XML_ERR_NO_MEMORY);
+    } else if (res == 0) {
 	/*
 	 * entity was already defined at another level.
 	 */
         xmlFreeEntity(ret);
-	return(NULL);
+	return(XML_WAR_ENTITY_REDEFINED);
     }
-    return(ret);
+
+    /*
+     * Link it to the DTD
+     */
+    ret->parent = dtd;
+    ret->doc = dtd->doc;
+    if (dtd->last == NULL) {
+	dtd->children = dtd->last = (xmlNodePtr) ret;
+    } else {
+	dtd->last->next = (xmlNodePtr) ret;
+	ret->prev = dtd->last;
+	dtd->last = (xmlNodePtr) ret;
+    }
+
+    if (out != NULL)
+        *out = ret;
+    return(0);
 }
 
 /**
@@ -361,34 +349,8 @@ xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
 	        const xmlChar *ExternalID, const xmlChar *SystemID,
 		const xmlChar *content) {
     xmlEntityPtr ret;
-    xmlDtdPtr dtd;
-
-    if (doc == NULL) {
-	xmlEntitiesErr(XML_DTD_NO_DOC,
-	        "xmlAddDtdEntity: document is NULL");
-	return(NULL);
-    }
-    if (doc->extSubset == NULL) {
-	xmlEntitiesErr(XML_DTD_NO_DTD,
-	        "xmlAddDtdEntity: document without external subset");
-	return(NULL);
-    }
-    dtd = doc->extSubset;
-    ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content);
-    if (ret == NULL) return(NULL);
 
-    /*
-     * Link it to the DTD
-     */
-    ret->parent = dtd;
-    ret->doc = dtd->doc;
-    if (dtd->last == NULL) {
-	dtd->children = dtd->last = (xmlNodePtr) ret;
-    } else {
-        dtd->last->next = (xmlNodePtr) ret;
-	ret->prev = dtd->last;
-	dtd->last = (xmlNodePtr) ret;
-    }
+    xmlAddEntity(doc, 1, name, type, ExternalID, SystemID, content, &ret);
     return(ret);
 }
 
@@ -410,34 +372,8 @@ xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
 	        const xmlChar *ExternalID, const xmlChar *SystemID,
 	        const xmlChar *content) {
     xmlEntityPtr ret;
-    xmlDtdPtr dtd;
-
-    if (doc == NULL) {
-	xmlEntitiesErr(XML_DTD_NO_DOC,
-	        "xmlAddDocEntity: document is NULL");
-	return(NULL);
-    }
-    if (doc->intSubset == NULL) {
-	xmlEntitiesErr(XML_DTD_NO_DTD,
-	        "xmlAddDocEntity: document without internal subset");
-	return(NULL);
-    }
-    dtd = doc->intSubset;
-    ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content);
-    if (ret == NULL) return(NULL);
 
-    /*
-     * Link it to the DTD
-     */
-    ret->parent = dtd;
-    ret->doc = dtd->doc;
-    if (dtd->last == NULL) {
-	dtd->children = dtd->last = (xmlNodePtr) ret;
-    } else {
-	dtd->last->next = (xmlNodePtr) ret;
-	ret->prev = dtd->last;
-	dtd->last = (xmlNodePtr) ret;
-    }
+    xmlAddEntity(doc, 0, name, type, ExternalID, SystemID, content, &ret);
     return(ret);
 }
 
@@ -462,21 +398,12 @@ xmlEntityPtr
 xmlNewEntity(xmlDocPtr doc, const xmlChar *name, int type,
 	     const xmlChar *ExternalID, const xmlChar *SystemID,
 	     const xmlChar *content) {
-    xmlEntityPtr ret;
-    xmlDictPtr dict;
-
     if ((doc != NULL) && (doc->intSubset != NULL)) {
 	return(xmlAddDocEntity(doc, name, type, ExternalID, SystemID, content));
     }
-    if (doc != NULL)
-        dict = doc->dict;
-    else
-        dict = NULL;
-    ret = xmlCreateEntity(dict, name, type, ExternalID, SystemID, content);
-    if (ret == NULL)
+    if (name == NULL)
         return(NULL);
-    ret->doc = doc;
-    return(ret);
+    return(xmlCreateEntity(doc, name, type, ExternalID, SystemID, content));
 }
 
 /**
@@ -627,11 +554,9 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
      * allocate an translation buffer.
      */
     buffer_size = 1000;
-    buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
-    if (buffer == NULL) {
-        xmlEntitiesErrMemory("xmlEncodeEntities: malloc failed");
+    buffer = (xmlChar *) xmlMalloc(buffer_size);
+    if (buffer == NULL)
 	return(NULL);
-    }
     out = buffer;
 
     while (*cur != '\0') {
@@ -731,57 +656,18 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
 		 *   cur[3] is 10xxxxxx if cur[0] is 1111xxxx
 		 *   cur[0] is not 11111xxx
 		 */
-		char buf[11], *ptr;
-		int val = 0, l = 1;
-
-		if (((cur[0] & 0xC0) != 0xC0) ||
-		    ((cur[1] & 0xC0) != 0x80) ||
-		    (((cur[0] & 0xE0) == 0xE0) && ((cur[2] & 0xC0) != 0x80)) ||
-		    (((cur[0] & 0xF0) == 0xF0) && ((cur[3] & 0xC0) != 0x80)) ||
-		    (((cur[0] & 0xF8) == 0xF8))) {
-		    xmlEntitiesErr(XML_CHECK_NOT_UTF8,
-			    "xmlEncodeEntities: input not UTF-8");
-		    if (doc != NULL)
-			doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
-		    snprintf(buf, sizeof(buf), "&#%d;", *cur);
-		    buf[sizeof(buf) - 1] = 0;
-		    ptr = buf;
-		    while (*ptr != 0) *out++ = *ptr++;
-		    cur++;
-		    continue;
-		} else if (*cur < 0xE0) {
-                    val = (cur[0]) & 0x1F;
-		    val <<= 6;
-		    val |= (cur[1]) & 0x3F;
-		    l = 2;
-		} else if (*cur < 0xF0) {
-                    val = (cur[0]) & 0x0F;
-		    val <<= 6;
-		    val |= (cur[1]) & 0x3F;
-		    val <<= 6;
-		    val |= (cur[2]) & 0x3F;
-		    l = 3;
-		} else if (*cur < 0xF8) {
-                    val = (cur[0]) & 0x07;
-		    val <<= 6;
-		    val |= (cur[1]) & 0x3F;
-		    val <<= 6;
-		    val |= (cur[2]) & 0x3F;
-		    val <<= 6;
-		    val |= (cur[3]) & 0x3F;
-		    l = 4;
-		}
-		if ((l == 1) || (!IS_CHAR(val))) {
-		    xmlEntitiesErr(XML_ERR_INVALID_CHAR,
-			"xmlEncodeEntities: char out of range\n");
-		    if (doc != NULL)
-			doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
-		    snprintf(buf, sizeof(buf), "&#%d;", *cur);
-		    buf[sizeof(buf) - 1] = 0;
-		    ptr = buf;
-		    while (*ptr != 0) *out++ = *ptr++;
-		    cur++;
-		    continue;
+		char buf[13], *ptr;
+		int val, l;
+
+                l = 4;
+                val = xmlGetUTF8Char(cur, &l);
+                if (val < 0) {
+                    val = 0xFFFD;
+                    cur++;
+                } else {
+                    if (!IS_CHAR(val))
+                        val = 0xFFFD;
+                    cur += l;
 		}
 		/*
 		 * We could do multiple things here. Just save as a char ref
@@ -790,7 +676,6 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
 		buf[sizeof(buf) - 1] = 0;
 		ptr = buf;
 		while (*ptr != 0) *out++ = *ptr++;
-		cur += l;
 		continue;
 	    }
 	} else if (IS_BYTE_CHAR(*cur)) {
@@ -807,7 +692,6 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
     return(buffer);
 
 mem_error:
-    xmlEntitiesErrMemory("xmlEncodeEntities: realloc failed");
     xmlFree(buffer);
     return(NULL);
 }
@@ -867,11 +751,9 @@ xmlEncodeSpecialChars(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlChar *input)
      * allocate an translation buffer.
      */
     buffer_size = 1000;
-    buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
-    if (buffer == NULL) {
-        xmlEntitiesErrMemory("xmlEncodeSpecialChars: malloc failed");
+    buffer = (xmlChar *) xmlMalloc(buffer_size);
+    if (buffer == NULL)
 	return(NULL);
-    }
     out = buffer;
 
     while (*cur != '\0') {
@@ -927,7 +809,6 @@ xmlEncodeSpecialChars(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlChar *input)
     return(buffer);
 
 mem_error:
-    xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed");
     xmlFree(buffer);
     return(NULL);
 }
@@ -984,27 +865,47 @@ xmlCopyEntity(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
     xmlEntityPtr cur;
 
     cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
-    if (cur == NULL) {
-        xmlEntitiesErrMemory("xmlCopyEntity:: malloc failed");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlEntity));
     cur->type = XML_ENTITY_DECL;
 
     cur->etype = ent->etype;
-    if (ent->name != NULL)
+    if (ent->name != NULL) {
 	cur->name = xmlStrdup(ent->name);
-    if (ent->ExternalID != NULL)
+        if (cur->name == NULL)
+            goto error;
+    }
+    if (ent->ExternalID != NULL) {
 	cur->ExternalID = xmlStrdup(ent->ExternalID);
-    if (ent->SystemID != NULL)
+        if (cur->ExternalID == NULL)
+            goto error;
+    }
+    if (ent->SystemID != NULL) {
 	cur->SystemID = xmlStrdup(ent->SystemID);
-    if (ent->content != NULL)
+        if (cur->SystemID == NULL)
+            goto error;
+    }
+    if (ent->content != NULL) {
 	cur->content = xmlStrdup(ent->content);
-    if (ent->orig != NULL)
+        if (cur->content == NULL)
+            goto error;
+    }
+    if (ent->orig != NULL) {
 	cur->orig = xmlStrdup(ent->orig);
-    if (ent->URI != NULL)
+        if (cur->orig == NULL)
+            goto error;
+    }
+    if (ent->URI != NULL) {
 	cur->URI = xmlStrdup(ent->URI);
+        if (cur->URI == NULL)
+            goto error;
+    }
     return(cur);
+
+error:
+    xmlFreeEntity(cur);
+    return(NULL);
 }
 
 /**
@@ -1017,53 +918,12 @@ xmlCopyEntity(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
  */
 xmlEntitiesTablePtr
 xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
-    return(xmlHashCopy(table, xmlCopyEntity));
+    return(xmlHashCopySafe(table, xmlCopyEntity, xmlFreeEntityWrapper));
 }
 #endif /* LIBXML_TREE_ENABLED */
 
 #ifdef LIBXML_OUTPUT_ENABLED
 
-/**
- * xmlDumpEntityContent:
- * @buf:  An XML buffer.
- * @content:  The entity content.
- *
- * This will dump the quoted string value, taking care of the special
- * treatment required by %
- */
-static void
-xmlDumpEntityContent(xmlBufferPtr buf, const xmlChar *content) {
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
-    if (xmlStrchr(content, '%')) {
-        const xmlChar * base, *cur;
-
-	xmlBufferCCat(buf, "\"");
-	base = cur = content;
-	while (*cur != 0) {
-	    if (*cur == '"') {
-		if (base != cur)
-		    xmlBufferAdd(buf, base, cur - base);
-		xmlBufferAdd(buf, BAD_CAST "&quot;", 6);
-		cur++;
-		base = cur;
-	    } else if (*cur == '%') {
-		if (base != cur)
-		    xmlBufferAdd(buf, base, cur - base);
-		xmlBufferAdd(buf, BAD_CAST "&#x25;", 6);
-		cur++;
-		base = cur;
-	    } else {
-		cur++;
-	    }
-	}
-	if (base != cur)
-	    xmlBufferAdd(buf, base, cur - base);
-	xmlBufferCCat(buf, "\"");
-    } else {
-        xmlBufferWriteQuotedString(buf, content);
-    }
-}
-
 /**
  * xmlDumpEntityDecl:
  * @buf:  An XML buffer.
@@ -1073,81 +933,15 @@ xmlDumpEntityContent(xmlBufferPtr buf, const xmlChar *content) {
  */
 void
 xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
-    if ((buf == NULL) || (ent == NULL)) return;
-    switch (ent->etype) {
-	case XML_INTERNAL_GENERAL_ENTITY:
-	    xmlBufferWriteChar(buf, "<!ENTITY ");
-	    xmlBufferWriteCHAR(buf, ent->name);
-	    xmlBufferWriteChar(buf, " ");
-	    if (ent->orig != NULL)
-		xmlBufferWriteQuotedString(buf, ent->orig);
-	    else
-		xmlDumpEntityContent(buf, ent->content);
-	    xmlBufferWriteChar(buf, ">\n");
-	    break;
-	case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
-	    xmlBufferWriteChar(buf, "<!ENTITY ");
-	    xmlBufferWriteCHAR(buf, ent->name);
-	    if (ent->ExternalID != NULL) {
-		 xmlBufferWriteChar(buf, " PUBLIC ");
-		 xmlBufferWriteQuotedString(buf, ent->ExternalID);
-		 xmlBufferWriteChar(buf, " ");
-		 xmlBufferWriteQuotedString(buf, ent->SystemID);
-	    } else {
-		 xmlBufferWriteChar(buf, " SYSTEM ");
-		 xmlBufferWriteQuotedString(buf, ent->SystemID);
-	    }
-	    xmlBufferWriteChar(buf, ">\n");
-	    break;
-	case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
-	    xmlBufferWriteChar(buf, "<!ENTITY ");
-	    xmlBufferWriteCHAR(buf, ent->name);
-	    if (ent->ExternalID != NULL) {
-		 xmlBufferWriteChar(buf, " PUBLIC ");
-		 xmlBufferWriteQuotedString(buf, ent->ExternalID);
-		 xmlBufferWriteChar(buf, " ");
-		 xmlBufferWriteQuotedString(buf, ent->SystemID);
-	    } else {
-		 xmlBufferWriteChar(buf, " SYSTEM ");
-		 xmlBufferWriteQuotedString(buf, ent->SystemID);
-	    }
-	    if (ent->content != NULL) { /* Should be true ! */
-		xmlBufferWriteChar(buf, " NDATA ");
-		if (ent->orig != NULL)
-		    xmlBufferWriteCHAR(buf, ent->orig);
-		else
-		    xmlBufferWriteCHAR(buf, ent->content);
-	    }
-	    xmlBufferWriteChar(buf, ">\n");
-	    break;
-	case XML_INTERNAL_PARAMETER_ENTITY:
-	    xmlBufferWriteChar(buf, "<!ENTITY % ");
-	    xmlBufferWriteCHAR(buf, ent->name);
-	    xmlBufferWriteChar(buf, " ");
-	    if (ent->orig == NULL)
-		xmlDumpEntityContent(buf, ent->content);
-	    else
-		xmlBufferWriteQuotedString(buf, ent->orig);
-	    xmlBufferWriteChar(buf, ">\n");
-	    break;
-	case XML_EXTERNAL_PARAMETER_ENTITY:
-	    xmlBufferWriteChar(buf, "<!ENTITY % ");
-	    xmlBufferWriteCHAR(buf, ent->name);
-	    if (ent->ExternalID != NULL) {
-		 xmlBufferWriteChar(buf, " PUBLIC ");
-		 xmlBufferWriteQuotedString(buf, ent->ExternalID);
-		 xmlBufferWriteChar(buf, " ");
-		 xmlBufferWriteQuotedString(buf, ent->SystemID);
-	    } else {
-		 xmlBufferWriteChar(buf, " SYSTEM ");
-		 xmlBufferWriteQuotedString(buf, ent->SystemID);
-	    }
-	    xmlBufferWriteChar(buf, ">\n");
-	    break;
-	default:
-	    xmlEntitiesErr(XML_DTD_UNKNOWN_ENTITY,
-		"xmlDumpEntitiesDecl: internal: unknown type entity type");
-    }
+    xmlSaveCtxtPtr save;
+
+    if ((buf == NULL) || (ent == NULL))
+        return;
+
+    save = xmlSaveToBuffer(buf, NULL, 0);
+    xmlSaveTree(save, (xmlNodePtr) ent);
+    if (xmlSaveFinish(save) != XML_ERR_OK)
+        xmlFree(xmlBufferDetach(buf));
 }
 
 /**
@@ -1158,9 +952,9 @@ xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
  * When using the hash table scan function, arguments need to be reversed
  */
 static void
-xmlDumpEntityDeclScan(void *ent, void *buf,
+xmlDumpEntityDeclScan(void *ent, void *save,
                       const xmlChar *name ATTRIBUTE_UNUSED) {
-    xmlDumpEntityDecl((xmlBufferPtr) buf, (xmlEntityPtr) ent);
+    xmlSaveTree(save, ent);
 }
 
 /**
@@ -1172,6 +966,14 @@ xmlDumpEntityDeclScan(void *ent, void *buf,
  */
 void
 xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
-    xmlHashScan(table, xmlDumpEntityDeclScan, buf);
+    xmlSaveCtxtPtr save;
+
+    if ((buf == NULL) || (table == NULL))
+        return;
+
+    save = xmlSaveToBuffer(buf, NULL, 0);
+    xmlHashScan(table, xmlDumpEntityDeclScan, save);
+    if (xmlSaveFinish(save) != XML_ERR_OK)
+        xmlFree(xmlBufferDetach(buf));
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
diff --git a/error.c b/error.c
index 5f42eadcc6d1e279b0b4c86a5e36ab03f9099b43..b678a0ee0048668f179a5713a165ee2a2319f256 100644
--- a/error.c
+++ b/error.c
@@ -11,46 +11,169 @@
 
 #include <string.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #include <libxml/parser.h>
 #include <libxml/xmlerror.h>
 #include <libxml/xmlmemory.h>
-#include <libxml/globals.h>
-
-void XMLCDECL xmlGenericErrorDefaultFunc	(void *ctx ATTRIBUTE_UNUSED,
-				 const char *msg,
-				 ...) LIBXML_ATTR_FORMAT(2,3);
-
-#define XML_GET_VAR_STR(msg, str) {				\
-    int       size, prev_size = -1;				\
-    int       chars;						\
-    char      *larger;						\
-    va_list   ap;						\
-								\
-    str = (char *) xmlMalloc(150);				\
-    if (str != NULL) {						\
-								\
-    size = 150;							\
-								\
-    while (size < 64000) {					\
-	va_start(ap, msg);					\
-	chars = vsnprintf(str, size, msg, ap);			\
-	va_end(ap);						\
-	if ((chars > -1) && (chars < size)) {			\
-	    if (prev_size == chars) {				\
-		break;						\
-	    } else {						\
-		prev_size = chars;				\
-	    }							\
-	}							\
-	if (chars > -1)						\
-	    size += chars + 1;					\
-	else							\
-	    size += 100;					\
-	if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
-	    break;						\
-	}							\
-	str = larger;						\
-    }}								\
+
+#include "private/error.h"
+#include "private/string.h"
+
+/************************************************************************
+ *									*
+ *			Error struct					*
+ *									*
+ ************************************************************************/
+
+static int
+xmlVSetError(xmlError *err,
+             void *ctxt, xmlNodePtr node,
+             int domain, int code, xmlErrorLevel level,
+             const char *file, int line,
+             const char *str1, const char *str2, const char *str3,
+             int int1, int col,
+             const char *fmt, va_list ap)
+{
+    char *message = NULL;
+    char *fileCopy = NULL;
+    char *str1Copy = NULL;
+    char *str2Copy = NULL;
+    char *str3Copy = NULL;
+
+    if (code == XML_ERR_OK) {
+        xmlResetError(err);
+        return(0);
+    }
+
+    /*
+     * Formatting the message
+     */
+    if (fmt == NULL) {
+        message = xmlMemStrdup("No error message provided");
+    } else {
+        xmlChar *tmp;
+        int res;
+
+        res = xmlStrVASPrintf(&tmp, MAX_ERR_MSG_SIZE, fmt, ap);
+        if (res < 0)
+            goto err_memory;
+        message = (char *) tmp;
+    }
+    if (message == NULL)
+        goto err_memory;
+
+    if (file != NULL) {
+        fileCopy = (char *) xmlStrdup((const xmlChar *) file);
+        if (fileCopy == NULL)
+            goto err_memory;
+    }
+    if (str1 != NULL) {
+        str1Copy = (char *) xmlStrdup((const xmlChar *) str1);
+        if (str1Copy == NULL)
+            goto err_memory;
+    }
+    if (str2 != NULL) {
+        str2Copy = (char *) xmlStrdup((const xmlChar *) str2);
+        if (str2Copy == NULL)
+            goto err_memory;
+    }
+    if (str3 != NULL) {
+        str3Copy = (char *) xmlStrdup((const xmlChar *) str3);
+        if (str3Copy == NULL)
+            goto err_memory;
+    }
+
+    xmlResetError(err);
+
+    err->domain = domain;
+    err->code = code;
+    err->message = message;
+    err->level = level;
+    err->file = fileCopy;
+    err->line = line;
+    err->str1 = str1Copy;
+    err->str2 = str2Copy;
+    err->str3 = str3Copy;
+    err->int1 = int1;
+    err->int2 = col;
+    err->node = node;
+    err->ctxt = ctxt;
+
+    return(0);
+
+err_memory:
+    xmlFree(message);
+    xmlFree(fileCopy);
+    xmlFree(str1Copy);
+    xmlFree(str2Copy);
+    xmlFree(str3Copy);
+    return(-1);
+}
+
+static int LIBXML_ATTR_FORMAT(14,15)
+xmlSetError(xmlError *err,
+            void *ctxt, xmlNodePtr node,
+            int domain, int code, xmlErrorLevel level,
+            const char *file, int line,
+            const char *str1, const char *str2, const char *str3,
+            int int1, int col,
+            const char *fmt, ...)
+{
+    va_list ap;
+    int res;
+
+    va_start(ap, fmt);
+    res = xmlVSetError(err, ctxt, node, domain, code, level, file, line,
+                       str1, str2, str3, int1, col, fmt, ap);
+    va_end(ap);
+
+    return(res);
+}
+
+static int
+xmlVUpdateError(xmlError *err,
+                void *ctxt, xmlNodePtr node,
+                int domain, int code, xmlErrorLevel level,
+                const char *file, int line,
+                const char *str1, const char *str2, const char *str3,
+                int int1, int col,
+                const char *fmt, va_list ap)
+{
+    int res;
+
+    /*
+     * Find first element parent.
+     */
+    if (node != NULL) {
+        int i;
+
+        for (i = 0; i < 10; i++) {
+            if ((node->type == XML_ELEMENT_NODE) ||
+                (node->parent == NULL))
+                break;
+            node = node->parent;
+        }
+    }
+
+    /*
+     * Get file and line from node.
+     */
+    if (node != NULL) {
+        if ((file == NULL) && (node->doc != NULL))
+            file = (const char *) node->doc->URL;
+
+        if (line == 0) {
+            if (node->type == XML_ELEMENT_NODE)
+                line = node->line;
+            if ((line == 0) || (line == 65535))
+                line = xmlGetLineNo(node);
+        }
+    }
+
+    res = xmlVSetError(err, ctxt, node, domain, code, level, file, line,
+                       str1, str2, str3, int1, col, fmt, ap);
+
+    return(res);
 }
 
 /************************************************************************
@@ -67,7 +190,7 @@ void XMLCDECL xmlGenericErrorDefaultFunc	(void *ctx ATTRIBUTE_UNUSED,
  *
  * Default handler for out of context error messages.
  */
-void XMLCDECL
+void
 xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
     va_list args;
 
@@ -83,6 +206,8 @@ xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
  * initGenericErrorDefaultFunc:
  * @handler:  the handler
  *
+ * DEPRECATED: Use xmlSetGenericErrorFunc.
+ *
  * Set or reset (if NULL) the default handler for generic errors
  * to the builtin error function.
  */
@@ -100,14 +225,21 @@ initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
  * @ctx:  the new error handling context
  * @handler:  the new handler function
  *
- * Function to reset the handler and the error context for out of
- * context error messages.
- * This simply means that @handler will be called for subsequent
- * error messages while not parsing nor validating. And @ctx will
- * be passed as first argument to @handler
- * One can simply force messages to be emitted to another FILE * than
- * stderr by setting @ctx to this file handle and @handler to NULL.
- * For multi-threaded applications, this must be set separately for each thread.
+ * DEPRECATED: See xmlSetStructuredErrorFunc for alternatives.
+ *
+ * Set the global "generic" handler and context for error messages.
+ * The generic error handler will only receive fragments of error
+ * messages which should be concatenated or printed to a stream.
+ *
+ * If handler is NULL, use the built-in default handler which prints
+ * to stderr.
+ *
+ * Since this is a global setting, it's a good idea to reset the
+ * error handler to its default value after collecting the errors
+ * you're interested in.
+ *
+ * For multi-threaded applications, this must be set separately for
+ * each thread.
  */
 void
 xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
@@ -123,12 +255,30 @@ xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
  * @ctx:  the new error handling context
  * @handler:  the new handler function
  *
- * Function to reset the handler and the error context for out of
- * context structured error messages.
- * This simply means that @handler will be called for subsequent
- * error messages while not parsing nor validating. And @ctx will
- * be passed as first argument to @handler
- * For multi-threaded applications, this must be set separately for each thread.
+ * DEPRECATED: Use a per-context error handler.
+ *
+ * It's recommended to use the per-context error handlers instead:
+ *
+ * - xmlCtxtSetErrorHandler (since 2.13.0)
+ * - xmlTextReaderSetStructuredErrorHandler
+ * - xmlXPathSetErrorHandler (since 2.13.0)
+ * - xmlXIncludeSetErrorHandler (since 2.13.0)
+ * - xmlSchemaSetParserStructuredErrors
+ * - xmlSchemaSetValidStructuredErrors
+ * - xmlRelaxNGSetParserStructuredErrors
+ * - xmlRelaxNGSetValidStructuredErrors
+ *
+ * Set the global "structured" handler and context for error messages.
+ * If handler is NULL, the error handler is deactivated.
+ *
+ * The structured error handler takes precedence over "generic"
+ * handlers, even per-context generic handlers.
+ *
+ * Since this is a global setting, it's a good idea to deactivate the
+ * error handler after collecting the errors you're interested in.
+ *
+ * For multi-threaded applications, this must be set separately for
+ * each thread.
  */
 void
 xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
@@ -146,6 +296,8 @@ xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
  * xmlParserPrintFileInfo:
  * @input:  an xmlParserInputPtr input
  *
+ * DEPRECATED: Use xmlFormatError.
+ *
  * Displays the associated file and line information for the current input
  */
 
@@ -163,7 +315,7 @@ xmlParserPrintFileInfo(xmlParserInputPtr input) {
 }
 
 /**
- * xmlParserPrintFileContext:
+ * xmlParserPrintFileContextInternal:
  * @input:  an xmlParserInputPtr input
  *
  * Displays current context within the input content for error tracking
@@ -172,7 +324,7 @@ xmlParserPrintFileInfo(xmlParserInputPtr input) {
 static void
 xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
 		xmlGenericErrorFunc channel, void *data ) {
-    const xmlChar *cur, *base;
+    const xmlChar *cur, *base, *start;
     unsigned int n, col;	/* GCC warns if signed, because compared with sizeof() */
     xmlChar  content[81]; /* space for 80 chars + line terminator */
     xmlChar *ctnt;
@@ -188,22 +340,35 @@ xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
     }
     n = 0;
     /* search backwards for beginning-of-line (to max buff size) */
-    while ((n++ < (sizeof(content)-1)) && (cur > base) &&
-	   (*(cur) != '\n') && (*(cur) != '\r'))
+    while ((n < sizeof(content) - 1) && (cur > base) &&
+	   (*cur != '\n') && (*cur != '\r')) {
         cur--;
-    if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
+        n++;
+    }
+    if ((n > 0) && ((*cur == '\n') || (*cur == '\r'))) {
+        cur++;
+    } else {
+        /* skip over continuation bytes */
+        while ((cur < input->cur) && ((*cur & 0xC0) == 0x80))
+            cur++;
+    }
     /* calculate the error position in terms of the current position */
     col = input->cur - cur;
     /* search forward for end-of-line (to max buff size) */
     n = 0;
-    ctnt = content;
+    start = cur;
     /* copy selected text to our buffer */
-    while ((*cur != 0) && (*(cur) != '\n') &&
-	   (*(cur) != '\r') && (n < sizeof(content)-1)) {
-		*ctnt++ = *cur++;
-	n++;
+    while ((*cur != 0) && (*(cur) != '\n') && (*(cur) != '\r')) {
+        int len = input->end - cur;
+        int c = xmlGetUTF8Char(cur, &len);
+
+        if ((c < 0) || (n + len > sizeof(content)-1))
+            break;
+        cur += len;
+	n += len;
     }
-    *ctnt = 0;
+    memcpy(content, start, n);
+    content[n] = 0;
     /* print out the selected text */
     channel(data ,"%s\n", content);
     /* create blank line with problem pointer */
@@ -224,6 +389,8 @@ xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
  * xmlParserPrintFileContext:
  * @input:  an xmlParserInputPtr input
  *
+ * DEPRECATED: Use xmlFormatError.
+ *
  * Displays current context within the input content for error tracking
  */
 void
@@ -233,35 +400,37 @@ xmlParserPrintFileContext(xmlParserInputPtr input) {
 }
 
 /**
- * xmlReportError:
- * @err: the error
- * @ctx: the parser context or NULL
- * @str: the formatted error message
+ * xmlFormatError:
+ * @err:  the error
+ * @channel:  callback
+ * @data:  user data for callback
+ *
+ * Report a formatted error to a printf-like callback.
  *
- * Report an error with its context, replace the 4 old error/warning
- * routines.
+ * This can result in a verbose multi-line report including additional
+ * information from the parser context.
+ *
+ * Available since 2.13.0.
  */
-static void
-xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
-               xmlGenericErrorFunc channel, void *data)
+void
+xmlFormatError(const xmlError *err, xmlGenericErrorFunc channel, void *data)
 {
-    char *file = NULL;
-    int line = 0;
-    int code = -1;
+    const char *message;
+    const char *file;
+    int line;
+    int code;
     int domain;
     const xmlChar *name = NULL;
     xmlNodePtr node;
     xmlErrorLevel level;
+    xmlParserCtxtPtr ctxt = NULL;
     xmlParserInputPtr input = NULL;
     xmlParserInputPtr cur = NULL;
 
-    if (err == NULL)
+    if ((err == NULL) || (channel == NULL))
         return;
 
-    if (channel == NULL) {
-	channel = xmlGenericError;
-	data = xmlGenericErrorContext;
-    }
+    message = err->message;
     file = err->file;
     line = err->line;
     code = err->code;
@@ -272,25 +441,30 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
     if (code == XML_ERR_OK)
         return;
 
-    if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
+    if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
+        (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
+	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
+	ctxt = err->ctxt;
+    }
+
+    if ((node != NULL) && (node->type == XML_ELEMENT_NODE) &&
+        (domain != XML_FROM_SCHEMASV))
         name = node->name;
 
     /*
      * Maintain the compatibility with the legacy error handling
      */
-    if (ctxt != NULL) {
+    if ((ctxt != NULL) && (ctxt->input != NULL)) {
         input = ctxt->input;
-        if ((input != NULL) && (input->filename == NULL) &&
+        if ((input->filename == NULL) &&
             (ctxt->inputNr > 1)) {
             cur = input;
             input = ctxt->inputTab[ctxt->inputNr - 2];
         }
-        if (input != NULL) {
-            if (input->filename)
-                channel(data, "%s:%d: ", input->filename, input->line);
-            else if ((line != 0) && (domain == XML_FROM_PARSER))
-                channel(data, "Entity: line %d: ", input->line);
-        }
+        if (input->filename)
+            channel(data, "%s:%d: ", input->filename, input->line);
+        else if ((line != 0) && (domain == XML_FROM_PARSER))
+            channel(data, "Entity: line %d: ", input->line);
     } else {
         if (file != NULL)
             channel(data, "%s:%d: ", file, line);
@@ -391,19 +565,35 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
             channel(data, "error : ");
             break;
     }
-    if (str != NULL) {
+    if (message != NULL) {
         int len;
-	len = xmlStrlen((const xmlChar *)str);
-	if ((len > 0) && (str[len - 1] != '\n'))
-	    channel(data, "%s\n", str);
+	len = xmlStrlen((const xmlChar *) message);
+	if ((len > 0) && (message[len - 1] != '\n'))
+	    channel(data, "%s\n", message);
 	else
-	    channel(data, "%s", str);
+	    channel(data, "%s", message);
     } else {
-        channel(data, "%s\n", "out of memory error");
+        channel(data, "%s\n", "No error message provided");
     }
 
     if (ctxt != NULL) {
+        if ((input != NULL) &&
+            ((input->buf == NULL) || (input->buf->encoder == NULL)) &&
+            (code == XML_ERR_INVALID_ENCODING) &&
+            (input->cur < input->end)) {
+            int i;
+
+            channel(data, "Bytes:");
+            for (i = 0; i < 4; i++) {
+                if (input->cur + i >= input->end)
+                    break;
+                channel(data, " 0x%02X", input->cur[i]);
+            }
+            channel(data, "\n");
+        }
+
         xmlParserPrintFileContextInternal(input, channel, data);
+
         if (cur != NULL) {
             if (cur->filename)
                 channel(data, "%s:%d: \n", cur->filename, cur->line);
@@ -428,12 +618,53 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
 }
 
 /**
- * __xmlRaiseError:
+ * xmlRaiseMemoryError:
+ * @schannel: the structured callback channel
+ * @channel: the old callback channel
+ * @data: the callback data
+ * @domain: the domain for the error
+ * @error: optional error struct to be filled
+ *
+ * Update the global and optional error structure, then forward the
+ * error to an error handler.
+ *
+ * This function doesn't make memory allocations which are likely
+ * to fail after an OOM error.
+ */
+void
+xmlRaiseMemoryError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel,
+                    void *data, int domain, xmlError *error)
+{
+    xmlError *lastError = &xmlLastError;
+
+    xmlResetLastError();
+    lastError->domain = domain;
+    lastError->code = XML_ERR_NO_MEMORY;
+    lastError->level = XML_ERR_FATAL;
+
+    if (error != NULL) {
+        xmlResetError(error);
+        error->domain = domain;
+        error->code = XML_ERR_NO_MEMORY;
+        error->level = XML_ERR_FATAL;
+    }
+
+    if (schannel != NULL) {
+        schannel(data, lastError);
+    } else if (xmlStructuredError != NULL) {
+        xmlStructuredError(xmlStructuredErrorContext, lastError);
+    } else if (channel != NULL) {
+        channel(data, "libxml2: out of memory\n");
+    }
+}
+
+/**
+ * xmlVRaiseError:
  * @schannel: the structured callback channel
  * @channel: the old callback channel
  * @data: the callback data
  * @ctx: the parser context or NULL
- * @ctx: the parser context or NULL
+ * @node: the current node or NULL
  * @domain: the domain for the error
  * @code: the code for the error
  * @level: the xmlErrorLevel for the error
@@ -445,245 +676,128 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
  * @int1: extra int info
  * @col: column number of the error or 0 if N/A
  * @msg:  the message to display/transmit
- * @...:  extra parameters for the message display
+ * @ap:  extra parameters for the message display
  *
  * Update the appropriate global or contextual error structure,
  * then forward the error message down the parser or generic
  * error callback handler
+ *
+ * Returns 0 on success, -1 if a memory allocation failed.
  */
-void XMLCDECL
-__xmlRaiseError(xmlStructuredErrorFunc schannel,
-              xmlGenericErrorFunc channel, void *data, void *ctx,
-              void *nod, int domain, int code, xmlErrorLevel level,
-              const char *file, int line, const char *str1,
-              const char *str2, const char *str3, int int1, int col,
-	      const char *msg, ...)
+int
+xmlVRaiseError(xmlStructuredErrorFunc schannel,
+               xmlGenericErrorFunc channel, void *data, void *ctx,
+               xmlNode *node, int domain, int code, xmlErrorLevel level,
+               const char *file, int line, const char *str1,
+               const char *str2, const char *str3, int int1, int col,
+               const char *msg, va_list ap)
 {
     xmlParserCtxtPtr ctxt = NULL;
-    xmlNodePtr node = (xmlNodePtr) nod;
-    char *str = NULL;
-    xmlParserInputPtr input = NULL;
-    xmlErrorPtr to = &xmlLastError;
-    xmlNodePtr baseptr = NULL;
+    /* xmlLastError is a macro retrieving the per-thread global. */
+    xmlErrorPtr lastError = &xmlLastError;
+    xmlErrorPtr to = lastError;
 
     if (code == XML_ERR_OK)
-        return;
+        return(0);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    if (code == XML_ERR_INTERNAL_ERROR) {
+        fprintf(stderr, "Unexpected error: %d\n", code);
+        abort();
+    }
+#endif
     if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
-        return;
+        return(0);
+
     if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
         (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
 	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
 	ctxt = (xmlParserCtxtPtr) ctx;
-	if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) &&
-	    (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
-	    (ctxt->sax->serror != NULL)) {
-	    schannel = ctxt->sax->serror;
-	    data = ctxt->userData;
-	}
-    }
-    /*
-     * Check if structured error handler set
-     */
-    if (schannel == NULL) {
-	schannel = xmlStructuredError;
-	/*
-	 * if user has defined handler, change data ptr to user's choice
-	 */
-	if (schannel != NULL)
-	    data = xmlStructuredErrorContext;
-    }
-    /*
-     * Formatting the message
-     */
-    if (msg == NULL) {
-        str = (char *) xmlStrdup(BAD_CAST "No error message provided");
-    } else {
-        XML_GET_VAR_STR(msg, str);
-    }
-
-    /*
-     * specific processing if a parser context is provided
-     */
-    if (ctxt != NULL) {
-        if (file == NULL) {
-            input = ctxt->input;
-            if ((input != NULL) && (input->filename == NULL) &&
-                (ctxt->inputNr > 1)) {
-                input = ctxt->inputTab[ctxt->inputNr - 2];
-            }
-            if (input != NULL) {
-                file = input->filename;
-                line = input->line;
-                col = input->col;
-            }
-        }
-        to = &ctxt->lastError;
-    } else if ((node != NULL) && (file == NULL)) {
-	int i;
 
-	if ((node->doc != NULL) && (node->doc->URL != NULL)) {
-	    baseptr = node;
-/*	    file = (const char *) node->doc->URL; */
-	}
-	for (i = 0;
-	     ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE));
-	     i++)
-	     node = node->parent;
-        if ((baseptr == NULL) && (node != NULL) &&
-	    (node->doc != NULL) && (node->doc->URL != NULL))
-	    baseptr = node;
-
-	if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
-	    line = node->line;
-	if ((line == 0) || (line == 65535))
-	    line = xmlGetLineNo(node);
+        if (ctxt != NULL)
+            to = &ctxt->lastError;
     }
 
-    /*
-     * Save the information about the error
-     */
-    xmlResetError(to);
-    to->domain = domain;
-    to->code = code;
-    to->message = str;
-    to->level = level;
-    if (file != NULL)
-        to->file = (char *) xmlStrdup((const xmlChar *) file);
-    else if (baseptr != NULL) {
-#ifdef LIBXML_XINCLUDE_ENABLED
-	/*
-	 * We check if the error is within an XInclude section and,
-	 * if so, attempt to print out the href of the XInclude instead
-	 * of the usual "base" (doc->URL) for the node (bug 152623).
-	 */
-        xmlNodePtr prev = baseptr;
-        char *href = NULL;
-	int inclcount = 0;
-	while (prev != NULL) {
-	    if (prev->prev == NULL)
-	        prev = prev->parent;
-	    else {
-	        prev = prev->prev;
-		if (prev->type == XML_XINCLUDE_START) {
-		    if (inclcount > 0) {
-                        --inclcount;
-                    } else {
-                        href = (char *) xmlGetProp(prev, BAD_CAST "href");
-                        if (href != NULL)
-		            break;
-                    }
-		} else if (prev->type == XML_XINCLUDE_END)
-		    inclcount++;
-	    }
-	}
-        if (href != NULL)
-            to->file = href;
-	else
-#endif
-	    to->file = (char *) xmlStrdup(baseptr->doc->URL);
-	if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
-	    to->file = (char *) xmlStrdup(node->doc->URL);
-	}
+    if (xmlVUpdateError(to, ctxt, node, domain, code, level, file, line,
+                        str1, str2, str3, int1, col, msg, ap))
+        return(-1);
+
+    if (to != lastError) {
+        if (xmlCopyError(to, lastError) < 0)
+            return(-1);
     }
-    to->line = line;
-    if (str1 != NULL)
-        to->str1 = (char *) xmlStrdup((const xmlChar *) str1);
-    if (str2 != NULL)
-        to->str2 = (char *) xmlStrdup((const xmlChar *) str2);
-    if (str3 != NULL)
-        to->str3 = (char *) xmlStrdup((const xmlChar *) str3);
-    to->int1 = int1;
-    to->int2 = col;
-    to->node = node;
-    to->ctxt = ctx;
-
-    if (to != &xmlLastError)
-        xmlCopyError(to,&xmlLastError);
 
     if (schannel != NULL) {
 	schannel(data, to);
-	return;
-    }
-
-    /*
-     * Find the callback channel if channel param is NULL
-     */
-    if ((ctxt != NULL) && (channel == NULL) &&
-        (xmlStructuredError == NULL) && (ctxt->sax != NULL)) {
-        if (level == XML_ERR_WARNING)
-	    channel = ctxt->sax->warning;
+    } else if (xmlStructuredError != NULL) {
+        xmlStructuredError(xmlStructuredErrorContext, to);
+    } else if (channel != NULL) {
+        /* Don't invoke legacy error handlers */
+        if ((channel == xmlGenericErrorDefaultFunc) ||
+            (channel == xmlParserError) ||
+            (channel == xmlParserWarning) ||
+            (channel == xmlParserValidityError) ||
+            (channel == xmlParserValidityWarning))
+            xmlFormatError(to, xmlGenericError, xmlGenericErrorContext);
         else
-	    channel = ctxt->sax->error;
-	data = ctxt->userData;
-    } else if (channel == NULL) {
-	channel = xmlGenericError;
-	if (ctxt != NULL) {
-	    data = ctxt;
-	} else {
-	    data = xmlGenericErrorContext;
-	}
+	    channel(data, "%s", to->message);
     }
-    if (channel == NULL)
-        return;
 
-    if ((channel == xmlParserError) ||
-        (channel == xmlParserWarning) ||
-	(channel == xmlParserValidityError) ||
-	(channel == xmlParserValidityWarning))
-	xmlReportError(to, ctxt, str, NULL, NULL);
-    else if (((void(*)(void)) channel == (void(*)(void)) fprintf) ||
-             (channel == xmlGenericErrorDefaultFunc))
-	xmlReportError(to, ctxt, str, channel, data);
-    else
-	channel(data, "%s", str);
+    return(0);
 }
 
 /**
- * __xmlSimpleError:
- * @domain: where the error comes from
- * @code: the error code
- * @node: the context node
- * @extra:  extra information
- *
- * Handle an out of memory condition
- */
-void
-__xmlSimpleError(int domain, int code, xmlNodePtr node,
-                 const char *msg, const char *extra)
-{
-
-    if (code == XML_ERR_NO_MEMORY) {
-	if (extra)
-	    __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
-			    XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
-			    NULL, NULL, 0, 0,
-			    "Memory allocation failed : %s\n", extra);
-	else
-	    __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
-			    XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
-			    NULL, NULL, 0, 0, "Memory allocation failed\n");
-    } else {
-	__xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
-			code, XML_ERR_ERROR, NULL, 0, extra,
-			NULL, NULL, 0, 0, msg, extra);
-    }
-}
-/**
- * xmlParserError:
- * @ctx:  an XML parser context
+ * __xmlRaiseError:
+ * @schannel: the structured callback channel
+ * @channel: the old callback channel
+ * @data: the callback data
+ * @ctx: the parser context or NULL
+ * @nod: the node or NULL
+ * @domain: the domain for the error
+ * @code: the code for the error
+ * @level: the xmlErrorLevel for the error
+ * @file: the file source of the error (or NULL)
+ * @line: the line of the error or 0 if N/A
+ * @str1: extra string info
+ * @str2: extra string info
+ * @str3: extra string info
+ * @int1: extra int info
+ * @col: column number of the error or 0 if N/A
  * @msg:  the message to display/transmit
  * @...:  extra parameters for the message display
  *
- * Display and format an error messages, gives file, line, position and
- * extra parameters.
+ * Update the appropriate global or contextual error structure,
+ * then forward the error message down the parser or generic
+ * error callback handler
+ *
+ * Returns 0 on success, -1 if a memory allocation failed.
  */
-void XMLCDECL
-xmlParserError(void *ctx, const char *msg, ...)
+int
+__xmlRaiseError(xmlStructuredErrorFunc schannel,
+                xmlGenericErrorFunc channel, void *data, void *ctx,
+                xmlNode *node, int domain, int code, xmlErrorLevel level,
+                const char *file, int line, const char *str1,
+                const char *str2, const char *str3, int int1, int col,
+                const char *msg, ...)
 {
+    va_list ap;
+    int res;
+
+    va_start(ap, msg);
+    res = xmlVRaiseError(schannel, channel, data, ctx, node, domain, code,
+                         level, file, line, str1, str2, str3, int1, col, msg,
+                         ap);
+    va_end(ap);
+
+    return(res);
+}
+
+static void
+xmlVFormatLegacyError(void *ctx, const char *level,
+                      const char *fmt, va_list ap) {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlParserInputPtr input = NULL;
     xmlParserInputPtr cur = NULL;
-    char * str;
+    xmlChar *str = NULL;
 
     if (ctxt != NULL) {
 	input = ctxt->input;
@@ -695,11 +809,13 @@ xmlParserError(void *ctx, const char *msg, ...)
 	xmlParserPrintFileInfo(input);
     }
 
-    xmlGenericError(xmlGenericErrorContext, "error: ");
-    XML_GET_VAR_STR(msg, str);
-    xmlGenericError(xmlGenericErrorContext, "%s", str);
-    if (str != NULL)
+    xmlGenericError(xmlGenericErrorContext, "%s: ", level);
+
+    xmlStrVASPrintf(&str, MAX_ERR_MSG_SIZE, fmt, ap);
+    if (str != NULL) {
+        xmlGenericError(xmlGenericErrorContext, "%s", (char *) str);
 	xmlFree(str);
+    }
 
     if (ctxt != NULL) {
 	xmlParserPrintFileContext(input);
@@ -712,54 +828,43 @@ xmlParserError(void *ctx, const char *msg, ...)
 }
 
 /**
- * xmlParserWarning:
+ * xmlParserError:
  * @ctx:  an XML parser context
  * @msg:  the message to display/transmit
  * @...:  extra parameters for the message display
  *
- * Display and format a warning messages, gives file, line, position and
+ * Display and format an error messages, gives file, line, position and
  * extra parameters.
  */
-void XMLCDECL
-xmlParserWarning(void *ctx, const char *msg, ...)
+void
+xmlParserError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlParserInputPtr input = NULL;
-    xmlParserInputPtr cur = NULL;
-    char * str;
+    va_list ap;
 
-    if (ctxt != NULL) {
-	input = ctxt->input;
-	if ((input != NULL) && (input->filename == NULL) &&
-	    (ctxt->inputNr > 1)) {
-	    cur = input;
-	    input = ctxt->inputTab[ctxt->inputNr - 2];
-	}
-	xmlParserPrintFileInfo(input);
-    }
+    va_start(ap, msg);
+    xmlVFormatLegacyError(ctx, "error", msg, ap);
+    va_end(ap);
+}
 
-    xmlGenericError(xmlGenericErrorContext, "warning: ");
-    XML_GET_VAR_STR(msg, str);
-    xmlGenericError(xmlGenericErrorContext, "%s", str);
-    if (str != NULL)
-	xmlFree(str);
+/**
+ * xmlParserWarning:
+ * @ctx:  an XML parser context
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ *
+ * Display and format a warning messages, gives file, line, position and
+ * extra parameters.
+ */
+void
+xmlParserWarning(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
+{
+    va_list ap;
 
-    if (ctxt != NULL) {
-	xmlParserPrintFileContext(input);
-	if (cur != NULL) {
-	    xmlParserPrintFileInfo(cur);
-	    xmlGenericError(xmlGenericErrorContext, "\n");
-	    xmlParserPrintFileContext(cur);
-	}
-    }
+    va_start(ap, msg);
+    xmlVFormatLegacyError(ctx, "warning", msg, ap);
+    va_end(ap);
 }
 
-/************************************************************************
- *									*
- *			Handling of validation errors			*
- *									*
- ************************************************************************/
-
 /**
  * xmlParserValidityError:
  * @ctx:  an XML parser context
@@ -769,39 +874,14 @@ xmlParserWarning(void *ctx, const char *msg, ...)
  * Display and format an validity error messages, gives file,
  * line, position and extra parameters.
  */
-void XMLCDECL
-xmlParserValidityError(void *ctx, const char *msg, ...)
+void
+xmlParserValidityError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlParserInputPtr input = NULL;
-    char * str;
-    int len = xmlStrlen((const xmlChar *) msg);
-    static int had_info = 0;
-
-    if ((len > 1) && (msg[len - 2] != ':')) {
-	if (ctxt != NULL) {
-	    input = ctxt->input;
-	    if ((input->filename == NULL) && (ctxt->inputNr > 1))
-		input = ctxt->inputTab[ctxt->inputNr - 2];
-
-	    if (had_info == 0) {
-		xmlParserPrintFileInfo(input);
-	    }
-	}
-	xmlGenericError(xmlGenericErrorContext, "validity error: ");
-	had_info = 0;
-    } else {
-	had_info = 1;
-    }
-
-    XML_GET_VAR_STR(msg, str);
-    xmlGenericError(xmlGenericErrorContext, "%s", str);
-    if (str != NULL)
-	xmlFree(str);
+    va_list ap;
 
-    if ((ctxt != NULL) && (input != NULL)) {
-	xmlParserPrintFileContext(input);
-    }
+    va_start(ap, msg);
+    xmlVFormatLegacyError(ctx, "validity error", msg, ap);
+    va_end(ap);
 }
 
 /**
@@ -813,31 +893,14 @@ xmlParserValidityError(void *ctx, const char *msg, ...)
  * Display and format a validity warning messages, gives file, line,
  * position and extra parameters.
  */
-void XMLCDECL
-xmlParserValidityWarning(void *ctx, const char *msg, ...)
+void
+xmlParserValidityWarning(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlParserInputPtr input = NULL;
-    char * str;
-    int len = xmlStrlen((const xmlChar *) msg);
+    va_list ap;
 
-    if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) {
-	input = ctxt->input;
-	if ((input->filename == NULL) && (ctxt->inputNr > 1))
-	    input = ctxt->inputTab[ctxt->inputNr - 2];
-
-	xmlParserPrintFileInfo(input);
-    }
-
-    xmlGenericError(xmlGenericErrorContext, "validity warning: ");
-    XML_GET_VAR_STR(msg, str);
-    xmlGenericError(xmlGenericErrorContext, "%s", str);
-    if (str != NULL)
-	xmlFree(str);
-
-    if (ctxt != NULL) {
-	xmlParserPrintFileContext(input);
-    }
+    va_start(ap, msg);
+    xmlVFormatLegacyError(ctx, "validity warning", msg, ap);
+    va_end(ap);
 }
 
 
@@ -853,9 +916,9 @@ xmlParserValidityWarning(void *ctx, const char *msg, ...)
  * Get the last global error registered. This is per thread if compiled
  * with thread support.
  *
- * Returns NULL if no error occurred or a pointer to the error
+ * Returns a pointer to the error
  */
-xmlErrorPtr
+const xmlError *
 xmlGetLastError(void)
 {
     if (xmlLastError.code == XML_ERR_OK)
@@ -912,7 +975,7 @@ xmlResetLastError(void)
  *
  * Returns NULL if no error occurred or a pointer to the error
  */
-xmlErrorPtr
+const xmlError *
 xmlCtxtGetLastError(void *ctx)
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
@@ -954,43 +1017,352 @@ xmlCtxtResetLastError(void *ctx)
  * Returns 0 in case of success and -1 in case of error.
  */
 int
-xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) {
-    char *message, *file, *str1, *str2, *str3;
+xmlCopyError(const xmlError *from, xmlErrorPtr to) {
+    const char *fmt = NULL;
 
     if ((from == NULL) || (to == NULL))
         return(-1);
 
-    message = (char *) xmlStrdup((xmlChar *) from->message);
-    file = (char *) xmlStrdup ((xmlChar *) from->file);
-    str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
-    str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
-    str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
-
-    if (to->message != NULL)
-        xmlFree(to->message);
-    if (to->file != NULL)
-        xmlFree(to->file);
-    if (to->str1 != NULL)
-        xmlFree(to->str1);
-    if (to->str2 != NULL)
-        xmlFree(to->str2);
-    if (to->str3 != NULL)
-        xmlFree(to->str3);
-    to->domain = from->domain;
-    to->code = from->code;
-    to->level = from->level;
-    to->line = from->line;
-    to->node = from->node;
-    to->int1 = from->int1;
-    to->int2 = from->int2;
-    to->node = from->node;
-    to->ctxt = from->ctxt;
-    to->message = message;
-    to->file = file;
-    to->str1 = str1;
-    to->str2 = str2;
-    to->str3 = str3;
-
-    return 0;
+    if (from->message != NULL)
+        fmt = "%s";
+
+    return(xmlSetError(to, from->ctxt, from->node,
+                       from->domain, from->code, from->level,
+                       from->file, from->line,
+                       from->str1, from->str2, from->str3,
+                       from->int1, from->int2,
+                       fmt, from->message));
 }
 
+/**
+ * xmlErrString:
+ * @code:  an xmlParserErrors code
+ *
+ * Returns an error message for a code.
+ */
+const char *
+xmlErrString(xmlParserErrors code) {
+    const char *errmsg;
+
+    switch (code) {
+        case XML_ERR_INVALID_HEX_CHARREF:
+            errmsg = "CharRef: invalid hexadecimal value";
+            break;
+        case XML_ERR_INVALID_DEC_CHARREF:
+            errmsg = "CharRef: invalid decimal value";
+            break;
+        case XML_ERR_INVALID_CHARREF:
+            errmsg = "CharRef: invalid value";
+            break;
+        case XML_ERR_INTERNAL_ERROR:
+            errmsg = "internal error";
+            break;
+        case XML_ERR_PEREF_AT_EOF:
+            errmsg = "PEReference at end of document";
+            break;
+        case XML_ERR_PEREF_IN_PROLOG:
+            errmsg = "PEReference in prolog";
+            break;
+        case XML_ERR_PEREF_IN_EPILOG:
+            errmsg = "PEReference in epilog";
+            break;
+        case XML_ERR_PEREF_NO_NAME:
+            errmsg = "PEReference: no name";
+            break;
+        case XML_ERR_PEREF_SEMICOL_MISSING:
+            errmsg = "PEReference: expecting ';'";
+            break;
+        case XML_ERR_ENTITY_LOOP:
+            errmsg = "Detected an entity reference loop";
+            break;
+        case XML_ERR_ENTITY_NOT_STARTED:
+            errmsg = "EntityValue: \" or ' expected";
+            break;
+        case XML_ERR_ENTITY_PE_INTERNAL:
+            errmsg = "PEReferences forbidden in internal subset";
+            break;
+        case XML_ERR_ENTITY_NOT_FINISHED:
+            errmsg = "EntityValue: \" or ' expected";
+            break;
+        case XML_ERR_ATTRIBUTE_NOT_STARTED:
+            errmsg = "AttValue: \" or ' expected";
+            break;
+        case XML_ERR_LT_IN_ATTRIBUTE:
+            errmsg = "Unescaped '<' not allowed in attributes values";
+            break;
+        case XML_ERR_LITERAL_NOT_STARTED:
+            errmsg = "SystemLiteral \" or ' expected";
+            break;
+        case XML_ERR_LITERAL_NOT_FINISHED:
+            errmsg = "Unfinished System or Public ID \" or ' expected";
+            break;
+        case XML_ERR_MISPLACED_CDATA_END:
+            errmsg = "Sequence ']]>' not allowed in content";
+            break;
+        case XML_ERR_URI_REQUIRED:
+            errmsg = "SYSTEM or PUBLIC, the URI is missing";
+            break;
+        case XML_ERR_PUBID_REQUIRED:
+            errmsg = "PUBLIC, the Public Identifier is missing";
+            break;
+        case XML_ERR_HYPHEN_IN_COMMENT:
+            errmsg = "Comment must not contain '--' (double-hyphen)";
+            break;
+        case XML_ERR_PI_NOT_STARTED:
+            errmsg = "xmlParsePI : no target name";
+            break;
+        case XML_ERR_RESERVED_XML_NAME:
+            errmsg = "Invalid PI name";
+            break;
+        case XML_ERR_NOTATION_NOT_STARTED:
+            errmsg = "NOTATION: Name expected here";
+            break;
+        case XML_ERR_NOTATION_NOT_FINISHED:
+            errmsg = "'>' required to close NOTATION declaration";
+            break;
+        case XML_ERR_VALUE_REQUIRED:
+            errmsg = "Entity value required";
+            break;
+        case XML_ERR_URI_FRAGMENT:
+            errmsg = "Fragment not allowed";
+            break;
+        case XML_ERR_ATTLIST_NOT_STARTED:
+            errmsg = "'(' required to start ATTLIST enumeration";
+            break;
+        case XML_ERR_NMTOKEN_REQUIRED:
+            errmsg = "NmToken expected in ATTLIST enumeration";
+            break;
+        case XML_ERR_ATTLIST_NOT_FINISHED:
+            errmsg = "')' required to finish ATTLIST enumeration";
+            break;
+        case XML_ERR_MIXED_NOT_STARTED:
+            errmsg = "MixedContentDecl : '|' or ')*' expected";
+            break;
+        case XML_ERR_PCDATA_REQUIRED:
+            errmsg = "MixedContentDecl : '#PCDATA' expected";
+            break;
+        case XML_ERR_ELEMCONTENT_NOT_STARTED:
+            errmsg = "ContentDecl : Name or '(' expected";
+            break;
+        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
+            errmsg = "ContentDecl : ',' '|' or ')' expected";
+            break;
+        case XML_ERR_PEREF_IN_INT_SUBSET:
+            errmsg =
+                "PEReference: forbidden within markup decl in internal subset";
+            break;
+        case XML_ERR_GT_REQUIRED:
+            errmsg = "expected '>'";
+            break;
+        case XML_ERR_CONDSEC_INVALID:
+            errmsg = "XML conditional section '[' expected";
+            break;
+        case XML_ERR_INT_SUBSET_NOT_FINISHED:
+            errmsg = "Content error in the internal subset";
+            break;
+        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
+            errmsg = "Content error in the external subset";
+            break;
+        case XML_ERR_CONDSEC_INVALID_KEYWORD:
+            errmsg =
+                "conditional section INCLUDE or IGNORE keyword expected";
+            break;
+        case XML_ERR_CONDSEC_NOT_FINISHED:
+            errmsg = "XML conditional section not closed";
+            break;
+        case XML_ERR_XMLDECL_NOT_STARTED:
+            errmsg = "Text declaration '<?xml' required";
+            break;
+        case XML_ERR_XMLDECL_NOT_FINISHED:
+            errmsg = "parsing XML declaration: '?>' expected";
+            break;
+        case XML_ERR_EXT_ENTITY_STANDALONE:
+            errmsg = "external parsed entities cannot be standalone";
+            break;
+        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
+            errmsg = "EntityRef: expecting ';'";
+            break;
+        case XML_ERR_DOCTYPE_NOT_FINISHED:
+            errmsg = "DOCTYPE improperly terminated";
+            break;
+        case XML_ERR_LTSLASH_REQUIRED:
+            errmsg = "EndTag: '</' not found";
+            break;
+        case XML_ERR_EQUAL_REQUIRED:
+            errmsg = "expected '='";
+            break;
+        case XML_ERR_STRING_NOT_CLOSED:
+            errmsg = "String not closed expecting \" or '";
+            break;
+        case XML_ERR_STRING_NOT_STARTED:
+            errmsg = "String not started expecting ' or \"";
+            break;
+        case XML_ERR_ENCODING_NAME:
+            errmsg = "Invalid XML encoding name";
+            break;
+        case XML_ERR_STANDALONE_VALUE:
+            errmsg = "standalone accepts only 'yes' or 'no'";
+            break;
+        case XML_ERR_DOCUMENT_EMPTY:
+            errmsg = "Document is empty";
+            break;
+        case XML_ERR_DOCUMENT_END:
+            errmsg = "Extra content at the end of the document";
+            break;
+        case XML_ERR_NOT_WELL_BALANCED:
+            errmsg = "chunk is not well balanced";
+            break;
+        case XML_ERR_EXTRA_CONTENT:
+            errmsg = "extra content at the end of well balanced chunk";
+            break;
+        case XML_ERR_VERSION_MISSING:
+            errmsg = "Malformed declaration expecting version";
+            break;
+        case XML_ERR_NAME_TOO_LONG:
+            errmsg = "Name too long";
+            break;
+        case XML_ERR_INVALID_ENCODING:
+            errmsg = "Invalid bytes in character encoding";
+            break;
+        case XML_ERR_RESOURCE_LIMIT:
+            errmsg = "Resource limit exceeded";
+            break;
+        case XML_ERR_ARGUMENT:
+            errmsg = "Invalid argument";
+            break;
+        case XML_ERR_SYSTEM:
+            errmsg = "Out of system resources";
+            break;
+        case XML_ERR_REDECL_PREDEF_ENTITY:
+            errmsg = "Invalid redeclaration of predefined entity";
+            break;
+        case XML_ERR_UNSUPPORTED_ENCODING:
+            errmsg = "Unsupported encoding";
+            break;
+        case XML_ERR_INVALID_CHAR:
+            errmsg = "Invalid character";
+            break;
+
+        case XML_IO_UNKNOWN:
+            errmsg = "Unknown IO error"; break;
+        case XML_IO_EACCES:
+            errmsg = "Permission denied"; break;
+        case XML_IO_EAGAIN:
+            errmsg = "Resource temporarily unavailable"; break;
+        case XML_IO_EBADF:
+            errmsg = "Bad file descriptor"; break;
+        case XML_IO_EBADMSG:
+            errmsg = "Bad message"; break;
+        case XML_IO_EBUSY:
+            errmsg = "Resource busy"; break;
+        case XML_IO_ECANCELED:
+            errmsg = "Operation canceled"; break;
+        case XML_IO_ECHILD:
+            errmsg = "No child processes"; break;
+        case XML_IO_EDEADLK:
+            errmsg = "Resource deadlock avoided"; break;
+        case XML_IO_EDOM:
+            errmsg = "Domain error"; break;
+        case XML_IO_EEXIST:
+            errmsg = "File exists"; break;
+        case XML_IO_EFAULT:
+            errmsg = "Bad address"; break;
+        case XML_IO_EFBIG:
+            errmsg = "File too large"; break;
+        case XML_IO_EINPROGRESS:
+            errmsg = "Operation in progress"; break;
+        case XML_IO_EINTR:
+            errmsg = "Interrupted function call"; break;
+        case XML_IO_EINVAL:
+            errmsg = "Invalid argument"; break;
+        case XML_IO_EIO:
+            errmsg = "Input/output error"; break;
+        case XML_IO_EISDIR:
+            errmsg = "Is a directory"; break;
+        case XML_IO_EMFILE:
+            errmsg = "Too many open files"; break;
+        case XML_IO_EMLINK:
+            errmsg = "Too many links"; break;
+        case XML_IO_EMSGSIZE:
+            errmsg = "Inappropriate message buffer length"; break;
+        case XML_IO_ENAMETOOLONG:
+            errmsg = "Filename too long"; break;
+        case XML_IO_ENFILE:
+            errmsg = "Too many open files in system"; break;
+        case XML_IO_ENODEV:
+            errmsg = "No such device"; break;
+        case XML_IO_ENOENT:
+            errmsg = "No such file or directory"; break;
+        case XML_IO_ENOEXEC:
+            errmsg = "Exec format error"; break;
+        case XML_IO_ENOLCK:
+            errmsg = "No locks available"; break;
+        case XML_IO_ENOMEM:
+            errmsg = "Not enough space"; break;
+        case XML_IO_ENOSPC:
+            errmsg = "No space left on device"; break;
+        case XML_IO_ENOSYS:
+            errmsg = "Function not implemented"; break;
+        case XML_IO_ENOTDIR:
+            errmsg = "Not a directory"; break;
+        case XML_IO_ENOTEMPTY:
+            errmsg = "Directory not empty"; break;
+        case XML_IO_ENOTSUP:
+            errmsg = "Not supported"; break;
+        case XML_IO_ENOTTY:
+            errmsg = "Inappropriate I/O control operation"; break;
+        case XML_IO_ENXIO:
+            errmsg = "No such device or address"; break;
+        case XML_IO_EPERM:
+            errmsg = "Operation not permitted"; break;
+        case XML_IO_EPIPE:
+            errmsg = "Broken pipe"; break;
+        case XML_IO_ERANGE:
+            errmsg = "Result too large"; break;
+        case XML_IO_EROFS:
+            errmsg = "Read-only file system"; break;
+        case XML_IO_ESPIPE:
+            errmsg = "Invalid seek"; break;
+        case XML_IO_ESRCH:
+            errmsg = "No such process"; break;
+        case XML_IO_ETIMEDOUT:
+            errmsg = "Operation timed out"; break;
+        case XML_IO_EXDEV:
+            errmsg = "Improper link"; break;
+        case XML_IO_NETWORK_ATTEMPT:
+            errmsg = "Attempt to load network entity"; break;
+        case XML_IO_ENCODER:
+            errmsg = "encoder error"; break;
+        case XML_IO_FLUSH:
+            errmsg = "flush error"; break;
+        case XML_IO_WRITE:
+            errmsg = "write error"; break;
+        case XML_IO_NO_INPUT:
+            errmsg = "no input"; break;
+        case XML_IO_BUFFER_FULL:
+            errmsg = "buffer full"; break;
+        case XML_IO_LOAD_ERROR:
+            errmsg = "loading error"; break;
+        case XML_IO_ENOTSOCK:
+            errmsg = "not a socket"; break;
+        case XML_IO_EISCONN:
+            errmsg = "already connected"; break;
+        case XML_IO_ECONNREFUSED:
+            errmsg = "connection refused"; break;
+        case XML_IO_ENETUNREACH:
+            errmsg = "unreachable network"; break;
+        case XML_IO_EADDRINUSE:
+            errmsg = "address in use"; break;
+        case XML_IO_EALREADY:
+            errmsg = "already in use"; break;
+        case XML_IO_EAFNOSUPPORT:
+            errmsg = "unknown address family"; break;
+        case XML_IO_UNSUPPORTED_PROTOCOL:
+            errmsg = "unsupported protocol"; break;
+
+        default:
+            errmsg = "Unregistered error message";
+    }
+
+    return(errmsg);
+}
diff --git a/globals.c b/globals.c
index a15ac3058ba7f3202fed3989cb723a48d10aac16..ff8fb4f3b0a3c60f8d8b7535d03f7d2424b6b77b 100644
--- a/globals.c
+++ b/globals.c
@@ -2,9 +2,6 @@
  * globals.c: definition and handling of the set of global variables
  *            of the library
  *
- * The bottom of this file is automatically generated by build_glob.py
- * based on the description file global.data
- *
  * See Copyright for the status of this software.
  *
  * Gary Pennington <Gary.Pennington@uk.sun.com>
@@ -14,42 +11,155 @@
 #define IN_LIBXML
 #include "libxml.h"
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#define XML_GLOBALS_NO_REDEFINITION
 #include <libxml/globals.h>
+#include <libxml/xmlerror.h>
 #include <libxml/xmlmemory.h>
+#include <libxml/xmlIO.h>
+#include <libxml/parser.h>
 #include <libxml/threads.h>
+#include <libxml/tree.h>
+#include <libxml/SAX.h>
+#include <libxml/SAX2.h>
 
-/* #define DEBUG_GLOBALS */
+#include "private/dict.h"
+#include "private/error.h"
+#include "private/globals.h"
+#include "private/threads.h"
+#include "private/tree.h"
+
+/*
+ * Thread-local storage emulation.
+ *
+ * This works by replacing a global variable
+ *
+ *     extern xmlError xmlLastError;
+ *
+ * with a macro that calls a function returning a pointer to the global in
+ * thread-local storage:
+ *
+ *     xmlError *__xmlLastError(void);
+ *     #define xmlError (*__xmlLastError());
+ *
+ * The code can operate in a multitude of ways depending on the environment.
+ * First we support POSIX and Windows threads. Then we support both thread-local
+ * storage provided by the compiler and older methods like thread-specific data
+ * (pthreads) or TlsAlloc (Windows).
+ *
+ * To clean up thread-local storage, we use thread-specific data on POSIX.
+ * On Windows, we either use DllMain when compiling a DLL or a registered wait
+ * function for static builds.
+ */
 
 /*
  * Helpful Macro
  */
 #ifdef LIBXML_THREAD_ENABLED
-#define IS_MAIN_THREAD (xmlIsMainThread())
+#define IS_MAIN_THREAD (xmlIsMainThreadInternal())
 #else
 #define IS_MAIN_THREAD 1
 #endif
 
+#define XML_DECLARE_MEMBER(name, type, attrs) \
+  type gs_##name;
+
+struct _xmlGlobalState {
+    int initialized;
+
+#if defined(HAVE_WIN32_THREADS) && \
+    defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
+    void *threadHandle;
+    void *waitHandle;
+#endif
+
+#ifdef LIBXML_THREAD_ENABLED
+    unsigned localRngState[2];
+#endif
+
+#define XML_OP XML_DECLARE_MEMBER
+XML_GLOBALS_ALLOC
+XML_GLOBALS_ERROR
+XML_GLOBALS_IO
+XML_GLOBALS_PARSER
+XML_GLOBALS_TREE
+#undef XML_OP
+};
+
+static int parserInitialized;
+
 /*
  * Mutex to protect "ForNewThreads" variables
  */
-static xmlMutexPtr xmlThrDefMutex = NULL;
+static xmlMutex xmlThrDefMutex;
 
-/**
- * xmlInitGlobals:
- *
- * DEPRECATED: This function will be made private. Call xmlInitParser to
- * initialize the library.
+#ifdef LIBXML_THREAD_ENABLED
+
+/*
+ * On Darwin, thread-local storage destructors seem to be run before
+ * pthread thread-specific data destructors. This causes ASan to
+ * report a use-after-free.
  *
- * Additional initialisation for multi-threading
+ * On Windows, we can't use TLS in static builds. The RegisterWait
+ * callback would run after TLS was deallocated.
  */
-void xmlInitGlobals(void)
-{
-    if (xmlThrDefMutex == NULL)
-        xmlThrDefMutex = xmlNewMutex();
-}
+#if defined(XML_THREAD_LOCAL) && \
+    !defined(__APPLE__) && \
+    (!defined(HAVE_WIN32_THREADS) || \
+     !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+#define USE_TLS
+#endif
+
+#ifdef USE_TLS
+static XML_THREAD_LOCAL xmlGlobalState globalState;
+#endif
+
+#ifdef HAVE_POSIX_THREADS
+
+/*
+ * Weak symbol hack, see threads.c
+ */
+#if defined(__GNUC__) && \
+    defined(__GLIBC__) && \
+    __GLIBC__ * 100 + __GLIBC_MINOR__ < 234
+
+#pragma weak pthread_getspecific
+#pragma weak pthread_setspecific
+#pragma weak pthread_key_create
+#pragma weak pthread_key_delete
+#pragma weak pthread_equal
+#pragma weak pthread_self
+
+#define XML_PTHREAD_WEAK
+
+static int libxml_is_threaded = -1;
+
+#endif
+
+/*
+ * On POSIX, we need thread-specific data even with thread-local storage
+ * to destroy indirect references from global state (xmlLastError) at
+ * thread exit.
+ */
+static pthread_key_t globalkey;
+static pthread_t mainthread;
+
+#elif defined HAVE_WIN32_THREADS
+
+#ifndef USE_TLS
+static DWORD globalkey = TLS_OUT_OF_INDEXES;
+#endif
+static DWORD mainthread;
+
+#endif /* HAVE_WIN32_THREADS */
+
+static void
+xmlFreeGlobalState(void *state);
+
+#endif /* LIBXML_THREAD_ENABLED */
 
 /************************************************************************
  *									*
@@ -57,22 +167,14 @@ void xmlInitGlobals(void)
  *									*
  ************************************************************************/
 
+#ifdef LIBXML_THREAD_ENABLED
+static unsigned xmlMainThreadRngState[2];
+#endif
+
 /*
  * Memory allocation routines
  */
-#undef	xmlFree
-#undef	xmlMalloc
-#undef	xmlMallocAtomic
-#undef	xmlMemStrdup
-#undef	xmlRealloc
-
-#if defined(DEBUG_MEMORY_LOCATION) || defined(DEBUG_MEMORY)
-xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
-xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
-xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc;
-xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
-xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
-#else
+
 /**
  * xmlFree:
  * @mem: an already allocated block of memory
@@ -131,50 +233,12 @@ xmlPosixStrdup(const char *cur) {
  * Returns the copy of the string or NULL in case of error
  */
 xmlStrdupFunc xmlMemStrdup = xmlPosixStrdup;
-#endif /* DEBUG_MEMORY_LOCATION || DEBUG_MEMORY */
-
-#include <libxml/threads.h>
-#include <libxml/globals.h>
-#include <libxml/SAX.h>
-
-#undef	htmlDefaultSAXHandler
-#undef	oldXMLWDcompatibility
-#undef	xmlBufferAllocScheme
-#undef	xmlDefaultBufferSize
-#undef	xmlDefaultSAXHandler
-#undef	xmlDefaultSAXLocator
-#undef	xmlDoValidityCheckingDefaultValue
-#undef	xmlGenericError
-#undef	xmlStructuredError
-#undef	xmlGenericErrorContext
-#undef	xmlStructuredErrorContext
-#undef	xmlGetWarningsDefaultValue
-#undef	xmlIndentTreeOutput
-#undef  xmlTreeIndentString
-#undef	xmlKeepBlanksDefaultValue
-#undef	xmlLineNumbersDefaultValue
-#undef	xmlLoadExtDtdDefaultValue
-#undef	xmlParserDebugEntities
-#undef	xmlParserVersion
-#undef	xmlPedanticParserDefaultValue
-#undef	xmlSaveNoEmptyTags
-#undef	xmlSubstituteEntitiesDefaultValue
-#undef	xmlRegisterNodeDefaultValue
-#undef	xmlDeregisterNodeDefaultValue
-#undef	xmlLastError
-
-#undef  xmlParserInputBufferCreateFilenameValue
-#undef  xmlOutputBufferCreateFilenameValue
-/**
- * xmlParserVersion:
- *
- * Constant string describing the internal version of the library
- */
-const char *xmlParserVersion = LIBXML_VERSION_STRING LIBXML_VERSION_EXTRA;
 
 /**
  * xmlBufferAllocScheme:
  *
+ * DEPRECATED: Don't use.
+ *
  * Global setting, default allocation policy for buffers, default is
  * XML_BUFFER_ALLOC_EXACT
  */
@@ -183,6 +247,8 @@ static xmlBufferAllocationScheme xmlBufferAllocSchemeThrDef = XML_BUFFER_ALLOC_E
 /**
  * xmlDefaultBufferSize:
  *
+ * DEPRECATED: Don't use.
+ *
  * Global setting, default buffer size. Default value is BASE_BUFFER_SIZE
  */
 int xmlDefaultBufferSize = BASE_BUFFER_SIZE;
@@ -197,19 +263,22 @@ static int xmlDefaultBufferSizeThrDef = BASE_BUFFER_SIZE;
  *
  * Global setting, DEPRECATED.
  */
-int oldXMLWDcompatibility = 0; /* DEPRECATED */
+const int oldXMLWDcompatibility = 0; /* DEPRECATED */
 /**
  * xmlParserDebugEntities:
  *
+ * DEPRECATED: Don't use
+ *
  * Global setting, asking the parser to print out debugging information.
  * while handling entities.
  * Disabled by default
  */
-int xmlParserDebugEntities = 0;
-static int xmlParserDebugEntitiesThrDef = 0;
+const int xmlParserDebugEntities = 0;
 /**
  * xmlDoValidityCheckingDefaultValue:
  *
+ * DEPRECATED: Use the modern options API with XML_PARSE_DTDVALID.
+ *
  * Global setting, indicate that the parser should work in validating mode.
  * Disabled by default.
  */
@@ -218,7 +287,9 @@ static int xmlDoValidityCheckingDefaultValueThrDef = 0;
 /**
  * xmlGetWarningsDefaultValue:
  *
- * Global setting, indicate that the parser should provide warnings.
+ * DEPRECATED: Use the modern options API with XML_PARSE_NOWARNING.
+ *
+ * Global setting, indicate that the DTD validation should provide warnings.
  * Activated by default.
  */
 int xmlGetWarningsDefaultValue = 1;
@@ -226,6 +297,8 @@ static int xmlGetWarningsDefaultValueThrDef = 1;
 /**
  * xmlLoadExtDtdDefaultValue:
  *
+ * DEPRECATED: Use the modern options API with XML_PARSE_DTDLOAD.
+ *
  * Global setting, indicate that the parser should load DTD while not
  * validating.
  * Disabled by default.
@@ -235,6 +308,8 @@ static int xmlLoadExtDtdDefaultValueThrDef = 0;
 /**
  * xmlPedanticParserDefaultValue:
  *
+ * DEPRECATED: Use the modern options API with XML_PARSE_PEDANTIC.
+ *
  * Global setting, indicate that the parser be pedantic
  * Disabled by default.
  */
@@ -243,6 +318,8 @@ static int xmlPedanticParserDefaultValueThrDef = 0;
 /**
  * xmlLineNumbersDefaultValue:
  *
+ * DEPRECATED: The modern options API always enables line numbers.
+ *
  * Global setting, indicate that the parser should store the line number
  * in the content field of elements in the DOM tree.
  * Disabled by default since this may not be safe for old classes of
@@ -253,6 +330,8 @@ static int xmlLineNumbersDefaultValueThrDef = 0;
 /**
  * xmlKeepBlanksDefaultValue:
  *
+ * DEPRECATED: Use the modern options API with XML_PARSE_NOBLANKS.
+ *
  * Global setting, indicate that the parser should keep all blanks
  * nodes found in the content
  * Activated by default, this is actually needed to have the parser
@@ -264,6 +343,8 @@ static int xmlKeepBlanksDefaultValueThrDef = 1;
 /**
  * xmlSubstituteEntitiesDefaultValue:
  *
+ * DEPRECATED: Use the modern options API with XML_PARSE_NOENT.
+ *
  * Global setting, indicate that the parser should not generate entity
  * references but replace them with the actual content of the entity
  * Disabled by default, this should be activated when using XPath since
@@ -273,26 +354,38 @@ static int xmlKeepBlanksDefaultValueThrDef = 1;
 int xmlSubstituteEntitiesDefaultValue = 0;
 static int xmlSubstituteEntitiesDefaultValueThrDef = 0;
 
+/**
+ * xmlRegisterNodeDefaultValue:
+ *
+ * DEPRECATED: Don't use
+ */
 xmlRegisterNodeFunc xmlRegisterNodeDefaultValue = NULL;
 static xmlRegisterNodeFunc xmlRegisterNodeDefaultValueThrDef = NULL;
+
+/**
+ * xmlDeregisterNodeDefaultValue:
+ *
+ * DEPRECATED: Don't use
+ */
 xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue = NULL;
 static xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValueThrDef = NULL;
 
+/**
+ * xmlParserInputBufferCreateFilenameValue:
+ *
+ * DEPRECATED: Don't use
+ */
 xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue = NULL;
 static xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValueThrDef = NULL;
 
+/**
+ * xmlOutputBufferCreateFilenameValue:
+ *
+ * DEPRECATED: Don't use
+ */
 xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue = NULL;
 static xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValueThrDef = NULL;
 
-/*
- * Error handling
- */
-
-/* xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc; */
-/* Must initialize xmlGenericError in xmlInitParser */
-void XMLCDECL xmlGenericErrorDefaultFunc	(void *ctx ATTRIBUTE_UNUSED,
-				 const char *msg,
-				 ...);
 /**
  * xmlGenericError:
  *
@@ -323,6 +416,7 @@ void *xmlStructuredErrorContext = NULL;
 static void *xmlStructuredErrorContextThrDef = NULL;
 xmlError xmlLastError;
 
+#ifdef LIBXML_OUTPUT_ENABLED
 /*
  * output defaults
  */
@@ -353,14 +447,18 @@ static const char *xmlTreeIndentStringThrDef = "  ";
  */
 int xmlSaveNoEmptyTags = 0;
 static int xmlSaveNoEmptyTagsThrDef = 0;
+#endif /* LIBXML_OUTPUT_ENABLED */
 
 #ifdef LIBXML_SAX1_ENABLED
 /**
  * xmlDefaultSAXHandler:
  *
+ * DEPRECATED: This handler is unused and will be removed from future
+ * versions.
+ *
  * Default SAX version1 handler for XML, builds the DOM tree
  */
-xmlSAXHandlerV1 xmlDefaultSAXHandler = {
+const xmlSAXHandlerV1 xmlDefaultSAXHandler = {
     xmlSAX2InternalSubset,
     xmlSAX2IsStandalone,
     xmlSAX2HasInternalSubset,
@@ -388,30 +486,35 @@ xmlSAXHandlerV1 xmlDefaultSAXHandler = {
     xmlSAX2GetParameterEntity,
     xmlSAX2CDataBlock,
     xmlSAX2ExternalSubset,
-    0,
+    1,
 };
 #endif /* LIBXML_SAX1_ENABLED */
 
 /**
  * xmlDefaultSAXLocator:
  *
+ * DEPRECATED: Don't use
+ *
  * The default SAX Locator
  * { getPublicId, getSystemId, getLineNumber, getColumnNumber}
  */
-xmlSAXLocator xmlDefaultSAXLocator = {
+const xmlSAXLocator xmlDefaultSAXLocator = {
     xmlSAX2GetPublicId,
     xmlSAX2GetSystemId,
     xmlSAX2GetLineNumber,
     xmlSAX2GetColumnNumber
 };
 
-#ifdef LIBXML_HTML_ENABLED
+#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_SAX1_ENABLED)
 /**
  * htmlDefaultSAXHandler:
  *
+ * DEPRECATED: This handler is unused and will be removed from future
+ * versions.
+ *
  * Default old SAX v1 handler for HTML, builds the DOM tree
  */
-xmlSAXHandlerV1 htmlDefaultSAXHandler = {
+const xmlSAXHandlerV1 htmlDefaultSAXHandler = {
     xmlSAX2InternalSubset,
     NULL,
     NULL,
@@ -436,644 +539,700 @@ xmlSAXHandlerV1 htmlDefaultSAXHandler = {
     xmlParserWarning,
     xmlParserError,
     xmlParserError,
-    xmlSAX2GetParameterEntity,
+    NULL,
     xmlSAX2CDataBlock,
     NULL,
-    0,
+    1,
 };
 #endif /* LIBXML_HTML_ENABLED */
 
+/************************************************************************
+ *									*
+ *			Per thread global state handling		*
+ *									*
+ ************************************************************************/
+
 /**
- * xmlInitializeGlobalState:
- * @gs: a pointer to a newly allocated global state
+ * xmlInitGlobals:
  *
- * xmlInitializeGlobalState() initialize a global state with all the
- * default values of the library.
+ * DEPRECATED: Alias for xmlInitParser.
  */
-void
-xmlInitializeGlobalState(xmlGlobalStatePtr gs)
-{
-#ifdef DEBUG_GLOBALS
-    fprintf(stderr, "Initializing globals at %lu for thread %d\n",
-	    (unsigned long) gs, xmlGetThreadId());
-#endif
-
-    /*
-     * Perform initialization as required by libxml
-     */
-    if (xmlThrDefMutex == NULL)
-        xmlInitGlobals();
-
-    xmlMutexLock(xmlThrDefMutex);
+void xmlInitGlobals(void) {
+    xmlInitParser();
+}
 
-#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_LEGACY_ENABLED) && defined(LIBXML_SAX1_ENABLED)
-    inithtmlDefaultSAXHandler(&gs->htmlDefaultSAXHandler);
+/**
+ * xmlInitGlobalsInternal:
+ *
+ * Additional initialisation for multi-threading
+ */
+void xmlInitGlobalsInternal(void) {
+    xmlInitMutex(&xmlThrDefMutex);
+
+#ifdef HAVE_POSIX_THREADS
+#ifdef XML_PTHREAD_WEAK
+    if (libxml_is_threaded == -1)
+        libxml_is_threaded =
+            (pthread_getspecific != NULL) &&
+            (pthread_setspecific != NULL) &&
+            (pthread_key_create != NULL) &&
+            (pthread_key_delete != NULL) &&
+            /*
+             * pthread_equal can be inline, resuting in -Waddress warnings.
+             * Let's assume it's available if all the other functions are.
+             */
+            /* (pthread_equal != NULL) && */
+            (pthread_self != NULL);
+    if (libxml_is_threaded == 0)
+        return;
+#endif /* XML_PTHREAD_WEAK */
+    pthread_key_create(&globalkey, xmlFreeGlobalState);
+    mainthread = pthread_self();
+#elif defined(HAVE_WIN32_THREADS)
+#ifndef USE_TLS
+    globalkey = TlsAlloc();
 #endif
-
-    gs->oldXMLWDcompatibility = 0;
-    gs->xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
-    gs->xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
-#if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_LEGACY_ENABLED)
-    initxmlDefaultSAXHandler(&gs->xmlDefaultSAXHandler, 1);
-#endif /* LIBXML_SAX1_ENABLED */
-    gs->xmlDefaultSAXLocator.getPublicId = xmlSAX2GetPublicId;
-    gs->xmlDefaultSAXLocator.getSystemId = xmlSAX2GetSystemId;
-    gs->xmlDefaultSAXLocator.getLineNumber = xmlSAX2GetLineNumber;
-    gs->xmlDefaultSAXLocator.getColumnNumber = xmlSAX2GetColumnNumber;
-    gs->xmlDoValidityCheckingDefaultValue =
-         xmlDoValidityCheckingDefaultValueThrDef;
-#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
-    gs->xmlFree = (xmlFreeFunc) xmlMemFree;
-    gs->xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
-    gs->xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc;
-    gs->xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
-    gs->xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
-#else
-    gs->xmlFree = (xmlFreeFunc) free;
-    gs->xmlMalloc = (xmlMallocFunc) malloc;
-    gs->xmlMallocAtomic = (xmlMallocFunc) malloc;
-    gs->xmlRealloc = (xmlReallocFunc) realloc;
-    gs->xmlMemStrdup = (xmlStrdupFunc) xmlStrdup;
+    mainthread = GetCurrentThreadId();
 #endif
-    gs->xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
-    gs->xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
-    gs->xmlTreeIndentString = xmlTreeIndentStringThrDef;
-    gs->xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
-    gs->xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
-    gs->xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
-    gs->xmlParserDebugEntities = xmlParserDebugEntitiesThrDef;
-    gs->xmlParserVersion = LIBXML_VERSION_STRING;
-    gs->xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
-    gs->xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
-    gs->xmlSubstituteEntitiesDefaultValue =
-        xmlSubstituteEntitiesDefaultValueThrDef;
-
-    gs->xmlGenericError = xmlGenericErrorThrDef;
-    gs->xmlStructuredError = xmlStructuredErrorThrDef;
-    gs->xmlGenericErrorContext = xmlGenericErrorContextThrDef;
-    gs->xmlStructuredErrorContext = xmlStructuredErrorContextThrDef;
-    gs->xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
-    gs->xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
-
-	gs->xmlParserInputBufferCreateFilenameValue = xmlParserInputBufferCreateFilenameValueThrDef;
-	gs->xmlOutputBufferCreateFilenameValue = xmlOutputBufferCreateFilenameValueThrDef;
-    memset(&gs->xmlLastError, 0, sizeof(xmlError));
 
-    xmlMutexUnlock(xmlThrDefMutex);
+#ifdef LIBXML_THREAD_ENABLED
+    xmlMainThreadRngState[0] = xmlGlobalRandom();
+    xmlMainThreadRngState[1] = xmlGlobalRandom();
+#endif
 }
 
 /**
  * xmlCleanupGlobals:
  *
- * DEPRECATED: This function will be made private. Call xmlCleanupParser
+ * DEPRECATED: This function is a no-op. Call xmlCleanupParser
  * to free global state but see the warnings there. xmlCleanupParser
  * should be only called once at program exit. In most cases, you don't
  * have call cleanup functions at all.
+ */
+void xmlCleanupGlobals(void) {
+}
+
+/**
+ * xmlCleanupGlobalsInternal:
  *
  * Additional cleanup for multi-threading
  */
-void xmlCleanupGlobals(void)
-{
+void xmlCleanupGlobalsInternal(void) {
     xmlResetError(&xmlLastError);
 
-    if (xmlThrDefMutex != NULL) {
-	xmlFreeMutex(xmlThrDefMutex);
-	xmlThrDefMutex = NULL;
+    xmlCleanupMutex(&xmlThrDefMutex);
+
+#ifdef HAVE_POSIX_THREADS
+#ifdef XML_PTHREAD_WEAK
+    if (libxml_is_threaded == 0)
+        return;
+#endif /* XML_PTHREAD_WEAK */
+    pthread_key_delete(globalkey);
+#elif defined(HAVE_WIN32_THREADS)
+#ifndef USE_TLS
+    if (globalkey != TLS_OUT_OF_INDEXES) {
+        TlsFree(globalkey);
+        globalkey = TLS_OUT_OF_INDEXES;
     }
-    __xmlGlobalInitMutexDestroy();
+#endif
+#endif
+
+    parserInitialized = 0;
 }
 
 /**
- * DOC_DISABLE : we ignore missing doc for the xmlThrDef functions,
- *               those are really internal work
+ * xmlInitializeGlobalState:
+ * @gs: a pointer to a newly allocated global state
+ *
+ * DEPRECATED: No-op.
  */
 void
-xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
-    xmlMutexLock(xmlThrDefMutex);
-    xmlGenericErrorContextThrDef = ctx;
-    if (handler != NULL)
-	xmlGenericErrorThrDef = handler;
-    else
-	xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
-    xmlMutexUnlock(xmlThrDefMutex);
-}
-
-void
-xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
-    xmlMutexLock(xmlThrDefMutex);
-    xmlStructuredErrorContextThrDef = ctx;
-    xmlStructuredErrorThrDef = handler;
-    xmlMutexUnlock(xmlThrDefMutex);
+xmlInitializeGlobalState(xmlGlobalStatePtr gs ATTRIBUTE_UNUSED)
+{
 }
 
 /**
- * xmlRegisterNodeDefault:
- * @func: function pointer to the new RegisterNodeFunc
+ * xmlGetGlobalState:
  *
- * Registers a callback for node creation
+ * DEPRECATED
  *
- * Returns the old value of the registration function
+ * Returns NULL.
  */
-xmlRegisterNodeFunc
-xmlRegisterNodeDefault(xmlRegisterNodeFunc func)
+xmlGlobalStatePtr
+xmlGetGlobalState(void)
 {
-    xmlRegisterNodeFunc old = xmlRegisterNodeDefaultValue;
-
-    __xmlRegisterCallbacks = 1;
-    xmlRegisterNodeDefaultValue = func;
-    return(old);
+    return(NULL);
 }
 
-xmlRegisterNodeFunc
-xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)
-{
-    xmlRegisterNodeFunc old;
-
-    xmlMutexLock(xmlThrDefMutex);
-    old = xmlRegisterNodeDefaultValueThrDef;
-
-    __xmlRegisterCallbacks = 1;
-    xmlRegisterNodeDefaultValueThrDef = func;
-    xmlMutexUnlock(xmlThrDefMutex);
+static int
+xmlIsMainThreadInternal(void) {
+    if (parserInitialized == 0) {
+        xmlInitParser();
+        parserInitialized = 1;
+    }
 
-    return(old);
+#ifdef HAVE_POSIX_THREADS
+#ifdef XML_PTHREAD_WEAK
+    if (libxml_is_threaded == 0)
+        return (1);
+#endif
+    return (pthread_equal(mainthread, pthread_self()));
+#elif defined HAVE_WIN32_THREADS
+    return (mainthread == GetCurrentThreadId());
+#else
+    return (1);
+#endif
 }
 
 /**
- * xmlDeregisterNodeDefault:
- * @func: function pointer to the new DeregisterNodeFunc
+ * xmlIsMainThread:
+ *
+ * DEPRECATED: Internal function, do not use.
  *
- * Registers a callback for node destruction
+ * Check whether the current thread is the main thread.
  *
- * Returns the previous value of the deregistration function
+ * Returns 1 if the current thread is the main thread, 0 otherwise
  */
-xmlDeregisterNodeFunc
-xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func)
-{
-    xmlDeregisterNodeFunc old = xmlDeregisterNodeDefaultValue;
-
-    __xmlRegisterCallbacks = 1;
-    xmlDeregisterNodeDefaultValue = func;
-    return(old);
+int
+xmlIsMainThread(void) {
+    return(xmlIsMainThreadInternal());
 }
 
-xmlDeregisterNodeFunc
-xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
+#ifdef LIBXML_THREAD_ENABLED
+
+static void
+xmlFreeGlobalState(void *state)
 {
-    xmlDeregisterNodeFunc old;
+    xmlGlobalState *gs = (xmlGlobalState *) state;
 
-    xmlMutexLock(xmlThrDefMutex);
-    old = xmlDeregisterNodeDefaultValueThrDef;
+    /*
+     * Free any memory allocated in the thread's xmlLastError. If it
+     * weren't for this indirect allocation, we wouldn't need
+     * a destructor with thread-local storage at all!
+     *
+     * It would be nice if we could make xmlLastError a special error
+     * type which uses statically allocated, fixed-size buffers.
+     * But the xmlError struct is fully public and widely used,
+     * so changes are dangerous.
+     */
+    xmlResetError(&(gs->gs_xmlLastError));
+#ifndef USE_TLS
+    free(state);
+#endif
+}
 
-    __xmlRegisterCallbacks = 1;
-    xmlDeregisterNodeDefaultValueThrDef = func;
-    xmlMutexUnlock(xmlThrDefMutex);
+#if defined(HAVE_WIN32_THREADS) && \
+    defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
+static void WINAPI
+xmlGlobalStateDtor(void *ctxt, unsigned char timedOut ATTRIBUTE_UNUSED) {
+    xmlGlobalStatePtr gs = ctxt;
 
-    return(old);
+    UnregisterWait(gs->waitHandle);
+    CloseHandle(gs->threadHandle);
+    xmlFreeGlobalState(gs);
 }
 
-xmlParserInputBufferCreateFilenameFunc
-xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
-{
-    xmlParserInputBufferCreateFilenameFunc old;
+static int
+xmlRegisterGlobalStateDtor(xmlGlobalState *gs) {
+    void *processHandle = GetCurrentProcess();
+    void *threadHandle;
+    void *waitHandle;
 
-    xmlMutexLock(xmlThrDefMutex);
-    old = xmlParserInputBufferCreateFilenameValueThrDef;
-    if (old == NULL) {
-		old = __xmlParserInputBufferCreateFilename;
-	}
+    if (DuplicateHandle(processHandle, GetCurrentThread(), processHandle,
+                &threadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) {
+        return(-1);
+    }
 
-    xmlParserInputBufferCreateFilenameValueThrDef = func;
-    xmlMutexUnlock(xmlThrDefMutex);
+    if (RegisterWaitForSingleObject(&waitHandle, threadHandle,
+                xmlGlobalStateDtor, gs, INFINITE, WT_EXECUTEONLYONCE) == 0) {
+        CloseHandle(threadHandle);
+        return(-1);
+    }
 
-    return(old);
+    gs->threadHandle = threadHandle;
+    gs->waitHandle = waitHandle;
+    return(0);
 }
+#endif /* LIBXML_STATIC */
 
-xmlOutputBufferCreateFilenameFunc
-xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
-{
-    xmlOutputBufferCreateFilenameFunc old;
+static void
+xmlInitGlobalState(xmlGlobalStatePtr gs) {
+    xmlMutexLock(&xmlThrDefMutex);
 
-    xmlMutexLock(xmlThrDefMutex);
-    old = xmlOutputBufferCreateFilenameValueThrDef;
+#ifdef LIBXML_THREAD_ENABLED
+    gs->localRngState[0] = xmlGlobalRandom();
+    gs->localRngState[1] = xmlGlobalRandom();
+#endif
+
+    gs->gs_xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
+    gs->gs_xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
+    gs->gs_xmlDoValidityCheckingDefaultValue =
+         xmlDoValidityCheckingDefaultValueThrDef;
+#ifdef LIBXML_THREAD_ALLOC_ENABLED
+    gs->gs_xmlFree = free;
+    gs->gs_xmlMalloc = malloc;
+    gs->gs_xmlMallocAtomic = malloc;
+    gs->gs_xmlRealloc = realloc;
+    gs->gs_xmlMemStrdup = xmlPosixStrdup;
+#endif
+    gs->gs_xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
 #ifdef LIBXML_OUTPUT_ENABLED
-    if (old == NULL) {
-		old = __xmlOutputBufferCreateFilename;
-	}
+    gs->gs_xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
+    gs->gs_xmlTreeIndentString = xmlTreeIndentStringThrDef;
+    gs->gs_xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
 #endif
-    xmlOutputBufferCreateFilenameValueThrDef = func;
-    xmlMutexUnlock(xmlThrDefMutex);
+    gs->gs_xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
+    gs->gs_xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
+    gs->gs_xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
+    gs->gs_xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
+    gs->gs_xmlSubstituteEntitiesDefaultValue =
+        xmlSubstituteEntitiesDefaultValueThrDef;
 
-    return(old);
+    gs->gs_xmlGenericError = xmlGenericErrorThrDef;
+    gs->gs_xmlStructuredError = xmlStructuredErrorThrDef;
+    gs->gs_xmlGenericErrorContext = xmlGenericErrorContextThrDef;
+    gs->gs_xmlStructuredErrorContext = xmlStructuredErrorContextThrDef;
+    gs->gs_xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
+    gs->gs_xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
+
+    gs->gs_xmlParserInputBufferCreateFilenameValue =
+        xmlParserInputBufferCreateFilenameValueThrDef;
+    gs->gs_xmlOutputBufferCreateFilenameValue =
+        xmlOutputBufferCreateFilenameValueThrDef;
+    memset(&gs->gs_xmlLastError, 0, sizeof(xmlError));
+
+    xmlMutexUnlock(&xmlThrDefMutex);
+
+#ifdef HAVE_POSIX_THREADS
+    pthread_setspecific(globalkey, gs);
+#elif defined HAVE_WIN32_THREADS
+#ifndef USE_TLS
+    TlsSetValue(globalkey, gs);
+#endif
+#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
+    xmlRegisterGlobalStateDtor(gs);
+#endif
+#endif
+
+    gs->initialized = 1;
 }
 
-#ifdef LIBXML_HTML_ENABLED
-#undef	htmlDefaultSAXHandler
-xmlSAXHandlerV1 *
-__htmlDefaultSAXHandler(void) {
-    if (IS_MAIN_THREAD)
-	return (&htmlDefaultSAXHandler);
-    else
-	return (&xmlGetGlobalState()->htmlDefaultSAXHandler);
+#ifndef USE_TLS
+/**
+ * xmlNewGlobalState:
+ *
+ * xmlNewGlobalState() allocates a global state. This structure is used to
+ * hold all data for use by a thread when supporting backwards compatibility
+ * of libxml2 to pre-thread-safe behaviour.
+ *
+ * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
+ */
+static xmlGlobalStatePtr
+xmlNewGlobalState(int allowFailure)
+{
+    xmlGlobalState *gs;
+
+    gs = malloc(sizeof(xmlGlobalState));
+    if (gs == NULL) {
+        if (allowFailure)
+            return(NULL);
+
+        /*
+         * If an application didn't call xmlCheckThreadLocalStorage to make
+         * sure that global state could be allocated, it's too late to
+         * handle the error.
+         */
+        fprintf(stderr, "libxml2: Failed to allocate globals for thread\n"
+                        "libxml2: See xmlCheckThreadLocalStorage\n");
+        abort();
+    }
+
+    memset(gs, 0, sizeof(xmlGlobalState));
+    xmlInitGlobalState(gs);
+    return (gs);
 }
 #endif
 
-#undef xmlLastError
-xmlError *
-__xmlLastError(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlLastError);
-    else
-	return (&xmlGetGlobalState()->xmlLastError);
+static xmlGlobalStatePtr
+xmlGetThreadLocalStorage(int allowFailure) {
+    xmlGlobalState *gs;
+
+    (void) allowFailure;
+
+#ifdef USE_TLS
+    gs = &globalState;
+    if (gs->initialized == 0)
+        xmlInitGlobalState(gs);
+#elif defined(HAVE_POSIX_THREADS)
+    gs = (xmlGlobalState *) pthread_getspecific(globalkey);
+    if (gs == NULL)
+        gs = xmlNewGlobalState(allowFailure);
+#elif defined(HAVE_WIN32_THREADS)
+    gs = (xmlGlobalState *) TlsGetValue(globalkey);
+    if (gs == NULL)
+        gs = xmlNewGlobalState(allowFailure);
+#else
+    gs = NULL;
+#endif
+
+    return(gs);
 }
 
-/*
- * The following memory routines were apparently lost at some point,
- * and were re-inserted at this point on June 10, 2004.  Hope it's
- * the right place for them :-)
+/* Define thread-local storage accessors with macro magic */
+
+#define XML_DEFINE_GLOBAL_WRAPPER(name, type, attrs) \
+    type *__vtklibxml2_##name(void) { \
+        if (IS_MAIN_THREAD) \
+            return (&name); \
+        else \
+            return (&xmlGetThreadLocalStorage(0)->gs_##name); \
+    }
+
+#define XML_OP XML_DEFINE_GLOBAL_WRAPPER
+XML_GLOBALS_ALLOC
+XML_GLOBALS_ERROR
+XML_GLOBALS_IO
+XML_GLOBALS_PARSER
+XML_GLOBALS_TREE
+#undef XML_OP
+
+#ifdef LIBXML_THREAD_ENABLED
+/**
+ * xmlGetLocalRngState:
+ *
+ * Returns the local RNG state.
  */
-#if defined(LIBXML_THREAD_ALLOC_ENABLED) && defined(LIBXML_THREAD_ENABLED)
-#undef xmlMalloc
-xmlMallocFunc *
-__xmlMalloc(void){
+unsigned *
+xmlGetLocalRngState(void) {
     if (IS_MAIN_THREAD)
-        return (&xmlMalloc);
+        return(xmlMainThreadRngState);
     else
-	return (&xmlGetGlobalState()->xmlMalloc);
+        return(xmlGetThreadLocalStorage(0)->localRngState);
 }
+#endif
 
-#undef xmlMallocAtomic
-xmlMallocFunc *
-__xmlMallocAtomic(void){
-    if (IS_MAIN_THREAD)
-        return (&xmlMallocAtomic);
-    else
-        return (&xmlGetGlobalState()->xmlMallocAtomic);
+/* For backward compatibility */
+
+const char *const *
+__xmlParserVersion(void) {
+    return &xmlParserVersion;
 }
 
-#undef xmlRealloc
-xmlReallocFunc *
-__xmlRealloc(void){
-    if (IS_MAIN_THREAD)
-        return (&xmlRealloc);
-    else
-        return (&xmlGetGlobalState()->xmlRealloc);
+const int *
+__oldXMLWDcompatibility(void) {
+    return &oldXMLWDcompatibility;
 }
 
-#undef xmlFree
-xmlFreeFunc *
-__xmlFree(void){
-    if (IS_MAIN_THREAD)
-        return (&xmlFree);
-    else
-        return (&xmlGetGlobalState()->xmlFree);
+const int *
+__xmlParserDebugEntities(void) {
+    return &xmlParserDebugEntities;
 }
 
-xmlStrdupFunc *
-__xmlMemStrdup(void){
-    if (IS_MAIN_THREAD)
-        return (&xmlMemStrdup);
-    else
-        return (&xmlGetGlobalState()->xmlMemStrdup);
+const xmlSAXLocator *
+__xmlDefaultSAXLocator(void) {
+    return &xmlDefaultSAXLocator;
 }
 
-#endif
+#ifdef LIBXML_SAX1_ENABLED
+const xmlSAXHandlerV1 *
+__xmlDefaultSAXHandler(void) {
+    return &xmlDefaultSAXHandler;
+}
 
-/*
- * Everything starting from the line below is
- * Automatically generated by build_glob.py.
- * Do not modify the previous line.
+#ifdef LIBXML_HTML_ENABLED
+const xmlSAXHandlerV1 *
+__htmlDefaultSAXHandler(void) {
+    return &htmlDefaultSAXHandler;
+}
+#endif /* LIBXML_HTML_ENABLED */
+#endif /* LIBXML_SAX1_ENABLED */
+
+#endif /* LIBXML_THREAD_ENABLED */
+
+/**
+ * xmlCheckThreadLocalStorage:
+ *
+ * Check whether thread-local storage could be allocated.
+ *
+ * In cross-platform code running in multithreaded environments, this
+ * function should be called once in each thread before calling other
+ * library functions to make sure that thread-local storage was
+ * allocated properly.
+ *
+ * Returns 0 on success or -1 if a memory allocation failed. A failed
+ * allocation signals a typically fatal and irrecoverable out-of-memory
+ * situation. Don't call any library functions in this case.
+ *
+ * This function never fails if the library is compiled with support
+ * for thread-local storage.
+ *
+ * This function never fails for the "main" thread which is the first
+ * thread calling xmlInitParser.
+ *
+ * Available since v2.12.0.
  */
+int
+xmlCheckThreadLocalStorage(void) {
+#if defined(LIBXML_THREAD_ENABLED) && !defined(USE_TLS)
+    if ((!xmlIsMainThreadInternal()) && (xmlGetThreadLocalStorage(1) == NULL))
+        return(-1);
+#endif
+    return(0);
+}
 
+/** DOC_DISABLE */
 
-#undef	oldXMLWDcompatibility
-int *
-__oldXMLWDcompatibility(void) {
-    if (IS_MAIN_THREAD)
-	return (&oldXMLWDcompatibility);
-    else
-	return (&xmlGetGlobalState()->oldXMLWDcompatibility);
+/**
+ * DllMain:
+ * @hinstDLL: handle to DLL instance
+ * @fdwReason: Reason code for entry
+ * @lpvReserved: generic pointer (depends upon reason code)
+ *
+ * Entry point for Windows library. It is being used to free thread-specific
+ * storage.
+ *
+ * Returns TRUE always
+ */
+#if defined(HAVE_WIN32_THREADS) && \
+    (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+#if defined(LIBXML_STATIC_FOR_DLL)
+int
+xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
+           ATTRIBUTE_UNUSED void *lpvReserved)
+#else
+/* declare to avoid "no previous prototype for 'DllMain'" warning */
+/* Note that we do NOT want to include this function declaration in
+   a public header because it's meant to be called by Windows itself,
+   not a program that uses this library.  This also has to be exported. */
+
+XMLPUBFUN BOOL WINAPI
+DllMain (HINSTANCE hinstDLL,
+         DWORD     fdwReason,
+         LPVOID    lpvReserved);
+
+BOOL WINAPI
+DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
+        ATTRIBUTE_UNUSED LPVOID lpvReserved)
+#endif
+{
+    switch (fdwReason) {
+        case DLL_THREAD_DETACH:
+#ifdef USE_TLS
+            xmlFreeGlobalState(&globalState);
+#else
+            if (globalkey != TLS_OUT_OF_INDEXES) {
+                xmlGlobalState *globalval;
+
+                globalval = (xmlGlobalState *) TlsGetValue(globalkey);
+                if (globalval) {
+                    xmlFreeGlobalState(globalval);
+                    TlsSetValue(globalkey, NULL);
+                }
+            }
+#endif
+            break;
+    }
+    return TRUE;
 }
+#endif
 
-#undef	xmlBufferAllocScheme
-xmlBufferAllocationScheme *
-__xmlBufferAllocScheme(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlBufferAllocScheme);
+void
+xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
+    xmlMutexLock(&xmlThrDefMutex);
+    xmlGenericErrorContextThrDef = ctx;
+    if (handler != NULL)
+	xmlGenericErrorThrDef = handler;
     else
-	return (&xmlGetGlobalState()->xmlBufferAllocScheme);
+	xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
+    xmlMutexUnlock(&xmlThrDefMutex);
+}
+
+void
+xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
+    xmlMutexLock(&xmlThrDefMutex);
+    xmlStructuredErrorContextThrDef = ctx;
+    xmlStructuredErrorThrDef = handler;
+    xmlMutexUnlock(&xmlThrDefMutex);
 }
+
 xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) {
     xmlBufferAllocationScheme ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlBufferAllocSchemeThrDef;
     xmlBufferAllocSchemeThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#undef	xmlDefaultBufferSize
-int *
-__xmlDefaultBufferSize(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlDefaultBufferSize);
-    else
-	return (&xmlGetGlobalState()->xmlDefaultBufferSize);
-}
 int xmlThrDefDefaultBufferSize(int v) {
     int ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlDefaultBufferSizeThrDef;
     xmlDefaultBufferSizeThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#ifdef LIBXML_SAX1_ENABLED
-#undef	xmlDefaultSAXHandler
-xmlSAXHandlerV1 *
-__xmlDefaultSAXHandler(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlDefaultSAXHandler);
-    else
-	return (&xmlGetGlobalState()->xmlDefaultSAXHandler);
-}
-#endif /* LIBXML_SAX1_ENABLED */
-
-#undef	xmlDefaultSAXLocator
-xmlSAXLocator *
-__xmlDefaultSAXLocator(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlDefaultSAXLocator);
-    else
-	return (&xmlGetGlobalState()->xmlDefaultSAXLocator);
-}
-
-#undef	xmlDoValidityCheckingDefaultValue
-int *
-__xmlDoValidityCheckingDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlDoValidityCheckingDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlDoValidityCheckingDefaultValue);
-}
 int xmlThrDefDoValidityCheckingDefaultValue(int v) {
     int ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlDoValidityCheckingDefaultValueThrDef;
     xmlDoValidityCheckingDefaultValueThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#undef	xmlGenericError
-xmlGenericErrorFunc *
-__xmlGenericError(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlGenericError);
-    else
-	return (&xmlGetGlobalState()->xmlGenericError);
-}
-
-#undef	xmlStructuredError
-xmlStructuredErrorFunc *
-__xmlStructuredError(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlStructuredError);
-    else
-	return (&xmlGetGlobalState()->xmlStructuredError);
-}
-
-#undef	xmlGenericErrorContext
-void * *
-__xmlGenericErrorContext(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlGenericErrorContext);
-    else
-	return (&xmlGetGlobalState()->xmlGenericErrorContext);
-}
-
-#undef	xmlStructuredErrorContext
-void * *
-__xmlStructuredErrorContext(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlStructuredErrorContext);
-    else
-	return (&xmlGetGlobalState()->xmlStructuredErrorContext);
-}
-
-#undef	xmlGetWarningsDefaultValue
-int *
-__xmlGetWarningsDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlGetWarningsDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlGetWarningsDefaultValue);
-}
 int xmlThrDefGetWarningsDefaultValue(int v) {
     int ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlGetWarningsDefaultValueThrDef;
     xmlGetWarningsDefaultValueThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#undef	xmlIndentTreeOutput
-int *
-__xmlIndentTreeOutput(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlIndentTreeOutput);
-    else
-	return (&xmlGetGlobalState()->xmlIndentTreeOutput);
-}
+#ifdef LIBXML_OUTPUT_ENABLED
 int xmlThrDefIndentTreeOutput(int v) {
     int ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlIndentTreeOutputThrDef;
     xmlIndentTreeOutputThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#undef	xmlTreeIndentString
-const char * *
-__xmlTreeIndentString(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlTreeIndentString);
-    else
-	return (&xmlGetGlobalState()->xmlTreeIndentString);
-}
 const char * xmlThrDefTreeIndentString(const char * v) {
     const char * ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlTreeIndentStringThrDef;
     xmlTreeIndentStringThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#undef	xmlKeepBlanksDefaultValue
-int *
-__xmlKeepBlanksDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlKeepBlanksDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlKeepBlanksDefaultValue);
+int xmlThrDefSaveNoEmptyTags(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlSaveNoEmptyTagsThrDef;
+    xmlSaveNoEmptyTagsThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
 }
+#endif
+
 int xmlThrDefKeepBlanksDefaultValue(int v) {
     int ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlKeepBlanksDefaultValueThrDef;
     xmlKeepBlanksDefaultValueThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#undef	xmlLineNumbersDefaultValue
-int *
-__xmlLineNumbersDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlLineNumbersDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlLineNumbersDefaultValue);
-}
 int xmlThrDefLineNumbersDefaultValue(int v) {
     int ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlLineNumbersDefaultValueThrDef;
     xmlLineNumbersDefaultValueThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#undef	xmlLoadExtDtdDefaultValue
-int *
-__xmlLoadExtDtdDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlLoadExtDtdDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlLoadExtDtdDefaultValue);
-}
 int xmlThrDefLoadExtDtdDefaultValue(int v) {
     int ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlLoadExtDtdDefaultValueThrDef;
     xmlLoadExtDtdDefaultValueThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlParserDebugEntities
-int *
-__xmlParserDebugEntities(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlParserDebugEntities);
-    else
-	return (&xmlGetGlobalState()->xmlParserDebugEntities);
-}
-int xmlThrDefParserDebugEntities(int v) {
-    int ret;
-    xmlMutexLock(xmlThrDefMutex);
-    ret = xmlParserDebugEntitiesThrDef;
-    xmlParserDebugEntitiesThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#undef	xmlParserVersion
-const char * *
-__xmlParserVersion(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlParserVersion);
-    else
-	return (&xmlGetGlobalState()->xmlParserVersion);
+int xmlThrDefParserDebugEntities(int v ATTRIBUTE_UNUSED) {
+    return(xmlParserDebugEntities);
 }
 
-#undef	xmlPedanticParserDefaultValue
-int *
-__xmlPedanticParserDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlPedanticParserDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlPedanticParserDefaultValue);
-}
 int xmlThrDefPedanticParserDefaultValue(int v) {
     int ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlPedanticParserDefaultValueThrDef;
     xmlPedanticParserDefaultValueThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlSaveNoEmptyTags
-int *
-__xmlSaveNoEmptyTags(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlSaveNoEmptyTags);
-    else
-	return (&xmlGetGlobalState()->xmlSaveNoEmptyTags);
-}
-int xmlThrDefSaveNoEmptyTags(int v) {
-    int ret;
-    xmlMutexLock(xmlThrDefMutex);
-    ret = xmlSaveNoEmptyTagsThrDef;
-    xmlSaveNoEmptyTagsThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#undef	xmlSubstituteEntitiesDefaultValue
-int *
-__xmlSubstituteEntitiesDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlSubstituteEntitiesDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlSubstituteEntitiesDefaultValue);
-}
 int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
     int ret;
-    xmlMutexLock(xmlThrDefMutex);
+    xmlMutexLock(&xmlThrDefMutex);
     ret = xmlSubstituteEntitiesDefaultValueThrDef;
     xmlSubstituteEntitiesDefaultValueThrDef = v;
-    xmlMutexUnlock(xmlThrDefMutex);
+    xmlMutexUnlock(&xmlThrDefMutex);
     return ret;
 }
 
-#undef	xmlRegisterNodeDefaultValue
-xmlRegisterNodeFunc *
-__xmlRegisterNodeDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlRegisterNodeDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlRegisterNodeDefaultValue);
+xmlRegisterNodeFunc
+xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)
+{
+    xmlRegisterNodeFunc old;
+
+    xmlMutexLock(&xmlThrDefMutex);
+    old = xmlRegisterNodeDefaultValueThrDef;
+
+    __xmlRegisterCallbacks = 1;
+    xmlRegisterNodeDefaultValueThrDef = func;
+    xmlMutexUnlock(&xmlThrDefMutex);
+
+    return(old);
 }
 
-#undef	xmlDeregisterNodeDefaultValue
-xmlDeregisterNodeFunc *
-__xmlDeregisterNodeDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlDeregisterNodeDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlDeregisterNodeDefaultValue);
+xmlDeregisterNodeFunc
+xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
+{
+    xmlDeregisterNodeFunc old;
+
+    xmlMutexLock(&xmlThrDefMutex);
+    old = xmlDeregisterNodeDefaultValueThrDef;
+
+    __xmlRegisterCallbacks = 1;
+    xmlDeregisterNodeDefaultValueThrDef = func;
+    xmlMutexUnlock(&xmlThrDefMutex);
+
+    return(old);
 }
 
-#undef	xmlParserInputBufferCreateFilenameValue
-xmlParserInputBufferCreateFilenameFunc *
-__xmlParserInputBufferCreateFilenameValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlParserInputBufferCreateFilenameValue);
-    else
-	return (&xmlGetGlobalState()->xmlParserInputBufferCreateFilenameValue);
+xmlParserInputBufferCreateFilenameFunc
+xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
+{
+    xmlParserInputBufferCreateFilenameFunc old;
+
+    xmlMutexLock(&xmlThrDefMutex);
+    old = xmlParserInputBufferCreateFilenameValueThrDef;
+    if (old == NULL) {
+		old = __xmlParserInputBufferCreateFilename;
+	}
+
+    xmlParserInputBufferCreateFilenameValueThrDef = func;
+    xmlMutexUnlock(&xmlThrDefMutex);
+
+    return(old);
 }
 
-#undef	xmlOutputBufferCreateFilenameValue
-xmlOutputBufferCreateFilenameFunc *
-__xmlOutputBufferCreateFilenameValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlOutputBufferCreateFilenameValue);
-    else
-	return (&xmlGetGlobalState()->xmlOutputBufferCreateFilenameValue);
+xmlOutputBufferCreateFilenameFunc
+xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
+{
+    xmlOutputBufferCreateFilenameFunc old;
+
+    xmlMutexLock(&xmlThrDefMutex);
+    old = xmlOutputBufferCreateFilenameValueThrDef;
+#ifdef LIBXML_OUTPUT_ENABLED
+    if (old == NULL) {
+		old = __xmlOutputBufferCreateFilename;
+	}
+#endif
+    xmlOutputBufferCreateFilenameValueThrDef = func;
+    xmlMutexUnlock(&xmlThrDefMutex);
+
+    return(old);
 }
 
+/** DOC_ENABLE */
+
diff --git a/hash.c b/hash.c
index 894174fb99ad9be38519ecf4045f75a86624ddc6..6af8527eafbdb11fdd7da41fcd6ff955d9f72e73 100644
--- a/hash.c
+++ b/hash.c
@@ -1,200 +1,197 @@
 /*
- * hash.c: chained hash tables
+ * hash.c: hash tables
  *
- * Reference: Your favorite introductory book on algorithms
+ * Hash table with open addressing, linear probing and
+ * Robin Hood reordering.
  *
- * Copyright (C) 2000,2012 Bjorn Reese and Daniel Veillard.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
- * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
- *
- * Author: breese@users.sourceforge.net
+ * See Copyright for the status of this software.
  */
 
 #define IN_LIBXML
 #include "libxml.h"
 
 #include <string.h>
-#include <stdlib.h>
-#include <time.h>
-
-/*
- * Following http://www.ocert.org/advisories/ocert-2011-003.html
- * it seems that having hash randomization might be a good idea
- * when using XML with untrusted data
- */
-#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
-#define HASH_RANDOMIZATION
-#endif
+#include <limits.h>
 
 #include <libxml/parser.h>
 #include <libxml/hash.h>
+#include <libxml/dict.h>
 #include <libxml/xmlmemory.h>
-#include <libxml/xmlerror.h>
-#include <libxml/globals.h>
+#include <libxml/xmlstring.h>
+
+#include "private/dict.h"
 
-#define MAX_HASH_LEN 8
+#ifndef SIZE_MAX
+  #define SIZE_MAX ((size_t) -1)
+#endif
 
-/* #define DEBUG_GROW */
+#define MAX_FILL_NUM 7
+#define MAX_FILL_DENOM 8
+#define MIN_HASH_SIZE 8
+#define MAX_HASH_SIZE (1u << 31)
 
 /*
  * A single entry in the hash table
  */
-typedef struct _xmlHashEntry xmlHashEntry;
-typedef xmlHashEntry *xmlHashEntryPtr;
-struct _xmlHashEntry {
-    struct _xmlHashEntry *next;
-    xmlChar *name;
-    xmlChar *name2;
-    xmlChar *name3;
+typedef struct {
+    unsigned hashValue; /* 0 means unoccupied, occupied entries have the
+                         * MAX_HASH_SIZE bit set to 1 */
+    xmlChar *key;
+    xmlChar *key2; /* TODO: Don't allocate possibly empty keys */
+    xmlChar *key3;
     void *payload;
-    int valid;
-};
+} xmlHashEntry;
 
 /*
  * The entire hash table
  */
 struct _xmlHashTable {
-    struct _xmlHashEntry *table;
-    int size;
-    int nbElems;
+    xmlHashEntry *table;
+    unsigned size; /* power of two */
+    unsigned nbElems;
     xmlDictPtr dict;
-#ifdef HASH_RANDOMIZATION
-    int random_seed;
-#endif
+    unsigned randomSeed;
 };
 
-/*
- * xmlHashComputeKey:
- * Calculate the hash key
- */
-#ifdef __clang__
-ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
-#endif
-static unsigned long
-xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
-	          const xmlChar *name2, const xmlChar *name3) {
-    unsigned long value = 0L;
-    unsigned long ch;
-
-#ifdef HASH_RANDOMIZATION
-    value = table->random_seed;
-#endif
-    if (name != NULL) {
-	value += 30 * (*name);
-	while ((ch = *name++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
-	}
+static int
+xmlHashGrow(xmlHashTablePtr hash, unsigned size);
+
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static unsigned
+xmlHashValue(unsigned seed, const xmlChar *key, const xmlChar *key2,
+             const xmlChar *key3, size_t *lengths) {
+    unsigned h1, h2;
+    size_t i;
+
+    HASH_INIT(h1, h2, seed);
+
+    for (i = 0; key[i] != 0; i++) {
+        HASH_UPDATE(h1, h2, key[i]);
     }
-    value = value ^ ((value << 5) + (value >> 3));
-    if (name2 != NULL) {
-	while ((ch = *name2++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
-	}
+    if (lengths)
+        lengths[0] = i;
+
+    HASH_UPDATE(h1, h2, 0);
+
+    if (key2 != NULL) {
+        for (i = 0; key2[i] != 0; i++) {
+            HASH_UPDATE(h1, h2, key2[i]);
+        }
+        if (lengths)
+            lengths[1] = i;
     }
-    value = value ^ ((value << 5) + (value >> 3));
-    if (name3 != NULL) {
-	while ((ch = *name3++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
-	}
+
+    HASH_UPDATE(h1, h2, 0);
+
+    if (key3 != NULL) {
+        for (i = 0; key3[i] != 0; i++) {
+            HASH_UPDATE(h1, h2, key3[i]);
+        }
+        if (lengths)
+            lengths[2] = i;
     }
-    return (value % table->size);
+
+    HASH_FINISH(h1, h2);
+
+    return(h2);
 }
 
-#ifdef __clang__
-ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
-#endif
-static unsigned long
-xmlHashComputeQKey(xmlHashTablePtr table,
-		   const xmlChar *prefix, const xmlChar *name,
-		   const xmlChar *prefix2, const xmlChar *name2,
-		   const xmlChar *prefix3, const xmlChar *name3) {
-    unsigned long value = 0L;
-    unsigned long ch;
-
-#ifdef HASH_RANDOMIZATION
-    value = table->random_seed;
-#endif
-    if (prefix != NULL)
-	value += 30 * (*prefix);
-    else
-	value += 30 * (*name);
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static unsigned
+xmlHashQNameValue(unsigned seed,
+                  const xmlChar *prefix, const xmlChar *name,
+                  const xmlChar *prefix2, const xmlChar *name2,
+                  const xmlChar *prefix3, const xmlChar *name3) {
+    unsigned h1, h2, ch;
+
+    HASH_INIT(h1, h2, seed);
 
     if (prefix != NULL) {
-	while ((ch = *prefix++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
-	}
-	value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
+        while ((ch = *prefix++) != 0) {
+            HASH_UPDATE(h1, h2, ch);
+        }
+        HASH_UPDATE(h1, h2, ':');
     }
     if (name != NULL) {
-	while ((ch = *name++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
-	}
+        while ((ch = *name++) != 0) {
+            HASH_UPDATE(h1, h2, ch);
+        }
     }
-    value = value ^ ((value << 5) + (value >> 3));
+    HASH_UPDATE(h1, h2, 0);
     if (prefix2 != NULL) {
-	while ((ch = *prefix2++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
-	}
-	value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
+        while ((ch = *prefix2++) != 0) {
+            HASH_UPDATE(h1, h2, ch);
+        }
+        HASH_UPDATE(h1, h2, ':');
     }
     if (name2 != NULL) {
-	while ((ch = *name2++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
-	}
+        while ((ch = *name2++) != 0) {
+            HASH_UPDATE(h1, h2, ch);
+        }
     }
-    value = value ^ ((value << 5) + (value >> 3));
+    HASH_UPDATE(h1, h2, 0);
     if (prefix3 != NULL) {
-	while ((ch = *prefix3++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
-	}
-	value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
+        while ((ch = *prefix3++) != 0) {
+            HASH_UPDATE(h1, h2, ch);
+        }
+        HASH_UPDATE(h1, h2, ':');
     }
     if (name3 != NULL) {
-	while ((ch = *name3++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
-	}
+        while ((ch = *name3++) != 0) {
+            HASH_UPDATE(h1, h2, ch);
+        }
     }
-    return (value % table->size);
+
+    HASH_FINISH(h1, h2);
+
+    return(h2);
 }
 
 /**
  * xmlHashCreate:
- * @size: the size of the hash table
+ * @size: initial size of the hash table
  *
- * Create a new xmlHashTablePtr.
+ * Create a new hash table. Set size to zero if the number of entries
+ * can't be estimated.
  *
- * Returns the newly created object, or NULL if an error occurred.
+ * Returns the newly created object, or NULL if a memory allocation failed.
  */
 xmlHashTablePtr
 xmlHashCreate(int size) {
-    xmlHashTablePtr table;
-
-    if (size <= 0)
-        size = 256;
-
-    table = xmlMalloc(sizeof(xmlHashTable));
-    if (table) {
-        table->dict = NULL;
-        table->size = size;
-	table->nbElems = 0;
-        table->table = xmlMalloc(size * sizeof(xmlHashEntry));
-        if (table->table) {
-	    memset(table->table, 0, size * sizeof(xmlHashEntry));
-#ifdef HASH_RANDOMIZATION
-            table->random_seed = __xmlRandom();
+    xmlHashTablePtr hash;
+
+    xmlInitParser();
+
+    hash = xmlMalloc(sizeof(*hash));
+    if (hash == NULL)
+        return(NULL);
+    hash->dict = NULL;
+    hash->size = 0;
+    hash->table = NULL;
+    hash->nbElems = 0;
+    hash->randomSeed = xmlRandom();
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    hash->randomSeed = 0;
 #endif
-	    return(table);
+
+    /*
+     * Unless a larger size is passed, the backing table is created
+     * lazily with MIN_HASH_SIZE capacity. In practice, there are many
+     * hash tables which are never filled.
+     */
+    if (size > MIN_HASH_SIZE) {
+        unsigned newSize = MIN_HASH_SIZE * 2;
+
+        while ((newSize < (unsigned) size) && (newSize < MAX_HASH_SIZE))
+            newSize *= 2;
+
+        if (xmlHashGrow(hash, newSize) != 0) {
+            xmlFree(hash);
+            return(NULL);
         }
-        xmlFree(table);
     }
-    return(NULL);
+
+    return(hash);
 }
 
 /**
@@ -202,938 +199,1147 @@ xmlHashCreate(int size) {
  * @size: the size of the hash table
  * @dict: a dictionary to use for the hash
  *
- * Create a new xmlHashTablePtr which will use @dict as the internal dictionary
+ * Create a new hash table backed by a dictionary. This can reduce
+ * resource usage considerably if most keys passed to API functions
+ * originate from this dictionary.
  *
- * Returns the newly created object, or NULL if an error occurred.
+ * Returns the newly created object, or NULL if a memory allocation failed.
  */
 xmlHashTablePtr
 xmlHashCreateDict(int size, xmlDictPtr dict) {
-    xmlHashTablePtr table;
+    xmlHashTablePtr hash;
+
+    hash = xmlHashCreate(size);
+    if (hash != NULL) {
+        hash->dict = dict;
+        xmlDictReference(dict);
+    }
+    return(hash);
+}
+
+/**
+ * xmlHashFree:
+ * @hash: hash table
+ * @dealloc: deallocator function or NULL
+ *
+ * Free the hash and its contents. The payload is deallocated with
+ * @dealloc if provided.
+ */
+void
+xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc) {
+    if (hash == NULL)
+        return;
+
+    if (hash->table) {
+        const xmlHashEntry *end = &hash->table[hash->size];
+        const xmlHashEntry *entry;
+
+        for (entry = hash->table; entry < end; entry++) {
+            if (entry->hashValue == 0)
+                continue;
+            if ((dealloc != NULL) && (entry->payload != NULL))
+                dealloc(entry->payload, entry->key);
+            if (hash->dict == NULL) {
+                if (entry->key)
+                    xmlFree(entry->key);
+                if (entry->key2)
+                    xmlFree(entry->key2);
+                if (entry->key3)
+                    xmlFree(entry->key3);
+            }
+        }
 
-    table = xmlHashCreate(size);
-    if (table != NULL) {
-        table->dict = dict;
-	xmlDictReference(dict);
+        xmlFree(hash->table);
     }
-    return(table);
+
+    if (hash->dict)
+        xmlDictFree(hash->dict);
+
+    xmlFree(hash);
+}
+
+/**
+ * xmlFastStrEqual:
+ * @s1: string
+ * @s2: string
+ *
+ * Compare two strings for equality, allowing NULL values.
+ */
+static int
+xmlFastStrEqual(const xmlChar *s1, const xmlChar *s2) {
+    if (s1 == NULL)
+        return(s2 == NULL);
+    else
+        return((s2 != NULL) &&
+               (strcmp((const char *) s1, (const char *) s2) == 0));
+}
+
+/**
+ * xmlHashFindEntry:
+ * @hash: hash table, non-NULL, size > 0
+ * @key: first string key, non-NULL
+ * @key2: second string key
+ * @key3: third string key
+ * @hashValue: valid hash value of keys
+ * @pfound: result of search
+ *
+ * Try to find a matching hash table entry. If an entry was found, set
+ * @found to 1 and return the entry. Otherwise, set @found to 0 and return
+ * the location where a new entry should be inserted.
+ */
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static xmlHashEntry *
+xmlHashFindEntry(const xmlHashTable *hash, const xmlChar *key,
+                 const xmlChar *key2, const xmlChar *key3,
+                 unsigned hashValue, int *pfound) {
+    xmlHashEntry *entry;
+    unsigned mask, pos, displ;
+    int found = 0;
+
+    mask = hash->size - 1;
+    pos = hashValue & mask;
+    entry = &hash->table[pos];
+
+    if (entry->hashValue != 0) {
+        /*
+         * Robin hood hashing: abort if the displacement of the entry
+         * is smaller than the displacement of the key we look for.
+         * This also stops at the correct position when inserting.
+         */
+        displ = 0;
+        hashValue |= MAX_HASH_SIZE;
+
+        do {
+            if (entry->hashValue == hashValue) {
+                if (hash->dict) {
+                    if ((entry->key == key) &&
+                        (entry->key2 == key2) &&
+                        (entry->key3 == key3)) {
+                        found = 1;
+                        break;
+                    }
+                }
+                if ((strcmp((const char *) entry->key,
+                            (const char *) key) == 0) &&
+                    (xmlFastStrEqual(entry->key2, key2)) &&
+                    (xmlFastStrEqual(entry->key3, key3))) {
+                    found = 1;
+                    break;
+                }
+            }
+
+            displ++;
+            pos++;
+            entry++;
+            if ((pos & mask) == 0)
+                entry = hash->table;
+        } while ((entry->hashValue != 0) &&
+                 (((pos - entry->hashValue) & mask) >= displ));
+    }
+
+    *pfound = found;
+    return(entry);
 }
 
 /**
  * xmlHashGrow:
- * @table: the hash table
- * @size: the new size of the hash table
+ * @hash: hash table
+ * @size: new size of the hash table
  *
- * resize the hash table
+ * Resize the hash table.
  *
- * Returns 0 in case of success, -1 in case of failure
+ * Returns 0 in case of success, -1 if a memory allocation failed.
  */
 static int
-xmlHashGrow(xmlHashTablePtr table, int size) {
-    unsigned long key;
-    int oldsize, i;
-    xmlHashEntryPtr iter, next;
-    struct _xmlHashEntry *oldtable;
-#ifdef DEBUG_GROW
-    unsigned long nbElem = 0;
-#endif
+xmlHashGrow(xmlHashTablePtr hash, unsigned size) {
+    const xmlHashEntry *oldentry, *oldend, *end;
+    xmlHashEntry *table;
+    unsigned oldsize, i;
 
+    /* Add 0 to avoid spurious -Wtype-limits warning on 64-bit GCC */
+    if ((size_t) size + 0 > SIZE_MAX / sizeof(table[0]))
+        return(-1);
+    table = xmlMalloc(size * sizeof(table[0]));
     if (table == NULL)
-	return(-1);
-    if (size < 8)
         return(-1);
-    if (size > 8 * 2048)
-	return(-1);
+    memset(table, 0, size * sizeof(table[0]));
 
-    oldsize = table->size;
-    oldtable = table->table;
-    if (oldtable == NULL)
-        return(-1);
+    oldsize = hash->size;
+    if (oldsize == 0)
+        goto done;
 
-    table->table = xmlMalloc(size * sizeof(xmlHashEntry));
-    if (table->table == NULL) {
-	table->table = oldtable;
-	return(-1);
-    }
-    memset(table->table, 0, size * sizeof(xmlHashEntry));
-    table->size = size;
-
-    /*	If the two loops are merged, there would be situations where
-	a new entry needs to allocated and data copied into it from
-	the main table. So instead, we run through the array twice, first
-	copying all the elements in the main array (where we can't get
-	conflicts) and then the rest, so we only free (and don't allocate)
-    */
-    for (i = 0; i < oldsize; i++) {
-	if (oldtable[i].valid == 0)
-	    continue;
-	key = xmlHashComputeKey(table, oldtable[i].name, oldtable[i].name2,
-				oldtable[i].name3);
-	memcpy(&(table->table[key]), &(oldtable[i]), sizeof(xmlHashEntry));
-	table->table[key].next = NULL;
+    oldend = &hash->table[oldsize];
+    end = &table[size];
+
+    /*
+     * Robin Hood sorting order is maintained if we
+     *
+     * - compute hash indices with modulo
+     * - resize by an integer factor
+     * - start to copy from the beginning of a probe sequence
+     */
+    oldentry = hash->table;
+    while (oldentry->hashValue != 0) {
+        if (++oldentry >= oldend)
+            oldentry = hash->table;
     }
 
     for (i = 0; i < oldsize; i++) {
-	iter = oldtable[i].next;
-	while (iter) {
-	    next = iter->next;
-
-	    /*
-	     * put back the entry in the new table
-	     */
-
-	    key = xmlHashComputeKey(table, iter->name, iter->name2,
-		                    iter->name3);
-	    if (table->table[key].valid == 0) {
-		memcpy(&(table->table[key]), iter, sizeof(xmlHashEntry));
-		table->table[key].next = NULL;
-		xmlFree(iter);
-	    } else {
-		iter->next = table->table[key].next;
-		table->table[key].next = iter;
-	    }
-
-#ifdef DEBUG_GROW
-	    nbElem++;
-#endif
+        if (oldentry->hashValue != 0) {
+            xmlHashEntry *entry = &table[oldentry->hashValue & (size - 1)];
 
-	    iter = next;
-	}
+            while (entry->hashValue != 0) {
+                if (++entry >= end)
+                    entry = table;
+            }
+            *entry = *oldentry;
+        }
+
+        if (++oldentry >= oldend)
+            oldentry = hash->table;
     }
 
-    xmlFree(oldtable);
+    xmlFree(hash->table);
 
-#ifdef DEBUG_GROW
-    xmlGenericError(xmlGenericErrorContext,
-	    "xmlHashGrow : from %d to %d, %d elems\n", oldsize, size, nbElem);
-#endif
+done:
+    hash->table = table;
+    hash->size = size;
 
     return(0);
 }
 
 /**
- * xmlHashFree:
- * @table: the hash table
- * @f:  the deallocator function for items in the hash
+ * xmlHashUpdateInternal:
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ * @key3: third string key
+ * @payload: pointer to the payload
+ * @dealloc: deallocator function for replaced item or NULL
+ * @update: whether existing entries should be updated
  *
- * Free the hash @table and its contents. The userdata is
- * deallocated with @f if provided.
+ * Internal function to add or update hash entries.
  */
-void
-xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) {
-    int i;
-    xmlHashEntryPtr iter;
-    xmlHashEntryPtr next;
-    int inside_table = 0;
-    int nbElems;
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static int
+xmlHashUpdateInternal(xmlHashTablePtr hash, const xmlChar *key,
+                      const xmlChar *key2, const xmlChar *key3,
+                      void *payload, xmlHashDeallocator dealloc, int update) {
+    xmlChar *copy, *copy2, *copy3;
+    xmlHashEntry *entry = NULL;
+    size_t lengths[3];
+    unsigned hashValue;
+    int found = 0;
+
+    if ((hash == NULL) || (key == NULL))
+        return(-1);
 
-    if (table == NULL)
-	return;
-    if (table->table) {
-	nbElems = table->nbElems;
-	for(i = 0; (i < table->size) && (nbElems > 0); i++) {
-	    iter = &(table->table[i]);
-	    if (iter->valid == 0)
-		continue;
-	    inside_table = 1;
-	    while (iter) {
-		next = iter->next;
-		if ((f != NULL) && (iter->payload != NULL))
-		    f(iter->payload, iter->name);
-		if (table->dict == NULL) {
-		    if (iter->name)
-			xmlFree(iter->name);
-		    if (iter->name2)
-			xmlFree(iter->name2);
-		    if (iter->name3)
-			xmlFree(iter->name3);
-		}
-		iter->payload = NULL;
-		if (!inside_table)
-		    xmlFree(iter);
-		nbElems--;
-		inside_table = 0;
-		iter = next;
-	    }
-	}
-	xmlFree(table->table);
+    /*
+     * Check for an existing entry
+     */
+    hashValue = xmlHashValue(hash->randomSeed, key, key2, key3, lengths);
+    if (hash->size > 0)
+        entry = xmlHashFindEntry(hash, key, key2, key3, hashValue, &found);
+    if (found) {
+        if (update) {
+            if (dealloc)
+                dealloc(entry->payload, entry->key);
+            entry->payload = payload;
+        }
+
+        return(0);
+    }
+
+    /*
+     * Grow the hash table if needed
+     */
+    if (hash->nbElems + 1 > hash->size / MAX_FILL_DENOM * MAX_FILL_NUM) {
+        unsigned newSize, mask, displ, pos;
+
+        if (hash->size == 0) {
+            newSize = MIN_HASH_SIZE;
+        } else {
+            /* This guarantees that nbElems < INT_MAX */
+            if (hash->size >= MAX_HASH_SIZE)
+                return(-1);
+            newSize = hash->size * 2;
+        }
+        if (xmlHashGrow(hash, newSize) != 0)
+            return(-1);
+
+        /*
+         * Find new entry
+         */
+        mask = hash->size - 1;
+        displ = 0;
+        pos = hashValue & mask;
+        entry = &hash->table[pos];
+
+        if (entry->hashValue != 0) {
+            do {
+                displ++;
+                pos++;
+                entry++;
+                if ((pos & mask) == 0)
+                    entry = hash->table;
+            } while ((entry->hashValue != 0) &&
+                     ((pos - entry->hashValue) & mask) >= displ);
+        }
+    }
+
+    /*
+     * Copy keys
+     */
+    if (hash->dict != NULL) {
+        if (xmlDictOwns(hash->dict, key)) {
+            copy = (xmlChar *) key;
+        } else {
+            copy = (xmlChar *) xmlDictLookup(hash->dict, key, -1);
+            if (copy == NULL)
+                return(-1);
+        }
+
+        if ((key2 == NULL) || (xmlDictOwns(hash->dict, key2))) {
+            copy2 = (xmlChar *) key2;
+        } else {
+            copy2 = (xmlChar *) xmlDictLookup(hash->dict, key2, -1);
+            if (copy2 == NULL)
+                return(-1);
+        }
+        if ((key3 == NULL) || (xmlDictOwns(hash->dict, key3))) {
+            copy3 = (xmlChar *) key3;
+        } else {
+            copy3 = (xmlChar *) xmlDictLookup(hash->dict, key3, -1);
+            if (copy3 == NULL)
+                return(-1);
+        }
+    } else {
+        copy = xmlMalloc(lengths[0] + 1);
+        if (copy == NULL)
+            return(-1);
+        memcpy(copy, key, lengths[0] + 1);
+
+        if (key2 != NULL) {
+            copy2 = xmlMalloc(lengths[1] + 1);
+            if (copy2 == NULL) {
+                xmlFree(copy);
+                return(-1);
+            }
+            memcpy(copy2, key2, lengths[1] + 1);
+        } else {
+            copy2 = NULL;
+        }
+
+        if (key3 != NULL) {
+            copy3 = xmlMalloc(lengths[2] + 1);
+            if (copy3 == NULL) {
+                xmlFree(copy);
+                xmlFree(copy2);
+                return(-1);
+            }
+            memcpy(copy3, key3, lengths[2] + 1);
+        } else {
+            copy3 = NULL;
+        }
+    }
+
+    /*
+     * Shift the remainder of the probe sequence to the right
+     */
+    if (entry->hashValue != 0) {
+        const xmlHashEntry *end = &hash->table[hash->size];
+        const xmlHashEntry *cur = entry;
+
+        do {
+            cur++;
+            if (cur >= end)
+                cur = hash->table;
+        } while (cur->hashValue != 0);
+
+        if (cur < entry) {
+            /*
+             * If we traversed the end of the buffer, handle the part
+             * at the start of the buffer.
+             */
+            memmove(&hash->table[1], hash->table,
+                    (char *) cur - (char *) hash->table);
+            cur = end - 1;
+            hash->table[0] = *cur;
+        }
+
+        memmove(&entry[1], entry, (char *) cur - (char *) entry);
     }
-    if (table->dict)
-        xmlDictFree(table->dict);
-    xmlFree(table);
+
+    /*
+     * Populate entry
+     */
+    entry->key = copy;
+    entry->key2 = copy2;
+    entry->key3 = copy3;
+    entry->payload = payload;
+    /* OR with MAX_HASH_SIZE to make sure that the value is non-zero */
+    entry->hashValue = hashValue | MAX_HASH_SIZE;
+
+    hash->nbElems++;
+
+    return(1);
 }
 
 /**
  * xmlHashDefaultDeallocator:
- * @entry: the hash table entry
- * @name: the entry's name
+ * @entry: hash table entry
+ * @key: the entry's string key
  *
  * Free a hash table entry with xmlFree.
  */
 void
-xmlHashDefaultDeallocator(void *entry, const xmlChar *name ATTRIBUTE_UNUSED) {
+xmlHashDefaultDeallocator(void *entry, const xmlChar *key ATTRIBUTE_UNUSED) {
     xmlFree(entry);
 }
 
 /**
- * xmlHashAddEntry:
- * @table: the hash table
- * @name: the name of the userdata
- * @userdata: a pointer to the userdata
+ * xmlHashAdd:
+ * @hash: hash table
+ * @key: string key
+ * @payload: pointer to the payload
+ *
+ * Add a hash table entry. If an entry with this key already exists,
+ * payload will not be updated and 0 is returned. This return value
+ * can't be distinguished from out-of-memory errors, so this function
+ * should be used with care.
  *
- * Add the @userdata to the hash @table. This can later be retrieved
- * by using the @name. Duplicate names generate errors.
+ * Available since 2.13.0.
  *
- * Returns 0 the addition succeeded and -1 in case of error.
+ * Returns 1 on success, 0 if an entry exists and -1 in case of error.
  */
 int
-xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata) {
-    return(xmlHashAddEntry3(table, name, NULL, NULL, userdata));
+xmlHashAdd(xmlHashTablePtr hash, const xmlChar *key, void *payload) {
+    return(xmlHashUpdateInternal(hash, key, NULL, NULL, payload, NULL, 0));
 }
 
 /**
- * xmlHashAddEntry2:
- * @table: the hash table
- * @name: the name of the userdata
- * @name2: a second name of the userdata
- * @userdata: a pointer to the userdata
+ * xmlHashAdd2:
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ * @payload: pointer to the payload
  *
- * Add the @userdata to the hash @table. This can later be retrieved
- * by using the (@name, @name2) tuple. Duplicate tuples generate errors.
+ * Add a hash table entry with two strings as key.
  *
- * Returns 0 the addition succeeded and -1 in case of error.
- */
-int
-xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name,
-	        const xmlChar *name2, void *userdata) {
-    return(xmlHashAddEntry3(table, name, name2, NULL, userdata));
-}
-
-/**
- * xmlHashUpdateEntry:
- * @table: the hash table
- * @name: the name of the userdata
- * @userdata: a pointer to the userdata
- * @f: the deallocator function for replaced item (if any)
+ * See xmlHashAdd.
  *
- * Add the @userdata to the hash @table. This can later be retrieved
- * by using the @name. Existing entry for this @name will be removed
- * and freed with @f if found.
+ * Available since 2.13.0.
  *
- * Returns 0 the addition succeeded and -1 in case of error.
+ * Returns 1 on success, 0 if an entry exists and -1 in case of error.
  */
 int
-xmlHashUpdateEntry(xmlHashTablePtr table, const xmlChar *name,
-	           void *userdata, xmlHashDeallocator f) {
-    return(xmlHashUpdateEntry3(table, name, NULL, NULL, userdata, f));
+xmlHashAdd2(xmlHashTablePtr hash, const xmlChar *key,
+                 const xmlChar *key2, void *payload) {
+    return(xmlHashUpdateInternal(hash, key, key2, NULL, payload, NULL, 0));
 }
 
 /**
- * xmlHashUpdateEntry2:
- * @table: the hash table
- * @name: the name of the userdata
- * @name2: a second name of the userdata
- * @userdata: a pointer to the userdata
- * @f: the deallocator function for replaced item (if any)
+ * xmlHashAdd3:
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ * @key3: third string key
+ * @payload: pointer to the payload
  *
- * Add the @userdata to the hash @table. This can later be retrieved
- * by using the (@name, @name2) tuple. Existing entry for this tuple will
- * be removed and freed with @f if found.
+ * Add a hash table entry with three strings as key.
  *
- * Returns 0 the addition succeeded and -1 in case of error.
+ * See xmlHashAdd.
+ *
+ * Available since 2.13.0.
+ *
+ * Returns 1 on success, 0 if an entry exists and -1 in case of error.
  */
 int
-xmlHashUpdateEntry2(xmlHashTablePtr table, const xmlChar *name,
-	           const xmlChar *name2, void *userdata,
-		   xmlHashDeallocator f) {
-    return(xmlHashUpdateEntry3(table, name, name2, NULL, userdata, f));
+xmlHashAdd3(xmlHashTablePtr hash, const xmlChar *key,
+                 const xmlChar *key2, const xmlChar *key3,
+                 void *payload) {
+    return(xmlHashUpdateInternal(hash, key, key2, key3, payload, NULL, 0));
 }
 
 /**
- * xmlHashLookup:
- * @table: the hash table
- * @name: the name of the userdata
+ * xmlHashAddEntry:
+ * @hash: hash table
+ * @key: string key
+ * @payload: pointer to the payload
+ *
+ * Add a hash table entry. If an entry with this key already exists,
+ * payload will not be updated and -1 is returned. This return value
+ * can't be distinguished from out-of-memory errors, so this function
+ * should be used with care.
  *
- * Find the userdata specified by the @name.
+ * NOTE: This function doesn't allow to distinguish malloc failures from
+ *       existing entries. Use xmlHashAdd instead.
  *
- * Returns the pointer to the userdata
+ * Returns 0 on success and -1 in case of error.
  */
-void *
-xmlHashLookup(xmlHashTablePtr table, const xmlChar *name) {
-    return(xmlHashLookup3(table, name, NULL, NULL));
+int
+xmlHashAddEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload) {
+    int res = xmlHashUpdateInternal(hash, key, NULL, NULL, payload, NULL, 0);
+
+    if (res == 0)
+        res = -1;
+    else if (res == 1)
+        res = 0;
+
+    return(res);
 }
 
 /**
- * xmlHashLookup2:
- * @table: the hash table
- * @name: the name of the userdata
- * @name2: a second name of the userdata
+ * xmlHashAddEntry2:
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ * @payload: pointer to the payload
+ *
+ * Add a hash table entry with two strings as key.
  *
- * Find the userdata specified by the (@name, @name2) tuple.
+ * See xmlHashAddEntry.
  *
- * Returns the pointer to the userdata
+ * Returns 0 on success and -1 in case of error.
  */
-void *
-xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name,
-	      const xmlChar *name2) {
-    return(xmlHashLookup3(table, name, name2, NULL));
+int
+xmlHashAddEntry2(xmlHashTablePtr hash, const xmlChar *key,
+                 const xmlChar *key2, void *payload) {
+    int res = xmlHashUpdateInternal(hash, key, key2, NULL, payload, NULL, 0);
+
+    if (res == 0)
+        res = -1;
+    else if (res == 1)
+        res = 0;
+
+    return(res);
 }
 
 /**
- * xmlHashQLookup:
- * @table: the hash table
- * @prefix: the prefix of the userdata
- * @name: the name of the userdata
+ * xmlHashAddEntry3:
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ * @key3: third string key
+ * @payload: pointer to the payload
  *
- * Find the userdata specified by the QName @prefix:@name/@name.
+ * Add a hash table entry with three strings as key.
  *
- * Returns the pointer to the userdata
+ * See xmlHashAddEntry.
+ *
+ * Returns 0 on success and -1 in case of error.
  */
-void *
-xmlHashQLookup(xmlHashTablePtr table, const xmlChar *prefix,
-               const xmlChar *name) {
-    return(xmlHashQLookup3(table, prefix, name, NULL, NULL, NULL, NULL));
+int
+xmlHashAddEntry3(xmlHashTablePtr hash, const xmlChar *key,
+                 const xmlChar *key2, const xmlChar *key3,
+                 void *payload) {
+    int res = xmlHashUpdateInternal(hash, key, key2, key3, payload, NULL, 0);
+
+    if (res == 0)
+        res = -1;
+    else if (res == 1)
+        res = 0;
+
+    return(res);
 }
 
 /**
- * xmlHashQLookup2:
- * @table: the hash table
- * @prefix: the prefix of the userdata
- * @name: the name of the userdata
- * @prefix2: the second prefix of the userdata
- * @name2: a second name of the userdata
+ * xmlHashUpdateEntry:
+ * @hash: hash table
+ * @key: string key
+ * @payload: pointer to the payload
+ * @dealloc: deallocator function for replaced item or NULL
  *
- * Find the userdata specified by the QNames tuple
+ * Add a hash table entry. If an entry with this key already exists,
+ * the old payload will be freed and updated with the new value.
  *
- * Returns the pointer to the userdata
+ * Returns 0 in case of success, -1 if a memory allocation failed.
  */
-void *
-xmlHashQLookup2(xmlHashTablePtr table, const xmlChar *prefix,
-                const xmlChar *name, const xmlChar *prefix2,
-	        const xmlChar *name2) {
-    return(xmlHashQLookup3(table, prefix, name, prefix2, name2, NULL, NULL));
+int
+xmlHashUpdateEntry(xmlHashTablePtr hash, const xmlChar *key,
+                   void *payload, xmlHashDeallocator dealloc) {
+    int res = xmlHashUpdateInternal(hash, key, NULL, NULL, payload,
+                                    dealloc, 1);
+
+    if (res == 1)
+        res = 0;
+
+    return(res);
 }
 
 /**
- * xmlHashAddEntry3:
- * @table: the hash table
- * @name: the name of the userdata
- * @name2: a second name of the userdata
- * @name3: a third name of the userdata
- * @userdata: a pointer to the userdata
+ * xmlHashUpdateEntry2:
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ * @payload: pointer to the payload
+ * @dealloc: deallocator function for replaced item or NULL
  *
- * Add the @userdata to the hash @table. This can later be retrieved
- * by using the tuple (@name, @name2, @name3). Duplicate entries generate
- * errors.
+ * Add a hash table entry with two strings as key.
  *
- * Returns 0 the addition succeeded and -1 in case of error.
+ * See xmlHashUpdateEntry.
+ *
+ * Returns 0 on success and -1 in case of error.
  */
 int
-xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
-	         const xmlChar *name2, const xmlChar *name3,
-		 void *userdata) {
-    unsigned long key, len = 0;
-    xmlHashEntryPtr entry;
-    xmlHashEntryPtr insert;
-
-    if ((table == NULL) || (name == NULL))
-	return(-1);
-
-    /*
-     * If using a dict internalize if needed
-     */
-    if (table->dict) {
-        if (!xmlDictOwns(table->dict, name)) {
-	    name = xmlDictLookup(table->dict, name, -1);
-	    if (name == NULL)
-	        return(-1);
-	}
-        if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) {
-	    name2 = xmlDictLookup(table->dict, name2, -1);
-	    if (name2 == NULL)
-	        return(-1);
-	}
-        if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) {
-	    name3 = xmlDictLookup(table->dict, name3, -1);
-	    if (name3 == NULL)
-	        return(-1);
-	}
-    }
-
-    /*
-     * Check for duplicate and insertion location.
-     */
-    key = xmlHashComputeKey(table, name, name2, name3);
-    if (table->table[key].valid == 0) {
-	insert = NULL;
-    } else {
-        if (table->dict) {
-	    for (insert = &(table->table[key]); insert->next != NULL;
-		 insert = insert->next) {
-		if ((insert->name == name) &&
-		    (insert->name2 == name2) &&
-		    (insert->name3 == name3))
-		    return(-1);
-		len++;
-	    }
-	    if ((insert->name == name) &&
-		(insert->name2 == name2) &&
-		(insert->name3 == name3))
-		return(-1);
-	} else {
-	    for (insert = &(table->table[key]); insert->next != NULL;
-		 insert = insert->next) {
-		if ((xmlStrEqual(insert->name, name)) &&
-		    (xmlStrEqual(insert->name2, name2)) &&
-		    (xmlStrEqual(insert->name3, name3)))
-		    return(-1);
-		len++;
-	    }
-	    if ((xmlStrEqual(insert->name, name)) &&
-		(xmlStrEqual(insert->name2, name2)) &&
-		(xmlStrEqual(insert->name3, name3)))
-		return(-1);
-	}
-    }
-
-    if (insert == NULL) {
-	entry = &(table->table[key]);
-    } else {
-	entry = xmlMalloc(sizeof(xmlHashEntry));
-	if (entry == NULL)
-	     return(-1);
-    }
-
-    if (table->dict != NULL) {
-        entry->name = (xmlChar *) name;
-        entry->name2 = (xmlChar *) name2;
-        entry->name3 = (xmlChar *) name3;
-    } else {
-	entry->name = xmlStrdup(name);
-	entry->name2 = xmlStrdup(name2);
-	entry->name3 = xmlStrdup(name3);
-    }
-    entry->payload = userdata;
-    entry->next = NULL;
-    entry->valid = 1;
+xmlHashUpdateEntry2(xmlHashTablePtr hash, const xmlChar *key,
+                   const xmlChar *key2, void *payload,
+                   xmlHashDeallocator dealloc) {
+    int res = xmlHashUpdateInternal(hash, key, key2, NULL, payload,
+                                    dealloc, 1);
 
+    if (res == 1)
+        res = 0;
 
-    if (insert != NULL)
-	insert->next = entry;
-
-    table->nbElems++;
-
-    if (len > MAX_HASH_LEN)
-	xmlHashGrow(table, MAX_HASH_LEN * table->size);
-
-    return(0);
+    return(res);
 }
 
 /**
  * xmlHashUpdateEntry3:
- * @table: the hash table
- * @name: the name of the userdata
- * @name2: a second name of the userdata
- * @name3: a third name of the userdata
- * @userdata: a pointer to the userdata
- * @f: the deallocator function for replaced item (if any)
- *
- * Add the @userdata to the hash @table. This can later be retrieved
- * by using the tuple (@name, @name2, @name3). Existing entry for this tuple
- * will be removed and freed with @f if found.
- *
- * Returns 0 the addition succeeded and -1 in case of error.
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ * @key3: third string key
+ * @payload: pointer to the payload
+ * @dealloc: deallocator function for replaced item or NULL
+ *
+ * Add a hash table entry with three strings as key.
+ *
+ * See xmlHashUpdateEntry.
+ *
+ * Returns 0 on success and -1 in case of error.
  */
 int
-xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name,
-	           const xmlChar *name2, const xmlChar *name3,
-		   void *userdata, xmlHashDeallocator f) {
-    unsigned long key;
-    xmlHashEntryPtr entry;
-    xmlHashEntryPtr insert;
-
-    if ((table == NULL) || name == NULL)
-	return(-1);
+xmlHashUpdateEntry3(xmlHashTablePtr hash, const xmlChar *key,
+                   const xmlChar *key2, const xmlChar *key3,
+                   void *payload, xmlHashDeallocator dealloc) {
+    int res = xmlHashUpdateInternal(hash, key, key2, key3, payload,
+                                    dealloc, 1);
 
-    /*
-     * If using a dict internalize if needed
-     */
-    if (table->dict) {
-        if (!xmlDictOwns(table->dict, name)) {
-	    name = xmlDictLookup(table->dict, name, -1);
-	    if (name == NULL)
-	        return(-1);
-	}
-        if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) {
-	    name2 = xmlDictLookup(table->dict, name2, -1);
-	    if (name2 == NULL)
-	        return(-1);
-	}
-        if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) {
-	    name3 = xmlDictLookup(table->dict, name3, -1);
-	    if (name3 == NULL)
-	        return(-1);
-	}
-    }
+    if (res == 1)
+        res = 0;
 
-    /*
-     * Check for duplicate and insertion location.
-     */
-    key = xmlHashComputeKey(table, name, name2, name3);
-    if (table->table[key].valid == 0) {
-	insert = NULL;
-    } else {
-        if (table ->dict) {
-	    for (insert = &(table->table[key]); insert->next != NULL;
-		 insert = insert->next) {
-		if ((insert->name == name) &&
-		    (insert->name2 == name2) &&
-		    (insert->name3 == name3)) {
-		    if (f)
-			f(insert->payload, insert->name);
-		    insert->payload = userdata;
-		    return(0);
-		}
-	    }
-	    if ((insert->name == name) &&
-		(insert->name2 == name2) &&
-		(insert->name3 == name3)) {
-		if (f)
-		    f(insert->payload, insert->name);
-		insert->payload = userdata;
-		return(0);
-	    }
-	} else {
-	    for (insert = &(table->table[key]); insert->next != NULL;
-		 insert = insert->next) {
-		if ((xmlStrEqual(insert->name, name)) &&
-		    (xmlStrEqual(insert->name2, name2)) &&
-		    (xmlStrEqual(insert->name3, name3))) {
-		    if (f)
-			f(insert->payload, insert->name);
-		    insert->payload = userdata;
-		    return(0);
-		}
-	    }
-	    if ((xmlStrEqual(insert->name, name)) &&
-		(xmlStrEqual(insert->name2, name2)) &&
-		(xmlStrEqual(insert->name3, name3))) {
-		if (f)
-		    f(insert->payload, insert->name);
-		insert->payload = userdata;
-		return(0);
-	    }
-	}
-    }
+    return(res);
+}
 
-    if (insert == NULL) {
-	entry =  &(table->table[key]);
-    } else {
-	entry = xmlMalloc(sizeof(xmlHashEntry));
-	if (entry == NULL)
-	     return(-1);
-    }
+/**
+ * xmlHashLookup:
+ * @hash: hash table
+ * @key: string key
+ *
+ * Find the entry specified by @key.
+ *
+ * Returns a pointer to the payload or NULL if no entry was found.
+ */
+void *
+xmlHashLookup(xmlHashTablePtr hash, const xmlChar *key) {
+    return(xmlHashLookup3(hash, key, NULL, NULL));
+}
 
-    if (table->dict != NULL) {
-        entry->name = (xmlChar *) name;
-        entry->name2 = (xmlChar *) name2;
-        entry->name3 = (xmlChar *) name3;
-    } else {
-	entry->name = xmlStrdup(name);
-	entry->name2 = xmlStrdup(name2);
-	entry->name3 = xmlStrdup(name3);
-    }
-    entry->payload = userdata;
-    entry->next = NULL;
-    entry->valid = 1;
-    table->nbElems++;
+/**
+ * xmlHashLookup2:
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ *
+ * Find the payload specified by the (@key, @key2) tuple.
+ *
+ * Returns a pointer to the payload or NULL if no entry was found.
+ */
+void *
+xmlHashLookup2(xmlHashTablePtr hash, const xmlChar *key,
+              const xmlChar *key2) {
+    return(xmlHashLookup3(hash, key, key2, NULL));
+}
 
+/**
+ * xmlHashQLookup:
+ * @hash: hash table
+ * @prefix: prefix of the string key
+ * @name: local name of the string key
+ *
+ * Find the payload specified by the QName @prefix:@name or @name.
+ *
+ * Returns a pointer to the payload or NULL if no entry was found.
+ */
+void *
+xmlHashQLookup(xmlHashTablePtr hash, const xmlChar *prefix,
+               const xmlChar *name) {
+    return(xmlHashQLookup3(hash, prefix, name, NULL, NULL, NULL, NULL));
+}
 
-    if (insert != NULL) {
-	insert->next = entry;
-    }
-    return(0);
+/**
+ * xmlHashQLookup2:
+ * @hash: hash table
+ * @prefix: first prefix
+ * @name: first local name
+ * @prefix2: second prefix
+ * @name2: second local name
+ *
+ * Find the payload specified by the QNames tuple.
+ *
+ * Returns a pointer to the payload or NULL if no entry was found.
+ */
+void *
+xmlHashQLookup2(xmlHashTablePtr hash, const xmlChar *prefix,
+                const xmlChar *name, const xmlChar *prefix2,
+                const xmlChar *name2) {
+    return(xmlHashQLookup3(hash, prefix, name, prefix2, name2, NULL, NULL));
 }
 
 /**
  * xmlHashLookup3:
- * @table: the hash table
- * @name: the name of the userdata
- * @name2: a second name of the userdata
- * @name3: a third name of the userdata
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ * @key3: third string key
  *
- * Find the userdata specified by the (@name, @name2, @name3) tuple.
+ * Find the payload specified by the (@key, @key2, @key3) tuple.
  *
- * Returns the a pointer to the userdata
+ * Returns a pointer to the payload or NULL if no entry was found.
  */
 void *
-xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name,
-	       const xmlChar *name2, const xmlChar *name3) {
-    unsigned long key;
-    xmlHashEntryPtr entry;
+xmlHashLookup3(xmlHashTablePtr hash, const xmlChar *key,
+               const xmlChar *key2, const xmlChar *key3) {
+    const xmlHashEntry *entry;
+    unsigned hashValue;
+    int found;
 
-    if (table == NULL)
-	return(NULL);
-    if (name == NULL)
-	return(NULL);
-    key = xmlHashComputeKey(table, name, name2, name3);
-    if (table->table[key].valid == 0)
-	return(NULL);
-    if (table->dict) {
-	for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
-	    if ((entry->name == name) &&
-		(entry->name2 == name2) &&
-		(entry->name3 == name3))
-		return(entry->payload);
-	}
-    }
-    for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
-	if ((xmlStrEqual(entry->name, name)) &&
-	    (xmlStrEqual(entry->name2, name2)) &&
-	    (xmlStrEqual(entry->name3, name3)))
-	    return(entry->payload);
-    }
+    if ((hash == NULL) || (hash->size == 0) || (key == NULL))
+        return(NULL);
+    hashValue = xmlHashValue(hash->randomSeed, key, key2, key3, NULL);
+    entry = xmlHashFindEntry(hash, key, key2, key3, hashValue, &found);
+    if (found)
+        return(entry->payload);
     return(NULL);
 }
 
 /**
  * xmlHashQLookup3:
- * @table: the hash table
- * @prefix: the prefix of the userdata
- * @name: the name of the userdata
- * @prefix2: the second prefix of the userdata
- * @name2: a second name of the userdata
- * @prefix3: the third prefix of the userdata
- * @name3: a third name of the userdata
+ * @hash: hash table
+ * @prefix: first prefix
+ * @name: first local name
+ * @prefix2: second prefix
+ * @name2: second local name
+ * @prefix3: third prefix
+ * @name3: third local name
  *
- * Find the userdata specified by the (@name, @name2, @name3) tuple.
+ * Find the payload specified by the QNames tuple.
  *
- * Returns the a pointer to the userdata
+ * Returns a pointer to the payload or NULL if no entry was found.
  */
+ATTRIBUTE_NO_SANITIZE_INTEGER
 void *
-xmlHashQLookup3(xmlHashTablePtr table,
+xmlHashQLookup3(xmlHashTablePtr hash,
                 const xmlChar *prefix, const xmlChar *name,
-		const xmlChar *prefix2, const xmlChar *name2,
-		const xmlChar *prefix3, const xmlChar *name3) {
-    unsigned long key;
-    xmlHashEntryPtr entry;
+                const xmlChar *prefix2, const xmlChar *name2,
+                const xmlChar *prefix3, const xmlChar *name3) {
+    const xmlHashEntry *entry;
+    unsigned hashValue, mask, pos, displ;
 
-    if (table == NULL)
-	return(NULL);
-    if (name == NULL)
-	return(NULL);
-    key = xmlHashComputeQKey(table, prefix, name, prefix2,
-                             name2, prefix3, name3);
-    if (table->table[key].valid == 0)
-	return(NULL);
-    for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
-	if ((xmlStrQEqual(prefix, name, entry->name)) &&
-	    (xmlStrQEqual(prefix2, name2, entry->name2)) &&
-	    (xmlStrQEqual(prefix3, name3, entry->name3)))
-	    return(entry->payload);
+    if ((hash == NULL) || (hash->size == 0) || (name == NULL))
+        return(NULL);
+
+    hashValue = xmlHashQNameValue(hash->randomSeed, prefix, name, prefix2,
+                                  name2, prefix3, name3);
+    mask = hash->size - 1;
+    pos = hashValue & mask;
+    entry = &hash->table[pos];
+
+    if (entry->hashValue != 0) {
+        displ = 0;
+        hashValue |= MAX_HASH_SIZE;
+
+        do {
+            if ((hashValue == entry->hashValue) &&
+                (xmlStrQEqual(prefix, name, entry->key)) &&
+                (xmlStrQEqual(prefix2, name2, entry->key2)) &&
+                (xmlStrQEqual(prefix3, name3, entry->key3)))
+                return(entry->payload);
+
+            displ++;
+            pos++;
+            entry++;
+            if ((pos & mask) == 0)
+                entry = hash->table;
+        } while ((entry->hashValue != 0) &&
+                 (((pos - entry->hashValue) & mask) >= displ));
     }
+
     return(NULL);
 }
 
 typedef struct {
-    xmlHashScanner hashscanner;
+    xmlHashScanner scan;
     void *data;
 } stubData;
 
 static void
-stubHashScannerFull (void *payload, void *data, const xmlChar *name,
-                     const xmlChar *name2 ATTRIBUTE_UNUSED,
-		     const xmlChar *name3 ATTRIBUTE_UNUSED) {
-    stubData *stubdata = (stubData *) data;
-    stubdata->hashscanner (payload, stubdata->data, (xmlChar *) name);
+stubHashScannerFull(void *payload, void *data, const xmlChar *key,
+                    const xmlChar *key2 ATTRIBUTE_UNUSED,
+                    const xmlChar *key3 ATTRIBUTE_UNUSED) {
+    stubData *sdata = (stubData *) data;
+    sdata->scan(payload, sdata->data, key);
 }
 
 /**
  * xmlHashScan:
- * @table: the hash table
- * @f:  the scanner function for items in the hash
- * @data:  extra data passed to f
+ * @hash: hash table
+ * @scan: scanner function for items in the hash
+ * @data: extra data passed to @scan
  *
- * Scan the hash @table and applied @f to each value.
+ * Scan the hash @table and apply @scan to each value.
  */
 void
-xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data) {
-    stubData stubdata;
-    stubdata.data = data;
-    stubdata.hashscanner = f;
-    xmlHashScanFull (table, stubHashScannerFull, &stubdata);
+xmlHashScan(xmlHashTablePtr hash, xmlHashScanner scan, void *data) {
+    stubData sdata;
+    sdata.data = data;
+    sdata.scan = scan;
+    xmlHashScanFull(hash, stubHashScannerFull, &sdata);
 }
 
 /**
  * xmlHashScanFull:
- * @table: the hash table
- * @f:  the scanner function for items in the hash
- * @data:  extra data passed to f
+ * @hash: hash table
+ * @scan: scanner function for items in the hash
+ * @data: extra data passed to @scan
  *
- * Scan the hash @table and applied @f to each value.
+ * Scan the hash @table and apply @scan to each value.
  */
 void
-xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data) {
-    int i, nb;
-    xmlHashEntryPtr iter;
-    xmlHashEntryPtr next;
+xmlHashScanFull(xmlHashTablePtr hash, xmlHashScannerFull scan, void *data) {
+    const xmlHashEntry *entry, *end;
+    xmlHashEntry old;
+    unsigned i;
 
-    if (table == NULL)
-	return;
-    if (f == NULL)
-	return;
-
-    if (table->table) {
-	for(i = 0; i < table->size; i++) {
-	    if (table->table[i].valid == 0)
-		continue;
-	    iter = &(table->table[i]);
-	    while (iter) {
-		next = iter->next;
-                nb = table->nbElems;
-		if ((f != NULL) && (iter->payload != NULL))
-		    f(iter->payload, data, iter->name,
-		      iter->name2, iter->name3);
-                if (nb != table->nbElems) {
-                    /* table was modified by the callback, be careful */
-                    if (iter == &(table->table[i])) {
-                        if (table->table[i].valid == 0)
-                            iter = NULL;
-                        if (table->table[i].next != next)
-			    iter = &(table->table[i]);
-                    } else
-		        iter = next;
-                } else
-		    iter = next;
-	    }
-	}
+    if ((hash == NULL) || (hash->size == 0) || (scan == NULL))
+        return;
+
+    /*
+     * We must handle the case that a scanned entry is removed when executing
+     * the callback (xmlCleanSpecialAttr and possibly other places).
+     *
+     * Find the start of a probe sequence to avoid scanning entries twice if
+     * a deletion happens.
+     */
+    entry = hash->table;
+    end = &hash->table[hash->size];
+    while (entry->hashValue != 0) {
+        if (++entry >= end)
+            entry = hash->table;
+    }
+
+    for (i = 0; i < hash->size; i++) {
+        if ((entry->hashValue != 0) && (entry->payload != NULL)) {
+            /*
+             * Make sure to rescan after a possible deletion.
+             */
+            do {
+                old = *entry;
+                scan(entry->payload, data, entry->key, entry->key2, entry->key3);
+            } while ((entry->hashValue != 0) &&
+                     (entry->payload != NULL) &&
+                     ((entry->key != old.key) ||
+                      (entry->key2 != old.key2) ||
+                      (entry->key3 != old.key3)));
+        }
+        if (++entry >= end)
+            entry = hash->table;
     }
 }
 
 /**
  * xmlHashScan3:
- * @table: the hash table
- * @name: the name of the userdata or NULL
- * @name2: a second name of the userdata or NULL
- * @name3: a third name of the userdata or NULL
- * @f:  the scanner function for items in the hash
- * @data:  extra data passed to f
- *
- * Scan the hash @table and applied @f to each value matching
- * (@name, @name2, @name3) tuple. If one of the names is null,
+ * @hash: hash table
+ * @key: first string key or NULL
+ * @key2: second string key or NULL
+ * @key3: third string key or NULL
+ * @scan: scanner function for items in the hash
+ * @data: extra data passed to @scan
+ *
+ * Scan the hash @table and apply @scan to each value matching
+ * (@key, @key2, @key3) tuple. If one of the keys is null,
  * the comparison is considered to match.
  */
 void
-xmlHashScan3(xmlHashTablePtr table, const xmlChar *name,
-	     const xmlChar *name2, const xmlChar *name3,
-	     xmlHashScanner f, void *data) {
-    stubData stubdata;
-    stubdata.data = data;
-    stubdata.hashscanner = f;
-    xmlHashScanFull3(table, name, name2, name3, stubHashScannerFull,
-                     &stubdata);
+xmlHashScan3(xmlHashTablePtr hash, const xmlChar *key,
+             const xmlChar *key2, const xmlChar *key3,
+             xmlHashScanner scan, void *data) {
+    stubData sdata;
+    sdata.data = data;
+    sdata.scan = scan;
+    xmlHashScanFull3(hash, key, key2, key3, stubHashScannerFull, &sdata);
 }
 
 /**
  * xmlHashScanFull3:
- * @table: the hash table
- * @name: the name of the userdata or NULL
- * @name2: a second name of the userdata or NULL
- * @name3: a third name of the userdata or NULL
- * @f:  the scanner function for items in the hash
- * @data:  extra data passed to f
- *
- * Scan the hash @table and applied @f to each value matching
- * (@name, @name2, @name3) tuple. If one of the names is null,
+ * @hash: hash table
+ * @key: first string key or NULL
+ * @key2: second string key or NULL
+ * @key3: third string key or NULL
+ * @scan: scanner function for items in the hash
+ * @data: extra data passed to @scan
+ *
+ * Scan the hash @table and apply @scan to each value matching
+ * (@key, @key2, @key3) tuple. If one of the keys is null,
  * the comparison is considered to match.
  */
 void
-xmlHashScanFull3(xmlHashTablePtr table, const xmlChar *name,
-		 const xmlChar *name2, const xmlChar *name3,
-		 xmlHashScannerFull f, void *data) {
-    int i;
-    xmlHashEntryPtr iter;
-    xmlHashEntryPtr next;
+xmlHashScanFull3(xmlHashTablePtr hash, const xmlChar *key,
+                 const xmlChar *key2, const xmlChar *key3,
+                 xmlHashScannerFull scan, void *data) {
+    const xmlHashEntry *entry, *end;
+    xmlHashEntry old;
+    unsigned i;
 
-    if (table == NULL)
-	return;
-    if (f == NULL)
-	return;
-
-    if (table->table) {
-	for(i = 0; i < table->size; i++) {
-	    if (table->table[i].valid == 0)
-		continue;
-	    iter = &(table->table[i]);
-	    while (iter) {
-		next = iter->next;
-		if (((name == NULL) || (xmlStrEqual(name, iter->name))) &&
-		    ((name2 == NULL) || (xmlStrEqual(name2, iter->name2))) &&
-		    ((name3 == NULL) || (xmlStrEqual(name3, iter->name3))) &&
-		    (iter->payload != NULL)) {
-		    f(iter->payload, data, iter->name,
-		      iter->name2, iter->name3);
-		}
-		iter = next;
-	    }
-	}
+    if ((hash == NULL) || (hash->size == 0) || (scan == NULL))
+        return;
+
+    /*
+     * We must handle the case that a scanned entry is removed when executing
+     * the callback (xmlCleanSpecialAttr and possibly other places).
+     *
+     * Find the start of a probe sequence to avoid scanning entries twice if
+     * a deletion happens.
+     */
+    entry = hash->table;
+    end = &hash->table[hash->size];
+    while (entry->hashValue != 0) {
+        if (++entry >= end)
+            entry = hash->table;
+    }
+
+    for (i = 0; i < hash->size; i++) {
+        if ((entry->hashValue != 0) && (entry->payload != NULL)) {
+            /*
+             * Make sure to rescan after a possible deletion.
+             */
+            do {
+                if (((key != NULL) && (strcmp((const char *) key,
+                                              (const char *) entry->key) != 0)) ||
+                    ((key2 != NULL) && (!xmlFastStrEqual(key2, entry->key2))) ||
+                    ((key3 != NULL) && (!xmlFastStrEqual(key3, entry->key3))))
+                    break;
+                old = *entry;
+                scan(entry->payload, data, entry->key, entry->key2, entry->key3);
+            } while ((entry->hashValue != 0) &&
+                     (entry->payload != NULL) &&
+                     ((entry->key != old.key) ||
+                      (entry->key2 != old.key2) ||
+                      (entry->key3 != old.key3)));
+        }
+        if (++entry >= end)
+            entry = hash->table;
     }
 }
 
-/**
- * xmlHashCopy:
- * @table: the hash table
- * @f:  the copier function for items in the hash
+/*
+ * xmlHashCopySafe:
+ * @hash: hash table
+ * @copyFunc: copier function for items in the hash
+ * @deallocFunc: deallocation function in case of errors
  *
- * Scan the hash @table and applied @f to each value.
+ * Copy the hash table using @copyFunc to copy payloads.
  *
- * Returns the new table or NULL in case of error.
+ * Available since 2.13.0.
+ *
+ * Returns the new table or NULL if a memory allocation failed.
  */
 xmlHashTablePtr
-xmlHashCopy(xmlHashTablePtr table, xmlHashCopier f) {
-    int i;
-    xmlHashEntryPtr iter;
-    xmlHashEntryPtr next;
+xmlHashCopySafe(xmlHashTablePtr hash, xmlHashCopier copyFunc,
+                xmlHashDeallocator deallocFunc) {
+    const xmlHashEntry *entry, *end;
     xmlHashTablePtr ret;
 
-    if (table == NULL)
-	return(NULL);
-    if (f == NULL)
-	return(NULL);
+    if ((hash == NULL) || (copyFunc == NULL))
+        return(NULL);
 
-    ret = xmlHashCreate(table->size);
+    ret = xmlHashCreate(hash->size);
     if (ret == NULL)
         return(NULL);
 
-    if (table->table) {
-	for(i = 0; i < table->size; i++) {
-	    if (table->table[i].valid == 0)
-		continue;
-	    iter = &(table->table[i]);
-	    while (iter) {
-		next = iter->next;
-		xmlHashAddEntry3(ret, iter->name, iter->name2,
-			         iter->name3, f(iter->payload, iter->name));
-		iter = next;
-	    }
-	}
+    if (hash->size == 0)
+        return(ret);
+
+    end = &hash->table[hash->size];
+
+    for (entry = hash->table; entry < end; entry++) {
+        if (entry->hashValue != 0) {
+            void *copy;
+
+            copy = copyFunc(entry->payload, entry->key);
+            if (copy == NULL)
+                goto error;
+            if (xmlHashAdd3(ret, entry->key, entry->key2, entry->key3,
+                            copy) <= 0) {
+                if (deallocFunc != NULL)
+                    deallocFunc(copy, entry->key);
+                goto error;
+            }
+        }
     }
-    ret->nbElems = table->nbElems;
+
     return(ret);
+
+error:
+    xmlHashFree(ret, deallocFunc);
+    return(NULL);
+}
+
+/*
+ * xmlHashCopy:
+ * @hash: hash table
+ * @copy: copier function for items in the hash
+ *
+ * DEPRECATED: Leaks memory in error case.
+ *
+ * Copy the hash table using @copy to copy payloads.
+ *
+ * Returns the new table or NULL if a memory allocation failed.
+ */
+xmlHashTablePtr
+xmlHashCopy(xmlHashTablePtr hash, xmlHashCopier copy) {
+    return(xmlHashCopySafe(hash, copy, NULL));
 }
 
 /**
  * xmlHashSize:
- * @table: the hash table
+ * @hash: hash table
  *
- * Query the number of elements installed in the hash @table.
+ * Query the number of elements in the hash table.
  *
  * Returns the number of elements in the hash table or
- * -1 in case of error
+ * -1 in case of error.
  */
 int
-xmlHashSize(xmlHashTablePtr table) {
-    if (table == NULL)
-	return(-1);
-    return(table->nbElems);
+xmlHashSize(xmlHashTablePtr hash) {
+    if (hash == NULL)
+        return(-1);
+    return(hash->nbElems);
 }
 
 /**
  * xmlHashRemoveEntry:
- * @table: the hash table
- * @name: the name of the userdata
- * @f: the deallocator function for removed item (if any)
+ * @hash: hash table
+ * @key: string key
+ * @dealloc: deallocator function for removed item or NULL
  *
- * Find the userdata specified by the @name and remove
- * it from the hash @table. Existing userdata for this tuple will be removed
- * and freed with @f.
+ * Find the entry specified by the @key and remove it from the hash table.
+ * Payload will be freed with @dealloc.
  *
- * Returns 0 if the removal succeeded and -1 in case of error or not found.
+ * Returns 0 on success and -1 if no entry was found.
  */
-int xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name,
-		       xmlHashDeallocator f) {
-    return(xmlHashRemoveEntry3(table, name, NULL, NULL, f));
+int xmlHashRemoveEntry(xmlHashTablePtr hash, const xmlChar *key,
+                       xmlHashDeallocator dealloc) {
+    return(xmlHashRemoveEntry3(hash, key, NULL, NULL, dealloc));
 }
 
 /**
  * xmlHashRemoveEntry2:
- * @table: the hash table
- * @name: the name of the userdata
- * @name2: a second name of the userdata
- * @f: the deallocator function for removed item (if any)
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ * @dealloc: deallocator function for removed item or NULL
  *
- * Find the userdata specified by the (@name, @name2) tuple and remove
- * it from the hash @table. Existing userdata for this tuple will be removed
- * and freed with @f.
+ * Remove an entry with two strings as key.
  *
- * Returns 0 if the removal succeeded and -1 in case of error or not found.
+ * See xmlHashRemoveEntry.
+ *
+ * Returns 0 on success and -1 in case of error.
  */
 int
-xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name,
-			const xmlChar *name2, xmlHashDeallocator f) {
-    return(xmlHashRemoveEntry3(table, name, name2, NULL, f));
+xmlHashRemoveEntry2(xmlHashTablePtr hash, const xmlChar *key,
+                    const xmlChar *key2, xmlHashDeallocator dealloc) {
+    return(xmlHashRemoveEntry3(hash, key, key2, NULL, dealloc));
 }
 
 /**
  * xmlHashRemoveEntry3:
- * @table: the hash table
- * @name: the name of the userdata
- * @name2: a second name of the userdata
- * @name3: a third name of the userdata
- * @f: the deallocator function for removed item (if any)
+ * @hash: hash table
+ * @key: first string key
+ * @key2: second string key
+ * @key3: third string key
+ * @dealloc: deallocator function for removed item or NULL
+ *
+ * Remove an entry with three strings as key.
  *
- * Find the userdata specified by the (@name, @name2, @name3) tuple and remove
- * it from the hash @table. Existing userdata for this tuple will be removed
- * and freed with @f.
+ * See xmlHashRemoveEntry.
  *
- * Returns 0 if the removal succeeded and -1 in case of error or not found.
+ * Returns 0 on success and -1 in case of error.
  */
+ATTRIBUTE_NO_SANITIZE_INTEGER
 int
-xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name,
-    const xmlChar *name2, const xmlChar *name3, xmlHashDeallocator f) {
-    unsigned long key;
-    xmlHashEntryPtr entry;
-    xmlHashEntryPtr prev = NULL;
-
-    if (table == NULL || name == NULL)
+xmlHashRemoveEntry3(xmlHashTablePtr hash, const xmlChar *key,
+                    const xmlChar *key2, const xmlChar *key3,
+                    xmlHashDeallocator dealloc) {
+    xmlHashEntry *entry, *cur, *next;
+    unsigned hashValue, mask, pos, nextpos;
+    int found;
+
+    if ((hash == NULL) || (hash->size == 0) || (key == NULL))
         return(-1);
 
-    key = xmlHashComputeKey(table, name, name2, name3);
-    if (table->table[key].valid == 0) {
-        return(-1);
-    } else {
-        for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
-            if (xmlStrEqual(entry->name, name) &&
-                    xmlStrEqual(entry->name2, name2) &&
-                    xmlStrEqual(entry->name3, name3)) {
-                if ((f != NULL) && (entry->payload != NULL))
-                    f(entry->payload, entry->name);
-                entry->payload = NULL;
-		if (table->dict == NULL) {
-		    if(entry->name)
-			xmlFree(entry->name);
-		    if(entry->name2)
-			xmlFree(entry->name2);
-		    if(entry->name3)
-			xmlFree(entry->name3);
-		}
-                if(prev) {
-                    prev->next = entry->next;
-		    xmlFree(entry);
-		} else {
-		    if (entry->next == NULL) {
-			entry->valid = 0;
-		    } else {
-			entry = entry->next;
-			memcpy(&(table->table[key]), entry, sizeof(xmlHashEntry));
-			xmlFree(entry);
-		    }
-		}
-                table->nbElems--;
-                return(0);
-            }
-            prev = entry;
-        }
+    hashValue = xmlHashValue(hash->randomSeed, key, key2, key3, NULL);
+    entry = xmlHashFindEntry(hash, key, key2, key3, hashValue, &found);
+    if (!found)
         return(-1);
+
+    if ((dealloc != NULL) && (entry->payload != NULL))
+        dealloc(entry->payload, entry->key);
+    if (hash->dict == NULL) {
+        if (entry->key)
+            xmlFree(entry->key);
+        if (entry->key2)
+            xmlFree(entry->key2);
+        if (entry->key3)
+            xmlFree(entry->key3);
+    }
+
+    /*
+     * Find end of probe sequence. Entries at their initial probe
+     * position start a new sequence.
+     */
+    mask = hash->size - 1;
+    pos = entry - hash->table;
+    cur = entry;
+
+    while (1) {
+        nextpos = pos + 1;
+        next = cur + 1;
+        if ((nextpos & mask) == 0)
+            next = hash->table;
+
+        if ((next->hashValue == 0) ||
+            (((next->hashValue - nextpos) & mask) == 0))
+            break;
+
+        cur = next;
+        pos = nextpos;
+    }
+
+    /*
+     * Backward shift
+     */
+    next = entry + 1;
+
+    if (cur < entry) {
+        xmlHashEntry *end = &hash->table[hash->size];
+
+        memmove(entry, next, (char *) end - (char *) next);
+        entry = hash->table;
+        end[-1] = *entry;
+        next = entry + 1;
     }
+
+    memmove(entry, next, (char *) cur - (char *) entry);
+
+    /*
+     * Update entry
+     */
+    cur->hashValue = 0;
+
+    hash->nbElems--;
+
+    return(0);
 }
 
diff --git a/include/libxml/HTMLparser.h b/include/libxml/HTMLparser.h
index 1d4fec2f734375efe95363e268ae8618d660e2de..7be3d2b8a434ec7032faef1502a028865239bf23 100644
--- a/include/libxml/HTMLparser.h
+++ b/include/libxml/HTMLparser.h
@@ -80,90 +80,117 @@ struct _htmlEntityDesc {
     const char *desc;   /* the description */
 };
 
+#ifdef LIBXML_SAX1_ENABLED
+
+XML_DEPRECATED
+XMLPUBVAR const xmlSAXHandlerV1 htmlDefaultSAXHandler;
+
+#ifdef LIBXML_THREAD_ENABLED
+XML_DEPRECATED
+XMLPUBFUN const xmlSAXHandlerV1 *__htmlDefaultSAXHandler(void);
+#endif
+
+#endif /* LIBXML_SAX1_ENABLED */
+
 /*
  * There is only few public functions.
  */
-XMLPUBFUN const htmlElemDesc * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
+			htmlInitAutoClose	(void);
+XMLPUBFUN const htmlElemDesc *
 			htmlTagLookup	(const xmlChar *tag);
-XMLPUBFUN const htmlEntityDesc * XMLCALL
+XMLPUBFUN const htmlEntityDesc *
 			htmlEntityLookup(const xmlChar *name);
-XMLPUBFUN const htmlEntityDesc * XMLCALL
+XMLPUBFUN const htmlEntityDesc *
 			htmlEntityValueLookup(unsigned int value);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			htmlIsAutoClosed(htmlDocPtr doc,
 					 htmlNodePtr elem);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			htmlAutoCloseTag(htmlDocPtr doc,
 					 const xmlChar *name,
 					 htmlNodePtr elem);
-XMLPUBFUN const htmlEntityDesc * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN const htmlEntityDesc *
 			htmlParseEntityRef(htmlParserCtxtPtr ctxt,
 					 const xmlChar **str);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			htmlParseCharRef(htmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			htmlParseElement(htmlParserCtxtPtr ctxt);
 
-XMLPUBFUN htmlParserCtxtPtr XMLCALL
+XMLPUBFUN htmlParserCtxtPtr
 			htmlNewParserCtxt(void);
+XMLPUBFUN htmlParserCtxtPtr
+			htmlNewSAXParserCtxt(const htmlSAXHandler *sax,
+					     void *userData);
 
-XMLPUBFUN htmlParserCtxtPtr XMLCALL
+XMLPUBFUN htmlParserCtxtPtr
 			htmlCreateMemoryParserCtxt(const char *buffer,
 						   int size);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			htmlParseDocument(htmlParserCtxtPtr ctxt);
-XMLPUBFUN htmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN htmlDocPtr
 			htmlSAXParseDoc	(const xmlChar *cur,
 					 const char *encoding,
 					 htmlSAXHandlerPtr sax,
 					 void *userData);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 			htmlParseDoc	(const xmlChar *cur,
 					 const char *encoding);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlParserCtxtPtr
+			htmlCreateFileParserCtxt(const char *filename,
+	                                         const char *encoding);
+XML_DEPRECATED
+XMLPUBFUN htmlDocPtr
 			htmlSAXParseFile(const char *filename,
 					 const char *encoding,
 					 htmlSAXHandlerPtr sax,
 					 void *userData);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 			htmlParseFile	(const char *filename,
 					 const char *encoding);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			UTF8ToHtml	(unsigned char *out,
 					 int *outlen,
 					 const unsigned char *in,
 					 int *inlen);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			htmlEncodeEntities(unsigned char *out,
 					 int *outlen,
 					 const unsigned char *in,
 					 int *inlen, int quoteChar);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			htmlIsScriptAttribute(const xmlChar *name);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			htmlHandleOmittedElem(int val);
 
 #ifdef LIBXML_PUSH_ENABLED
 /**
  * Interfaces for the Push mode.
  */
-XMLPUBFUN htmlParserCtxtPtr XMLCALL
+XMLPUBFUN htmlParserCtxtPtr
 			htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax,
 						 void *user_data,
 						 const char *chunk,
 						 int size,
 						 const char *filename,
 						 xmlCharEncoding enc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			htmlParseChunk		(htmlParserCtxtPtr ctxt,
 						 const char *chunk,
 						 int size,
 						 int terminate);
 #endif /* LIBXML_PUSH_ENABLED */
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			htmlFreeParserCtxt	(htmlParserCtxtPtr ctxt);
 
 /*
@@ -188,63 +215,66 @@ typedef enum {
     HTML_PARSE_IGNORE_ENC=1<<21 /* ignore internal document encoding hint */
 } htmlParserOption;
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		htmlCtxtReset		(htmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		htmlCtxtUseOptions	(htmlParserCtxtPtr ctxt,
 					 int options);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlReadDoc		(const xmlChar *cur,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlReadFile		(const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlReadMemory		(const char *buffer,
 					 int size,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlReadFd		(int fd,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlReadIO		(xmlInputReadCallback ioread,
 					 xmlInputCloseCallback ioclose,
 					 void *ioctx,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
+		htmlCtxtParseDocument	(htmlParserCtxtPtr ctxt,
+					 xmlParserInputPtr input);
+XMLPUBFUN htmlDocPtr
 		htmlCtxtReadDoc		(xmlParserCtxtPtr ctxt,
 					 const xmlChar *cur,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlCtxtReadFile		(xmlParserCtxtPtr ctxt,
 					 const char *filename,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlCtxtReadMemory		(xmlParserCtxtPtr ctxt,
 					 const char *buffer,
 					 int size,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlCtxtReadFd		(xmlParserCtxtPtr ctxt,
 					 int fd,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlCtxtReadIO		(xmlParserCtxtPtr ctxt,
 					 xmlInputReadCallback ioread,
 					 xmlInputCloseCallback ioclose,
@@ -266,10 +296,10 @@ typedef enum {
 /* Using htmlElemDesc rather than name here, to emphasise the fact
    that otherwise there's a lookup overhead
 */
-XMLPUBFUN htmlStatus XMLCALL htmlAttrAllowed(const htmlElemDesc*, const xmlChar*, int) ;
-XMLPUBFUN int XMLCALL htmlElementAllowedHere(const htmlElemDesc*, const xmlChar*) ;
-XMLPUBFUN htmlStatus XMLCALL htmlElementStatusHere(const htmlElemDesc*, const htmlElemDesc*) ;
-XMLPUBFUN htmlStatus XMLCALL htmlNodeStatus(const htmlNodePtr, int) ;
+XMLPUBFUN htmlStatus htmlAttrAllowed(const htmlElemDesc*, const xmlChar*, int) ;
+XMLPUBFUN int htmlElementAllowedHere(const htmlElemDesc*, const xmlChar*) ;
+XMLPUBFUN htmlStatus htmlElementStatusHere(const htmlElemDesc*, const htmlElemDesc*) ;
+XMLPUBFUN htmlStatus htmlNodeStatus(htmlNodePtr, int) ;
 /**
  * htmlDefaultSubelement:
  * @elt: HTML element
diff --git a/include/libxml/HTMLtree.h b/include/libxml/HTMLtree.h
index c0e110330c5b03e38fcdd6bae5f131ac8a6b7d81..8e1ba90e9157b3bb7ad47b13f9ceae99cc748a13 100644
--- a/include/libxml/HTMLtree.h
+++ b/include/libxml/HTMLtree.h
@@ -59,73 +59,73 @@ extern "C" {
  */
 #define HTML_PI_NODE		XML_PI_NODE
 
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlNewDoc		(const xmlChar *URI,
 					 const xmlChar *ExternalID);
-XMLPUBFUN htmlDocPtr XMLCALL
+XMLPUBFUN htmlDocPtr
 		htmlNewDocNoDtD		(const xmlChar *URI,
 					 const xmlChar *ExternalID);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		htmlGetMetaEncoding	(htmlDocPtr doc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		htmlSetMetaEncoding	(htmlDocPtr doc,
 					 const xmlChar *encoding);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		htmlDocDumpMemory	(xmlDocPtr cur,
 					 xmlChar **mem,
 					 int *size);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		htmlDocDumpMemoryFormat	(xmlDocPtr cur,
 					 xmlChar **mem,
 					 int *size,
 					 int format);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		htmlDocDump		(FILE *f,
 					 xmlDocPtr cur);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		htmlSaveFile		(const char *filename,
 					 xmlDocPtr cur);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		htmlNodeDump		(xmlBufferPtr buf,
 					 xmlDocPtr doc,
 					 xmlNodePtr cur);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		htmlNodeDumpFile	(FILE *out,
 					 xmlDocPtr doc,
 					 xmlNodePtr cur);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		htmlNodeDumpFileFormat	(FILE *out,
 					 xmlDocPtr doc,
 					 xmlNodePtr cur,
 					 const char *encoding,
 					 int format);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		htmlSaveFileEnc		(const char *filename,
 					 xmlDocPtr cur,
 					 const char *encoding);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		htmlSaveFileFormat	(const char *filename,
 					 xmlDocPtr cur,
 					 const char *encoding,
 					 int format);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf,
 					 xmlDocPtr doc,
 					 xmlNodePtr cur,
 					 const char *encoding,
 					 int format);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		htmlDocContentDumpOutput(xmlOutputBufferPtr buf,
 					 xmlDocPtr cur,
 					 const char *encoding);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf,
 					 xmlDocPtr cur,
 					 const char *encoding,
 					 int format);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		htmlNodeDumpOutput	(xmlOutputBufferPtr buf,
 					 xmlDocPtr doc,
 					 xmlNodePtr cur,
@@ -133,7 +133,7 @@ XMLPUBFUN void XMLCALL
 
 #endif /* LIBXML_OUTPUT_ENABLED */
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		htmlIsBooleanAttr	(const xmlChar *name);
 
 
diff --git a/include/libxml/SAX.h b/include/libxml/SAX.h
index fa50568f2539fc954c2af0b788d13943509473aa..eea1057bfcc533cd2309a4de73767f004c97380f 100644
--- a/include/libxml/SAX.h
+++ b/include/libxml/SAX.h
@@ -12,8 +12,6 @@
 #ifndef __XML_SAX_H__
 #define __XML_SAX_H__
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <libxml/xmlversion.h>
 #include <libxml/parser.h>
 
@@ -23,61 +21,61 @@
 extern "C" {
 #endif
 XML_DEPRECATED
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		getPublicId			(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		getSystemId			(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		setDocumentLocator		(void *ctx,
 						 xmlSAXLocatorPtr loc);
 
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		getLineNumber			(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		getColumnNumber			(void *ctx);
 
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		isStandalone			(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		hasInternalSubset		(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		hasExternalSubset		(void *ctx);
 
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		internalSubset			(void *ctx,
 						 const xmlChar *name,
 						 const xmlChar *ExternalID,
 						 const xmlChar *SystemID);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		externalSubset			(void *ctx,
 						 const xmlChar *name,
 						 const xmlChar *ExternalID,
 						 const xmlChar *SystemID);
 XML_DEPRECATED
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN xmlEntityPtr
 		getEntity			(void *ctx,
 						 const xmlChar *name);
 XML_DEPRECATED
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN xmlEntityPtr
 		getParameterEntity		(void *ctx,
 						 const xmlChar *name);
 XML_DEPRECATED
-XMLPUBFUN xmlParserInputPtr XMLCALL
+XMLPUBFUN xmlParserInputPtr
 		resolveEntity			(void *ctx,
 						 const xmlChar *publicId,
 						 const xmlChar *systemId);
 
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		entityDecl			(void *ctx,
 						 const xmlChar *name,
 						 int type,
@@ -85,7 +83,7 @@ XMLPUBFUN void XMLCALL
 						 const xmlChar *systemId,
 						 xmlChar *content);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		attributeDecl			(void *ctx,
 						 const xmlChar *elem,
 						 const xmlChar *fullname,
@@ -94,19 +92,19 @@ XMLPUBFUN void XMLCALL
 						 const xmlChar *defaultValue,
 						 xmlEnumerationPtr tree);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		elementDecl			(void *ctx,
 						 const xmlChar *name,
 						 int type,
 						 xmlElementContentPtr content);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		notationDecl			(void *ctx,
 						 const xmlChar *name,
 						 const xmlChar *publicId,
 						 const xmlChar *systemId);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		unparsedEntityDecl		(void *ctx,
 						 const xmlChar *name,
 						 const xmlChar *publicId,
@@ -114,83 +112,83 @@ XMLPUBFUN void XMLCALL
 						 const xmlChar *notationName);
 
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		startDocument			(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		endDocument			(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		attribute			(void *ctx,
 						 const xmlChar *fullname,
 						 const xmlChar *value);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		startElement			(void *ctx,
 						 const xmlChar *fullname,
 						 const xmlChar **atts);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		endElement			(void *ctx,
 						 const xmlChar *name);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		reference			(void *ctx,
 						 const xmlChar *name);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		characters			(void *ctx,
 						 const xmlChar *ch,
 						 int len);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		ignorableWhitespace		(void *ctx,
 						 const xmlChar *ch,
 						 int len);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		processingInstruction		(void *ctx,
 						 const xmlChar *target,
 						 const xmlChar *data);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		globalNamespace			(void *ctx,
 						 const xmlChar *href,
 						 const xmlChar *prefix);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		setNamespace			(void *ctx,
 						 const xmlChar *name);
 XML_DEPRECATED
-XMLPUBFUN xmlNsPtr XMLCALL
+XMLPUBFUN xmlNsPtr
 		getNamespace			(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		checkNamespace			(void *ctx,
 						 xmlChar *nameSpace);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		namespaceDecl			(void *ctx,
 						 const xmlChar *href,
 						 const xmlChar *prefix);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		comment				(void *ctx,
 						 const xmlChar *value);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		cdataBlock			(void *ctx,
 						 const xmlChar *value,
 						 int len);
 
 #ifdef LIBXML_SAX1_ENABLED
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		initxmlDefaultSAXHandler	(xmlSAXHandlerV1 *hdlr,
 						 int warning);
 #ifdef LIBXML_HTML_ENABLED
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		inithtmlDefaultSAXHandler	(xmlSAXHandlerV1 *hdlr);
 #endif
 #endif /* LIBXML_SAX1_ENABLED */
diff --git a/include/libxml/SAX2.h b/include/libxml/SAX2.h
index 8e9b0b95fe5610de138f849ecd4d4a75d12e3c88..4c4ecce8e598b2bb2011f9daf6367bcc8f028b88 100644
--- a/include/libxml/SAX2.h
+++ b/include/libxml/SAX2.h
@@ -12,63 +12,61 @@
 #ifndef __XML_SAX2_H__
 #define __XML_SAX2_H__
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <libxml/xmlversion.h>
 #include <libxml/parser.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		xmlSAX2GetPublicId		(void *ctx);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		xmlSAX2GetSystemId		(void *ctx);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2SetDocumentLocator	(void *ctx,
 						 xmlSAXLocatorPtr loc);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSAX2GetLineNumber		(void *ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSAX2GetColumnNumber		(void *ctx);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSAX2IsStandalone		(void *ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSAX2HasInternalSubset	(void *ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSAX2HasExternalSubset	(void *ctx);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2InternalSubset		(void *ctx,
 						 const xmlChar *name,
 						 const xmlChar *ExternalID,
 						 const xmlChar *SystemID);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2ExternalSubset		(void *ctx,
 						 const xmlChar *name,
 						 const xmlChar *ExternalID,
 						 const xmlChar *SystemID);
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN xmlEntityPtr
 		xmlSAX2GetEntity		(void *ctx,
 						 const xmlChar *name);
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN xmlEntityPtr
 		xmlSAX2GetParameterEntity	(void *ctx,
 						 const xmlChar *name);
-XMLPUBFUN xmlParserInputPtr XMLCALL
+XMLPUBFUN xmlParserInputPtr
 		xmlSAX2ResolveEntity		(void *ctx,
 						 const xmlChar *publicId,
 						 const xmlChar *systemId);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2EntityDecl		(void *ctx,
 						 const xmlChar *name,
 						 int type,
 						 const xmlChar *publicId,
 						 const xmlChar *systemId,
 						 xmlChar *content);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2AttributeDecl		(void *ctx,
 						 const xmlChar *elem,
 						 const xmlChar *fullname,
@@ -76,38 +74,38 @@ XMLPUBFUN void XMLCALL
 						 int def,
 						 const xmlChar *defaultValue,
 						 xmlEnumerationPtr tree);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2ElementDecl		(void *ctx,
 						 const xmlChar *name,
 						 int type,
 						 xmlElementContentPtr content);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2NotationDecl		(void *ctx,
 						 const xmlChar *name,
 						 const xmlChar *publicId,
 						 const xmlChar *systemId);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2UnparsedEntityDecl	(void *ctx,
 						 const xmlChar *name,
 						 const xmlChar *publicId,
 						 const xmlChar *systemId,
 						 const xmlChar *notationName);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2StartDocument		(void *ctx);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2EndDocument		(void *ctx);
 #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
     defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2StartElement		(void *ctx,
 						 const xmlChar *fullname,
 						 const xmlChar **atts);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2EndElement		(void *ctx,
 						 const xmlChar *name);
 #endif /* LIBXML_SAX1_ENABLED or LIBXML_HTML_ENABLED or LIBXML_LEGACY_ENABLED */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2StartElementNs		(void *ctx,
 						 const xmlChar *localname,
 						 const xmlChar *prefix,
@@ -117,54 +115,55 @@ XMLPUBFUN void XMLCALL
 						 int nb_attributes,
 						 int nb_defaulted,
 						 const xmlChar **attributes);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2EndElementNs		(void *ctx,
 						 const xmlChar *localname,
 						 const xmlChar *prefix,
 						 const xmlChar *URI);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2Reference		(void *ctx,
 						 const xmlChar *name);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2Characters		(void *ctx,
 						 const xmlChar *ch,
 						 int len);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2IgnorableWhitespace	(void *ctx,
 						 const xmlChar *ch,
 						 int len);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2ProcessingInstruction	(void *ctx,
 						 const xmlChar *target,
 						 const xmlChar *data);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2Comment			(void *ctx,
 						 const xmlChar *value);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2CDataBlock		(void *ctx,
 						 const xmlChar *value,
 						 int len);
 
 #ifdef LIBXML_SAX1_ENABLED
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlSAXDefaultVersion		(int version);
 #endif /* LIBXML_SAX1_ENABLED */
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSAXVersion			(xmlSAXHandler *hdlr,
 						 int version);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2InitDefaultSAXHandler    (xmlSAXHandler *hdlr,
 						 int warning);
 #ifdef LIBXML_HTML_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		htmlDefaultSAXHandlerInit	(void);
 #endif
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlDefaultSAXHandlerInit	(void);
 #ifdef __cplusplus
 }
diff --git a/include/libxml/c14n.h b/include/libxml/c14n.h
index af93de63a4c3a8ae20709a343c909d14d7b95056..8ccd1cef632e920751aefa6a8b112e2be660bc2d 100644
--- a/include/libxml/c14n.h
+++ b/include/libxml/c14n.h
@@ -20,7 +20,6 @@
 #include <libxml/xmlversion.h>
 
 #ifdef LIBXML_C14N_ENABLED
-#ifdef LIBXML_OUTPUT_ENABLED
 
 #include <libxml/tree.h>
 #include <libxml/xpath.h>
@@ -40,18 +39,7 @@ extern "C" {
  *  a) default attributes (if any) are added to all nodes
  *  b) all character and parsed entity references are resolved
  * In order to achieve this in libxml2 the document MUST be loaded with
- * following global settings:
- *
- *    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
- *    xmlSubstituteEntitiesDefault(1);
- *
- * or corresponding parser context setting:
- *    xmlParserCtxtPtr ctxt;
- *
- *    ...
- *    ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
- *    ctxt->replaceEntities = 1;
- *    ...
+ * following options: XML_PARSE_DTDATTR | XML_PARSE_NOENT
  */
 
 /*
@@ -66,7 +54,7 @@ typedef enum {
     XML_C14N_1_1            = 2     /* C14N 1.1 spec */
 } xmlC14NMode;
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlC14NDocSaveTo	(xmlDocPtr doc,
 					 xmlNodeSetPtr nodes,
 					 int mode, /* a xmlC14NMode */
@@ -74,7 +62,7 @@ XMLPUBFUN int XMLCALL
 					 int with_comments,
 					 xmlOutputBufferPtr buf);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlC14NDocDumpMemory	(xmlDocPtr doc,
 					 xmlNodeSetPtr nodes,
 					 int mode, /* a xmlC14NMode */
@@ -82,7 +70,7 @@ XMLPUBFUN int XMLCALL
 					 int with_comments,
 					 xmlChar **doc_txt_ptr);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlC14NDocSave		(xmlDocPtr doc,
 					 xmlNodeSetPtr nodes,
 					 int mode, /* a xmlC14NMode */
@@ -109,7 +97,7 @@ typedef int (*xmlC14NIsVisibleCallback)	(void* user_data,
 					 xmlNodePtr node,
 					 xmlNodePtr parent);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlC14NExecute		(xmlDocPtr doc,
 					 xmlC14NIsVisibleCallback is_visible_callback,
 					 void* user_data,
@@ -122,7 +110,6 @@ XMLPUBFUN int XMLCALL
 }
 #endif /* __cplusplus */
 
-#endif /* LIBXML_OUTPUT_ENABLED */
 #endif /* LIBXML_C14N_ENABLED */
 #endif /* __XML_C14N_H__ */
 
diff --git a/include/libxml/catalog.h b/include/libxml/catalog.h
index 26b178dbbc9caecc2bd6ef4f50f661d0772e0735..02fa7ab2a03a95563cf4ccdf7b644c95af1b15c2 100644
--- a/include/libxml/catalog.h
+++ b/include/libxml/catalog.h
@@ -66,113 +66,113 @@ typedef xmlCatalog *xmlCatalogPtr;
 /*
  * Operations on a given catalog.
  */
-XMLPUBFUN xmlCatalogPtr XMLCALL
+XMLPUBFUN xmlCatalogPtr
 		xmlNewCatalog		(int sgml);
-XMLPUBFUN xmlCatalogPtr XMLCALL
+XMLPUBFUN xmlCatalogPtr
 		xmlLoadACatalog		(const char *filename);
-XMLPUBFUN xmlCatalogPtr XMLCALL
+XMLPUBFUN xmlCatalogPtr
 		xmlLoadSGMLSuperCatalog	(const char *filename);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlConvertSGMLCatalog	(xmlCatalogPtr catal);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlACatalogAdd		(xmlCatalogPtr catal,
 					 const xmlChar *type,
 					 const xmlChar *orig,
 					 const xmlChar *replace);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlACatalogRemove	(xmlCatalogPtr catal,
 					 const xmlChar *value);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlACatalogResolve	(xmlCatalogPtr catal,
 					 const xmlChar *pubID,
 	                                 const xmlChar *sysID);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlACatalogResolveSystem(xmlCatalogPtr catal,
 					 const xmlChar *sysID);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlACatalogResolvePublic(xmlCatalogPtr catal,
 					 const xmlChar *pubID);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlACatalogResolveURI	(xmlCatalogPtr catal,
 					 const xmlChar *URI);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlACatalogDump		(xmlCatalogPtr catal,
 					 FILE *out);
 #endif /* LIBXML_OUTPUT_ENABLED */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeCatalog		(xmlCatalogPtr catal);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlCatalogIsEmpty	(xmlCatalogPtr catal);
 
 /*
  * Global operations.
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlInitializeCatalog	(void);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlLoadCatalog		(const char *filename);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlLoadCatalogs		(const char *paths);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlCatalogCleanup	(void);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlCatalogDump		(FILE *out);
 #endif /* LIBXML_OUTPUT_ENABLED */
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlCatalogResolve	(const xmlChar *pubID,
 	                                 const xmlChar *sysID);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlCatalogResolveSystem	(const xmlChar *sysID);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlCatalogResolvePublic	(const xmlChar *pubID);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlCatalogResolveURI	(const xmlChar *URI);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlCatalogAdd		(const xmlChar *type,
 					 const xmlChar *orig,
 					 const xmlChar *replace);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlCatalogRemove	(const xmlChar *value);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlParseCatalogFile	(const char *filename);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlCatalogConvert	(void);
 
 /*
  * Strictly minimal interfaces for per-document catalogs used
  * by the parser.
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlCatalogFreeLocal	(void *catalogs);
-XMLPUBFUN void * XMLCALL
+XMLPUBFUN void *
 		xmlCatalogAddLocal	(void *catalogs,
 					 const xmlChar *URL);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlCatalogLocalResolve	(void *catalogs,
 					 const xmlChar *pubID,
 	                                 const xmlChar *sysID);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlCatalogLocalResolveURI(void *catalogs,
 					 const xmlChar *URI);
 /*
  * Preference settings.
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlCatalogSetDebug	(int level);
-XMLPUBFUN xmlCatalogPrefer XMLCALL
+XMLPUBFUN xmlCatalogPrefer
 		xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlCatalogSetDefaults	(xmlCatalogAllow allow);
-XMLPUBFUN xmlCatalogAllow XMLCALL
+XMLPUBFUN xmlCatalogAllow
 		xmlCatalogGetDefaults	(void);
 
 
 /* DEPRECATED interfaces */
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		xmlCatalogGetSystem	(const xmlChar *sysID);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		xmlCatalogGetPublic	(const xmlChar *pubID);
 
 #ifdef __cplusplus
diff --git a/include/libxml/chvalid.h b/include/libxml/chvalid.h
index fb43016982d3ed5d15afa461b744b90f0f8af69e..8225c95ee865f9639f46bd22db54932f257df52c 100644
--- a/include/libxml/chvalid.h
+++ b/include/libxml/chvalid.h
@@ -51,7 +51,7 @@ struct _xmlChRangeGroup {
 /**
  * Range checking routine
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlCharInRange(unsigned int val, const xmlChRangeGroup *group);
 
 
@@ -207,21 +207,21 @@ XMLPUBVAR const unsigned char xmlIsPubidChar_tab[256];
 #define xmlIsPubidCharQ(c)	(((c) < 0x100) ? \
 				 xmlIsPubidChar_ch((c)) : 0)
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsBaseChar(unsigned int ch);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsBlank(unsigned int ch);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsChar(unsigned int ch);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsCombining(unsigned int ch);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsDigit(unsigned int ch);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsExtender(unsigned int ch);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsIdeographic(unsigned int ch);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsPubidChar(unsigned int ch);
 
 #ifdef __cplusplus
diff --git a/include/libxml/debugXML.h b/include/libxml/debugXML.h
index 5b3be13d8572021404e69a261a4f6ece2fd22e62..1332dd73d9c774625c00560e9962cffc995f6059 100644
--- a/include/libxml/debugXML.h
+++ b/include/libxml/debugXML.h
@@ -25,39 +25,39 @@ extern "C" {
 /*
  * The standard Dump routines.
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlDebugDumpString	(FILE *output,
 				 const xmlChar *str);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlDebugDumpAttr	(FILE *output,
 				 xmlAttrPtr attr,
 				 int depth);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlDebugDumpAttrList	(FILE *output,
 				 xmlAttrPtr attr,
 				 int depth);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlDebugDumpOneNode	(FILE *output,
 				 xmlNodePtr node,
 				 int depth);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlDebugDumpNode	(FILE *output,
 				 xmlNodePtr node,
 				 int depth);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlDebugDumpNodeList	(FILE *output,
 				 xmlNodePtr node,
 				 int depth);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlDebugDumpDocumentHead(FILE *output,
 				 xmlDocPtr doc);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlDebugDumpDocument	(FILE *output,
 				 xmlDocPtr doc);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlDebugDumpDTD		(FILE *output,
 				 xmlDtdPtr dtd);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlDebugDumpEntities	(FILE *output,
 				 xmlDocPtr doc);
 
@@ -67,7 +67,7 @@ XMLPUBFUN void XMLCALL
  *								*
  ****************************************************************/
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlDebugCheckDocument	(FILE * output,
 				 xmlDocPtr doc);
 
@@ -77,12 +77,12 @@ XMLPUBFUN int XMLCALL
  *								*
  ****************************************************************/
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlLsOneNode		(FILE *output, xmlNodePtr node);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlLsCountNode		(xmlNodePtr node);
 
-XMLPUBFUN const char * XMLCALL
+XMLPUBFUN const char *
 	xmlBoolToText		(int boolval);
 
 /****************************************************************
@@ -136,63 +136,63 @@ typedef int (* xmlShellCmd) (xmlShellCtxtPtr ctxt,
 			     xmlNodePtr node,
 			     xmlNodePtr node2);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlShellPrintXPathError	(int errorType,
 				 const char *arg);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlShellPrintXPathResult(xmlXPathObjectPtr list);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlShellList		(xmlShellCtxtPtr ctxt,
 				 char *arg,
 				 xmlNodePtr node,
 				 xmlNodePtr node2);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlShellBase		(xmlShellCtxtPtr ctxt,
 				 char *arg,
 				 xmlNodePtr node,
 				 xmlNodePtr node2);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlShellDir		(xmlShellCtxtPtr ctxt,
 				 char *arg,
 				 xmlNodePtr node,
 				 xmlNodePtr node2);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlShellLoad		(xmlShellCtxtPtr ctxt,
 				 char *filename,
 				 xmlNodePtr node,
 				 xmlNodePtr node2);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlShellPrintNode	(xmlNodePtr node);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlShellCat		(xmlShellCtxtPtr ctxt,
 				 char *arg,
 				 xmlNodePtr node,
 				 xmlNodePtr node2);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlShellWrite		(xmlShellCtxtPtr ctxt,
 				 char *filename,
 				 xmlNodePtr node,
 				 xmlNodePtr node2);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlShellSave		(xmlShellCtxtPtr ctxt,
 				 char *filename,
 				 xmlNodePtr node,
 				 xmlNodePtr node2);
 #endif /* LIBXML_OUTPUT_ENABLED */
 #ifdef LIBXML_VALID_ENABLED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlShellValidate	(xmlShellCtxtPtr ctxt,
 				 char *dtd,
 				 xmlNodePtr node,
 				 xmlNodePtr node2);
 #endif /* LIBXML_VALID_ENABLED */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlShellDu		(xmlShellCtxtPtr ctxt,
 				 char *arg,
 				 xmlNodePtr tree,
 				 xmlNodePtr node2);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlShellPwd		(xmlShellCtxtPtr ctxt,
 				 char *buffer,
 				 xmlNodePtr node,
@@ -201,9 +201,9 @@ XMLPUBFUN int XMLCALL
 /*
  * The Shell interface.
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlShell		(xmlDocPtr doc,
-				 char *filename,
+				 const char *filename,
 				 xmlShellReadlineFunc input,
 				 FILE *output);
 
diff --git a/include/libxml/dict.h b/include/libxml/dict.h
index 91f74d1b8ffe05539a56334ceaf50f9ffd4e4984..22aa3d9db8b56b252b28c3ef17b814f6c6df44c0 100644
--- a/include/libxml/dict.h
+++ b/include/libxml/dict.h
@@ -13,6 +13,7 @@
 
 #include <stddef.h>
 #include <libxml/xmlversion.h>
+#include <libxml/xmlstring.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -28,51 +29,51 @@ typedef xmlDict *xmlDictPtr;
  * Initializer
  */
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL  xmlInitializeDict(void);
+XMLPUBFUN int  xmlInitializeDict(void);
 
 /*
  * Constructor and destructor.
  */
-XMLPUBFUN xmlDictPtr XMLCALL
+XMLPUBFUN xmlDictPtr
 			xmlDictCreate	(void);
-XMLPUBFUN size_t XMLCALL
+XMLPUBFUN size_t
 			xmlDictSetLimit	(xmlDictPtr dict,
                                          size_t limit);
-XMLPUBFUN size_t XMLCALL
+XMLPUBFUN size_t
 			xmlDictGetUsage (xmlDictPtr dict);
-XMLPUBFUN xmlDictPtr XMLCALL
+XMLPUBFUN xmlDictPtr
 			xmlDictCreateSub(xmlDictPtr sub);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlDictReference(xmlDictPtr dict);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlDictFree	(xmlDictPtr dict);
 
 /*
  * Lookup of entry in the dictionary.
  */
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 			xmlDictLookup	(xmlDictPtr dict,
 		                         const xmlChar *name,
 		                         int len);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 			xmlDictExists	(xmlDictPtr dict,
 		                         const xmlChar *name,
 		                         int len);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 			xmlDictQLookup	(xmlDictPtr dict,
 		                         const xmlChar *prefix,
 		                         const xmlChar *name);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlDictOwns	(xmlDictPtr dict,
 					 const xmlChar *str);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlDictSize	(xmlDictPtr dict);
 
 /*
  * Cleanup function
  */
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
                         xmlDictCleanup  (void);
 
 #ifdef __cplusplus
diff --git a/include/libxml/encoding.h b/include/libxml/encoding.h
index 381e1886bf8f744012f18ec3e078ad20f0f2d692..599a03e12cd5c47d181500371ebe1e6579d4e02d 100644
--- a/include/libxml/encoding.h
+++ b/include/libxml/encoding.h
@@ -32,6 +32,15 @@
 extern "C" {
 #endif
 
+typedef enum {
+    XML_ENC_ERR_SUCCESS     =  0,
+    XML_ENC_ERR_SPACE       = -1,
+    XML_ENC_ERR_INPUT       = -2,
+    XML_ENC_ERR_PARTIAL     = -3,
+    XML_ENC_ERR_INTERNAL    = -4,
+    XML_ENC_ERR_MEMORY      = -5
+} xmlCharEncError;
+
 /*
  * xmlCharEncoding:
  *
@@ -142,30 +151,29 @@ struct _xmlCharEncodingHandler {
 #endif /* LIBXML_ICU_ENABLED */
 };
 
-#ifdef __cplusplus
-}
-#endif
-#include <libxml/tree.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
  * Interfaces for encoding handlers.
  */
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlInitCharEncodingHandlers	(void);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlCleanupCharEncodingHandlers	(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlRegisterCharEncodingHandler	(xmlCharEncodingHandlerPtr handler);
-XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL
+XMLPUBFUN int
+	xmlLookupCharEncodingHandler	(xmlCharEncoding enc,
+					 xmlCharEncodingHandlerPtr *out);
+XMLPUBFUN int
+	xmlOpenCharEncodingHandler	(const char *name,
+					 int output,
+					 xmlCharEncodingHandlerPtr *out);
+XMLPUBFUN xmlCharEncodingHandlerPtr
 	xmlGetCharEncodingHandler	(xmlCharEncoding enc);
-XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL
+XMLPUBFUN xmlCharEncodingHandlerPtr
 	xmlFindCharEncodingHandler	(const char *name);
-XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL
+XMLPUBFUN xmlCharEncodingHandlerPtr
 	xmlNewCharEncodingHandler	(const char *name,
 					 xmlCharEncodingInputFunc input,
 					 xmlCharEncodingOutputFunc output);
@@ -173,54 +181,58 @@ XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL
 /*
  * Interfaces for encoding names and aliases.
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlAddEncodingAlias		(const char *name,
 					 const char *alias);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlDelEncodingAlias		(const char *alias);
-XMLPUBFUN const char * XMLCALL
+XMLPUBFUN const char *
 	xmlGetEncodingAlias		(const char *alias);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlCleanupEncodingAliases	(void);
-XMLPUBFUN xmlCharEncoding XMLCALL
+XMLPUBFUN xmlCharEncoding
 	xmlParseCharEncoding		(const char *name);
-XMLPUBFUN const char * XMLCALL
+XMLPUBFUN const char *
 	xmlGetCharEncodingName		(xmlCharEncoding enc);
 
 /*
  * Interfaces directly used by the parsers.
  */
-XMLPUBFUN xmlCharEncoding XMLCALL
+XMLPUBFUN xmlCharEncoding
 	xmlDetectCharEncoding		(const unsigned char *in,
 					 int len);
 
-XMLPUBFUN int XMLCALL
+/** DOC_DISABLE */
+struct _xmlBuffer;
+/** DOC_ENABLE */
+XMLPUBFUN int
 	xmlCharEncOutFunc		(xmlCharEncodingHandler *handler,
-					 xmlBufferPtr out,
-					 xmlBufferPtr in);
+					 struct _xmlBuffer *out,
+					 struct _xmlBuffer *in);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlCharEncInFunc		(xmlCharEncodingHandler *handler,
-					 xmlBufferPtr out,
-					 xmlBufferPtr in);
-XMLPUBFUN int XMLCALL
+					 struct _xmlBuffer *out,
+					 struct _xmlBuffer *in);
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlCharEncFirstLine		(xmlCharEncodingHandler *handler,
-					 xmlBufferPtr out,
-					 xmlBufferPtr in);
-XMLPUBFUN int XMLCALL
+					 struct _xmlBuffer *out,
+					 struct _xmlBuffer *in);
+XMLPUBFUN int
 	xmlCharEncCloseFunc		(xmlCharEncodingHandler *handler);
 
 /*
  * Export a few useful functions
  */
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	UTF8Toisolat1			(unsigned char *out,
 					 int *outlen,
 					 const unsigned char *in,
 					 int *inlen);
 #endif /* LIBXML_OUTPUT_ENABLED */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	isolat1ToUTF8			(unsigned char *out,
 					 int *outlen,
 					 const unsigned char *in,
diff --git a/include/libxml/entities.h b/include/libxml/entities.h
index 2b60d9e62284e70a79fc729005b1be365af3159a..a0cfca8133f660b2b93d069003c0f69ca36c34fc 100644
--- a/include/libxml/entities.h
+++ b/include/libxml/entities.h
@@ -11,8 +11,12 @@
 #ifndef __XML_ENTITIES_H__
 #define __XML_ENTITIES_H__
 
+/** DOC_DISABLE */
 #include <libxml/xmlversion.h>
+#define XML_TREE_INTERNALS
 #include <libxml/tree.h>
+#undef XML_TREE_INTERNALS
+/** DOC_ENABLE */
 
 #ifdef __cplusplus
 extern "C" {
@@ -55,11 +59,9 @@ struct _xmlEntity {
 
     struct _xmlEntity     *nexte;	/* unused */
     const xmlChar           *URI;	/* the full URI as computed */
-    int                    owner;	/* does the entity own the childrens */
-    int			 checked;	/* was the entity content checked */
-					/* this is also used to count entities
-					 * references done from that entity
-					 * and if it contains '<' */
+    int                    owner;	/* unused */
+    int                    flags;       /* various flags */
+    unsigned long   expandedSize;       /* expanded size */
 };
 
 /*
@@ -76,72 +78,83 @@ typedef xmlEntitiesTable *xmlEntitiesTablePtr;
 
 #ifdef LIBXML_LEGACY_ENABLED
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlInitializePredefinedEntities	(void);
 #endif /* LIBXML_LEGACY_ENABLED */
 
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN xmlEntityPtr
 			xmlNewEntity		(xmlDocPtr doc,
 						 const xmlChar *name,
 						 int type,
 						 const xmlChar *ExternalID,
 						 const xmlChar *SystemID,
 						 const xmlChar *content);
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN void
+			xmlFreeEntity		(xmlEntityPtr entity);
+XMLPUBFUN int
+			xmlAddEntity		(xmlDocPtr doc,
+						 int extSubset,
+						 const xmlChar *name,
+						 int type,
+						 const xmlChar *ExternalID,
+						 const xmlChar *SystemID,
+						 const xmlChar *content,
+						 xmlEntityPtr *out);
+XMLPUBFUN xmlEntityPtr
 			xmlAddDocEntity		(xmlDocPtr doc,
 						 const xmlChar *name,
 						 int type,
 						 const xmlChar *ExternalID,
 						 const xmlChar *SystemID,
 						 const xmlChar *content);
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN xmlEntityPtr
 			xmlAddDtdEntity		(xmlDocPtr doc,
 						 const xmlChar *name,
 						 int type,
 						 const xmlChar *ExternalID,
 						 const xmlChar *SystemID,
 						 const xmlChar *content);
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN xmlEntityPtr
 			xmlGetPredefinedEntity	(const xmlChar *name);
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN xmlEntityPtr
 			xmlGetDocEntity		(const xmlDoc *doc,
 						 const xmlChar *name);
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN xmlEntityPtr
 			xmlGetDtdEntity		(xmlDocPtr doc,
 						 const xmlChar *name);
-XMLPUBFUN xmlEntityPtr XMLCALL
+XMLPUBFUN xmlEntityPtr
 			xmlGetParameterEntity	(xmlDocPtr doc,
 						 const xmlChar *name);
 #ifdef LIBXML_LEGACY_ENABLED
 XML_DEPRECATED
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 			xmlEncodeEntities	(xmlDocPtr doc,
 						 const xmlChar *input);
 #endif /* LIBXML_LEGACY_ENABLED */
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlEncodeEntitiesReentrant(xmlDocPtr doc,
 						 const xmlChar *input);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlEncodeSpecialChars	(const xmlDoc *doc,
 						 const xmlChar *input);
-XMLPUBFUN xmlEntitiesTablePtr XMLCALL
+XMLPUBFUN xmlEntitiesTablePtr
 			xmlCreateEntitiesTable	(void);
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN xmlEntitiesTablePtr XMLCALL
+XMLPUBFUN xmlEntitiesTablePtr
 			xmlCopyEntitiesTable	(xmlEntitiesTablePtr table);
 #endif /* LIBXML_TREE_ENABLED */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlFreeEntitiesTable	(xmlEntitiesTablePtr table);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlDumpEntitiesTable	(xmlBufferPtr buf,
 						 xmlEntitiesTablePtr table);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlDumpEntityDecl	(xmlBufferPtr buf,
 						 xmlEntityPtr ent);
 #endif /* LIBXML_OUTPUT_ENABLED */
 #ifdef LIBXML_LEGACY_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlCleanupPredefinedEntities(void);
 #endif /* LIBXML_LEGACY_ENABLED */
 
diff --git a/include/libxml/globals.h b/include/libxml/globals.h
index d57ccb05415ef8f7eda389765d60c7fe76e2336c..92f41312f549efa176e48dd719c1652cfc21ef34 100644
--- a/include/libxml/globals.h
+++ b/include/libxml/globals.h
@@ -1,496 +1,38 @@
 /*
  * Summary: interface for all global variables of the library
- * Description: all the global variables and thread handling for
- *              those variables is handled by this module.
- *
- * The bottom of this file is automatically generated by build_glob.py
- * based on the description file global.data
+ * Description: Deprecated, don't use
  *
  * Copy: See Copyright for the status of this software.
- *
- * Author: Gary Pennington <Gary.Pennington@uk.sun.com>, Daniel Veillard
  */
 
 #ifndef __XML_GLOBALS_H
 #define __XML_GLOBALS_H
 
 #include <libxml/xmlversion.h>
-#include <libxml/parser.h>
-#include <libxml/xmlerror.h>
-#include <libxml/SAX2.h>
-#include <libxml/xmlmemory.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-XML_DEPRECATED
-XMLPUBFUN void XMLCALL xmlInitGlobals(void);
-XML_DEPRECATED
-XMLPUBFUN void XMLCALL xmlCleanupGlobals(void);
-
-/**
- * xmlParserInputBufferCreateFilenameFunc:
- * @URI: the URI to read from
- * @enc: the requested source encoding
- *
- * Signature for the function doing the lookup for a suitable input method
- * corresponding to an URI.
- *
- * Returns the new xmlParserInputBufferPtr in case of success or NULL if no
- *         method was found.
- */
-typedef xmlParserInputBufferPtr (*xmlParserInputBufferCreateFilenameFunc) (const char *URI,
-									   xmlCharEncoding enc);
-
-
-/**
- * xmlOutputBufferCreateFilenameFunc:
- * @URI: the URI to write to
- * @enc: the requested target encoding
- *
- * Signature for the function doing the lookup for a suitable output method
- * corresponding to an URI.
- *
- * Returns the new xmlOutputBufferPtr in case of success or NULL if no
- *         method was found.
- */
-typedef xmlOutputBufferPtr (*xmlOutputBufferCreateFilenameFunc) (const char *URI,
-								 xmlCharEncodingHandlerPtr encoder,
-								 int compression);
-
-XMLPUBFUN xmlParserInputBufferCreateFilenameFunc
-XMLCALL xmlParserInputBufferCreateFilenameDefault (xmlParserInputBufferCreateFilenameFunc func);
-XMLPUBFUN xmlOutputBufferCreateFilenameFunc
-XMLCALL xmlOutputBufferCreateFilenameDefault (xmlOutputBufferCreateFilenameFunc func);
 
 /*
- * Externally global symbols which need to be protected for backwards
- * compatibility support.
- */
-
-#undef	htmlDefaultSAXHandler
-#undef	oldXMLWDcompatibility
-#undef	xmlBufferAllocScheme
-#undef	xmlDefaultBufferSize
-#undef	xmlDefaultSAXHandler
-#undef	xmlDefaultSAXLocator
-#undef	xmlDoValidityCheckingDefaultValue
-#undef	xmlFree
-#undef	xmlGenericError
-#undef	xmlStructuredError
-#undef	xmlGenericErrorContext
-#undef	xmlStructuredErrorContext
-#undef	xmlGetWarningsDefaultValue
-#undef	xmlIndentTreeOutput
-#undef  xmlTreeIndentString
-#undef	xmlKeepBlanksDefaultValue
-#undef	xmlLineNumbersDefaultValue
-#undef	xmlLoadExtDtdDefaultValue
-#undef	xmlMalloc
-#undef	xmlMallocAtomic
-#undef	xmlMemStrdup
-#undef	xmlParserDebugEntities
-#undef	xmlParserVersion
-#undef	xmlPedanticParserDefaultValue
-#undef	xmlRealloc
-#undef	xmlSaveNoEmptyTags
-#undef	xmlSubstituteEntitiesDefaultValue
-#undef  xmlRegisterNodeDefaultValue
-#undef  xmlDeregisterNodeDefaultValue
-#undef  xmlLastError
-#undef  xmlParserInputBufferCreateFilenameValue
-#undef  xmlOutputBufferCreateFilenameValue
-
-/**
- * xmlRegisterNodeFunc:
- * @node: the current node
- *
- * Signature for the registration callback of a created node
- */
-typedef void (*xmlRegisterNodeFunc) (xmlNodePtr node);
-/**
- * xmlDeregisterNodeFunc:
- * @node: the current node
+ * This file was required to access global variables until version v2.12.0.
  *
- * Signature for the deregistration callback of a discarded node
+ * These includes are for backward compatibility.
  */
-typedef void (*xmlDeregisterNodeFunc) (xmlNodePtr node);
-
-typedef struct _xmlGlobalState xmlGlobalState;
-typedef xmlGlobalState *xmlGlobalStatePtr;
-struct _xmlGlobalState
-{
-	const char *xmlParserVersion;
-
-	xmlSAXLocator xmlDefaultSAXLocator;
-	xmlSAXHandlerV1 xmlDefaultSAXHandler;
-	xmlSAXHandlerV1 docbDefaultSAXHandler; /* unused */
-	xmlSAXHandlerV1 htmlDefaultSAXHandler;
-
-	xmlFreeFunc xmlFree;
-	xmlMallocFunc xmlMalloc;
-	xmlStrdupFunc xmlMemStrdup;
-	xmlReallocFunc xmlRealloc;
-
-	xmlGenericErrorFunc xmlGenericError;
-	xmlStructuredErrorFunc xmlStructuredError;
-	void *xmlGenericErrorContext;
-
-	int oldXMLWDcompatibility;
-
-	xmlBufferAllocationScheme xmlBufferAllocScheme;
-	int xmlDefaultBufferSize;
-
-	int xmlSubstituteEntitiesDefaultValue;
-	int xmlDoValidityCheckingDefaultValue;
-	int xmlGetWarningsDefaultValue;
-	int xmlKeepBlanksDefaultValue;
-	int xmlLineNumbersDefaultValue;
-	int xmlLoadExtDtdDefaultValue;
-	int xmlParserDebugEntities;
-	int xmlPedanticParserDefaultValue;
-
-	int xmlSaveNoEmptyTags;
-	int xmlIndentTreeOutput;
-	const char *xmlTreeIndentString;
-
-	xmlRegisterNodeFunc xmlRegisterNodeDefaultValue;
-	xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue;
-
-	xmlMallocFunc xmlMallocAtomic;
-	xmlError xmlLastError;
-
-	xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue;
-	xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue;
-
-	void *xmlStructuredErrorContext;
-};
-
-#ifdef __cplusplus
-}
-#endif
+#include <libxml/HTMLparser.h>
+#include <libxml/parser.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xmlsave.h>
 #include <libxml/threads.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-XMLPUBFUN void XMLCALL	xmlInitializeGlobalState(xmlGlobalStatePtr gs);
-
-XMLPUBFUN void XMLCALL xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler);
-
-XMLPUBFUN void XMLCALL xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler);
-
-XMLPUBFUN xmlRegisterNodeFunc XMLCALL xmlRegisterNodeDefault(xmlRegisterNodeFunc func);
-XMLPUBFUN xmlRegisterNodeFunc XMLCALL xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func);
-XMLPUBFUN xmlDeregisterNodeFunc XMLCALL xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func);
-XMLPUBFUN xmlDeregisterNodeFunc XMLCALL xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func);
-
-XMLPUBFUN xmlOutputBufferCreateFilenameFunc XMLCALL
-	xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func);
-XMLPUBFUN xmlParserInputBufferCreateFilenameFunc XMLCALL
-	xmlThrDefParserInputBufferCreateFilenameDefault(
-				xmlParserInputBufferCreateFilenameFunc func);
-
-/** DOC_DISABLE */
-/*
- * In general the memory allocation entry points are not kept
- * thread specific but this can be overridden by LIBXML_THREAD_ALLOC_ENABLED
- *    - xmlMalloc
- *    - xmlMallocAtomic
- *    - xmlRealloc
- *    - xmlMemStrdup
- *    - xmlFree
- */
-
-#ifdef LIBXML_THREAD_ALLOC_ENABLED
-#ifdef LIBXML_THREAD_ENABLED
-XMLPUBFUN  xmlMallocFunc * XMLCALL __xmlMalloc(void);
-#define xmlMalloc \
-(*(__xmlMalloc()))
-#else
-XMLPUBVAR xmlMallocFunc xmlMalloc;
-#endif
-
-#ifdef LIBXML_THREAD_ENABLED
-XMLPUBFUN  xmlMallocFunc * XMLCALL __xmlMallocAtomic(void);
-#define xmlMallocAtomic \
-(*(__xmlMallocAtomic()))
-#else
-XMLPUBVAR xmlMallocFunc xmlMallocAtomic;
-#endif
-
-#ifdef LIBXML_THREAD_ENABLED
-XMLPUBFUN  xmlReallocFunc * XMLCALL __xmlRealloc(void);
-#define xmlRealloc \
-(*(__xmlRealloc()))
-#else
-XMLPUBVAR xmlReallocFunc xmlRealloc;
-#endif
-
-#ifdef LIBXML_THREAD_ENABLED
-XMLPUBFUN  xmlFreeFunc * XMLCALL __xmlFree(void);
-#define xmlFree \
-(*(__xmlFree()))
-#else
-XMLPUBVAR xmlFreeFunc xmlFree;
-#endif
-
-#ifdef LIBXML_THREAD_ENABLED
-XMLPUBFUN  xmlStrdupFunc * XMLCALL __xmlMemStrdup(void);
-#define xmlMemStrdup \
-(*(__xmlMemStrdup()))
-#else
-XMLPUBVAR xmlStrdupFunc xmlMemStrdup;
-#endif
-
-#else /* !LIBXML_THREAD_ALLOC_ENABLED */
-XMLPUBVAR xmlMallocFunc xmlMalloc;
-XMLPUBVAR xmlMallocFunc xmlMallocAtomic;
-XMLPUBVAR xmlReallocFunc xmlRealloc;
-XMLPUBVAR xmlFreeFunc xmlFree;
-XMLPUBVAR xmlStrdupFunc xmlMemStrdup;
-#endif /* LIBXML_THREAD_ALLOC_ENABLED */
-
-#ifdef LIBXML_HTML_ENABLED
-XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __htmlDefaultSAXHandler(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define htmlDefaultSAXHandler \
-(*(__htmlDefaultSAXHandler()))
-#else
-XMLPUBVAR xmlSAXHandlerV1 htmlDefaultSAXHandler;
-#endif
-#endif
-
-XMLPUBFUN xmlError * XMLCALL __xmlLastError(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlLastError \
-(*(__xmlLastError()))
-#else
-XMLPUBVAR xmlError xmlLastError;
-#endif
-
-/*
- * Everything starting from the line below is
- * Automatically generated by build_glob.py.
- * Do not modify the previous line.
- */
-
-
-XMLPUBFUN int * XMLCALL __oldXMLWDcompatibility(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define oldXMLWDcompatibility \
-(*(__oldXMLWDcompatibility()))
-#else
-XMLPUBVAR int oldXMLWDcompatibility;
-#endif
-
-XMLPUBFUN xmlBufferAllocationScheme * XMLCALL __xmlBufferAllocScheme(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlBufferAllocScheme \
-(*(__xmlBufferAllocScheme()))
-#else
-XMLPUBVAR xmlBufferAllocationScheme xmlBufferAllocScheme;
-#endif
-XMLPUBFUN xmlBufferAllocationScheme XMLCALL
-	xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v);
-
-XMLPUBFUN int * XMLCALL __xmlDefaultBufferSize(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlDefaultBufferSize \
-(*(__xmlDefaultBufferSize()))
-#else
-XMLPUBVAR int xmlDefaultBufferSize;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefDefaultBufferSize(int v);
-
-XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __xmlDefaultSAXHandler(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlDefaultSAXHandler \
-(*(__xmlDefaultSAXHandler()))
-#else
-XMLPUBVAR xmlSAXHandlerV1 xmlDefaultSAXHandler;
-#endif
-
-XMLPUBFUN xmlSAXLocator * XMLCALL __xmlDefaultSAXLocator(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlDefaultSAXLocator \
-(*(__xmlDefaultSAXLocator()))
-#else
-XMLPUBVAR xmlSAXLocator xmlDefaultSAXLocator;
-#endif
-
-XMLPUBFUN int * XMLCALL __xmlDoValidityCheckingDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlDoValidityCheckingDefaultValue \
-(*(__xmlDoValidityCheckingDefaultValue()))
-#else
-XMLPUBVAR int xmlDoValidityCheckingDefaultValue;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefDoValidityCheckingDefaultValue(int v);
-
-XMLPUBFUN xmlGenericErrorFunc * XMLCALL __xmlGenericError(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlGenericError \
-(*(__xmlGenericError()))
-#else
-XMLPUBVAR xmlGenericErrorFunc xmlGenericError;
-#endif
-
-XMLPUBFUN xmlStructuredErrorFunc * XMLCALL __xmlStructuredError(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlStructuredError \
-(*(__xmlStructuredError()))
-#else
-XMLPUBVAR xmlStructuredErrorFunc xmlStructuredError;
-#endif
-
-XMLPUBFUN void * * XMLCALL __xmlGenericErrorContext(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlGenericErrorContext \
-(*(__xmlGenericErrorContext()))
-#else
-XMLPUBVAR void * xmlGenericErrorContext;
-#endif
-
-XMLPUBFUN void * * XMLCALL __xmlStructuredErrorContext(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlStructuredErrorContext \
-(*(__xmlStructuredErrorContext()))
-#else
-XMLPUBVAR void * xmlStructuredErrorContext;
-#endif
-
-XMLPUBFUN int * XMLCALL __xmlGetWarningsDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlGetWarningsDefaultValue \
-(*(__xmlGetWarningsDefaultValue()))
-#else
-XMLPUBVAR int xmlGetWarningsDefaultValue;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefGetWarningsDefaultValue(int v);
-
-XMLPUBFUN int * XMLCALL __xmlIndentTreeOutput(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlIndentTreeOutput \
-(*(__xmlIndentTreeOutput()))
-#else
-XMLPUBVAR int xmlIndentTreeOutput;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefIndentTreeOutput(int v);
-
-XMLPUBFUN const char * * XMLCALL __xmlTreeIndentString(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlTreeIndentString \
-(*(__xmlTreeIndentString()))
-#else
-XMLPUBVAR const char * xmlTreeIndentString;
-#endif
-XMLPUBFUN const char * XMLCALL xmlThrDefTreeIndentString(const char * v);
-
-XMLPUBFUN int * XMLCALL __xmlKeepBlanksDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlKeepBlanksDefaultValue \
-(*(__xmlKeepBlanksDefaultValue()))
-#else
-XMLPUBVAR int xmlKeepBlanksDefaultValue;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefKeepBlanksDefaultValue(int v);
-
-XMLPUBFUN int * XMLCALL __xmlLineNumbersDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlLineNumbersDefaultValue \
-(*(__xmlLineNumbersDefaultValue()))
-#else
-XMLPUBVAR int xmlLineNumbersDefaultValue;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefLineNumbersDefaultValue(int v);
-
-XMLPUBFUN int * XMLCALL __xmlLoadExtDtdDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlLoadExtDtdDefaultValue \
-(*(__xmlLoadExtDtdDefaultValue()))
-#else
-XMLPUBVAR int xmlLoadExtDtdDefaultValue;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefLoadExtDtdDefaultValue(int v);
-
-XMLPUBFUN int * XMLCALL __xmlParserDebugEntities(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlParserDebugEntities \
-(*(__xmlParserDebugEntities()))
-#else
-XMLPUBVAR int xmlParserDebugEntities;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefParserDebugEntities(int v);
-
-XMLPUBFUN const char * * XMLCALL __xmlParserVersion(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlParserVersion \
-(*(__xmlParserVersion()))
-#else
-XMLPUBVAR const char * xmlParserVersion;
-#endif
-
-XMLPUBFUN int * XMLCALL __xmlPedanticParserDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlPedanticParserDefaultValue \
-(*(__xmlPedanticParserDefaultValue()))
-#else
-XMLPUBVAR int xmlPedanticParserDefaultValue;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefPedanticParserDefaultValue(int v);
-
-XMLPUBFUN int * XMLCALL __xmlSaveNoEmptyTags(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlSaveNoEmptyTags \
-(*(__xmlSaveNoEmptyTags()))
-#else
-XMLPUBVAR int xmlSaveNoEmptyTags;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefSaveNoEmptyTags(int v);
-
-XMLPUBFUN int * XMLCALL __xmlSubstituteEntitiesDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlSubstituteEntitiesDefaultValue \
-(*(__xmlSubstituteEntitiesDefaultValue()))
-#else
-XMLPUBVAR int xmlSubstituteEntitiesDefaultValue;
-#endif
-XMLPUBFUN int XMLCALL xmlThrDefSubstituteEntitiesDefaultValue(int v);
-
-XMLPUBFUN xmlRegisterNodeFunc * XMLCALL __xmlRegisterNodeDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlRegisterNodeDefaultValue \
-(*(__xmlRegisterNodeDefaultValue()))
-#else
-XMLPUBVAR xmlRegisterNodeFunc xmlRegisterNodeDefaultValue;
-#endif
-
-XMLPUBFUN xmlDeregisterNodeFunc * XMLCALL __xmlDeregisterNodeDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlDeregisterNodeDefaultValue \
-(*(__xmlDeregisterNodeDefaultValue()))
-#else
-XMLPUBVAR xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue;
-#endif
-
-XMLPUBFUN xmlParserInputBufferCreateFilenameFunc * XMLCALL \
-				__xmlParserInputBufferCreateFilenameValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlParserInputBufferCreateFilenameValue \
-(*(__xmlParserInputBufferCreateFilenameValue()))
-#else
-XMLPUBVAR xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue;
-#endif
+typedef struct _xmlGlobalState xmlGlobalState;
+typedef xmlGlobalState *xmlGlobalStatePtr;
 
-XMLPUBFUN xmlOutputBufferCreateFilenameFunc * XMLCALL __xmlOutputBufferCreateFilenameValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlOutputBufferCreateFilenameValue \
-(*(__xmlOutputBufferCreateFilenameValue()))
-#else
-XMLPUBVAR xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue;
-#endif
+XML_DEPRECATED XMLPUBFUN void
+xmlInitializeGlobalState(xmlGlobalStatePtr gs);
+XML_DEPRECATED XMLPUBFUN
+xmlGlobalStatePtr xmlGetGlobalState(void);
 
 #ifdef __cplusplus
 }
diff --git a/include/libxml/hash.h b/include/libxml/hash.h
index b682b6b9403a0bed9da4d501e96d356eca8819f9..135b69669b38b65abc7ef51476ad532f2923042e 100644
--- a/include/libxml/hash.h
+++ b/include/libxml/hash.h
@@ -11,6 +11,10 @@
 #ifndef __XML_HASH_H__
 #define __XML_HASH_H__
 
+#include <libxml/xmlversion.h>
+#include <libxml/dict.h>
+#include <libxml/xmlstring.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -21,18 +25,6 @@ extern "C" {
 typedef struct _xmlHashTable xmlHashTable;
 typedef xmlHashTable *xmlHashTablePtr;
 
-#ifdef __cplusplus
-}
-#endif
-
-#include <libxml/xmlversion.h>
-#include <libxml/parser.h>
-#include <libxml/dict.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
  * Recent version of gcc produce a warning when a function pointer is assigned
  * to an object pointer, or vice versa.  The following macro is a dirty hack
@@ -55,7 +47,6 @@ extern "C" {
 
 #define XML_CAST_FPTR(fptr) fptr
 
-
 /*
  * function types:
  */
@@ -103,132 +94,156 @@ typedef void (*xmlHashScannerFull)(void *payload, void *data,
 /*
  * Constructor and destructor.
  */
-XMLPUBFUN xmlHashTablePtr XMLCALL
-			xmlHashCreate	(int size);
-XMLPUBFUN xmlHashTablePtr XMLCALL
-			xmlHashCreateDict(int size,
+XMLPUBFUN xmlHashTablePtr
+		xmlHashCreate		(int size);
+XMLPUBFUN xmlHashTablePtr
+		xmlHashCreateDict	(int size,
 					 xmlDictPtr dict);
-XMLPUBFUN void XMLCALL
-			xmlHashFree	(xmlHashTablePtr table,
-					 xmlHashDeallocator f);
-XMLPUBFUN void XMLCALL
-			xmlHashDefaultDeallocator(void *entry,
+XMLPUBFUN void
+		xmlHashFree		(xmlHashTablePtr hash,
+					 xmlHashDeallocator dealloc);
+XMLPUBFUN void
+		xmlHashDefaultDeallocator(void *entry,
 					 const xmlChar *name);
 
 /*
  * Add a new entry to the hash table.
  */
-XMLPUBFUN int XMLCALL
-			xmlHashAddEntry	(xmlHashTablePtr table,
+XMLPUBFUN int
+		xmlHashAdd		(xmlHashTablePtr hash,
+		                         const xmlChar *name,
+		                         void *userdata);
+XMLPUBFUN int
+		xmlHashAddEntry		(xmlHashTablePtr hash,
 		                         const xmlChar *name,
 		                         void *userdata);
-XMLPUBFUN int XMLCALL
-			xmlHashUpdateEntry(xmlHashTablePtr table,
+XMLPUBFUN int
+		xmlHashUpdateEntry	(xmlHashTablePtr hash,
 		                         const xmlChar *name,
 		                         void *userdata,
-					 xmlHashDeallocator f);
-XMLPUBFUN int XMLCALL
-			xmlHashAddEntry2(xmlHashTablePtr table,
+					 xmlHashDeallocator dealloc);
+XMLPUBFUN int
+		xmlHashAdd2		(xmlHashTablePtr hash,
 		                         const xmlChar *name,
 		                         const xmlChar *name2,
 		                         void *userdata);
-XMLPUBFUN int XMLCALL
-			xmlHashUpdateEntry2(xmlHashTablePtr table,
+XMLPUBFUN int
+		xmlHashAddEntry2	(xmlHashTablePtr hash,
+		                         const xmlChar *name,
+		                         const xmlChar *name2,
+		                         void *userdata);
+XMLPUBFUN int
+		xmlHashUpdateEntry2	(xmlHashTablePtr hash,
 		                         const xmlChar *name,
 		                         const xmlChar *name2,
 		                         void *userdata,
-					 xmlHashDeallocator f);
-XMLPUBFUN int XMLCALL
-			xmlHashAddEntry3(xmlHashTablePtr table,
+					 xmlHashDeallocator dealloc);
+XMLPUBFUN int
+		xmlHashAdd3		(xmlHashTablePtr hash,
+		                         const xmlChar *name,
+		                         const xmlChar *name2,
+		                         const xmlChar *name3,
+		                         void *userdata);
+XMLPUBFUN int
+		xmlHashAddEntry3	(xmlHashTablePtr hash,
 		                         const xmlChar *name,
 		                         const xmlChar *name2,
 		                         const xmlChar *name3,
 		                         void *userdata);
-XMLPUBFUN int XMLCALL
-			xmlHashUpdateEntry3(xmlHashTablePtr table,
+XMLPUBFUN int
+		xmlHashUpdateEntry3	(xmlHashTablePtr hash,
 		                         const xmlChar *name,
 		                         const xmlChar *name2,
 		                         const xmlChar *name3,
 		                         void *userdata,
-					 xmlHashDeallocator f);
+					 xmlHashDeallocator dealloc);
 
 /*
  * Remove an entry from the hash table.
  */
-XMLPUBFUN int XMLCALL
-			xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name,
-                           xmlHashDeallocator f);
-XMLPUBFUN int XMLCALL
-			xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name,
-                            const xmlChar *name2, xmlHashDeallocator f);
-XMLPUBFUN int  XMLCALL
-			xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name,
-                            const xmlChar *name2, const xmlChar *name3,
-                            xmlHashDeallocator f);
+XMLPUBFUN int
+		xmlHashRemoveEntry	(xmlHashTablePtr hash,
+					 const xmlChar *name,
+					 xmlHashDeallocator dealloc);
+XMLPUBFUN int
+		xmlHashRemoveEntry2	(xmlHashTablePtr hash,
+					 const xmlChar *name,
+					 const xmlChar *name2,
+					 xmlHashDeallocator dealloc);
+XMLPUBFUN int 
+		xmlHashRemoveEntry3	(xmlHashTablePtr hash,
+					 const xmlChar *name,
+					 const xmlChar *name2,
+					 const xmlChar *name3,
+					 xmlHashDeallocator dealloc);
 
 /*
- * Retrieve the userdata.
+ * Retrieve the payload.
  */
-XMLPUBFUN void * XMLCALL
-			xmlHashLookup	(xmlHashTablePtr table,
+XMLPUBFUN void *
+		xmlHashLookup		(xmlHashTablePtr hash,
 					 const xmlChar *name);
-XMLPUBFUN void * XMLCALL
-			xmlHashLookup2	(xmlHashTablePtr table,
+XMLPUBFUN void *
+		xmlHashLookup2		(xmlHashTablePtr hash,
 					 const xmlChar *name,
 					 const xmlChar *name2);
-XMLPUBFUN void * XMLCALL
-			xmlHashLookup3	(xmlHashTablePtr table,
+XMLPUBFUN void *
+		xmlHashLookup3		(xmlHashTablePtr hash,
 					 const xmlChar *name,
 					 const xmlChar *name2,
 					 const xmlChar *name3);
-XMLPUBFUN void * XMLCALL
-			xmlHashQLookup	(xmlHashTablePtr table,
-					 const xmlChar *name,
-					 const xmlChar *prefix);
-XMLPUBFUN void * XMLCALL
-			xmlHashQLookup2	(xmlHashTablePtr table,
-					 const xmlChar *name,
+XMLPUBFUN void *
+		xmlHashQLookup		(xmlHashTablePtr hash,
+					 const xmlChar *prefix,
+					 const xmlChar *name);
+XMLPUBFUN void *
+		xmlHashQLookup2		(xmlHashTablePtr hash,
 					 const xmlChar *prefix,
-					 const xmlChar *name2,
-					 const xmlChar *prefix2);
-XMLPUBFUN void * XMLCALL
-			xmlHashQLookup3	(xmlHashTablePtr table,
 					 const xmlChar *name,
+					 const xmlChar *prefix2,
+					 const xmlChar *name2);
+XMLPUBFUN void *
+		xmlHashQLookup3		(xmlHashTablePtr hash,
 					 const xmlChar *prefix,
-					 const xmlChar *name2,
+					 const xmlChar *name,
 					 const xmlChar *prefix2,
-					 const xmlChar *name3,
-					 const xmlChar *prefix3);
+					 const xmlChar *name2,
+					 const xmlChar *prefix3,
+					 const xmlChar *name3);
 
 /*
  * Helpers.
  */
-XMLPUBFUN xmlHashTablePtr XMLCALL
-			xmlHashCopy	(xmlHashTablePtr table,
-					 xmlHashCopier f);
-XMLPUBFUN int XMLCALL
-			xmlHashSize	(xmlHashTablePtr table);
-XMLPUBFUN void XMLCALL
-			xmlHashScan	(xmlHashTablePtr table,
-					 xmlHashScanner f,
+XMLPUBFUN xmlHashTablePtr
+		xmlHashCopySafe		(xmlHashTablePtr hash,
+					 xmlHashCopier copy,
+					 xmlHashDeallocator dealloc);
+XMLPUBFUN xmlHashTablePtr
+		xmlHashCopy		(xmlHashTablePtr hash,
+					 xmlHashCopier copy);
+XMLPUBFUN int
+		xmlHashSize		(xmlHashTablePtr hash);
+XMLPUBFUN void
+		xmlHashScan		(xmlHashTablePtr hash,
+					 xmlHashScanner scan,
 					 void *data);
-XMLPUBFUN void XMLCALL
-			xmlHashScan3	(xmlHashTablePtr table,
+XMLPUBFUN void
+		xmlHashScan3		(xmlHashTablePtr hash,
 					 const xmlChar *name,
 					 const xmlChar *name2,
 					 const xmlChar *name3,
-					 xmlHashScanner f,
+					 xmlHashScanner scan,
 					 void *data);
-XMLPUBFUN void XMLCALL
-			xmlHashScanFull	(xmlHashTablePtr table,
-					 xmlHashScannerFull f,
+XMLPUBFUN void
+		xmlHashScanFull		(xmlHashTablePtr hash,
+					 xmlHashScannerFull scan,
 					 void *data);
-XMLPUBFUN void XMLCALL
-			xmlHashScanFull3(xmlHashTablePtr table,
+XMLPUBFUN void
+		xmlHashScanFull3	(xmlHashTablePtr hash,
 					 const xmlChar *name,
 					 const xmlChar *name2,
 					 const xmlChar *name3,
-					 xmlHashScannerFull f,
+					 xmlHashScannerFull scan,
 					 void *data);
 #ifdef __cplusplus
 }
diff --git a/include/libxml/list.h b/include/libxml/list.h
index 3211c755247b3d5d335dd8dcc82242d6ce58edef..1fa76aff0847fd3de18c942f5037bf6f12bbbb56 100644
--- a/include/libxml/list.h
+++ b/include/libxml/list.h
@@ -52,79 +52,79 @@ typedef int  (*xmlListDataCompare) (const void *data0, const void *data1);
 typedef int (*xmlListWalker) (const void *data, void *user);
 
 /* Creation/Deletion */
-XMLPUBFUN xmlListPtr XMLCALL
+XMLPUBFUN xmlListPtr
 		xmlListCreate		(xmlListDeallocator deallocator,
 	                                 xmlListDataCompare compare);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlListDelete		(xmlListPtr l);
 
 /* Basic Operators */
-XMLPUBFUN void * XMLCALL
+XMLPUBFUN void *
 		xmlListSearch		(xmlListPtr l,
 					 void *data);
-XMLPUBFUN void * XMLCALL
+XMLPUBFUN void *
 		xmlListReverseSearch	(xmlListPtr l,
 					 void *data);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlListInsert		(xmlListPtr l,
 					 void *data) ;
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlListAppend		(xmlListPtr l,
 					 void *data) ;
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlListRemoveFirst	(xmlListPtr l,
 					 void *data);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlListRemoveLast	(xmlListPtr l,
 					 void *data);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlListRemoveAll	(xmlListPtr l,
 					 void *data);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlListClear		(xmlListPtr l);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlListEmpty		(xmlListPtr l);
-XMLPUBFUN xmlLinkPtr XMLCALL
+XMLPUBFUN xmlLinkPtr
 		xmlListFront		(xmlListPtr l);
-XMLPUBFUN xmlLinkPtr XMLCALL
+XMLPUBFUN xmlLinkPtr
 		xmlListEnd		(xmlListPtr l);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlListSize		(xmlListPtr l);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlListPopFront		(xmlListPtr l);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlListPopBack		(xmlListPtr l);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlListPushFront	(xmlListPtr l,
 					 void *data);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlListPushBack		(xmlListPtr l,
 					 void *data);
 
 /* Advanced Operators */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlListReverse		(xmlListPtr l);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlListSort		(xmlListPtr l);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlListWalk		(xmlListPtr l,
 					 xmlListWalker walker,
 					 void *user);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlListReverseWalk	(xmlListPtr l,
 					 xmlListWalker walker,
 					 void *user);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlListMerge		(xmlListPtr l1,
 					 xmlListPtr l2);
-XMLPUBFUN xmlListPtr XMLCALL
-		xmlListDup		(const xmlListPtr old);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN xmlListPtr
+		xmlListDup		(xmlListPtr old);
+XMLPUBFUN int
 		xmlListCopy		(xmlListPtr cur,
-					 const xmlListPtr old);
+					 xmlListPtr old);
 /* Link operators */
-XMLPUBFUN void * XMLCALL
+XMLPUBFUN void *
 		xmlLinkGetData          (xmlLinkPtr lk);
 
 /* xmlListUnique() */
diff --git a/include/libxml/nanoftp.h b/include/libxml/nanoftp.h
index f39bde5be0729047748239003c3552dc96f49a38..ed3ac4f1fd2d68901d0066a5eae3dd904a8634ea 100644
--- a/include/libxml/nanoftp.h
+++ b/include/libxml/nanoftp.h
@@ -14,7 +14,7 @@
 
 #include <libxml/xmlversion.h>
 
-#ifdef LIBXML_FTP_ENABLED
+#if defined(LIBXML_FTP_ENABLED)
 
 /* Needed for portability to Windows 64 bits */
 #if defined(_WIN32)
@@ -80,52 +80,52 @@ typedef void (*ftpDataCallback) (void *userData,
  * Init
  */
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlNanoFTPInit		(void);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlNanoFTPCleanup	(void);
 
 /*
  * Creating/freeing contexts.
  */
 XML_DEPRECATED
-XMLPUBFUN void * XMLCALL
+XMLPUBFUN void *
 	xmlNanoFTPNewCtxt	(const char *URL);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlNanoFTPFreeCtxt	(void * ctx);
 XML_DEPRECATED
-XMLPUBFUN void * XMLCALL
+XMLPUBFUN void *
 	xmlNanoFTPConnectTo	(const char *server,
 				 int port);
 /*
  * Opening/closing session connections.
  */
 XML_DEPRECATED
-XMLPUBFUN void * XMLCALL
+XMLPUBFUN void *
 	xmlNanoFTPOpen		(const char *URL);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPConnect	(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPClose		(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPQuit		(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlNanoFTPScanProxy	(const char *URL);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlNanoFTPProxy		(const char *host,
 				 int port,
 				 const char *user,
 				 const char *passwd,
 				 int type);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPUpdateURL	(void *ctx,
 				 const char *URL);
 
@@ -133,48 +133,48 @@ XMLPUBFUN int XMLCALL
  * Rather internal commands.
  */
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPGetResponse	(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPCheckResponse	(void *ctx);
 
 /*
  * CD/DIR/GET handlers.
  */
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPCwd		(void *ctx,
 				 const char *directory);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPDele		(void *ctx,
 				 const char *file);
 
 XML_DEPRECATED
-XMLPUBFUN SOCKET XMLCALL
+XMLPUBFUN SOCKET
 	xmlNanoFTPGetConnection	(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPCloseConnection(void *ctx);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPList		(void *ctx,
 				 ftpListCallback callback,
 				 void *userData,
 				 const char *filename);
 XML_DEPRECATED
-XMLPUBFUN SOCKET XMLCALL
+XMLPUBFUN SOCKET
 	xmlNanoFTPGetSocket	(void *ctx,
 				 const char *filename);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPGet		(void *ctx,
 				 ftpDataCallback callback,
 				 void *userData,
 				 const char *filename);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlNanoFTPRead		(void *ctx,
 				 void *dest,
 				 int len);
@@ -182,5 +182,5 @@ XMLPUBFUN int XMLCALL
 #ifdef __cplusplus
 }
 #endif
-#endif /* LIBXML_FTP_ENABLED */
+#endif /* defined(LIBXML_FTP_ENABLED) || defined(LIBXML_LEGACY_ENABLED) */
 #endif /* __NANO_FTP_H__ */
diff --git a/include/libxml/nanohttp.h b/include/libxml/nanohttp.h
index 22b8fb43381c816464bcf47715db7f80a62a95d6..c70d1c26bb880ccdfcee16d2c79f69d1d3472518 100644
--- a/include/libxml/nanohttp.h
+++ b/include/libxml/nanohttp.h
@@ -18,24 +18,30 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 	xmlNanoHTTPInit		(void);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 	xmlNanoHTTPCleanup	(void);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 	xmlNanoHTTPScanProxy	(const char *URL);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlNanoHTTPFetch	(const char *URL,
 				 const char *filename,
 				 char **contentType);
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlNanoHTTPMethod	(const char *URL,
 				 const char *method,
 				 const char *input,
 				 char **contentType,
 				 const char *headers,
 				 int   ilen);
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlNanoHTTPMethodRedir	(const char *URL,
 				 const char *method,
 				 const char *input,
@@ -43,35 +49,46 @@ XMLPUBFUN void * XMLCALL
 				 char **redir,
 				 const char *headers,
 				 int   ilen);
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlNanoHTTPOpen		(const char *URL,
 				 char **contentType);
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlNanoHTTPOpenRedir	(const char *URL,
 				 char **contentType,
 				 char **redir);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlNanoHTTPReturnCode	(void *ctx);
-XMLPUBFUN const char * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN const char *
 	xmlNanoHTTPAuthHeader	(void *ctx);
-XMLPUBFUN const char * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN const char *
 	xmlNanoHTTPRedir	(void *ctx);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlNanoHTTPContentLength( void * ctx );
-XMLPUBFUN const char * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN const char *
 	xmlNanoHTTPEncoding	(void *ctx);
-XMLPUBFUN const char * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN const char *
 	xmlNanoHTTPMimeType	(void *ctx);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlNanoHTTPRead		(void *ctx,
 				 void *dest,
 				 int len);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlNanoHTTPSave		(void *ctxt,
 				 const char *filename);
 #endif /* LIBXML_OUTPUT_ENABLED */
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 	xmlNanoHTTPClose	(void *ctx);
 #ifdef __cplusplus
 }
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index 82c61d67e92967d5c9d6249238a0d810710b7b92..831aa53b42304187c2b9782939a91eba1234c535 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -10,14 +10,24 @@
 #ifndef __XML_PARSER_H__
 #define __XML_PARSER_H__
 
+/** DOC_DISABLE */
 #include <libxml/xmlversion.h>
+#define XML_TREE_INTERNALS
 #include <libxml/tree.h>
+#undef XML_TREE_INTERNALS
 #include <libxml/dict.h>
 #include <libxml/hash.h>
 #include <libxml/valid.h>
 #include <libxml/entities.h>
 #include <libxml/xmlerror.h>
 #include <libxml/xmlstring.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/encoding.h>
+#include <libxml/xmlIO.h>
+/* for compatibility */
+#include <libxml/SAX2.h>
+#include <libxml/threads.h>
+/** DOC_ENABLE */
 
 #ifdef __cplusplus
 extern "C" {
@@ -54,24 +64,21 @@ struct _xmlParserInput {
     xmlParserInputBufferPtr buf;      /* UTF-8 encoded buffer */
 
     const char *filename;             /* The file analyzed, if any */
-    const char *directory;            /* the directory/base of the file */
+    const char *directory;            /* unused */
     const xmlChar *base;              /* Base of the array to parse */
     const xmlChar *cur;               /* Current char being parsed */
     const xmlChar *end;               /* end of the array to parse */
-    int length;                       /* length if known */
+    int length;                       /* unused */
     int line;                         /* Current line */
     int col;                          /* Current column */
-    /*
-     * NOTE: consumed is only tested for equality in the parser code,
-     *       so even if there is an overflow this should not give troubles
-     *       for parsing very large instances.
-     */
     unsigned long consumed;           /* How many xmlChars already consumed */
     xmlParserInputDeallocate free;    /* function to deallocate the base */
-    const xmlChar *encoding;          /* the encoding string for entity */
+    const xmlChar *encoding;          /* unused */
     const xmlChar *version;           /* the version string for entity */
-    int standalone;                   /* Was that entity marked standalone */
+    int flags;                        /* Flags */
     int id;                           /* an unique identifier for the entity */
+    unsigned long parentConsumed;     /* unused */
+    xmlEntityPtr entity;              /* entity, if any */
 };
 
 /**
@@ -125,33 +132,18 @@ typedef enum {
     XML_PARSER_SYSTEM_LITERAL,	/* within a SYSTEM value */
     XML_PARSER_EPILOG,		/* the Misc* after the last end tag */
     XML_PARSER_IGNORE,		/* within an IGNORED section */
-    XML_PARSER_PUBLIC_LITERAL	/* within a PUBLIC value */
+    XML_PARSER_PUBLIC_LITERAL,	/* within a PUBLIC value */
+    XML_PARSER_XML_DECL         /* before XML decl (but after BOM) */
 } xmlParserInputState;
 
-/**
- * XML_DETECT_IDS:
- *
- * Bit in the loadsubset context field to tell to do ID/REFs lookups.
- * Use it to initialize xmlLoadExtDtdDefaultValue.
+/** DOC_DISABLE */
+/*
+ * Internal bits in the 'loadsubset' context member
  */
 #define XML_DETECT_IDS		2
-
-/**
- * XML_COMPLETE_ATTRS:
- *
- * Bit in the loadsubset context field to tell to do complete the
- * elements attributes lists with the ones defaulted from the DTDs.
- * Use it to initialize xmlLoadExtDtdDefaultValue.
- */
 #define XML_COMPLETE_ATTRS	4
-
-/**
- * XML_SKIP_IDS:
- *
- * Bit in the loadsubset context field to tell to not do ID/REFs registration.
- * Used to initialize xmlLoadExtDtdDefaultValue in some special cases.
- */
 #define XML_SKIP_IDS		8
+/** DOC_ENABLE */
 
 /**
  * xmlParserMode:
@@ -168,6 +160,8 @@ typedef enum {
 } xmlParserMode;
 
 typedef struct _xmlStartTag xmlStartTag;
+typedef struct _xmlParserNsData xmlParserNsData;
+typedef struct _xmlAttrHashBucket xmlAttrHashBucket;
 
 /**
  * xmlParserCtxt:
@@ -214,16 +208,16 @@ struct _xmlParserCtxt {
 
     int     hasExternalSubset;        /* reference and external subset */
     int             hasPErefs;        /* the internal subset has PE refs */
-    int              external;        /* are we parsing an external entity */
+    int              external;        /* unused */
 
     int                 valid;        /* is the document valid */
     int              validate;        /* shall we try to validate ? */
     xmlValidCtxt        vctxt;        /* The validity context */
 
-    xmlParserInputState instate;      /* current type of input */
-    int                 token;        /* next char look-ahead */
+    xmlParserInputState instate;      /* push parser state */
+    int                 token;        /* unused */
 
-    char           *directory;        /* the data directory */
+    char           *directory;        /* unused */
 
     /* Node name stack */
     const xmlChar     *name;          /* Current parsed Node */
@@ -247,9 +241,8 @@ struct _xmlParserCtxt {
     int *              spaceTab;      /* array of space infos */
 
     int                depth;         /* to prevent entity substitution loops */
-    xmlParserInputPtr  entity;        /* used to check entities boundaries */
-    int                charset;       /* encoding of the in-memory content
-				         actually an xmlCharEncoding */
+    xmlParserInputPtr  entity;        /* unused */
+    int                charset;       /* unused */
     int                nodelen;       /* Those two fields are there to */
     int                nodemem;       /* Speed up large node parsing */
     int                pedantic;      /* signal pedantic warnings */
@@ -259,11 +252,11 @@ struct _xmlParserCtxt {
     int                linenumbers;   /* set line number in element content */
     void              *catalogs;      /* document's own catalog */
     int                recovery;      /* run in recovery mode */
-    int                progressive;   /* is this a progressive parsing */
+    int                progressive;   /* unused */
     xmlDictPtr         dict;          /* dictionary for the parser */
     const xmlChar *   *atts;          /* array for the attributes callbacks */
     int                maxatts;       /* the size of the array */
-    int                docdict;       /* use strings from dict to build tree */
+    int                docdict;       /* unused */
 
     /*
      * pre-interned strings
@@ -279,7 +272,7 @@ struct _xmlParserCtxt {
     int                nsNr;          /* the number of inherited namespaces */
     int                nsMax;         /* the size of the arrays */
     const xmlChar *   *nsTab;         /* the array of prefix/namespace name */
-    int               *attallocs;     /* which attribute were allocated */
+    unsigned          *attallocs;     /* which attribute were allocated */
     xmlStartTag       *pushTab;       /* array of data for push */
     xmlHashTablePtr    attsDefault;   /* defaulted attributes if any */
     xmlHashTablePtr    attsSpecial;   /* non-CDATA attributes if any */
@@ -300,8 +293,8 @@ struct _xmlParserCtxt {
      */
     xmlError          lastError;
     xmlParserMode     parseMode;    /* the parser mode */
-    unsigned long    nbentities;    /* number of entities references */
-    unsigned long  sizeentities;    /* size of parsed entities */
+    unsigned long    nbentities;    /* unused */
+    unsigned long  sizeentities;    /* size of external entities */
 
     /* for use by HTML non-recursive parser */
     xmlParserNodeInfo *nodeInfo;      /* Current NodeInfo */
@@ -311,6 +304,18 @@ struct _xmlParserCtxt {
 
     int                input_id;      /* we need to label inputs */
     unsigned long      sizeentcopy;   /* volume of entity copy */
+
+    int           endCheckState;    /* quote state for push parser */
+    unsigned short     nbErrors;    /* number of errors */
+    unsigned short   nbWarnings;    /* number of warnings */
+    unsigned            maxAmpl;    /* maximum amplification factor */
+
+    xmlParserNsData       *nsdb;    /* namespace database */
+    unsigned        attrHashMax;    /* allocated size */
+    xmlAttrHashBucket *attrHash;    /* atttribute hash table */
+
+    xmlStructuredErrorFunc errorHandler;
+    void *errorCtxt;
 };
 
 /**
@@ -605,7 +610,7 @@ typedef void (*cdataBlockSAXFunc) (
  *
  * Display and format a warning messages, callback.
  */
-typedef void (XMLCDECL *warningSAXFunc) (void *ctx,
+typedef void (*warningSAXFunc) (void *ctx,
 				const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
 /**
  * errorSAXFunc:
@@ -615,7 +620,7 @@ typedef void (XMLCDECL *warningSAXFunc) (void *ctx,
  *
  * Display and format an error messages, callback.
  */
-typedef void (XMLCDECL *errorSAXFunc) (void *ctx,
+typedef void (*errorSAXFunc) (void *ctx,
 				const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
 /**
  * fatalErrorSAXFunc:
@@ -627,7 +632,7 @@ typedef void (XMLCDECL *errorSAXFunc) (void *ctx,
  * Note: so far fatalError() SAX callbacks are not used, error()
  *       get all the callbacks for errors.
  */
-typedef void (XMLCDECL *fatalErrorSAXFunc) (void *ctx,
+typedef void (*fatalErrorSAXFunc) (void *ctx,
 				const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
 /**
  * isStandaloneSAXFunc:
@@ -731,6 +736,19 @@ struct _xmlSAXHandler {
     setDocumentLocatorSAXFunc setDocumentLocator;
     startDocumentSAXFunc startDocument;
     endDocumentSAXFunc endDocument;
+    /*
+     * `startElement` and `endElement` are only used by the legacy SAX1
+     * interface and should not be used in new software. If you really
+     * have to enable SAX1, the preferred way is set the `initialized`
+     * member to 1 instead of XML_SAX2_MAGIC.
+     *
+     * For backward compatibility, it's also possible to set the
+     * `startElementNs` and `endElementNs` handlers to NULL.
+     *
+     * You can also set the XML_PARSE_SAX1 parser option, but versions
+     * older than 2.12.0 will probably crash if this option is provided
+     * together with custom SAX callbacks.
+     */
     startElementSAXFunc startElement;
     endElementSAXFunc endElement;
     referenceSAXFunc reference;
@@ -744,8 +762,14 @@ struct _xmlSAXHandler {
     getParameterEntitySAXFunc getParameterEntity;
     cdataBlockSAXFunc cdataBlock;
     externalSubsetSAXFunc externalSubset;
+    /*
+     * `initialized` should always be set to XML_SAX2_MAGIC to enable the
+     * modern SAX2 interface.
+     */
     unsigned int initialized;
-    /* The following fields are extensions available only on version 2 */
+    /*
+     * The following members are only used by the SAX2 interface.
+     */
     void *_private;
     startElementNsSAX2Func startElementNs;
     endElementNsSAX2Func endElementNs;
@@ -803,34 +827,119 @@ typedef xmlParserInputPtr (*xmlExternalEntityLoader) (const char *URL,
 					 const char *ID,
 					 xmlParserCtxtPtr context);
 
-#ifdef __cplusplus
-}
+/*
+ * Variables
+ */
+
+XMLPUBVAR const char *const xmlParserVersion;
+XML_DEPRECATED
+XMLPUBVAR const int oldXMLWDcompatibility;
+XML_DEPRECATED
+XMLPUBVAR const int xmlParserDebugEntities;
+XML_DEPRECATED
+XMLPUBVAR const xmlSAXLocator xmlDefaultSAXLocator;
+#ifdef LIBXML_SAX1_ENABLED
+XML_DEPRECATED
+XMLPUBVAR const xmlSAXHandlerV1 xmlDefaultSAXHandler;
 #endif
 
-#include <libxml/encoding.h>
-#include <libxml/xmlIO.h>
-#include <libxml/globals.h>
+#ifdef LIBXML_THREAD_ENABLED
+/* backward compatibility */
+XMLPUBFUN const char *const *__xmlParserVersion(void);
+XML_DEPRECATED
+XMLPUBFUN const int *__oldXMLWDcompatibility(void);
+XML_DEPRECATED
+XMLPUBFUN const int *__xmlParserDebugEntities(void);
+XML_DEPRECATED
+XMLPUBFUN const xmlSAXLocator *__xmlDefaultSAXLocator(void);
+#ifdef LIBXML_SAX1_ENABLED
+XML_DEPRECATED
+XMLPUBFUN const xmlSAXHandlerV1 *__xmlDefaultSAXHandler(void);
+#endif
+#endif
 
-#ifdef __cplusplus
-extern "C" {
+/** DOC_DISABLE */
+#define XML_GLOBALS_PARSER_CORE \
+  XML_OP(xmlDoValidityCheckingDefaultValue, int, XML_DEPRECATED) \
+  XML_OP(xmlGetWarningsDefaultValue, int, XML_DEPRECATED) \
+  XML_OP(xmlKeepBlanksDefaultValue, int, XML_DEPRECATED) \
+  XML_OP(xmlLineNumbersDefaultValue, int, XML_DEPRECATED) \
+  XML_OP(xmlLoadExtDtdDefaultValue, int, XML_DEPRECATED) \
+  XML_OP(xmlPedanticParserDefaultValue, int, XML_DEPRECATED) \
+  XML_OP(xmlSubstituteEntitiesDefaultValue, int, XML_DEPRECATED)
+
+#ifdef LIBXML_OUTPUT_ENABLED
+  #define XML_GLOBALS_PARSER_OUTPUT \
+    XML_OP(xmlIndentTreeOutput, int, XML_NO_ATTR) \
+    XML_OP(xmlTreeIndentString, const char *, XML_NO_ATTR) \
+    XML_OP(xmlSaveNoEmptyTags, int, XML_NO_ATTR)
+#else
+  #define XML_GLOBALS_PARSER_OUTPUT
 #endif
 
+#define XML_GLOBALS_PARSER \
+  XML_GLOBALS_PARSER_CORE \
+  XML_GLOBALS_PARSER_OUTPUT
+
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_PARSER
+#undef XML_OP
+
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+  #define xmlDoValidityCheckingDefaultValue \
+    XML_GLOBAL_MACRO(xmlDoValidityCheckingDefaultValue)
+  #define xmlGetWarningsDefaultValue \
+    XML_GLOBAL_MACRO(xmlGetWarningsDefaultValue)
+  #define xmlKeepBlanksDefaultValue XML_GLOBAL_MACRO(xmlKeepBlanksDefaultValue)
+  #define xmlLineNumbersDefaultValue \
+    XML_GLOBAL_MACRO(xmlLineNumbersDefaultValue)
+  #define xmlLoadExtDtdDefaultValue XML_GLOBAL_MACRO(xmlLoadExtDtdDefaultValue)
+  #define xmlPedanticParserDefaultValue \
+    XML_GLOBAL_MACRO(xmlPedanticParserDefaultValue)
+  #define xmlSubstituteEntitiesDefaultValue \
+    XML_GLOBAL_MACRO(xmlSubstituteEntitiesDefaultValue)
+  #ifdef LIBXML_OUTPUT_ENABLED
+    #define xmlIndentTreeOutput XML_GLOBAL_MACRO(xmlIndentTreeOutput)
+    #define xmlTreeIndentString XML_GLOBAL_MACRO(xmlTreeIndentString)
+    #define xmlSaveNoEmptyTags XML_GLOBAL_MACRO(xmlSaveNoEmptyTags)
+  #endif
+#else
+#define xmlDoValidityCheckingDefaultValue vtklibxml2_xmlDoValidityCheckingDefaultValue
+#define xmlGetWarningsDefaultValue vtklibxml2_xmlGetWarningsDefaultValue
+#define xmlKeepBlanksDefaultValue vtklibxml2_xmlKeepBlanksDefaultValue
+#define xmlLineNumbersDefaultValue vtklibxml2_xmlLineNumbersDefaultValue
+#define xmlLoadExtDtdDefaultValue vtklibxml2_xmlLoadExtDtdDefaultValue
+#define xmlPedanticParserDefaultValue vtklibxml2_xmlPedanticParserDefaultValue
+#define xmlSubstituteEntitiesDefaultValue vtklibxml2_xmlSubstituteEntitiesDefaultValue
+#define xmlIndentTreeOutput vtklibxml2_xmlIndentTreeOutput
+#define xmlTreeIndentString vtklibxml2_xmlTreeIndentString
+#define xmlSaveNoEmptyTags vtklibxml2_xmlSaveNoEmptyTags
+#endif
+/** DOC_ENABLE */
 
 /*
  * Init/Cleanup
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlInitParser		(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlCleanupParser	(void);
+XML_DEPRECATED
+XMLPUBFUN void
+		xmlInitGlobals		(void);
+XML_DEPRECATED
+XMLPUBFUN void
+		xmlCleanupGlobals	(void);
 
 /*
  * Input functions
  */
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlParserInputRead	(xmlParserInputPtr in,
 					 int len);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlParserInputGrow	(xmlParserInputPtr in,
 					 int len);
 
@@ -838,101 +947,130 @@ XMLPUBFUN int XMLCALL
  * Basic parsing Interfaces
  */
 #ifdef LIBXML_SAX1_ENABLED
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlParseDoc		(const xmlChar *cur);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlParseFile		(const char *filename);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlParseMemory		(const char *buffer,
 					 int size);
 #endif /* LIBXML_SAX1_ENABLED */
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED XMLPUBFUN int
 		xmlSubstituteEntitiesDefault(int val);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED XMLPUBFUN int
+                xmlThrDefSubstituteEntitiesDefaultValue(int v);
+XMLPUBFUN int
 		xmlKeepBlanksDefault	(int val);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED XMLPUBFUN int
+		xmlThrDefKeepBlanksDefaultValue(int v);
+XMLPUBFUN void
 		xmlStopParser		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED XMLPUBFUN int
 		xmlPedanticParserDefault(int val);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED XMLPUBFUN int
+                xmlThrDefPedanticParserDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int
 		xmlLineNumbersDefault	(int val);
+XML_DEPRECATED XMLPUBFUN int
+                xmlThrDefLineNumbersDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int
+                xmlThrDefDoValidityCheckingDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int
+                xmlThrDefGetWarningsDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int
+                xmlThrDefLoadExtDtdDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int
+                xmlThrDefParserDebugEntities(int v);
 
 #ifdef LIBXML_SAX1_ENABLED
 /*
  * Recovery mode
  */
-XMLPUBFUN xmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDocPtr
 		xmlRecoverDoc		(const xmlChar *cur);
-XMLPUBFUN xmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDocPtr
 		xmlRecoverMemory	(const char *buffer,
 					 int size);
-XMLPUBFUN xmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDocPtr
 		xmlRecoverFile		(const char *filename);
 #endif /* LIBXML_SAX1_ENABLED */
 
 /*
  * Less common routines and SAX interfaces
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlParseDocument	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlParseExtParsedEnt	(xmlParserCtxtPtr ctxt);
 #ifdef LIBXML_SAX1_ENABLED
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlSAXUserParseFile	(xmlSAXHandlerPtr sax,
 					 void *user_data,
 					 const char *filename);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlSAXUserParseMemory	(xmlSAXHandlerPtr sax,
 					 void *user_data,
 					 const char *buffer,
 					 int size);
-XMLPUBFUN xmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDocPtr
 		xmlSAXParseDoc		(xmlSAXHandlerPtr sax,
 					 const xmlChar *cur,
 					 int recovery);
-XMLPUBFUN xmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDocPtr
 		xmlSAXParseMemory	(xmlSAXHandlerPtr sax,
 					 const char *buffer,
 					 int size,
 					 int recovery);
-XMLPUBFUN xmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDocPtr
 		xmlSAXParseMemoryWithData (xmlSAXHandlerPtr sax,
 					 const char *buffer,
 					 int size,
 					 int recovery,
 					 void *data);
-XMLPUBFUN xmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDocPtr
 		xmlSAXParseFile		(xmlSAXHandlerPtr sax,
 					 const char *filename,
 					 int recovery);
-XMLPUBFUN xmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDocPtr
 		xmlSAXParseFileWithData	(xmlSAXHandlerPtr sax,
 					 const char *filename,
 					 int recovery,
 					 void *data);
-XMLPUBFUN xmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDocPtr
 		xmlSAXParseEntity	(xmlSAXHandlerPtr sax,
 					 const char *filename);
-XMLPUBFUN xmlDocPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDocPtr
 		xmlParseEntity		(const char *filename);
 #endif /* LIBXML_SAX1_ENABLED */
 
 #ifdef LIBXML_VALID_ENABLED
-XMLPUBFUN xmlDtdPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlDtdPtr
 		xmlSAXParseDTD		(xmlSAXHandlerPtr sax,
 					 const xmlChar *ExternalID,
 					 const xmlChar *SystemID);
-XMLPUBFUN xmlDtdPtr XMLCALL
+XMLPUBFUN xmlDtdPtr
 		xmlParseDTD		(const xmlChar *ExternalID,
 					 const xmlChar *SystemID);
-XMLPUBFUN xmlDtdPtr XMLCALL
+XMLPUBFUN xmlDtdPtr
 		xmlIOParseDTD		(xmlSAXHandlerPtr sax,
 					 xmlParserInputBufferPtr input,
 					 xmlCharEncoding enc);
 #endif /* LIBXML_VALID_ENABLE */
 #ifdef LIBXML_SAX1_ENABLED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlParseBalancedChunkMemory(xmlDocPtr doc,
 					 xmlSAXHandlerPtr sax,
 					 void *user_data,
@@ -940,14 +1078,14 @@ XMLPUBFUN int XMLCALL
 					 const xmlChar *string,
 					 xmlNodePtr *lst);
 #endif /* LIBXML_SAX1_ENABLED */
-XMLPUBFUN xmlParserErrors XMLCALL
+XMLPUBFUN xmlParserErrors
 		xmlParseInNodeContext	(xmlNodePtr node,
 					 const char *data,
 					 int datalen,
 					 int options,
 					 xmlNodePtr *lst);
 #ifdef LIBXML_SAX1_ENABLED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc,
                      xmlSAXHandlerPtr sax,
                      void *user_data,
@@ -955,7 +1093,8 @@ XMLPUBFUN int XMLCALL
                      const xmlChar *string,
                      xmlNodePtr *lst,
                      int recover);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlParseExternalEntity	(xmlDocPtr doc,
 					 xmlSAXHandlerPtr sax,
 					 void *user_data,
@@ -964,7 +1103,7 @@ XMLPUBFUN int XMLCALL
 					 const xmlChar *ID,
 					 xmlNodePtr *lst);
 #endif /* LIBXML_SAX1_ENABLED */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx,
 					 const xmlChar *URL,
 					 const xmlChar *ID,
@@ -973,21 +1112,25 @@ XMLPUBFUN int XMLCALL
 /*
  * Parser contexts handling.
  */
-XMLPUBFUN xmlParserCtxtPtr XMLCALL
+XMLPUBFUN xmlParserCtxtPtr
 		xmlNewParserCtxt	(void);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN xmlParserCtxtPtr
+		xmlNewSAXParserCtxt	(const xmlSAXHandler *sax,
+					 void *userData);
+XMLPUBFUN int
 		xmlInitParserCtxt	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlClearParserCtxt	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeParserCtxt	(xmlParserCtxtPtr ctxt);
 #ifdef LIBXML_SAX1_ENABLED
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 		xmlSetupParserForBuffer	(xmlParserCtxtPtr ctxt,
 					 const xmlChar* buffer,
 					 const char *filename);
 #endif /* LIBXML_SAX1_ENABLED */
-XMLPUBFUN xmlParserCtxtPtr XMLCALL
+XMLPUBFUN xmlParserCtxtPtr
 		xmlCreateDocParserCtxt	(const xmlChar *cur);
 
 #ifdef LIBXML_LEGACY_ENABLED
@@ -995,16 +1138,16 @@ XMLPUBFUN xmlParserCtxtPtr XMLCALL
  * Reading/setting optional parsing features.
  */
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlGetFeaturesList	(int *len,
 					 const char **result);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlGetFeature		(xmlParserCtxtPtr ctxt,
 					 const char *name,
 					 void *result);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSetFeature		(xmlParserCtxtPtr ctxt,
 					 const char *name,
 					 void *value);
@@ -1014,13 +1157,13 @@ XMLPUBFUN int XMLCALL
 /*
  * Interfaces for the Push mode.
  */
-XMLPUBFUN xmlParserCtxtPtr XMLCALL
+XMLPUBFUN xmlParserCtxtPtr
 		xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax,
 					 void *user_data,
 					 const char *chunk,
 					 int size,
 					 const char *filename);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlParseChunk		(xmlParserCtxtPtr ctxt,
 					 const char *chunk,
 					 int size,
@@ -1031,7 +1174,7 @@ XMLPUBFUN int XMLCALL
  * Special I/O mode.
  */
 
-XMLPUBFUN xmlParserCtxtPtr XMLCALL
+XMLPUBFUN xmlParserCtxtPtr
 		xmlCreateIOParserCtxt	(xmlSAXHandlerPtr sax,
 					 void *user_data,
 					 xmlInputReadCallback   ioread,
@@ -1039,7 +1182,7 @@ XMLPUBFUN xmlParserCtxtPtr XMLCALL
 					 void *ioctx,
 					 xmlCharEncoding enc);
 
-XMLPUBFUN xmlParserInputPtr XMLCALL
+XMLPUBFUN xmlParserInputPtr
 		xmlNewIOInputStream	(xmlParserCtxtPtr ctxt,
 					 xmlParserInputBufferPtr input,
 					 xmlCharEncoding enc);
@@ -1047,29 +1190,29 @@ XMLPUBFUN xmlParserInputPtr XMLCALL
 /*
  * Node infos.
  */
-XMLPUBFUN const xmlParserNodeInfo* XMLCALL
-		xmlParserFindNodeInfo	(const xmlParserCtxtPtr ctxt,
-				         const xmlNodePtr node);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN const xmlParserNodeInfo*
+		xmlParserFindNodeInfo	(xmlParserCtxtPtr ctxt,
+				         xmlNodePtr node);
+XMLPUBFUN void
 		xmlInitNodeInfoSeq	(xmlParserNodeInfoSeqPtr seq);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlClearNodeInfoSeq	(xmlParserNodeInfoSeqPtr seq);
-XMLPUBFUN unsigned long XMLCALL
-		xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq,
-                                         const xmlNodePtr node);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN unsigned long
+		xmlParserFindNodeInfoIndex(xmlParserNodeInfoSeqPtr seq,
+                                         xmlNodePtr node);
+XMLPUBFUN void
 		xmlParserAddNodeInfo	(xmlParserCtxtPtr ctxt,
-					 const xmlParserNodeInfoPtr info);
+					 xmlParserNodeInfoPtr info);
 
 /*
  * External entities handling actually implemented in xmlIO.
  */
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSetExternalEntityLoader(xmlExternalEntityLoader f);
-XMLPUBFUN xmlExternalEntityLoader XMLCALL
+XMLPUBFUN xmlExternalEntityLoader
 		xmlGetExternalEntityLoader(void);
-XMLPUBFUN xmlParserInputPtr XMLCALL
+XMLPUBFUN xmlParserInputPtr
 		xmlLoadExternalEntity	(const char *URL,
 					 const char *ID,
 					 xmlParserCtxtPtr ctxt);
@@ -1077,7 +1220,7 @@ XMLPUBFUN xmlParserInputPtr XMLCALL
 /*
  * Index lookup, actually implemented in the encoding module
  */
-XMLPUBFUN long XMLCALL
+XMLPUBFUN long
 		xmlByteConsumed		(xmlParserCtxtPtr ctxt);
 
 /*
@@ -1114,72 +1257,86 @@ typedef enum {
     XML_PARSE_HUGE      = 1<<19,/* relax any hardcoded limit from the parser */
     XML_PARSE_OLDSAX    = 1<<20,/* parse using SAX2 interface before 2.7.0 */
     XML_PARSE_IGNORE_ENC= 1<<21,/* ignore internal document encoding hint */
-    XML_PARSE_BIG_LINES = 1<<22 /* Store big lines numbers in text PSVI field */
+    XML_PARSE_BIG_LINES = 1<<22,/* Store big lines numbers in text PSVI field */
+    XML_PARSE_NO_XXE    = 1<<23 /* disable loading of external content */
 } xmlParserOption;
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlCtxtReset		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlCtxtResetPush	(xmlParserCtxtPtr ctxt,
 					 const char *chunk,
 					 int size,
 					 const char *filename,
 					 const char *encoding);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
+		xmlCtxtSetOptions	(xmlParserCtxtPtr ctxt,
+					 int options);
+XMLPUBFUN int
 		xmlCtxtUseOptions	(xmlParserCtxtPtr ctxt,
 					 int options);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN void
+		xmlCtxtSetErrorHandler	(xmlParserCtxtPtr ctxt,
+					 xmlStructuredErrorFunc handler,
+					 void *data);
+XMLPUBFUN void
+		xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt,
+					 unsigned maxAmpl);
+XMLPUBFUN xmlDocPtr
 		xmlReadDoc		(const xmlChar *cur,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlReadFile		(const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlReadMemory		(const char *buffer,
 					 int size,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlReadFd		(int fd,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlReadIO		(xmlInputReadCallback ioread,
 					 xmlInputCloseCallback ioclose,
 					 void *ioctx,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
+		xmlCtxtParseDocument	(xmlParserCtxtPtr ctxt,
+					 xmlParserInputPtr input);
+XMLPUBFUN xmlDocPtr
 		xmlCtxtReadDoc		(xmlParserCtxtPtr ctxt,
 					 const xmlChar *cur,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlCtxtReadFile		(xmlParserCtxtPtr ctxt,
 					 const char *filename,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlCtxtReadMemory		(xmlParserCtxtPtr ctxt,
 					 const char *buffer,
 					 int size,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlCtxtReadFd		(xmlParserCtxtPtr ctxt,
 					 int fd,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlCtxtReadIO		(xmlParserCtxtPtr ctxt,
 					 xmlInputReadCallback ioread,
 					 xmlInputCloseCallback ioclose,
@@ -1228,14 +1385,14 @@ typedef enum {
     XML_WITH_MODULES = 27,
     XML_WITH_DEBUG = 28,
     XML_WITH_DEBUG_MEM = 29,
-    XML_WITH_DEBUG_RUN = 30,
+    XML_WITH_DEBUG_RUN = 30, /* unused */
     XML_WITH_ZLIB = 31,
     XML_WITH_ICU = 32,
     XML_WITH_LZMA = 33,
     XML_WITH_NONE = 99999 /* just to be sure of allocation size */
 } xmlFeature;
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlHasFeature		(xmlFeature feature);
 
 #ifdef __cplusplus
diff --git a/include/libxml/parserInternals.h b/include/libxml/parserInternals.h
index 656ee4625c3f1c639eb1c954a19ac13ac3635181..c4d4363b53aa04269ac55c186c1d447494fded68 100644
--- a/include/libxml/parserInternals.h
+++ b/include/libxml/parserInternals.h
@@ -16,6 +16,7 @@
 #include <libxml/parser.h>
 #include <libxml/HTMLparser.h>
 #include <libxml/chvalid.h>
+#include <libxml/SAX2.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -24,11 +25,14 @@ extern "C" {
 /**
  * xmlParserMaxDepth:
  *
+ * DEPRECATED: has no effect
+ *
  * arbitrary depth limit for the XML documents that we allow to
  * process. This is not a limitation of the parser but a safety
  * boundary feature, use XML_PARSE_HUGE option to override it.
  */
-XMLPUBVAR unsigned int xmlParserMaxDepth;
+XML_DEPRECATED
+XMLPUBVAR const unsigned int xmlParserMaxDepth;
 
 /**
  * XML_MAX_TEXT_LENGTH:
@@ -40,6 +44,13 @@ XMLPUBVAR unsigned int xmlParserMaxDepth;
  */
 #define XML_MAX_TEXT_LENGTH 10000000
 
+/**
+ * XML_MAX_HUGE_LENGTH:
+ *
+ * Maximum size allowed when XML_PARSE_HUGE is set.
+ */
+#define XML_MAX_HUGE_LENGTH 1000000000
+
 /**
  * XML_MAX_NAME_LENGTH:
  *
@@ -278,34 +289,6 @@ XMLPUBVAR unsigned int xmlParserMaxDepth;
  */
 #define IS_PUBIDCHAR_CH(c) xmlIsPubidChar_ch(c)
 
-/**
- * SKIP_EOL:
- * @p:  and UTF8 string pointer
- *
- * Skips the end of line chars.
- */
-#define SKIP_EOL(p)							\
-    if (*(p) == 0x13) { p++ ; if (*(p) == 0x10) p++; }			\
-    if (*(p) == 0x10) { p++ ; if (*(p) == 0x13) p++; }
-
-/**
- * MOVETO_ENDTAG:
- * @p:  and UTF8 string pointer
- *
- * Skips to the next '>' char.
- */
-#define MOVETO_ENDTAG(p)						\
-    while ((*p) && (*(p) != '>')) (p)++
-
-/**
- * MOVETO_STARTTAG:
- * @p:  and UTF8 string pointer
- *
- * Skips to the next '<' char.
- */
-#define MOVETO_STARTTAG(p)						\
-    while ((*p) && (*(p) != '<')) (p)++
-
 /**
  * Global variables used for predefined strings.
  */
@@ -316,71 +299,67 @@ XMLPUBVAR const xmlChar xmlStringComment[];
 /*
  * Function to finish the work of the macros where needed.
  */
-XMLPUBFUN int XMLCALL                   xmlIsLetter     (int c);
+XMLPUBFUN int                   xmlIsLetter     (int c);
 
 /**
  * Parser context.
  */
-XMLPUBFUN xmlParserCtxtPtr XMLCALL
+XMLPUBFUN xmlParserCtxtPtr
 			xmlCreateFileParserCtxt	(const char *filename);
-XMLPUBFUN xmlParserCtxtPtr XMLCALL
+XMLPUBFUN xmlParserCtxtPtr
 			xmlCreateURLParserCtxt	(const char *filename,
 						 int options);
-XMLPUBFUN xmlParserCtxtPtr XMLCALL
+XMLPUBFUN xmlParserCtxtPtr
 			xmlCreateMemoryParserCtxt(const char *buffer,
 						 int size);
-XMLPUBFUN xmlParserCtxtPtr XMLCALL
+XMLPUBFUN xmlParserCtxtPtr
 			xmlCreateEntityParserCtxt(const xmlChar *URL,
 						 const xmlChar *ID,
 						 const xmlChar *base);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN void
+			xmlCtxtErrMemory	(xmlParserCtxtPtr ctxt);
+XMLPUBFUN int
 			xmlSwitchEncoding	(xmlParserCtxtPtr ctxt,
 						 xmlCharEncoding enc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
+			xmlSwitchEncodingName	(xmlParserCtxtPtr ctxt,
+						 const char *encoding);
+XMLPUBFUN int
 			xmlSwitchToEncoding	(xmlParserCtxtPtr ctxt,
 					 xmlCharEncodingHandlerPtr handler);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlSwitchInputEncoding	(xmlParserCtxtPtr ctxt,
 						 xmlParserInputPtr input,
 					 xmlCharEncodingHandlerPtr handler);
 
-#ifdef IN_LIBXML
-/* internal error reporting */
-XMLPUBFUN void XMLCALL
-			__xmlErrEncoding	(xmlParserCtxtPtr ctxt,
-						 xmlParserErrors xmlerr,
-						 const char *msg,
-						 const xmlChar * str1,
-						 const xmlChar * str2) LIBXML_ATTR_FORMAT(3,0);
-#endif
-
 /**
  * Input Streams.
  */
-XMLPUBFUN xmlParserInputPtr XMLCALL
+XMLPUBFUN xmlParserInputPtr
 			xmlNewStringInputStream	(xmlParserCtxtPtr ctxt,
 						 const xmlChar *buffer);
-XMLPUBFUN xmlParserInputPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlParserInputPtr
 			xmlNewEntityInputStream	(xmlParserCtxtPtr ctxt,
 						 xmlEntityPtr entity);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlPushInput		(xmlParserCtxtPtr ctxt,
 						 xmlParserInputPtr input);
-XMLPUBFUN xmlChar XMLCALL
+XMLPUBFUN xmlChar
 			xmlPopInput		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlFreeInputStream	(xmlParserInputPtr input);
-XMLPUBFUN xmlParserInputPtr XMLCALL
+XMLPUBFUN xmlParserInputPtr
 			xmlNewInputFromFile	(xmlParserCtxtPtr ctxt,
 						 const char *filename);
-XMLPUBFUN xmlParserInputPtr XMLCALL
+XMLPUBFUN xmlParserInputPtr
 			xmlNewInputStream	(xmlParserCtxtPtr ctxt);
 
 /**
  * Namespaces.
  */
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlSplitQName		(xmlParserCtxtPtr ctxt,
 						 const xmlChar *name,
 						 xmlChar **prefix);
@@ -388,109 +367,151 @@ XMLPUBFUN xmlChar * XMLCALL
 /**
  * Generic production rules.
  */
-XMLPUBFUN const xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN const xmlChar *
 			xmlParseName		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 			xmlParseNmtoken		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 			xmlParseEntityValue	(xmlParserCtxtPtr ctxt,
 						 xmlChar **orig);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 			xmlParseAttValue	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 			xmlParseSystemLiteral	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 			xmlParsePubidLiteral	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseCharData	(xmlParserCtxtPtr ctxt,
 						 int cdata);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 			xmlParseExternalID	(xmlParserCtxtPtr ctxt,
 						 xmlChar **publicID,
 						 int strict);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseComment		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN const xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN const xmlChar *
 			xmlParsePITarget	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParsePI		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseNotationDecl	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseEntityDecl	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			xmlParseDefaultDecl	(xmlParserCtxtPtr ctxt,
 						 xmlChar **value);
-XMLPUBFUN xmlEnumerationPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlEnumerationPtr
 			xmlParseNotationType	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN xmlEnumerationPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlEnumerationPtr
 			xmlParseEnumerationType	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			xmlParseEnumeratedType	(xmlParserCtxtPtr ctxt,
 						 xmlEnumerationPtr *tree);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			xmlParseAttributeType	(xmlParserCtxtPtr ctxt,
 						 xmlEnumerationPtr *tree);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt);
-XMLPUBFUN xmlElementContentPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlElementContentPtr
 			xmlParseElementMixedContentDecl
 						(xmlParserCtxtPtr ctxt,
 						 int inputchk);
-XMLPUBFUN xmlElementContentPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlElementContentPtr
 			xmlParseElementChildrenContentDecl
 						(xmlParserCtxtPtr ctxt,
 						 int inputchk);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			xmlParseElementContentDecl(xmlParserCtxtPtr ctxt,
 						 const xmlChar *name,
 						 xmlElementContentPtr *result);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			xmlParseElementDecl	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseMarkupDecl	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			xmlParseCharRef		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN xmlEntityPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlEntityPtr
 			xmlParseEntityRef	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseReference	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParsePEReference	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseDocTypeDecl	(xmlParserCtxtPtr ctxt);
 #ifdef LIBXML_SAX1_ENABLED
-XMLPUBFUN const xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN const xmlChar *
 			xmlParseAttribute	(xmlParserCtxtPtr ctxt,
 						 xmlChar **value);
-XMLPUBFUN const xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN const xmlChar *
 			xmlParseStartTag	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseEndTag		(xmlParserCtxtPtr ctxt);
 #endif /* LIBXML_SAX1_ENABLED */
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseCDSect		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlParseContent		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseElement		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 			xmlParseVersionNum	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 			xmlParseVersionInfo	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 			xmlParseEncName		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN const xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN const xmlChar *
 			xmlParseEncodingDecl	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			xmlParseSDDecl		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseXMLDecl		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseTextDecl	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 			xmlParseMisc		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlParseExternalSubset	(xmlParserCtxtPtr ctxt,
 						 const xmlChar *ExternalID,
 						 const xmlChar *SystemID);
@@ -519,14 +540,16 @@ XMLPUBFUN void XMLCALL
  */
 #define XML_SUBSTITUTE_BOTH	3
 
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 		xmlStringDecodeEntities		(xmlParserCtxtPtr ctxt,
 						 const xmlChar *str,
 						 int what,
 						 xmlChar end,
 						 xmlChar  end2,
 						 xmlChar end3);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 		xmlStringLenDecodeEntities	(xmlParserCtxtPtr ctxt,
 						 const xmlChar *str,
 						 int len,
@@ -538,48 +561,49 @@ XMLPUBFUN xmlChar * XMLCALL
 /*
  * Generated by MACROS on top of parser.c c.f. PUSH_AND_POP.
  */
-XMLPUBFUN int XMLCALL			nodePush		(xmlParserCtxtPtr ctxt,
+XML_DEPRECATED
+XMLPUBFUN int			nodePush		(xmlParserCtxtPtr ctxt,
 						 xmlNodePtr value);
-XMLPUBFUN xmlNodePtr XMLCALL		nodePop			(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL			inputPush		(xmlParserCtxtPtr ctxt,
+XML_DEPRECATED
+XMLPUBFUN xmlNodePtr		nodePop			(xmlParserCtxtPtr ctxt);
+XMLPUBFUN int			inputPush		(xmlParserCtxtPtr ctxt,
 						 xmlParserInputPtr value);
-XMLPUBFUN xmlParserInputPtr XMLCALL	inputPop		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN const xmlChar * XMLCALL	namePop			(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL			namePush		(xmlParserCtxtPtr ctxt,
+XMLPUBFUN xmlParserInputPtr	inputPop		(xmlParserCtxtPtr ctxt);
+XML_DEPRECATED
+XMLPUBFUN const xmlChar *	namePop			(xmlParserCtxtPtr ctxt);
+XML_DEPRECATED
+XMLPUBFUN int			namePush		(xmlParserCtxtPtr ctxt,
 						 const xmlChar *value);
 
 /*
  * other commodities shared between parser.c and parserInternals.
  */
-XMLPUBFUN int XMLCALL			xmlSkipBlankChars	(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL			xmlStringCurrentChar	(xmlParserCtxtPtr ctxt,
+XML_DEPRECATED
+XMLPUBFUN int			xmlSkipBlankChars	(xmlParserCtxtPtr ctxt);
+XML_DEPRECATED
+XMLPUBFUN int			xmlStringCurrentChar	(xmlParserCtxtPtr ctxt,
 						 const xmlChar *cur,
 						 int *len);
-XMLPUBFUN void XMLCALL			xmlParserHandlePEReference(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL			xmlCheckLanguageID	(const xmlChar *lang);
+XML_DEPRECATED
+XMLPUBFUN void			xmlParserHandlePEReference(xmlParserCtxtPtr ctxt);
+XML_DEPRECATED
+XMLPUBFUN int			xmlCheckLanguageID	(const xmlChar *lang);
 
 /*
  * Really core function shared with HTML parser.
  */
-XMLPUBFUN int XMLCALL			xmlCurrentChar		(xmlParserCtxtPtr ctxt,
+XML_DEPRECATED
+XMLPUBFUN int			xmlCurrentChar		(xmlParserCtxtPtr ctxt,
 						 int *len);
-XMLPUBFUN int XMLCALL		xmlCopyCharMultiByte	(xmlChar *out,
+XMLPUBFUN int		xmlCopyCharMultiByte	(xmlChar *out,
 						 int val);
-XMLPUBFUN int XMLCALL			xmlCopyChar		(int len,
+XMLPUBFUN int			xmlCopyChar		(int len,
 						 xmlChar *out,
 						 int val);
-XMLPUBFUN void XMLCALL			xmlNextChar		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL			xmlParserInputShrink	(xmlParserInputPtr in);
-
-#ifdef LIBXML_HTML_ENABLED
-/*
- * Actually comes from the HTML parser but launched from the init stuff.
- */
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL			htmlInitAutoClose	(void);
-XMLPUBFUN htmlParserCtxtPtr XMLCALL	htmlCreateFileParserCtxt(const char *filename,
-	                                         const char *encoding);
-#endif
+XMLPUBFUN void			xmlNextChar		(xmlParserCtxtPtr ctxt);
+XML_DEPRECATED
+XMLPUBFUN void			xmlParserInputShrink	(xmlParserInputPtr in);
 
 /*
  * Specific function to keep track of entities references
@@ -600,34 +624,34 @@ typedef	void	(*xmlEntityReferenceFunc)	(xmlEntityPtr ent,
 						 xmlNodePtr lastNode);
 
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL		xmlSetEntityReferenceFunc	(xmlEntityReferenceFunc func);
+XMLPUBFUN void		xmlSetEntityReferenceFunc	(xmlEntityReferenceFunc func);
 
 XML_DEPRECATED
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlParseQuotedString	(xmlParserCtxtPtr ctxt);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
                         xmlParseNamespace       (xmlParserCtxtPtr ctxt);
 XML_DEPRECATED
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlNamespaceParseNSDef	(xmlParserCtxtPtr ctxt);
 XML_DEPRECATED
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlScanName		(xmlParserCtxtPtr ctxt);
 XML_DEPRECATED
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlNamespaceParseNCName	(xmlParserCtxtPtr ctxt);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL	xmlParserHandleReference(xmlParserCtxtPtr ctxt);
+XMLPUBFUN void	xmlParserHandleReference(xmlParserCtxtPtr ctxt);
 XML_DEPRECATED
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlNamespaceParseQName	(xmlParserCtxtPtr ctxt,
 						 xmlChar **prefix);
 /**
  * Entities
  */
 XML_DEPRECATED
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlDecodeEntities		(xmlParserCtxtPtr ctxt,
 						 int len,
 						 int what,
@@ -635,21 +659,12 @@ XMLPUBFUN xmlChar * XMLCALL
 						 xmlChar  end2,
 						 xmlChar end3);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlHandleEntity		(xmlParserCtxtPtr ctxt,
 						 xmlEntityPtr entity);
 
 #endif /* LIBXML_LEGACY_ENABLED */
 
-#ifdef IN_LIBXML
-/*
- * internal only
- */
-XMLPUBFUN void XMLCALL
-	xmlErrMemory		(xmlParserCtxtPtr ctxt,
-				 const char *extra);
-#endif
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/libxml/pattern.h b/include/libxml/pattern.h
index 97d2cd2bc08521ad9f51063b5a9bef14d7ee9fb9..947f0900a23e0a7fb424d73fb31ddd9abaaf1656 100644
--- a/include/libxml/pattern.h
+++ b/include/libxml/pattern.h
@@ -43,18 +43,24 @@ typedef enum {
     XML_PATTERN_XSFIELD		= 1<<2	/* XPath subset for schema field */
 } xmlPatternFlags;
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlFreePattern		(xmlPatternPtr comp);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlFreePatternList	(xmlPatternPtr comp);
 
-XMLPUBFUN xmlPatternPtr XMLCALL
+XMLPUBFUN xmlPatternPtr
 			xmlPatterncompile	(const xmlChar *pattern,
 						 xmlDict *dict,
 						 int flags,
 						 const xmlChar **namespaces);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
+			xmlPatternCompileSafe	(const xmlChar *pattern,
+						 xmlDict *dict,
+						 int flags,
+						 const xmlChar **namespaces,
+						 xmlPatternPtr *patternOut);
+XMLPUBFUN int
 			xmlPatternMatch		(xmlPatternPtr comp,
 						 xmlNodePtr node);
 
@@ -62,34 +68,34 @@ XMLPUBFUN int XMLCALL
 typedef struct _xmlStreamCtxt xmlStreamCtxt;
 typedef xmlStreamCtxt *xmlStreamCtxtPtr;
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlPatternStreamable	(xmlPatternPtr comp);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlPatternMaxDepth	(xmlPatternPtr comp);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlPatternMinDepth	(xmlPatternPtr comp);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlPatternFromRoot	(xmlPatternPtr comp);
-XMLPUBFUN xmlStreamCtxtPtr XMLCALL
+XMLPUBFUN xmlStreamCtxtPtr
 			xmlPatternGetStreamCtxt	(xmlPatternPtr comp);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlFreeStreamCtxt	(xmlStreamCtxtPtr stream);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlStreamPushNode	(xmlStreamCtxtPtr stream,
 						 const xmlChar *name,
 						 const xmlChar *ns,
 						 int nodeType);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlStreamPush		(xmlStreamCtxtPtr stream,
 						 const xmlChar *name,
 						 const xmlChar *ns);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlStreamPushAttr	(xmlStreamCtxtPtr stream,
 						 const xmlChar *name,
 						 const xmlChar *ns);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlStreamPop		(xmlStreamCtxtPtr stream);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlStreamWantsAnyNode	(xmlStreamCtxtPtr stream);
 #ifdef __cplusplus
 }
diff --git a/include/libxml/relaxng.h b/include/libxml/relaxng.h
index 6369785cef0ef58211c2f7a595ea281bf8c05a17..079b7f125d0d2d31b740faecd146bbd85705868e 100644
--- a/include/libxml/relaxng.h
+++ b/include/libxml/relaxng.h
@@ -11,8 +11,9 @@
 #define __XML_RELAX_NG__
 
 #include <libxml/xmlversion.h>
-#include <libxml/hash.h>
+#include <libxml/xmlerror.h>
 #include <libxml/xmlstring.h>
+#include <libxml/tree.h>
 
 #ifdef LIBXML_SCHEMAS_ENABLED
 
@@ -32,7 +33,7 @@ typedef xmlRelaxNG *xmlRelaxNGPtr;
  *
  * Signature of an error callback from a Relax-NG validation
  */
-typedef void (XMLCDECL *xmlRelaxNGValidityErrorFunc) (void *ctx,
+typedef void (*xmlRelaxNGValidityErrorFunc) (void *ctx,
 						      const char *msg,
 						      ...) LIBXML_ATTR_FORMAT(2,3);
 
@@ -44,7 +45,7 @@ typedef void (XMLCDECL *xmlRelaxNGValidityErrorFunc) (void *ctx,
  *
  * Signature of a warning callback from a Relax-NG validation
  */
-typedef void (XMLCDECL *xmlRelaxNGValidityWarningFunc) (void *ctx,
+typedef void (*xmlRelaxNGValidityWarningFunc) (void *ctx,
 							const char *msg,
 							...) LIBXML_ATTR_FORMAT(2,3);
 
@@ -116,95 +117,95 @@ typedef enum {
     XML_RELAXNGP_CRNG = 2
 } xmlRelaxNGParserFlag;
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRelaxNGInitTypes		(void);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRelaxNGCleanupTypes	(void);
 
 /*
  * Interfaces for parsing.
  */
-XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL
+XMLPUBFUN xmlRelaxNGParserCtxtPtr
 		    xmlRelaxNGNewParserCtxt	(const char *URL);
-XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL
+XMLPUBFUN xmlRelaxNGParserCtxtPtr
 		    xmlRelaxNGNewMemParserCtxt	(const char *buffer,
 						 int size);
-XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL
+XMLPUBFUN xmlRelaxNGParserCtxtPtr
 		    xmlRelaxNGNewDocParserCtxt	(xmlDocPtr doc);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRelaxParserSetFlag	(xmlRelaxNGParserCtxtPtr ctxt,
 						 int flag);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRelaxNGFreeParserCtxt	(xmlRelaxNGParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
 					 xmlRelaxNGValidityErrorFunc err,
 					 xmlRelaxNGValidityWarningFunc warn,
 					 void *ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
 					 xmlRelaxNGValidityErrorFunc *err,
 					 xmlRelaxNGValidityWarningFunc *warn,
 					 void **ctx);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRelaxNGSetParserStructuredErrors(
 					 xmlRelaxNGParserCtxtPtr ctxt,
 					 xmlStructuredErrorFunc serror,
 					 void *ctx);
-XMLPUBFUN xmlRelaxNGPtr XMLCALL
+XMLPUBFUN xmlRelaxNGPtr
 		    xmlRelaxNGParse		(xmlRelaxNGParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRelaxNGFree		(xmlRelaxNGPtr schema);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRelaxNGDump		(FILE *output,
 					 xmlRelaxNGPtr schema);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRelaxNGDumpTree	(FILE * output,
 					 xmlRelaxNGPtr schema);
 #endif /* LIBXML_OUTPUT_ENABLED */
 /*
  * Interfaces for validating
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
 					 xmlRelaxNGValidityErrorFunc err,
 					 xmlRelaxNGValidityWarningFunc warn,
 					 void *ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
 					 xmlRelaxNGValidityErrorFunc *err,
 					 xmlRelaxNGValidityWarningFunc *warn,
 					 void **ctx);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt,
 					  xmlStructuredErrorFunc serror, void *ctx);
-XMLPUBFUN xmlRelaxNGValidCtxtPtr XMLCALL
+XMLPUBFUN xmlRelaxNGValidCtxtPtr
 		    xmlRelaxNGNewValidCtxt	(xmlRelaxNGPtr schema);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRelaxNGFreeValidCtxt	(xmlRelaxNGValidCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRelaxNGValidateDoc	(xmlRelaxNGValidCtxtPtr ctxt,
 						 xmlDocPtr doc);
 /*
  * Interfaces for progressive validation when possible
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRelaxNGValidatePushElement	(xmlRelaxNGValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlNodePtr elem);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRelaxNGValidatePushCData	(xmlRelaxNGValidCtxtPtr ctxt,
 					 const xmlChar *data,
 					 int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRelaxNGValidatePopElement	(xmlRelaxNGValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlNodePtr elem);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRelaxNGValidateFullElement	(xmlRelaxNGValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlNodePtr elem);
diff --git a/include/libxml/schemasInternals.h b/include/libxml/schemasInternals.h
index c521d1c184cc998fb077eb7012f8408e926b2dee..e9d3b3c7abb1e5b6fa1b1f25fb9bc2ee5e46d56f 100644
--- a/include/libxml/schemasInternals.h
+++ b/include/libxml/schemasInternals.h
@@ -21,6 +21,7 @@
 #include <libxml/xmlregexp.h>
 #include <libxml/hash.h>
 #include <libxml/dict.h>
+#include <libxml/tree.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -947,8 +948,8 @@ struct _xmlSchema {
     void *volatiles; /* Obsolete */
 };
 
-XMLPUBFUN void XMLCALL         xmlSchemaFreeType        (xmlSchemaTypePtr type);
-XMLPUBFUN void XMLCALL         xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard);
+XMLPUBFUN void         xmlSchemaFreeType        (xmlSchemaTypePtr type);
+XMLPUBFUN void         xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard);
 
 #ifdef __cplusplus
 }
diff --git a/include/libxml/schematron.h b/include/libxml/schematron.h
index c61e61b3cf57a7a514330eace02de9c3afff3576..8dd8d25c451c3ee2fb988cc32f6d7f24492eb589 100644
--- a/include/libxml/schematron.h
+++ b/include/libxml/schematron.h
@@ -15,6 +15,7 @@
 
 #ifdef LIBXML_SCHEMATRON_ENABLED
 
+#include <libxml/xmlerror.h>
 #include <libxml/tree.h>
 
 #ifdef __cplusplus
@@ -69,68 +70,68 @@ typedef xmlSchematronValidCtxt *xmlSchematronValidCtxtPtr;
 /*
  * Interfaces for parsing.
  */
-XMLPUBFUN xmlSchematronParserCtxtPtr XMLCALL
+XMLPUBFUN xmlSchematronParserCtxtPtr
 	    xmlSchematronNewParserCtxt	(const char *URL);
-XMLPUBFUN xmlSchematronParserCtxtPtr XMLCALL
+XMLPUBFUN xmlSchematronParserCtxtPtr
 	    xmlSchematronNewMemParserCtxt(const char *buffer,
 					 int size);
-XMLPUBFUN xmlSchematronParserCtxtPtr XMLCALL
+XMLPUBFUN xmlSchematronParserCtxtPtr
 	    xmlSchematronNewDocParserCtxt(xmlDocPtr doc);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchematronFreeParserCtxt	(xmlSchematronParserCtxtPtr ctxt);
 /*****
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchematronSetParserErrors(xmlSchematronParserCtxtPtr ctxt,
 					 xmlSchematronValidityErrorFunc err,
 					 xmlSchematronValidityWarningFunc warn,
 					 void *ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchematronGetParserErrors(xmlSchematronParserCtxtPtr ctxt,
 					xmlSchematronValidityErrorFunc * err,
 					xmlSchematronValidityWarningFunc * warn,
 					void **ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchematronIsValid	(xmlSchematronValidCtxtPtr ctxt);
  *****/
-XMLPUBFUN xmlSchematronPtr XMLCALL
+XMLPUBFUN xmlSchematronPtr
 	    xmlSchematronParse		(xmlSchematronParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchematronFree		(xmlSchematronPtr schema);
 /*
  * Interfaces for validating
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchematronSetValidStructuredErrors(
 	                                  xmlSchematronValidCtxtPtr ctxt,
 					  xmlStructuredErrorFunc serror,
 					  void *ctx);
 /******
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchematronSetValidErrors	(xmlSchematronValidCtxtPtr ctxt,
 					 xmlSchematronValidityErrorFunc err,
 					 xmlSchematronValidityWarningFunc warn,
 					 void *ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlSchematronGetValidErrors	(xmlSchematronValidCtxtPtr ctxt,
 					 xmlSchematronValidityErrorFunc *err,
 					 xmlSchematronValidityWarningFunc *warn,
 					 void **ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlSchematronSetValidOptions(xmlSchematronValidCtxtPtr ctxt,
 					 int options);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlSchematronValidCtxtGetOptions(xmlSchematronValidCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
             xmlSchematronValidateOneElement (xmlSchematronValidCtxtPtr ctxt,
 			                 xmlNodePtr elem);
  *******/
 
-XMLPUBFUN xmlSchematronValidCtxtPtr XMLCALL
+XMLPUBFUN xmlSchematronValidCtxtPtr
 	    xmlSchematronNewValidCtxt	(xmlSchematronPtr schema,
 					 int options);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchematronFreeValidCtxt	(xmlSchematronValidCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlSchematronValidateDoc	(xmlSchematronValidCtxtPtr ctxt,
 					 xmlDocPtr instance);
 
diff --git a/include/libxml/threads.h b/include/libxml/threads.h
index 6eedac1f3746daaf3f4ea95f898981de15dee1bd..8f4b6e174fbac6e724e5a8da4ed65a8a297c0373 100644
--- a/include/libxml/threads.h
+++ b/include/libxml/threads.h
@@ -29,59 +29,55 @@ typedef xmlMutex *xmlMutexPtr;
 typedef struct _xmlRMutex xmlRMutex;
 typedef xmlRMutex *xmlRMutexPtr;
 
-#ifdef __cplusplus
-}
-#endif
-#include <libxml/globals.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-XMLPUBFUN xmlMutexPtr XMLCALL
+XMLPUBFUN int
+			xmlCheckThreadLocalStorage(void);
+
+XMLPUBFUN xmlMutexPtr
 			xmlNewMutex	(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlMutexLock	(xmlMutexPtr tok);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlMutexUnlock	(xmlMutexPtr tok);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlFreeMutex	(xmlMutexPtr tok);
 
-XMLPUBFUN xmlRMutexPtr XMLCALL
+XMLPUBFUN xmlRMutexPtr
 			xmlNewRMutex	(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlRMutexLock	(xmlRMutexPtr tok);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlRMutexUnlock	(xmlRMutexPtr tok);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlFreeRMutex	(xmlRMutexPtr tok);
 
 /*
  * Library wide APIs.
  */
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlInitThreads	(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlLockLibrary	(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlUnlockLibrary(void);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			xmlGetThreadId	(void);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 			xmlIsMainThread	(void);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlCleanupThreads(void);
-XMLPUBFUN xmlGlobalStatePtr XMLCALL
-			xmlGetGlobalState(void);
 
-#ifdef HAVE_PTHREAD_H
-#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
-#if defined(LIBXML_STATIC_FOR_DLL)
-int XMLCALL
+/** DOC_DISABLE */
+#if defined(LIBXML_THREAD_ENABLED) && defined(_WIN32) && \
+    defined(LIBXML_STATIC_FOR_DLL)
+int
 xmlDllMain(void *hinstDLL, unsigned long fdwReason,
            void *lpvReserved);
 #endif
-#endif
+/** DOC_ENABLE */
 
 #ifdef __cplusplus
 }
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 98e208745a923b50b8cf45f0472255304a2c5efd..f6b0b06301f8eaf4da348c876a3f1b1f22f85bff 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -9,6 +9,15 @@
  * Author: Daniel Veillard
  */
 
+#ifndef XML_TREE_INTERNALS
+
+/*
+ * Emulate circular dependency for backward compatibility
+ */
+#include <libxml/parser.h>
+
+#else /* XML_TREE_INTERNALS */
+
 #ifndef __XML_TREE_H__
 #define __XML_TREE_H__
 
@@ -16,6 +25,8 @@
 #include <limits.h>
 #include <libxml/xmlversion.h>
 #include <libxml/xmlstring.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlregexp.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -74,7 +85,7 @@ typedef xmlEntity *xmlEntityPtr;
 typedef enum {
     XML_BUFFER_ALLOC_DOUBLEIT,	/* double each time one need to grow */
     XML_BUFFER_ALLOC_EXACT,	/* grow only to the minimal size */
-    XML_BUFFER_ALLOC_IMMUTABLE, /* immutable buffer */
+    XML_BUFFER_ALLOC_IMMUTABLE, /* immutable buffer, deprecated */
     XML_BUFFER_ALLOC_IO,	/* special allocation scheme used for I/O */
     XML_BUFFER_ALLOC_HYBRID,	/* exact up to a threshold, and doubleit thereafter */
     XML_BUFFER_ALLOC_BOUNDED	/* limit the upper size of the buffer */
@@ -117,10 +128,10 @@ typedef xmlBuf *xmlBufPtr;
  * A few public routines for xmlBuf. As those are expected to be used
  * mostly internally the bulk of the routines are internal in buf.h
  */
-XMLPUBFUN xmlChar* XMLCALL       xmlBufContent	(const xmlBuf* buf);
-XMLPUBFUN xmlChar* XMLCALL       xmlBufEnd      (xmlBufPtr buf);
-XMLPUBFUN size_t XMLCALL         xmlBufUse      (const xmlBufPtr buf);
-XMLPUBFUN size_t XMLCALL         xmlBufShrink	(xmlBufPtr buf, size_t len);
+XMLPUBFUN xmlChar*       xmlBufContent	(const xmlBuf* buf);
+XMLPUBFUN xmlChar*       xmlBufEnd      (xmlBufPtr buf);
+XMLPUBFUN size_t         xmlBufUse      (const xmlBufPtr buf);
+XMLPUBFUN size_t         xmlBufShrink	(xmlBufPtr buf, size_t len);
 
 /*
  * LIBXML2_NEW_BUFFER:
@@ -162,13 +173,13 @@ typedef enum {
     XML_TEXT_NODE=		3,
     XML_CDATA_SECTION_NODE=	4,
     XML_ENTITY_REF_NODE=	5,
-    XML_ENTITY_NODE=		6,
+    XML_ENTITY_NODE=		6,  /* unused */
     XML_PI_NODE=		7,
     XML_COMMENT_NODE=		8,
     XML_DOCUMENT_NODE=		9,
-    XML_DOCUMENT_TYPE_NODE=	10,
+    XML_DOCUMENT_TYPE_NODE=	10, /* unused */
     XML_DOCUMENT_FRAG_NODE=	11,
-    XML_NOTATION_NODE=		12,
+    XML_NOTATION_NODE=		12, /* unused */
     XML_HTML_DOCUMENT_NODE=	13,
     XML_DTD_NODE=		14,
     XML_ELEMENT_DECL=		15,
@@ -180,8 +191,10 @@ typedef enum {
     /* XML_DOCB_DOCUMENT_NODE=	21 */ /* removed */
 } xmlElementType;
 
+/** DOC_DISABLE */
 /* For backward compatibility */
 #define XML_DOCB_DOCUMENT_NODE 21
+/** DOC_ENABLE */
 
 /**
  * xmlNotation:
@@ -327,14 +340,6 @@ typedef enum {
     XML_ELEMENT_TYPE_ELEMENT
 } xmlElementTypeVal;
 
-#ifdef __cplusplus
-}
-#endif
-#include <libxml/xmlregexp.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * xmlElement:
  *
@@ -444,6 +449,7 @@ struct _xmlAttr {
     xmlNs           *ns;        /* pointer to the associated namespace */
     xmlAttributeType atype;     /* the attribute type if validating */
     void            *psvi;	/* for type/PSVI information */
+    struct _xmlID   *id;        /* the ID struct */
 };
 
 /**
@@ -571,12 +577,11 @@ struct _xmlDoc {
     struct _xmlDtd  *extSubset;	/* the document external subset */
     struct _xmlNs   *oldNs;	/* Global namespace, the old way */
     const xmlChar  *version;	/* the XML version string */
-    const xmlChar  *encoding;   /* external initial encoding, if any */
+    const xmlChar  *encoding;   /* actual encoding, if any */
     void           *ids;        /* Hash table for ID attributes if any */
     void           *refs;       /* Hash table for IDREFs attributes if any */
     const xmlChar  *URL;	/* The URI for that document */
-    int             charset;    /* Internal flag for charset handling,
-				   actually an xmlCharEncoding */
+    int             charset;    /* unused */
     struct _xmlDict *dict;      /* dict used to allocate names or NULL */
     void           *psvi;	/* for type/PSVI information */
     int             parseFlags;	/* set of xmlParserOption used to parse the
@@ -628,6 +633,22 @@ struct _xmlDOMWrapCtxt {
     xmlDOMWrapAcquireNsFunction getNsForNodeFunc;
 };
 
+/**
+ * xmlRegisterNodeFunc:
+ * @node: the current node
+ *
+ * Signature for the registration callback of a created node
+ */
+typedef void (*xmlRegisterNodeFunc) (xmlNodePtr node);
+
+/**
+ * xmlDeregisterNodeFunc:
+ * @node: the current node
+ *
+ * Signature for the deregistration callback of a discarded node
+ */
+typedef void (*xmlDeregisterNodeFunc) (xmlNodePtr node);
+
 /**
  * xmlChildrenNode:
  *
@@ -652,40 +673,61 @@ struct _xmlDOMWrapCtxt {
  * Variables.
  */
 
+/** DOC_DISABLE */
+#define XML_GLOBALS_TREE \
+  XML_OP(xmlBufferAllocScheme, xmlBufferAllocationScheme, XML_DEPRECATED) \
+  XML_OP(xmlDefaultBufferSize, int, XML_DEPRECATED) \
+  XML_OP(xmlRegisterNodeDefaultValue, xmlRegisterNodeFunc, XML_DEPRECATED) \
+  XML_OP(xmlDeregisterNodeDefaultValue, xmlDeregisterNodeFunc, \
+         XML_DEPRECATED)
+
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_TREE
+#undef XML_OP
+
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+  #define xmlBufferAllocScheme XML_GLOBAL_MACRO(xmlBufferAllocScheme)
+  #define xmlDefaultBufferSize XML_GLOBAL_MACRO(xmlDefaultBufferSize)
+  #define xmlRegisterNodeDefaultValue \
+    XML_GLOBAL_MACRO(xmlRegisterNodeDefaultValue)
+  #define xmlDeregisterNodeDefaultValue \
+    XML_GLOBAL_MACRO(xmlDeregisterNodeDefaultValue)
+#else
+#define xmlBufferAllocScheme vtklibxml2_xmlBufferAllocScheme
+#define xmlDefaultBufferSize vtklibxml2_xmlDefaultBufferSize
+#define xmlRegisterNodeDefaultValue vtklibxml2_xmlRegisterNodeDefaultValue
+#define xmlDeregisterNodeDefaultValue vtklibxml2_xmlDeregisterNodeDefaultValue
+#endif
+/** DOC_ENABLE */
+
 /*
  * Some helper functions
  */
-#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || \
-    defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || \
-    defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || \
-    defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || \
-    defined(LIBXML_LEGACY_ENABLED)
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateNCName	(const xmlChar *value,
 					 int space);
-#endif
 
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateQName	(const xmlChar *value,
 					 int space);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateName		(const xmlChar *value,
 					 int space);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateNMToken	(const xmlChar *value,
 					 int space);
 #endif
 
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlBuildQName		(const xmlChar *ncname,
 					 const xmlChar *prefix,
 					 xmlChar *memory,
 					 int len);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlSplitQName2		(const xmlChar *name,
 					 xmlChar **prefix);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		xmlSplitQName3		(const xmlChar *name,
 					 int *len);
 
@@ -693,318 +735,322 @@ XMLPUBFUN const xmlChar * XMLCALL
  * Handling Buffers, the old ones see @xmlBuf for the new ones.
  */
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme);
-XMLPUBFUN xmlBufferAllocationScheme XMLCALL
+XMLPUBFUN xmlBufferAllocationScheme
 		xmlGetBufferAllocationScheme(void);
 
-XMLPUBFUN xmlBufferPtr XMLCALL
+XMLPUBFUN xmlBufferPtr
 		xmlBufferCreate		(void);
-XMLPUBFUN xmlBufferPtr XMLCALL
+XMLPUBFUN xmlBufferPtr
 		xmlBufferCreateSize	(size_t size);
-XMLPUBFUN xmlBufferPtr XMLCALL
+XMLPUBFUN xmlBufferPtr
 		xmlBufferCreateStatic	(void *mem,
 					 size_t size);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlBufferResize		(xmlBufferPtr buf,
 					 unsigned int size);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlBufferFree		(xmlBufferPtr buf);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlBufferDump		(FILE *file,
 					 xmlBufferPtr buf);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlBufferAdd		(xmlBufferPtr buf,
 					 const xmlChar *str,
 					 int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlBufferAddHead	(xmlBufferPtr buf,
 					 const xmlChar *str,
 					 int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlBufferCat		(xmlBufferPtr buf,
 					 const xmlChar *str);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlBufferCCat		(xmlBufferPtr buf,
 					 const char *str);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlBufferShrink		(xmlBufferPtr buf,
 					 unsigned int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlBufferGrow		(xmlBufferPtr buf,
 					 unsigned int len);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlBufferEmpty		(xmlBufferPtr buf);
-XMLPUBFUN const xmlChar* XMLCALL
+XMLPUBFUN const xmlChar*
 		xmlBufferContent	(const xmlBuffer *buf);
-XMLPUBFUN xmlChar* XMLCALL
+XMLPUBFUN xmlChar*
 		xmlBufferDetach         (xmlBufferPtr buf);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlBufferSetAllocationScheme(xmlBufferPtr buf,
 					 xmlBufferAllocationScheme scheme);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlBufferLength		(const xmlBuffer *buf);
 
 /*
  * Creating/freeing new structures.
  */
-XMLPUBFUN xmlDtdPtr XMLCALL
+XMLPUBFUN xmlDtdPtr
 		xmlCreateIntSubset	(xmlDocPtr doc,
 					 const xmlChar *name,
 					 const xmlChar *ExternalID,
 					 const xmlChar *SystemID);
-XMLPUBFUN xmlDtdPtr XMLCALL
+XMLPUBFUN xmlDtdPtr
 		xmlNewDtd		(xmlDocPtr doc,
 					 const xmlChar *name,
 					 const xmlChar *ExternalID,
 					 const xmlChar *SystemID);
-XMLPUBFUN xmlDtdPtr XMLCALL
+XMLPUBFUN xmlDtdPtr
 		xmlGetIntSubset		(const xmlDoc *doc);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeDtd		(xmlDtdPtr cur);
 #ifdef LIBXML_LEGACY_ENABLED
 XML_DEPRECATED
-XMLPUBFUN xmlNsPtr XMLCALL
+XMLPUBFUN xmlNsPtr
 		xmlNewGlobalNs		(xmlDocPtr doc,
 					 const xmlChar *href,
 					 const xmlChar *prefix);
 #endif /* LIBXML_LEGACY_ENABLED */
-XMLPUBFUN xmlNsPtr XMLCALL
+XMLPUBFUN xmlNsPtr
 		xmlNewNs		(xmlNodePtr node,
 					 const xmlChar *href,
 					 const xmlChar *prefix);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeNs		(xmlNsPtr cur);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeNsList		(xmlNsPtr cur);
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlNewDoc		(const xmlChar *version);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeDoc		(xmlDocPtr cur);
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlNewDocProp		(xmlDocPtr doc,
 					 const xmlChar *name,
 					 const xmlChar *value);
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
     defined(LIBXML_SCHEMAS_ENABLED)
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlNewProp		(xmlNodePtr node,
 					 const xmlChar *name,
 					 const xmlChar *value);
 #endif
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlNewNsProp		(xmlNodePtr node,
 					 xmlNsPtr ns,
 					 const xmlChar *name,
 					 const xmlChar *value);
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlNewNsPropEatName	(xmlNodePtr node,
 					 xmlNsPtr ns,
 					 xmlChar *name,
 					 const xmlChar *value);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreePropList		(xmlAttrPtr cur);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeProp		(xmlAttrPtr cur);
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlCopyProp		(xmlNodePtr target,
 					 xmlAttrPtr cur);
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlCopyPropList		(xmlNodePtr target,
 					 xmlAttrPtr cur);
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN xmlDtdPtr XMLCALL
+XMLPUBFUN xmlDtdPtr
 		xmlCopyDtd		(xmlDtdPtr dtd);
 #endif /* LIBXML_TREE_ENABLED */
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		xmlCopyDoc		(xmlDocPtr doc,
 					 int recursive);
 #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) */
 /*
  * Creating new nodes.
  */
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewDocNode		(xmlDocPtr doc,
 					 xmlNsPtr ns,
 					 const xmlChar *name,
 					 const xmlChar *content);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewDocNodeEatName	(xmlDocPtr doc,
 					 xmlNsPtr ns,
 					 xmlChar *name,
 					 const xmlChar *content);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewNode		(xmlNsPtr ns,
 					 const xmlChar *name);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewNodeEatName	(xmlNsPtr ns,
 					 xmlChar *name);
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewChild		(xmlNodePtr parent,
 					 xmlNsPtr ns,
 					 const xmlChar *name,
 					 const xmlChar *content);
 #endif
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewDocText		(const xmlDoc *doc,
 					 const xmlChar *content);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewText		(const xmlChar *content);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewDocPI		(xmlDocPtr doc,
 					 const xmlChar *name,
 					 const xmlChar *content);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewPI		(const xmlChar *name,
 					 const xmlChar *content);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewDocTextLen	(xmlDocPtr doc,
 					 const xmlChar *content,
 					 int len);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewTextLen		(const xmlChar *content,
 					 int len);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewDocComment	(xmlDocPtr doc,
 					 const xmlChar *content);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewComment		(const xmlChar *content);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewCDataBlock	(xmlDocPtr doc,
 					 const xmlChar *content,
 					 int len);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewCharRef		(xmlDocPtr doc,
 					 const xmlChar *name);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewReference		(const xmlDoc *doc,
 					 const xmlChar *name);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlCopyNode		(xmlNodePtr node,
 					 int recursive);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlDocCopyNode		(xmlNodePtr node,
 					 xmlDocPtr doc,
 					 int recursive);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlDocCopyNodeList	(xmlDocPtr doc,
 					 xmlNodePtr node);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlCopyNodeList		(xmlNodePtr node);
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewTextChild		(xmlNodePtr parent,
 					 xmlNsPtr ns,
 					 const xmlChar *name,
 					 const xmlChar *content);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewDocRawNode	(xmlDocPtr doc,
 					 xmlNsPtr ns,
 					 const xmlChar *name,
 					 const xmlChar *content);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlNewDocFragment	(xmlDocPtr doc);
 #endif /* LIBXML_TREE_ENABLED */
 
 /*
  * Navigating.
  */
-XMLPUBFUN long XMLCALL
+XMLPUBFUN long
 		xmlGetLineNo		(const xmlNode *node);
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlGetNodePath		(const xmlNode *node);
 #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED) */
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlDocGetRootElement	(const xmlDoc *doc);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlGetLastChild		(const xmlNode *parent);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlNodeIsText		(const xmlNode *node);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsBlankNode		(const xmlNode *node);
 
 /*
  * Changing the structure.
  */
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlDocSetRootElement	(xmlDocPtr doc,
 					 xmlNodePtr root);
 #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) */
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlNodeSetName		(xmlNodePtr cur,
 					 const xmlChar *name);
 #endif /* LIBXML_TREE_ENABLED */
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlAddChild		(xmlNodePtr parent,
 					 xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlAddChildList		(xmlNodePtr parent,
 					 xmlNodePtr cur);
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlReplaceNode		(xmlNodePtr old,
 					 xmlNodePtr cur);
 #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) */
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
     defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlAddPrevSibling	(xmlNodePtr cur,
 					 xmlNodePtr elem);
 #endif /* LIBXML_TREE_ENABLED || LIBXML_HTML_ENABLED || LIBXML_SCHEMAS_ENABLED */
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlAddSibling		(xmlNodePtr cur,
 					 xmlNodePtr elem);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlAddNextSibling	(xmlNodePtr cur,
 					 xmlNodePtr elem);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlUnlinkNode		(xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlTextMerge		(xmlNodePtr first,
 					 xmlNodePtr second);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlTextConcat		(xmlNodePtr node,
 					 const xmlChar *content,
 					 int len);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeNodeList		(xmlNodePtr cur);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeNode		(xmlNodePtr cur);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN int
 		xmlSetTreeDoc		(xmlNodePtr tree,
 					 xmlDocPtr doc);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN int
 		xmlSetListDoc		(xmlNodePtr list,
 					 xmlDocPtr doc);
 /*
  * Namespaces.
  */
-XMLPUBFUN xmlNsPtr XMLCALL
+XMLPUBFUN xmlNsPtr
 		xmlSearchNs		(xmlDocPtr doc,
 					 xmlNodePtr node,
 					 const xmlChar *nameSpace);
-XMLPUBFUN xmlNsPtr XMLCALL
+XMLPUBFUN xmlNsPtr
 		xmlSearchNsByHref	(xmlDocPtr doc,
 					 xmlNodePtr node,
 					 const xmlChar *href);
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || \
     defined(LIBXML_SCHEMAS_ENABLED)
-XMLPUBFUN xmlNsPtr * XMLCALL
+XMLPUBFUN int
+		xmlGetNsListSafe	(const xmlDoc *doc,
+					 const xmlNode *node,
+					 xmlNsPtr **out);
+XMLPUBFUN xmlNsPtr *
 		xmlGetNsList		(const xmlDoc *doc,
 					 const xmlNode *node);
 #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) */
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSetNs		(xmlNodePtr node,
 					 xmlNsPtr ns);
-XMLPUBFUN xmlNsPtr XMLCALL
+XMLPUBFUN xmlNsPtr
 		xmlCopyNamespace	(xmlNsPtr cur);
-XMLPUBFUN xmlNsPtr XMLCALL
+XMLPUBFUN xmlNsPtr
 		xmlCopyNamespaceList	(xmlNsPtr cur);
 
 /*
@@ -1012,94 +1058,103 @@ XMLPUBFUN xmlNsPtr XMLCALL
  */
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || \
     defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlSetProp		(xmlNodePtr node,
 					 const xmlChar *name,
 					 const xmlChar *value);
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlSetNsProp		(xmlNodePtr node,
 					 xmlNsPtr ns,
 					 const xmlChar *name,
 					 const xmlChar *value);
 #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || \
 	  defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED) */
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN int
+		xmlNodeGetAttrValue	(const xmlNode *node,
+					 const xmlChar *name,
+					 const xmlChar *nsUri,
+					 xmlChar **out);
+XMLPUBFUN xmlChar *
 		xmlGetNoNsProp		(const xmlNode *node,
 					 const xmlChar *name);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlGetProp		(const xmlNode *node,
 					 const xmlChar *name);
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlHasProp		(const xmlNode *node,
 					 const xmlChar *name);
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlHasNsProp		(const xmlNode *node,
 					 const xmlChar *name,
 					 const xmlChar *nameSpace);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlGetNsProp		(const xmlNode *node,
 					 const xmlChar *name,
 					 const xmlChar *nameSpace);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlStringGetNodeList	(const xmlDoc *doc,
 					 const xmlChar *value);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		xmlStringLenGetNodeList	(const xmlDoc *doc,
 					 const xmlChar *value,
 					 int len);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlNodeListGetString	(xmlDocPtr doc,
 					 const xmlNode *list,
 					 int inLine);
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlNodeListGetRawString	(const xmlDoc *doc,
 					 const xmlNode *list,
 					 int inLine);
 #endif /* LIBXML_TREE_ENABLED */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN int
 		xmlNodeSetContent	(xmlNodePtr cur,
 					 const xmlChar *content);
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN int
 		xmlNodeSetContentLen	(xmlNodePtr cur,
 					 const xmlChar *content,
 					 int len);
 #endif /* LIBXML_TREE_ENABLED */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN int
 		xmlNodeAddContent	(xmlNodePtr cur,
 					 const xmlChar *content);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN int
 		xmlNodeAddContentLen	(xmlNodePtr cur,
 					 const xmlChar *content,
 					 int len);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlNodeGetContent	(const xmlNode *cur);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlNodeBufGetContent	(xmlBufferPtr buffer,
 					 const xmlNode *cur);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlBufGetNodeContent	(xmlBufPtr buf,
 					 const xmlNode *cur);
 
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlNodeGetLang		(const xmlNode *cur);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlNodeGetSpacePreserve	(const xmlNode *cur);
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN int
 		xmlNodeSetLang		(xmlNodePtr cur,
 					 const xmlChar *lang);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN int
 		xmlNodeSetSpacePreserve (xmlNodePtr cur,
 					 int val);
 #endif /* LIBXML_TREE_ENABLED */
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN int
+		xmlNodeGetBaseSafe	(const xmlDoc *doc,
+					 const xmlNode *cur,
+					 xmlChar **baseOut);
+XMLPUBFUN xmlChar *
 		xmlNodeGetBase		(const xmlDoc *doc,
 					 const xmlNode *cur);
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
-XMLPUBFUN void XMLCALL
+XMLPUBFUN int
 		xmlNodeSetBase		(xmlNodePtr cur,
 					 const xmlChar *uri);
 #endif
@@ -1107,14 +1162,14 @@ XMLPUBFUN void XMLCALL
 /*
  * Removing content.
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlRemoveProp		(xmlAttrPtr cur);
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlUnsetNsProp		(xmlNodePtr node,
 					 xmlNsPtr ns,
 					 const xmlChar *name);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlUnsetProp		(xmlNodePtr node,
 					 const xmlChar *name);
 #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) */
@@ -1122,13 +1177,13 @@ XMLPUBFUN int XMLCALL
 /*
  * Internal, don't use.
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlBufferWriteCHAR	(xmlBufferPtr buf,
 					 const xmlChar *string);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlBufferWriteChar	(xmlBufferPtr buf,
 					 const char *string);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlBufferWriteQuotedString(xmlBufferPtr buf,
 					 const xmlChar *string);
 
@@ -1143,7 +1198,7 @@ XMLPUBFUN void xmlAttrSerializeTxtContent(xmlBufferPtr buf,
 /*
  * Namespace handling.
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlReconciliateNs	(xmlDocPtr doc,
 					 xmlNodePtr tree);
 #endif
@@ -1152,67 +1207,67 @@ XMLPUBFUN int XMLCALL
 /*
  * Saving.
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlDocDumpFormatMemory	(xmlDocPtr cur,
 					 xmlChar **mem,
 					 int *size,
 					 int format);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlDocDumpMemory	(xmlDocPtr cur,
 					 xmlChar **mem,
 					 int *size);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlDocDumpMemoryEnc	(xmlDocPtr out_doc,
 					 xmlChar **doc_txt_ptr,
 					 int * doc_txt_len,
 					 const char *txt_encoding);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc,
 					 xmlChar **doc_txt_ptr,
 					 int * doc_txt_len,
 					 const char *txt_encoding,
 					 int format);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlDocFormatDump	(FILE *f,
 					 xmlDocPtr cur,
 					 int format);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlDocDump		(FILE *f,
 					 xmlDocPtr cur);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlElemDump		(FILE *f,
 					 xmlDocPtr doc,
 					 xmlNodePtr cur);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSaveFile		(const char *filename,
 					 xmlDocPtr cur);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSaveFormatFile	(const char *filename,
 					 xmlDocPtr cur,
 					 int format);
-XMLPUBFUN size_t XMLCALL
+XMLPUBFUN size_t
 		xmlBufNodeDump		(xmlBufPtr buf,
 					 xmlDocPtr doc,
 					 xmlNodePtr cur,
 					 int level,
 					 int format);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlNodeDump		(xmlBufferPtr buf,
 					 xmlDocPtr doc,
 					 xmlNodePtr cur,
 					 int level,
 					 int format);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSaveFileTo		(xmlOutputBufferPtr buf,
 					 xmlDocPtr cur,
 					 const char *encoding);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSaveFormatFileTo     (xmlOutputBufferPtr buf,
 					 xmlDocPtr cur,
 				         const char *encoding,
 				         int format);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlNodeDumpOutput	(xmlOutputBufferPtr buf,
 					 xmlDocPtr doc,
 					 xmlNodePtr cur,
@@ -1220,13 +1275,13 @@ XMLPUBFUN void XMLCALL
 					 int format,
 					 const char *encoding);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSaveFormatFileEnc    (const char *filename,
 					 xmlDocPtr cur,
 					 const char *encoding,
 					 int format);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSaveFileEnc		(const char *filename,
 					 xmlDocPtr cur,
 					 const char *encoding);
@@ -1235,47 +1290,49 @@ XMLPUBFUN int XMLCALL
 /*
  * XHTML
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsXHTML		(const xmlChar *systemID,
 					 const xmlChar *publicID);
 
 /*
  * Compression.
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlGetDocCompressMode	(const xmlDoc *doc);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSetDocCompressMode	(xmlDocPtr doc,
 					 int mode);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlGetCompressMode	(void);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 		xmlSetCompressMode	(int mode);
 
 /*
 * DOM-wrapper helper functions.
 */
-XMLPUBFUN xmlDOMWrapCtxtPtr XMLCALL
+XMLPUBFUN xmlDOMWrapCtxtPtr
 		xmlDOMWrapNewCtxt	(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlDOMWrapFreeCtxt	(xmlDOMWrapCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt,
 					 xmlNodePtr elem,
 					 int options);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlDOMWrapAdoptNode		(xmlDOMWrapCtxtPtr ctxt,
 					 xmlDocPtr sourceDoc,
 					 xmlNodePtr node,
 					 xmlDocPtr destDoc,
 					 xmlNodePtr destParent,
 					 int options);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlDOMWrapRemoveNode	(xmlDOMWrapCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlNodePtr node,
 					 int options);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlDOMWrapCloneNode		(xmlDOMWrapCtxtPtr ctxt,
 					 xmlDocPtr sourceDoc,
 					 xmlNodePtr node,
@@ -1290,23 +1347,41 @@ XMLPUBFUN int XMLCALL
  * 5 interfaces from DOM ElementTraversal, but different in entities
  * traversal.
  */
-XMLPUBFUN unsigned long XMLCALL
+XMLPUBFUN unsigned long
             xmlChildElementCount        (xmlNodePtr parent);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
             xmlNextElementSibling       (xmlNodePtr node);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
             xmlFirstElementChild        (xmlNodePtr parent);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
             xmlLastElementChild         (xmlNodePtr parent);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
             xmlPreviousElementSibling   (xmlNodePtr node);
 #endif
+
+XML_DEPRECATED
+XMLPUBFUN xmlRegisterNodeFunc
+	    xmlRegisterNodeDefault	(xmlRegisterNodeFunc func);
+XML_DEPRECATED
+XMLPUBFUN xmlDeregisterNodeFunc
+	    xmlDeregisterNodeDefault	(xmlDeregisterNodeFunc func);
+XML_DEPRECATED
+XMLPUBFUN xmlRegisterNodeFunc
+            xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func);
+XML_DEPRECATED
+XMLPUBFUN xmlDeregisterNodeFunc
+            xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func);
+
+XML_DEPRECATED XMLPUBFUN xmlBufferAllocationScheme
+            xmlThrDefBufferAllocScheme  (xmlBufferAllocationScheme v);
+XML_DEPRECATED XMLPUBFUN int
+            xmlThrDefDefaultBufferSize  (int v);
+
 #ifdef __cplusplus
 }
 #endif
-#ifndef __XML_PARSER_H__
-#include <libxml/xmlmemory.h>
-#endif
 
 #endif /* __XML_TREE_H__ */
 
+#endif /* XML_TREE_INTERNALS */
+
diff --git a/include/libxml/uri.h b/include/libxml/uri.h
index db48262b136f3c8895832a43cc5cad4c6b5edb9f..19980b711c56ef9c4b56c1f9f58e1c599d874008 100644
--- a/include/libxml/uri.h
+++ b/include/libxml/uri.h
@@ -11,8 +11,9 @@
 #ifndef __XML_URI_H__
 #define __XML_URI_H__
 
+#include <stdio.h>
 #include <libxml/xmlversion.h>
-#include <libxml/tree.h>
+#include <libxml/xmlstring.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -49,43 +50,54 @@ struct _xmlURI {
  * xmlChar *	xmlNodeGetBase	(xmlDocPtr doc,
  *                               xmlNodePtr cur);
  */
-XMLPUBFUN xmlURIPtr XMLCALL
+XMLPUBFUN xmlURIPtr
 		xmlCreateURI		(void);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN int
+		xmlBuildURISafe		(const xmlChar *URI,
+					 const xmlChar *base,
+					 xmlChar **out);
+XMLPUBFUN xmlChar *
 		xmlBuildURI		(const xmlChar *URI,
 					 const xmlChar *base);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN int
+		xmlBuildRelativeURISafe	(const xmlChar *URI,
+					 const xmlChar *base,
+					 xmlChar **out);
+XMLPUBFUN xmlChar *
 		xmlBuildRelativeURI	(const xmlChar *URI,
 					 const xmlChar *base);
-XMLPUBFUN xmlURIPtr XMLCALL
+XMLPUBFUN xmlURIPtr
 		xmlParseURI		(const char *str);
-XMLPUBFUN xmlURIPtr XMLCALL
+XMLPUBFUN int
+		xmlParseURISafe		(const char *str,
+					 xmlURIPtr *uri);
+XMLPUBFUN xmlURIPtr
 		xmlParseURIRaw		(const char *str,
 					 int raw);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlParseURIReference	(xmlURIPtr uri,
 					 const char *str);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlSaveUri		(xmlURIPtr uri);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlPrintURI		(FILE *stream,
 					 xmlURIPtr uri);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlURIEscapeStr         (const xmlChar *str,
 					 const xmlChar *list);
-XMLPUBFUN char * XMLCALL
+XMLPUBFUN char *
 		xmlURIUnescapeString	(const char *str,
 					 int len,
 					 char *target);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlNormalizeURIPath	(char *path);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlURIEscape		(const xmlChar *str);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeURI		(xmlURIPtr uri);
-XMLPUBFUN xmlChar* XMLCALL
+XMLPUBFUN xmlChar*
 		xmlCanonicPath		(const xmlChar *path);
-XMLPUBFUN xmlChar* XMLCALL
+XMLPUBFUN xmlChar*
 		xmlPathToURI		(const xmlChar *path);
 
 #ifdef __cplusplus
diff --git a/include/libxml/valid.h b/include/libxml/valid.h
index 3eaf84adcb4644a70c229df7437e21b9b09c7667..e1698d7a34025fe05b86d76ff1bd0ea873108523 100644
--- a/include/libxml/valid.h
+++ b/include/libxml/valid.h
@@ -11,12 +11,16 @@
 #ifndef __XML_VALID_H__
 #define __XML_VALID_H__
 
+/** DOC_DISABLE */
 #include <libxml/xmlversion.h>
 #include <libxml/xmlerror.h>
+#define XML_TREE_INTERNALS
 #include <libxml/tree.h>
+#undef XML_TREE_INTERNALS
 #include <libxml/list.h>
 #include <libxml/xmlautomata.h>
 #include <libxml/xmlregexp.h>
+/** DOC_ENABLE */
 
 #ifdef __cplusplus
 extern "C" {
@@ -39,7 +43,7 @@ typedef xmlValidState *xmlValidStatePtr;
  * Callback called when a validity error is found. This is a message
  * oriented function similar to an *printf function.
  */
-typedef void (XMLCDECL *xmlValidityErrorFunc) (void *ctx,
+typedef void (*xmlValidityErrorFunc) (void *ctx,
 			     const char *msg,
 			     ...) LIBXML_ATTR_FORMAT(2,3);
 
@@ -54,25 +58,10 @@ typedef void (XMLCDECL *xmlValidityErrorFunc) (void *ctx,
  * Callback called when a validity warning is found. This is a message
  * oriented function similar to an *printf function.
  */
-typedef void (XMLCDECL *xmlValidityWarningFunc) (void *ctx,
+typedef void (*xmlValidityWarningFunc) (void *ctx,
 			       const char *msg,
 			       ...) LIBXML_ATTR_FORMAT(2,3);
 
-#ifdef IN_LIBXML
-/**
- * XML_VCTXT_DTD_VALIDATED:
- *
- * Set after xmlValidateDtdFinal was called.
- */
-#define XML_VCTXT_DTD_VALIDATED (1u << 0)
-/**
- * XML_VCTXT_USE_PCTXT:
- *
- * Set if the validation context is part of a parser context.
- */
-#define XML_VCTXT_USE_PCTXT (1u << 1)
-#endif
-
 /*
  * xmlValidCtxt:
  * An xmlValidCtxt is used for error reporting when validating.
@@ -150,95 +139,98 @@ typedef struct _xmlHashTable xmlRefTable;
 typedef xmlRefTable *xmlRefTablePtr;
 
 /* Notation */
-XMLPUBFUN xmlNotationPtr XMLCALL
+XMLPUBFUN xmlNotationPtr
 		xmlAddNotationDecl	(xmlValidCtxtPtr ctxt,
 					 xmlDtdPtr dtd,
 					 const xmlChar *name,
 					 const xmlChar *PublicID,
 					 const xmlChar *SystemID);
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN xmlNotationTablePtr XMLCALL
+XMLPUBFUN xmlNotationTablePtr
 		xmlCopyNotationTable	(xmlNotationTablePtr table);
 #endif /* LIBXML_TREE_ENABLED */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeNotationTable	(xmlNotationTablePtr table);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 		xmlDumpNotationDecl	(xmlBufferPtr buf,
 					 xmlNotationPtr nota);
-XMLPUBFUN void XMLCALL
+/* XML_DEPRECATED, still used in lxml */
+XMLPUBFUN void
 		xmlDumpNotationTable	(xmlBufferPtr buf,
 					 xmlNotationTablePtr table);
 #endif /* LIBXML_OUTPUT_ENABLED */
 
 /* Element Content */
 /* the non Doc version are being deprecated */
-XMLPUBFUN xmlElementContentPtr XMLCALL
+XMLPUBFUN xmlElementContentPtr
 		xmlNewElementContent	(const xmlChar *name,
 					 xmlElementContentType type);
-XMLPUBFUN xmlElementContentPtr XMLCALL
+XMLPUBFUN xmlElementContentPtr
 		xmlCopyElementContent	(xmlElementContentPtr content);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeElementContent	(xmlElementContentPtr cur);
 /* the new versions with doc argument */
-XMLPUBFUN xmlElementContentPtr XMLCALL
+XMLPUBFUN xmlElementContentPtr
 		xmlNewDocElementContent	(xmlDocPtr doc,
 					 const xmlChar *name,
 					 xmlElementContentType type);
-XMLPUBFUN xmlElementContentPtr XMLCALL
+XMLPUBFUN xmlElementContentPtr
 		xmlCopyDocElementContent(xmlDocPtr doc,
 					 xmlElementContentPtr content);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeDocElementContent(xmlDocPtr doc,
 					 xmlElementContentPtr cur);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSnprintfElementContent(char *buf,
 					 int size,
 	                                 xmlElementContentPtr content,
 					 int englob);
 #ifdef LIBXML_OUTPUT_ENABLED
-/* DEPRECATED */
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 		xmlSprintfElementContent(char *buf,
 	                                 xmlElementContentPtr content,
 					 int englob);
 #endif /* LIBXML_OUTPUT_ENABLED */
-/* DEPRECATED */
 
 /* Element */
-XMLPUBFUN xmlElementPtr XMLCALL
+XMLPUBFUN xmlElementPtr
 		xmlAddElementDecl	(xmlValidCtxtPtr ctxt,
 					 xmlDtdPtr dtd,
 					 const xmlChar *name,
 					 xmlElementTypeVal type,
 					 xmlElementContentPtr content);
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN xmlElementTablePtr XMLCALL
+XMLPUBFUN xmlElementTablePtr
 		xmlCopyElementTable	(xmlElementTablePtr table);
 #endif /* LIBXML_TREE_ENABLED */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeElementTable	(xmlElementTablePtr table);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 		xmlDumpElementTable	(xmlBufferPtr buf,
 					 xmlElementTablePtr table);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 		xmlDumpElementDecl	(xmlBufferPtr buf,
 					 xmlElementPtr elem);
 #endif /* LIBXML_OUTPUT_ENABLED */
 
 /* Enumeration */
-XMLPUBFUN xmlEnumerationPtr XMLCALL
+XMLPUBFUN xmlEnumerationPtr
 		xmlCreateEnumeration	(const xmlChar *name);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeEnumeration	(xmlEnumerationPtr cur);
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN xmlEnumerationPtr XMLCALL
+XMLPUBFUN xmlEnumerationPtr
 		xmlCopyEnumeration	(xmlEnumerationPtr cur);
 #endif /* LIBXML_TREE_ENABLED */
 
 /* Attribute */
-XMLPUBFUN xmlAttributePtr XMLCALL
+XMLPUBFUN xmlAttributePtr
 		xmlAddAttributeDecl	(xmlValidCtxtPtr ctxt,
 					 xmlDtdPtr dtd,
 					 const xmlChar *elem,
@@ -249,60 +241,65 @@ XMLPUBFUN xmlAttributePtr XMLCALL
 					 const xmlChar *defaultValue,
 					 xmlEnumerationPtr tree);
 #ifdef LIBXML_TREE_ENABLED
-XMLPUBFUN xmlAttributeTablePtr XMLCALL
+XMLPUBFUN xmlAttributeTablePtr
 		xmlCopyAttributeTable  (xmlAttributeTablePtr table);
 #endif /* LIBXML_TREE_ENABLED */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeAttributeTable  (xmlAttributeTablePtr table);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 		xmlDumpAttributeTable  (xmlBufferPtr buf,
 					xmlAttributeTablePtr table);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 		xmlDumpAttributeDecl   (xmlBufferPtr buf,
 					xmlAttributePtr attr);
 #endif /* LIBXML_OUTPUT_ENABLED */
 
 /* IDs */
-XMLPUBFUN xmlIDPtr XMLCALL
+XMLPUBFUN int
+		xmlAddIDSafe	       (xmlAttrPtr attr,
+					const xmlChar *value);
+XMLPUBFUN xmlIDPtr
 		xmlAddID	       (xmlValidCtxtPtr ctxt,
 					xmlDocPtr doc,
 					const xmlChar *value,
 					xmlAttrPtr attr);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeIDTable	       (xmlIDTablePtr table);
-XMLPUBFUN xmlAttrPtr XMLCALL
+XMLPUBFUN xmlAttrPtr
 		xmlGetID	       (xmlDocPtr doc,
 					const xmlChar *ID);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsID		       (xmlDocPtr doc,
 					xmlNodePtr elem,
 					xmlAttrPtr attr);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlRemoveID	       (xmlDocPtr doc,
 					xmlAttrPtr attr);
 
 /* IDREFs */
 XML_DEPRECATED
-XMLPUBFUN xmlRefPtr XMLCALL
+XMLPUBFUN xmlRefPtr
 		xmlAddRef	       (xmlValidCtxtPtr ctxt,
 					xmlDocPtr doc,
 					const xmlChar *value,
 					xmlAttrPtr attr);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeRefTable	       (xmlRefTablePtr table);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsRef	       (xmlDocPtr doc,
 					xmlNodePtr elem,
 					xmlAttrPtr attr);
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlRemoveRef	       (xmlDocPtr doc,
 					xmlAttrPtr attr);
 XML_DEPRECATED
-XMLPUBFUN xmlListPtr XMLCALL
+XMLPUBFUN xmlListPtr
 		xmlGetRefs	       (xmlDocPtr doc,
 					const xmlChar *ID);
 
@@ -311,146 +308,163 @@ XMLPUBFUN xmlListPtr XMLCALL
  */
 #ifdef LIBXML_VALID_ENABLED
 /* Allocate/Release Validation Contexts */
-XMLPUBFUN xmlValidCtxtPtr XMLCALL
+XMLPUBFUN xmlValidCtxtPtr
 		xmlNewValidCtxt(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlFreeValidCtxt(xmlValidCtxtPtr);
 
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateRoot		(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateElementDecl	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 		                         xmlElementPtr elem);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 		xmlValidNormalizeAttributeValue(xmlDocPtr doc,
 					 xmlNodePtr elem,
 					 const xmlChar *name,
 					 const xmlChar *value);
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 		xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlNodePtr elem,
 					 const xmlChar *name,
 					 const xmlChar *value);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 		                         xmlAttributePtr attr);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateAttributeValue(xmlAttributeType type,
 					 const xmlChar *value);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateNotationDecl	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 		                         xmlNotationPtr nota);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateDtd		(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlDtdPtr dtd);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateDtdFinal	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateDocument	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateElement	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlNodePtr elem);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateOneElement	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 		                         xmlNodePtr elem);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateOneAttribute	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlNodePtr	elem,
 					 xmlAttrPtr attr,
 					 const xmlChar *value);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateOneNamespace	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlNodePtr elem,
 					 const xmlChar *prefix,
 					 xmlNsPtr ns,
 					 const xmlChar *value);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc);
 #endif /* LIBXML_VALID_ENABLED */
 
 #if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidateNotationUse	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 const xmlChar *notationName);
 #endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlIsMixedElement	(xmlDocPtr doc,
 					 const xmlChar *name);
-XMLPUBFUN xmlAttributePtr XMLCALL
+XMLPUBFUN xmlAttributePtr
 		xmlGetDtdAttrDesc	(xmlDtdPtr dtd,
 					 const xmlChar *elem,
 					 const xmlChar *name);
-XMLPUBFUN xmlAttributePtr XMLCALL
+XMLPUBFUN xmlAttributePtr
 		xmlGetDtdQAttrDesc	(xmlDtdPtr dtd,
 					 const xmlChar *elem,
 					 const xmlChar *name,
 					 const xmlChar *prefix);
-XMLPUBFUN xmlNotationPtr XMLCALL
+XMLPUBFUN xmlNotationPtr
 		xmlGetDtdNotationDesc	(xmlDtdPtr dtd,
 					 const xmlChar *name);
-XMLPUBFUN xmlElementPtr XMLCALL
+XMLPUBFUN xmlElementPtr
 		xmlGetDtdQElementDesc	(xmlDtdPtr dtd,
 					 const xmlChar *name,
 					 const xmlChar *prefix);
-XMLPUBFUN xmlElementPtr XMLCALL
+XMLPUBFUN xmlElementPtr
 		xmlGetDtdElementDesc	(xmlDtdPtr dtd,
 					 const xmlChar *name);
 
 #ifdef LIBXML_VALID_ENABLED
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidGetPotentialChildren(xmlElementContent *ctree,
 					 const xmlChar **names,
 					 int *len,
 					 int max);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidGetValidElements(xmlNode *prev,
 					 xmlNode *next,
 					 const xmlChar **names,
 					 int max);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateNameValue	(const xmlChar *value);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateNamesValue	(const xmlChar *value);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateNmtokenValue	(const xmlChar *value);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlValidateNmtokensValue(const xmlChar *value);
 
 #ifdef LIBXML_REGEXP_ENABLED
 /*
  * Validation based on the regexp support
  */
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidBuildContentModel(xmlValidCtxtPtr ctxt,
 					 xmlElementPtr elem);
 
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidatePushElement	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlNodePtr elem,
 					 const xmlChar *qname);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidatePushCData	(xmlValidCtxtPtr ctxt,
 					 const xmlChar *data,
 					 int len);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 		xmlValidatePopElement	(xmlValidCtxtPtr ctxt,
 					 xmlDocPtr doc,
 					 xmlNodePtr elem,
diff --git a/include/libxml/vtk_libxml2_mangle.h b/include/libxml/vtk_libxml2_mangle.h
index a84beeb23e0cb6ebab3932ae8a743e75f3487a68..a598b67f6fab38d203701ec4ebb03d23c27605eb 100644
--- a/include/libxml/vtk_libxml2_mangle.h
+++ b/include/libxml/vtk_libxml2_mangle.h
@@ -1,24 +1,20 @@
 #ifndef vtk_libxml2_mangle_h
 #define vtk_libxml2_mangle_h
 
-#define docbCreateFileParserCtxt vtklibxml2_docbCreateFileParserCtxt
-#define docbCreatePushParserCtxt vtklibxml2_docbCreatePushParserCtxt
-#define __docbDefaultSAXHandler vtklibxml2___docbDefaultSAXHandler
-#define docbDefaultSAXHandler vtklibxml2_docbDefaultSAXHandler
-#define docbDefaultSAXHandlerInit vtklibxml2_docbDefaultSAXHandlerInit
-#define docbEncodeEntities vtklibxml2_docbEncodeEntities
-#define docbFreeParserCtxt vtklibxml2_docbFreeParserCtxt
-#define docbParseChunk vtklibxml2_docbParseChunk
-#define docbParseDoc vtklibxml2_docbParseDoc
-#define docbParseDocument vtklibxml2_docbParseDocument
-#define docbParseFile vtklibxml2_docbParseFile
-#define docbSAXParseDoc vtklibxml2_docbSAXParseDoc
-#define docbSAXParseFile vtklibxml2_docbSAXParseFile
+/**
+ * Generated using:
+ *
+ * nm -g lib/libvtklibxml2-9.3.so |   grep -e ' [TDRSB] ' |\
+ *   cut -d' ' -f3 | grep -v -e 'vtklibxml2_' | \
+ *   sort | sed -e 's/\(.*\)/#define \1 vtklibxml2_\1/' > /tmp/vtk_libxml2_mangle.h
+ */
+
 #define htmlAttrAllowed vtklibxml2_htmlAttrAllowed
 #define htmlAutoCloseTag vtklibxml2_htmlAutoCloseTag
 #define htmlCreateFileParserCtxt vtklibxml2_htmlCreateFileParserCtxt
 #define htmlCreateMemoryParserCtxt vtklibxml2_htmlCreateMemoryParserCtxt
 #define htmlCreatePushParserCtxt vtklibxml2_htmlCreatePushParserCtxt
+#define htmlCtxtParseDocument vtklibxml2_htmlCtxtParseDocument
 #define htmlCtxtReadDoc vtklibxml2_htmlCtxtReadDoc
 #define htmlCtxtReadFd vtklibxml2_htmlCtxtReadFd
 #define htmlCtxtReadFile vtklibxml2_htmlCtxtReadFile
@@ -49,6 +45,7 @@
 #define htmlNewDoc vtklibxml2_htmlNewDoc
 #define htmlNewDocNoDtD vtklibxml2_htmlNewDocNoDtD
 #define htmlNewParserCtxt vtklibxml2_htmlNewParserCtxt
+#define htmlNewSAXParserCtxt vtklibxml2_htmlNewSAXParserCtxt
 #define htmlNodeDump vtklibxml2_htmlNodeDump
 #define htmlNodeDumpFile vtklibxml2_htmlNodeDumpFile
 #define htmlNodeDumpFileFormat vtklibxml2_htmlNodeDumpFileFormat
@@ -57,7 +54,6 @@
 #define htmlNodeStatus vtklibxml2_htmlNodeStatus
 #define htmlParseCharRef vtklibxml2_htmlParseCharRef
 #define htmlParseChunk vtklibxml2_htmlParseChunk
-#define __htmlParseContent vtklibxml2___htmlParseContent
 #define htmlParseDoc vtklibxml2_htmlParseDoc
 #define htmlParseDocument vtklibxml2_htmlParseDocument
 #define htmlParseElement vtklibxml2_htmlParseElement
@@ -110,14 +106,15 @@
 #define xmlAddDtdEntity vtklibxml2_xmlAddDtdEntity
 #define xmlAddElementDecl vtklibxml2_xmlAddElementDecl
 #define xmlAddEncodingAlias vtklibxml2_xmlAddEncodingAlias
+#define xmlAddEntity vtklibxml2_xmlAddEntity
 #define xmlAddID vtklibxml2_xmlAddID
+#define xmlAddIDSafe vtklibxml2_xmlAddIDSafe
 #define xmlAddNextSibling vtklibxml2_xmlAddNextSibling
 #define xmlAddNotationDecl vtklibxml2_xmlAddNotationDecl
 #define xmlAddPrevSibling vtklibxml2_xmlAddPrevSibling
 #define xmlAddRef vtklibxml2_xmlAddRef
 #define xmlAddSibling vtklibxml2_xmlAddSibling
 #define xmlAllocOutputBuffer vtklibxml2_xmlAllocOutputBuffer
-#define xmlAllocOutputBufferInternal vtklibxml2_xmlAllocOutputBufferInternal
 #define xmlAllocParserInputBuffer vtklibxml2_xmlAllocParserInputBuffer
 #define xmlAttrSerializeTxtContent vtklibxml2_xmlAttrSerializeTxtContent
 #define xmlAutomataCompile vtklibxml2_xmlAutomataCompile
@@ -137,32 +134,10 @@
 #define xmlAutomataNewTransition vtklibxml2_xmlAutomataNewTransition
 #define xmlAutomataNewTransition2 vtklibxml2_xmlAutomataNewTransition2
 #define xmlAutomataSetFinalState vtklibxml2_xmlAutomataSetFinalState
-#define xmlAutomataSetFlags vtklibxml2_xmlAutomataSetFlags
-#define xmlBufAdd vtklibxml2_xmlBufAdd
-#define xmlBufAddHead vtklibxml2_xmlBufAddHead
-#define xmlBufAddLen vtklibxml2_xmlBufAddLen
-#define xmlBufAttrSerializeTxtContent vtklibxml2_xmlBufAttrSerializeTxtContent
-#define xmlBufAvail vtklibxml2_xmlBufAvail
-#define xmlBufBackToBuffer vtklibxml2_xmlBufBackToBuffer
-#define xmlBufCat vtklibxml2_xmlBufCat
-#define xmlBufCCat vtklibxml2_xmlBufCCat
 #define xmlBufContent vtklibxml2_xmlBufContent
-#define xmlBufCreate vtklibxml2_xmlBufCreate
-#define xmlBufCreateSize vtklibxml2_xmlBufCreateSize
-#define xmlBufCreateStatic vtklibxml2_xmlBufCreateStatic
-#define xmlBufDetach vtklibxml2_xmlBufDetach
-#define xmlBufDump vtklibxml2_xmlBufDump
-#define xmlBufDumpAttributeDecl vtklibxml2_xmlBufDumpAttributeDecl
-#define xmlBufDumpElementDecl vtklibxml2_xmlBufDumpElementDecl
-#define xmlBufDumpEntityDecl vtklibxml2_xmlBufDumpEntityDecl
-#define xmlBufDumpNotationTable vtklibxml2_xmlBufDumpNotationTable
-#define xmlBufEmpty vtklibxml2_xmlBufEmpty
 #define xmlBufEnd vtklibxml2_xmlBufEnd
-#define xmlBufErase vtklibxml2_xmlBufErase
 #define xmlBufferAdd vtklibxml2_xmlBufferAdd
 #define xmlBufferAddHead vtklibxml2_xmlBufferAddHead
-#define __xmlBufferAllocScheme vtklibxml2___xmlBufferAllocScheme
-#define xmlBufferAllocScheme vtklibxml2_xmlBufferAllocScheme
 #define xmlBufferCat vtklibxml2_xmlBufferCat
 #define xmlBufferCCat vtklibxml2_xmlBufferCCat
 #define xmlBufferContent vtklibxml2_xmlBufferContent
@@ -181,29 +156,15 @@
 #define xmlBufferWriteChar vtklibxml2_xmlBufferWriteChar
 #define xmlBufferWriteCHAR vtklibxml2_xmlBufferWriteCHAR
 #define xmlBufferWriteQuotedString vtklibxml2_xmlBufferWriteQuotedString
-#define xmlBufFree vtklibxml2_xmlBufFree
-#define xmlBufFromBuffer vtklibxml2_xmlBufFromBuffer
-#define xmlBufGetAllocationScheme vtklibxml2_xmlBufGetAllocationScheme
-#define xmlBufGetInputBase vtklibxml2_xmlBufGetInputBase
 #define xmlBufGetNodeContent vtklibxml2_xmlBufGetNodeContent
-#define xmlBufGrow vtklibxml2_xmlBufGrow
-#define xmlBufInflate vtklibxml2_xmlBufInflate
-#define xmlBufIsEmpty vtklibxml2_xmlBufIsEmpty
-#define xmlBufLength vtklibxml2_xmlBufLength
-#define xmlBufMergeBuffer vtklibxml2_xmlBufMergeBuffer
 #define xmlBufNodeDump vtklibxml2_xmlBufNodeDump
-#define xmlBufResetInput vtklibxml2_xmlBufResetInput
-#define xmlBufResize vtklibxml2_xmlBufResize
-#define xmlBufSetAllocationScheme vtklibxml2_xmlBufSetAllocationScheme
-#define xmlBufSetInputBaseCur vtklibxml2_xmlBufSetInputBaseCur
 #define xmlBufShrink vtklibxml2_xmlBufShrink
 #define xmlBufUse vtklibxml2_xmlBufUse
-#define xmlBufWriteChar vtklibxml2_xmlBufWriteChar
-#define xmlBufWriteCHAR vtklibxml2_xmlBufWriteCHAR
-#define xmlBufWriteQuotedString vtklibxml2_xmlBufWriteQuotedString
 #define xmlBuildQName vtklibxml2_xmlBuildQName
 #define xmlBuildRelativeURI vtklibxml2_xmlBuildRelativeURI
+#define xmlBuildRelativeURISafe vtklibxml2_xmlBuildRelativeURISafe
 #define xmlBuildURI vtklibxml2_xmlBuildURI
+#define xmlBuildURISafe vtklibxml2_xmlBuildURISafe
 #define xmlByteConsumed vtklibxml2_xmlByteConsumed
 #define xmlC14NDocDumpMemory vtklibxml2_xmlC14NDocDumpMemory
 #define xmlC14NDocSave vtklibxml2_xmlC14NDocSave
@@ -232,18 +193,15 @@
 #define xmlCatalogSetDefaults vtklibxml2_xmlCatalogSetDefaults
 #define xmlCharEncCloseFunc vtklibxml2_xmlCharEncCloseFunc
 #define xmlCharEncFirstLine vtklibxml2_xmlCharEncFirstLine
-#define xmlCharEncFirstLineInput vtklibxml2_xmlCharEncFirstLineInput
-#define xmlCharEncFirstLineInt vtklibxml2_xmlCharEncFirstLineInt
 #define xmlCharEncInFunc vtklibxml2_xmlCharEncInFunc
-#define xmlCharEncInput vtklibxml2_xmlCharEncInput
 #define xmlCharEncOutFunc vtklibxml2_xmlCharEncOutFunc
-#define xmlCharEncOutput vtklibxml2_xmlCharEncOutput
 #define xmlCharInRange vtklibxml2_xmlCharInRange
 #define xmlCharStrdup vtklibxml2_xmlCharStrdup
 #define xmlCharStrndup vtklibxml2_xmlCharStrndup
 #define xmlCheckFilename vtklibxml2_xmlCheckFilename
 #define xmlCheckHTTPInput vtklibxml2_xmlCheckHTTPInput
 #define xmlCheckLanguageID vtklibxml2_xmlCheckLanguageID
+#define xmlCheckThreadLocalStorage vtklibxml2_xmlCheckThreadLocalStorage
 #define xmlCheckUTF8 vtklibxml2_xmlCheckUTF8
 #define xmlCheckVersion vtklibxml2_xmlCheckVersion
 #define xmlChildElementCount vtklibxml2_xmlChildElementCount
@@ -287,7 +245,9 @@
 #define xmlCreatePushParserCtxt vtklibxml2_xmlCreatePushParserCtxt
 #define xmlCreateURI vtklibxml2_xmlCreateURI
 #define xmlCreateURLParserCtxt vtklibxml2_xmlCreateURLParserCtxt
+#define xmlCtxtErrMemory vtklibxml2_xmlCtxtErrMemory
 #define xmlCtxtGetLastError vtklibxml2_xmlCtxtGetLastError
+#define xmlCtxtParseDocument vtklibxml2_xmlCtxtParseDocument
 #define xmlCtxtReadDoc vtklibxml2_xmlCtxtReadDoc
 #define xmlCtxtReadFd vtklibxml2_xmlCtxtReadFd
 #define xmlCtxtReadFile vtklibxml2_xmlCtxtReadFile
@@ -296,10 +256,11 @@
 #define xmlCtxtReset vtklibxml2_xmlCtxtReset
 #define xmlCtxtResetLastError vtklibxml2_xmlCtxtResetLastError
 #define xmlCtxtResetPush vtklibxml2_xmlCtxtResetPush
+#define xmlCtxtSetErrorHandler vtklibxml2_xmlCtxtSetErrorHandler
+#define xmlCtxtSetMaxAmplification vtklibxml2_xmlCtxtSetMaxAmplification
+#define xmlCtxtSetOptions vtklibxml2_xmlCtxtSetOptions
 #define xmlCtxtUseOptions vtklibxml2_xmlCtxtUseOptions
 #define xmlCurrentChar vtklibxml2_xmlCurrentChar
-#define __xmlDefaultBufferSize vtklibxml2___xmlDefaultBufferSize
-#define xmlDefaultBufferSize vtklibxml2_xmlDefaultBufferSize
 #define __xmlDefaultSAXHandler vtklibxml2___xmlDefaultSAXHandler
 #define xmlDefaultSAXHandler vtklibxml2_xmlDefaultSAXHandler
 #define xmlDefaultSAXHandlerInit vtklibxml2_xmlDefaultSAXHandlerInit
@@ -307,8 +268,6 @@
 #define xmlDefaultSAXLocator vtklibxml2_xmlDefaultSAXLocator
 #define xmlDelEncodingAlias vtklibxml2_xmlDelEncodingAlias
 #define xmlDeregisterNodeDefault vtklibxml2_xmlDeregisterNodeDefault
-#define __xmlDeregisterNodeDefaultValue vtklibxml2___xmlDeregisterNodeDefaultValue
-#define xmlDeregisterNodeDefaultValue vtklibxml2_xmlDeregisterNodeDefaultValue
 #define xmlDetectCharEncoding vtklibxml2_xmlDetectCharEncoding
 #define xmlDictCleanup vtklibxml2_xmlDictCleanup
 #define xmlDictCreate vtklibxml2_xmlDictCreate
@@ -338,8 +297,6 @@
 #define xmlDOMWrapNewCtxt vtklibxml2_xmlDOMWrapNewCtxt
 #define xmlDOMWrapReconcileNamespaces vtklibxml2_xmlDOMWrapReconcileNamespaces
 #define xmlDOMWrapRemoveNode vtklibxml2_xmlDOMWrapRemoveNode
-#define __xmlDoValidityCheckingDefaultValue vtklibxml2___xmlDoValidityCheckingDefaultValue
-#define xmlDoValidityCheckingDefaultValue vtklibxml2_xmlDoValidityCheckingDefaultValue
 #define xmlDumpAttributeDecl vtklibxml2_xmlDumpAttributeDecl
 #define xmlDumpAttributeTable vtklibxml2_xmlDumpAttributeTable
 #define xmlDumpElementDecl vtklibxml2_xmlDumpElementDecl
@@ -349,20 +306,15 @@
 #define xmlDumpNotationDecl vtklibxml2_xmlDumpNotationDecl
 #define xmlDumpNotationTable vtklibxml2_xmlDumpNotationTable
 #define xmlElemDump vtklibxml2_xmlElemDump
-#define xmlEncodeAttributeEntities vtklibxml2_xmlEncodeAttributeEntities
 #define xmlEncodeEntitiesReentrant vtklibxml2_xmlEncodeEntitiesReentrant
 #define xmlEncodeSpecialChars vtklibxml2_xmlEncodeSpecialChars
-#define __xmlErrEncoding vtklibxml2___xmlErrEncoding
-#define xmlErrMemory vtklibxml2_xmlErrMemory
-#define xmlEscapeFormatString vtklibxml2_xmlEscapeFormatString
 #define xmlFileClose vtklibxml2_xmlFileClose
 #define xmlFileMatch vtklibxml2_xmlFileMatch
 #define xmlFileOpen vtklibxml2_xmlFileOpen
 #define xmlFileRead vtklibxml2_xmlFileRead
 #define xmlFindCharEncodingHandler vtklibxml2_xmlFindCharEncodingHandler
 #define xmlFirstElementChild vtklibxml2_xmlFirstElementChild
-#define __xmlFree vtklibxml2___xmlFree
-#define xmlFree vtklibxml2_xmlFree
+#define xmlFormatError vtklibxml2_xmlFormatError
 #define xmlFreeAttributeTable vtklibxml2_xmlFreeAttributeTable
 #define xmlFreeAutomata vtklibxml2_xmlFreeAutomata
 #define xmlFreeCatalog vtklibxml2_xmlFreeCatalog
@@ -372,6 +324,7 @@
 #define xmlFreeElementContent vtklibxml2_xmlFreeElementContent
 #define xmlFreeElementTable vtklibxml2_xmlFreeElementTable
 #define xmlFreeEntitiesTable vtklibxml2_xmlFreeEntitiesTable
+#define xmlFreeEntity vtklibxml2_xmlFreeEntity
 #define xmlFreeEnumeration vtklibxml2_xmlFreeEnumeration
 #define xmlFreeIDTable vtklibxml2_xmlFreeIDTable
 #define xmlFreeInputStream vtklibxml2_xmlFreeInputStream
@@ -396,11 +349,6 @@
 #define xmlFreeValidCtxt vtklibxml2_xmlFreeValidCtxt
 #define xmlGcMemGet vtklibxml2_xmlGcMemGet
 #define xmlGcMemSetup vtklibxml2_xmlGcMemSetup
-#define __xmlGenericError vtklibxml2___xmlGenericError
-#define xmlGenericError vtklibxml2_xmlGenericError
-#define __xmlGenericErrorContext vtklibxml2___xmlGenericErrorContext
-#define xmlGenericErrorContext vtklibxml2_xmlGenericErrorContext
-#define xmlGenericErrorDefaultFunc vtklibxml2_xmlGenericErrorDefaultFunc
 #define xmlGetBufferAllocationScheme vtklibxml2_xmlGetBufferAllocationScheme
 #define xmlGetCharEncodingHandler vtklibxml2_xmlGetCharEncodingHandler
 #define xmlGetCharEncodingName vtklibxml2_xmlGetCharEncodingName
@@ -424,6 +372,7 @@
 #define xmlGetNodePath vtklibxml2_xmlGetNodePath
 #define xmlGetNoNsProp vtklibxml2_xmlGetNoNsProp
 #define xmlGetNsList vtklibxml2_xmlGetNsList
+#define xmlGetNsListSafe vtklibxml2_xmlGetNsListSafe
 #define xmlGetNsProp vtklibxml2_xmlGetNsProp
 #define xmlGetParameterEntity vtklibxml2_xmlGetParameterEntity
 #define xmlGetPredefinedEntity vtklibxml2_xmlGetPredefinedEntity
@@ -431,16 +380,15 @@
 #define xmlGetRefs vtklibxml2_xmlGetRefs
 #define xmlGetThreadId vtklibxml2_xmlGetThreadId
 #define xmlGetUTF8Char vtklibxml2_xmlGetUTF8Char
-#define __xmlGetWarningsDefaultValue vtklibxml2___xmlGetWarningsDefaultValue
-#define xmlGetWarningsDefaultValue vtklibxml2_xmlGetWarningsDefaultValue
-#define __xmlGlobalInitMutexDestroy vtklibxml2___xmlGlobalInitMutexDestroy
-#define __xmlGlobalInitMutexLock vtklibxml2___xmlGlobalInitMutexLock
-#define __xmlGlobalInitMutexUnlock vtklibxml2___xmlGlobalInitMutexUnlock
 #define xmlHasFeature vtklibxml2_xmlHasFeature
+#define xmlHashAdd vtklibxml2_xmlHashAdd
+#define xmlHashAdd2 vtklibxml2_xmlHashAdd2
+#define xmlHashAdd3 vtklibxml2_xmlHashAdd3
 #define xmlHashAddEntry vtklibxml2_xmlHashAddEntry
 #define xmlHashAddEntry2 vtklibxml2_xmlHashAddEntry2
 #define xmlHashAddEntry3 vtklibxml2_xmlHashAddEntry3
 #define xmlHashCopy vtklibxml2_xmlHashCopy
+#define xmlHashCopySafe vtklibxml2_xmlHashCopySafe
 #define xmlHashCreate vtklibxml2_xmlHashCreate
 #define xmlHashCreateDict vtklibxml2_xmlHashCreateDict
 #define xmlHashDefaultDeallocator vtklibxml2_xmlHashDefaultDeallocator
@@ -464,12 +412,9 @@
 #define xmlHashUpdateEntry3 vtklibxml2_xmlHashUpdateEntry3
 #define xmlHasNsProp vtklibxml2_xmlHasNsProp
 #define xmlHasProp vtklibxml2_xmlHasProp
-#define __xmlIndentTreeOutput vtklibxml2___xmlIndentTreeOutput
-#define xmlIndentTreeOutput vtklibxml2_xmlIndentTreeOutput
 #define xmlInitCharEncodingHandlers vtklibxml2_xmlInitCharEncodingHandlers
 #define xmlInitGlobals vtklibxml2_xmlInitGlobals
 #define xmlInitializeCatalog vtklibxml2_xmlInitializeCatalog
-#define __xmlInitializeDict vtklibxml2___xmlInitializeDict
 #define xmlInitializeDict vtklibxml2_xmlInitializeDict
 #define xmlInitializeGlobalState vtklibxml2_xmlInitializeGlobalState
 #define xmlInitMemory vtklibxml2_xmlInitMemory
@@ -477,8 +422,6 @@
 #define xmlInitParser vtklibxml2_xmlInitParser
 #define xmlInitParserCtxt vtklibxml2_xmlInitParserCtxt
 #define xmlInitThreads vtklibxml2_xmlInitThreads
-#define xmlInputReadCallbackNop vtklibxml2_xmlInputReadCallbackNop
-#define __xmlIOErr vtklibxml2___xmlIOErr
 #define xmlIOParseDTD vtklibxml2_xmlIOParseDTD
 #define xmlIsBaseChar vtklibxml2_xmlIsBaseChar
 #define xmlIsBaseCharGroup vtklibxml2_xmlIsBaseCharGroup
@@ -503,14 +446,8 @@
 #define xmlIsRef vtklibxml2_xmlIsRef
 #define xmlIsXHTML vtklibxml2_xmlIsXHTML
 #define xmlKeepBlanksDefault vtklibxml2_xmlKeepBlanksDefault
-#define __xmlKeepBlanksDefaultValue vtklibxml2___xmlKeepBlanksDefaultValue
-#define xmlKeepBlanksDefaultValue vtklibxml2_xmlKeepBlanksDefaultValue
 #define xmlLastElementChild vtklibxml2_xmlLastElementChild
-#define __xmlLastError vtklibxml2___xmlLastError
-#define xmlLastError vtklibxml2_xmlLastError
 #define xmlLineNumbersDefault vtklibxml2_xmlLineNumbersDefault
-#define __xmlLineNumbersDefaultValue vtklibxml2___xmlLineNumbersDefaultValue
-#define xmlLineNumbersDefaultValue vtklibxml2_xmlLineNumbersDefaultValue
 #define xmlLinkGetData vtklibxml2_xmlLinkGetData
 #define xmlListAppend vtklibxml2_xmlListAppend
 #define xmlListClear vtklibxml2_xmlListClear
@@ -540,18 +477,11 @@
 #define xmlLoadACatalog vtklibxml2_xmlLoadACatalog
 #define xmlLoadCatalog vtklibxml2_xmlLoadCatalog
 #define xmlLoadCatalogs vtklibxml2_xmlLoadCatalogs
-#define __xmlLoaderErr vtklibxml2___xmlLoaderErr
-#define __xmlLoadExtDtdDefaultValue vtklibxml2___xmlLoadExtDtdDefaultValue
-#define xmlLoadExtDtdDefaultValue vtklibxml2_xmlLoadExtDtdDefaultValue
 #define xmlLoadExternalEntity vtklibxml2_xmlLoadExternalEntity
 #define xmlLoadSGMLSuperCatalog vtklibxml2_xmlLoadSGMLSuperCatalog
 #define xmlLockLibrary vtklibxml2_xmlLockLibrary
-#define __xmlMalloc vtklibxml2___xmlMalloc
-#define xmlMalloc vtklibxml2_xmlMalloc
-#define __xmlMallocAtomic vtklibxml2___xmlMallocAtomic
-#define xmlMallocAtomic vtklibxml2_xmlMallocAtomic
+#define xmlLookupCharEncodingHandler vtklibxml2_xmlLookupCharEncodingHandler
 #define xmlMallocAtomicLoc vtklibxml2_xmlMallocAtomicLoc
-#define xmlMallocBreakpoint vtklibxml2_xmlMallocBreakpoint
 #define xmlMallocLoc vtklibxml2_xmlMallocLoc
 #define xmlMemBlocks vtklibxml2_xmlMemBlocks
 #define xmlMemDisplay vtklibxml2_xmlMemDisplay
@@ -564,8 +494,7 @@
 #define xmlMemRealloc vtklibxml2_xmlMemRealloc
 #define xmlMemSetup vtklibxml2_xmlMemSetup
 #define xmlMemShow vtklibxml2_xmlMemShow
-#define __xmlMemStrdup vtklibxml2___xmlMemStrdup
-#define xmlMemStrdup vtklibxml2_xmlMemStrdup
+#define xmlMemSize vtklibxml2_xmlMemSize
 #define xmlMemStrdupLoc vtklibxml2_xmlMemStrdupLoc
 #define xmlMemUsed vtklibxml2_xmlMemUsed
 #define xmlModuleClose vtklibxml2_xmlModuleClose
@@ -610,6 +539,7 @@
 #define xmlNewProp vtklibxml2_xmlNewProp
 #define xmlNewReference vtklibxml2_xmlNewReference
 #define xmlNewRMutex vtklibxml2_xmlNewRMutex
+#define xmlNewSAXParserCtxt vtklibxml2_xmlNewSAXParserCtxt
 #define xmlNewStringInputStream vtklibxml2_xmlNewStringInputStream
 #define xmlNewText vtklibxml2_xmlNewText
 #define xmlNewTextChild vtklibxml2_xmlNewTextChild
@@ -630,7 +560,9 @@
 #define xmlNodeBufGetContent vtklibxml2_xmlNodeBufGetContent
 #define xmlNodeDump vtklibxml2_xmlNodeDump
 #define xmlNodeDumpOutput vtklibxml2_xmlNodeDumpOutput
+#define xmlNodeGetAttrValue vtklibxml2_xmlNodeGetAttrValue
 #define xmlNodeGetBase vtklibxml2_xmlNodeGetBase
+#define xmlNodeGetBaseSafe vtklibxml2_xmlNodeGetBaseSafe
 #define xmlNodeGetContent vtklibxml2_xmlNodeGetContent
 #define xmlNodeGetLang vtklibxml2_xmlNodeGetLang
 #define xmlNodeGetSpacePreserve vtklibxml2_xmlNodeGetSpacePreserve
@@ -646,7 +578,7 @@
 #define xmlNoNetExternalEntityLoader vtklibxml2_xmlNoNetExternalEntityLoader
 #define xmlNormalizeURIPath vtklibxml2_xmlNormalizeURIPath
 #define xmlNormalizeWindowsPath vtklibxml2_xmlNormalizeWindowsPath
-#define xmlNsListDumpOutput vtklibxml2_xmlNsListDumpOutput
+#define xmlOpenCharEncodingHandler vtklibxml2_xmlOpenCharEncodingHandler
 #define xmlOutputBufferClose vtklibxml2_xmlOutputBufferClose
 #define xmlOutputBufferCreateBuffer vtklibxml2_xmlOutputBufferCreateBuffer
 #define xmlOutputBufferCreateFd vtklibxml2_xmlOutputBufferCreateFd
@@ -654,8 +586,6 @@
 #define __xmlOutputBufferCreateFilename vtklibxml2___xmlOutputBufferCreateFilename
 #define xmlOutputBufferCreateFilename vtklibxml2_xmlOutputBufferCreateFilename
 #define xmlOutputBufferCreateFilenameDefault vtklibxml2_xmlOutputBufferCreateFilenameDefault
-#define __xmlOutputBufferCreateFilenameValue vtklibxml2___xmlOutputBufferCreateFilenameValue
-#define xmlOutputBufferCreateFilenameValue vtklibxml2_xmlOutputBufferCreateFilenameValue
 #define xmlOutputBufferCreateIO vtklibxml2_xmlOutputBufferCreateIO
 #define xmlOutputBufferFlush vtklibxml2_xmlOutputBufferFlush
 #define xmlOutputBufferGetContent vtklibxml2_xmlOutputBufferGetContent
@@ -728,8 +658,6 @@
 #define __xmlParserInputBufferCreateFilename vtklibxml2___xmlParserInputBufferCreateFilename
 #define xmlParserInputBufferCreateFilename vtklibxml2_xmlParserInputBufferCreateFilename
 #define xmlParserInputBufferCreateFilenameDefault vtklibxml2_xmlParserInputBufferCreateFilenameDefault
-#define __xmlParserInputBufferCreateFilenameValue vtklibxml2___xmlParserInputBufferCreateFilenameValue
-#define xmlParserInputBufferCreateFilenameValue vtklibxml2_xmlParserInputBufferCreateFilenameValue
 #define xmlParserInputBufferCreateIO vtklibxml2_xmlParserInputBufferCreateIO
 #define xmlParserInputBufferCreateMem vtklibxml2_xmlParserInputBufferCreateMem
 #define xmlParserInputBufferCreateStatic vtklibxml2_xmlParserInputBufferCreateStatic
@@ -754,11 +682,13 @@
 #define xmlParseURI vtklibxml2_xmlParseURI
 #define xmlParseURIRaw vtklibxml2_xmlParseURIRaw
 #define xmlParseURIReference vtklibxml2_xmlParseURIReference
+#define xmlParseURISafe vtklibxml2_xmlParseURISafe
 #define xmlParseVersionInfo vtklibxml2_xmlParseVersionInfo
 #define xmlParseVersionNum vtklibxml2_xmlParseVersionNum
 #define xmlParseXMLDecl vtklibxml2_xmlParseXMLDecl
 #define xmlPathToURI vtklibxml2_xmlPathToURI
 #define xmlPatterncompile vtklibxml2_xmlPatterncompile
+#define xmlPatternCompileSafe vtklibxml2_xmlPatternCompileSafe
 #define xmlPatternFromRoot vtklibxml2_xmlPatternFromRoot
 #define xmlPatternGetStreamCtxt vtklibxml2_xmlPatternGetStreamCtxt
 #define xmlPatternMatch vtklibxml2_xmlPatternMatch
@@ -766,16 +696,12 @@
 #define xmlPatternMinDepth vtklibxml2_xmlPatternMinDepth
 #define xmlPatternStreamable vtklibxml2_xmlPatternStreamable
 #define xmlPedanticParserDefault vtklibxml2_xmlPedanticParserDefault
-#define __xmlPedanticParserDefaultValue vtklibxml2___xmlPedanticParserDefaultValue
-#define xmlPedanticParserDefaultValue vtklibxml2_xmlPedanticParserDefaultValue
 #define xmlPopInput vtklibxml2_xmlPopInput
 #define xmlPopInputCallbacks vtklibxml2_xmlPopInputCallbacks
 #define xmlPopOutputCallbacks vtklibxml2_xmlPopOutputCallbacks
 #define xmlPreviousElementSibling vtklibxml2_xmlPreviousElementSibling
 #define xmlPrintURI vtklibxml2_xmlPrintURI
 #define xmlPushInput vtklibxml2_xmlPushInput
-#define __xmlRaiseError vtklibxml2___xmlRaiseError
-#define __xmlRandom vtklibxml2___xmlRandom
 #define xmlReadDoc vtklibxml2_xmlReadDoc
 #define xmlReaderForDoc vtklibxml2_xmlReaderForDoc
 #define xmlReaderForFd vtklibxml2_xmlReaderForFd
@@ -793,8 +719,6 @@
 #define xmlReadFile vtklibxml2_xmlReadFile
 #define xmlReadIO vtklibxml2_xmlReadIO
 #define xmlReadMemory vtklibxml2_xmlReadMemory
-#define __xmlRealloc vtklibxml2___xmlRealloc
-#define xmlRealloc vtklibxml2_xmlRealloc
 #define xmlReallocLoc vtklibxml2_xmlReallocLoc
 #define xmlReconciliateNs vtklibxml2_xmlReconciliateNs
 #define xmlRecoverDoc vtklibxml2_xmlRecoverDoc
@@ -810,14 +734,11 @@
 #define xmlRegexpPrint vtklibxml2_xmlRegexpPrint
 #define xmlRegFreeExecCtxt vtklibxml2_xmlRegFreeExecCtxt
 #define xmlRegFreeRegexp vtklibxml2_xmlRegFreeRegexp
-#define __xmlRegisterCallbacks vtklibxml2___xmlRegisterCallbacks
 #define xmlRegisterCharEncodingHandler vtklibxml2_xmlRegisterCharEncodingHandler
 #define xmlRegisterDefaultInputCallbacks vtklibxml2_xmlRegisterDefaultInputCallbacks
 #define xmlRegisterDefaultOutputCallbacks vtklibxml2_xmlRegisterDefaultOutputCallbacks
 #define xmlRegisterInputCallbacks vtklibxml2_xmlRegisterInputCallbacks
 #define xmlRegisterNodeDefault vtklibxml2_xmlRegisterNodeDefault
-#define __xmlRegisterNodeDefaultValue vtklibxml2___xmlRegisterNodeDefaultValue
-#define xmlRegisterNodeDefaultValue vtklibxml2_xmlRegisterNodeDefaultValue
 #define xmlRegisterOutputCallbacks vtklibxml2_xmlRegisterOutputCallbacks
 #define xmlRegNewExecCtxt vtklibxml2_xmlRegNewExecCtxt
 #define xmlRelaxNGCleanupTypes vtklibxml2_xmlRelaxNGCleanupTypes
@@ -857,12 +778,11 @@
 #define xmlSaveFile vtklibxml2_xmlSaveFile
 #define xmlSaveFileEnc vtklibxml2_xmlSaveFileEnc
 #define xmlSaveFileTo vtklibxml2_xmlSaveFileTo
+#define xmlSaveFinish vtklibxml2_xmlSaveFinish
 #define xmlSaveFlush vtklibxml2_xmlSaveFlush
 #define xmlSaveFormatFile vtklibxml2_xmlSaveFormatFile
 #define xmlSaveFormatFileEnc vtklibxml2_xmlSaveFormatFileEnc
 #define xmlSaveFormatFileTo vtklibxml2_xmlSaveFormatFileTo
-#define __xmlSaveNoEmptyTags vtklibxml2___xmlSaveNoEmptyTags
-#define xmlSaveNoEmptyTags vtklibxml2_xmlSaveNoEmptyTags
 #define xmlSaveSetAttrEscape vtklibxml2_xmlSaveSetAttrEscape
 #define xmlSaveSetEscape vtklibxml2_xmlSaveSetEscape
 #define xmlSaveToBuffer vtklibxml2_xmlSaveToBuffer
@@ -891,7 +811,6 @@
 #define xmlSAX2HasInternalSubset vtklibxml2_xmlSAX2HasInternalSubset
 #define xmlSAX2IgnorableWhitespace vtklibxml2_xmlSAX2IgnorableWhitespace
 #define xmlSAX2InitDefaultSAXHandler vtklibxml2_xmlSAX2InitDefaultSAXHandler
-#define xmlSAX2InitDocbDefaultSAXHandler vtklibxml2_xmlSAX2InitDocbDefaultSAXHandler
 #define xmlSAX2InitHtmlDefaultSAXHandler vtklibxml2_xmlSAX2InitHtmlDefaultSAXHandler
 #define xmlSAX2InternalSubset vtklibxml2_xmlSAX2InternalSubset
 #define xmlSAX2IsStandalone vtklibxml2_xmlSAX2IsStandalone
@@ -1002,7 +921,6 @@
 #define xmlSetStructuredErrorFunc vtklibxml2_xmlSetStructuredErrorFunc
 #define xmlSetTreeDoc vtklibxml2_xmlSetTreeDoc
 #define xmlSetupParserForBuffer vtklibxml2_xmlSetupParserForBuffer
-#define __xmlSimpleError vtklibxml2___xmlSimpleError
 #define xmlSkipBlankChars vtklibxml2_xmlSkipBlankChars
 #define xmlSnprintfElementContent vtklibxml2_xmlSnprintfElementContent
 #define xmlSplitQName vtklibxml2_xmlSplitQName
@@ -1040,15 +958,10 @@
 #define xmlStrQEqual vtklibxml2_xmlStrQEqual
 #define xmlStrstr vtklibxml2_xmlStrstr
 #define xmlStrsub vtklibxml2_xmlStrsub
-#define __xmlStructuredError vtklibxml2___xmlStructuredError
-#define xmlStructuredError vtklibxml2_xmlStructuredError
-#define __xmlStructuredErrorContext vtklibxml2___xmlStructuredErrorContext
-#define xmlStructuredErrorContext vtklibxml2_xmlStructuredErrorContext
 #define xmlStrVPrintf vtklibxml2_xmlStrVPrintf
 #define xmlSubstituteEntitiesDefault vtklibxml2_xmlSubstituteEntitiesDefault
-#define __xmlSubstituteEntitiesDefaultValue vtklibxml2___xmlSubstituteEntitiesDefaultValue
-#define xmlSubstituteEntitiesDefaultValue vtklibxml2_xmlSubstituteEntitiesDefaultValue
 #define xmlSwitchEncoding vtklibxml2_xmlSwitchEncoding
+#define xmlSwitchEncodingName vtklibxml2_xmlSwitchEncodingName
 #define xmlSwitchInputEncoding vtklibxml2_xmlSwitchInputEncoding
 #define xmlSwitchToEncoding vtklibxml2_xmlSwitchToEncoding
 #define xmlTextConcat vtklibxml2_xmlTextConcat
@@ -1075,6 +988,7 @@
 #define xmlTextReaderGetAttributeNo vtklibxml2_xmlTextReaderGetAttributeNo
 #define xmlTextReaderGetAttributeNs vtklibxml2_xmlTextReaderGetAttributeNs
 #define xmlTextReaderGetErrorHandler vtklibxml2_xmlTextReaderGetErrorHandler
+#define xmlTextReaderGetLastError vtklibxml2_xmlTextReaderGetLastError
 #define xmlTextReaderGetParserColumnNumber vtklibxml2_xmlTextReaderGetParserColumnNumber
 #define xmlTextReaderGetParserLineNumber vtklibxml2_xmlTextReaderGetParserLineNumber
 #define xmlTextReaderGetParserProp vtklibxml2_xmlTextReaderGetParserProp
@@ -1117,6 +1031,7 @@
 #define xmlTextReaderSchemaValidate vtklibxml2_xmlTextReaderSchemaValidate
 #define xmlTextReaderSchemaValidateCtxt vtklibxml2_xmlTextReaderSchemaValidateCtxt
 #define xmlTextReaderSetErrorHandler vtklibxml2_xmlTextReaderSetErrorHandler
+#define xmlTextReaderSetMaxAmplification vtklibxml2_xmlTextReaderSetMaxAmplification
 #define xmlTextReaderSetParserProp vtklibxml2_xmlTextReaderSetParserProp
 #define xmlTextReaderSetSchema vtklibxml2_xmlTextReaderSetSchema
 #define xmlTextReaderSetStructuredErrorHandler vtklibxml2_xmlTextReaderSetStructuredErrorHandler
@@ -1124,6 +1039,7 @@
 #define xmlTextReaderStandalone vtklibxml2_xmlTextReaderStandalone
 #define xmlTextReaderValue vtklibxml2_xmlTextReaderValue
 #define xmlTextReaderXmlLang vtklibxml2_xmlTextReaderXmlLang
+#define xmlTextWriterClose vtklibxml2_xmlTextWriterClose
 #define xmlTextWriterEndAttribute vtklibxml2_xmlTextWriterEndAttribute
 #define xmlTextWriterEndCDATA vtklibxml2_xmlTextWriterEndCDATA
 #define xmlTextWriterEndComment vtklibxml2_xmlTextWriterEndComment
@@ -1216,8 +1132,6 @@
 #define xmlThrDefSetStructuredErrorFunc vtklibxml2_xmlThrDefSetStructuredErrorFunc
 #define xmlThrDefSubstituteEntitiesDefaultValue vtklibxml2_xmlThrDefSubstituteEntitiesDefaultValue
 #define xmlThrDefTreeIndentString vtklibxml2_xmlThrDefTreeIndentString
-#define __xmlTreeIndentString vtklibxml2___xmlTreeIndentString
-#define xmlTreeIndentString vtklibxml2_xmlTreeIndentString
 #define xmlUCSIsAegeanNumbers vtklibxml2_xmlUCSIsAegeanNumbers
 #define xmlUCSIsAlphabeticPresentationForms vtklibxml2_xmlUCSIsAlphabeticPresentationForms
 #define xmlUCSIsArabic vtklibxml2_xmlUCSIsArabic
@@ -1430,6 +1344,7 @@
 #define xmlValidGetValidElements vtklibxml2_xmlValidGetValidElements
 #define xmlValidNormalizeAttributeValue vtklibxml2_xmlValidNormalizeAttributeValue
 #define xmlXIncludeFreeContext vtklibxml2_xmlXIncludeFreeContext
+#define xmlXIncludeGetLastError vtklibxml2_xmlXIncludeGetLastError
 #define xmlXIncludeNewContext vtklibxml2_xmlXIncludeNewContext
 #define xmlXIncludeProcess vtklibxml2_xmlXIncludeProcess
 #define xmlXIncludeProcessFlags vtklibxml2_xmlXIncludeProcessFlags
@@ -1438,6 +1353,7 @@
 #define xmlXIncludeProcessTree vtklibxml2_xmlXIncludeProcessTree
 #define xmlXIncludeProcessTreeFlags vtklibxml2_xmlXIncludeProcessTreeFlags
 #define xmlXIncludeProcessTreeFlagsData vtklibxml2_xmlXIncludeProcessTreeFlagsData
+#define xmlXIncludeSetErrorHandler vtklibxml2_xmlXIncludeSetErrorHandler
 #define xmlXIncludeSetFlags vtklibxml2_xmlXIncludeSetFlags
 #define xmlXPathAddValues vtklibxml2_xmlXPathAddValues
 #define xmlXPathBooleanFunction vtklibxml2_xmlXPathBooleanFunction
@@ -1575,6 +1491,7 @@
 #define xmlXPathRoot vtklibxml2_xmlXPathRoot
 #define xmlXPathRoundFunction vtklibxml2_xmlXPathRoundFunction
 #define xmlXPathSetContextNode vtklibxml2_xmlXPathSetContextNode
+#define xmlXPathSetErrorHandler vtklibxml2_xmlXPathSetErrorHandler
 #define xmlXPathStartsWithFunction vtklibxml2_xmlXPathStartsWithFunction
 #define xmlXPathStringEvalNumber vtklibxml2_xmlXPathStringEvalNumber
 #define xmlXPathStringFunction vtklibxml2_xmlXPathStringFunction
@@ -1595,27 +1512,7 @@
 #define xmlXPathWrapExternal vtklibxml2_xmlXPathWrapExternal
 #define xmlXPathWrapNodeSet vtklibxml2_xmlXPathWrapNodeSet
 #define xmlXPathWrapString vtklibxml2_xmlXPathWrapString
-#define xmlXPtrAdvanceNode vtklibxml2_xmlXPtrAdvanceNode
-#define xmlXPtrBuildNodeList vtklibxml2_xmlXPtrBuildNodeList
 #define xmlXPtrEval vtklibxml2_xmlXPtrEval
-#define xmlXPtrEvalRangePredicate vtklibxml2_xmlXPtrEvalRangePredicate
-#define xmlXPtrFreeLocationSet vtklibxml2_xmlXPtrFreeLocationSet
-#define xmlXPtrLocationSetAdd vtklibxml2_xmlXPtrLocationSetAdd
-#define xmlXPtrLocationSetCreate vtklibxml2_xmlXPtrLocationSetCreate
-#define xmlXPtrLocationSetDel vtklibxml2_xmlXPtrLocationSetDel
-#define xmlXPtrLocationSetMerge vtklibxml2_xmlXPtrLocationSetMerge
-#define xmlXPtrLocationSetRemove vtklibxml2_xmlXPtrLocationSetRemove
-#define xmlXPtrNewCollapsedRange vtklibxml2_xmlXPtrNewCollapsedRange
 #define xmlXPtrNewContext vtklibxml2_xmlXPtrNewContext
-#define xmlXPtrNewLocationSetNodes vtklibxml2_xmlXPtrNewLocationSetNodes
-#define xmlXPtrNewLocationSetNodeSet vtklibxml2_xmlXPtrNewLocationSetNodeSet
-#define xmlXPtrNewRange vtklibxml2_xmlXPtrNewRange
-#define xmlXPtrNewRangeNodeObject vtklibxml2_xmlXPtrNewRangeNodeObject
-#define xmlXPtrNewRangeNodePoint vtklibxml2_xmlXPtrNewRangeNodePoint
-#define xmlXPtrNewRangeNodes vtklibxml2_xmlXPtrNewRangeNodes
-#define xmlXPtrNewRangePointNode vtklibxml2_xmlXPtrNewRangePointNode
-#define xmlXPtrNewRangePoints vtklibxml2_xmlXPtrNewRangePoints
-#define xmlXPtrRangeToFunction vtklibxml2_xmlXPtrRangeToFunction
-#define xmlXPtrWrapLocationSet vtklibxml2_xmlXPtrWrapLocationSet
 
 #endif
diff --git a/include/libxml/xinclude.h b/include/libxml/xinclude.h
index 863ab25ad9feeadf61be4c1fc761a8e396fc0644..71fa4c20dc2507242b50415f854c0362f913734c 100644
--- a/include/libxml/xinclude.h
+++ b/include/libxml/xinclude.h
@@ -14,6 +14,7 @@
 #define __XML_XINCLUDE_H__
 
 #include <libxml/xmlversion.h>
+#include <libxml/xmlerror.h>
 #include <libxml/tree.h>
 
 #ifdef LIBXML_XINCLUDE_ENABLED
@@ -89,35 +90,41 @@ typedef xmlXIncludeCtxt *xmlXIncludeCtxtPtr;
 /*
  * standalone processing
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXIncludeProcess	(xmlDocPtr doc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXIncludeProcessFlags	(xmlDocPtr doc,
 					 int flags);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXIncludeProcessFlagsData(xmlDocPtr doc,
 					 int flags,
 					 void *data);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                 xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree,
                                          int flags,
                                          void *data);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXIncludeProcessTree	(xmlNodePtr tree);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXIncludeProcessTreeFlags(xmlNodePtr tree,
 					 int flags);
 /*
  * contextual processing
  */
-XMLPUBFUN xmlXIncludeCtxtPtr XMLCALL
+XMLPUBFUN xmlXIncludeCtxtPtr
 		xmlXIncludeNewContext	(xmlDocPtr doc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXIncludeSetFlags	(xmlXIncludeCtxtPtr ctxt,
 					 int flags);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
+		xmlXIncludeSetErrorHandler(xmlXIncludeCtxtPtr ctxt,
+					 xmlStructuredErrorFunc handler,
+					 void *data);
+XMLPUBFUN int
+		xmlXIncludeGetLastError	(xmlXIncludeCtxtPtr ctxt);
+XMLPUBFUN void
 		xmlXIncludeFreeContext	(xmlXIncludeCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXIncludeProcessNode	(xmlXIncludeCtxtPtr ctxt,
 					 xmlNodePtr tree);
 #ifdef __cplusplus
diff --git a/include/libxml/xlink.h b/include/libxml/xlink.h
index 04e4b32c015f6fc5f52f3c62b7e3d7cc9f386849..106573666ae462f2b4c1dafe86b39b1afb84530e 100644
--- a/include/libxml/xlink.h
+++ b/include/libxml/xlink.h
@@ -160,23 +160,23 @@ struct _xlinkHandler {
  * detection callbacks.
  */
 
-XMLPUBFUN xlinkNodeDetectFunc XMLCALL
+XMLPUBFUN xlinkNodeDetectFunc
 		xlinkGetDefaultDetect	(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xlinkSetDefaultDetect	(xlinkNodeDetectFunc func);
 
 /*
  * Routines to set/get the default handlers.
  */
-XMLPUBFUN xlinkHandlerPtr XMLCALL
+XMLPUBFUN xlinkHandlerPtr
 		xlinkGetDefaultHandler	(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xlinkSetDefaultHandler	(xlinkHandlerPtr handler);
 
 /*
  * Link detection module itself.
  */
-XMLPUBFUN xlinkType XMLCALL
+XMLPUBFUN xlinkType
 		xlinkIsLink		(xmlDocPtr doc,
 					 xmlNodePtr node);
 
diff --git a/include/libxml/xmlIO.h b/include/libxml/xmlIO.h
index 095b2f56d96c0ca448bb5f988e68959c021e808d..7810e42a86e41321a10493a4a295c8c28b720cae 100644
--- a/include/libxml/xmlIO.h
+++ b/include/libxml/xmlIO.h
@@ -10,8 +10,14 @@
 #ifndef __XML_IO_H__
 #define __XML_IO_H__
 
+/** DOC_DISABLE */
 #include <stdio.h>
 #include <libxml/xmlversion.h>
+#include <libxml/encoding.h>
+#define XML_TREE_INTERNALS
+#include <libxml/tree.h>
+#undef XML_TREE_INTERNALS
+/** DOC_ENABLE */
 
 #ifdef __cplusplus
 extern "C" {
@@ -31,7 +37,7 @@ extern "C" {
  *
  * Returns 1 if yes and 0 if another Input module should be used
  */
-typedef int (XMLCALL *xmlInputMatchCallback) (char const *filename);
+typedef int (*xmlInputMatchCallback) (char const *filename);
 /**
  * xmlInputOpenCallback:
  * @filename: the filename or URI
@@ -40,7 +46,7 @@ typedef int (XMLCALL *xmlInputMatchCallback) (char const *filename);
  *
  * Returns an Input context or NULL in case or error
  */
-typedef void * (XMLCALL *xmlInputOpenCallback) (char const *filename);
+typedef void * (*xmlInputOpenCallback) (char const *filename);
 /**
  * xmlInputReadCallback:
  * @context:  an Input context
@@ -51,7 +57,7 @@ typedef void * (XMLCALL *xmlInputOpenCallback) (char const *filename);
  *
  * Returns the number of bytes read or -1 in case of error
  */
-typedef int (XMLCALL *xmlInputReadCallback) (void * context, char * buffer, int len);
+typedef int (*xmlInputReadCallback) (void * context, char * buffer, int len);
 /**
  * xmlInputCloseCallback:
  * @context:  an Input context
@@ -60,7 +66,7 @@ typedef int (XMLCALL *xmlInputReadCallback) (void * context, char * buffer, int
  *
  * Returns 0 or -1 in case of error
  */
-typedef int (XMLCALL *xmlInputCloseCallback) (void * context);
+typedef int (*xmlInputCloseCallback) (void * context);
 
 #ifdef LIBXML_OUTPUT_ENABLED
 /*
@@ -77,7 +83,7 @@ typedef int (XMLCALL *xmlInputCloseCallback) (void * context);
  *
  * Returns 1 if yes and 0 if another Output module should be used
  */
-typedef int (XMLCALL *xmlOutputMatchCallback) (char const *filename);
+typedef int (*xmlOutputMatchCallback) (char const *filename);
 /**
  * xmlOutputOpenCallback:
  * @filename: the filename or URI
@@ -86,7 +92,7 @@ typedef int (XMLCALL *xmlOutputMatchCallback) (char const *filename);
  *
  * Returns an Output context or NULL in case or error
  */
-typedef void * (XMLCALL *xmlOutputOpenCallback) (char const *filename);
+typedef void * (*xmlOutputOpenCallback) (char const *filename);
 /**
  * xmlOutputWriteCallback:
  * @context:  an Output context
@@ -97,7 +103,7 @@ typedef void * (XMLCALL *xmlOutputOpenCallback) (char const *filename);
  *
  * Returns the number of bytes written or -1 in case of error
  */
-typedef int (XMLCALL *xmlOutputWriteCallback) (void * context, const char * buffer,
+typedef int (*xmlOutputWriteCallback) (void * context, const char * buffer,
                                        int len);
 /**
  * xmlOutputCloseCallback:
@@ -107,21 +113,38 @@ typedef int (XMLCALL *xmlOutputWriteCallback) (void * context, const char * buff
  *
  * Returns 0 or -1 in case of error
  */
-typedef int (XMLCALL *xmlOutputCloseCallback) (void * context);
+typedef int (*xmlOutputCloseCallback) (void * context);
 #endif /* LIBXML_OUTPUT_ENABLED */
 
-#ifdef __cplusplus
-}
-#endif
+/**
+ * xmlParserInputBufferCreateFilenameFunc:
+ * @URI: the URI to read from
+ * @enc: the requested source encoding
+ *
+ * Signature for the function doing the lookup for a suitable input method
+ * corresponding to an URI.
+ *
+ * Returns the new xmlParserInputBufferPtr in case of success or NULL if no
+ *         method was found.
+ */
+typedef xmlParserInputBufferPtr
+(*xmlParserInputBufferCreateFilenameFunc)(const char *URI, xmlCharEncoding enc);
 
-#include <libxml/globals.h>
-#include <libxml/tree.h>
-#include <libxml/parser.h>
-#include <libxml/encoding.h>
+/**
+ * xmlOutputBufferCreateFilenameFunc:
+ * @URI: the URI to write to
+ * @enc: the requested target encoding
+ *
+ * Signature for the function doing the lookup for a suitable output method
+ * corresponding to an URI.
+ *
+ * Returns the new xmlOutputBufferPtr in case of success or NULL if no
+ *         method was found.
+ */
+typedef xmlOutputBufferPtr
+(*xmlOutputBufferCreateFilenameFunc)(const char *URI,
+        xmlCharEncodingHandlerPtr encoder, int compression);
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 struct _xmlParserInputBuffer {
     void*                  context;
     xmlInputReadCallback   readcallback;
@@ -152,56 +175,78 @@ struct _xmlOutputBuffer {
 };
 #endif /* LIBXML_OUTPUT_ENABLED */
 
+/** DOC_DISABLE */
+#define XML_GLOBALS_IO \
+  XML_OP(xmlParserInputBufferCreateFilenameValue, \
+           xmlParserInputBufferCreateFilenameFunc, XML_DEPRECATED) \
+  XML_OP(xmlOutputBufferCreateFilenameValue, \
+           xmlOutputBufferCreateFilenameFunc, XML_DEPRECATED)
+
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_IO
+#undef XML_OP
+
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+  #define xmlParserInputBufferCreateFilenameValue \
+    XML_GLOBAL_MACRO(xmlParserInputBufferCreateFilenameValue)
+  #define xmlOutputBufferCreateFilenameValue \
+    XML_GLOBAL_MACRO(xmlOutputBufferCreateFilenameValue)
+#else
+#define xmlParserInputBufferCreateFilenameValue vtklibxml2_xmlParserInputBufferCreateFilenameValue
+#define xmlOutputBufferCreateFilenameValue vtklibxml2_xmlOutputBufferCreateFilenameValue
+#endif
+/** DOC_ENABLE */
+
 /*
  * Interfaces for input
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlCleanupInputCallbacks		(void);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlPopInputCallbacks			(void);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlRegisterDefaultInputCallbacks	(void);
-XMLPUBFUN xmlParserInputBufferPtr XMLCALL
+XMLPUBFUN xmlParserInputBufferPtr
 	xmlAllocParserInputBuffer		(xmlCharEncoding enc);
 
-XMLPUBFUN xmlParserInputBufferPtr XMLCALL
+XMLPUBFUN xmlParserInputBufferPtr
 	xmlParserInputBufferCreateFilename	(const char *URI,
                                                  xmlCharEncoding enc);
-XMLPUBFUN xmlParserInputBufferPtr XMLCALL
+XMLPUBFUN xmlParserInputBufferPtr
 	xmlParserInputBufferCreateFile		(FILE *file,
                                                  xmlCharEncoding enc);
-XMLPUBFUN xmlParserInputBufferPtr XMLCALL
+XMLPUBFUN xmlParserInputBufferPtr
 	xmlParserInputBufferCreateFd		(int fd,
 	                                         xmlCharEncoding enc);
-XMLPUBFUN xmlParserInputBufferPtr XMLCALL
+XMLPUBFUN xmlParserInputBufferPtr
 	xmlParserInputBufferCreateMem		(const char *mem, int size,
 	                                         xmlCharEncoding enc);
-XMLPUBFUN xmlParserInputBufferPtr XMLCALL
+XMLPUBFUN xmlParserInputBufferPtr
 	xmlParserInputBufferCreateStatic	(const char *mem, int size,
 	                                         xmlCharEncoding enc);
-XMLPUBFUN xmlParserInputBufferPtr XMLCALL
+XMLPUBFUN xmlParserInputBufferPtr
 	xmlParserInputBufferCreateIO		(xmlInputReadCallback   ioread,
 						 xmlInputCloseCallback  ioclose,
 						 void *ioctx,
 	                                         xmlCharEncoding enc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlParserInputBufferRead		(xmlParserInputBufferPtr in,
 						 int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlParserInputBufferGrow		(xmlParserInputBufferPtr in,
 						 int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlParserInputBufferPush		(xmlParserInputBufferPtr in,
 						 int len,
 						 const char *buf);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlFreeParserInputBuffer		(xmlParserInputBufferPtr in);
-XMLPUBFUN char * XMLCALL
+XMLPUBFUN char *
 	xmlParserGetDirectory			(const char *filename);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlRegisterInputCallbacks		(xmlInputMatchCallback matchFunc,
 						 xmlInputOpenCallback openFunc,
 						 xmlInputReadCallback readFunc,
@@ -215,62 +260,62 @@ xmlParserInputBufferPtr
 /*
  * Interfaces for output
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlCleanupOutputCallbacks		(void);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlPopOutputCallbacks			(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlRegisterDefaultOutputCallbacks(void);
-XMLPUBFUN xmlOutputBufferPtr XMLCALL
+XMLPUBFUN xmlOutputBufferPtr
 	xmlAllocOutputBuffer		(xmlCharEncodingHandlerPtr encoder);
 
-XMLPUBFUN xmlOutputBufferPtr XMLCALL
+XMLPUBFUN xmlOutputBufferPtr
 	xmlOutputBufferCreateFilename	(const char *URI,
 					 xmlCharEncodingHandlerPtr encoder,
 					 int compression);
 
-XMLPUBFUN xmlOutputBufferPtr XMLCALL
+XMLPUBFUN xmlOutputBufferPtr
 	xmlOutputBufferCreateFile	(FILE *file,
 					 xmlCharEncodingHandlerPtr encoder);
 
-XMLPUBFUN xmlOutputBufferPtr XMLCALL
+XMLPUBFUN xmlOutputBufferPtr
 	xmlOutputBufferCreateBuffer	(xmlBufferPtr buffer,
 					 xmlCharEncodingHandlerPtr encoder);
 
-XMLPUBFUN xmlOutputBufferPtr XMLCALL
+XMLPUBFUN xmlOutputBufferPtr
 	xmlOutputBufferCreateFd		(int fd,
 					 xmlCharEncodingHandlerPtr encoder);
 
-XMLPUBFUN xmlOutputBufferPtr XMLCALL
+XMLPUBFUN xmlOutputBufferPtr
 	xmlOutputBufferCreateIO		(xmlOutputWriteCallback   iowrite,
 					 xmlOutputCloseCallback  ioclose,
 					 void *ioctx,
 					 xmlCharEncodingHandlerPtr encoder);
 
 /* Couple of APIs to get the output without digging into the buffers */
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
         xmlOutputBufferGetContent       (xmlOutputBufferPtr out);
-XMLPUBFUN size_t XMLCALL
+XMLPUBFUN size_t
         xmlOutputBufferGetSize          (xmlOutputBufferPtr out);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlOutputBufferWrite		(xmlOutputBufferPtr out,
 					 int len,
 					 const char *buf);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlOutputBufferWriteString	(xmlOutputBufferPtr out,
 					 const char *str);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlOutputBufferWriteEscape	(xmlOutputBufferPtr out,
 					 const xmlChar *str,
 					 xmlCharEncodingOutputFunc escaping);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlOutputBufferFlush		(xmlOutputBufferPtr out);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlOutputBufferClose		(xmlOutputBufferPtr out);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlRegisterOutputCallbacks	(xmlOutputMatchCallback matchFunc,
 					 xmlOutputOpenCallback openFunc,
 					 xmlOutputWriteCallback writeFunc,
@@ -283,83 +328,111 @@ xmlOutputBufferPtr
 
 #ifdef LIBXML_HTTP_ENABLED
 /*  This function only exists if HTTP support built into the library  */
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 	xmlRegisterHTTPPostCallbacks	(void );
 #endif /* LIBXML_HTTP_ENABLED */
 
 #endif /* LIBXML_OUTPUT_ENABLED */
 
-XMLPUBFUN xmlParserInputPtr XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlParserInputPtr
 	xmlCheckHTTPInput		(xmlParserCtxtPtr ctxt,
 					 xmlParserInputPtr ret);
 
 /*
  * A predefined entity loader disabling network accesses
  */
-XMLPUBFUN xmlParserInputPtr XMLCALL
+XMLPUBFUN xmlParserInputPtr
 	xmlNoNetExternalEntityLoader	(const char *URL,
 					 const char *ID,
 					 xmlParserCtxtPtr ctxt);
 
-/*
- * xmlNormalizeWindowsPath is obsolete, don't use it.
- * Check xmlCanonicPath in uri.h for a better alternative.
- */
-XMLPUBFUN xmlChar * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN xmlChar *
 	xmlNormalizeWindowsPath		(const xmlChar *path);
 
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlCheckFilename		(const char *path);
 /**
  * Default 'file://' protocol callbacks
  */
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlFileMatch			(const char *filename);
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlFileOpen			(const char *filename);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlFileRead			(void * context,
 					 char * buffer,
 					 int len);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlFileClose			(void * context);
 
 /**
  * Default 'http://' protocol callbacks
  */
 #ifdef LIBXML_HTTP_ENABLED
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlIOHTTPMatch			(const char *filename);
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlIOHTTPOpen			(const char *filename);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlIOHTTPOpenW			(const char * post_uri,
 					 int   compression );
 #endif /* LIBXML_OUTPUT_ENABLED */
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlIOHTTPRead			(void * context,
 					 char * buffer,
 					 int len);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlIOHTTPClose			(void * context);
 #endif /* LIBXML_HTTP_ENABLED */
 
 /**
  * Default 'ftp://' protocol callbacks
  */
-#ifdef LIBXML_FTP_ENABLED
-XMLPUBFUN int XMLCALL
+#if defined(LIBXML_FTP_ENABLED)
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlIOFTPMatch			(const char *filename);
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlIOFTPOpen			(const char *filename);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlIOFTPRead			(void * context,
 					 char * buffer,
 					 int len);
-XMLPUBFUN int XMLCALL
+XML_DEPRECATED
+XMLPUBFUN int
 	xmlIOFTPClose			(void * context);
-#endif /* LIBXML_FTP_ENABLED */
+#endif /* defined(LIBXML_FTP_ENABLED) */
+
+XMLPUBFUN xmlParserInputBufferCreateFilenameFunc
+	xmlParserInputBufferCreateFilenameDefault(
+		xmlParserInputBufferCreateFilenameFunc func);
+XMLPUBFUN xmlOutputBufferCreateFilenameFunc
+	xmlOutputBufferCreateFilenameDefault(
+		xmlOutputBufferCreateFilenameFunc func);
+XML_DEPRECATED
+XMLPUBFUN xmlOutputBufferCreateFilenameFunc
+	xmlThrDefOutputBufferCreateFilenameDefault(
+		xmlOutputBufferCreateFilenameFunc func);
+XML_DEPRECATED
+XMLPUBFUN xmlParserInputBufferCreateFilenameFunc
+	xmlThrDefParserInputBufferCreateFilenameDefault(
+		xmlParserInputBufferCreateFilenameFunc func);
 
 #ifdef __cplusplus
 }
diff --git a/include/libxml/xmlautomata.h b/include/libxml/xmlautomata.h
index bf1b131c653427eff6989dfd8e57698411787da6..ea38eb37f09fe43a34d0d3f6fedbb8313d9b839f 100644
--- a/include/libxml/xmlautomata.h
+++ b/include/libxml/xmlautomata.h
@@ -11,11 +11,11 @@
 #define __XML_AUTOMATA_H__
 
 #include <libxml/xmlversion.h>
-#include <libxml/tree.h>
 
 #ifdef LIBXML_REGEXP_ENABLED
 #ifdef LIBXML_AUTOMATA_ENABLED
-#include <libxml/xmlregexp.h>
+
+#include <libxml/xmlstring.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -40,32 +40,32 @@ typedef xmlAutomataState *xmlAutomataStatePtr;
 /*
  * Building API
  */
-XMLPUBFUN xmlAutomataPtr XMLCALL
+XMLPUBFUN xmlAutomataPtr
 		    xmlNewAutomata		(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlFreeAutomata		(xmlAutomataPtr am);
 
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataGetInitState	(xmlAutomataPtr am);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlAutomataSetFinalState	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr state);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewState		(xmlAutomataPtr am);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewTransition	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to,
 						 const xmlChar *token,
 						 void *data);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewTransition2	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to,
 						 const xmlChar *token,
 						 const xmlChar *token2,
 						 void *data);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
                     xmlAutomataNewNegTrans	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to,
@@ -73,7 +73,7 @@ XMLPUBFUN xmlAutomataStatePtr XMLCALL
 						 const xmlChar *token2,
 						 void *data);
 
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewCountTrans	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to,
@@ -81,7 +81,7 @@ XMLPUBFUN xmlAutomataStatePtr XMLCALL
 						 int min,
 						 int max,
 						 void *data);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewCountTrans2	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to,
@@ -90,7 +90,7 @@ XMLPUBFUN xmlAutomataStatePtr XMLCALL
 						 int min,
 						 int max,
 						 void *data);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewOnceTrans	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to,
@@ -98,7 +98,7 @@ XMLPUBFUN xmlAutomataStatePtr XMLCALL
 						 int min,
 						 int max,
 						 void *data);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewOnceTrans2	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to,
@@ -107,33 +107,33 @@ XMLPUBFUN xmlAutomataStatePtr XMLCALL
 						 int min,
 						 int max,
 						 void *data);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewAllTrans	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to,
 						 int lax);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewEpsilon	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewCountedTrans	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to,
 						 int counter);
-XMLPUBFUN xmlAutomataStatePtr XMLCALL
+XMLPUBFUN xmlAutomataStatePtr
 		    xmlAutomataNewCounterTrans	(xmlAutomataPtr am,
 						 xmlAutomataStatePtr from,
 						 xmlAutomataStatePtr to,
 						 int counter);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlAutomataNewCounter	(xmlAutomataPtr am,
 						 int min,
 						 int max);
 
-XMLPUBFUN xmlRegexpPtr XMLCALL
+XMLPUBFUN struct _xmlRegexp *
 		    xmlAutomataCompile		(xmlAutomataPtr am);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlAutomataIsDeterminist	(xmlAutomataPtr am);
 
 #ifdef __cplusplus
diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h
index ee95be9c9c21cf1dca42a7ae319196c1cd93034c..bd075b89c8118b4e74bddd011bbcd18143a135f4 100644
--- a/include/libxml/xmlerror.h
+++ b/include/libxml/xmlerror.h
@@ -7,11 +7,11 @@
  * Author: Daniel Veillard
  */
 
-#include <libxml/parser.h>
-
 #ifndef __XML_ERROR_H__
 #define __XML_ERROR_H__
 
+#include <libxml/xmlversion.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -210,6 +210,12 @@ typedef enum {
     XML_ERR_NAME_TOO_LONG, /* 110 */
     XML_ERR_USER_STOP, /* 111 */
     XML_ERR_COMMENT_ABRUPTLY_ENDED, /* 112 */
+    XML_WAR_ENCODING_MISMATCH, /* 113 */
+    XML_ERR_RESOURCE_LIMIT, /* 114 */
+    XML_ERR_ARGUMENT, /* 115 */
+    XML_ERR_SYSTEM, /* 116 */
+    XML_ERR_REDECL_PREDEF_ENTITY, /* 117 */
+    XML_ERR_INT_SUBSET_NOT_FINISHED, /* 118 */
     XML_NS_ERR_XML_NAMESPACE = 200,
     XML_NS_ERR_UNDEFINED_NAMESPACE, /* 201 */
     XML_NS_ERR_QNAME, /* 202 */
@@ -472,6 +478,7 @@ typedef enum {
     XML_IO_EADDRINUSE, /* 1554 */
     XML_IO_EALREADY, /* 1555 */
     XML_IO_EAFNOSUPPORT, /* 1556 */
+    XML_IO_UNSUPPORTED_PROTOCOL, /* 1557 */
     XML_XINCLUDE_RECURSION=1600,
     XML_XINCLUDE_PARSE_VALUE, /* 1601 */
     XML_XINCLUDE_ENTITY_DEF_MISMATCH, /* 1602 */
@@ -844,7 +851,7 @@ typedef enum {
  * Signature of the function to use when there is an error and
  * no parsing or validity context available .
  */
-typedef void (XMLCDECL *xmlGenericErrorFunc) (void *ctx,
+typedef void (*xmlGenericErrorFunc) (void *ctx,
 				 const char *msg,
 				 ...) LIBXML_ATTR_FORMAT(2,3);
 /**
@@ -855,92 +862,106 @@ typedef void (XMLCDECL *xmlGenericErrorFunc) (void *ctx,
  * Signature of the function to use when there is an error and
  * the module handles the new error reporting mechanism.
  */
-typedef void (XMLCALL *xmlStructuredErrorFunc) (void *userData, xmlErrorPtr error);
+typedef void (*xmlStructuredErrorFunc) (void *userData, const xmlError *error);
+
+/** DOC_DISABLE */
+#define XML_GLOBALS_ERROR \
+  XML_OP(xmlLastError, xmlError, XML_DEPRECATED) \
+  XML_OP(xmlGenericError, xmlGenericErrorFunc, XML_NO_ATTR) \
+  XML_OP(xmlGenericErrorContext, void *, XML_NO_ATTR) \
+  XML_OP(xmlStructuredError, xmlStructuredErrorFunc, XML_NO_ATTR) \
+  XML_OP(xmlStructuredErrorContext, void *, XML_NO_ATTR)
+
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_ERROR
+#undef XML_OP
+
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+  #define xmlLastError XML_GLOBAL_MACRO(xmlLastError)
+  #define xmlGenericError XML_GLOBAL_MACRO(xmlGenericError)
+  #define xmlGenericErrorContext XML_GLOBAL_MACRO(xmlGenericErrorContext)
+  #define xmlStructuredError XML_GLOBAL_MACRO(xmlStructuredError)
+  #define xmlStructuredErrorContext XML_GLOBAL_MACRO(xmlStructuredErrorContext)
+#else
+#define xmlLastError vtklibxml2_xmlLastError
+#define xmlGenericError vtklibxml2_xmlGenericError
+#define xmlGenericErrorContext vtklibxml2_xmlGenericErrorContext
+#define xmlStructuredError vtklibxml2_xmlStructuredError
+#define xmlStructuredErrorContext vtklibxml2_xmlStructuredErrorContext
+#endif
+/** DOC_ENABLE */
 
 /*
  * Use the following function to reset the two global variables
  * xmlGenericError and xmlGenericErrorContext.
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
     xmlSetGenericErrorFunc	(void *ctx,
 				 xmlGenericErrorFunc handler);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
+    xmlThrDefSetGenericErrorFunc(void *ctx,
+                                 xmlGenericErrorFunc handler);
+XML_DEPRECATED
+XMLPUBFUN void
     initGenericErrorDefaultFunc	(xmlGenericErrorFunc *handler);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
     xmlSetStructuredErrorFunc	(void *ctx,
 				 xmlStructuredErrorFunc handler);
+XML_DEPRECATED
+XMLPUBFUN void
+    xmlThrDefSetStructuredErrorFunc(void *ctx,
+                                 xmlStructuredErrorFunc handler);
 /*
  * Default message routines used by SAX and Valid context for error
  * and warning reporting.
  */
-XMLPUBFUN void XMLCDECL
+XMLPUBFUN void
     xmlParserError		(void *ctx,
 				 const char *msg,
 				 ...) LIBXML_ATTR_FORMAT(2,3);
-XMLPUBFUN void XMLCDECL
+XMLPUBFUN void
     xmlParserWarning		(void *ctx,
 				 const char *msg,
 				 ...) LIBXML_ATTR_FORMAT(2,3);
-XMLPUBFUN void XMLCDECL
+XMLPUBFUN void
     xmlParserValidityError	(void *ctx,
 				 const char *msg,
 				 ...) LIBXML_ATTR_FORMAT(2,3);
-XMLPUBFUN void XMLCDECL
+XMLPUBFUN void
     xmlParserValidityWarning	(void *ctx,
 				 const char *msg,
 				 ...) LIBXML_ATTR_FORMAT(2,3);
-XMLPUBFUN void XMLCALL
-    xmlParserPrintFileInfo	(xmlParserInputPtr input);
-XMLPUBFUN void XMLCALL
-    xmlParserPrintFileContext	(xmlParserInputPtr input);
+/** DOC_DISABLE */
+struct _xmlParserInput;
+/** DOC_ENABLE */
+XMLPUBFUN void
+    xmlParserPrintFileInfo	(struct _xmlParserInput *input);
+XMLPUBFUN void
+    xmlParserPrintFileContext	(struct _xmlParserInput *input);
+XMLPUBFUN void
+xmlFormatError			(const xmlError *err,
+				 xmlGenericErrorFunc channel,
+				 void *data);
 
 /*
  * Extended error information routines
  */
-XMLPUBFUN xmlErrorPtr XMLCALL
+XMLPUBFUN const xmlError *
     xmlGetLastError		(void);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
     xmlResetLastError		(void);
-XMLPUBFUN xmlErrorPtr XMLCALL
+XMLPUBFUN const xmlError *
     xmlCtxtGetLastError		(void *ctx);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
     xmlCtxtResetLastError	(void *ctx);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
     xmlResetError		(xmlErrorPtr err);
-XMLPUBFUN int XMLCALL
-    xmlCopyError		(xmlErrorPtr from,
+XMLPUBFUN int
+    xmlCopyError		(const xmlError *from,
 				 xmlErrorPtr to);
 
-#ifdef IN_LIBXML
-/*
- * Internal callback reporting routine
- */
-XMLPUBFUN void XMLCALL
-    __xmlRaiseError		(xmlStructuredErrorFunc schannel,
-				 xmlGenericErrorFunc channel,
-				 void *data,
-                                 void *ctx,
-				 void *node,
-				 int domain,
-				 int code,
-				 xmlErrorLevel level,
-				 const char *file,
-				 int line,
-				 const char *str1,
-				 const char *str2,
-				 const char *str3,
-				 int int1,
-				 int col,
-				 const char *msg,
-				 ...) LIBXML_ATTR_FORMAT(16,17);
-XMLPUBFUN void XMLCALL
-    __xmlSimpleError		(int domain,
-				 int code,
-				 xmlNodePtr node,
-				 const char *msg,
-				 const char *extra) LIBXML_ATTR_FORMAT(4,0);
-#endif
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/libxml/xmlexports.h b/include/libxml/xmlexports.h
index 8831c54029e5399f7f948509b4354237aa6e7706..cc121f2f6ea2db61841a3e5dac0e8bda1348fb25 100644
--- a/include/libxml/xmlexports.h
+++ b/include/libxml/xmlexports.h
@@ -10,68 +10,137 @@
 
 #include "vtk_libxml2_mangle.h"
 
-#if defined(_WIN32) || defined(__CYGWIN__)
 /** DOC_DISABLE */
 
-#ifdef LIBXML_STATIC
+/*
+ * Symbol visibility
+ */
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+  #ifdef LIBXML_STATIC
+    #define XMLPUBLIC
+  #elif defined(IN_LIBXML)
+    #define XMLPUBLIC __declspec(dllexport)
+  #else
+    #define XMLPUBLIC __declspec(dllimport)
+  #endif
+#else /* not Windows */
   #define XMLPUBLIC
-#elif defined(IN_LIBXML)
-  #define XMLPUBLIC __declspec(dllexport)
+#endif /* platform switch */
+
+#define XMLPUBFUN XMLPUBLIC
+
+#define XMLPUBVAR XMLPUBLIC extern
+
+/* Compatibility */
+#define XMLCALL
+#define XMLCDECL
+#ifndef LIBXML_DLL_IMPORT
+  #define LIBXML_DLL_IMPORT XMLPUBVAR
+#endif
+
+/*
+ * Attributes
+ */
+
+#ifndef ATTRIBUTE_UNUSED
+  #if __GNUC__ * 100 + __GNUC_MINOR__ >= 207 || defined(__clang__)
+    #define ATTRIBUTE_UNUSED __attribute__((unused))
+  #else
+    #define ATTRIBUTE_UNUSED
+  #endif
+#endif
+
+#if !defined(__clang__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
+  #define LIBXML_ATTR_ALLOC_SIZE(x) __attribute__((alloc_size(x)))
 #else
-  #define XMLPUBLIC __declspec(dllimport)
+  #define LIBXML_ATTR_ALLOC_SIZE(x)
 #endif
 
-#if defined(LIBXML_FASTCALL)
-  #define XMLCALL __fastcall
+#if __GNUC__ * 100 + __GNUC_MINOR__ >= 303
+  #define LIBXML_ATTR_FORMAT(fmt,args) \
+    __attribute__((__format__(__printf__,fmt,args)))
 #else
-  #define XMLCALL __cdecl
+  #define LIBXML_ATTR_FORMAT(fmt,args)
 #endif
-#define XMLCDECL __cdecl
 
-/** DOC_ENABLE */
-#else /* not Windows */
+#ifndef XML_DEPRECATED
+  #if defined(IN_LIBXML)
+    #define XML_DEPRECATED
+  #elif __GNUC__ * 100 + __GNUC_MINOR__ >= 301
+    #define XML_DEPRECATED __attribute__((deprecated))
+  #elif defined(_MSC_VER) && _MSC_VER >= 1400
+    /* Available since Visual Studio 2005 */
+    #define XML_DEPRECATED __declspec(deprecated)
+  #else
+    #define XML_DEPRECATED
+  #endif
+#endif
 
-/**
- * XMLPUBLIC:
- *
- * Macro which declares a public symbol
+/*
+ * Warnings pragmas, should be moved from public headers
  */
-#define XMLPUBLIC
 
-/**
- * XMLCALL:
- *
- * Macro which declares the calling convention for exported functions
- */
-#define XMLCALL
+#if defined(__LCC__)
 
-/**
- * XMLCDECL:
- *
- * Macro which declares the calling convention for exported functions that
- * use '...'.
- */
-#define XMLCDECL
+  #define XML_IGNORE_FPTR_CAST_WARNINGS
+  #define XML_POP_WARNINGS \
+    _Pragma("diag_default 1215")
 
-#endif /* platform switch */
+#elif defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)
+
+  #if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 800)
+    #define XML_IGNORE_FPTR_CAST_WARNINGS \
+      _Pragma("GCC diagnostic push") \
+      _Pragma("GCC diagnostic ignored \"-Wpedantic\"") \
+      _Pragma("GCC diagnostic ignored \"-Wcast-function-type\"")
+  #else
+    #define XML_IGNORE_FPTR_CAST_WARNINGS \
+      _Pragma("GCC diagnostic push") \
+      _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
+  #endif
+  #define XML_POP_WARNINGS \
+    _Pragma("GCC diagnostic pop")
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+
+  #define XML_IGNORE_FPTR_CAST_WARNINGS __pragma(warning(push))
+  #define XML_POP_WARNINGS __pragma(warning(pop))
+
+#else
+
+  #define XML_IGNORE_FPTR_CAST_WARNINGS
+  #define XML_POP_WARNINGS
+
+#endif
 
 /*
- * XMLPUBFUN:
- *
- * Macro which declares an exportable function
+ * Accessors for globals
  */
-#define XMLPUBFUN XMLPUBLIC
 
-/**
- * XMLPUBVAR:
- *
- * Macro which declares an exportable variable
+#define XML_NO_ATTR
+
+#ifdef LIBXML_THREAD_ENABLED
+  #define XML_DECLARE_GLOBAL(name, type, attrs) \
+    attrs XMLPUBFUN type *__vtklibxml2_##name(void);
+  #define XML_GLOBAL_MACRO(name) (*__vtklibxml2_##name())
+#else
+  #define XML_DECLARE_GLOBAL(name, type, attrs) \
+    attrs XMLPUBVAR type vtklibxml2_##name;
+#endif
+
+/*
+ * Originally declared in xmlversion.h which is generated
  */
-#define XMLPUBVAR XMLPUBLIC extern
 
-/* Compatibility */
-#if !defined(LIBXML_DLL_IMPORT)
-#define LIBXML_DLL_IMPORT XMLPUBVAR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+XMLPUBFUN void xmlCheckVersion(int version);
+
+#ifdef __cplusplus
+}
 #endif
 
 #endif /* __XML_EXPORTS_H__ */
diff --git a/include/libxml/xmlmemory.h b/include/libxml/xmlmemory.h
index ae2a4275a3b1ddfb432fc9e7ee62e8ebea594547..0743bf08173ac634aebf7068235949dffcbd4a99 100644
--- a/include/libxml/xmlmemory.h
+++ b/include/libxml/xmlmemory.h
@@ -15,32 +15,6 @@
 #include <stdio.h>
 #include <libxml/xmlversion.h>
 
-/**
- * DEBUG_MEMORY:
- *
- * DEBUG_MEMORY replaces the allocator with a collect and debug
- * shell to the libc allocator.
- * DEBUG_MEMORY should only be activated when debugging
- * libxml i.e. if libxml has been configured with --with-debug-mem too.
- */
-/* #define DEBUG_MEMORY_FREED */
-/* #define DEBUG_MEMORY_LOCATION */
-
-#ifdef DEBUG
-#ifndef DEBUG_MEMORY
-#define DEBUG_MEMORY
-#endif
-#endif
-
-/**
- * DEBUG_MEMORY_LOCATION:
- *
- * DEBUG_MEMORY_LOCATION should be activated only when debugging
- * libxml i.e. if libxml has been configured with --with-debug-mem too.
- */
-#ifdef DEBUG_MEMORY_LOCATION
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -54,7 +28,7 @@ extern "C" {
  *
  * Signature for a free() implementation.
  */
-typedef void (XMLCALL *xmlFreeFunc)(void *mem);
+typedef void (*xmlFreeFunc)(void *mem);
 /**
  * xmlMallocFunc:
  * @size:  the size requested in bytes
@@ -63,7 +37,7 @@ typedef void (XMLCALL *xmlFreeFunc)(void *mem);
  *
  * Returns a pointer to the newly allocated block or NULL in case of error.
  */
-typedef void *(LIBXML_ATTR_ALLOC_SIZE(1) XMLCALL *xmlMallocFunc)(size_t size);
+typedef void *(LIBXML_ATTR_ALLOC_SIZE(1) *xmlMallocFunc)(size_t size);
 
 /**
  * xmlReallocFunc:
@@ -74,7 +48,7 @@ typedef void *(LIBXML_ATTR_ALLOC_SIZE(1) XMLCALL *xmlMallocFunc)(size_t size);
  *
  * Returns a pointer to the newly reallocated block or NULL in case of error.
  */
-typedef void *(XMLCALL *xmlReallocFunc)(void *mem, size_t size);
+typedef void *(*xmlReallocFunc)(void *mem, size_t size);
 
 /**
  * xmlStrdupFunc:
@@ -84,39 +58,80 @@ typedef void *(XMLCALL *xmlReallocFunc)(void *mem, size_t size);
  *
  * Returns the copy of the string or NULL in case of error.
  */
-typedef char *(XMLCALL *xmlStrdupFunc)(const char *str);
+typedef char *(*xmlStrdupFunc)(const char *str);
 
 /*
- * The 4 interfaces used for all memory handling within libxml.
-LIBXML_DLL_IMPORT xmlFreeFunc xmlFree;
-LIBXML_DLL_IMPORT xmlMallocFunc xmlMalloc;
-LIBXML_DLL_IMPORT xmlMallocFunc xmlMallocAtomic;
-LIBXML_DLL_IMPORT xmlReallocFunc xmlRealloc;
-LIBXML_DLL_IMPORT xmlStrdupFunc xmlMemStrdup;
- */
+ * In general the memory allocation entry points are not kept
+ * thread specific but this can be overridden by LIBXML_THREAD_ALLOC_ENABLED
+ *    - xmlMalloc
+ *    - xmlMallocAtomic
+ *    - xmlRealloc
+ *    - xmlMemStrdup
+ *    - xmlFree
+ */
+/** DOC_DISABLE */
+#ifdef LIBXML_THREAD_ALLOC_ENABLED
+  #define XML_GLOBALS_ALLOC \
+    XML_OP(xmlMalloc, xmlMallocFunc, XML_NO_ATTR) \
+    XML_OP(xmlMallocAtomic, xmlMallocFunc, XML_NO_ATTR) \
+    XML_OP(xmlRealloc, xmlReallocFunc, XML_NO_ATTR) \
+    XML_OP(xmlFree, xmlFreeFunc, XML_NO_ATTR) \
+    XML_OP(xmlMemStrdup, xmlStrdupFunc, XML_NO_ATTR)
+  #define XML_OP XML_DECLARE_GLOBAL
+    XML_GLOBALS_ALLOC
+  #undef XML_OP
+  #if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+    #define xmlMalloc XML_GLOBAL_MACRO(xmlMalloc)
+    #define xmlMallocAtomic XML_GLOBAL_MACRO(xmlMallocAtomic)
+    #define xmlRealloc XML_GLOBAL_MACRO(xmlRealloc)
+    #define xmlFree XML_GLOBAL_MACRO(xmlFree)
+    #define xmlMemStrdup XML_GLOBAL_MACRO(xmlMemStrdup)
+  #else
+    #define xmlMalloc vtklibxml2_xmlMalloc
+    #define xmlMallocAtomic vtklibxml2_xmlMallocAtomic
+    #define xmlRealloc vtklibxml2_xmlRealloc
+    #define xmlFree vtklibxml2_xmlFree
+    #define xmlMemStrdup vtklibxml2_xmlMemStrdup
+  #endif
+#else
+  #define XML_GLOBALS_ALLOC
+
+  #define xmlMalloc vtklibxml2_xmlMalloc
+  #define xmlMallocAtomic vtklibxml2_xmlMallocAtomic
+  #define xmlRealloc vtklibxml2_xmlRealloc
+  #define xmlFree vtklibxml2_xmlFree
+  #define xmlMemStrdup vtklibxml2_xmlMemStrdup
+
+/** DOC_ENABLE */
+  XMLPUBVAR xmlMallocFunc xmlMalloc;
+  XMLPUBVAR xmlMallocFunc xmlMallocAtomic;
+  XMLPUBVAR xmlReallocFunc xmlRealloc;
+  XMLPUBVAR xmlFreeFunc xmlFree;
+  XMLPUBVAR xmlStrdupFunc xmlMemStrdup;
+#endif
 
 /*
  * The way to overload the existing functions.
  * The xmlGc function have an extra entry for atomic block
  * allocations useful for garbage collected memory allocators
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlMemSetup	(xmlFreeFunc freeFunc,
 			 xmlMallocFunc mallocFunc,
 			 xmlReallocFunc reallocFunc,
 			 xmlStrdupFunc strdupFunc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlMemGet	(xmlFreeFunc *freeFunc,
 			 xmlMallocFunc *mallocFunc,
 			 xmlReallocFunc *reallocFunc,
 			 xmlStrdupFunc *strdupFunc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlGcMemSetup	(xmlFreeFunc freeFunc,
 			 xmlMallocFunc mallocFunc,
 			 xmlMallocFunc mallocAtomicFunc,
 			 xmlReallocFunc reallocFunc,
 			 xmlStrdupFunc strdupFunc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlGcMemGet	(xmlFreeFunc *freeFunc,
 			 xmlMallocFunc *mallocFunc,
 			 xmlMallocFunc *mallocAtomicFunc,
@@ -127,100 +142,60 @@ XMLPUBFUN int XMLCALL
  * Initialization of the memory layer.
  */
 XML_DEPRECATED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlInitMemory	(void);
 
 /*
  * Cleanup of the memory layer.
  */
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
                 xmlCleanupMemory        (void);
 /*
  * These are specific to the XML debug memory wrapper.
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN size_t
+	xmlMemSize	(void *ptr);
+XMLPUBFUN int
 	xmlMemUsed	(void);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	xmlMemBlocks	(void);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 	xmlMemDisplay	(FILE *fp);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 	xmlMemDisplayLast(FILE *fp, long nbBytes);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 	xmlMemShow	(FILE *fp, int nr);
-XMLPUBFUN void XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void
 	xmlMemoryDump	(void);
-XMLPUBFUN void * XMLCALL
+XMLPUBFUN void *
 	xmlMemMalloc	(size_t size) LIBXML_ATTR_ALLOC_SIZE(1);
-XMLPUBFUN void * XMLCALL
+XMLPUBFUN void *
 	xmlMemRealloc	(void *ptr,size_t size);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlMemFree	(void *ptr);
-XMLPUBFUN char * XMLCALL
+XMLPUBFUN char *
 	xmlMemoryStrdup	(const char *str);
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlMallocLoc	(size_t size, const char *file, int line) LIBXML_ATTR_ALLOC_SIZE(1);
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlReallocLoc	(void *ptr, size_t size, const char *file, int line);
-XMLPUBFUN void * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN void *
 	xmlMallocAtomicLoc (size_t size, const char *file, int line) LIBXML_ATTR_ALLOC_SIZE(1);
-XMLPUBFUN char * XMLCALL
+XML_DEPRECATED
+XMLPUBFUN char *
 	xmlMemStrdupLoc	(const char *str, const char *file, int line);
 
-
-#ifdef DEBUG_MEMORY_LOCATION
-/**
- * xmlMalloc:
- * @size:  number of bytes to allocate
- *
- * Wrapper for the malloc() function used in the XML library.
- *
- * Returns the pointer to the allocated area or NULL in case of error.
- */
-#define xmlMalloc(size) xmlMallocLoc((size), __FILE__, __LINE__)
-/**
- * xmlMallocAtomic:
- * @size:  number of bytes to allocate
- *
- * Wrapper for the malloc() function used in the XML library for allocation
- * of block not containing pointers to other areas.
- *
- * Returns the pointer to the allocated area or NULL in case of error.
- */
-#define xmlMallocAtomic(size) xmlMallocAtomicLoc((size), __FILE__, __LINE__)
-/**
- * xmlRealloc:
- * @ptr:  pointer to the existing allocated area
- * @size:  number of bytes to allocate
- *
- * Wrapper for the realloc() function used in the XML library.
- *
- * Returns the pointer to the allocated area or NULL in case of error.
- */
-#define xmlRealloc(ptr, size) xmlReallocLoc((ptr), (size), __FILE__, __LINE__)
-/**
- * xmlMemStrdup:
- * @str:  pointer to the existing string
- *
- * Wrapper for the strdup() function, xmlStrdup() is usually preferred.
- *
- * Returns the pointer to the allocated area or NULL in case of error.
- */
-#define xmlMemStrdup(str) xmlMemStrdupLoc((str), __FILE__, __LINE__)
-
-#endif /* DEBUG_MEMORY_LOCATION */
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
 
-#ifndef __XML_GLOBALS_H
-#ifndef __XML_THREADS_H__
-#include <libxml/threads.h>
-#include <libxml/globals.h>
-#endif
-#endif
-
 #endif  /* __DEBUG_MEMORY_ALLOC__ */
 
diff --git a/include/libxml/xmlmodule.h b/include/libxml/xmlmodule.h
index 9667820070af9341935bdaf57738a576c8308627..279986c1a9fe9c4025aa3f98cf5235018e5a22de 100644
--- a/include/libxml/xmlmodule.h
+++ b/include/libxml/xmlmodule.h
@@ -37,16 +37,16 @@ typedef enum {
     XML_MODULE_LOCAL= 2		/* local binding */
 } xmlModuleOption;
 
-XMLPUBFUN xmlModulePtr XMLCALL xmlModuleOpen	(const char *filename,
+XMLPUBFUN xmlModulePtr xmlModuleOpen	(const char *filename,
 						 int options);
 
-XMLPUBFUN int XMLCALL xmlModuleSymbol		(xmlModulePtr module,
+XMLPUBFUN int xmlModuleSymbol		(xmlModulePtr module,
 						 const char* name,
 						 void **result);
 
-XMLPUBFUN int XMLCALL xmlModuleClose		(xmlModulePtr module);
+XMLPUBFUN int xmlModuleClose		(xmlModulePtr module);
 
-XMLPUBFUN int XMLCALL xmlModuleFree		(xmlModulePtr module);
+XMLPUBFUN int xmlModuleFree		(xmlModulePtr module);
 
 #ifdef __cplusplus
 }
diff --git a/include/libxml/xmlreader.h b/include/libxml/xmlreader.h
index e8a8bcc9aab0041b5acabd8715952b078a36e674..5d4fc5d5a179fc7c128e44cf9aa9bf4b406ef8a8 100644
--- a/include/libxml/xmlreader.h
+++ b/include/libxml/xmlreader.h
@@ -12,11 +12,14 @@
 
 #include <libxml/xmlversion.h>
 #include <libxml/tree.h>
+#include <libxml/xmlerror.h>
 #include <libxml/xmlIO.h>
 #ifdef LIBXML_SCHEMAS_ENABLED
 #include <libxml/relaxng.h>
 #include <libxml/xmlschemas.h>
 #endif
+/* for compatibility */
+#include <libxml/parser.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -108,239 +111,244 @@ typedef xmlTextReader *xmlTextReaderPtr;
 /*
  * Constructors & Destructor
  */
-XMLPUBFUN xmlTextReaderPtr XMLCALL
+XMLPUBFUN xmlTextReaderPtr
 			xmlNewTextReader	(xmlParserInputBufferPtr input,
 	                                         const char *URI);
-XMLPUBFUN xmlTextReaderPtr XMLCALL
+XMLPUBFUN xmlTextReaderPtr
 			xmlNewTextReaderFilename(const char *URI);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlFreeTextReader	(xmlTextReaderPtr reader);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
             xmlTextReaderSetup(xmlTextReaderPtr reader,
                    xmlParserInputBufferPtr input, const char *URL,
                    const char *encoding, int options);
+XMLPUBFUN void
+            xmlTextReaderSetMaxAmplification(xmlTextReaderPtr reader,
+                   unsigned maxAmpl);
+XMLPUBFUN const xmlError *
+            xmlTextReaderGetLastError(xmlTextReaderPtr reader);
 
 /*
  * Iterators
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderRead	(xmlTextReaderPtr reader);
 
 #ifdef LIBXML_WRITER_ENABLED
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlTextReaderReadInnerXml(xmlTextReaderPtr reader);
 
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlTextReaderReadOuterXml(xmlTextReaderPtr reader);
 #endif
 
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlTextReaderReadString	(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader);
 
 /*
  * Attributes of the node
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderAttributeCount(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderDepth	(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderHasAttributes(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderHasValue(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderIsDefault	(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderNodeType	(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderQuoteChar	(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlTextReaderReadState	(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                         xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader);
 
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		    xmlTextReaderConstBaseUri	(xmlTextReaderPtr reader);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		    xmlTextReaderConstLocalName	(xmlTextReaderPtr reader);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		    xmlTextReaderConstName	(xmlTextReaderPtr reader);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		    xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		    xmlTextReaderConstPrefix	(xmlTextReaderPtr reader);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		    xmlTextReaderConstXmlLang	(xmlTextReaderPtr reader);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		    xmlTextReaderConstString	(xmlTextReaderPtr reader,
 						 const xmlChar *str);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		    xmlTextReaderConstValue	(xmlTextReaderPtr reader);
 
 /*
  * use the Const version of the routine for
  * better performance and simpler code
  */
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlTextReaderBaseUri	(xmlTextReaderPtr reader);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlTextReaderLocalName	(xmlTextReaderPtr reader);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlTextReaderName	(xmlTextReaderPtr reader);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlTextReaderNamespaceUri(xmlTextReaderPtr reader);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlTextReaderPrefix	(xmlTextReaderPtr reader);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlTextReaderXmlLang	(xmlTextReaderPtr reader);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 			xmlTextReaderValue	(xmlTextReaderPtr reader);
 
 /*
  * Methods of the XmlTextReader
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderClose		(xmlTextReaderPtr reader);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		    xmlTextReaderGetAttributeNo	(xmlTextReaderPtr reader,
 						 int no);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		    xmlTextReaderGetAttribute	(xmlTextReaderPtr reader,
 						 const xmlChar *name);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		    xmlTextReaderGetAttributeNs	(xmlTextReaderPtr reader,
 						 const xmlChar *localName,
 						 const xmlChar *namespaceURI);
-XMLPUBFUN xmlParserInputBufferPtr XMLCALL
+XMLPUBFUN xmlParserInputBufferPtr
 		    xmlTextReaderGetRemainder	(xmlTextReaderPtr reader);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		    xmlTextReaderLookupNamespace(xmlTextReaderPtr reader,
 						 const xmlChar *prefix);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader,
 						 int no);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader,
 						 const xmlChar *name);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
 						 const xmlChar *localName,
 						 const xmlChar *namespaceURI);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderMoveToElement	(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderNormalization	(xmlTextReaderPtr reader);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		    xmlTextReaderConstEncoding  (xmlTextReaderPtr reader);
 
 /*
  * Extensions
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderSetParserProp	(xmlTextReaderPtr reader,
 						 int prop,
 						 int value);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderGetParserProp	(xmlTextReaderPtr reader,
 						 int prop);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		    xmlTextReaderCurrentNode	(xmlTextReaderPtr reader);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
             xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
             xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader);
 
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		    xmlTextReaderPreserve	(xmlTextReaderPtr reader);
 #ifdef LIBXML_PATTERN_ENABLED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderPreservePattern(xmlTextReaderPtr reader,
 						 const xmlChar *pattern,
 						 const xmlChar **namespaces);
 #endif /* LIBXML_PATTERN_ENABLED */
-XMLPUBFUN xmlDocPtr XMLCALL
+XMLPUBFUN xmlDocPtr
 		    xmlTextReaderCurrentDoc	(xmlTextReaderPtr reader);
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		    xmlTextReaderExpand		(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderNext		(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderNextSibling	(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderIsValid	(xmlTextReaderPtr reader);
 #ifdef LIBXML_SCHEMAS_ENABLED
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader,
 						 const char *rng);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
 						 xmlRelaxNGValidCtxtPtr ctxt,
 						 int options);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader,
 						 xmlRelaxNGPtr schema);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderSchemaValidate	(xmlTextReaderPtr reader,
 						 const char *xsd);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
 						 xmlSchemaValidCtxtPtr ctxt,
 						 int options);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderSetSchema	(xmlTextReaderPtr reader,
 						 xmlSchemaPtr schema);
 #endif
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		    xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlTextReaderStandalone     (xmlTextReaderPtr reader);
 
 
 /*
  * Index lookup
  */
-XMLPUBFUN long XMLCALL
+XMLPUBFUN long
 		xmlTextReaderByteConsumed	(xmlTextReaderPtr reader);
 
 /*
  * New more complete APIs for simpler creation and reuse of readers
  */
-XMLPUBFUN xmlTextReaderPtr XMLCALL
+XMLPUBFUN xmlTextReaderPtr
 		xmlReaderWalker		(xmlDocPtr doc);
-XMLPUBFUN xmlTextReaderPtr XMLCALL
+XMLPUBFUN xmlTextReaderPtr
 		xmlReaderForDoc		(const xmlChar * cur,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlTextReaderPtr XMLCALL
+XMLPUBFUN xmlTextReaderPtr
 		xmlReaderForFile	(const char *filename,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlTextReaderPtr XMLCALL
+XMLPUBFUN xmlTextReaderPtr
 		xmlReaderForMemory	(const char *buffer,
 					 int size,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlTextReaderPtr XMLCALL
+XMLPUBFUN xmlTextReaderPtr
 		xmlReaderForFd		(int fd,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlTextReaderPtr XMLCALL
+XMLPUBFUN xmlTextReaderPtr
 		xmlReaderForIO		(xmlInputReadCallback ioread,
 					 xmlInputCloseCallback ioclose,
 					 void *ioctx,
@@ -348,34 +356,34 @@ XMLPUBFUN xmlTextReaderPtr XMLCALL
 					 const char *encoding,
 					 int options);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlReaderNewWalker	(xmlTextReaderPtr reader,
 					 xmlDocPtr doc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlReaderNewDoc		(xmlTextReaderPtr reader,
 					 const xmlChar * cur,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlReaderNewFile	(xmlTextReaderPtr reader,
 					 const char *filename,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlReaderNewMemory	(xmlTextReaderPtr reader,
 					 const char *buffer,
 					 int size,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlReaderNewFd		(xmlTextReaderPtr reader,
 					 int fd,
 					 const char *URL,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlReaderNewIO		(xmlTextReaderPtr reader,
 					 xmlInputReadCallback ioread,
 					 xmlInputCloseCallback ioclose,
@@ -397,23 +405,23 @@ typedef void *  xmlTextReaderLocatorPtr;
  *
  * Signature of an error callback from a reader parser
  */
-typedef void (XMLCALL *xmlTextReaderErrorFunc)(void *arg,
+typedef void (*xmlTextReaderErrorFunc)(void *arg,
 					       const char *msg,
 					       xmlParserSeverities severity,
 					       xmlTextReaderLocatorPtr locator);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 	    xmlTextReaderLocatorBaseURI (xmlTextReaderLocatorPtr locator);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
 					 xmlTextReaderErrorFunc f,
 					 void *arg);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
 						   xmlStructuredErrorFunc f,
 						   void *arg);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
 					 xmlTextReaderErrorFunc *f,
 					 void **arg);
diff --git a/include/libxml/xmlregexp.h b/include/libxml/xmlregexp.h
index 7009645a9252aa2b245c8fc247ab47adf4b3b3c9..2d66437a55b547fc809941ee0a9bafec722a432d 100644
--- a/include/libxml/xmlregexp.h
+++ b/include/libxml/xmlregexp.h
@@ -11,7 +11,9 @@
 #ifndef __XML_REGEXP_H__
 #define __XML_REGEXP_H__
 
+#include <stdio.h>
 #include <libxml/xmlversion.h>
+#include <libxml/xmlstring.h>
 
 #ifdef LIBXML_REGEXP_ENABLED
 
@@ -36,28 +38,19 @@ typedef xmlRegexp *xmlRegexpPtr;
 typedef struct _xmlRegExecCtxt xmlRegExecCtxt;
 typedef xmlRegExecCtxt *xmlRegExecCtxtPtr;
 
-#ifdef __cplusplus
-}
-#endif
-#include <libxml/tree.h>
-#include <libxml/dict.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
  * The POSIX like API
  */
-XMLPUBFUN xmlRegexpPtr XMLCALL
+XMLPUBFUN xmlRegexpPtr
 		    xmlRegexpCompile	(const xmlChar *regexp);
-XMLPUBFUN void XMLCALL			 xmlRegFreeRegexp(xmlRegexpPtr regexp);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN void			 xmlRegFreeRegexp(xmlRegexpPtr regexp);
+XMLPUBFUN int
 		    xmlRegexpExec	(xmlRegexpPtr comp,
 					 const xmlChar *value);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRegexpPrint	(FILE *output,
 					 xmlRegexpPtr regexp);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRegexpIsDeterminist(xmlRegexpPtr comp);
 
 /**
@@ -77,29 +70,29 @@ typedef void (*xmlRegExecCallbacks) (xmlRegExecCtxtPtr exec,
 /*
  * The progressive API
  */
-XMLPUBFUN xmlRegExecCtxtPtr XMLCALL
+XMLPUBFUN xmlRegExecCtxtPtr
 		    xmlRegNewExecCtxt	(xmlRegexpPtr comp,
 					 xmlRegExecCallbacks callback,
 					 void *data);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlRegFreeExecCtxt	(xmlRegExecCtxtPtr exec);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRegExecPushString(xmlRegExecCtxtPtr exec,
 					 const xmlChar *value,
 					 void *data);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRegExecPushString2(xmlRegExecCtxtPtr exec,
 					 const xmlChar *value,
 					 const xmlChar *value2,
 					 void *data);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRegExecNextValues(xmlRegExecCtxtPtr exec,
 					 int *nbval,
 					 int *nbneg,
 					 xmlChar **values,
 					 int *terminal);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlRegExecErrInfo	(xmlRegExecCtxtPtr exec,
 					 const xmlChar **string,
 					 int *nbval,
@@ -116,15 +109,15 @@ XMLPUBFUN int XMLCALL
 typedef struct _xmlExpCtxt xmlExpCtxt;
 typedef xmlExpCtxt *xmlExpCtxtPtr;
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlExpFreeCtxt	(xmlExpCtxtPtr ctxt);
-XMLPUBFUN xmlExpCtxtPtr XMLCALL
+XMLPUBFUN xmlExpCtxtPtr
 			xmlExpNewCtxt	(int maxNodes,
 					 xmlDictPtr dict);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlExpCtxtNbNodes(xmlExpCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlExpCtxtNbCons(xmlExpCtxtPtr ctxt);
 
 /* Expressions are trees but the tree is opaque */
@@ -150,31 +143,31 @@ XMLPUBVAR xmlExpNodePtr emptyExp;
 /*
  * Expressions are reference counted internally
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlExpFree	(xmlExpCtxtPtr ctxt,
 					 xmlExpNodePtr expr);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlExpRef	(xmlExpNodePtr expr);
 
 /*
  * constructors can be either manual or from a string
  */
-XMLPUBFUN xmlExpNodePtr XMLCALL
+XMLPUBFUN xmlExpNodePtr
 			xmlExpParse	(xmlExpCtxtPtr ctxt,
 					 const char *expr);
-XMLPUBFUN xmlExpNodePtr XMLCALL
+XMLPUBFUN xmlExpNodePtr
 			xmlExpNewAtom	(xmlExpCtxtPtr ctxt,
 					 const xmlChar *name,
 					 int len);
-XMLPUBFUN xmlExpNodePtr XMLCALL
+XMLPUBFUN xmlExpNodePtr
 			xmlExpNewOr	(xmlExpCtxtPtr ctxt,
 					 xmlExpNodePtr left,
 					 xmlExpNodePtr right);
-XMLPUBFUN xmlExpNodePtr XMLCALL
+XMLPUBFUN xmlExpNodePtr
 			xmlExpNewSeq	(xmlExpCtxtPtr ctxt,
 					 xmlExpNodePtr left,
 					 xmlExpNodePtr right);
-XMLPUBFUN xmlExpNodePtr XMLCALL
+XMLPUBFUN xmlExpNodePtr
 			xmlExpNewRange	(xmlExpCtxtPtr ctxt,
 					 xmlExpNodePtr subset,
 					 int min,
@@ -182,34 +175,34 @@ XMLPUBFUN xmlExpNodePtr XMLCALL
 /*
  * The really interesting APIs
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlExpIsNillable(xmlExpNodePtr expr);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlExpMaxToken	(xmlExpNodePtr expr);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlExpGetLanguage(xmlExpCtxtPtr ctxt,
 					 xmlExpNodePtr expr,
 					 const xmlChar**langList,
 					 int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlExpGetStart	(xmlExpCtxtPtr ctxt,
 					 xmlExpNodePtr expr,
 					 const xmlChar**tokList,
 					 int len);
-XMLPUBFUN xmlExpNodePtr XMLCALL
+XMLPUBFUN xmlExpNodePtr
 			xmlExpStringDerive(xmlExpCtxtPtr ctxt,
 					 xmlExpNodePtr expr,
 					 const xmlChar *str,
 					 int len);
-XMLPUBFUN xmlExpNodePtr XMLCALL
+XMLPUBFUN xmlExpNodePtr
 			xmlExpExpDerive	(xmlExpCtxtPtr ctxt,
 					 xmlExpNodePtr expr,
 					 xmlExpNodePtr sub);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 			xmlExpSubsume	(xmlExpCtxtPtr ctxt,
 					 xmlExpNodePtr expr,
 					 xmlExpNodePtr sub);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 			xmlExpDump	(xmlBufferPtr buf,
 					 xmlExpNodePtr expr);
 #endif /* LIBXML_EXPR_ENABLED */
diff --git a/include/libxml/xmlsave.h b/include/libxml/xmlsave.h
index fb329b22dbc2a8d113f34329ca9e44b410c5c7eb..e266e467c24b282a17818a013035cfe473fe50d8 100644
--- a/include/libxml/xmlsave.h
+++ b/include/libxml/xmlsave.h
@@ -41,47 +41,61 @@ typedef enum {
 typedef struct _xmlSaveCtxt xmlSaveCtxt;
 typedef xmlSaveCtxt *xmlSaveCtxtPtr;
 
-XMLPUBFUN xmlSaveCtxtPtr XMLCALL
+XMLPUBFUN xmlSaveCtxtPtr
 		xmlSaveToFd		(int fd,
 					 const char *encoding,
 					 int options);
-XMLPUBFUN xmlSaveCtxtPtr XMLCALL
+XMLPUBFUN xmlSaveCtxtPtr
 		xmlSaveToFilename	(const char *filename,
 					 const char *encoding,
 					 int options);
 
-XMLPUBFUN xmlSaveCtxtPtr XMLCALL
+XMLPUBFUN xmlSaveCtxtPtr
 		xmlSaveToBuffer		(xmlBufferPtr buffer,
 					 const char *encoding,
 					 int options);
 
-XMLPUBFUN xmlSaveCtxtPtr XMLCALL
+XMLPUBFUN xmlSaveCtxtPtr
 		xmlSaveToIO		(xmlOutputWriteCallback iowrite,
 					 xmlOutputCloseCallback ioclose,
 					 void *ioctx,
 					 const char *encoding,
 					 int options);
 
-XMLPUBFUN long XMLCALL
+XMLPUBFUN long
 		xmlSaveDoc		(xmlSaveCtxtPtr ctxt,
 					 xmlDocPtr doc);
-XMLPUBFUN long XMLCALL
+XMLPUBFUN long
 		xmlSaveTree		(xmlSaveCtxtPtr ctxt,
 					 xmlNodePtr node);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSaveFlush		(xmlSaveCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSaveClose		(xmlSaveCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
+		xmlSaveFinish		(xmlSaveCtxtPtr ctxt);
+XMLPUBFUN int
 		xmlSaveSetEscape	(xmlSaveCtxtPtr ctxt,
 					 xmlCharEncodingOutputFunc escape);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSaveSetAttrEscape	(xmlSaveCtxtPtr ctxt,
 					 xmlCharEncodingOutputFunc escape);
+
+XML_DEPRECATED
+XMLPUBFUN int
+                xmlThrDefIndentTreeOutput(int v);
+XML_DEPRECATED
+XMLPUBFUN const char *
+                xmlThrDefTreeIndentString(const char * v);
+XML_DEPRECATED
+XMLPUBFUN int
+                xmlThrDefSaveNoEmptyTags(int v);
+
 #ifdef __cplusplus
 }
 #endif
+
 #endif /* LIBXML_OUTPUT_ENABLED */
 #endif /* __XML_XMLSAVE_H__ */
 
diff --git a/include/libxml/xmlschemas.h b/include/libxml/xmlschemas.h
index b90e9d18c6e60de5291b3fe1a16a0400c7a72914..c2af3d7098b924f0ed7bc0ab37299ae3e06d204b 100644
--- a/include/libxml/xmlschemas.h
+++ b/include/libxml/xmlschemas.h
@@ -16,7 +16,10 @@
 
 #ifdef LIBXML_SCHEMAS_ENABLED
 
+#include <stdio.h>
+#include <libxml/encoding.h>
 #include <libxml/tree.h>
+#include <libxml/xmlerror.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -92,7 +95,7 @@ typedef xmlSchema *xmlSchemaPtr;
  *
  * Signature of an error callback from an XSD validation
  */
-typedef void (XMLCDECL *xmlSchemaValidityErrorFunc)
+typedef void (*xmlSchemaValidityErrorFunc)
                  (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
 
 /**
@@ -103,7 +106,7 @@ typedef void (XMLCDECL *xmlSchemaValidityErrorFunc)
  *
  * Signature of a warning callback from an XSD validation
  */
-typedef void (XMLCDECL *xmlSchemaValidityWarningFunc)
+typedef void (*xmlSchemaValidityWarningFunc)
                  (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
 
 /**
@@ -128,95 +131,95 @@ typedef xmlSchemaValidCtxt *xmlSchemaValidCtxtPtr;
  * Returns: 0 in case of success and -1 in case of error
  */
 
-typedef int (XMLCDECL *xmlSchemaValidityLocatorFunc) (void *ctx,
+typedef int (*xmlSchemaValidityLocatorFunc) (void *ctx,
                            const char **file, unsigned long *line);
 
 /*
  * Interfaces for parsing.
  */
-XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL
+XMLPUBFUN xmlSchemaParserCtxtPtr
 	    xmlSchemaNewParserCtxt	(const char *URL);
-XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL
+XMLPUBFUN xmlSchemaParserCtxtPtr
 	    xmlSchemaNewMemParserCtxt	(const char *buffer,
 					 int size);
-XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL
+XMLPUBFUN xmlSchemaParserCtxtPtr
 	    xmlSchemaNewDocParserCtxt	(xmlDocPtr doc);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchemaFreeParserCtxt	(xmlSchemaParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchemaSetParserErrors	(xmlSchemaParserCtxtPtr ctxt,
 					 xmlSchemaValidityErrorFunc err,
 					 xmlSchemaValidityWarningFunc warn,
 					 void *ctx);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
 					 xmlStructuredErrorFunc serror,
 					 void *ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
 					xmlSchemaValidityErrorFunc * err,
 					xmlSchemaValidityWarningFunc * warn,
 					void **ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaIsValid	(xmlSchemaValidCtxtPtr ctxt);
 
-XMLPUBFUN xmlSchemaPtr XMLCALL
+XMLPUBFUN xmlSchemaPtr
 	    xmlSchemaParse		(xmlSchemaParserCtxtPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchemaFree		(xmlSchemaPtr schema);
 #ifdef LIBXML_OUTPUT_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchemaDump		(FILE *output,
 					 xmlSchemaPtr schema);
 #endif /* LIBXML_OUTPUT_ENABLED */
 /*
  * Interfaces for validating
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchemaSetValidErrors	(xmlSchemaValidCtxtPtr ctxt,
 					 xmlSchemaValidityErrorFunc err,
 					 xmlSchemaValidityWarningFunc warn,
 					 void *ctx);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
 					 xmlStructuredErrorFunc serror,
 					 void *ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlSchemaGetValidErrors	(xmlSchemaValidCtxtPtr ctxt,
 					 xmlSchemaValidityErrorFunc *err,
 					 xmlSchemaValidityWarningFunc *warn,
 					 void **ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlSchemaSetValidOptions	(xmlSchemaValidCtxtPtr ctxt,
 					 int options);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
             xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,
 	                                 const char *filename);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt);
 
-XMLPUBFUN xmlSchemaValidCtxtPtr XMLCALL
+XMLPUBFUN xmlSchemaValidCtxtPtr
 	    xmlSchemaNewValidCtxt	(xmlSchemaPtr schema);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlSchemaFreeValidCtxt	(xmlSchemaValidCtxtPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlSchemaValidateDoc	(xmlSchemaValidCtxtPtr ctxt,
 					 xmlDocPtr instance);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
             xmlSchemaValidateOneElement (xmlSchemaValidCtxtPtr ctxt,
 			                 xmlNodePtr elem);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlSchemaValidateStream	(xmlSchemaValidCtxtPtr ctxt,
 					 xmlParserInputBufferPtr input,
 					 xmlCharEncoding enc,
 					 xmlSAXHandlerPtr sax,
 					 void *user_data);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 	    xmlSchemaValidateFile	(xmlSchemaValidCtxtPtr ctxt,
 					 const char * filename,
 					 int options);
 
-XMLPUBFUN xmlParserCtxtPtr XMLCALL
+XMLPUBFUN xmlParserCtxtPtr
 	    xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt);
 
 /*
@@ -225,15 +228,15 @@ XMLPUBFUN xmlParserCtxtPtr XMLCALL
 typedef struct _xmlSchemaSAXPlug xmlSchemaSAXPlugStruct;
 typedef xmlSchemaSAXPlugStruct *xmlSchemaSAXPlugPtr;
 
-XMLPUBFUN xmlSchemaSAXPlugPtr XMLCALL
+XMLPUBFUN xmlSchemaSAXPlugPtr
             xmlSchemaSAXPlug		(xmlSchemaValidCtxtPtr ctxt,
 					 xmlSAXHandlerPtr *sax,
 					 void **user_data);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
             xmlSchemaSAXUnplug		(xmlSchemaSAXPlugPtr plug);
 
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
             xmlSchemaValidateSetLocator	(xmlSchemaValidCtxtPtr vctxt,
 					 xmlSchemaValidityLocatorFunc f,
 					 void *ctxt);
diff --git a/include/libxml/xmlschemastypes.h b/include/libxml/xmlschemastypes.h
index 5d588f92ea348d0bbaad2eeb06eebf0cbeff767c..e2cde35707c5d14f4bdab4d0a6750719d52edda6 100644
--- a/include/libxml/xmlschemastypes.h
+++ b/include/libxml/xmlschemastypes.h
@@ -30,118 +30,118 @@ typedef enum {
     XML_SCHEMA_WHITESPACE_COLLAPSE = 3
 } xmlSchemaWhitespaceValueType;
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN int
 		xmlSchemaInitTypes		(void);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSchemaCleanupTypes		(void);
-XMLPUBFUN xmlSchemaTypePtr XMLCALL
+XMLPUBFUN xmlSchemaTypePtr
 		xmlSchemaGetPredefinedType	(const xmlChar *name,
 						 const xmlChar *ns);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaValidatePredefinedType	(xmlSchemaTypePtr type,
 						 const xmlChar *value,
 						 xmlSchemaValPtr *val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaValPredefTypeNode	(xmlSchemaTypePtr type,
 						 const xmlChar *value,
 						 xmlSchemaValPtr *val,
 						 xmlNodePtr node);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaValidateFacet		(xmlSchemaTypePtr base,
 						 xmlSchemaFacetPtr facet,
 						 const xmlChar *value,
 						 xmlSchemaValPtr val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaValidateFacetWhtsp	(xmlSchemaFacetPtr facet,
 						 xmlSchemaWhitespaceValueType fws,
 						 xmlSchemaValType valType,
 						 const xmlChar *value,
 						 xmlSchemaValPtr val,
 						 xmlSchemaWhitespaceValueType ws);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSchemaFreeValue		(xmlSchemaValPtr val);
-XMLPUBFUN xmlSchemaFacetPtr XMLCALL
+XMLPUBFUN xmlSchemaFacetPtr
 		xmlSchemaNewFacet		(void);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaCheckFacet		(xmlSchemaFacetPtr facet,
 						 xmlSchemaTypePtr typeDecl,
 						 xmlSchemaParserCtxtPtr ctxt,
 						 const xmlChar *name);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlSchemaFreeFacet		(xmlSchemaFacetPtr facet);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaCompareValues		(xmlSchemaValPtr x,
 						 xmlSchemaValPtr y);
-XMLPUBFUN xmlSchemaTypePtr XMLCALL
+XMLPUBFUN xmlSchemaTypePtr
     xmlSchemaGetBuiltInListSimpleTypeItemType	(xmlSchemaTypePtr type);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
     xmlSchemaValidateListSimpleTypeFacet	(xmlSchemaFacetPtr facet,
 						 const xmlChar *value,
 						 unsigned long actualLen,
 						 unsigned long *expectedLen);
-XMLPUBFUN xmlSchemaTypePtr XMLCALL
+XMLPUBFUN xmlSchemaTypePtr
 		xmlSchemaGetBuiltInType		(xmlSchemaValType type);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaIsBuiltInTypeFacet	(xmlSchemaTypePtr type,
 						 int facetType);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlSchemaCollapseString		(const xmlChar *value);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlSchemaWhiteSpaceReplace	(const xmlChar *value);
-XMLPUBFUN unsigned long  XMLCALL
+XMLPUBFUN unsigned long 
 		xmlSchemaGetFacetValueAsULong	(xmlSchemaFacetPtr facet);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaValidateLengthFacet	(xmlSchemaTypePtr type,
 						 xmlSchemaFacetPtr facet,
 						 const xmlChar *value,
 						 xmlSchemaValPtr val,
 						 unsigned long *length);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
 						  xmlSchemaValType valType,
 						  const xmlChar *value,
 						  xmlSchemaValPtr val,
 						  unsigned long *length,
 						  xmlSchemaWhitespaceValueType ws);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type,
 						 const xmlChar *value,
 						 xmlSchemaValPtr *val,
 						 xmlNodePtr node);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaGetCanonValue		(xmlSchemaValPtr val,
 						 const xmlChar **retValue);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaGetCanonValueWhtsp	(xmlSchemaValPtr val,
 						 const xmlChar **retValue,
 						 xmlSchemaWhitespaceValueType ws);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaValueAppend		(xmlSchemaValPtr prev,
 						 xmlSchemaValPtr cur);
-XMLPUBFUN xmlSchemaValPtr XMLCALL
+XMLPUBFUN xmlSchemaValPtr
 		xmlSchemaValueGetNext		(xmlSchemaValPtr cur);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		xmlSchemaValueGetAsString	(xmlSchemaValPtr val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaValueGetAsBoolean	(xmlSchemaValPtr val);
-XMLPUBFUN xmlSchemaValPtr XMLCALL
+XMLPUBFUN xmlSchemaValPtr
 		xmlSchemaNewStringValue		(xmlSchemaValType type,
 						 const xmlChar *value);
-XMLPUBFUN xmlSchemaValPtr XMLCALL
+XMLPUBFUN xmlSchemaValPtr
 		xmlSchemaNewNOTATIONValue	(const xmlChar *name,
 						 const xmlChar *ns);
-XMLPUBFUN xmlSchemaValPtr XMLCALL
+XMLPUBFUN xmlSchemaValPtr
 		xmlSchemaNewQNameValue		(const xmlChar *namespaceName,
 						 const xmlChar *localName);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlSchemaCompareValuesWhtsp	(xmlSchemaValPtr x,
 						 xmlSchemaWhitespaceValueType xws,
 						 xmlSchemaValPtr y,
 						 xmlSchemaWhitespaceValueType yws);
-XMLPUBFUN xmlSchemaValPtr XMLCALL
+XMLPUBFUN xmlSchemaValPtr
 		xmlSchemaCopyValue		(xmlSchemaValPtr val);
-XMLPUBFUN xmlSchemaValType XMLCALL
+XMLPUBFUN xmlSchemaValType
 		xmlSchemaGetValType		(xmlSchemaValPtr val);
 
 #ifdef __cplusplus
diff --git a/include/libxml/xmlstring.h b/include/libxml/xmlstring.h
index 2d0b2d1668eb7c9cd50cf54642577795e473c69e..db11a0b0e50482acf67efd6b9c7ca03879648d45 100644
--- a/include/libxml/xmlstring.h
+++ b/include/libxml/xmlstring.h
@@ -37,100 +37,100 @@ typedef unsigned char xmlChar;
 /*
  * xmlChar handling
  */
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
                 xmlStrdup                (const xmlChar *cur);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
                 xmlStrndup               (const xmlChar *cur,
                                          int len);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
                 xmlCharStrndup           (const char *cur,
                                          int len);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
                 xmlCharStrdup            (const char *cur);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
                 xmlStrsub                (const xmlChar *str,
                                          int start,
                                          int len);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
                 xmlStrchr                (const xmlChar *str,
                                          xmlChar val);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
                 xmlStrstr                (const xmlChar *str,
                                          const xmlChar *val);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
                 xmlStrcasestr            (const xmlChar *str,
                                          const xmlChar *val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                 xmlStrcmp                (const xmlChar *str1,
                                          const xmlChar *str2);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                 xmlStrncmp               (const xmlChar *str1,
                                          const xmlChar *str2,
                                          int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                 xmlStrcasecmp            (const xmlChar *str1,
                                          const xmlChar *str2);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                 xmlStrncasecmp           (const xmlChar *str1,
                                          const xmlChar *str2,
                                          int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                 xmlStrEqual              (const xmlChar *str1,
                                          const xmlChar *str2);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                 xmlStrQEqual             (const xmlChar *pref,
                                          const xmlChar *name,
                                          const xmlChar *str);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                 xmlStrlen                (const xmlChar *str);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
                 xmlStrcat                (xmlChar *cur,
                                          const xmlChar *add);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
                 xmlStrncat               (xmlChar *cur,
                                          const xmlChar *add,
                                          int len);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
                 xmlStrncatNew            (const xmlChar *str1,
                                          const xmlChar *str2,
                                          int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                 xmlStrPrintf             (xmlChar *buf,
                                          int len,
                                          const char *msg,
                                          ...) LIBXML_ATTR_FORMAT(3,4);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
                 xmlStrVPrintf                (xmlChar *buf,
                                          int len,
                                          const char *msg,
                                          va_list ap) LIBXML_ATTR_FORMAT(3,0);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
         xmlGetUTF8Char                   (const unsigned char *utf,
                                          int *len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
         xmlCheckUTF8                     (const unsigned char *utf);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
         xmlUTF8Strsize                   (const xmlChar *utf,
                                          int len);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
         xmlUTF8Strndup                   (const xmlChar *utf,
                                          int len);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
         xmlUTF8Strpos                    (const xmlChar *utf,
                                          int pos);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
         xmlUTF8Strloc                    (const xmlChar *utf,
                                          const xmlChar *utfchar);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
         xmlUTF8Strsub                    (const xmlChar *utf,
                                          int start,
                                          int len);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
         xmlUTF8Strlen                    (const xmlChar *utf);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
         xmlUTF8Size                      (const xmlChar *utf);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
         xmlUTF8Charcmp                   (const xmlChar *utf1,
                                          const xmlChar *utf2);
 
diff --git a/include/libxml/xmlunicode.h b/include/libxml/xmlunicode.h
index 01ac8b61f56a8e6955ff1004c19d9b62fdfb4280..b6d795b267d50c22553caed286ec2aea1803a336 100644
--- a/include/libxml/xmlunicode.h
+++ b/include/libxml/xmlunicode.h
@@ -7,7 +7,7 @@
  * http://www.unicode.org/Public/4.0-Update1/UCD-4.0.1.html
  * using the genUnicode.py Python script.
  *
- * Generation date: Mon Mar 27 11:09:52 2006
+ * Generation date: Tue Apr 30 17:30:38 2024
  * Sources: Blocks-4.0.1.txt UnicodeData-4.0.1.txt
  * Author: Daniel Veillard
  */
@@ -23,175 +23,339 @@
 extern "C" {
 #endif
 
-XMLPUBFUN int XMLCALL xmlUCSIsAegeanNumbers	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsAlphabeticPresentationForms	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsArabic	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsArabicPresentationFormsA	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsArabicPresentationFormsB	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsArmenian	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsArrows	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsBasicLatin	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsBengali	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsBlockElements	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsBopomofo	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsBopomofoExtended	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsBoxDrawing	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsBraillePatterns	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsBuhid	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsByzantineMusicalSymbols	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibility	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityForms	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityIdeographs	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityIdeographsSupplement	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCJKRadicalsSupplement	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCJKSymbolsandPunctuation	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographs	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographsExtensionA	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographsExtensionB	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCherokee	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCombiningDiacriticalMarks	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCombiningDiacriticalMarksforSymbols	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCombiningHalfMarks	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCombiningMarksforSymbols	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsControlPictures	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCurrencySymbols	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCypriotSyllabary	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCyrillic	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCyrillicSupplement	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsDeseret	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsDevanagari	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsDingbats	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsEnclosedAlphanumerics	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsEnclosedCJKLettersandMonths	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsEthiopic	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsGeneralPunctuation	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsGeometricShapes	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsGeorgian	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsGothic	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsGreek	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsGreekExtended	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsGreekandCoptic	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsGujarati	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsGurmukhi	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsHalfwidthandFullwidthForms	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsHangulCompatibilityJamo	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsHangulJamo	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsHangulSyllables	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsHanunoo	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsHebrew	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsHighPrivateUseSurrogates	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsHighSurrogates	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsHiragana	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsIPAExtensions	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsIdeographicDescriptionCharacters	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsKanbun	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsKangxiRadicals	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsKannada	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsKatakana	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsKatakanaPhoneticExtensions	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsKhmer	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsKhmerSymbols	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsLao	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsLatin1Supplement	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedA	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedB	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedAdditional	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsLetterlikeSymbols	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsLimbu	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsLinearBIdeograms	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsLinearBSyllabary	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsLowSurrogates	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMalayalam	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMathematicalAlphanumericSymbols	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMathematicalOperators	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousMathematicalSymbolsA	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousMathematicalSymbolsB	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousSymbols	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousSymbolsandArrows	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousTechnical	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMongolian	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMusicalSymbols	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsMyanmar	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsNumberForms	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsOgham	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsOldItalic	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsOpticalCharacterRecognition	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsOriya	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsOsmanya	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsPhoneticExtensions	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsPrivateUse	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsPrivateUseArea	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsRunic	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsShavian	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSinhala	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSmallFormVariants	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSpacingModifierLetters	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSpecials	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSuperscriptsandSubscripts	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSupplementalArrowsA	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSupplementalArrowsB	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSupplementalMathematicalOperators	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSupplementaryPrivateUseAreaA	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSupplementaryPrivateUseAreaB	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsSyriac	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsTagalog	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsTagbanwa	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsTags	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsTaiLe	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsTaiXuanJingSymbols	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsTamil	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsTelugu	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsThaana	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsThai	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsTibetan	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsUgaritic	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsUnifiedCanadianAboriginalSyllabics	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsVariationSelectors	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsVariationSelectorsSupplement	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsYiRadicals	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsYiSyllables	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsYijingHexagramSymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsAegeanNumbers	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsAlphabeticPresentationForms	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsArabic	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsArabicPresentationFormsA	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsArabicPresentationFormsB	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsArmenian	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsArrows	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsBasicLatin	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsBengali	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsBlockElements	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsBopomofo	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsBopomofoExtended	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsBoxDrawing	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsBraillePatterns	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsBuhid	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsByzantineMusicalSymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCJKCompatibility	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCJKCompatibilityForms	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCJKCompatibilityIdeographs	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCJKCompatibilityIdeographsSupplement	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCJKRadicalsSupplement	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCJKSymbolsandPunctuation	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCJKUnifiedIdeographs	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCJKUnifiedIdeographsExtensionA	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCJKUnifiedIdeographsExtensionB	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCherokee	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCombiningDiacriticalMarks	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCombiningDiacriticalMarksforSymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCombiningHalfMarks	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCombiningMarksforSymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsControlPictures	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCurrencySymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCypriotSyllabary	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCyrillic	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCyrillicSupplement	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsDeseret	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsDevanagari	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsDingbats	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsEnclosedAlphanumerics	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsEnclosedCJKLettersandMonths	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsEthiopic	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsGeneralPunctuation	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsGeometricShapes	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsGeorgian	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsGothic	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsGreek	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsGreekExtended	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsGreekandCoptic	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsGujarati	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsGurmukhi	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsHalfwidthandFullwidthForms	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsHangulCompatibilityJamo	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsHangulJamo	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsHangulSyllables	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsHanunoo	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsHebrew	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsHighPrivateUseSurrogates	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsHighSurrogates	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsHiragana	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsIPAExtensions	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsIdeographicDescriptionCharacters	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsKanbun	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsKangxiRadicals	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsKannada	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsKatakana	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsKatakanaPhoneticExtensions	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsKhmer	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsKhmerSymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsLao	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsLatin1Supplement	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsLatinExtendedA	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsLatinExtendedB	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsLatinExtendedAdditional	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsLetterlikeSymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsLimbu	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsLinearBIdeograms	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsLinearBSyllabary	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsLowSurrogates	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMalayalam	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMathematicalAlphanumericSymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMathematicalOperators	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMiscellaneousMathematicalSymbolsA	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMiscellaneousMathematicalSymbolsB	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMiscellaneousSymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMiscellaneousSymbolsandArrows	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMiscellaneousTechnical	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMongolian	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMusicalSymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsMyanmar	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsNumberForms	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsOgham	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsOldItalic	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsOpticalCharacterRecognition	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsOriya	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsOsmanya	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsPhoneticExtensions	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsPrivateUse	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsPrivateUseArea	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsRunic	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsShavian	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSinhala	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSmallFormVariants	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSpacingModifierLetters	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSpecials	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSuperscriptsandSubscripts	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSupplementalArrowsA	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSupplementalArrowsB	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSupplementalMathematicalOperators	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSupplementaryPrivateUseAreaA	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSupplementaryPrivateUseAreaB	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsSyriac	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsTagalog	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsTagbanwa	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsTags	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsTaiLe	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsTaiXuanJingSymbols	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsTamil	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsTelugu	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsThaana	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsThai	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsTibetan	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsUgaritic	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsUnifiedCanadianAboriginalSyllabics	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsVariationSelectors	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsVariationSelectorsSupplement	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsYiRadicals	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsYiSyllables	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsYijingHexagramSymbols	(int code);
 
-XMLPUBFUN int XMLCALL xmlUCSIsBlock	(int code, const char *block);
+XMLPUBFUN int xmlUCSIsBlock	(int code, const char *block);
 
-XMLPUBFUN int XMLCALL xmlUCSIsCatC	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatCc	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatCf	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatCo	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatCs	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatL	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatLl	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatLm	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatLo	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatLt	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatLu	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatM	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatMc	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatMe	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatMn	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatN	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatNd	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatNl	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatNo	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatP	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatPc	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatPd	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatPe	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatPf	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatPi	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatPo	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatPs	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatS	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatSc	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatSk	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatSm	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatSo	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatZ	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatZl	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatZp	(int code);
-XMLPUBFUN int XMLCALL xmlUCSIsCatZs	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatC	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatCc	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatCf	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatCo	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatCs	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatL	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatLl	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatLm	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatLo	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatLt	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatLu	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatM	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatMc	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatMe	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatMn	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatN	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatNd	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatNl	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatNo	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatP	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatPc	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatPd	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatPe	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatPf	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatPi	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatPo	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatPs	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatS	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatSc	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatSk	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatSm	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatSo	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatZ	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatZl	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatZp	(int code);
+XML_DEPRECATED
+XMLPUBFUN int xmlUCSIsCatZs	(int code);
 
-XMLPUBFUN int XMLCALL xmlUCSIsCat	(int code, const char *cat);
+XMLPUBFUN int xmlUCSIsCat	(int code, const char *cat);
 
 #ifdef __cplusplus
 }
diff --git a/include/libxml/xmlversion.h.in b/include/libxml/xmlversion.h.in
index bdebfe3b0c9eaa35f8cd0e94ca10f69ade97605a..f153a942f262a6340d8c7a7244e7163ade66a6ab 100644
--- a/include/libxml/xmlversion.h.in
+++ b/include/libxml/xmlversion.h.in
@@ -10,20 +10,6 @@
 #ifndef __XML_VERSION_H__
 #define __XML_VERSION_H__
 
-#include <libxml/xmlexports.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * use those to be sure nothing nasty will happen if
- * your library and includes mismatch
- */
-#ifndef LIBXML2_COMPILING_MSCCDEF
-XMLPUBFUN void XMLCALL xmlCheckVersion(int version);
-#endif /* LIBXML2_COMPILING_MSCCDEF */
-
 /**
  * LIBXML_DOTTED_VERSION:
  *
@@ -60,31 +46,6 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version);
  */
 #define LIBXML_TEST_VERSION xmlCheckVersion(@LIBXML_VERSION_NUMBER@);
 
-#ifndef VMS
-#if @WITH_TRIO@
-/**
- * WITH_TRIO:
- *
- * defined if the trio support need to be configured in
- */
-#define WITH_TRIO
-#else
-/**
- * WITHOUT_TRIO:
- *
- * defined if the trio support should not be configured in
- */
-#define WITHOUT_TRIO
-#endif
-#else /* VMS */
-/**
- * WITH_TRIO:
- *
- * defined if the trio support need to be configured in
- */
-#define WITH_TRIO 1
-#endif /* VMS */
-
 /**
  * LIBXML_THREAD_ENABLED:
  *
@@ -301,24 +262,6 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version);
 #define LIBXML_DEBUG_ENABLED
 #endif
 
-/**
- * DEBUG_MEMORY_LOCATION:
- *
- * Whether the memory debugging is configured in
- */
-#if @WITH_MEM_DEBUG@
-#define DEBUG_MEMORY_LOCATION
-#endif
-
-/**
- * LIBXML_DEBUG_RUNTIME:
- *
- * Whether the runtime debugging is configured in
- */
-#if @WITH_RUN_DEBUG@
-#define LIBXML_DEBUG_RUNTIME
-#endif
-
 /**
  * LIBXML_UNICODE_ENABLED:
  *
@@ -346,17 +289,6 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version);
 #define LIBXML_AUTOMATA_ENABLED
 #endif
 
-/**
- * LIBXML_EXPR_ENABLED:
- *
- * Whether the formal expressions interfaces are compiled in
- *
- * This code is unused and disabled unconditionally for now.
- */
-#if 0
-#define LIBXML_EXPR_ENABLED
-#endif
-
 /**
  * LIBXML_SCHEMAS_ENABLED:
  *
@@ -408,96 +340,8 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version);
 #define LIBXML_LZMA_ENABLED
 #endif
 
-#ifdef __GNUC__
-
-/**
- * ATTRIBUTE_UNUSED:
- *
- * Macro used to signal to GCC unused function parameters
- */
-
-#ifndef ATTRIBUTE_UNUSED
-# if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7)))
-#  define ATTRIBUTE_UNUSED __attribute__((unused))
-# else
-#  define ATTRIBUTE_UNUSED
-# endif
-#endif
-
-/**
- * LIBXML_ATTR_ALLOC_SIZE:
- *
- * Macro used to indicate to GCC this is an allocator function
- */
-
-#ifndef LIBXML_ATTR_ALLOC_SIZE
-# if (!defined(__clang__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))))
-#  define LIBXML_ATTR_ALLOC_SIZE(x) __attribute__((alloc_size(x)))
-# else
-#  define LIBXML_ATTR_ALLOC_SIZE(x)
-# endif
-#else
-# define LIBXML_ATTR_ALLOC_SIZE(x)
-#endif
-
-/**
- * LIBXML_ATTR_FORMAT:
- *
- * Macro used to indicate to GCC the parameter are printf like
- */
-
-#ifndef LIBXML_ATTR_FORMAT
-# if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)))
-#  define LIBXML_ATTR_FORMAT(fmt,args) __attribute__((__format__(__printf__,fmt,args)))
-# else
-#  define LIBXML_ATTR_FORMAT(fmt,args)
-# endif
-#else
-# define LIBXML_ATTR_FORMAT(fmt,args)
-#endif
-
-#ifndef XML_DEPRECATED
-#  ifdef IN_LIBXML
-#    define XML_DEPRECATED
-#  else
-/* Available since at least GCC 3.1 */
-#    define XML_DEPRECATED __attribute__((deprecated))
-#  endif
-#endif
-
-#else /* ! __GNUC__ */
-/**
- * ATTRIBUTE_UNUSED:
- *
- * Macro used to signal to GCC unused function parameters
- */
-#define ATTRIBUTE_UNUSED
-/**
- * LIBXML_ATTR_ALLOC_SIZE:
- *
- * Macro used to indicate to GCC this is an allocator function
- */
-#define LIBXML_ATTR_ALLOC_SIZE(x)
-/**
- * LIBXML_ATTR_FORMAT:
- *
- * Macro used to indicate to GCC the parameter are printf like
- */
-#define LIBXML_ATTR_FORMAT(fmt,args)
-/**
- * XML_DEPRECATED:
- *
- * Macro used to indicate that a function, variable, type or struct member
- * is deprecated.
- */
-#ifndef XML_DEPRECATED
-#define XML_DEPRECATED
-#endif
-#endif /* __GNUC__ */
+#include <libxml/xmlexports.h>
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 #endif
 
 
diff --git a/include/libxml/xmlwriter.h b/include/libxml/xmlwriter.h
index dd5add341668c549aff41fead5a04c0e3fbdb97c..55f88bc71f0c55d0d162a398bc5300dc87290f1b 100644
--- a/include/libxml/xmlwriter.h
+++ b/include/libxml/xmlwriter.h
@@ -29,20 +29,20 @@ extern "C" {
 /*
  * Constructors & Destructor
  */
-    XMLPUBFUN xmlTextWriterPtr XMLCALL
+    XMLPUBFUN xmlTextWriterPtr
         xmlNewTextWriter(xmlOutputBufferPtr out);
-    XMLPUBFUN xmlTextWriterPtr XMLCALL
+    XMLPUBFUN xmlTextWriterPtr
         xmlNewTextWriterFilename(const char *uri, int compression);
-    XMLPUBFUN xmlTextWriterPtr XMLCALL
+    XMLPUBFUN xmlTextWriterPtr
         xmlNewTextWriterMemory(xmlBufferPtr buf, int compression);
-    XMLPUBFUN xmlTextWriterPtr XMLCALL
+    XMLPUBFUN xmlTextWriterPtr
         xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt, int compression);
-    XMLPUBFUN xmlTextWriterPtr XMLCALL
+    XMLPUBFUN xmlTextWriterPtr
         xmlNewTextWriterDoc(xmlDocPtr * doc, int compression);
-    XMLPUBFUN xmlTextWriterPtr XMLCALL
+    XMLPUBFUN xmlTextWriterPtr
         xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node,
                              int compression);
-    XMLPUBFUN void XMLCALL xmlFreeTextWriter(xmlTextWriterPtr writer);
+    XMLPUBFUN void xmlFreeTextWriter(xmlTextWriterPtr writer);
 
 /*
  * Functions
@@ -52,30 +52,30 @@ extern "C" {
 /*
  * Document
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterStartDocument(xmlTextWriterPtr writer,
                                    const char *version,
                                    const char *encoding,
                                    const char *standalone);
-    XMLPUBFUN int XMLCALL xmlTextWriterEndDocument(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterEndDocument(xmlTextWriterPtr
                                                    writer);
 
 /*
  * Comments
  */
-    XMLPUBFUN int XMLCALL xmlTextWriterStartComment(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterStartComment(xmlTextWriterPtr
                                                     writer);
-    XMLPUBFUN int XMLCALL xmlTextWriterEndComment(xmlTextWriterPtr writer);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int xmlTextWriterEndComment(xmlTextWriterPtr writer);
+    XMLPUBFUN int
         xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
                                         const char *format, ...)
 					LIBXML_ATTR_FORMAT(2,3);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
                                          const char *format,
                                          va_list argptr)
 					 LIBXML_ATTR_FORMAT(2,0);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteComment(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterWriteComment(xmlTextWriterPtr
                                                     writer,
                                                     const xmlChar *
                                                     content);
@@ -83,47 +83,47 @@ extern "C" {
 /*
  * Elements
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterStartElement(xmlTextWriterPtr writer,
                                   const xmlChar * name);
-    XMLPUBFUN int XMLCALL xmlTextWriterStartElementNS(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterStartElementNS(xmlTextWriterPtr
                                                       writer,
                                                       const xmlChar *
                                                       prefix,
                                                       const xmlChar * name,
                                                       const xmlChar *
                                                       namespaceURI);
-    XMLPUBFUN int XMLCALL xmlTextWriterEndElement(xmlTextWriterPtr writer);
-    XMLPUBFUN int XMLCALL xmlTextWriterFullEndElement(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterEndElement(xmlTextWriterPtr writer);
+    XMLPUBFUN int xmlTextWriterFullEndElement(xmlTextWriterPtr
                                                       writer);
 
 /*
  * Elements conveniency functions
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
                                         const xmlChar * name,
                                         const char *format, ...)
 					LIBXML_ATTR_FORMAT(3,4);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
                                          const xmlChar * name,
                                          const char *format,
                                          va_list argptr)
 					 LIBXML_ATTR_FORMAT(3,0);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteElement(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterWriteElement(xmlTextWriterPtr
                                                     writer,
                                                     const xmlChar * name,
                                                     const xmlChar *
                                                     content);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
                                           const xmlChar * prefix,
                                           const xmlChar * name,
                                           const xmlChar * namespaceURI,
                                           const char *format, ...)
 					  LIBXML_ATTR_FORMAT(5,6);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
                                            const xmlChar * prefix,
                                            const xmlChar * name,
@@ -131,7 +131,7 @@ extern "C" {
                                            const char *format,
                                            va_list argptr)
 					   LIBXML_ATTR_FORMAT(5,0);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteElementNS(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterWriteElementNS(xmlTextWriterPtr
                                                       writer,
                                                       const xmlChar *
                                                       prefix,
@@ -144,48 +144,48 @@ extern "C" {
 /*
  * Text
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer,
                                     const char *format, ...)
 				    LIBXML_ATTR_FORMAT(2,3);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer,
                                      const char *format, va_list argptr)
 				     LIBXML_ATTR_FORMAT(2,0);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteRawLen(xmlTextWriterPtr writer,
                                  const xmlChar * content, int len);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteRaw(xmlTextWriterPtr writer,
                               const xmlChar * content);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatString(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterWriteFormatString(xmlTextWriterPtr
                                                          writer,
                                                          const char
                                                          *format, ...)
 							 LIBXML_ATTR_FORMAT(2,3);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatString(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterWriteVFormatString(xmlTextWriterPtr
                                                           writer,
                                                           const char
                                                           *format,
                                                           va_list argptr)
 							  LIBXML_ATTR_FORMAT(2,0);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteString(xmlTextWriterPtr writer,
+    XMLPUBFUN int xmlTextWriterWriteString(xmlTextWriterPtr writer,
                                                    const xmlChar *
                                                    content);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteBase64(xmlTextWriterPtr writer,
+    XMLPUBFUN int xmlTextWriterWriteBase64(xmlTextWriterPtr writer,
                                                    const char *data,
                                                    int start, int len);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteBinHex(xmlTextWriterPtr writer,
+    XMLPUBFUN int xmlTextWriterWriteBinHex(xmlTextWriterPtr writer,
                                                    const char *data,
                                                    int start, int len);
 
 /*
  * Attributes
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterStartAttribute(xmlTextWriterPtr writer,
                                     const xmlChar * name);
-    XMLPUBFUN int XMLCALL xmlTextWriterStartAttributeNS(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterStartAttributeNS(xmlTextWriterPtr
                                                         writer,
                                                         const xmlChar *
                                                         prefix,
@@ -193,36 +193,36 @@ extern "C" {
                                                         name,
                                                         const xmlChar *
                                                         namespaceURI);
-    XMLPUBFUN int XMLCALL xmlTextWriterEndAttribute(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterEndAttribute(xmlTextWriterPtr
                                                     writer);
 
 /*
  * Attributes conveniency functions
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
                                           const xmlChar * name,
                                           const char *format, ...)
 					  LIBXML_ATTR_FORMAT(3,4);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
                                            const xmlChar * name,
                                            const char *format,
                                            va_list argptr)
 					   LIBXML_ATTR_FORMAT(3,0);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteAttribute(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterWriteAttribute(xmlTextWriterPtr
                                                       writer,
                                                       const xmlChar * name,
                                                       const xmlChar *
                                                       content);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
                                             const xmlChar * prefix,
                                             const xmlChar * name,
                                             const xmlChar * namespaceURI,
                                             const char *format, ...)
 					    LIBXML_ATTR_FORMAT(5,6);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
                                              const xmlChar * prefix,
                                              const xmlChar * name,
@@ -230,7 +230,7 @@ extern "C" {
                                              const char *format,
                                              va_list argptr)
 					     LIBXML_ATTR_FORMAT(5,0);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteAttributeNS(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterWriteAttributeNS(xmlTextWriterPtr
                                                         writer,
                                                         const xmlChar *
                                                         prefix,
@@ -244,25 +244,25 @@ extern "C" {
 /*
  * PI's
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterStartPI(xmlTextWriterPtr writer,
                              const xmlChar * target);
-    XMLPUBFUN int XMLCALL xmlTextWriterEndPI(xmlTextWriterPtr writer);
+    XMLPUBFUN int xmlTextWriterEndPI(xmlTextWriterPtr writer);
 
 /*
  * PI conveniency functions
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer,
                                    const xmlChar * target,
                                    const char *format, ...)
 				   LIBXML_ATTR_FORMAT(3,4);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
                                     const xmlChar * target,
                                     const char *format, va_list argptr)
 				    LIBXML_ATTR_FORMAT(3,0);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWritePI(xmlTextWriterPtr writer,
                              const xmlChar * target,
                              const xmlChar * content);
@@ -277,52 +277,52 @@ extern "C" {
 /*
  * CDATA
  */
-    XMLPUBFUN int XMLCALL xmlTextWriterStartCDATA(xmlTextWriterPtr writer);
-    XMLPUBFUN int XMLCALL xmlTextWriterEndCDATA(xmlTextWriterPtr writer);
+    XMLPUBFUN int xmlTextWriterStartCDATA(xmlTextWriterPtr writer);
+    XMLPUBFUN int xmlTextWriterEndCDATA(xmlTextWriterPtr writer);
 
 /*
  * CDATA conveniency functions
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer,
                                       const char *format, ...)
 				      LIBXML_ATTR_FORMAT(2,3);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer,
                                        const char *format, va_list argptr)
 				       LIBXML_ATTR_FORMAT(2,0);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteCDATA(xmlTextWriterPtr writer,
                                 const xmlChar * content);
 
 /*
  * DTD
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterStartDTD(xmlTextWriterPtr writer,
                               const xmlChar * name,
                               const xmlChar * pubid,
                               const xmlChar * sysid);
-    XMLPUBFUN int XMLCALL xmlTextWriterEndDTD(xmlTextWriterPtr writer);
+    XMLPUBFUN int xmlTextWriterEndDTD(xmlTextWriterPtr writer);
 
 /*
  * DTD conveniency functions
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
                                     const xmlChar * name,
                                     const xmlChar * pubid,
                                     const xmlChar * sysid,
                                     const char *format, ...)
 				    LIBXML_ATTR_FORMAT(5,6);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
                                      const xmlChar * name,
                                      const xmlChar * pubid,
                                      const xmlChar * sysid,
                                      const char *format, va_list argptr)
 				     LIBXML_ATTR_FORMAT(5,0);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
                               const xmlChar * name,
                               const xmlChar * pubid,
@@ -339,27 +339,27 @@ extern "C" {
 /*
  * DTD element definition
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterStartDTDElement(xmlTextWriterPtr writer,
                                      const xmlChar * name);
-    XMLPUBFUN int XMLCALL xmlTextWriterEndDTDElement(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterEndDTDElement(xmlTextWriterPtr
                                                      writer);
 
 /*
  * DTD element definition conveniency functions
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
                                            const xmlChar * name,
                                            const char *format, ...)
 					   LIBXML_ATTR_FORMAT(3,4);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
                                             const xmlChar * name,
                                             const char *format,
                                             va_list argptr)
 					    LIBXML_ATTR_FORMAT(3,0);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDElement(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterWriteDTDElement(xmlTextWriterPtr
                                                        writer,
                                                        const xmlChar *
                                                        name,
@@ -369,27 +369,27 @@ extern "C" {
 /*
  * DTD attribute list definition
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer,
                                      const xmlChar * name);
-    XMLPUBFUN int XMLCALL xmlTextWriterEndDTDAttlist(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterEndDTDAttlist(xmlTextWriterPtr
                                                      writer);
 
 /*
  * DTD attribute list definition conveniency functions
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
                                            const xmlChar * name,
                                            const char *format, ...)
 					   LIBXML_ATTR_FORMAT(3,4);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
                                             const xmlChar * name,
                                             const char *format,
                                             va_list argptr)
 					    LIBXML_ATTR_FORMAT(3,0);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr
                                                        writer,
                                                        const xmlChar *
                                                        name,
@@ -399,48 +399,48 @@ extern "C" {
 /*
  * DTD entity definition
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
                                     int pe, const xmlChar * name);
-    XMLPUBFUN int XMLCALL xmlTextWriterEndDTDEntity(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterEndDTDEntity(xmlTextWriterPtr
                                                     writer);
 
 /*
  * DTD entity definition conveniency functions
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
                                                   int pe,
                                                   const xmlChar * name,
                                                   const char *format, ...)
 						  LIBXML_ATTR_FORMAT(4,5);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
                                                    int pe,
                                                    const xmlChar * name,
                                                    const char *format,
                                                    va_list argptr)
 						   LIBXML_ATTR_FORMAT(4,0);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
                                             int pe,
                                             const xmlChar * name,
                                             const xmlChar * content);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
                                             int pe,
                                             const xmlChar * name,
                                             const xmlChar * pubid,
                                             const xmlChar * sysid,
                                             const xmlChar * ndataid);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr
                                                     writer,
                                                     const xmlChar * pubid,
                                                     const xmlChar * sysid,
                                                     const xmlChar *
                                                     ndataid);
-    XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDEntity(xmlTextWriterPtr
+    XMLPUBFUN int xmlTextWriterWriteDTDEntity(xmlTextWriterPtr
                                                       writer, int pe,
                                                       const xmlChar * name,
                                                       const xmlChar *
@@ -455,7 +455,7 @@ extern "C" {
 /*
  * DTD notation definition
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
                                       const xmlChar * name,
                                       const xmlChar * pubid,
@@ -464,20 +464,21 @@ extern "C" {
 /*
  * Indentation
  */
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent);
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterSetIndentString(xmlTextWriterPtr writer,
                                      const xmlChar * str);
 
-    XMLPUBFUN int XMLCALL
+    XMLPUBFUN int
         xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar);
 
 
 /*
  * misc
  */
-    XMLPUBFUN int XMLCALL xmlTextWriterFlush(xmlTextWriterPtr writer);
+    XMLPUBFUN int xmlTextWriterFlush(xmlTextWriterPtr writer);
+    XMLPUBFUN int xmlTextWriterClose(xmlTextWriterPtr writer);
 
 #ifdef __cplusplus
 }
diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
index bfbc5d6d99517a045211349c82413ef22ba83f01..b89e105c08f8d0b815302aec689059306903f96f 100644
--- a/include/libxml/xpath.h
+++ b/include/libxml/xpath.h
@@ -400,7 +400,7 @@ struct _xmlXPathParserContext {
     int xptr;				/* it this an XPointer expression */
     xmlNodePtr         ancestor;	/* used for walking preceding axis */
 
-    int              valueFrame;        /* used to limit Pop on the stack */
+    int              valueFrame;        /* always zero for compatibility */
 };
 
 /************************************************************************
@@ -454,68 +454,72 @@ XMLPUBVAR double xmlXPathNINF;
     (((ns) == NULL) || ((ns)->nodeNr == 0) || ((ns)->nodeTab == NULL))
 
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPathFreeObject		(xmlXPathObjectPtr obj);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		    xmlXPathNodeSetCreate	(xmlNodePtr val);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPathFreeNodeSetList	(xmlXPathObjectPtr obj);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPathFreeNodeSet		(xmlNodeSetPtr obj);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPathObjectCopy		(xmlXPathObjectPtr val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlXPathCmpNodes		(xmlNodePtr node1,
 						 xmlNodePtr node2);
 /**
  * Conversion functions to basic types.
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlXPathCastNumberToBoolean	(double val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlXPathCastStringToBoolean	(const xmlChar * val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlXPathCastNodeSetToBoolean(xmlNodeSetPtr ns);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlXPathCastToBoolean	(xmlXPathObjectPtr val);
 
-XMLPUBFUN double XMLCALL
+XMLPUBFUN double
 		    xmlXPathCastBooleanToNumber	(int val);
-XMLPUBFUN double XMLCALL
+XMLPUBFUN double
 		    xmlXPathCastStringToNumber	(const xmlChar * val);
-XMLPUBFUN double XMLCALL
+XMLPUBFUN double
 		    xmlXPathCastNodeToNumber	(xmlNodePtr node);
-XMLPUBFUN double XMLCALL
+XMLPUBFUN double
 		    xmlXPathCastNodeSetToNumber	(xmlNodeSetPtr ns);
-XMLPUBFUN double XMLCALL
+XMLPUBFUN double
 		    xmlXPathCastToNumber	(xmlXPathObjectPtr val);
 
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		    xmlXPathCastBooleanToString	(int val);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		    xmlXPathCastNumberToString	(double val);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		    xmlXPathCastNodeToString	(xmlNodePtr node);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		    xmlXPathCastNodeSetToString	(xmlNodeSetPtr ns);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		    xmlXPathCastToString	(xmlXPathObjectPtr val);
 
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPathConvertBoolean	(xmlXPathObjectPtr val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPathConvertNumber	(xmlXPathObjectPtr val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPathConvertString	(xmlXPathObjectPtr val);
 
 /**
  * Context handling.
  */
-XMLPUBFUN xmlXPathContextPtr XMLCALL
+XMLPUBFUN xmlXPathContextPtr
 		    xmlXPathNewContext		(xmlDocPtr doc);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPathFreeContext		(xmlXPathContextPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN void
+		    xmlXPathSetErrorHandler(xmlXPathContextPtr ctxt,
+					    xmlStructuredErrorFunc handler,
+					    void *context);
+XMLPUBFUN int
 		    xmlXPathContextSetCache(xmlXPathContextPtr ctxt,
 				            int active,
 					    int value,
@@ -523,48 +527,48 @@ XMLPUBFUN int XMLCALL
 /**
  * Evaluation functions.
  */
-XMLPUBFUN long XMLCALL
+XMLPUBFUN long
 		    xmlXPathOrderDocElems	(xmlDocPtr doc);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlXPathSetContextNode	(xmlNodePtr node,
 						 xmlXPathContextPtr ctx);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPathNodeEval		(xmlNodePtr node,
 						 const xmlChar *str,
 						 xmlXPathContextPtr ctx);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPathEval		(const xmlChar *str,
 						 xmlXPathContextPtr ctx);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPathEvalExpression	(const xmlChar *str,
 						 xmlXPathContextPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlXPathEvalPredicate	(xmlXPathContextPtr ctxt,
 						 xmlXPathObjectPtr res);
 /**
  * Separate compilation/evaluation entry points.
  */
-XMLPUBFUN xmlXPathCompExprPtr XMLCALL
+XMLPUBFUN xmlXPathCompExprPtr
 		    xmlXPathCompile		(const xmlChar *str);
-XMLPUBFUN xmlXPathCompExprPtr XMLCALL
+XMLPUBFUN xmlXPathCompExprPtr
 		    xmlXPathCtxtCompile		(xmlXPathContextPtr ctxt,
 						 const xmlChar *str);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPathCompiledEval	(xmlXPathCompExprPtr comp,
 						 xmlXPathContextPtr ctx);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		    xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp,
 						 xmlXPathContextPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPathFreeCompExpr	(xmlXPathCompExprPtr comp);
 #endif /* LIBXML_XPATH_ENABLED */
 #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPathInit		(void);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathIsNaN	(double val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathIsInf	(double val);
 
 #ifdef __cplusplus
diff --git a/include/libxml/xpathInternals.h b/include/libxml/xpathInternals.h
index 76a6b481572d72a06c778ef949b0bf0df30382af..d1c90dff2aac24ba418503d433e7609661233060 100644
--- a/include/libxml/xpathInternals.h
+++ b/include/libxml/xpathInternals.h
@@ -12,6 +12,7 @@
 #ifndef __XML_XPATH_INTERNALS_H__
 #define __XML_XPATH_INTERNALS_H__
 
+#include <stdio.h>
 #include <libxml/xmlversion.h>
 #include <libxml/xpath.h>
 
@@ -100,15 +101,15 @@ extern "C" {
  */
 #define xmlXPathGetContextNode(ctxt)	((ctxt)->context->node)
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathPopBoolean	(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN double XMLCALL
+XMLPUBFUN double
 		xmlXPathPopNumber	(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlXPathPopString	(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathPopNodeSet	(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN void * XMLCALL
+XMLPUBFUN void *
 		xmlXPathPopExternal	(xmlXPathParserContextPtr ctxt);
 
 /**
@@ -297,7 +298,7 @@ XMLPUBFUN void * XMLCALL
     if (ctxt == NULL) return;						\
     if (nargs != (x))							\
         XP_ERROR(XPATH_INVALID_ARITY);					\
-    if (ctxt->valueNr < ctxt->valueFrame + (x))				\
+    if (ctxt->valueNr < (x))						\
         XP_ERROR(XPATH_STACK_ERROR);
 
 /**
@@ -331,7 +332,7 @@ XMLPUBFUN void * XMLCALL
  * Variable Lookup forwarding.
  */
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	xmlXPathRegisterVariableLookup	(xmlXPathContextPtr ctxt,
 					 xmlXPathVariableLookupFunc f,
 					 void *data);
@@ -340,7 +341,7 @@ XMLPUBFUN void XMLCALL
  * Function Lookup forwarding.
  */
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlXPathRegisterFuncLookup	(xmlXPathContextPtr ctxt,
 					 xmlXPathFuncLookupFunc f,
 					 void *funcCtxt);
@@ -348,22 +349,22 @@ XMLPUBFUN void XMLCALL
 /*
  * Error reporting.
  */
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPatherror	(xmlXPathParserContextPtr ctxt,
 				 const char *file,
 				 int line,
 				 int no);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathErr	(xmlXPathParserContextPtr ctxt,
 				 int error);
 
 #ifdef LIBXML_DEBUG_ENABLED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathDebugDumpObject	(FILE *output,
 					 xmlXPathObjectPtr cur,
 					 int depth);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 	    xmlXPathDebugDumpCompExpr(FILE *output,
 					 xmlXPathCompExprPtr comp,
 					 int depth);
@@ -371,48 +372,48 @@ XMLPUBFUN void XMLCALL
 /**
  * NodeSet handling.
  */
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathNodeSetContains		(xmlNodeSetPtr cur,
 						 xmlNodePtr val);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathDifference		(xmlNodeSetPtr nodes1,
 						 xmlNodeSetPtr nodes2);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathIntersection		(xmlNodeSetPtr nodes1,
 						 xmlNodeSetPtr nodes2);
 
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathDistinctSorted		(xmlNodeSetPtr nodes);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathDistinct		(xmlNodeSetPtr nodes);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathHasSameNodes		(xmlNodeSetPtr nodes1,
 						 xmlNodeSetPtr nodes2);
 
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathNodeLeadingSorted	(xmlNodeSetPtr nodes,
 						 xmlNodePtr node);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathLeadingSorted		(xmlNodeSetPtr nodes1,
 						 xmlNodeSetPtr nodes2);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathNodeLeading		(xmlNodeSetPtr nodes,
 						 xmlNodePtr node);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathLeading			(xmlNodeSetPtr nodes1,
 						 xmlNodeSetPtr nodes2);
 
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathNodeTrailingSorted	(xmlNodeSetPtr nodes,
 						 xmlNodePtr node);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathTrailingSorted		(xmlNodeSetPtr nodes1,
 						 xmlNodeSetPtr nodes2);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathNodeTrailing		(xmlNodeSetPtr nodes,
 						 xmlNodePtr node);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathTrailing		(xmlNodeSetPtr nodes1,
 						 xmlNodeSetPtr nodes2);
 
@@ -421,208 +422,208 @@ XMLPUBFUN xmlNodeSetPtr XMLCALL
  * Extending a context.
  */
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathRegisterNs		(xmlXPathContextPtr ctxt,
 						 const xmlChar *prefix,
 						 const xmlChar *ns_uri);
-XMLPUBFUN const xmlChar * XMLCALL
+XMLPUBFUN const xmlChar *
 		xmlXPathNsLookup		(xmlXPathContextPtr ctxt,
 						 const xmlChar *prefix);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathRegisteredNsCleanup	(xmlXPathContextPtr ctxt);
 
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathRegisterFunc		(xmlXPathContextPtr ctxt,
 						 const xmlChar *name,
 						 xmlXPathFunction f);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathRegisterFuncNS		(xmlXPathContextPtr ctxt,
 						 const xmlChar *name,
 						 const xmlChar *ns_uri,
 						 xmlXPathFunction f);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathRegisterVariable	(xmlXPathContextPtr ctxt,
 						 const xmlChar *name,
 						 xmlXPathObjectPtr value);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathRegisterVariableNS	(xmlXPathContextPtr ctxt,
 						 const xmlChar *name,
 						 const xmlChar *ns_uri,
 						 xmlXPathObjectPtr value);
-XMLPUBFUN xmlXPathFunction XMLCALL
+XMLPUBFUN xmlXPathFunction
 		xmlXPathFunctionLookup		(xmlXPathContextPtr ctxt,
 						 const xmlChar *name);
-XMLPUBFUN xmlXPathFunction XMLCALL
+XMLPUBFUN xmlXPathFunction
 		xmlXPathFunctionLookupNS	(xmlXPathContextPtr ctxt,
 						 const xmlChar *name,
 						 const xmlChar *ns_uri);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathRegisteredFuncsCleanup	(xmlXPathContextPtr ctxt);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathVariableLookup		(xmlXPathContextPtr ctxt,
 						 const xmlChar *name);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathVariableLookupNS	(xmlXPathContextPtr ctxt,
 						 const xmlChar *name,
 						 const xmlChar *ns_uri);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt);
 
 /**
  * Utilities to extend XPath.
  */
-XMLPUBFUN xmlXPathParserContextPtr XMLCALL
+XMLPUBFUN xmlXPathParserContextPtr
 		  xmlXPathNewParserContext	(const xmlChar *str,
 						 xmlXPathContextPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathFreeParserContext	(xmlXPathParserContextPtr ctxt);
 
 /* TODO: remap to xmlXPathValuePop and Push. */
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		valuePop			(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		valuePush			(xmlXPathParserContextPtr ctxt,
 						 xmlXPathObjectPtr value);
 
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathNewString		(const xmlChar *val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathNewCString		(const char *val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathWrapString		(xmlChar *val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathWrapCString		(char * val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathNewFloat		(double val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathNewBoolean		(int val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathNewNodeSet		(xmlNodePtr val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathNewValueTree		(xmlNodePtr val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathNodeSetAdd		(xmlNodeSetPtr cur,
 						 xmlNodePtr val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathNodeSetAddUnique	(xmlNodeSetPtr cur,
 						 xmlNodePtr val);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathNodeSetAddNs		(xmlNodeSetPtr cur,
 						 xmlNodePtr node,
 						 xmlNsPtr ns);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathNodeSetSort		(xmlNodeSetPtr set);
 
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathRoot			(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathEvalExpr		(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlXPathParseName		(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN xmlChar * XMLCALL
+XMLPUBFUN xmlChar *
 		xmlXPathParseNCName		(xmlXPathParserContextPtr ctxt);
 
 /*
  * Existing functions.
  */
-XMLPUBFUN double XMLCALL
+XMLPUBFUN double
 		xmlXPathStringEvalNumber	(const xmlChar *str);
-XMLPUBFUN int XMLCALL
+XMLPUBFUN int
 		xmlXPathEvaluatePredicateResult (xmlXPathParserContextPtr ctxt,
 						 xmlXPathObjectPtr res);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathRegisterAllFunctions	(xmlXPathContextPtr ctxt);
-XMLPUBFUN xmlNodeSetPtr XMLCALL
+XMLPUBFUN xmlNodeSetPtr
 		xmlXPathNodeSetMerge		(xmlNodeSetPtr val1,
 						 xmlNodeSetPtr val2);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathNodeSetDel		(xmlNodeSetPtr cur,
 						 xmlNodePtr val);
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		xmlXPathNodeSetRemove		(xmlNodeSetPtr cur,
 						 int val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathNewNodeSetList		(xmlNodeSetPtr val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathWrapNodeSet		(xmlNodeSetPtr val);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		xmlXPathWrapExternal		(void *val);
 
-XMLPUBFUN int XMLCALL xmlXPathEqualValues(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN int XMLCALL xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN int XMLCALL xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict);
-XMLPUBFUN void XMLCALL xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN void XMLCALL xmlXPathAddValues(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN void XMLCALL xmlXPathSubValues(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN void XMLCALL xmlXPathMultValues(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN void XMLCALL xmlXPathDivValues(xmlXPathParserContextPtr ctxt);
-XMLPUBFUN void XMLCALL xmlXPathModValues(xmlXPathParserContextPtr ctxt);
+XMLPUBFUN int xmlXPathEqualValues(xmlXPathParserContextPtr ctxt);
+XMLPUBFUN int xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt);
+XMLPUBFUN int xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict);
+XMLPUBFUN void xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt);
+XMLPUBFUN void xmlXPathAddValues(xmlXPathParserContextPtr ctxt);
+XMLPUBFUN void xmlXPathSubValues(xmlXPathParserContextPtr ctxt);
+XMLPUBFUN void xmlXPathMultValues(xmlXPathParserContextPtr ctxt);
+XMLPUBFUN void xmlXPathDivValues(xmlXPathParserContextPtr ctxt);
+XMLPUBFUN void xmlXPathModValues(xmlXPathParserContextPtr ctxt);
 
-XMLPUBFUN int XMLCALL xmlXPathIsNodeType(const xmlChar *name);
+XMLPUBFUN int xmlXPathIsNodeType(const xmlChar *name);
 
 /*
  * Some of the axis navigation routines.
  */
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextSelf(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextSelf(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextChild(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextChild(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextParent(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextParent(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
-XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt,
+XMLPUBFUN xmlNodePtr xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt,
 			xmlNodePtr cur);
 /*
  * The official core of XPath functions.
  */
-XMLPUBFUN void XMLCALL xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs);
-XMLPUBFUN void XMLCALL xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs);
+XMLPUBFUN void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs);
 
 /**
  * Really internal functions
  */
-XMLPUBFUN void XMLCALL xmlXPathNodeSetFreeNs(xmlNsPtr ns);
+XMLPUBFUN void xmlXPathNodeSetFreeNs(xmlNsPtr ns);
 
 #ifdef __cplusplus
 }
diff --git a/include/libxml/xpointer.h b/include/libxml/xpointer.h
index ca7bdbe085f936a3e88342eb7ef75d75197cfa33..a5260008fc09875d409c59d8c6099f97110ebd6f 100644
--- a/include/libxml/xpointer.h
+++ b/include/libxml/xpointer.h
@@ -28,7 +28,7 @@
 extern "C" {
 #endif
 
-#ifdef LIBXML_XPTR_LOCS_ENABLED
+#if defined(LIBXML_XPTR_LOCS_ENABLED)
 /*
  * A Location Set
  */
@@ -45,90 +45,91 @@ struct _xmlLocationSet {
  */
 
 XML_DEPRECATED
-XMLPUBFUN xmlLocationSetPtr XMLCALL
+XMLPUBFUN xmlLocationSetPtr
 		    xmlXPtrLocationSetCreate	(xmlXPathObjectPtr val);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPtrFreeLocationSet	(xmlLocationSetPtr obj);
 XML_DEPRECATED
-XMLPUBFUN xmlLocationSetPtr XMLCALL
+XMLPUBFUN xmlLocationSetPtr
 		    xmlXPtrLocationSetMerge	(xmlLocationSetPtr val1,
 						 xmlLocationSetPtr val2);
 XML_DEPRECATED
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrNewRange		(xmlNodePtr start,
 						 int startindex,
 						 xmlNodePtr end,
 						 int endindex);
 XML_DEPRECATED
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrNewRangePoints	(xmlXPathObjectPtr start,
 						 xmlXPathObjectPtr end);
 XML_DEPRECATED
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrNewRangeNodePoint	(xmlNodePtr start,
 						 xmlXPathObjectPtr end);
 XML_DEPRECATED
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrNewRangePointNode	(xmlXPathObjectPtr start,
 						 xmlNodePtr end);
 XML_DEPRECATED
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrNewRangeNodes	(xmlNodePtr start,
 						 xmlNodePtr end);
 XML_DEPRECATED
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrNewLocationSetNodes	(xmlNodePtr start,
 						 xmlNodePtr end);
 XML_DEPRECATED
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set);
 XML_DEPRECATED
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrNewRangeNodeObject	(xmlNodePtr start,
 						 xmlXPathObjectPtr end);
 XML_DEPRECATED
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrNewCollapsedRange	(xmlNodePtr start);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPtrLocationSetAdd	(xmlLocationSetPtr cur,
 						 xmlXPathObjectPtr val);
 XML_DEPRECATED
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrWrapLocationSet	(xmlLocationSetPtr val);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPtrLocationSetDel	(xmlLocationSetPtr cur,
 						 xmlXPathObjectPtr val);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPtrLocationSetRemove	(xmlLocationSetPtr cur,
 						 int val);
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
+#endif /* defined(LIBXML_XPTR_LOCS_ENABLED) */
 
 /*
  * Functions.
  */
-XMLPUBFUN xmlXPathContextPtr XMLCALL
+XMLPUBFUN xmlXPathContextPtr
 		    xmlXPtrNewContext		(xmlDocPtr doc,
 						 xmlNodePtr here,
 						 xmlNodePtr origin);
-XMLPUBFUN xmlXPathObjectPtr XMLCALL
+XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrEval			(const xmlChar *str,
 						 xmlXPathContextPtr ctx);
-#ifdef LIBXML_XPTR_LOCS_ENABLED
+
+#if defined(LIBXML_XPTR_LOCS_ENABLED)
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPtrRangeToFunction	(xmlXPathParserContextPtr ctxt,
 						 int nargs);
 XML_DEPRECATED
-XMLPUBFUN xmlNodePtr XMLCALL
+XMLPUBFUN xmlNodePtr
 		    xmlXPtrBuildNodeList	(xmlXPathObjectPtr obj);
 XML_DEPRECATED
-XMLPUBFUN void XMLCALL
+XMLPUBFUN void
 		    xmlXPtrEvalRangePredicate	(xmlXPathParserContextPtr ctxt);
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
+#endif /* defined(LIBXML_XPTR_LOCS_ENABLED) */
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/private/buf.h b/include/private/buf.h
new file mode 100644
index 0000000000000000000000000000000000000000..982b9eea00b132598c523c32c2b4ad3dee0788c4
--- /dev/null
+++ b/include/private/buf.h
@@ -0,0 +1,61 @@
+#ifndef XML_BUF_H_PRIVATE__
+#define XML_BUF_H_PRIVATE__
+
+#include <libxml/tree.h>
+
+XML_HIDDEN xmlBufPtr
+xmlBufCreate(void);
+XML_HIDDEN xmlBufPtr
+xmlBufCreateSize(size_t size);
+
+XML_HIDDEN int
+xmlBufSetAllocationScheme(xmlBufPtr buf, xmlBufferAllocationScheme scheme);
+XML_HIDDEN int
+xmlBufGetAllocationScheme(xmlBufPtr buf);
+
+XML_HIDDEN void
+xmlBufFree(xmlBufPtr buf);
+XML_HIDDEN void
+xmlBufEmpty(xmlBufPtr buf);
+
+/* size_t xmlBufShrink(xmlBufPtr buf, size_t len); */
+XML_HIDDEN int
+xmlBufGrow(xmlBufPtr buf, int len);
+XML_HIDDEN int
+xmlBufResize(xmlBufPtr buf, size_t len);
+
+XML_HIDDEN int
+xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len);
+XML_HIDDEN int
+xmlBufCat(xmlBufPtr buf, const xmlChar *str);
+
+XML_HIDDEN size_t
+xmlBufAvail(const xmlBufPtr buf);
+XML_HIDDEN size_t
+xmlBufLength(const xmlBufPtr buf);
+/* size_t xmlBufUse(const xmlBufPtr buf); */
+XML_HIDDEN int
+xmlBufIsEmpty(const xmlBufPtr buf);
+XML_HIDDEN int
+xmlBufAddLen(xmlBufPtr buf, size_t len);
+
+/* const xmlChar * xmlBufContent(const xmlBuf *buf); */
+/* const xmlChar * xmlBufEnd(xmlBufPtr buf); */
+
+XML_HIDDEN xmlChar *
+xmlBufDetach(xmlBufPtr buf);
+
+XML_HIDDEN size_t
+xmlBufDump(FILE *file, xmlBufPtr buf);
+
+XML_HIDDEN xmlBufPtr
+xmlBufFromBuffer(xmlBufferPtr buffer);
+XML_HIDDEN xmlBufferPtr
+xmlBufBackToBuffer(xmlBufPtr buf);
+
+XML_HIDDEN int
+xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input);
+XML_HIDDEN int
+xmlBufUpdateInput(xmlBufPtr buf, xmlParserInputPtr input, size_t pos);
+
+#endif /* XML_BUF_H_PRIVATE__ */
diff --git a/include/private/dict.h b/include/private/dict.h
new file mode 100644
index 0000000000000000000000000000000000000000..826ac54a51f95720d7cff1394b1b1bdfe037fa83
--- /dev/null
+++ b/include/private/dict.h
@@ -0,0 +1,74 @@
+#ifndef XML_DICT_H_PRIVATE__
+#define XML_DICT_H_PRIVATE__
+
+#include <libxml/dict.h>
+
+/*
+ * Values are ANDed with 0xFFFFFFFF to support platforms where
+ * unsigned is larger than 32 bits. With 32-bit unsigned values,
+ * modern compilers should optimize the operation away.
+ */
+
+#define HASH_ROL(x,n) ((x) << (n) | ((x) & 0xFFFFFFFF) >> (32 - (n)))
+#define HASH_ROR(x,n) (((x) & 0xFFFFFFFF) >> (n) | (x) << (32 - (n)))
+
+/*
+ * GoodOAAT: One of a smallest non-multiplicative One-At-a-Time functions
+ * that passes SMHasher.
+ *
+ * Author: Sokolov Yura aka funny-falcon
+ */
+
+#define HASH_INIT(h1, h2, seed) \
+    do { \
+        h1 = seed ^ 0x3b00; \
+        h2 = HASH_ROL(seed, 15); \
+    } while (0)
+
+#define HASH_UPDATE(h1, h2, ch) \
+    do { \
+        h1 += ch; \
+        h1 += h1 << 3; \
+        h2 += h1; \
+        h2 = HASH_ROL(h2, 7); \
+        h2 += h2 << 2; \
+    } while (0)
+
+/* Result is in h2 */
+#define HASH_FINISH(h1, h2) \
+    do { \
+        h1 ^= h2; \
+        h1 += HASH_ROL(h2, 14); \
+        h2 ^= h1; h2 += HASH_ROR(h1, 6); \
+        h1 ^= h2; h1 += HASH_ROL(h2, 5); \
+        h2 ^= h1; h2 += HASH_ROR(h1, 8); \
+        h2 &= 0xFFFFFFFF; \
+    } while (0)
+
+typedef struct {
+    unsigned hashValue;
+    const xmlChar *name;
+} xmlHashedString;
+
+XML_HIDDEN void
+xmlInitDictInternal(void);
+XML_HIDDEN void
+xmlCleanupDictInternal(void);
+
+XML_HIDDEN unsigned
+xmlDictComputeHash(const xmlDict *dict, const xmlChar *string);
+XML_HIDDEN unsigned
+xmlDictCombineHash(unsigned v1, unsigned v2);
+XML_HIDDEN xmlHashedString
+xmlDictLookupHashed(xmlDictPtr dict, const xmlChar *name, int len);
+
+XML_HIDDEN void
+xmlInitRandom(void);
+XML_HIDDEN void
+xmlCleanupRandom(void);
+XML_HIDDEN unsigned
+xmlGlobalRandom(void);
+XML_HIDDEN unsigned
+xmlRandom(void);
+
+#endif /* XML_DICT_H_PRIVATE__ */
diff --git a/include/private/enc.h b/include/private/enc.h
new file mode 100644
index 0000000000000000000000000000000000000000..cd549145eb284ded3e9c7b7b4f8a396b888460db
--- /dev/null
+++ b/include/private/enc.h
@@ -0,0 +1,18 @@
+#ifndef XML_ENC_H_PRIVATE__
+#define XML_ENC_H_PRIVATE__
+
+#include <libxml/encoding.h>
+#include <libxml/tree.h>
+
+XML_HIDDEN void
+xmlInitEncodingInternal(void);
+
+XML_HIDDEN int
+xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
+                 int *outlen, const unsigned char *in, int *inlen);
+XML_HIDDEN int
+xmlCharEncInput(xmlParserInputBufferPtr input);
+XML_HIDDEN int
+xmlCharEncOutput(xmlOutputBufferPtr output, int init);
+
+#endif /* XML_ENC_H_PRIVATE__ */
diff --git a/include/private/entities.h b/include/private/entities.h
new file mode 100644
index 0000000000000000000000000000000000000000..d262ef47f6545cc38cced4d510b1b87d1ef91e9a
--- /dev/null
+++ b/include/private/entities.h
@@ -0,0 +1,27 @@
+#ifndef XML_ENTITIES_H_PRIVATE__
+#define XML_ENTITIES_H_PRIVATE__
+
+#include <libxml/tree.h>
+#include <libxml/xmlstring.h>
+
+/*
+ * Entity flags
+ *
+ * XML_ENT_PARSED: The entity was parsed and `children` points to the
+ * content.
+ *
+ * XML_ENT_CHECKED: The entity was checked for loops and amplification.
+ * expandedSize was set.
+ *
+ * XML_ENT_VALIDATED: The entity contains a valid attribute value.
+ * Only used when entities aren't substituted.
+ */
+#define XML_ENT_PARSED      (1u << 0)
+#define XML_ENT_CHECKED     (1u << 1)
+#define XML_ENT_VALIDATED   (1u << 2)
+#define XML_ENT_EXPANDING   (1u << 3)
+
+XML_HIDDEN xmlChar *
+xmlEncodeAttributeEntities(xmlDocPtr doc, const xmlChar *input);
+
+#endif /* XML_ENTITIES_H_PRIVATE__ */
diff --git a/include/private/error.h b/include/private/error.h
new file mode 100644
index 0000000000000000000000000000000000000000..506405a1f06fac44c6bfa295b9f5b9fefb5bcbbc
--- /dev/null
+++ b/include/private/error.h
@@ -0,0 +1,34 @@
+#ifndef XML_ERROR_H_PRIVATE__
+#define XML_ERROR_H_PRIVATE__
+
+#include <libxml/xmlerror.h>
+#include <libxml/xmlversion.h>
+
+#define MAX_ERR_MSG_SIZE 64000
+
+struct _xmlNode;
+
+XML_HIDDEN void
+xmlRaiseMemoryError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel,
+                    void *data, int domain, xmlError *error);
+XML_HIDDEN int
+xmlVRaiseError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel,
+               void *data, void *ctx, struct _xmlNode *node,
+               int domain, int code, xmlErrorLevel level,
+               const char *file, int line, const char *str1,
+               const char *str2, const char *str3, int int1, int col,
+               const char *msg, va_list ap);
+XML_HIDDEN int
+__xmlRaiseError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel,
+                void *data, void *ctx, struct _xmlNode *node,
+                int domain, int code, xmlErrorLevel level,
+                const char *file, int line, const char *str1,
+                const char *str2, const char *str3, int int1, int col,
+	        const char *msg, ...) LIBXML_ATTR_FORMAT(16,17);
+XML_HIDDEN void
+xmlGenericErrorDefaultFunc(void *ctx, const char *msg,
+                           ...) LIBXML_ATTR_FORMAT(2,3);
+XML_HIDDEN const char *
+xmlErrString(xmlParserErrors code);
+
+#endif /* XML_ERROR_H_PRIVATE__ */
diff --git a/include/private/globals.h b/include/private/globals.h
new file mode 100644
index 0000000000000000000000000000000000000000..828b6d50fe7ded4baf6521f930fd35ab5e1e28ab
--- /dev/null
+++ b/include/private/globals.h
@@ -0,0 +1,14 @@
+#ifndef XML_GLOBALS_H_PRIVATE__
+#define XML_GLOBALS_H_PRIVATE__
+
+XML_HIDDEN void
+xmlInitGlobalsInternal(void);
+XML_HIDDEN void
+xmlCleanupGlobalsInternal(void);
+
+#ifdef LIBXML_THREAD_ENABLED
+XML_HIDDEN unsigned *
+xmlGetLocalRngState(void);
+#endif
+
+#endif /* XML_GLOBALS_H_PRIVATE__ */
diff --git a/include/private/html.h b/include/private/html.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b499296a6b016e01093c358618de983617c5821
--- /dev/null
+++ b/include/private/html.h
@@ -0,0 +1,14 @@
+#ifndef XML_HTML_H_PRIVATE__
+#define XML_HTML_H_PRIVATE__
+
+#include <libxml/xmlversion.h>
+
+#ifdef LIBXML_HTML_ENABLED
+
+XML_HIDDEN void
+__htmlParseContent(void *ctx);
+
+#endif /* LIBXML_HTML_ENABLED */
+
+#endif /* XML_HTML_H_PRIVATE__ */
+
diff --git a/include/private/io.h b/include/private/io.h
new file mode 100644
index 0000000000000000000000000000000000000000..a2535ae196193883805a8a41437118b42ad6732f
--- /dev/null
+++ b/include/private/io.h
@@ -0,0 +1,35 @@
+#ifndef XML_IO_H_PRIVATE__
+#define XML_IO_H_PRIVATE__
+
+#include <libxml/encoding.h>
+#include <libxml/tree.h>
+#include <libxml/xmlversion.h>
+
+XML_HIDDEN void
+xmlInitIOCallbacks(void);
+
+XML_HIDDEN int
+__xmlIOErr(int domain, int code, const char *extra);
+
+XML_HIDDEN int
+xmlNoNetExists(const char *filename);
+
+XML_HIDDEN int
+xmlParserInputBufferCreateFilenameSafe(const char *URI, xmlCharEncoding enc,
+                                       xmlParserInputBufferPtr *out);
+
+XML_HIDDEN xmlParserInputBufferPtr
+xmlNewInputBufferString(const char *str, int flags);
+XML_HIDDEN xmlParserInputBufferPtr
+xmlNewInputBufferMemory(const void *mem, size_t size, int flags,
+                        xmlCharEncoding enc);
+
+#ifdef LIBXML_OUTPUT_ENABLED
+XML_HIDDEN xmlOutputBufferPtr
+xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
+XML_HIDDEN void
+xmlOutputBufferWriteQuotedString(xmlOutputBufferPtr buf,
+                                 const xmlChar *string);
+#endif
+
+#endif /* XML_IO_H_PRIVATE__ */
diff --git a/include/private/memory.h b/include/private/memory.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef0497c65cf0ee5d172fa73aff6541f5f0f9d4f0
--- /dev/null
+++ b/include/private/memory.h
@@ -0,0 +1,9 @@
+#ifndef XML_MEMORY_H_PRIVATE__
+#define XML_MEMORY_H_PRIVATE__
+
+XML_HIDDEN void
+xmlInitMemoryInternal(void);
+XML_HIDDEN void
+xmlCleanupMemoryInternal(void);
+
+#endif /* XML_MEMORY_H_PRIVATE__ */
diff --git a/include/private/parser.h b/include/private/parser.h
new file mode 100644
index 0000000000000000000000000000000000000000..b14bebf918e0a0c182a1497721da978995905cab
--- /dev/null
+++ b/include/private/parser.h
@@ -0,0 +1,121 @@
+#ifndef XML_PARSER_H_PRIVATE__
+#define XML_PARSER_H_PRIVATE__
+
+#include <libxml/parser.h>
+#include <libxml/xmlversion.h>
+
+/**
+ * XML_VCTXT_DTD_VALIDATED:
+ *
+ * Set after xmlValidateDtdFinal was called.
+ */
+#define XML_VCTXT_DTD_VALIDATED (1u << 0)
+/**
+ * XML_VCTXT_USE_PCTXT:
+ *
+ * Set if the validation context is part of a parser context.
+ */
+#define XML_VCTXT_USE_PCTXT (1u << 1)
+
+#define XML_INPUT_HAS_ENCODING      (1u << 0)
+#define XML_INPUT_AUTO_ENCODING     (7u << 1)
+#define XML_INPUT_AUTO_UTF8         (1u << 1)
+#define XML_INPUT_AUTO_UTF16LE      (2u << 1)
+#define XML_INPUT_AUTO_UTF16BE      (3u << 1)
+#define XML_INPUT_AUTO_OTHER        (4u << 1)
+#define XML_INPUT_USES_ENC_DECL     (1u << 4)
+#define XML_INPUT_ENCODING_ERROR    (1u << 5)
+#define XML_INPUT_PROGRESSIVE       (1u << 6)
+
+#define PARSER_STOPPED(ctxt) ((ctxt)->disableSAX > 1)
+
+#define PARSER_PROGRESSIVE(ctxt) \
+    ((ctxt)->input->flags & XML_INPUT_PROGRESSIVE)
+
+#define PARSER_IN_PE(ctxt) \
+    (((ctxt)->input->entity != NULL) && \
+     (((ctxt)->input->entity->etype == XML_INTERNAL_PARAMETER_ENTITY) || \
+      ((ctxt)->input->entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)))
+
+#define PARSER_EXTERNAL(ctxt) \
+    (((ctxt)->inSubset == 2) || \
+     (((ctxt)->input->entity != NULL) && \
+      ((ctxt)->input->entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)))
+
+XML_HIDDEN void
+xmlCtxtVErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain,
+            xmlParserErrors code, xmlErrorLevel level,
+            const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
+            int int1, const char *msg, va_list ap);
+XML_HIDDEN void
+xmlCtxtErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain,
+           xmlParserErrors code, xmlErrorLevel level,
+           const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
+           int int1, const char *msg, ...);
+XML_HIDDEN void
+xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
+XML_HIDDEN void LIBXML_ATTR_FORMAT(3,0)
+xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
+              const char *msg, const xmlChar *str1, const xmlChar *str2);
+XML_HIDDEN void
+xmlCtxtErrIO(xmlParserCtxtPtr ctxt, int code, const char *uri);
+
+XML_HIDDEN void
+xmlHaltParser(xmlParserCtxtPtr ctxt);
+XML_HIDDEN int
+xmlParserGrow(xmlParserCtxtPtr ctxt);
+XML_HIDDEN void
+xmlParserShrink(xmlParserCtxtPtr ctxt);
+
+XML_HIDDEN void
+xmlDetectEncoding(xmlParserCtxtPtr ctxt);
+XML_HIDDEN void
+xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding);
+XML_HIDDEN const xmlChar *
+xmlGetActualEncoding(xmlParserCtxtPtr ctxt);
+
+XML_HIDDEN xmlParserNsData *
+xmlParserNsCreate(void);
+XML_HIDDEN void
+xmlParserNsFree(xmlParserNsData *nsdb);
+/*
+ * These functions allow SAX handlers to attach extra data to namespaces
+ * efficiently and should be made public.
+ */
+XML_HIDDEN int
+xmlParserNsUpdateSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
+                     void *saxData);
+XML_HIDDEN void *
+xmlParserNsLookupSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix);
+
+#define XML_INPUT_BUF_STATIC		(1u << 1)
+#define XML_INPUT_BUF_ZERO_TERMINATED	(1u << 2)
+
+XML_HIDDEN xmlParserInputPtr
+xmlNewInputURL(xmlParserCtxtPtr ctxt, const char *url, const char *publicId,
+               const char *encoding, int flags);
+XML_HIDDEN xmlParserInputPtr
+xmlNewInputMemory(xmlParserCtxtPtr ctxt, const char *url,
+                  const void *mem, size_t size,
+                  const char *encoding, int flags);
+XML_HIDDEN xmlParserInputPtr
+xmlNewInputString(xmlParserCtxtPtr ctxt, const char *url, const char *str,
+                  const char *encoding, int flags);
+XML_HIDDEN xmlParserInputPtr
+xmlNewInputFd(xmlParserCtxtPtr ctxt, const char *filename, int fd,
+              const char *encoding, int flags);
+XML_HIDDEN xmlParserInputPtr
+xmlNewInputIO(xmlParserCtxtPtr ctxt, const char *url,
+              xmlInputReadCallback ioRead,
+              xmlInputCloseCallback ioClose,
+              void *ioCtxt,
+              const char *encoding, int flags);
+XML_HIDDEN xmlParserInputPtr
+xmlNewInputPush(xmlParserCtxtPtr ctxt, const char *url,
+                const char *chunk, int size, const char *encoding);
+
+XML_HIDDEN xmlChar *
+xmlExpandEntitiesInAttValue(xmlParserCtxtPtr ctxt, const xmlChar *str,
+                            int normalize);
+
+#endif /* XML_PARSER_H_PRIVATE__ */
diff --git a/include/private/regexp.h b/include/private/regexp.h
new file mode 100644
index 0000000000000000000000000000000000000000..b55c932bc0eaf80f220f783a93adc08bc6f6524c
--- /dev/null
+++ b/include/private/regexp.h
@@ -0,0 +1,23 @@
+#ifndef XML_REGEXP_H_PRIVATE__
+#define XML_REGEXP_H_PRIVATE__
+
+#include <libxml/xmlautomata.h>
+
+#ifdef LIBXML_REGEXP_ENABLED
+
+/*
+ * -2 and -3 are used by xmlValidateElementType for other things.
+ */
+#define XML_REGEXP_OK               0
+#define XML_REGEXP_NOT_FOUND        (-1)
+#define XML_REGEXP_INTERNAL_ERROR   (-4)
+#define XML_REGEXP_OUT_OF_MEMORY    (-5)
+#define XML_REGEXP_INTERNAL_LIMIT   (-6)
+#define XML_REGEXP_INVALID_UTF8     (-7)
+
+XML_HIDDEN void
+xmlAutomataSetFlags(xmlAutomataPtr am, int flags);
+
+#endif /* LIBXML_REGEXP_ENABLED */
+
+#endif /* XML_REGEXP_H_PRIVATE__ */
diff --git a/include/private/save.h b/include/private/save.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d4a753f1ac78e0cdfe815ecad34877291d2c24e
--- /dev/null
+++ b/include/private/save.h
@@ -0,0 +1,24 @@
+#ifndef XML_SAVE_H_PRIVATE__
+#define XML_SAVE_H_PRIVATE__
+
+#include <libxml/tree.h>
+#include <libxml/xmlsave.h>
+#include <libxml/xmlversion.h>
+
+#ifdef LIBXML_OUTPUT_ENABLED
+
+XML_HIDDEN int
+xmlSaveNotationDecl(xmlSaveCtxtPtr ctxt, xmlNotationPtr cur);
+XML_HIDDEN int
+xmlSaveNotationTable(xmlSaveCtxtPtr ctxt, xmlNotationTablePtr cur);
+
+XML_HIDDEN void
+xmlBufAttrSerializeTxtContent(xmlOutputBufferPtr buf, xmlDocPtr doc,
+                              const xmlChar *string);
+XML_HIDDEN void
+xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
+
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+#endif /* XML_SAVE_H_PRIVATE__ */
+
diff --git a/include/private/string.h b/include/private/string.h
new file mode 100644
index 0000000000000000000000000000000000000000..34f4c96cb206abb0e78a1d01702f628b6e94c023
--- /dev/null
+++ b/include/private/string.h
@@ -0,0 +1,13 @@
+#ifndef XML_STRING_H_PRIVATE__
+#define XML_STRING_H_PRIVATE__
+
+#include <libxml/xmlstring.h>
+
+XML_HIDDEN int
+xmlStrVASPrintf(xmlChar **out, int maxSize, const char *msg, va_list ap);
+XML_HIDDEN int
+xmlStrASPrintf(xmlChar **out, int maxSize, const char *msg, ...);
+XML_HIDDEN xmlChar *
+xmlEscapeFormatString(xmlChar **msg);
+
+#endif /* XML_STRING_H_PRIVATE__ */
diff --git a/include/private/threads.h b/include/private/threads.h
new file mode 100644
index 0000000000000000000000000000000000000000..473bc7c0bcb37bcc5d59765b7af1bd5044ca81e7
--- /dev/null
+++ b/include/private/threads.h
@@ -0,0 +1,35 @@
+#ifndef XML_THREADS_H_PRIVATE__
+#define XML_THREADS_H_PRIVATE__
+
+#include <libxml/threads.h>
+
+#ifdef LIBXML_THREAD_ENABLED
+  #ifdef HAVE_PTHREAD_H
+    #include <pthread.h>
+    #define HAVE_POSIX_THREADS
+  #elif defined(_WIN32)
+    #define WIN32_LEAN_AND_MEAN
+    #include <windows.h>
+    #define HAVE_WIN32_THREADS
+  #endif
+#endif
+
+/*
+ * xmlMutex are a simple mutual exception locks
+ */
+struct _xmlMutex {
+#ifdef HAVE_POSIX_THREADS
+    pthread_mutex_t lock;
+#elif defined HAVE_WIN32_THREADS
+    CRITICAL_SECTION cs;
+#else
+    int empty;
+#endif
+};
+
+XML_HIDDEN void
+xmlInitMutex(xmlMutexPtr mutex);
+XML_HIDDEN void
+xmlCleanupMutex(xmlMutexPtr mutex);
+
+#endif /* XML_THREADS_H_PRIVATE__ */
diff --git a/include/private/tree.h b/include/private/tree.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d651d53f4bb3776b8661f393e72f602daebf3bb
--- /dev/null
+++ b/include/private/tree.h
@@ -0,0 +1,27 @@
+#ifndef XML_TREE_H_PRIVATE__
+#define XML_TREE_H_PRIVATE__
+
+/*
+ * Internal variable indicating if a callback has been registered for
+ * node creation/destruction. It avoids spending a lot of time in locking
+ * function while checking if the callback exists.
+ */
+XML_HIDDEN extern int
+__xmlRegisterCallbacks;
+
+XML_HIDDEN int
+xmlSearchNsSafe(xmlNodePtr node, const xmlChar *href, xmlNsPtr *out);
+XML_HIDDEN int
+xmlSearchNsByHrefSafe(xmlNodePtr node, const xmlChar *href, xmlNsPtr *out);
+
+XML_HIDDEN int
+xmlNodeParseContent(xmlNodePtr node, const xmlChar *content, int len);
+XML_HIDDEN xmlNodePtr
+xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
+                  int extended);
+XML_HIDDEN xmlNodePtr
+xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
+XML_HIDDEN const xmlChar *
+xmlSplitQName4(const xmlChar *name, xmlChar **prefixPtr);
+
+#endif /* XML_TREE_H_PRIVATE__ */
diff --git a/include/private/xinclude.h b/include/private/xinclude.h
new file mode 100644
index 0000000000000000000000000000000000000000..43c77e5061816f83afd6646a7f0d2a3e9d800744
--- /dev/null
+++ b/include/private/xinclude.h
@@ -0,0 +1,9 @@
+#ifndef XML_INCLUDE_H_PRIVATE__
+#define XML_INCLUDE_H_PRIVATE__
+
+#include <libxml/xinclude.h>
+
+XML_HIDDEN int
+xmlXIncludeSetStreamingMode(xmlXIncludeCtxtPtr ctxt, int mode);
+
+#endif /* XML_INCLUDE_H_PRIVATE__ */
diff --git a/include/private/xpath.h b/include/private/xpath.h
new file mode 100644
index 0000000000000000000000000000000000000000..72a69720332175e332f9b5417818f4fabd325fec
--- /dev/null
+++ b/include/private/xpath.h
@@ -0,0 +1,16 @@
+#ifndef XML_XPATH_H_PRIVATE__
+#define XML_XPATH_H_PRIVATE__
+
+#include <libxml/xpath.h>
+
+XML_HIDDEN void
+xmlInitXPathInternal(void);
+
+#ifdef LIBXML_XPATH_ENABLED
+XML_HIDDEN void
+xmlXPathErrMemory(xmlXPathContextPtr ctxt);
+XML_HIDDEN void
+xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt);
+#endif
+
+#endif /* XML_XPATH_H_PRIVATE__ */
diff --git a/include/private/xzlib.h b/include/private/xzlib.h
new file mode 100644
index 0000000000000000000000000000000000000000..8505ef329e8f3dc19eb4747eaac0e3a8302fefdf
--- /dev/null
+++ b/include/private/xzlib.h
@@ -0,0 +1,32 @@
+/**
+ * xzlib.h: header for the front end for the transparent support of lzma
+ *          compression at the I/O layer
+ *
+ * See Copyright for the status of this software.
+ *
+ * Anders F Bjorklund <afb@users.sourceforge.net>
+ */
+
+#ifndef LIBXML2_XZLIB_H
+#define LIBXML2_XZLIB_H
+
+#include <libxml/xmlversion.h>
+
+#ifdef LIBXML_LZMA_ENABLED
+
+typedef void *xzFile;           /* opaque lzma file descriptor */
+
+XML_HIDDEN xzFile
+__libxml2_xzopen(const char *path, const char *mode);
+XML_HIDDEN xzFile
+__libxml2_xzdopen(const char *path, int fd, const char *mode);
+XML_HIDDEN int
+__libxml2_xzread(xzFile file, void *buf, unsigned len);
+XML_HIDDEN int
+__libxml2_xzclose(xzFile file);
+XML_HIDDEN int
+__libxml2_xzcompressed(xzFile f);
+
+#endif /* LIBXML_LZMA_ENABLED */
+
+#endif /* LIBXML2_XZLIB_H */
diff --git a/include/win32config.h b/include/win32config.h
index 4f99ae0b2ea6aa54e9996e4711ced7bc123d1833..a25e0385024fc080daf26adb6512da73bdf530eb 100644
--- a/include/win32config.h
+++ b/include/win32config.h
@@ -1,20 +1,21 @@
 #ifndef __LIBXML_WIN32_CONFIG__
 #define __LIBXML_WIN32_CONFIG__
 
-#define SEND_ARG2_CAST
-#define GETHOSTBYNAME_ARG_CAST
-
 #define HAVE_SYS_STAT_H
 #define HAVE_STAT
 #define HAVE_FCNTL_H
 
 #if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1600)
-#define HAVE_STDINT_H
+  #define HAVE_STDINT_H
 #endif
 
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#define snprintf _snprintf
-#define vsnprintf _vsnprintf
+#if defined(_MSC_VER)
+  #if _MSC_VER < 1900
+    #define snprintf _snprintf
+  #endif
+  #if _MSC_VER < 1500
+    #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
+  #endif
 #endif
 
 #endif /* __LIBXML_WIN32_CONFIG__ */
diff --git a/include/wsockcompat.h b/include/wsockcompat.h
new file mode 100644
index 0000000000000000000000000000000000000000..141de0c6405b25c4b8c7c2065ffd31e1185b0bd6
--- /dev/null
+++ b/include/wsockcompat.h
@@ -0,0 +1,53 @@
+/* include/wsockcompat.h
+ * Windows -> Berkeley Sockets compatibility things.
+ */
+
+#if !defined __XML_WSOCKCOMPAT_H__
+#define __XML_WSOCKCOMPAT_H__
+
+#include <errno.h>
+#include <winsock2.h>
+
+/* Fix for old MinGW. */
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_
+#endif
+
+/* the following is a workaround a problem for 'inline' keyword in said
+   header when compiled with Borland C++ 6 */
+#if defined(__BORLANDC__) && !defined(__cplusplus)
+#define inline __inline
+#define _inline __inline
+#endif
+
+#include <ws2tcpip.h>
+
+/* Check if ws2tcpip.h is a recent version which provides getaddrinfo() */
+#if defined(GetAddrInfo)
+#include <wspiapi.h>
+#ifndef SUPPORT_IP6
+  #define SUPPORT_IP6
+#endif
+#endif
+
+#ifndef XML_SOCKLEN_T
+#define XML_SOCKLEN_T int
+#endif
+
+#ifndef ECONNRESET
+#define ECONNRESET WSAECONNRESET
+#endif
+#ifndef EINPROGRESS
+#define EINPROGRESS WSAEINPROGRESS
+#endif
+#ifndef EINTR
+#define EINTR WSAEINTR
+#endif
+#ifndef ESHUTDOWN
+#define ESHUTDOWN WSAESHUTDOWN
+#endif
+#ifndef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
+
+#endif /* __XML_WSOCKCOMPAT_H__ */
diff --git a/legacy.c b/legacy.c
index bde3854d92bb1cd896a1c2d02b289231d0072728..ac80c0e4df9f5f5a18764e7acd987bdb4ad0861c 100644
--- a/legacy.c
+++ b/legacy.c
@@ -11,6 +11,7 @@
 #include "libxml.h"
 
 #ifdef LIBXML_LEGACY_ENABLED
+#include <stdio.h>
 #include <string.h>
 
 #include <libxml/tree.h>
@@ -55,7 +56,7 @@ htmlDecodeEntities(htmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "htmlDecodeEntities() deprecated function reached\n");
         deprecated = 1;
     }
@@ -416,7 +417,7 @@ xmlDecodeEntities(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlDecodeEntities() deprecated function reached\n");
         deprecated = 1;
     }
@@ -446,7 +447,7 @@ xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlNamespaceParseNCName() deprecated function reached\n");
         deprecated = 1;
     }
@@ -481,7 +482,7 @@ xmlNamespaceParseQName(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlNamespaceParseQName() deprecated function reached\n");
         deprecated = 1;
     }
@@ -510,7 +511,7 @@ xmlNamespaceParseNSDef(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlNamespaceParseNSDef() deprecated function reached\n");
         deprecated = 1;
     }
@@ -533,7 +534,7 @@ xmlParseQuotedString(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlParseQuotedString() deprecated function reached\n");
         deprecated = 1;
     }
@@ -561,7 +562,7 @@ xmlParseNamespace(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlParseNamespace() deprecated function reached\n");
         deprecated = 1;
     }
@@ -593,7 +594,7 @@ xmlScanName(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlScanName() deprecated function reached\n");
         deprecated = 1;
     }
@@ -633,7 +634,7 @@ xmlParserHandleReference(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlParserHandleReference() deprecated function reached\n");
         deprecated = 1;
     }
@@ -659,7 +660,7 @@ xmlHandleEntity(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlHandleEntity() deprecated function reached\n");
         deprecated = 1;
     }
@@ -683,7 +684,7 @@ xmlNewGlobalNs(xmlDocPtr doc ATTRIBUTE_UNUSED,
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlNewGlobalNs() deprecated function reached\n");
         deprecated = 1;
     }
@@ -703,7 +704,7 @@ xmlUpgradeOldNs(xmlDocPtr doc ATTRIBUTE_UNUSED)
     static int deprecated = 0;
 
     if (!deprecated) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "xmlUpgradeOldNs() deprecated function reached\n");
         deprecated = 1;
     }
@@ -729,15 +730,26 @@ xmlEncodeEntities(xmlDocPtr doc ATTRIBUTE_UNUSED,
     static int warning = 1;
 
     if (warning) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "Deprecated API xmlEncodeEntities() used\n");
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
                         "   change code to use xmlEncodeEntitiesReentrant()\n");
         warning = 0;
     }
     return (NULL);
 }
 
+/**
+ * xmlSetEntityReferenceFunc:
+ * @func: A valid function
+ *
+ * Set the function to call call back when a xml reference has been made
+ */
+void
+xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func ATTRIBUTE_UNUSED)
+{
+}
+
 /************************************************************************
  *									*
  *		Old set of SAXv1 functions				*
@@ -747,7 +759,7 @@ static int deprecated_v1_msg = 0;
 
 #define DEPRECATED(n)						\
     if (deprecated_v1_msg == 0)					\
-	xmlGenericError(xmlGenericErrorContext,			\
+	fprintf(stderr,			\
 	  "Use of deprecated SAXv1 function %s\n", n);		\
     deprecated_v1_msg++;
 
@@ -1338,5 +1350,427 @@ cdataBlock(void *ctx, const xmlChar * value, int len)
         xmlSAX2CDataBlock(ctx, value, len);
 }
 
+/*
+ * nanoftp.h
+ */
+
+#ifndef LIBXML_FTP_ENABLED
+
+#include <libxml/nanoftp.h>
+
+/** DOC_DISABLE */
+
+#ifdef _WIN32
+  #include <winsock2.h>
+#else
+  #define SOCKET int
+#endif
+
+typedef void
+(*ftpListCallback)(void *userData, const char *filename, const char *attrib,
+                   const char *owner, const char *group, unsigned long size,
+                   int links, int year, const char *month, int day, int hour,
+                   int minute);
+
+typedef void
+(*ftpDataCallback) (void *userData, const char *data, int len);
+
+XMLPUBFUN void
+xmlNanoFTPInit(void);
+
+void
+xmlNanoFTPInit(void) {
+}
+
+XMLPUBFUN void
+xmlNanoFTPCleanup(void);
+
+void
+xmlNanoFTPCleanup(void) {
+}
+
+XMLPUBFUN void
+xmlNanoFTPProxy(const char *host, int port, const char *user,
+                const char *passwd, int type);
+
+void
+xmlNanoFTPProxy(const char *host ATTRIBUTE_UNUSED, int port ATTRIBUTE_UNUSED,
+                const char *user ATTRIBUTE_UNUSED,
+	        const char *passwd ATTRIBUTE_UNUSED, int type ATTRIBUTE_UNUSED) {
+}
+
+XMLPUBFUN int
+xmlNanoFTPUpdateURL(void *ctx, const char *URL);
+
+int
+xmlNanoFTPUpdateURL(void *ctx ATTRIBUTE_UNUSED,
+                    const char *URL ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN void
+xmlNanoFTPScanProxy(const char *URL);
+
+void
+xmlNanoFTPScanProxy(const char *URL ATTRIBUTE_UNUSED) {
+}
+
+XMLPUBFUN void *
+xmlNanoFTPNewCtxt(const char *URL);
+
+void*
+xmlNanoFTPNewCtxt(const char *URL ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN void
+xmlNanoFTPFreeCtxt(void *ctx);
+
+void
+xmlNanoFTPFreeCtxt(void * ctx ATTRIBUTE_UNUSED) {
+}
+
+XMLPUBFUN int
+xmlNanoFTPGetResponse(void *ctx);
+
+int
+xmlNanoFTPGetResponse(void *ctx ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN int
+xmlNanoFTPCheckResponse(void *ctx);
+
+int
+xmlNanoFTPCheckResponse(void *ctx ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN int
+xmlNanoFTPQuit(void *ctx);
+
+int
+xmlNanoFTPQuit(void *ctx ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN int
+xmlNanoFTPConnect(void *ctx);
+
+int
+xmlNanoFTPConnect(void *ctx ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN void *
+xmlNanoFTPConnectTo(const char *server, int port);
+
+void*
+xmlNanoFTPConnectTo(const char *server ATTRIBUTE_UNUSED,
+                    int port ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN int
+xmlNanoFTPCwd(void *ctx, const char *directory);
+
+int
+xmlNanoFTPCwd(void *ctx ATTRIBUTE_UNUSED,
+              const char *directory ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN int
+xmlNanoFTPDele(void *ctx, const char *file);
+
+int
+xmlNanoFTPDele(void *ctx ATTRIBUTE_UNUSED, const char *file ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN SOCKET
+xmlNanoFTPGetConnection(void *ctx);
+
+SOCKET
+xmlNanoFTPGetConnection(void *ctx ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN int
+xmlNanoFTPCloseConnection(void *ctx);
+
+int
+xmlNanoFTPCloseConnection(void *ctx ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN int
+xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData,
+	       const char *filename);
+
+int
+xmlNanoFTPList(void *ctx ATTRIBUTE_UNUSED,
+               ftpListCallback callback ATTRIBUTE_UNUSED,
+               void *userData ATTRIBUTE_UNUSED,
+	       const char *filename ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN SOCKET
+xmlNanoFTPGetSocket(void *ctx, const char *filename);
+
+SOCKET
+xmlNanoFTPGetSocket(void *ctx ATTRIBUTE_UNUSED,
+                    const char *filename ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN int
+xmlNanoFTPGet(void *ctx, ftpDataCallback callback, void *userData,
+	      const char *filename);
+
+int
+xmlNanoFTPGet(void *ctx ATTRIBUTE_UNUSED,
+              ftpDataCallback callback ATTRIBUTE_UNUSED,
+              void *userData ATTRIBUTE_UNUSED,
+	      const char *filename ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN int
+xmlNanoFTPRead(void *ctx, void *dest, int len);
+
+int
+xmlNanoFTPRead(void *ctx ATTRIBUTE_UNUSED, void *dest ATTRIBUTE_UNUSED,
+               int len ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN void *
+xmlNanoFTPOpen(const char *URL);
+
+void*
+xmlNanoFTPOpen(const char *URL ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN int
+xmlNanoFTPClose(void *ctx);
+
+int
+xmlNanoFTPClose(void *ctx ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN int
+xmlIOFTPMatch(const char *filename);
+
+int
+xmlIOFTPMatch(const char *filename ATTRIBUTE_UNUSED) {
+    return(0);
+}
+
+XMLPUBFUN void *
+xmlIOFTPOpen(const char *filename);
+
+void *
+xmlIOFTPOpen(const char *filename ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN int
+xmlIOFTPRead(void *context, char *buffer, int len);
+
+int
+xmlIOFTPRead(void *context ATTRIBUTE_UNUSED, char *buffer ATTRIBUTE_UNUSED,
+             int len ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+XMLPUBFUN int
+xmlIOFTPClose(void *context);
+
+int
+xmlIOFTPClose(void *context ATTRIBUTE_UNUSED) {
+    return(-1);
+}
+
+/** DOC_ENABLE */
+
+#endif /* #ifndef LIBXML_FTP_ENABLED */
+
+/*
+ * xpointer.h
+ */
+
+#ifndef LIBXML_XPTR_LOCS_ENABLED
+
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/xpointer.h>
+
+/** DOC_DISABLE */
+
+typedef struct _xmlLocationSet *xmlLocationSetPtr;
+
+XMLPUBFUN xmlXPathObjectPtr
+xmlXPtrNewRange(xmlNodePtr start, int startindex,
+                xmlNodePtr end, int endindex);
+
+xmlXPathObjectPtr
+xmlXPtrNewRange(xmlNodePtr start ATTRIBUTE_UNUSED,
+                int startindex ATTRIBUTE_UNUSED,
+                xmlNodePtr end ATTRIBUTE_UNUSED,
+                int endindex ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN xmlXPathObjectPtr
+xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end);
+
+xmlXPathObjectPtr
+xmlXPtrNewRangePoints(xmlXPathObjectPtr start ATTRIBUTE_UNUSED,
+                      xmlXPathObjectPtr end ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN xmlXPathObjectPtr
+xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end);
+
+xmlXPathObjectPtr
+xmlXPtrNewRangePointNode(xmlXPathObjectPtr start ATTRIBUTE_UNUSED,
+                         xmlNodePtr end ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN xmlXPathObjectPtr
+xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end);
+
+xmlXPathObjectPtr
+xmlXPtrNewRangeNodePoint(xmlNodePtr start ATTRIBUTE_UNUSED,
+                         xmlXPathObjectPtr end ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN xmlXPathObjectPtr
+xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end);
+
+xmlXPathObjectPtr
+xmlXPtrNewRangeNodes(xmlNodePtr start ATTRIBUTE_UNUSED,
+                     xmlNodePtr end ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN xmlXPathObjectPtr
+xmlXPtrNewCollapsedRange(xmlNodePtr start);
+
+xmlXPathObjectPtr
+xmlXPtrNewCollapsedRange(xmlNodePtr start ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN xmlXPathObjectPtr
+xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end);
+
+xmlXPathObjectPtr
+xmlXPtrNewRangeNodeObject(xmlNodePtr start ATTRIBUTE_UNUSED,
+                          xmlXPathObjectPtr end ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN xmlLocationSetPtr
+xmlXPtrLocationSetCreate(xmlXPathObjectPtr val);
+
+xmlLocationSetPtr
+xmlXPtrLocationSetCreate(xmlXPathObjectPtr val ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN void
+xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val);
+
+void
+xmlXPtrLocationSetAdd(xmlLocationSetPtr cur ATTRIBUTE_UNUSED,
+                      xmlXPathObjectPtr val ATTRIBUTE_UNUSED) {
+}
+
+XMLPUBFUN xmlLocationSetPtr
+xmlXPtrLocationSetMerge(xmlLocationSetPtr val1, xmlLocationSetPtr val2);
+
+xmlLocationSetPtr
+xmlXPtrLocationSetMerge(xmlLocationSetPtr val1 ATTRIBUTE_UNUSED,
+                        xmlLocationSetPtr val2 ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN void
+xmlXPtrLocationSetDel(xmlLocationSetPtr cur, xmlXPathObjectPtr val);
+
+void
+xmlXPtrLocationSetDel(xmlLocationSetPtr cur ATTRIBUTE_UNUSED,
+                      xmlXPathObjectPtr val ATTRIBUTE_UNUSED) {
+}
+
+XMLPUBFUN void
+xmlXPtrLocationSetRemove(xmlLocationSetPtr cur, int val);
+
+void
+xmlXPtrLocationSetRemove(xmlLocationSetPtr cur ATTRIBUTE_UNUSED,
+                         int val ATTRIBUTE_UNUSED) {
+}
+
+XMLPUBFUN void
+xmlXPtrFreeLocationSet(xmlLocationSetPtr obj);
+
+void
+xmlXPtrFreeLocationSet(xmlLocationSetPtr obj ATTRIBUTE_UNUSED) {
+}
+
+XMLPUBFUN xmlXPathObjectPtr
+xmlXPtrNewLocationSetNodes(xmlNodePtr start, xmlNodePtr end);
+
+xmlXPathObjectPtr
+xmlXPtrNewLocationSetNodes(xmlNodePtr start ATTRIBUTE_UNUSED,
+                           xmlNodePtr end ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN xmlXPathObjectPtr
+xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set);
+
+xmlXPathObjectPtr
+xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN xmlXPathObjectPtr
+xmlXPtrWrapLocationSet(xmlLocationSetPtr val);
+
+xmlXPathObjectPtr
+xmlXPtrWrapLocationSet(xmlLocationSetPtr val ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN xmlNodePtr
+xmlXPtrBuildNodeList(xmlXPathObjectPtr obj);
+
+xmlNodePtr
+xmlXPtrBuildNodeList(xmlXPathObjectPtr obj ATTRIBUTE_UNUSED) {
+    return(NULL);
+}
+
+XMLPUBFUN void
+xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, int nargs);
+
+void
+xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt,
+                       int nargs ATTRIBUTE_UNUSED) {
+    XP_ERROR(XPATH_EXPR_ERROR);
+}
+
+/** DOC_ENABLE */
+
+#endif /* #ifndef LIBXML_XPTR_LOCS_ENABLED */
+
 #endif /* LIBXML_LEGACY_ENABLED */
 
diff --git a/libxml.h b/libxml.h
index 66f164d544b3a2a269846cce32f25cf6158e21e7..d94677b56693c759a5d1d35298ac1816800256a8 100644
--- a/libxml.h
+++ b/libxml.h
@@ -14,103 +14,57 @@
  * Do not add any #include directives above this block.
  */
 #ifndef NO_LARGEFILE_SOURCE
-#ifndef _LARGEFILE_SOURCE
-#define _LARGEFILE_SOURCE
-#endif
-#ifndef _FILE_OFFSET_BITS
-#define _FILE_OFFSET_BITS 64
-#endif
+  #ifndef _LARGEFILE_SOURCE
+    #define _LARGEFILE_SOURCE
+  #endif
+  #ifndef _FILE_OFFSET_BITS
+    #define _FILE_OFFSET_BITS 64
+  #endif
 #endif
 
 /*
- * Currently supported platforms use either autoconf or
- * copy to config.h own "preset" configuration file.
- * As result ifdef HAVE_CONFIG_H is omitted here.
+ * These files are generated by the build system and contain private
+ * and public build configuration.
  */
 #include "config.h"
 #include <libxml/xmlversion.h>
-#include <libxml/xmlstring.h>
 
+/*
+ * Due to some Autotools limitations, this variable must be passed as
+ * compiler flag. Define a default value if the macro wasn't set by the
+ * build system.
+ */
 #ifndef SYSCONFDIR
   #define SYSCONFDIR "/etc"
 #endif
 
-#if defined(__Lynx__)
-#include <stdio.h> /* pull definition of size_t */
-#include <varargs.h>
-int snprintf(char *, size_t, const char *, ...);
-int vfprintf(FILE *, const char *, va_list);
-#endif
-
-#ifndef WITH_TRIO
-#include <stdio.h>
+#if !defined(_WIN32) && \
+    !defined(__CYGWIN__) && \
+    (defined(__clang__) || \
+     (defined(__GNUC__) && (__GNUC__ >= 4)))
+  #define XML_HIDDEN __attribute__((visibility("hidden")))
 #else
-/**
- * TRIO_REPLACE_STDIO:
- *
- * This macro is defined if the trio string formatting functions are to
- * be used instead of the default stdio ones.
- */
-#define TRIO_REPLACE_STDIO
-#include "trio.h"
+  #define XML_HIDDEN
 #endif
 
 #if defined(__clang__) || \
-    (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
-#define XML_IGNORE_PEDANTIC_WARNINGS \
-    _Pragma("GCC diagnostic push") \
-    _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
-#define XML_POP_WARNINGS \
-    _Pragma("GCC diagnostic pop")
+    (defined(__GNUC__) && (__GNUC__ >= 8) && !defined(__EDG__))
+  #define ATTRIBUTE_NO_SANITIZE(arg) __attribute__((no_sanitize(arg)))
 #else
-#define XML_IGNORE_PEDANTIC_WARNINGS
-#define XML_POP_WARNINGS
+  #define ATTRIBUTE_NO_SANITIZE(arg)
 #endif
 
-#if defined(__clang__) || \
-    (defined(__GNUC__) && (__GNUC__ >= 8))
-#define ATTRIBUTE_NO_SANITIZE(arg) __attribute__((no_sanitize(arg)))
+#ifdef __clang__
+  #if __clang_major__ >= 12
+    #define ATTRIBUTE_NO_SANITIZE_INTEGER \
+      ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") \
+      ATTRIBUTE_NO_SANITIZE("unsigned-shift-base")
+  #else
+    #define ATTRIBUTE_NO_SANITIZE_INTEGER \
+      ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
+  #endif
 #else
-#define ATTRIBUTE_NO_SANITIZE(arg)
-#endif
-
-/*
- * Internal variable indicating if a callback has been registered for
- * node creation/destruction. It avoids spending a lot of time in locking
- * function while checking if the callback exists.
- */
-extern int __xmlRegisterCallbacks;
-/*
- * internal error reporting routines, shared but not part of the API.
- */
-void __xmlIOErr(int domain, int code, const char *extra);
-void __xmlLoaderErr(void *ctx, const char *msg, const char *filename) LIBXML_ATTR_FORMAT(2,0);
-#ifdef LIBXML_HTML_ENABLED
-/*
- * internal function of HTML parser needed for xmlParseInNodeContext
- * but not part of the API
- */
-void __htmlParseContent(void *ctx);
+  #define ATTRIBUTE_NO_SANITIZE_INTEGER
 #endif
 
-/*
- * internal global initialization critical section routines.
- */
-void __xmlGlobalInitMutexLock(void);
-void __xmlGlobalInitMutexUnlock(void);
-void __xmlGlobalInitMutexDestroy(void);
-
-int __xmlInitializeDict(void);
-
-/*
- * internal thread safe random function
- */
-int __xmlRandom(void);
-
-XMLPUBFUN xmlChar * XMLCALL xmlEscapeFormatString(xmlChar **msg);
-int xmlInputReadCallbackNop(void *context, char *buffer, int len);
-
-#if !defined(PIC) && !defined(NOLIBTOOL) && !defined(LIBXML_STATIC)
-#  define LIBXML_STATIC
-#endif
 #endif /* ! __XML_LIBXML_H__ */
diff --git a/list.c b/list.c
index 12a7c009277cff091ccaf0ad090964e952ed2ba8..20df26c87c7c324fe85d6e835972bbf82780e19e 100644
--- a/list.c
+++ b/list.c
@@ -21,8 +21,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <libxml/xmlmemory.h>
+#include <libxml/xmlerror.h>
 #include <libxml/list.h>
-#include <libxml/globals.h>
 
 /*
  * Type definition are kept internal
@@ -188,18 +188,13 @@ xmlListPtr
 xmlListCreate(xmlListDeallocator deallocator, xmlListDataCompare compare)
 {
     xmlListPtr l;
-    if (NULL == (l = (xmlListPtr )xmlMalloc( sizeof(xmlList)))) {
-        xmlGenericError(xmlGenericErrorContext,
-		        "Cannot initialize memory for list");
+    if (NULL == (l = (xmlListPtr )xmlMalloc( sizeof(xmlList))))
         return (NULL);
-    }
     /* Initialize the list to NULL */
     memset(l, 0, sizeof(xmlList));
 
     /* Add the sentinel */
     if (NULL ==(l->sentinel = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) {
-        xmlGenericError(xmlGenericErrorContext,
-		        "Cannot initialize memory for sentinel");
 	xmlFree(l);
         return (NULL);
     }
@@ -279,11 +274,8 @@ xmlListInsert(xmlListPtr l, void *data)
     lkPlace = xmlListLowerSearch(l, data);
     /* Add the new link */
     lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink));
-    if (lkNew == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-		        "Cannot initialize memory for new link");
+    if (lkNew == NULL)
         return (1);
-    }
     lkNew->data = data;
     lkPlace = lkPlace->prev;
     lkNew->next = lkPlace->next;
@@ -311,11 +303,8 @@ int xmlListAppend(xmlListPtr l, void *data)
     lkPlace = xmlListHigherSearch(l, data);
     /* Add the new link */
     lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink));
-    if (lkNew == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-		        "Cannot initialize memory for new link");
+    if (lkNew == NULL)
         return (1);
-    }
     lkNew->data = data;
     lkNew->next = lkPlace->next;
     (lkPlace->next)->prev = lkNew;
@@ -548,11 +537,8 @@ xmlListPushFront(xmlListPtr l, void *data)
     lkPlace = l->sentinel;
     /* Add the new link */
     lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink));
-    if (lkNew == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-		        "Cannot initialize memory for new link");
+    if (lkNew == NULL)
         return (0);
-    }
     lkNew->data = data;
     lkNew->next = lkPlace->next;
     (lkPlace->next)->prev = lkNew;
@@ -579,11 +565,8 @@ xmlListPushBack(xmlListPtr l, void *data)
         return(0);
     lkPlace = l->sentinel->prev;
     /* Add the new link */
-    if (NULL ==(lkNew = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) {
-        xmlGenericError(xmlGenericErrorContext,
-		        "Cannot initialize memory for new link");
+    if (NULL ==(lkNew = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink))))
         return (0);
-    }
     lkNew->data = data;
     lkNew->next = lkPlace->next;
     (lkPlace->next)->prev = lkNew;
@@ -729,7 +712,7 @@ xmlListMerge(xmlListPtr l1, xmlListPtr l2)
  * Returns a new copy of the list or NULL in case of error
  */
 xmlListPtr
-xmlListDup(const xmlListPtr old)
+xmlListDup(xmlListPtr old)
 {
     xmlListPtr cur;
 
@@ -758,7 +741,7 @@ xmlListDup(const xmlListPtr old)
  * Returns 0 in case of success 1 in case of error
  */
 int
-xmlListCopy(xmlListPtr cur, const xmlListPtr old)
+xmlListCopy(xmlListPtr cur, xmlListPtr old)
 {
     /* Walk the old tree and insert the data into the new one */
     xmlLinkPtr lk;
diff --git a/nanoftp.c b/nanoftp.c
index 6de7d300a3abce5e9a4894a378d512bcf0b683b7..fc8f8d751458a58b853da69b2cba05deb0e4e4e4 100644
--- a/nanoftp.c
+++ b/nanoftp.c
@@ -23,6 +23,8 @@
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#elif defined (_WIN32)
+#include <io.h>
 #endif
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
@@ -48,24 +50,15 @@
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
 
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/xmlerror.h>
 #include <libxml/uri.h>
 #include <libxml/nanoftp.h>
-#include <libxml/globals.h>
-
-/* #define DEBUG_FTP 1  */
-#ifdef STANDALONE
-#ifndef DEBUG_FTP
-#define DEBUG_FTP 1
-#endif
-#endif
 
+#include "private/error.h"
+#include "private/io.h"
 
 #if defined(_WIN32)
 #include <wsockcompat.h>
@@ -75,27 +68,16 @@
  * A couple portability macros
  */
 #ifndef _WINSOCKAPI_
-#if !defined(__BEOS__) || defined(__HAIKU__)
 #define closesocket(s) close(s)
 #endif
-#endif
-
-#ifdef __BEOS__
-#ifndef PF_INET
-#define PF_INET AF_INET
-#endif
-#endif
-
-#ifdef _AIX
-#ifdef HAVE_BROKEN_SS_FAMILY
-#define ss_family __ss_family
-#endif
-#endif
 
 #ifndef XML_SOCKLEN_T
 #define XML_SOCKLEN_T unsigned int
 #endif
 
+#define GETHOSTBYNAME_ARG_CAST (char *)
+#define SEND_ARG2_CAST (char *)
+
 #define FTP_COMMAND_OK		200
 #define FTP_SYNTAX_ERROR	500
 #define FTP_GET_PASSWD		331
@@ -155,9 +137,9 @@ int have_ipv6(void) {
  * Handle an out of memory condition
  */
 static void
-xmlFTPErrMemory(const char *extra)
+xmlFTPErrMemory(const char *extra ATTRIBUTE_UNUSED)
 {
-    __xmlSimpleError(XML_FROM_FTP, XML_ERR_NO_MEMORY, NULL, NULL, extra);
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_FTP, NULL);
 }
 
 /**
@@ -417,14 +399,6 @@ xmlNanoFTPScanProxy(const char *URL) {
     }
     proxyPort = 0;
 
-#ifdef DEBUG_FTP
-    if (URL == NULL)
-	xmlGenericError(xmlGenericErrorContext,
-		"Removing FTP proxy info\n");
-    else
-	xmlGenericError(xmlGenericErrorContext,
-		"Using FTP proxy %s\n", URL);
-#endif
     if (URL == NULL) return;
 
     uri = xmlParseURIRaw(URL, 1);
@@ -557,28 +531,13 @@ xmlNanoFTPGetMore(void *ctx) {
     if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
 
     if ((ctxt->controlBufIndex < 0) || (ctxt->controlBufIndex > FTP_BUF_SIZE)) {
-#ifdef DEBUG_FTP
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPGetMore : controlBufIndex = %d\n",
-		ctxt->controlBufIndex);
-#endif
 	return(-1);
     }
 
     if ((ctxt->controlBufUsed < 0) || (ctxt->controlBufUsed > FTP_BUF_SIZE)) {
-#ifdef DEBUG_FTP
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPGetMore : controlBufUsed = %d\n",
-		ctxt->controlBufUsed);
-#endif
 	return(-1);
     }
     if (ctxt->controlBufIndex > ctxt->controlBufUsed) {
-#ifdef DEBUG_FTP
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPGetMore : controlBufIndex > controlBufUsed %d > %d\n",
-	       ctxt->controlBufIndex, ctxt->controlBufUsed);
-#endif
 	return(-1);
     }
 
@@ -593,10 +552,6 @@ xmlNanoFTPGetMore(void *ctx) {
     }
     size = FTP_BUF_SIZE - ctxt->controlBufUsed;
     if (size == 0) {
-#ifdef DEBUG_FTP
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPGetMore : buffer full %d \n", ctxt->controlBufUsed);
-#endif
 	return(0);
     }
 
@@ -610,11 +565,6 @@ xmlNanoFTPGetMore(void *ctx) {
         ctxt->controlFd = INVALID_SOCKET;
         return(-1);
     }
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext,
-	    "xmlNanoFTPGetMore : read %d [%d - %d]\n", len,
-	   ctxt->controlBufUsed, ctxt->controlBufUsed + len);
-#endif
     ctxt->controlBufUsed += len;
     ctxt->controlBuf[ctxt->controlBufUsed] = 0;
 
@@ -652,10 +602,6 @@ get_more:
     ptr = &ctxt->controlBuf[ctxt->controlBufIndex];
     end = &ctxt->controlBuf[ctxt->controlBufUsed];
 
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext,
-	    "\n<<<\n%s\n--\n", ptr);
-#endif
     while (ptr < end) {
         cur = xmlNanoFTPParseResponse(ptr, end - ptr);
 	if (cur > 0) {
@@ -682,14 +628,7 @@ get_more:
 
     if (res < 0) goto get_more;
     ctxt->controlBufIndex = ptr - ctxt->controlBuf;
-#ifdef DEBUG_FTP
-    ptr = &ctxt->controlBuf[ctxt->controlBufIndex];
-    xmlGenericError(xmlGenericErrorContext, "\n---\n%s\n--\n", ptr);
-#endif
 
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "Got %d\n", res);
-#endif
     return(res / 100);
 }
 
@@ -758,9 +697,6 @@ xmlNanoFTPSendUser(void *ctx) {
 	snprintf(buf, sizeof(buf), "USER %s\r\n", ctxt->user);
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -786,9 +722,6 @@ xmlNanoFTPSendPasswd(void *ctx) {
 	snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -817,9 +750,6 @@ xmlNanoFTPQuit(void *ctx) {
 
     snprintf(buf, sizeof(buf), "QUIT\r\n");
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf); /* Just to be consistent, even though we know it can't have a % in it */
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1013,9 +943,6 @@ xmlNanoFTPConnect(void *ctx) {
 	    snprintf(buf, sizeof(buf), "USER %s\r\n", proxyUser);
             buf[sizeof(buf) - 1] = 0;
             len = strlen(buf);
-#ifdef DEBUG_FTP
-	    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 	    res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 	    if (res < 0) {
 		__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1036,9 +963,6 @@ xmlNanoFTPConnect(void *ctx) {
 			snprintf(buf, sizeof(buf), "PASS anonymous@\r\n");
                     buf[sizeof(buf) - 1] = 0;
                     len = strlen(buf);
-#ifdef DEBUG_FTP
-		    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 		    res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 		    if (res < 0) {
 			__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1077,9 +1001,6 @@ xmlNanoFTPConnect(void *ctx) {
 		snprintf(buf, sizeof(buf), "SITE %s\r\n", ctxt->hostname);
                 buf[sizeof(buf) - 1] = 0;
                 len = strlen(buf);
-#ifdef DEBUG_FTP
-		xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 		res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 		if (res < 0) {
 		    __xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1109,9 +1030,6 @@ xmlNanoFTPConnect(void *ctx) {
 			           ctxt->user, ctxt->hostname);
                 buf[sizeof(buf) - 1] = 0;
                 len = strlen(buf);
-#ifdef DEBUG_FTP
-		xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 		res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 		if (res < 0) {
 		    __xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1131,9 +1049,6 @@ xmlNanoFTPConnect(void *ctx) {
 		    snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);
                 buf[sizeof(buf) - 1] = 0;
                 len = strlen(buf);
-#ifdef DEBUG_FTP
-		xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 		res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 		if (res < 0) {
 		    __xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1282,9 +1197,6 @@ xmlNanoFTPCwd(void *ctx, const char *directory) {
     snprintf(buf, sizeof(buf), "CWD %s\r\n", directory);
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1333,9 +1245,6 @@ xmlNanoFTPDele(void *ctx, const char *file) {
     snprintf(buf, sizeof(buf), "DELE %s\r\n", file);
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1405,9 +1314,6 @@ xmlNanoFTPGetConnection(void *ctx) {
 #endif
 	    snprintf (buf, sizeof(buf), "PASV\r\n");
         len = strlen (buf);
-#ifdef DEBUG_FTP
-	xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 	res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 	if (res < 0) {
 	    __xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1505,9 +1411,6 @@ xmlNanoFTPGetConnection(void *ctx) {
 
         buf[sizeof(buf) - 1] = 0;
         len = strlen(buf);
-#ifdef DEBUG_FTP
-	xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 
 	res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 	if (res < 0) {
@@ -1552,17 +1455,10 @@ xmlNanoFTPCloseConnection(void *ctx) {
     FD_SET(ctxt->controlFd, &efd);
     res = select(ctxt->controlFd + 1, &rfd, NULL, &efd, &tv);
     if (res < 0) {
-#ifdef DEBUG_FTP
-	perror("select");
-#endif
 	closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
 	return(-1);
     }
     if (res == 0) {
-#ifdef DEBUG_FTP
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPCloseConnection: timeout\n");
-#endif
 	closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
     } else {
 	res = xmlNanoFTPGetResponse(ctxt);
@@ -1743,9 +1639,6 @@ xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData,
     }
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1767,9 +1660,6 @@ xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData,
 	FD_SET(ctxt->dataFd, &efd);
 	res = select(ctxt->dataFd + 1, &rfd, NULL, &efd, &tv);
 	if (res < 0) {
-#ifdef DEBUG_FTP
-	    perror("select");
-#endif
 	    closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
 	    return(-1);
 	}
@@ -1794,9 +1684,6 @@ xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData,
 	    ctxt->dataFd = INVALID_SOCKET;
 	    return(-1);
 	}
-#ifdef DEBUG_FTP
-        write(1, &buf[indx], len);
-#endif
 	indx += len;
 	buf[indx] = 0;
 	base = 0;
@@ -1838,9 +1725,6 @@ xmlNanoFTPGetSocket(void *ctx, const char *filename) {
 
     snprintf(buf, sizeof(buf), "TYPE I\r\n");
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1858,9 +1742,6 @@ xmlNanoFTPGetSocket(void *ctx, const char *filename) {
 	snprintf(buf, sizeof(buf), "RETR %s\r\n", filename);
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1912,9 +1793,6 @@ xmlNanoFTPGet(void *ctx, ftpDataCallback callback, void *userData,
 	FD_SET(ctxt->dataFd, &rfd);
 	res = select(ctxt->dataFd + 1, &rfd, NULL, NULL, &tv);
 	if (res < 0) {
-#ifdef DEBUG_FTP
-	    perror("select");
-#endif
 	    closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
 	    return(-1);
 	}
@@ -1971,9 +1849,6 @@ xmlNanoFTPRead(void *ctx, void *dest, int len) {
 	    __xmlIOErr(XML_FROM_FTP, 0, "recv failed");
 	xmlNanoFTPCloseConnection(ctxt);
     }
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "Recvd %d bytes\n", len);
-#endif
     return(len);
 }
 
@@ -2048,7 +1923,7 @@ static
 void ftpList(void *userData, const char *filename, const char* attrib,
 	     const char *owner, const char *group, unsigned long size, int links,
 	     int year, const char *month, int day, int hour, int minute) {
-    xmlGenericError(xmlGenericErrorContext,
+    fprintf(stderr,
 	    "%s %s %s %ld %s\n", attrib, owner, group, size, filename);
 }
 static
@@ -2070,7 +1945,7 @@ int main(int argc, char **argv) {
     if (argc > 1) {
 	ctxt = xmlNanoFTPNewCtxt(argv[1]);
 	if (xmlNanoFTPConnect(ctxt) < 0) {
-	    xmlGenericError(xmlGenericErrorContext,
+	    fprintf(stderr,
 		    "Couldn't connect to %s\n", argv[1]);
 	    exit(1);
 	}
@@ -2079,7 +1954,7 @@ int main(int argc, char **argv) {
     } else
 	ctxt = xmlNanoFTPConnectTo("localhost", 0);
     if (ctxt == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
 		"Couldn't connect to localhost\n");
         exit(1);
     }
@@ -2087,12 +1962,11 @@ int main(int argc, char **argv) {
     output = fopen("/tmp/tstdata", "w");
     if (output != NULL) {
 	if (xmlNanoFTPGet(ctxt, ftpData, (void *) output, tstfile) < 0)
-	    xmlGenericError(xmlGenericErrorContext,
+	    fprintf(stderr,
 		    "Failed to get file\n");
 
     }
     xmlNanoFTPClose(ctxt);
-    xmlMemoryDump();
     exit(0);
 }
 #endif /* STANDALONE */
@@ -2100,7 +1974,7 @@ int main(int argc, char **argv) {
 #ifdef STANDALONE
 #include <stdio.h>
 int main(int argc, char **argv) {
-    xmlGenericError(xmlGenericErrorContext,
+    fprintf(stderr,
 	    "%s : FTP support not compiled in\n", argv[0]);
     return(0);
 }
diff --git a/nanohttp.c b/nanohttp.c
index 2eafd3f4910f68990870bbf29b453c3af045d596..5c67893058433444da1345a5299eeed732a65341 100644
--- a/nanohttp.c
+++ b/nanohttp.c
@@ -16,14 +16,14 @@
 
 #ifdef LIBXML_HTTP_ENABLED
 #include <string.h>
+#include <ctype.h>
 #include <stdlib.h>
 #include <errno.h>
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
+#elif defined (_WIN32)
+#include <io.h>
 #endif
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
@@ -37,12 +37,6 @@
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif
-#ifdef HAVE_RESOLV_H
-#ifdef HAVE_ARPA_NAMESER_H
-#include <arpa/nameser.h>
-#endif
-#include <resolv.h>
-#endif
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
@@ -70,37 +64,32 @@
 #include <wsockcompat.h>
 #endif
 
-#include <libxml/globals.h>
 #include <libxml/xmlerror.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h> /* for xmlStr(n)casecmp() */
 #include <libxml/nanohttp.h>
-#include <libxml/globals.h>
 #include <libxml/uri.h>
 
+#include "private/error.h"
+#include "private/io.h"
+
 /**
  * A couple portability macros
  */
 #ifndef _WINSOCKAPI_
-#if !defined(__BEOS__) || defined(__HAIKU__)
 #define closesocket(s) close(s)
-#endif
 #define SOCKET int
 #define INVALID_SOCKET (-1)
 #endif
 
-#ifdef __BEOS__
-#ifndef PF_INET
-#define PF_INET AF_INET
-#endif
-#endif
-
 #ifndef XML_SOCKLEN_T
 #define XML_SOCKLEN_T unsigned int
 #endif
 
+#define GETHOSTBYNAME_ARG_CAST (char *)
+#define SEND_ARG2_CAST (char *)
+
 #ifdef STANDALONE
-#define DEBUG_HTTP
 #define xmlStrncasecmp(a, b, n) strncasecmp((char *)a, (char *)b, n)
 #define xmlStrcasecmpi(a, b) strcasecmp((char *)a, (char *)b)
 #endif
@@ -158,9 +147,9 @@ static int xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len );
  * Handle an out of memory condition
  */
 static void
-xmlHTTPErrMemory(const char *extra)
+xmlHTTPErrMemory(void)
 {
-    __xmlSimpleError(XML_FROM_HTTP, XML_ERR_NO_MEMORY, NULL, NULL, extra);
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_HTTP, NULL);
 }
 
 /**
@@ -188,20 +177,6 @@ static int socket_errno(void) {
 #endif
 }
 
-#ifdef SUPPORT_IP6
-static
-int have_ipv6(void) {
-    SOCKET s;
-
-    s = socket (AF_INET6, SOCK_STREAM, 0);
-    if (s != INVALID_SOCKET) {
-	close (s);
-	return (1);
-    }
-    return (0);
-}
-#endif
-
 /**
  * xmlNanoHTTPInit:
  *
@@ -350,14 +325,6 @@ xmlNanoHTTPScanProxy(const char *URL) {
     }
     proxyPort = 0;
 
-#ifdef DEBUG_HTTP
-    if (URL == NULL)
-	xmlGenericError(xmlGenericErrorContext,
-		"Removing HTTP proxy info\n");
-    else
-	xmlGenericError(xmlGenericErrorContext,
-		"Using HTTP proxy %s\n", URL);
-#endif
     if (URL == NULL) return;
 
     uri = xmlParseURIRaw(URL, 1);
@@ -391,7 +358,7 @@ xmlNanoHTTPNewCtxt(const char *URL) {
 
     ret = (xmlNanoHTTPCtxtPtr) xmlMalloc(sizeof(xmlNanoHTTPCtxt));
     if (ret == NULL) {
-        xmlHTTPErrMemory("allocating context");
+        xmlHTTPErrMemory();
         return(NULL);
     }
 
@@ -535,9 +502,9 @@ xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt)
 
     while (ctxt->state & XML_NANO_HTTP_READ) {
         if (ctxt->in == NULL) {
-            ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char));
+            ctxt->in = (char *) xmlMallocAtomic(65000);
             if (ctxt->in == NULL) {
-                xmlHTTPErrMemory("allocating input");
+                xmlHTTPErrMemory();
                 ctxt->last = -1;
                 return (-1);
             }
@@ -562,7 +529,7 @@ xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt)
             ctxt->inlen *= 2;
             ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen);
             if (ctxt->in == NULL) {
-                xmlHTTPErrMemory("allocating input buffer");
+                xmlHTTPErrMemory();
                 xmlFree(tmp_ptr);
                 ctxt->last = -1;
                 return (-1);
@@ -876,9 +843,6 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
         addrlen = sizeof(struct sockaddr_in);
     }
     if (s == INVALID_SOCKET) {
-#ifdef DEBUG_HTTP
-        perror("socket");
-#endif
         __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n");
         return INVALID_SOCKET;
     }
@@ -896,15 +860,6 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
         status = ioctl(s, FIONBIO, &enable);
     }
 #else /* VMS */
-#if defined(__BEOS__) && !defined(__HAIKU__)
-    {
-        bool noblock = true;
-
-        status =
-            setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock,
-                       sizeof(noblock));
-    }
-#else /* __BEOS__ */
     if ((status = fcntl(s, F_GETFL, 0)) != -1) {
 #ifdef O_NONBLOCK
         status |= O_NONBLOCK;
@@ -916,14 +871,10 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
         status = fcntl(s, F_SETFL, status);
     }
     if (status < 0) {
-#ifdef DEBUG_HTTP
-        perror("nonblocking");
-#endif
         __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n");
         closesocket(s);
         return INVALID_SOCKET;
     }
-#endif /* !__BEOS__ */
 #endif /* !VMS */
 #endif /* !_WINSOCKAPI_ */
 
@@ -1042,33 +993,19 @@ xmlNanoHTTPConnectHost(const char *host, int port)
     struct sockaddr_in sockin;
 
 #ifdef SUPPORT_IP6
-    struct in6_addr ia6;
     struct sockaddr_in6 sockin6;
 #endif
     SOCKET s;
 
     memset (&sockin, 0, sizeof(sockin));
-#ifdef SUPPORT_IP6
-    memset (&sockin6, 0, sizeof(sockin6));
-#endif
-
-#if !defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && defined(RES_USE_INET6)
-    if (have_ipv6 ())
-    {
-	if (!(_res.options & RES_INIT))
-	    res_init();
-	_res.options |= RES_USE_INET6;
-    }
-#endif
 
-#if defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && !defined(_WIN32)
-    if (have_ipv6 ())
-#endif
-#if defined(HAVE_GETADDRINFO) && (defined(SUPPORT_IP6) || defined(_WIN32))
+#if defined(SUPPORT_IP6)
     {
 	int status;
 	struct addrinfo hints, *res, *result;
 
+        memset (&sockin6, 0, sizeof(sockin6));
+
 	result = NULL;
 	memset (&hints, 0,sizeof(hints));
 	hints.ai_socktype = SOCK_STREAM;
@@ -1089,8 +1026,7 @@ xmlNanoHTTPConnectHost(const char *host, int port)
 		memcpy (&sockin, res->ai_addr, res->ai_addrlen);
 		sockin.sin_port = htons (port);
 		addr = (struct sockaddr *)&sockin;
-#ifdef SUPPORT_IP6
-	    } else if (have_ipv6 () && (res->ai_family == AF_INET6)) {
+	    } else if (res->ai_family == AF_INET6) {
 		if ((size_t)res->ai_addrlen > sizeof(sockin6)) {
 		    __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
 		    freeaddrinfo (result);
@@ -1099,7 +1035,6 @@ xmlNanoHTTPConnectHost(const char *host, int port)
 		memcpy (&sockin6, res->ai_addr, res->ai_addrlen);
 		sockin6.sin6_port = htons (port);
 		addr = (struct sockaddr *)&sockin6;
-#endif
 	    } else
 		continue;              /* for */
 
@@ -1113,11 +1048,7 @@ xmlNanoHTTPConnectHost(const char *host, int port)
 	if (result)
 	    freeaddrinfo (result);
     }
-#endif
-#if defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && !defined(_WIN32)
-    else
-#endif
-#if !defined(HAVE_GETADDRINFO) || !defined(_WIN32)
+#else
     {
         struct hostent *h;
         struct in_addr ia;
@@ -1179,19 +1110,6 @@ xmlNanoHTTPConnectHost(const char *host, int port)
 		sockin.sin_addr = ia;
 		sockin.sin_port = (unsigned short)htons ((unsigned short)port);
 		addr = (struct sockaddr *) &sockin;
-#ifdef SUPPORT_IP6
-	    } else if (have_ipv6 () && (h->h_addrtype == AF_INET6)) {
-		/* AAAA records (IPv6) */
-		if ((unsigned int) h->h_length > sizeof(ia6)) {
-		    __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
-		    return INVALID_SOCKET;
-		}
-		memcpy (&ia6, h->h_addr_list[i], h->h_length);
-		sockin6.sin6_family = h->h_addrtype;
-		sockin6.sin6_addr = ia6;
-		sockin6.sin6_port = htons (port);
-		addr = (struct sockaddr *) &sockin6;
-#endif
 	    } else
 		break;              /* for */
 
@@ -1202,11 +1120,6 @@ xmlNanoHTTPConnectHost(const char *host, int port)
     }
 #endif
 
-#ifdef DEBUG_HTTP
-    xmlGenericError(xmlGenericErrorContext,
-                    "xmlNanoHTTPConnectHost:  unable to connect to '%s'.\n",
-                    host);
-#endif
     return INVALID_SOCKET;
 }
 
@@ -1306,8 +1219,10 @@ xmlNanoHTTPRead(void *ctx, void *dest, int len) {
     }
     if (ctxt->inptr - ctxt->inrptr < len)
         len = ctxt->inptr - ctxt->inrptr;
-    memcpy(dest, ctxt->inrptr, len);
-    ctxt->inrptr += len;
+    if (len > 0) {
+        memcpy(dest, ctxt->inrptr, len);
+        ctxt->inrptr += len;
+    }
     return(len);
 }
 
@@ -1327,6 +1242,107 @@ xmlNanoHTTPClose(void *ctx) {
     xmlNanoHTTPFreeCtxt(ctxt);
 }
 
+
+/**
+ * xmlNanoHTTPHostnameMatch:
+ * @pattern: The pattern as it appears in no_proxy environment variable
+ * @hostname: The hostname to test as it appears in the URL
+ *
+ * This function tests whether a given hostname matches a pattern. The pattern
+ * usually is a token from the no_proxy environment variable. Wildcards in the
+ * pattern are not supported.
+ *
+ * Returns true, iff hostname matches the pattern.
+ */
+
+static int 
+xmlNanoHTTPHostnameMatch(const char *pattern, const char *hostname) {
+    int idx_pattern, idx_hostname;
+    const char * pattern_start;
+
+    if (!pattern || *pattern == '\0' || !hostname)
+	return 0;
+
+    /* Ignore trailing '.' */
+    if (*pattern == '.') {
+        idx_pattern = strlen(pattern) -1;
+        pattern_start = pattern + 1;
+    }
+    else {
+        idx_pattern = strlen(pattern);
+        pattern_start = pattern;
+    }
+    idx_hostname = strlen(hostname);
+
+    for (; idx_pattern >= 0 && idx_hostname >= 0; 
+           --idx_pattern, --idx_hostname) {
+	if (tolower(pattern_start[idx_pattern]) != tolower(hostname[idx_hostname]))
+	    break;
+    }
+
+    return idx_pattern == -1 && (idx_hostname == -1|| hostname[idx_hostname] == '.');
+}
+
+
+/**
+ * xmlNanoHTTPBypassProxy:
+ * @hostname: The hostname as it appears in the URL
+ *
+ * This function evaluates the no_proxy environment variable and returns
+ * whether the proxy server should be bypassed for a given host.
+ *
+ * Returns true, iff a proxy server should be bypassed for the given hostname.
+ */
+
+static int
+xmlNanoHTTPBypassProxy(const char *hostname) {
+    size_t envlen;
+    char *env = getenv("no_proxy"), *cpy=NULL, *p=NULL;
+    if (!env)
+	return 0;
+
+    /* (Avoid strdup because it's not portable.) */
+    envlen = strlen(env) + 1;
+    cpy = xmlMalloc(envlen);
+    memcpy(cpy, env, envlen);
+    env = cpy;
+
+    /* The remainder of the function is basically a tokenizing: */
+    while (isspace(*env))
+    	++env;
+    if (*env == '\0') {
+    	xmlFree(cpy);
+	return 0;
+    }
+
+    p = env;
+    while (*env) {
+
+    	if (*env != ',') {
+	    ++env;
+	    continue;
+	}
+
+	*(env++) = '\0';
+	if (xmlNanoHTTPHostnameMatch(p, hostname)) {
+	    xmlFree(cpy);
+	    return 1;
+	}
+
+	while (isspace(*env))
+	    ++env;
+	p = env;
+    }
+    if (xmlNanoHTTPHostnameMatch(p, hostname)) {
+    	xmlFree(cpy);
+    	return 1;
+    }
+
+    xmlFree(cpy);
+    return 0;
+}
+
+
 /**
  * xmlNanoHTTPMethodRedir:
  * @URL:  The URL to load
@@ -1354,10 +1370,8 @@ xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input,
     int blen;
     SOCKET ret;
     int nbRedirects = 0;
+    int use_proxy;
     char *redirURL = NULL;
-#ifdef DEBUG_HTTP
-    int xmt_bytes;
-#endif
 
     if (URL == NULL) return(NULL);
     if (method == NULL) method = "GET";
@@ -1376,7 +1390,7 @@ retry:
     }
 
     if ((ctxt->protocol == NULL) || (strcmp(ctxt->protocol, "http"))) {
-	__xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Not a valid HTTP URI");
+	__xmlIOErr(XML_FROM_IO, XML_IO_UNSUPPORTED_PROTOCOL, ctxt->protocol);
         xmlNanoHTTPFreeCtxt(ctxt);
 	if (redirURL != NULL) xmlFree(redirURL);
         return(NULL);
@@ -1388,7 +1402,8 @@ retry:
 	if (redirURL != NULL) xmlFree(redirURL);
         return(NULL);
     }
-    if (proxy) {
+    use_proxy = proxy && !xmlNanoHTTPBypassProxy(ctxt->hostname);
+    if (use_proxy) {
 	blen = strlen(ctxt->hostname) * 2 + 16;
 	ret = xmlNanoHTTPConnectHost(proxy, proxyPort);
     }
@@ -1423,7 +1438,7 @@ retry:
 #endif
     if (ctxt->port != 80) {
 	/* reserve space for ':xxxxx', incl. potential proxy */
-	if (proxy)
+	if (use_proxy)
 	    blen += 17;
 	else
 	    blen += 11;
@@ -1431,13 +1446,13 @@ retry:
     bp = (char*)xmlMallocAtomic(blen);
     if ( bp == NULL ) {
         xmlNanoHTTPFreeCtxt( ctxt );
-	xmlHTTPErrMemory("allocating header buffer");
+	xmlHTTPErrMemory();
 	return ( NULL );
     }
 
     p = bp;
 
-    if (proxy) {
+    if (use_proxy) {
 	if (ctxt->port != 80) {
 	    p += snprintf( p, blen - (p - bp), "%s http://%s:%d%s",
 			method, ctxt->hostname,
@@ -1476,41 +1491,13 @@ retry:
     else
 	snprintf(p, blen - (p - bp), "\r\n");
 
-#ifdef DEBUG_HTTP
-    xmlGenericError(xmlGenericErrorContext,
-	    "-> %s%s", proxy? "(Proxy) " : "", bp);
-    if ((blen -= strlen(bp)+1) < 0)
-	xmlGenericError(xmlGenericErrorContext,
-		"ERROR: overflowed buffer by %d bytes\n", -blen);
-#endif
     ctxt->outptr = ctxt->out = bp;
     ctxt->state = XML_NANO_HTTP_WRITE;
     blen = strlen( ctxt->out );
-#ifdef DEBUG_HTTP
-    xmt_bytes = xmlNanoHTTPSend(ctxt, ctxt->out, blen );
-    if ( xmt_bytes != blen )
-        xmlGenericError( xmlGenericErrorContext,
-			"xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
-			xmt_bytes, blen,
-			"bytes of HTTP headers sent to host",
-			ctxt->hostname );
-#else
     xmlNanoHTTPSend(ctxt, ctxt->out, blen );
-#endif
 
     if ( input != NULL ) {
-#ifdef DEBUG_HTTP
-        xmt_bytes = xmlNanoHTTPSend( ctxt, input, ilen );
-
-	if ( xmt_bytes != ilen )
-	    xmlGenericError( xmlGenericErrorContext,
-			"xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
-			xmt_bytes, ilen,
-			"bytes of HTTP content sent to host",
-			ctxt->hostname );
-#else
 	xmlNanoHTTPSend( ctxt, input, ilen );
-#endif
     }
 
     ctxt->state = XML_NANO_HTTP_READ;
@@ -1523,18 +1510,11 @@ retry:
 	}
 	xmlNanoHTTPScanAnswer(ctxt, p);
 
-#ifdef DEBUG_HTTP
-	xmlGenericError(xmlGenericErrorContext, "<- %s\n", p);
-#endif
         xmlFree(p);
     }
 
     if ((ctxt->location != NULL) && (ctxt->returnValue >= 300) &&
         (ctxt->returnValue < 400)) {
-#ifdef DEBUG_HTTP
-	xmlGenericError(xmlGenericErrorContext,
-		"\nRedirect to: %s\n", ctxt->location);
-#endif
 	while ( xmlNanoHTTPRecv(ctxt) > 0 )
             ;
         if (nbRedirects < XML_NANO_HTTP_MAX_REDIR) {
@@ -1547,10 +1527,6 @@ retry:
 	}
 	xmlNanoHTTPFreeCtxt(ctxt);
 	if (redirURL != NULL) xmlFree(redirURL);
-#ifdef DEBUG_HTTP
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoHTTPMethodRedir: Too many redirects, aborting ...\n");
-#endif
 	return(NULL);
     }
 
@@ -1570,17 +1546,6 @@ retry:
 	    *redir = NULL;
     }
 
-#ifdef DEBUG_HTTP
-    if (ctxt->contentType != NULL)
-	xmlGenericError(xmlGenericErrorContext,
-		"\nCode %d, content-type '%s'\n\n",
-	       ctxt->returnValue, ctxt->contentType);
-    else
-	xmlGenericError(xmlGenericErrorContext,
-		"\nCode %d, no content-type\n\n",
-	       ctxt->returnValue);
-#endif
-
     return((void *) ctxt);
 }
 
@@ -1868,13 +1833,12 @@ int main(int argc, char **argv) {
 	    xmlNanoHTTPFetch(argv[1], "-", &contentType);
 	if (contentType != NULL) xmlFree(contentType);
     } else {
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
 		"%s: minimal HTTP GET implementation\n", argv[0]);
-        xmlGenericError(xmlGenericErrorContext,
+        fprintf(stderr,
 		"\tusage %s [ URL [ filename ] ]\n", argv[0]);
     }
     xmlNanoHTTPCleanup();
-    xmlMemoryDump();
     return(0);
 }
 #endif /* STANDALONE */
@@ -1882,7 +1846,7 @@ int main(int argc, char **argv) {
 #ifdef STANDALONE
 #include <stdio.h>
 int main(int argc, char **argv) {
-    xmlGenericError(xmlGenericErrorContext,
+    fprintf(stderr,
 	    "%s : HTTP support not compiled in\n", argv[0]);
     return(0);
 }
diff --git a/parser.c b/parser.c
index 93f031be863a7de2f814767a86721dadae14343b..365025c5eb94f3811e42d325a6e3b1173a67a032 100644
--- a/parser.c
+++ b/parser.c
@@ -51,11 +51,9 @@
 #include <stddef.h>
 #include <ctype.h>
 #include <stdlib.h>
+#include <libxml/parser.h>
 #include <libxml/xmlmemory.h>
-#include <libxml/threads.h>
-#include <libxml/globals.h>
 #include <libxml/tree.h>
-#include <libxml/parser.h>
 #include <libxml/parserInternals.h>
 #include <libxml/valid.h>
 #include <libxml/entities.h>
@@ -63,16 +61,27 @@
 #include <libxml/encoding.h>
 #include <libxml/xmlIO.h>
 #include <libxml/uri.h>
+#include <libxml/SAX2.h>
 #ifdef LIBXML_CATALOG_ENABLED
 #include <libxml/catalog.h>
 #endif
-#ifdef LIBXML_SCHEMAS_ENABLED
-#include <libxml/xmlschemastypes.h>
-#include <libxml/relaxng.h>
-#endif
 
-#include "buf.h"
-#include "enc.h"
+#include "private/buf.h"
+#include "private/dict.h"
+#include "private/entities.h"
+#include "private/error.h"
+#include "private/html.h"
+#include "private/io.h"
+#include "private/parser.h"
+
+#define NS_INDEX_EMPTY  INT_MAX
+#define NS_INDEX_XML    (INT_MAX - 1)
+#define URI_HASH_EMPTY  0xD943A04E
+#define URI_HASH_XML    0xF0451F02
+
+#ifndef STDIN_FILENO
+  #define STDIN_FILENO 0
+#endif
 
 struct _xmlStartTag {
     const xmlChar *prefix;
@@ -81,14 +90,34 @@ struct _xmlStartTag {
     int nsNr;
 };
 
-static void
-xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
-
-static xmlParserCtxtPtr
-xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
-	                  const xmlChar *base, xmlParserCtxtPtr pctx);
+typedef struct {
+    void *saxData;
+    unsigned prefixHashValue;
+    unsigned uriHashValue;
+    unsigned elementId;
+    int oldIndex;
+} xmlParserNsExtra;
+
+typedef struct {
+    unsigned hashValue;
+    int index;
+} xmlParserNsBucket;
+
+struct _xmlParserNsData {
+    xmlParserNsExtra *extra;
+
+    unsigned hashSize;
+    unsigned hashElems;
+    xmlParserNsBucket *hash;
+
+    unsigned elementId;
+    int defaultNsIndex;
+    int minNsIndex;
+};
 
-static void xmlHaltParser(xmlParserCtxtPtr ctxt);
+struct _xmlAttrHashBucket {
+    int index;
+};
 
 static int
 xmlParseElementStart(xmlParserCtxtPtr ctxt);
@@ -96,6 +125,12 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt);
 static void
 xmlParseElementEnd(xmlParserCtxtPtr ctxt);
 
+static xmlEntityPtr
+xmlLookupGeneralEntity(xmlParserCtxtPtr ctxt, const xmlChar *name, int inAttr);
+
+static const xmlChar *
+xmlParseEntityRefInternal(xmlParserCtxtPtr ctxt);
+
 /************************************************************************
  *									*
  *	Arbitrary limits set in the parser. See XML_PARSE_HUGE		*
@@ -106,156 +141,21 @@ xmlParseElementEnd(xmlParserCtxtPtr ctxt);
 #define XML_PARSER_LOT_ENTITY 5000
 
 /*
- * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
- *    replacement over the size in byte of the input indicates that you have
- *    and exponential behaviour. A value of 10 correspond to at least 3 entity
- *    replacement per byte of input.
+ * Constants for protection against abusive entity expansion
+ * ("billion laughs").
  */
-#define XML_PARSER_NON_LINEAR 10
 
 /*
- * xmlParserEntityCheck
- *
- * Function to check non-linear entity expansion behaviour
- * This is here to detect and stop exponential linear entity expansion
- * This is not a limitation of the parser but a safety
- * boundary feature. It can be disabled with the XML_PARSE_HUGE
- * parser option.
+ * A certain amount of entity expansion which is always allowed.
  */
-static int
-xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
-                     xmlEntityPtr ent, size_t replacement)
-{
-    size_t consumed = 0;
-    int i;
-
-    if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
-        return (0);
-    if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
-        return (1);
-
-    /*
-     * This may look absurd but is needed to detect
-     * entities problems
-     */
-    if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
-	(ent->content != NULL) && (ent->checked == 0) &&
-	(ctxt->errNo != XML_ERR_ENTITY_LOOP)) {
-	unsigned long oldnbent = ctxt->nbentities, diff;
-	xmlChar *rep;
-
-	ent->checked = 1;
-
-        ++ctxt->depth;
-	rep = xmlStringDecodeEntities(ctxt, ent->content,
-				  XML_SUBSTITUTE_REF, 0, 0, 0);
-        --ctxt->depth;
-	if ((rep == NULL) || (ctxt->errNo == XML_ERR_ENTITY_LOOP)) {
-	    ent->content[0] = 0;
-	}
-
-        diff = ctxt->nbentities - oldnbent + 1;
-        if (diff > INT_MAX / 2)
-            diff = INT_MAX / 2;
-	ent->checked = diff * 2;
-	if (rep != NULL) {
-	    if (xmlStrchr(rep, '<'))
-		ent->checked |= 1;
-	    xmlFree(rep);
-	    rep = NULL;
-	}
-    }
-
-    /*
-     * Prevent entity exponential check, not just replacement while
-     * parsing the DTD
-     * The check is potentially costly so do that only once in a thousand
-     */
-    if ((ctxt->instate == XML_PARSER_DTD) && (ctxt->nbentities > 10000) &&
-        (ctxt->nbentities % 1024 == 0)) {
-	for (i = 0;i < ctxt->inputNr;i++) {
-	    consumed += ctxt->inputTab[i]->consumed +
-	               (ctxt->inputTab[i]->cur - ctxt->inputTab[i]->base);
-	}
-	if (ctxt->nbentities > consumed * XML_PARSER_NON_LINEAR) {
-	    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
-	    ctxt->instate = XML_PARSER_EOF;
-	    return (1);
-	}
-	consumed = 0;
-    }
-
-
-
-    if (replacement != 0) {
-	if (replacement < XML_MAX_TEXT_LENGTH)
-	    return(0);
-
-        /*
-	 * If the volume of entity copy reaches 10 times the
-	 * amount of parsed data and over the large text threshold
-	 * then that's very likely to be an abuse.
-	 */
-        if (ctxt->input != NULL) {
-	    consumed = ctxt->input->consumed +
-	               (ctxt->input->cur - ctxt->input->base);
-	}
-        consumed += ctxt->sizeentities;
-
-        if (replacement < XML_PARSER_NON_LINEAR * consumed)
-	    return(0);
-    } else if (size != 0) {
-        /*
-         * Do the check based on the replacement size of the entity
-         */
-        if (size < XML_PARSER_BIG_ENTITY)
-	    return(0);
-
-        /*
-         * A limit on the amount of text data reasonably used
-         */
-        if (ctxt->input != NULL) {
-            consumed = ctxt->input->consumed +
-                (ctxt->input->cur - ctxt->input->base);
-        }
-        consumed += ctxt->sizeentities;
-
-        if ((size < XML_PARSER_NON_LINEAR * consumed) &&
-	    (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed))
-            return (0);
-    } else if (ent != NULL) {
-        /*
-         * use the number of parsed entities in the replacement
-         */
-        size = ent->checked / 2;
+#define XML_PARSER_ALLOWED_EXPANSION 1000000
 
-        /*
-         * The amount of data parsed counting entities size only once
-         */
-        if (ctxt->input != NULL) {
-            consumed = ctxt->input->consumed +
-                (ctxt->input->cur - ctxt->input->base);
-        }
-        consumed += ctxt->sizeentities;
-
-        /*
-         * Check the density of entities for the amount of data
-	 * knowing an entity reference will take at least 3 bytes
-         */
-        if (size * 3 < consumed * XML_PARSER_NON_LINEAR)
-            return (0);
-    } else {
-        /*
-         * strange we got no data for checking
-         */
-	if (((ctxt->lastError.code != XML_ERR_UNDECLARED_ENTITY) &&
-	     (ctxt->lastError.code != XML_WAR_UNDECLARED_ENTITY)) ||
-	    (ctxt->nbentities <= 10000))
-	    return (0);
-    }
-    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
-    return (1);
-}
+/*
+ * Fixed cost for each entity reference. This crudely models processing time
+ * as well to protect, for example, against exponential expansion of empty
+ * or very short entities.
+ */
+#define XML_ENT_FIXED_COST 20
 
 /**
  * xmlParserMaxDepth:
@@ -265,11 +165,10 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
  * boundary feature. It can be disabled with the XML_PARSE_HUGE
  * parser option.
  */
-unsigned int xmlParserMaxDepth = 256;
+const unsigned int xmlParserMaxDepth = 256;
 
 
 
-#define SAX2 1
 #define XML_PARSER_BIG_BUFFER_SIZE 300
 #define XML_PARSER_BUFFER_SIZE 100
 #define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
@@ -285,6 +184,14 @@ unsigned int xmlParserMaxDepth = 256;
  */
 #define XML_PARSER_CHUNK_SIZE 100
 
+/**
+ * xmlParserVersion:
+ *
+ * Constant string describing the internal version of the library
+ */
+const char *const
+xmlParserVersion = LIBXML_VERSION_STRING LIBXML_VERSION_EXTRA;
+
 /*
  * List of XML prefixed PI allowed by W3C specs
  */
@@ -300,24 +207,8 @@ static const char* const xmlW3CPIs[] = {
 static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
                                               const xmlChar **str);
 
-static xmlParserErrors
-xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
-	              xmlSAXHandlerPtr sax,
-		      void *user_data, int depth, const xmlChar *URL,
-		      const xmlChar *ID, xmlNodePtr *list);
-
-static int
-xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
-                          const char *encoding);
-#ifdef LIBXML_LEGACY_ENABLED
 static void
-xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
-                      xmlNodePtr lastNode);
-#endif /* LIBXML_LEGACY_ENABLED */
-
-static xmlParserErrors
-xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
-		      const xmlChar *string, void *user_data, xmlNodePtr *lst);
+xmlCtxtParseEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr ent);
 
 static int
 xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
@@ -328,6 +219,11 @@ xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
  *									*
  ************************************************************************/
 
+static void
+xmlErrMemory(xmlParserCtxtPtr ctxt) {
+    xmlCtxtErrMemory(ctxt);
+}
+
 /**
  * xmlErrAttributeDup:
  * @ctxt:  an XML parser context
@@ -340,244 +236,14 @@ static void
 xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
                    const xmlChar * localname)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
-
     if (prefix == NULL)
-        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
-                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
-                        (const char *) localname, NULL, NULL, 0, 0,
-                        "Attribute %s redefined\n", localname);
+        xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, XML_ERR_ATTRIBUTE_REDEFINED,
+                   XML_ERR_FATAL, localname, NULL, NULL, 0,
+                   "Attribute %s redefined\n", localname);
     else
-        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
-                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
-                        (const char *) prefix, (const char *) localname,
-                        NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
-                        localname);
-    if (ctxt != NULL) {
-	ctxt->wellFormed = 0;
-	if (ctxt->recovery == 0)
-	    ctxt->disableSAX = 1;
-    }
-}
-
-/**
- * xmlFatalErr:
- * @ctxt:  an XML parser context
- * @error:  the error number
- * @extra:  extra information string
- *
- * Handle a fatal parser error, i.e. violating Well-Formedness constraints
- */
-static void
-xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
-{
-    const char *errmsg;
-
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    switch (error) {
-        case XML_ERR_INVALID_HEX_CHARREF:
-            errmsg = "CharRef: invalid hexadecimal value";
-            break;
-        case XML_ERR_INVALID_DEC_CHARREF:
-            errmsg = "CharRef: invalid decimal value";
-            break;
-        case XML_ERR_INVALID_CHARREF:
-            errmsg = "CharRef: invalid value";
-            break;
-        case XML_ERR_INTERNAL_ERROR:
-            errmsg = "internal error";
-            break;
-        case XML_ERR_PEREF_AT_EOF:
-            errmsg = "PEReference at end of document";
-            break;
-        case XML_ERR_PEREF_IN_PROLOG:
-            errmsg = "PEReference in prolog";
-            break;
-        case XML_ERR_PEREF_IN_EPILOG:
-            errmsg = "PEReference in epilog";
-            break;
-        case XML_ERR_PEREF_NO_NAME:
-            errmsg = "PEReference: no name";
-            break;
-        case XML_ERR_PEREF_SEMICOL_MISSING:
-            errmsg = "PEReference: expecting ';'";
-            break;
-        case XML_ERR_ENTITY_LOOP:
-            errmsg = "Detected an entity reference loop";
-            break;
-        case XML_ERR_ENTITY_NOT_STARTED:
-            errmsg = "EntityValue: \" or ' expected";
-            break;
-        case XML_ERR_ENTITY_PE_INTERNAL:
-            errmsg = "PEReferences forbidden in internal subset";
-            break;
-        case XML_ERR_ENTITY_NOT_FINISHED:
-            errmsg = "EntityValue: \" or ' expected";
-            break;
-        case XML_ERR_ATTRIBUTE_NOT_STARTED:
-            errmsg = "AttValue: \" or ' expected";
-            break;
-        case XML_ERR_LT_IN_ATTRIBUTE:
-            errmsg = "Unescaped '<' not allowed in attributes values";
-            break;
-        case XML_ERR_LITERAL_NOT_STARTED:
-            errmsg = "SystemLiteral \" or ' expected";
-            break;
-        case XML_ERR_LITERAL_NOT_FINISHED:
-            errmsg = "Unfinished System or Public ID \" or ' expected";
-            break;
-        case XML_ERR_MISPLACED_CDATA_END:
-            errmsg = "Sequence ']]>' not allowed in content";
-            break;
-        case XML_ERR_URI_REQUIRED:
-            errmsg = "SYSTEM or PUBLIC, the URI is missing";
-            break;
-        case XML_ERR_PUBID_REQUIRED:
-            errmsg = "PUBLIC, the Public Identifier is missing";
-            break;
-        case XML_ERR_HYPHEN_IN_COMMENT:
-            errmsg = "Comment must not contain '--' (double-hyphen)";
-            break;
-        case XML_ERR_PI_NOT_STARTED:
-            errmsg = "xmlParsePI : no target name";
-            break;
-        case XML_ERR_RESERVED_XML_NAME:
-            errmsg = "Invalid PI name";
-            break;
-        case XML_ERR_NOTATION_NOT_STARTED:
-            errmsg = "NOTATION: Name expected here";
-            break;
-        case XML_ERR_NOTATION_NOT_FINISHED:
-            errmsg = "'>' required to close NOTATION declaration";
-            break;
-        case XML_ERR_VALUE_REQUIRED:
-            errmsg = "Entity value required";
-            break;
-        case XML_ERR_URI_FRAGMENT:
-            errmsg = "Fragment not allowed";
-            break;
-        case XML_ERR_ATTLIST_NOT_STARTED:
-            errmsg = "'(' required to start ATTLIST enumeration";
-            break;
-        case XML_ERR_NMTOKEN_REQUIRED:
-            errmsg = "NmToken expected in ATTLIST enumeration";
-            break;
-        case XML_ERR_ATTLIST_NOT_FINISHED:
-            errmsg = "')' required to finish ATTLIST enumeration";
-            break;
-        case XML_ERR_MIXED_NOT_STARTED:
-            errmsg = "MixedContentDecl : '|' or ')*' expected";
-            break;
-        case XML_ERR_PCDATA_REQUIRED:
-            errmsg = "MixedContentDecl : '#PCDATA' expected";
-            break;
-        case XML_ERR_ELEMCONTENT_NOT_STARTED:
-            errmsg = "ContentDecl : Name or '(' expected";
-            break;
-        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
-            errmsg = "ContentDecl : ',' '|' or ')' expected";
-            break;
-        case XML_ERR_PEREF_IN_INT_SUBSET:
-            errmsg =
-                "PEReference: forbidden within markup decl in internal subset";
-            break;
-        case XML_ERR_GT_REQUIRED:
-            errmsg = "expected '>'";
-            break;
-        case XML_ERR_CONDSEC_INVALID:
-            errmsg = "XML conditional section '[' expected";
-            break;
-        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
-            errmsg = "Content error in the external subset";
-            break;
-        case XML_ERR_CONDSEC_INVALID_KEYWORD:
-            errmsg =
-                "conditional section INCLUDE or IGNORE keyword expected";
-            break;
-        case XML_ERR_CONDSEC_NOT_FINISHED:
-            errmsg = "XML conditional section not closed";
-            break;
-        case XML_ERR_XMLDECL_NOT_STARTED:
-            errmsg = "Text declaration '<?xml' required";
-            break;
-        case XML_ERR_XMLDECL_NOT_FINISHED:
-            errmsg = "parsing XML declaration: '?>' expected";
-            break;
-        case XML_ERR_EXT_ENTITY_STANDALONE:
-            errmsg = "external parsed entities cannot be standalone";
-            break;
-        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
-            errmsg = "EntityRef: expecting ';'";
-            break;
-        case XML_ERR_DOCTYPE_NOT_FINISHED:
-            errmsg = "DOCTYPE improperly terminated";
-            break;
-        case XML_ERR_LTSLASH_REQUIRED:
-            errmsg = "EndTag: '</' not found";
-            break;
-        case XML_ERR_EQUAL_REQUIRED:
-            errmsg = "expected '='";
-            break;
-        case XML_ERR_STRING_NOT_CLOSED:
-            errmsg = "String not closed expecting \" or '";
-            break;
-        case XML_ERR_STRING_NOT_STARTED:
-            errmsg = "String not started expecting ' or \"";
-            break;
-        case XML_ERR_ENCODING_NAME:
-            errmsg = "Invalid XML encoding name";
-            break;
-        case XML_ERR_STANDALONE_VALUE:
-            errmsg = "standalone accepts only 'yes' or 'no'";
-            break;
-        case XML_ERR_DOCUMENT_EMPTY:
-            errmsg = "Document is empty";
-            break;
-        case XML_ERR_DOCUMENT_END:
-            errmsg = "Extra content at the end of the document";
-            break;
-        case XML_ERR_NOT_WELL_BALANCED:
-            errmsg = "chunk is not well balanced";
-            break;
-        case XML_ERR_EXTRA_CONTENT:
-            errmsg = "extra content at the end of well balanced chunk";
-            break;
-        case XML_ERR_VERSION_MISSING:
-            errmsg = "Malformed declaration expecting version";
-            break;
-        case XML_ERR_NAME_TOO_LONG:
-            errmsg = "Name too long use XML_PARSE_HUGE option";
-            break;
-#if 0
-        case:
-            errmsg = "";
-            break;
-#endif
-        default:
-            errmsg = "Unregistered error message";
-    }
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    if (info == NULL) {
-        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
-                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
-                        errmsg);
-    } else {
-        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
-                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
-                        errmsg, info);
-    }
-    if (ctxt != NULL) {
-	ctxt->wellFormed = 0;
-	if (ctxt->recovery == 0)
-	    ctxt->disableSAX = 1;
-    }
+        xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, XML_ERR_ATTRIBUTE_REDEFINED,
+                   XML_ERR_FATAL, prefix, localname, NULL, 0,
+                   "Attribute %s:%s redefined\n", prefix, localname);
 }
 
 /**
@@ -592,18 +258,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                const char *msg)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
-                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
-    if (ctxt != NULL) {
-	ctxt->wellFormed = 0;
-	if (ctxt->recovery == 0)
-	    ctxt->disableSAX = 1;
-    }
+    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
+               NULL, NULL, NULL, 0, "%s", msg);
 }
 
 /**
@@ -616,33 +272,12 @@ xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
  *
  * Handle a warning.
  */
-static void LIBXML_ATTR_FORMAT(3,0)
+void LIBXML_ATTR_FORMAT(3,0)
 xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
               const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
-    xmlStructuredErrorFunc schannel = NULL;
-
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if ((ctxt != NULL) && (ctxt->sax != NULL) &&
-        (ctxt->sax->initialized == XML_SAX2_MAGIC))
-        schannel = ctxt->sax->serror;
-    if (ctxt != NULL) {
-        __xmlRaiseError(schannel,
-                    (ctxt->sax) ? ctxt->sax->warning : NULL,
-                    ctxt->userData,
-                    ctxt, NULL, XML_FROM_PARSER, error,
-                    XML_ERR_WARNING, NULL, 0,
-		    (const char *) str1, (const char *) str2, NULL, 0, 0,
-		    msg, (const char *) str1, (const char *) str2);
-    } else {
-        __xmlRaiseError(schannel, NULL, NULL,
-                    ctxt, NULL, XML_FROM_PARSER, error,
-                    XML_ERR_WARNING, NULL, 0,
-		    (const char *) str1, (const char *) str2, NULL, 0, 0,
-		    msg, (const char *) str1, (const char *) str2);
-    }
+    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_WARNING,
+               str1, str2, NULL, 0, msg, str1, str2);
 }
 
 /**
@@ -658,31 +293,10 @@ static void LIBXML_ATTR_FORMAT(3,0)
 xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
               const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
-    xmlStructuredErrorFunc schannel = NULL;
+    ctxt->valid = 0;
 
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL) {
-	ctxt->errNo = error;
-	if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
-	    schannel = ctxt->sax->serror;
-    }
-    if (ctxt != NULL) {
-        __xmlRaiseError(schannel,
-                    ctxt->vctxt.error, ctxt->vctxt.userData,
-                    ctxt, NULL, XML_FROM_DTD, error,
-                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
-		    (const char *) str2, NULL, 0, 0,
-		    msg, (const char *) str1, (const char *) str2);
-	ctxt->valid = 0;
-    } else {
-        __xmlRaiseError(schannel, NULL, NULL,
-                    ctxt, NULL, XML_FROM_DTD, error,
-                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
-		    (const char *) str2, NULL, 0, 0,
-		    msg, (const char *) str1, (const char *) str2);
-    }
+    xmlCtxtErr(ctxt, NULL, XML_FROM_DTD, error, XML_ERR_ERROR,
+               str1, str2, NULL, 0, msg, str1, str2);
 }
 
 /**
@@ -698,19 +312,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, int val)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL,
-                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
-                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
-    if (ctxt != NULL) {
-	ctxt->wellFormed = 0;
-	if (ctxt->recovery == 0)
-	    ctxt->disableSAX = 1;
-    }
+    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
+               NULL, NULL, NULL, val, msg, val);
 }
 
 /**
@@ -729,20 +332,8 @@ xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar *str1, int val,
 		  const xmlChar *str2)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL,
-                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
-                    NULL, 0, (const char *) str1, (const char *) str2,
-		    NULL, val, 0, msg, str1, val, str2);
-    if (ctxt != NULL) {
-	ctxt->wellFormed = 0;
-	if (ctxt->recovery == 0)
-	    ctxt->disableSAX = 1;
-    }
+    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
+               str1, str2, NULL, val, msg, str1, val, str2);
 }
 
 /**
@@ -758,20 +349,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar * val)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
-                    XML_FROM_PARSER, error, XML_ERR_FATAL,
-                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
-                    val);
-    if (ctxt != NULL) {
-	ctxt->wellFormed = 0;
-	if (ctxt->recovery == 0)
-	    ctxt->disableSAX = 1;
-    }
+    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
+               val, NULL, NULL, 0, msg, val);
 }
 
 /**
@@ -787,15 +366,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar * val)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
-                    XML_FROM_PARSER, error, XML_ERR_ERROR,
-                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
-                    val);
+    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_ERROR,
+               val, NULL, NULL, 0, msg, val);
 }
 
 /**
@@ -814,17 +386,10 @@ xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
          const xmlChar * info1, const xmlChar * info2,
          const xmlChar * info3)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
-                    XML_ERR_ERROR, NULL, 0, (const char *) info1,
-                    (const char *) info2, (const char *) info3, 0, 0, msg,
-                    info1, info2, info3);
-    if (ctxt != NULL)
-	ctxt->nsWellFormed = 0;
+    ctxt->nsWellFormed = 0;
+
+    xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_ERROR,
+               info1, info2, info3, 0, msg, info1, info2, info3);
 }
 
 /**
@@ -843,13 +408,96 @@ xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
          const xmlChar * info1, const xmlChar * info2,
          const xmlChar * info3)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
-                    XML_ERR_WARNING, NULL, 0, (const char *) info1,
-                    (const char *) info2, (const char *) info3, 0, 0, msg,
-                    info1, info2, info3);
+    xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_WARNING,
+               info1, info2, info3, 0, msg, info1, info2, info3);
+}
+
+static void
+xmlSaturatedAdd(unsigned long *dst, unsigned long val) {
+    if (val > ULONG_MAX - *dst)
+        *dst = ULONG_MAX;
+    else
+        *dst += val;
+}
+
+static void
+xmlSaturatedAddSizeT(unsigned long *dst, unsigned long val) {
+    if (val > ULONG_MAX - *dst)
+        *dst = ULONG_MAX;
+    else
+        *dst += val;
+}
+
+/**
+ * xmlParserEntityCheck:
+ * @ctxt:  parser context
+ * @extra:  sum of unexpanded entity sizes
+ *
+ * Check for non-linear entity expansion behaviour.
+ *
+ * In some cases like xmlExpandEntityInAttValue, this function is called
+ * for each, possibly nested entity and its unexpanded content length.
+ *
+ * In other cases like xmlParseReference, it's only called for each
+ * top-level entity with its unexpanded content length plus the sum of
+ * the unexpanded content lengths (plus fixed cost) of all nested
+ * entities.
+ *
+ * Summing the unexpanded lengths also adds the length of the reference.
+ * This is by design. Taking the length of the entity name into account
+ * discourages attacks that try to waste CPU time with abusively long
+ * entity names. See test/recurse/lol6.xml for example. Each call also
+ * adds some fixed cost XML_ENT_FIXED_COST to discourage attacks with
+ * short entities.
+ *
+ * Returns 1 on error, 0 on success.
+ */
+static int
+xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long extra)
+{
+    unsigned long consumed;
+    unsigned long *expandedSize;
+    xmlParserInputPtr input = ctxt->input;
+    xmlEntityPtr entity = input->entity;
+
+    if ((entity) && (entity->flags & XML_ENT_CHECKED))
+        return(0);
+
+    /*
+     * Compute total consumed bytes so far, including input streams of
+     * external entities.
+     */
+    consumed = input->consumed;
+    xmlSaturatedAddSizeT(&consumed, input->cur - input->base);
+    xmlSaturatedAdd(&consumed, ctxt->sizeentities);
+
+    if (entity)
+        expandedSize = &entity->expandedSize;
+    else
+        expandedSize = &ctxt->sizeentcopy;
+
+    /*
+     * Add extra cost and some fixed cost.
+     */
+    xmlSaturatedAdd(expandedSize, extra);
+    xmlSaturatedAdd(expandedSize, XML_ENT_FIXED_COST);
+
+    /*
+     * It's important to always use saturation arithmetic when tracking
+     * entity sizes to make the size checks reliable. If "sizeentcopy"
+     * overflows, we have to abort.
+     */
+    if ((*expandedSize > XML_PARSER_ALLOWED_EXPANSION) &&
+        ((*expandedSize >= ULONG_MAX) ||
+         (*expandedSize / ctxt->maxAmpl > consumed))) {
+        xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
+                       "Maximum entity amplification factor exceeded, see "
+                       "xmlCtxtSetMaxAmplification.\n");
+        xmlHaltParser(ctxt);
+        return(1);
+    }
+
+    return(0);
 }
 
 /************************************************************************
@@ -1041,17 +689,7 @@ xmlHasFeature(xmlFeature feature)
             return(0);
 #endif
         case XML_WITH_DEBUG_MEM:
-#ifdef DEBUG_MEMORY_LOCATION
-            return(1);
-#else
-            return(0);
-#endif
-        case XML_WITH_DEBUG_RUN:
-#ifdef LIBXML_DEBUG_RUNTIME
-            return(1);
-#else
             return(0);
-#endif
         case XML_WITH_ZLIB:
 #ifdef LIBXML_ZLIB_ENABLED
             return(1);
@@ -1078,43 +716,283 @@ xmlHasFeature(xmlFeature feature)
 
 /************************************************************************
  *									*
- *		SAX2 defaulted attributes handling			*
+ *			Simple string buffer				*
  *									*
  ************************************************************************/
 
-/**
- * xmlDetectSAX2:
- * @ctxt:  an XML parser context
- *
- * Do the SAX2 detection and specific initialization
- */
+typedef struct {
+    xmlChar *mem;
+    unsigned size;
+    unsigned cap; /* size < cap */
+    unsigned max; /* size <= max */
+    xmlParserErrors code;
+} xmlSBuf;
+
 static void
-xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
-    xmlSAXHandlerPtr sax;
+xmlSBufInit(xmlSBuf *buf, unsigned max) {
+    buf->mem = NULL;
+    buf->size = 0;
+    buf->cap = 0;
+    buf->max = max;
+    buf->code = XML_ERR_OK;
+}
 
-    /* Avoid unused variable warning if features are disabled. */
-    (void) sax;
+static int
+xmlSBufGrow(xmlSBuf *buf, unsigned len) {
+    xmlChar *mem;
+    unsigned cap;
 
-    if (ctxt == NULL) return;
-    sax = ctxt->sax;
-#ifdef LIBXML_SAX1_ENABLED
-    if ((sax) &&  (sax->initialized == XML_SAX2_MAGIC) &&
-        ((sax->startElementNs != NULL) ||
-         (sax->endElementNs != NULL) ||
-         ((sax->startElement == NULL) && (sax->endElement == NULL))))
-        ctxt->sax2 = 1;
-#else
-    ctxt->sax2 = 1;
-#endif /* LIBXML_SAX1_ENABLED */
+    if (len >= UINT_MAX / 2 - buf->size) {
+        if (buf->code == XML_ERR_OK)
+            buf->code = XML_ERR_RESOURCE_LIMIT;
+        return(-1);
+    }
 
-    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
-    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
-    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
-    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
-		(ctxt->str_xml_ns == NULL)) {
-        xmlErrMemory(ctxt, NULL);
+    cap = (buf->size + len) * 2;
+    if (cap < 240)
+        cap = 240;
+
+    mem = xmlRealloc(buf->mem, cap);
+    if (mem == NULL) {
+        buf->code = XML_ERR_NO_MEMORY;
+        return(-1);
     }
-}
+
+    buf->mem = mem;
+    buf->cap = cap;
+
+    return(0);
+}
+
+static void
+xmlSBufAddString(xmlSBuf *buf, const xmlChar *str, unsigned len) {
+    if (buf->max - buf->size < len) {
+        if (buf->code == XML_ERR_OK)
+            buf->code = XML_ERR_RESOURCE_LIMIT;
+        return;
+    }
+
+    if (buf->cap - buf->size <= len) {
+        if (xmlSBufGrow(buf, len) < 0)
+            return;
+    }
+
+    if (len > 0)
+        memcpy(buf->mem + buf->size, str, len);
+    buf->size += len;
+}
+
+static void
+xmlSBufAddCString(xmlSBuf *buf, const char *str, unsigned len) {
+    xmlSBufAddString(buf, (const xmlChar *) str, len);
+}
+
+static void
+xmlSBufAddChar(xmlSBuf *buf, int c) {
+    xmlChar *end;
+
+    if (buf->max - buf->size < 4) {
+        if (buf->code == XML_ERR_OK)
+            buf->code = XML_ERR_RESOURCE_LIMIT;
+        return;
+    }
+
+    if (buf->cap - buf->size <= 4) {
+        if (xmlSBufGrow(buf, 4) < 0)
+            return;
+    }
+
+    end = buf->mem + buf->size;
+
+    if (c < 0x80) {
+        *end = (xmlChar) c;
+        buf->size += 1;
+    } else {
+        buf->size += xmlCopyCharMultiByte(end, c);
+    }
+}
+
+static void
+xmlSBufAddReplChar(xmlSBuf *buf) {
+    xmlSBufAddCString(buf, "\xEF\xBF\xBD", 3);
+}
+
+static void
+xmlSBufReportError(xmlSBuf *buf, xmlParserCtxtPtr ctxt, const char *errMsg) {
+    if (buf->code == XML_ERR_NO_MEMORY)
+        xmlCtxtErrMemory(ctxt);
+    else
+        xmlFatalErr(ctxt, buf->code, errMsg);
+}
+
+static xmlChar *
+xmlSBufFinish(xmlSBuf *buf, int *sizeOut, xmlParserCtxtPtr ctxt,
+              const char *errMsg) {
+    if (buf->mem == NULL) {
+        buf->mem = xmlMalloc(1);
+        if (buf->mem == NULL) {
+            buf->code = XML_ERR_NO_MEMORY;
+        } else {
+            buf->mem[0] = 0;
+        }
+    } else {
+        buf->mem[buf->size] = 0;
+    }
+
+    if (buf->code == XML_ERR_OK) {
+        if (sizeOut != NULL)
+            *sizeOut = buf->size;
+        return(buf->mem);
+    }
+
+    xmlSBufReportError(buf, ctxt, errMsg);
+
+    xmlFree(buf->mem);
+
+    if (sizeOut != NULL)
+        *sizeOut = 0;
+    return(NULL);
+}
+
+static void
+xmlSBufCleanup(xmlSBuf *buf, xmlParserCtxtPtr ctxt, const char *errMsg) {
+    if (buf->code != XML_ERR_OK)
+        xmlSBufReportError(buf, ctxt, errMsg);
+
+    xmlFree(buf->mem);
+}
+
+static int
+xmlUTF8MultibyteLen(xmlParserCtxtPtr ctxt, const xmlChar *str,
+                    const char *errMsg) {
+    int c = str[0];
+    int c1 = str[1];
+
+    if ((c1 & 0xC0) != 0x80)
+        goto encoding_error;
+
+    if (c < 0xE0) {
+        /* 2-byte sequence */
+        if (c < 0xC2)
+            goto encoding_error;
+
+        return(2);
+    } else {
+        int c2 = str[2];
+
+        if ((c2 & 0xC0) != 0x80)
+            goto encoding_error;
+
+        if (c < 0xF0) {
+            /* 3-byte sequence */
+            if (c == 0xE0) {
+                /* overlong */
+                if (c1 < 0xA0)
+                    goto encoding_error;
+            } else if (c == 0xED) {
+                /* surrogate */
+                if (c1 >= 0xA0)
+                    goto encoding_error;
+            } else if (c == 0xEF) {
+                /* U+FFFE and U+FFFF are invalid Chars */
+                if ((c1 == 0xBF) && (c2 >= 0xBE))
+                    xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, errMsg);
+            }
+
+            return(3);
+        } else {
+            /* 4-byte sequence */
+            if ((str[3] & 0xC0) != 0x80)
+                goto encoding_error;
+            if (c == 0xF0) {
+                /* overlong */
+                if (c1 < 0x90)
+                    goto encoding_error;
+            } else if (c >= 0xF4) {
+                /* greater than 0x10FFFF */
+                if ((c > 0xF4) || (c1 >= 0x90))
+                    goto encoding_error;
+            }
+
+            return(4);
+        }
+    }
+
+encoding_error:
+    /* Only report the first error */
+    if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) {
+        xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL);
+        ctxt->input->flags |= XML_INPUT_ENCODING_ERROR;
+    }
+
+    return(0);
+}
+
+/************************************************************************
+ *									*
+ *		SAX2 defaulted attributes handling			*
+ *									*
+ ************************************************************************/
+
+/**
+ * xmlCtxtInitializeLate:
+ * @ctxt:  an XML parser context
+ *
+ * Final initialization of the parser context before starting to parse.
+ *
+ * This accounts for users modifying struct members of parser context
+ * directly.
+ */
+static void
+xmlCtxtInitializeLate(xmlParserCtxtPtr ctxt) {
+    xmlSAXHandlerPtr sax;
+
+    /* Avoid unused variable warning if features are disabled. */
+    (void) sax;
+
+    /*
+     * Changing the SAX struct directly is still widespread practice
+     * in internal and external code.
+     */
+    if (ctxt == NULL) return;
+    sax = ctxt->sax;
+#ifdef LIBXML_SAX1_ENABLED
+    /*
+     * Only enable SAX2 if there SAX2 element handlers, except when there
+     * are no element handlers at all.
+     */
+    if (((ctxt->options & XML_PARSE_SAX1) == 0) &&
+        (sax) &&
+        (sax->initialized == XML_SAX2_MAGIC) &&
+        ((sax->startElementNs != NULL) ||
+         (sax->endElementNs != NULL) ||
+         ((sax->startElement == NULL) && (sax->endElement == NULL))))
+        ctxt->sax2 = 1;
+#else
+    ctxt->sax2 = 1;
+#endif /* LIBXML_SAX1_ENABLED */
+
+    /*
+     * Some users replace the dictionary directly in the context struct.
+     * We really need an API function to do that cleanly.
+     */
+    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
+    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
+    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
+    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
+		(ctxt->str_xml_ns == NULL)) {
+        xmlErrMemory(ctxt);
+    }
+}
+
+typedef struct {
+    xmlHashedString prefix;
+    xmlHashedString name;
+    xmlHashedString value;
+    const xmlChar *valueEnd;
+    int external;
+    int expandedSize;
+} xmlDefAttr;
 
 typedef struct _xmlDefAttrs xmlDefAttrs;
 typedef xmlDefAttrs *xmlDefAttrsPtr;
@@ -1123,9 +1001,9 @@ struct _xmlDefAttrs {
     int maxAttrs;       /* the size of the array */
 #if __STDC_VERSION__ >= 199901L
     /* Using a C99 flexible array member avoids UBSan errors. */
-    const xmlChar *values[]; /* array of localname/prefix/values/external */
+    xmlDefAttr attrs[]; /* array of localname/prefix/values/external */
 #else
-    const xmlChar *values[5];
+    xmlDefAttr attrs[1];
 #endif
 };
 
@@ -1168,65 +1046,6 @@ xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
     return(dst);
 }
 
-/**
- * xmlAttrNormalizeSpace2:
- * @src: the source string
- *
- * Normalize the space in non CDATA attribute values, a slightly more complex
- * front end to avoid allocation problems when running on attribute values
- * coming from the input.
- *
- * Returns a pointer to the normalized value (dst) or NULL if no conversion
- *         is needed.
- */
-static const xmlChar *
-xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
-{
-    int i;
-    int remove_head = 0;
-    int need_realloc = 0;
-    const xmlChar *cur;
-
-    if ((ctxt == NULL) || (src == NULL) || (len == NULL))
-        return(NULL);
-    i = *len;
-    if (i <= 0)
-        return(NULL);
-
-    cur = src;
-    while (*cur == 0x20) {
-        cur++;
-	remove_head++;
-    }
-    while (*cur != 0) {
-	if (*cur == 0x20) {
-	    cur++;
-	    if ((*cur == 0x20) || (*cur == 0)) {
-	        need_realloc = 1;
-		break;
-	    }
-	} else
-	    cur++;
-    }
-    if (need_realloc) {
-        xmlChar *ret;
-
-	ret = xmlStrndup(src + remove_head, i - remove_head + 1);
-	if (ret == NULL) {
-	    xmlErrMemory(ctxt, NULL);
-	    return(NULL);
-	}
-	xmlAttrNormalizeSpace(ret, ret);
-	*len = (int) strlen((const char *)ret);
-        return(ret);
-    } else if (remove_head) {
-        *len -= remove_head;
-        memmove(src, src + remove_head, 1 + *len);
-	return(src);
-    }
-    return(NULL);
-}
-
 /**
  * xmlAddDefAttrs:
  * @ctxt:  an XML parser context
@@ -1242,9 +1061,12 @@ xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
                const xmlChar *fullattr,
                const xmlChar *value) {
     xmlDefAttrsPtr defaults;
-    int len;
-    const xmlChar *name;
-    const xmlChar *prefix;
+    xmlDefAttr *attr;
+    int len, expandedSize;
+    xmlHashedString name;
+    xmlHashedString prefix;
+    xmlHashedString hvalue;
+    const xmlChar *localname;
 
     /*
      * Allows to detect attribute redefinitions
@@ -1264,41 +1086,38 @@ xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
      * split the element name into prefix:localname , the string found
      * are within the DTD and then not associated to namespace names.
      */
-    name = xmlSplitQName3(fullname, &len);
-    if (name == NULL) {
-        name = xmlDictLookup(ctxt->dict, fullname, -1);
-	prefix = NULL;
+    localname = xmlSplitQName3(fullname, &len);
+    if (localname == NULL) {
+        name = xmlDictLookupHashed(ctxt->dict, fullname, -1);
+	prefix.name = NULL;
     } else {
-        name = xmlDictLookup(ctxt->dict, name, -1);
-	prefix = xmlDictLookup(ctxt->dict, fullname, len);
+        name = xmlDictLookupHashed(ctxt->dict, localname, -1);
+	prefix = xmlDictLookupHashed(ctxt->dict, fullname, len);
+        if (prefix.name == NULL)
+            goto mem_error;
     }
+    if (name.name == NULL)
+        goto mem_error;
 
     /*
      * make sure there is some storage
      */
-    defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
-    if (defaults == NULL) {
-        defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
-	                   (4 * 5) * sizeof(const xmlChar *));
-	if (defaults == NULL)
-	    goto mem_error;
-	defaults->nbAttrs = 0;
-	defaults->maxAttrs = 4;
-	if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
-	                        defaults, NULL) < 0) {
-	    xmlFree(defaults);
-	    goto mem_error;
-	}
-    } else if (defaults->nbAttrs >= defaults->maxAttrs) {
+    defaults = xmlHashLookup2(ctxt->attsDefault, name.name, prefix.name);
+    if ((defaults == NULL) ||
+        (defaults->nbAttrs >= defaults->maxAttrs)) {
         xmlDefAttrsPtr temp;
+        int newSize;
 
-        temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
-		       (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *));
+        newSize = (defaults != NULL) ? 2 * defaults->maxAttrs : 4;
+        temp = xmlRealloc(defaults,
+                          sizeof(*defaults) + newSize * sizeof(xmlDefAttr));
 	if (temp == NULL)
 	    goto mem_error;
-	defaults = temp;
-	defaults->maxAttrs *= 2;
-	if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
+        if (defaults == NULL)
+            temp->nbAttrs = 0;
+	temp->maxAttrs = newSize;
+        defaults = temp;
+	if (xmlHashUpdateEntry2(ctxt->attsDefault, name.name, prefix.name,
 	                        defaults, NULL) < 0) {
 	    xmlFree(defaults);
 	    goto mem_error;
@@ -1306,35 +1125,45 @@ xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
     }
 
     /*
-     * Split the element name into prefix:localname , the string found
+     * Split the attribute name into prefix:localname , the string found
      * are within the DTD and hen not associated to namespace names.
      */
-    name = xmlSplitQName3(fullattr, &len);
-    if (name == NULL) {
-        name = xmlDictLookup(ctxt->dict, fullattr, -1);
-	prefix = NULL;
+    localname = xmlSplitQName3(fullattr, &len);
+    if (localname == NULL) {
+        name = xmlDictLookupHashed(ctxt->dict, fullattr, -1);
+	prefix.name = NULL;
     } else {
-        name = xmlDictLookup(ctxt->dict, name, -1);
-	prefix = xmlDictLookup(ctxt->dict, fullattr, len);
+        name = xmlDictLookupHashed(ctxt->dict, localname, -1);
+	prefix = xmlDictLookupHashed(ctxt->dict, fullattr, len);
+        if (prefix.name == NULL)
+            goto mem_error;
     }
+    if (name.name == NULL)
+        goto mem_error;
 
-    defaults->values[5 * defaults->nbAttrs] = name;
-    defaults->values[5 * defaults->nbAttrs + 1] = prefix;
     /* intern the string and precompute the end */
-    len = xmlStrlen(value);
-    value = xmlDictLookup(ctxt->dict, value, len);
-    defaults->values[5 * defaults->nbAttrs + 2] = value;
-    defaults->values[5 * defaults->nbAttrs + 3] = value + len;
-    if (ctxt->external)
-        defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external";
-    else
-        defaults->values[5 * defaults->nbAttrs + 4] = NULL;
-    defaults->nbAttrs++;
+    len = strlen((const char *) value);
+    hvalue = xmlDictLookupHashed(ctxt->dict, value, len);
+    if (hvalue.name == NULL)
+        goto mem_error;
+
+    expandedSize = strlen((const char *) name.name);
+    if (prefix.name != NULL)
+        expandedSize += strlen((const char *) prefix.name);
+    expandedSize += len;
+
+    attr = &defaults->attrs[defaults->nbAttrs++];
+    attr->name = name;
+    attr->prefix = prefix;
+    attr->value = hvalue;
+    attr->valueEnd = hvalue.name + len;
+    attr->external = PARSER_EXTERNAL(ctxt);
+    attr->expandedSize = expandedSize;
 
     return;
 
 mem_error:
-    xmlErrMemory(ctxt, NULL);
+    xmlErrMemory(ctxt);
     return;
 }
 
@@ -1359,15 +1188,13 @@ xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
 	    goto mem_error;
     }
 
-    if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
-        return;
-
-    xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
-                     (void *) (ptrdiff_t) type);
+    if (xmlHashAdd2(ctxt->attsSpecial, fullname, fullattr,
+                    (void *) (ptrdiff_t) type) < 0)
+        goto mem_error;
     return;
 
 mem_error:
-    xmlErrMemory(ctxt, NULL);
+    xmlErrMemory(ctxt);
     return;
 }
 
@@ -1414,6 +1241,8 @@ xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
  * xmlCheckLanguageID:
  * @lang:  pointer to the string value
  *
+ * DEPRECATED: Internal function, do not use.
+ *
  * Checks that the value conforms to the LanguageID production:
  *
  * NOTE: this is somewhat deprecated, those productions were removed from
@@ -1610,168 +1439,556 @@ region_m49:
  *									*
  ************************************************************************/
 
-static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
-                                            const xmlChar ** str);
+static xmlChar *
+xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar **str);
 
-#ifdef SAX2
 /**
- * nsPush:
- * @ctxt:  an XML parser context
- * @prefix:  the namespace prefix or NULL
- * @URL:  the namespace name
+ * xmlParserNsCreate:
  *
- * Pushes a new parser namespace on top of the ns stack
+ * Create a new namespace database.
  *
- * Returns -1 in case of error, -2 if the namespace should be discarded
- *	   and the index in the stack otherwise.
+ * Returns the new obejct.
  */
-static int
-nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
-{
-    if (ctxt->options & XML_PARSE_NSCLEAN) {
-        int i;
-	for (i = ctxt->nsNr - 2;i >= 0;i -= 2) {
-	    if (ctxt->nsTab[i] == prefix) {
-		/* in scope */
-	        if (ctxt->nsTab[i + 1] == URL)
-		    return(-2);
-		/* out of scope keep it */
-		break;
-	    }
-	}
-    }
-    if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
-	ctxt->nsMax = 10;
-	ctxt->nsNr = 0;
-	ctxt->nsTab = (const xmlChar **)
-	              xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
-	if (ctxt->nsTab == NULL) {
-	    xmlErrMemory(ctxt, NULL);
-	    ctxt->nsMax = 0;
-            return (-1);
-	}
-    } else if (ctxt->nsNr >= ctxt->nsMax) {
-        const xmlChar ** tmp;
-        ctxt->nsMax *= 2;
-        tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
-				    ctxt->nsMax * sizeof(ctxt->nsTab[0]));
-        if (tmp == NULL) {
-            xmlErrMemory(ctxt, NULL);
-	    ctxt->nsMax /= 2;
-            return (-1);
-        }
-	ctxt->nsTab = tmp;
-    }
-    ctxt->nsTab[ctxt->nsNr++] = prefix;
-    ctxt->nsTab[ctxt->nsNr++] = URL;
-    return (ctxt->nsNr);
+xmlParserNsData *
+xmlParserNsCreate(void) {
+    xmlParserNsData *nsdb = xmlMalloc(sizeof(*nsdb));
+
+    if (nsdb == NULL)
+        return(NULL);
+    memset(nsdb, 0, sizeof(*nsdb));
+    nsdb->defaultNsIndex = INT_MAX;
+
+    return(nsdb);
 }
+
 /**
- * nsPop:
- * @ctxt: an XML parser context
- * @nr:  the number to pop
+ * xmlParserNsFree:
+ * @nsdb: namespace database
  *
- * Pops the top @nr parser prefix/namespace from the ns stack
+ * Free a namespace database.
+ */
+void
+xmlParserNsFree(xmlParserNsData *nsdb) {
+    if (nsdb == NULL)
+        return;
+
+    xmlFree(nsdb->extra);
+    xmlFree(nsdb->hash);
+    xmlFree(nsdb);
+}
+
+/**
+ * xmlParserNsReset:
+ * @nsdb: namespace database
  *
- * Returns the number of namespaces removed
+ * Reset a namespace database.
  */
-static int
-nsPop(xmlParserCtxtPtr ctxt, int nr)
-{
-    int i;
+static void
+xmlParserNsReset(xmlParserNsData *nsdb) {
+    if (nsdb == NULL)
+        return;
 
-    if (ctxt->nsTab == NULL) return(0);
-    if (ctxt->nsNr < nr) {
-        xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
-        nr = ctxt->nsNr;
-    }
-    if (ctxt->nsNr <= 0)
-        return (0);
+    nsdb->hashElems = 0;
+    nsdb->elementId = 0;
+    nsdb->defaultNsIndex = INT_MAX;
 
-    for (i = 0;i < nr;i++) {
-         ctxt->nsNr--;
-	 ctxt->nsTab[ctxt->nsNr] = NULL;
-    }
-    return(nr);
+    if (nsdb->hash)
+        memset(nsdb->hash, 0, nsdb->hashSize * sizeof(nsdb->hash[0]));
 }
-#endif
 
+/**
+ * xmlParserStartElement:
+ * @nsdb: namespace database
+ *
+ * Signal that a new element has started.
+ *
+ * Returns 0 on success, -1 if the element counter overflowed.
+ */
 static int
-xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
-    const xmlChar **atts;
-    int *attallocs;
-    int maxatts;
+xmlParserNsStartElement(xmlParserNsData *nsdb) {
+    if (nsdb->elementId == UINT_MAX)
+        return(-1);
+    nsdb->elementId++;
 
-    if (ctxt->atts == NULL) {
-	maxatts = 55; /* allow for 10 attrs by default */
-	atts = (const xmlChar **)
-	       xmlMalloc(maxatts * sizeof(xmlChar *));
-	if (atts == NULL) goto mem_error;
-	ctxt->atts = atts;
-	attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int));
-	if (attallocs == NULL) goto mem_error;
-	ctxt->attallocs = attallocs;
-	ctxt->maxatts = maxatts;
-    } else if (nr + 5 > ctxt->maxatts) {
-	maxatts = (nr + 5) * 2;
-	atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts,
-				     maxatts * sizeof(const xmlChar *));
-	if (atts == NULL) goto mem_error;
-	ctxt->atts = atts;
-	attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
-	                             (maxatts / 5) * sizeof(int));
-	if (attallocs == NULL) goto mem_error;
-	ctxt->attallocs = attallocs;
-	ctxt->maxatts = maxatts;
-    }
-    return(ctxt->maxatts);
-mem_error:
-    xmlErrMemory(ctxt, NULL);
-    return(-1);
+    return(0);
 }
 
 /**
- * inputPush:
- * @ctxt:  an XML parser context
- * @value:  the parser input
+ * xmlParserNsLookup:
+ * @ctxt: parser context
+ * @prefix: namespace prefix
+ * @bucketPtr: optional bucket (return value)
  *
- * Pushes a new parser input on top of the input stack
+ * Lookup namespace with given prefix. If @bucketPtr is non-NULL, it will
+ * be set to the matching bucket, or the first empty bucket if no match
+ * was found.
  *
- * Returns -1 in case of error, the index in the stack otherwise
+ * Returns the namespace index on success, INT_MAX if no namespace was
+ * found.
  */
-int
-inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
-{
-    if ((ctxt == NULL) || (value == NULL))
-        return(-1);
-    if (ctxt->inputNr >= ctxt->inputMax) {
-        ctxt->inputMax *= 2;
-        ctxt->inputTab =
-            (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
-                                             ctxt->inputMax *
-                                             sizeof(ctxt->inputTab[0]));
-        if (ctxt->inputTab == NULL) {
-            xmlErrMemory(ctxt, NULL);
-	    ctxt->inputMax /= 2;
-            return (-1);
+static int
+xmlParserNsLookup(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix,
+                  xmlParserNsBucket **bucketPtr) {
+    xmlParserNsBucket *bucket, *tombstone;
+    unsigned index, hashValue;
+
+    if (prefix->name == NULL)
+        return(ctxt->nsdb->defaultNsIndex);
+
+    if (ctxt->nsdb->hashSize == 0)
+        return(INT_MAX);
+
+    hashValue = prefix->hashValue;
+    index = hashValue & (ctxt->nsdb->hashSize - 1);
+    bucket = &ctxt->nsdb->hash[index];
+    tombstone = NULL;
+
+    while (bucket->hashValue) {
+        if (bucket->index == INT_MAX) {
+            if (tombstone == NULL)
+                tombstone = bucket;
+        } else if (bucket->hashValue == hashValue) {
+            if (ctxt->nsTab[bucket->index * 2] == prefix->name) {
+                if (bucketPtr != NULL)
+                    *bucketPtr = bucket;
+                return(bucket->index);
+            }
+        }
+
+        index++;
+        bucket++;
+        if (index == ctxt->nsdb->hashSize) {
+            index = 0;
+            bucket = ctxt->nsdb->hash;
         }
     }
-    ctxt->inputTab[ctxt->inputNr] = value;
-    ctxt->input = value;
-    return (ctxt->inputNr++);
+
+    if (bucketPtr != NULL)
+        *bucketPtr = tombstone ? tombstone : bucket;
+    return(INT_MAX);
 }
+
 /**
- * inputPop:
- * @ctxt: an XML parser context
+ * xmlParserNsLookupUri:
+ * @ctxt: parser context
+ * @prefix: namespace prefix
  *
- * Pops the top parser input from the input stack
+ * Lookup namespace URI with given prefix.
  *
- * Returns the input just removed
+ * Returns the namespace URI on success, NULL if no namespace was found.
  */
-xmlParserInputPtr
-inputPop(xmlParserCtxtPtr ctxt)
-{
-    xmlParserInputPtr ret;
+static const xmlChar *
+xmlParserNsLookupUri(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix) {
+    const xmlChar *ret;
+    int nsIndex;
+
+    if (prefix->name == ctxt->str_xml)
+        return(ctxt->str_xml_ns);
+
+    /*
+     * minNsIndex is used when building an entity tree. We must
+     * ignore namespaces declared outside the entity.
+     */
+    nsIndex = xmlParserNsLookup(ctxt, prefix, NULL);
+    if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex))
+        return(NULL);
+
+    ret = ctxt->nsTab[nsIndex * 2 + 1];
+    if (ret[0] == 0)
+        ret = NULL;
+    return(ret);
+}
+
+/**
+ * xmlParserNsLookupSax:
+ * @ctxt: parser context
+ * @prefix: namespace prefix
+ *
+ * Lookup extra data for the given prefix. This returns data stored
+ * with xmlParserNsUdpateSax.
+ *
+ * Returns the data on success, NULL if no namespace was found.
+ */
+void *
+xmlParserNsLookupSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
+    xmlHashedString hprefix;
+    int nsIndex;
+
+    if (prefix == ctxt->str_xml)
+        return(NULL);
+
+    hprefix.name = prefix;
+    if (prefix != NULL)
+        hprefix.hashValue = xmlDictComputeHash(ctxt->dict, prefix);
+    else
+        hprefix.hashValue = 0;
+    nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL);
+    if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex))
+        return(NULL);
+
+    return(ctxt->nsdb->extra[nsIndex].saxData);
+}
+
+/**
+ * xmlParserNsUpdateSax:
+ * @ctxt: parser context
+ * @prefix: namespace prefix
+ * @saxData: extra data for SAX handler
+ *
+ * Sets or updates extra data for the given prefix. This value will be
+ * returned by xmlParserNsLookupSax as long as the namespace with the
+ * given prefix is in scope.
+ *
+ * Returns the data on success, NULL if no namespace was found.
+ */
+int
+xmlParserNsUpdateSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
+                     void *saxData) {
+    xmlHashedString hprefix;
+    int nsIndex;
+
+    if (prefix == ctxt->str_xml)
+        return(-1);
+
+    hprefix.name = prefix;
+    if (prefix != NULL)
+        hprefix.hashValue = xmlDictComputeHash(ctxt->dict, prefix);
+    else
+        hprefix.hashValue = 0;
+    nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL);
+    if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex))
+        return(-1);
+
+    ctxt->nsdb->extra[nsIndex].saxData = saxData;
+    return(0);
+}
+
+/**
+ * xmlParserNsGrow:
+ * @ctxt: parser context
+ *
+ * Grows the namespace tables.
+ *
+ * Returns 0 on success, -1 if a memory allocation failed.
+ */
+static int
+xmlParserNsGrow(xmlParserCtxtPtr ctxt) {
+    const xmlChar **table;
+    xmlParserNsExtra *extra;
+    int newSize;
+
+    if (ctxt->nsMax > INT_MAX / 2)
+        goto error;
+    newSize = ctxt->nsMax ? ctxt->nsMax * 2 : 16;
+
+    table = xmlRealloc(ctxt->nsTab, 2 * newSize * sizeof(table[0]));
+    if (table == NULL)
+        goto error;
+    ctxt->nsTab = table;
+
+    extra = xmlRealloc(ctxt->nsdb->extra, newSize * sizeof(extra[0]));
+    if (extra == NULL)
+        goto error;
+    ctxt->nsdb->extra = extra;
+
+    ctxt->nsMax = newSize;
+    return(0);
+
+error:
+    xmlErrMemory(ctxt);
+    return(-1);
+}
+
+/**
+ * xmlParserNsPush:
+ * @ctxt: parser context
+ * @prefix: prefix with hash value
+ * @uri: uri with hash value
+ * @saxData: extra data for SAX handler
+ * @defAttr: whether the namespace comes from a default attribute
+ *
+ * Push a new namespace on the table.
+ *
+ * Returns 1 if the namespace was pushed, 0 if the namespace was ignored,
+ * -1 if a memory allocation failed.
+ */
+static int
+xmlParserNsPush(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix,
+                const xmlHashedString *uri, void *saxData, int defAttr) {
+    xmlParserNsBucket *bucket = NULL;
+    xmlParserNsExtra *extra;
+    const xmlChar **ns;
+    unsigned hashValue, nsIndex, oldIndex;
+
+    if ((prefix != NULL) && (prefix->name == ctxt->str_xml))
+        return(0);
+
+    if ((ctxt->nsNr >= ctxt->nsMax) && (xmlParserNsGrow(ctxt) < 0)) {
+        xmlErrMemory(ctxt);
+        return(-1);
+    }
+
+    /*
+     * Default namespace and 'xml' namespace
+     */
+    if ((prefix == NULL) || (prefix->name == NULL)) {
+        oldIndex = ctxt->nsdb->defaultNsIndex;
+
+        if (oldIndex != INT_MAX) {
+            extra = &ctxt->nsdb->extra[oldIndex];
+
+            if (extra->elementId == ctxt->nsdb->elementId) {
+                if (defAttr == 0)
+                    xmlErrAttributeDup(ctxt, NULL, BAD_CAST "xmlns");
+                return(0);
+            }
+
+            if ((ctxt->options & XML_PARSE_NSCLEAN) &&
+                (uri->name == ctxt->nsTab[oldIndex * 2 + 1]))
+                return(0);
+        }
+
+        ctxt->nsdb->defaultNsIndex = ctxt->nsNr;
+        goto populate_entry;
+    }
+
+    /*
+     * Hash table lookup
+     */
+    oldIndex = xmlParserNsLookup(ctxt, prefix, &bucket);
+    if (oldIndex != INT_MAX) {
+        extra = &ctxt->nsdb->extra[oldIndex];
+
+        /*
+         * Check for duplicate definitions on the same element.
+         */
+        if (extra->elementId == ctxt->nsdb->elementId) {
+            if (defAttr == 0)
+                xmlErrAttributeDup(ctxt, BAD_CAST "xmlns", prefix->name);
+            return(0);
+        }
+
+        if ((ctxt->options & XML_PARSE_NSCLEAN) &&
+            (uri->name == ctxt->nsTab[bucket->index * 2 + 1]))
+            return(0);
+
+        bucket->index = ctxt->nsNr;
+        goto populate_entry;
+    }
+
+    /*
+     * Insert new bucket
+     */
+
+    hashValue = prefix->hashValue;
+
+    /*
+     * Grow hash table, 50% fill factor
+     */
+    if (ctxt->nsdb->hashElems + 1 > ctxt->nsdb->hashSize / 2) {
+        xmlParserNsBucket *newHash;
+        unsigned newSize, i, index;
+
+        if (ctxt->nsdb->hashSize > UINT_MAX / 2) {
+            xmlErrMemory(ctxt);
+            return(-1);
+        }
+        newSize = ctxt->nsdb->hashSize ? ctxt->nsdb->hashSize * 2 : 16;
+        newHash = xmlMalloc(newSize * sizeof(newHash[0]));
+        if (newHash == NULL) {
+            xmlErrMemory(ctxt);
+            return(-1);
+        }
+        memset(newHash, 0, newSize * sizeof(newHash[0]));
+
+        for (i = 0; i < ctxt->nsdb->hashSize; i++) {
+            unsigned hv = ctxt->nsdb->hash[i].hashValue;
+            unsigned newIndex;
+
+            if ((hv == 0) || (ctxt->nsdb->hash[i].index == INT_MAX))
+                continue;
+            newIndex = hv & (newSize - 1);
+
+            while (newHash[newIndex].hashValue != 0) {
+                newIndex++;
+                if (newIndex == newSize)
+                    newIndex = 0;
+            }
+
+            newHash[newIndex] = ctxt->nsdb->hash[i];
+        }
+
+        xmlFree(ctxt->nsdb->hash);
+        ctxt->nsdb->hash = newHash;
+        ctxt->nsdb->hashSize = newSize;
+
+        /*
+         * Relookup
+         */
+        index = hashValue & (newSize - 1);
+
+        while (newHash[index].hashValue != 0) {
+            index++;
+            if (index == newSize)
+                index = 0;
+        }
+
+        bucket = &newHash[index];
+    }
+
+    bucket->hashValue = hashValue;
+    bucket->index = ctxt->nsNr;
+    ctxt->nsdb->hashElems++;
+    oldIndex = INT_MAX;
+
+populate_entry:
+    nsIndex = ctxt->nsNr;
+
+    ns = &ctxt->nsTab[nsIndex * 2];
+    ns[0] = prefix ? prefix->name : NULL;
+    ns[1] = uri->name;
+
+    extra = &ctxt->nsdb->extra[nsIndex];
+    extra->saxData = saxData;
+    extra->prefixHashValue = prefix ? prefix->hashValue : 0;
+    extra->uriHashValue = uri->hashValue;
+    extra->elementId = ctxt->nsdb->elementId;
+    extra->oldIndex = oldIndex;
+
+    ctxt->nsNr++;
+
+    return(1);
+}
+
+/**
+ * xmlParserNsPop:
+ * @ctxt: an XML parser context
+ * @nr:  the number to pop
+ *
+ * Pops the top @nr namespaces and restores the hash table.
+ *
+ * Returns the number of namespaces popped.
+ */
+static int
+xmlParserNsPop(xmlParserCtxtPtr ctxt, int nr)
+{
+    int i;
+
+    /* assert(nr <= ctxt->nsNr); */
+
+    for (i = ctxt->nsNr - 1; i >= ctxt->nsNr - nr; i--) {
+        const xmlChar *prefix = ctxt->nsTab[i * 2];
+        xmlParserNsExtra *extra = &ctxt->nsdb->extra[i];
+
+        if (prefix == NULL) {
+            ctxt->nsdb->defaultNsIndex = extra->oldIndex;
+        } else {
+            xmlHashedString hprefix;
+            xmlParserNsBucket *bucket = NULL;
+
+            hprefix.name = prefix;
+            hprefix.hashValue = extra->prefixHashValue;
+            xmlParserNsLookup(ctxt, &hprefix, &bucket);
+            /* assert(bucket && bucket->hashValue); */
+            bucket->index = extra->oldIndex;
+        }
+    }
+
+    ctxt->nsNr -= nr;
+    return(nr);
+}
+
+static int
+xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
+    const xmlChar **atts;
+    unsigned *attallocs;
+    int maxatts;
+
+    if (nr + 5 > ctxt->maxatts) {
+	maxatts = ctxt->maxatts == 0 ? 55 : (nr + 5) * 2;
+	atts = (const xmlChar **) xmlMalloc(
+				     maxatts * sizeof(const xmlChar *));
+	if (atts == NULL) goto mem_error;
+	attallocs = xmlRealloc(ctxt->attallocs,
+                               (maxatts / 5) * sizeof(attallocs[0]));
+	if (attallocs == NULL) {
+            xmlFree(atts);
+            goto mem_error;
+        }
+        if (ctxt->maxatts > 0)
+            memcpy(atts, ctxt->atts, ctxt->maxatts * sizeof(const xmlChar *));
+        xmlFree(ctxt->atts);
+	ctxt->atts = atts;
+	ctxt->attallocs = attallocs;
+	ctxt->maxatts = maxatts;
+    }
+    return(ctxt->maxatts);
+mem_error:
+    xmlErrMemory(ctxt);
+    return(-1);
+}
+
+/**
+ * inputPush:
+ * @ctxt:  an XML parser context
+ * @value:  the parser input
+ *
+ * Pushes a new parser input on top of the input stack
+ *
+ * Returns -1 in case of error, the index in the stack otherwise
+ */
+int
+inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
+{
+    char *directory = NULL;
+
+    if ((ctxt == NULL) || (value == NULL))
+        return(-1);
+
+    if (ctxt->inputNr >= ctxt->inputMax) {
+        size_t newSize = ctxt->inputMax * 2;
+        xmlParserInputPtr *tmp;
+
+        tmp = (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
+                                               newSize * sizeof(*tmp));
+        if (tmp == NULL) {
+            xmlErrMemory(ctxt);
+            return (-1);
+        }
+        ctxt->inputTab = tmp;
+        ctxt->inputMax = newSize;
+    }
+
+    if ((ctxt->inputNr == 0) && (value->filename != NULL)) {
+        directory = xmlParserGetDirectory(value->filename);
+        if (directory == NULL) {
+            xmlErrMemory(ctxt);
+            return(-1);
+        }
+    }
+
+    ctxt->inputTab[ctxt->inputNr] = value;
+    ctxt->input = value;
+
+    if (ctxt->inputNr == 0) {
+        xmlFree(ctxt->directory);
+        ctxt->directory = directory;
+    }
+
+    return(ctxt->inputNr++);
+}
+/**
+ * inputPop:
+ * @ctxt: an XML parser context
+ *
+ * Pops the top parser input from the input stack
+ *
+ * Returns the input just removed
+ */
+xmlParserInputPtr
+inputPop(xmlParserCtxtPtr ctxt)
+{
+    xmlParserInputPtr ret;
 
     if (ctxt == NULL)
         return(NULL);
@@ -1791,6 +2008,8 @@ inputPop(xmlParserCtxtPtr ctxt)
  * @ctxt:  an XML parser context
  * @value:  the element node
  *
+ * DEPRECATED: Internal function, do not use.
+ *
  * Pushes a new element node on top of the node stack
  *
  * Returns -1 in case of error, the index in the stack otherwise
@@ -1798,7 +2017,19 @@ inputPop(xmlParserCtxtPtr ctxt)
 int
 nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
 {
-    if (ctxt == NULL) return(0);
+    int maxDepth;
+
+    if (ctxt == NULL)
+        return(0);
+
+    maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 2048 : 256;
+    if (ctxt->nodeNr > maxDepth) {
+        xmlFatalErrMsgInt(ctxt, XML_ERR_RESOURCE_LIMIT,
+                "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
+                ctxt->nodeNr);
+        xmlHaltParser(ctxt);
+        return(-1);
+    }
     if (ctxt->nodeNr >= ctxt->nodeMax) {
         xmlNodePtr *tmp;
 
@@ -1806,20 +2037,12 @@ nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
                                       ctxt->nodeMax * 2 *
                                       sizeof(ctxt->nodeTab[0]));
         if (tmp == NULL) {
-            xmlErrMemory(ctxt, NULL);
+            xmlErrMemory(ctxt);
             return (-1);
         }
         ctxt->nodeTab = tmp;
 	ctxt->nodeMax *= 2;
     }
-    if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
-        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-	xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
-		 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
-			  xmlParserMaxDepth);
-	xmlHaltParser(ctxt);
-	return(-1);
-    }
     ctxt->nodeTab[ctxt->nodeNr] = value;
     ctxt->node = value;
     return (ctxt->nodeNr++);
@@ -1829,6 +2052,8 @@ nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
  * nodePop:
  * @ctxt: an XML parser context
  *
+ * DEPRECATED: Internal function, do not use.
+ *
  * Pops the top element node from the node stack
  *
  * Returns the node just removed
@@ -1905,7 +2130,7 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
     tag->nsNr = nsNr;
     return (ctxt->nameNr++);
 mem_error:
-    xmlErrMemory(ctxt, NULL);
+    xmlErrMemory(ctxt);
     return (-1);
 }
 #ifdef LIBXML_PUSH_ENABLED
@@ -1940,6 +2165,8 @@ nameNsPop(xmlParserCtxtPtr ctxt)
  * @ctxt:  an XML parser context
  * @value:  the element name
  *
+ * DEPRECATED: Internal function, do not use.
+ *
  * Pushes a new element name on top of the name stack
  *
  * Returns -1 in case of error, the index in the stack otherwise
@@ -1964,13 +2191,16 @@ namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
     ctxt->name = value;
     return (ctxt->nameNr++);
 mem_error:
-    xmlErrMemory(ctxt, NULL);
+    xmlErrMemory(ctxt);
     return (-1);
 }
+
 /**
  * namePop:
  * @ctxt: an XML parser context
  *
+ * DEPRECATED: Internal function, do not use.
+ *
  * Pops the top element name from the name stack
  *
  * Returns the name just removed
@@ -2000,7 +2230,7 @@ static int spacePush(xmlParserCtxtPtr ctxt, int val) {
         tmp = (int *) xmlRealloc(ctxt->spaceTab,
 	                         ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
         if (tmp == NULL) {
-	    xmlErrMemory(ctxt, NULL);
+	    xmlErrMemory(ctxt);
 	    ctxt->spaceMax /=2;
 	    return(-1);
 	}
@@ -2086,7 +2316,7 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
 #define SKIP(val) do {							\
     ctxt->input->cur += (val),ctxt->input->col+=(val);			\
     if (*ctxt->input->cur == 0)						\
-        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);			\
+        xmlParserGrow(ctxt);						\
   } while (0)
 
 #define SKIPL(val) do {							\
@@ -2098,57 +2328,31 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
 	ctxt->input->cur++;						\
     }									\
     if (*ctxt->input->cur == 0)						\
-        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);			\
+        xmlParserGrow(ctxt);						\
   } while (0)
 
-#define SHRINK if ((ctxt->progressive == 0) &&				\
-		   (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
-		   (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
-	xmlSHRINK (ctxt);
+#define SHRINK \
+    if ((!PARSER_PROGRESSIVE(ctxt)) && \
+        (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
+	(ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
+	xmlParserShrink(ctxt);
 
-static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
-    xmlParserInputShrink(ctxt->input);
-    if (*ctxt->input->cur == 0)
-        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-}
-
-#define GROW if ((ctxt->progressive == 0) &&				\
-		 (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))	\
-	xmlGROW (ctxt);
-
-static void xmlGROW (xmlParserCtxtPtr ctxt) {
-    ptrdiff_t curEnd = ctxt->input->end - ctxt->input->cur;
-    ptrdiff_t curBase = ctxt->input->cur - ctxt->input->base;
-
-    if (((curEnd > XML_MAX_LOOKUP_LIMIT) ||
-         (curBase > XML_MAX_LOOKUP_LIMIT)) &&
-         ((ctxt->input->buf) &&
-          (ctxt->input->buf->readcallback != xmlInputReadCallbackNop)) &&
-        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
-        xmlHaltParser(ctxt);
-	return;
-    }
-    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-    if ((ctxt->input->cur > ctxt->input->end) ||
-        (ctxt->input->cur < ctxt->input->base)) {
-        xmlHaltParser(ctxt);
-        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "cur index out of bound");
-	return;
-    }
-    if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0))
-        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-}
+#define GROW \
+    if ((!PARSER_PROGRESSIVE(ctxt)) && \
+        (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \
+	xmlParserGrow(ctxt);
 
 #define SKIP_BLANKS xmlSkipBlankChars(ctxt)
 
+#define SKIP_BLANKS_PE xmlSkipBlankCharsPE(ctxt)
+
 #define NEXT xmlNextChar(ctxt)
 
 #define NEXT1 {								\
 	ctxt->input->col++;						\
 	ctxt->input->cur++;						\
 	if (*ctxt->input->cur == 0)					\
-	    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);		\
+	    xmlParserGrow(ctxt);						\
     }
 
 #define NEXTL(l) do {							\
@@ -2161,86 +2365,156 @@ static void xmlGROW (xmlParserCtxtPtr ctxt) {
 #define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
 #define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
 
-#define COPY_BUF(l,b,i,v)						\
-    if (l == 1) b[i++] = (xmlChar) v;					\
+#define COPY_BUF(b, i, v)						\
+    if (v < 0x80) b[i++] = v;						\
     else i += xmlCopyCharMultiByte(&b[i],v)
 
-#define CUR_CONSUMED \
-    (ctxt->input->consumed + (ctxt->input->cur - ctxt->input->base))
-
 /**
  * xmlSkipBlankChars:
  * @ctxt:  the XML parser context
  *
- * skip all blanks character found at that point in the input streams.
- * It pops up finished entities in the process if allowable at that point.
+ * DEPRECATED: Internal function, do not use.
+ *
+ * Skip whitespace in the input stream.
  *
  * Returns the number of space chars skipped
  */
-
 int
 xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
+    const xmlChar *cur;
     int res = 0;
 
     /*
      * It's Okay to use CUR/NEXT here since all the blanks are on
      * the ASCII range.
      */
-    if (((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) ||
-        (ctxt->instate == XML_PARSER_START)) {
-	const xmlChar *cur;
-	/*
-	 * if we are in the document content, go really fast
-	 */
-	cur = ctxt->input->cur;
-	while (IS_BLANK_CH(*cur)) {
-	    if (*cur == '\n') {
-		ctxt->input->line++; ctxt->input->col = 1;
-	    } else {
-		ctxt->input->col++;
-	    }
-	    cur++;
-	    if (res < INT_MAX)
-		res++;
-	    if (*cur == 0) {
-		ctxt->input->cur = cur;
-		xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-		cur = ctxt->input->cur;
-	    }
-	}
-	ctxt->input->cur = cur;
-    } else {
-        int expandPE = ((ctxt->external != 0) || (ctxt->inputNr != 1));
-
-	while (1) {
-            if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */
-		NEXT;
-	    } else if (CUR == '%') {
-                /*
-                 * Need to handle support of entities branching here
-                 */
-	        if ((expandPE == 0) || (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0))
-                    break;
-	        xmlParsePEReference(ctxt);
-            } else if (CUR == 0) {
-                if (ctxt->inputNr <= 1)
-                    break;
-                xmlPopInput(ctxt);
-            } else {
-                break;
-            }
-
-            /*
-             * Also increase the counter when entering or exiting a PERef.
-             * The spec says: "When a parameter-entity reference is recognized
-             * in the DTD and included, its replacement text MUST be enlarged
-             * by the attachment of one leading and one following space (#x20)
-             * character."
-             */
-	    if (res < INT_MAX)
-		res++;
+    cur = ctxt->input->cur;
+    while (IS_BLANK_CH(*cur)) {
+        if (*cur == '\n') {
+            ctxt->input->line++; ctxt->input->col = 1;
+        } else {
+            ctxt->input->col++;
         }
+        cur++;
+        if (res < INT_MAX)
+            res++;
+        if (*cur == 0) {
+            ctxt->input->cur = cur;
+            xmlParserGrow(ctxt);
+            cur = ctxt->input->cur;
+        }
+    }
+    ctxt->input->cur = cur;
+
+    return(res);
+}
+
+static void
+xmlPopPE(xmlParserCtxtPtr ctxt) {
+    unsigned long consumed;
+    xmlEntityPtr ent;
+
+    ent = ctxt->input->entity;
+
+    ent->flags &= ~XML_ENT_EXPANDING;
+
+    if ((ent->flags & XML_ENT_CHECKED) == 0) {
+        int result;
+
+        /*
+         * Read the rest of the stream in case of errors. We want
+         * to account for the whole entity size.
+         */
+        do {
+            ctxt->input->cur = ctxt->input->end;
+            xmlParserShrink(ctxt);
+            result = xmlParserGrow(ctxt);
+        } while (result > 0);
+
+        consumed = ctxt->input->consumed;
+        xmlSaturatedAddSizeT(&consumed,
+                             ctxt->input->end - ctxt->input->base);
+
+        xmlSaturatedAdd(&ent->expandedSize, consumed);
+
+        /*
+         * Add to sizeentities when parsing an external entity
+         * for the first time.
+         */
+        if (ent->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
+            xmlSaturatedAdd(&ctxt->sizeentities, consumed);
+        }
+
+        ent->flags |= XML_ENT_CHECKED;
+    }
+
+    xmlPopInput(ctxt);
+
+    xmlParserEntityCheck(ctxt, ent->expandedSize);
+}
+
+/**
+ * xmlSkipBlankCharsPE:
+ * @ctxt:  the XML parser context
+ *
+ * Skip whitespace in the input stream, also handling parameter
+ * entities.
+ *
+ * Returns the number of space chars skipped
+ */
+static int
+xmlSkipBlankCharsPE(xmlParserCtxtPtr ctxt) {
+    int res = 0;
+    int inParam;
+    int expandParam;
+
+    inParam = PARSER_IN_PE(ctxt);
+    expandParam = PARSER_EXTERNAL(ctxt);
+
+    if (!inParam && !expandParam)
+        return(xmlSkipBlankChars(ctxt));
+
+    while (PARSER_STOPPED(ctxt) == 0) {
+        if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */
+            NEXT;
+        } else if (CUR == '%') {
+            if ((expandParam == 0) ||
+                (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0))
+                break;
+
+            /*
+             * Expand parameter entity. We continue to consume
+             * whitespace at the start of the entity and possible
+             * even consume the whole entity and pop it. We might
+             * even pop multiple PEs in this loop.
+             */
+            xmlParsePEReference(ctxt);
+
+            inParam = PARSER_IN_PE(ctxt);
+            expandParam = PARSER_EXTERNAL(ctxt);
+        } else if (CUR == 0) {
+            if (inParam == 0)
+                break;
+
+            xmlPopPE(ctxt);
+
+            inParam = PARSER_IN_PE(ctxt);
+            expandParam = PARSER_EXTERNAL(ctxt);
+        } else {
+            break;
+        }
+
+        /*
+         * Also increase the counter when entering or exiting a PERef.
+         * The spec says: "When a parameter-entity reference is recognized
+         * in the DTD and included, its replacement text MUST be enlarged
+         * by the attachment of one leading and one following space (#x20)
+         * character."
+         */
+        if (res < INT_MAX)
+            res++;
     }
+
     return(res);
 }
 
@@ -2261,17 +2535,13 @@ xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
  */
 xmlChar
 xmlPopInput(xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr input;
+
     if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
-    if (xmlParserDebugEntities)
-	xmlGenericError(xmlGenericErrorContext,
-		"Popping input %d\n", ctxt->inputNr);
-    if ((ctxt->inputNr > 1) && (ctxt->inSubset == 0) &&
-        (ctxt->instate != XML_PARSER_EOF))
-        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-                    "Unfinished entity outside the DTD");
-    xmlFreeInputStream(inputPop(ctxt));
+    input = inputPop(ctxt);
+    xmlFreeInputStream(input);
     if (*ctxt->input->cur == 0)
-        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+        xmlParserGrow(ctxt);
     return(CUR);
 }
 
@@ -2280,33 +2550,26 @@ xmlPopInput(xmlParserCtxtPtr ctxt) {
  * @ctxt:  an XML parser context
  * @input:  an XML parser input fragment (entity, XML fragment ...).
  *
- * xmlPushInput: switch to a new input stream which is stacked on top
- *               of the previous one(s).
+ * Push an input stream onto the stack.
+ *
  * Returns -1 in case of error or the index in the input stack
  */
 int
 xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
+    int maxDepth;
     int ret;
-    if (input == NULL) return(-1);
-
-    if (xmlParserDebugEntities) {
-	if ((ctxt->input != NULL) && (ctxt->input->filename))
-	    xmlGenericError(xmlGenericErrorContext,
-		    "%s(%d): ", ctxt->input->filename,
-		    ctxt->input->line);
-	xmlGenericError(xmlGenericErrorContext,
-		"Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
-    }
-    if (((ctxt->inputNr > 40) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
-        (ctxt->inputNr > 1024)) {
-        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
-        while (ctxt->inputNr > 1)
-            xmlFreeInputStream(inputPop(ctxt));
+
+    if ((ctxt == NULL) || (input == NULL))
+        return(-1);
+
+    maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20;
+    if (ctxt->inputNr > maxDepth) {
+        xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
+                       "Maximum entity nesting depth exceeded");
+        xmlHaltParser(ctxt);
 	return(-1);
     }
     ret = inputPush(ctxt, input);
-    if (ctxt->instate == XML_PARSER_EOF)
-        return(-1);
     GROW;
     return(ret);
 }
@@ -2315,7 +2578,9 @@ xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
  * xmlParseCharRef:
  * @ctxt:  an XML parser context
  *
- * parse Reference declarations
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Parse a numeric character reference. Always consumes '&'.
  *
  * [66] CharRef ::= '&#' [0-9]+ ';' |
  *                  '&#x' [0-9a-fA-F]+ ';'
@@ -2338,12 +2603,10 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
         (NXT(2) == 'x')) {
 	SKIP(3);
 	GROW;
-	while (RAW != ';') { /* loop blocked by count */
+	while ((RAW != ';') && (PARSER_STOPPED(ctxt) == 0)) {
 	    if (count++ > 20) {
 		count = 0;
 		GROW;
-                if (ctxt->instate == XML_PARSER_EOF)
-                    return(0);
 	    }
 	    if ((RAW >= '0') && (RAW <= '9'))
 	        val = val * 16 + (CUR - '0');
@@ -2374,8 +2637,6 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
 	    if (count++ > 20) {
 		count = 0;
 		GROW;
-                if (ctxt->instate == XML_PARSER_EOF)
-                    return(0);
 	    }
 	    if ((RAW >= '0') && (RAW <= '9'))
 	        val = val * 10 + (CUR - '0');
@@ -2396,6 +2657,8 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
 	    ctxt->input->cur++;
 	}
     } else {
+        if (RAW == '&')
+            SKIP(1);
         xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
     }
 
@@ -2516,6 +2779,8 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
  * xmlParserHandlePEReference:
  * @ctxt:  the parser context
  *
+ * DEPRECATED: Internal function, do not use.
+ *
  * [69] PEReference ::= '%' Name ';'
  *
  * [ WFC: No Recursion ]
@@ -2546,78 +2811,9 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
  */
 void
 xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
-    switch(ctxt->instate) {
-	case XML_PARSER_CDATA_SECTION:
-	    return;
-        case XML_PARSER_COMMENT:
-	    return;
-	case XML_PARSER_START_TAG:
-	    return;
-	case XML_PARSER_END_TAG:
-	    return;
-        case XML_PARSER_EOF:
-	    xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
-	    return;
-        case XML_PARSER_PROLOG:
-	case XML_PARSER_START:
-	case XML_PARSER_MISC:
-	    xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
-	    return;
-	case XML_PARSER_ENTITY_DECL:
-        case XML_PARSER_CONTENT:
-        case XML_PARSER_ATTRIBUTE_VALUE:
-        case XML_PARSER_PI:
-	case XML_PARSER_SYSTEM_LITERAL:
-	case XML_PARSER_PUBLIC_LITERAL:
-	    /* we just ignore it there */
-	    return;
-        case XML_PARSER_EPILOG:
-	    xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
-	    return;
-	case XML_PARSER_ENTITY_VALUE:
-	    /*
-	     * NOTE: in the case of entity values, we don't do the
-	     *       substitution here since we need the literal
-	     *       entity value to be able to save the internal
-	     *       subset of the document.
-	     *       This will be handled by xmlStringDecodeEntities
-	     */
-	    return;
-        case XML_PARSER_DTD:
-	    /*
-	     * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
-	     * In the internal DTD subset, parameter-entity references
-	     * can occur only where markup declarations can occur, not
-	     * within markup declarations.
-	     * In that case this is handled in xmlParseMarkupDecl
-	     */
-	    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
-		return;
-	    if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
-		return;
-            break;
-        case XML_PARSER_IGNORE:
-            return;
-    }
-
     xmlParsePEReference(ctxt);
 }
 
-/*
- * Macro used to grow the current buffer.
- * buffer##_size is expected to be a size_t
- * mem_error: is expected to handle memory allocation failures
- */
-#define growBuffer(buffer, n) {						\
-    xmlChar *tmp;							\
-    size_t new_size = buffer##_size * 2 + n;                            \
-    if (new_size < buffer##_size) goto mem_error;                       \
-    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
-    if (tmp == NULL) goto mem_error;					\
-    buffer = tmp;							\
-    buffer##_size = new_size;                                           \
-}
-
 /**
  * xmlStringLenDecodeEntities:
  * @ctxt:  the parser context
@@ -2628,191 +2824,23 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
  * @end2:  an end marker xmlChar, 0 if none
  * @end3:  an end marker xmlChar, 0 if none
  *
- * Takes a entity string content and process to do the adequate substitutions.
- *
- * [67] Reference ::= EntityRef | CharRef
- *
- * [69] PEReference ::= '%' Name ';'
+ * DEPRECATED: Internal function, don't use.
  *
  * Returns A newly allocated string with the substitution done. The caller
  *      must deallocate it !
  */
 xmlChar *
 xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
-		      int what, xmlChar end, xmlChar  end2, xmlChar end3) {
-    xmlChar *buffer = NULL;
-    size_t buffer_size = 0;
-    size_t nbchars = 0;
-
-    xmlChar *current = NULL;
-    xmlChar *rep = NULL;
-    const xmlChar *last;
-    xmlEntityPtr ent;
-    int c,l;
-
+                           int what ATTRIBUTE_UNUSED,
+                           xmlChar end, xmlChar end2, xmlChar end3) {
     if ((ctxt == NULL) || (str == NULL) || (len < 0))
-	return(NULL);
-    last = str + len;
-
-    if (((ctxt->depth > 40) &&
-         ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
-	(ctxt->depth > 1024)) {
-	xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
-	return(NULL);
-    }
-
-    /*
-     * allocate a translation buffer.
-     */
-    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
-    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
-    if (buffer == NULL) goto mem_error;
-
-    /*
-     * OK loop until we reach one of the ending char or a size limit.
-     * we are operating on already parsed values.
-     */
-    if (str < last)
-	c = CUR_SCHAR(str, l);
-    else
-        c = 0;
-    while ((c != 0) && (c != end) && /* non input consuming loop */
-           (c != end2) && (c != end3) &&
-           (ctxt->instate != XML_PARSER_EOF)) {
-
-	if (c == 0) break;
-        if ((c == '&') && (str[1] == '#')) {
-	    int val = xmlParseStringCharRef(ctxt, &str);
-	    if (val == 0)
-                goto int_error;
-	    COPY_BUF(0,buffer,nbchars,val);
-	    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
-	        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
-	    }
-	} else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
-	    if (xmlParserDebugEntities)
-		xmlGenericError(xmlGenericErrorContext,
-			"String decoding Entity Reference: %.30s\n",
-			str);
-	    ent = xmlParseStringEntityRef(ctxt, &str);
-	    xmlParserEntityCheck(ctxt, 0, ent, 0);
-	    if (ent != NULL)
-	        ctxt->nbentities += ent->checked / 2;
-	    if ((ent != NULL) &&
-		(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
-		if (ent->content != NULL) {
-		    COPY_BUF(0,buffer,nbchars,ent->content[0]);
-		    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
-			growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
-		    }
-		} else {
-		    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
-			    "predefined entity has no content\n");
-                    goto int_error;
-		}
-	    } else if ((ent != NULL) && (ent->content != NULL)) {
-		ctxt->depth++;
-		rep = xmlStringDecodeEntities(ctxt, ent->content, what,
-			                      0, 0, 0);
-		ctxt->depth--;
-		if (rep == NULL) {
-                    ent->content[0] = 0;
-                    goto int_error;
-                }
+        return(NULL);
 
-                current = rep;
-                while (*current != 0) { /* non input consuming loop */
-                    buffer[nbchars++] = *current++;
-                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
-                        if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
-                            goto int_error;
-                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
-                    }
-                }
-                xmlFree(rep);
-                rep = NULL;
-	    } else if (ent != NULL) {
-		int i = xmlStrlen(ent->name);
-		const xmlChar *cur = ent->name;
-
-		buffer[nbchars++] = '&';
-		if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
-		    growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
-		}
-		for (;i > 0;i--)
-		    buffer[nbchars++] = *cur++;
-		buffer[nbchars++] = ';';
-	    }
-	} else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
-	    if (xmlParserDebugEntities)
-		xmlGenericError(xmlGenericErrorContext,
-			"String decoding PE Reference: %.30s\n", str);
-	    ent = xmlParseStringPEReference(ctxt, &str);
-	    xmlParserEntityCheck(ctxt, 0, ent, 0);
-	    if (ent != NULL)
-	        ctxt->nbentities += ent->checked / 2;
-	    if (ent != NULL) {
-                if (ent->content == NULL) {
-		    /*
-		     * Note: external parsed entities will not be loaded,
-		     * it is not required for a non-validating parser to
-		     * complete external PEReferences coming from the
-		     * internal subset
-		     */
-		    if (((ctxt->options & XML_PARSE_NOENT) != 0) ||
-			((ctxt->options & XML_PARSE_DTDVALID) != 0) ||
-			(ctxt->validate != 0)) {
-			xmlLoadEntityContent(ctxt, ent);
-		    } else {
-			xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
-		  "not validating will not read content for PE entity %s\n",
-		                      ent->name, NULL);
-		    }
-		}
-		ctxt->depth++;
-		rep = xmlStringDecodeEntities(ctxt, ent->content, what,
-			                      0, 0, 0);
-		ctxt->depth--;
-		if (rep == NULL) {
-                    if (ent->content != NULL)
-                        ent->content[0] = 0;
-                    goto int_error;
-                }
-                current = rep;
-                while (*current != 0) { /* non input consuming loop */
-                    buffer[nbchars++] = *current++;
-                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
-                        if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
-                            goto int_error;
-                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
-                    }
-                }
-                xmlFree(rep);
-                rep = NULL;
-	    }
-	} else {
-	    COPY_BUF(l,buffer,nbchars,c);
-	    str += l;
-	    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
-	        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
-	    }
-	}
-	if (str < last)
-	    c = CUR_SCHAR(str, l);
-	else
-	    c = 0;
-    }
-    buffer[nbchars] = 0;
-    return(buffer);
+    if ((str[len] != 0) ||
+        (end != 0) || (end2 != 0) || (end3 != 0))
+        return(NULL);
 
-mem_error:
-    xmlErrMemory(ctxt, NULL);
-int_error:
-    if (rep != NULL)
-        xmlFree(rep);
-    if (buffer != NULL)
-        xmlFree(buffer);
-    return(NULL);
+    return(xmlExpandEntitiesInAttValue(ctxt, str, 0));
 }
 
 /**
@@ -2824,21 +2852,22 @@ int_error:
  * @end2:  an end marker xmlChar, 0 if none
  * @end3:  an end marker xmlChar, 0 if none
  *
- * Takes a entity string content and process to do the adequate substitutions.
- *
- * [67] Reference ::= EntityRef | CharRef
- *
- * [69] PEReference ::= '%' Name ';'
+ * DEPRECATED: Internal function, don't use.
  *
  * Returns A newly allocated string with the substitution done. The caller
  *      must deallocate it !
  */
 xmlChar *
-xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
+xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
+                        int what ATTRIBUTE_UNUSED,
 		        xmlChar end, xmlChar  end2, xmlChar end3) {
-    if ((ctxt == NULL) || (str == NULL)) return(NULL);
-    return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
-           end, end2, end3));
+    if ((ctxt == NULL) || (str == NULL))
+        return(NULL);
+
+    if ((end != 0) || (end2 != 0) || (end3 != 0))
+        return(NULL);
+
+    return(xmlExpandEntitiesInAttValue(ctxt, str, 0));
 }
 
 /************************************************************************
@@ -2861,7 +2890,7 @@ xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
 
 static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
                      int blank_chars) {
-    int i, ret;
+    int i;
     xmlNodePtr lastChild;
 
     /*
@@ -2891,9 +2920,25 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
      */
     if (ctxt->node == NULL) return(0);
     if (ctxt->myDoc != NULL) {
-	ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
-        if (ret == 0) return(1);
-        if (ret == 1) return(0);
+        xmlElementPtr elemDecl = NULL;
+        xmlDocPtr doc = ctxt->myDoc;
+        const xmlChar *prefix = NULL;
+
+        if (ctxt->node->ns)
+            prefix = ctxt->node->ns->prefix;
+        if (doc->intSubset != NULL)
+            elemDecl = xmlHashLookup2(doc->intSubset->elements, ctxt->node->name,
+                                      prefix);
+        if ((elemDecl == NULL) && (doc->extSubset != NULL))
+            elemDecl = xmlHashLookup2(doc->extSubset->elements, ctxt->node->name,
+                                      prefix);
+        if (elemDecl != NULL) {
+            if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)
+                return(1);
+            if ((elemDecl->etype == XML_ELEMENT_TYPE_ANY) ||
+                (elemDecl->etype == XML_ELEMENT_TYPE_MIXED))
+                return(0);
+        }
     }
 
     /*
@@ -2926,7 +2971,7 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
  * xmlSplitQName:
  * @ctxt:  an XML parser context
  * @name:  an XML parser context
- * @prefix:  a xmlChar **
+ * @prefixOut:  a xmlChar **
  *
  * parse an UTF8 encoded XML qualified name string
  *
@@ -2941,27 +2986,21 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
  */
 
 xmlChar *
-xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
+xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefixOut) {
     xmlChar buf[XML_MAX_NAMELEN + 5];
     xmlChar *buffer = NULL;
     int len = 0;
     int max = XML_MAX_NAMELEN;
     xmlChar *ret = NULL;
+    xmlChar *prefix;
     const xmlChar *cur = name;
     int c;
 
-    if (prefix == NULL) return(NULL);
-    *prefix = NULL;
+    if (prefixOut == NULL) return(NULL);
+    *prefixOut = NULL;
 
     if (cur == NULL) return(NULL);
 
-#ifndef XML_XML_NAMESPACE
-    /* xml: prefix is not really a namespace */
-    if ((cur[0] == 'x') && (cur[1] == 'm') &&
-        (cur[2] == 'l') && (cur[3] == ':'))
-	return(xmlStrdup(name));
-#endif
-
     /* nasty but well=formed */
     if (cur[0] == ':')
 	return(xmlStrdup(name));
@@ -2978,9 +3017,9 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
 	 */
 	max = len * 2;
 
-	buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
+	buffer = (xmlChar *) xmlMallocAtomic(max);
 	if (buffer == NULL) {
-	    xmlErrMemory(ctxt, NULL);
+	    xmlErrMemory(ctxt);
 	    return(NULL);
 	}
 	memcpy(buffer, buf, len);
@@ -2989,11 +3028,10 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
 	        xmlChar *tmp;
 
 		max *= 2;
-		tmp = (xmlChar *) xmlRealloc(buffer,
-						max * sizeof(xmlChar));
+		tmp = (xmlChar *) xmlRealloc(buffer, max);
 		if (tmp == NULL) {
 		    xmlFree(buffer);
-		    xmlErrMemory(ctxt, NULL);
+		    xmlErrMemory(ctxt);
 		    return(NULL);
 		}
 		buffer = tmp;
@@ -3007,13 +3045,16 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
     if ((c == ':') && (*cur == 0)) {
         if (buffer != NULL)
 	    xmlFree(buffer);
-	*prefix = NULL;
 	return(xmlStrdup(name));
     }
 
-    if (buffer == NULL)
+    if (buffer == NULL) {
 	ret = xmlStrndup(buf, len);
-    else {
+        if (ret == NULL) {
+	    xmlErrMemory(ctxt);
+	    return(NULL);
+        }
+    } else {
 	ret = buffer;
 	buffer = NULL;
 	max = XML_MAX_NAMELEN;
@@ -3022,9 +3063,15 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
 
     if (c == ':') {
 	c = *cur;
-        *prefix = ret;
+        prefix = ret;
 	if (c == 0) {
-	    return(xmlStrndup(BAD_CAST "", 0));
+	    ret = xmlStrndup(BAD_CAST "", 0);
+            if (ret == NULL) {
+                xmlFree(prefix);
+                return(NULL);
+            }
+            *prefixOut = prefix;
+            return(ret);
 	}
 	len = 0;
 
@@ -3057,9 +3104,10 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
 	     */
 	    max = len * 2;
 
-	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
+	    buffer = (xmlChar *) xmlMallocAtomic(max);
 	    if (buffer == NULL) {
-	        xmlErrMemory(ctxt, NULL);
+	        xmlErrMemory(ctxt);
+                xmlFree(prefix);
 		return(NULL);
 	    }
 	    memcpy(buffer, buf, len);
@@ -3068,10 +3116,10 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
 		    xmlChar *tmp;
 
 		    max *= 2;
-		    tmp = (xmlChar *) xmlRealloc(buffer,
-						    max * sizeof(xmlChar));
+		    tmp = (xmlChar *) xmlRealloc(buffer, max);
 		    if (tmp == NULL) {
-			xmlErrMemory(ctxt, NULL);
+			xmlErrMemory(ctxt);
+                        xmlFree(prefix);
 			xmlFree(buffer);
 			return(NULL);
 		    }
@@ -3083,11 +3131,17 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
 	    buffer[len] = 0;
 	}
 
-	if (buffer == NULL)
+	if (buffer == NULL) {
 	    ret = xmlStrndup(buf, len);
-	else {
+            if (ret == NULL) {
+                xmlFree(prefix);
+                return(NULL);
+            }
+	} else {
 	    ret = buffer;
 	}
+
+        *prefixOut = prefix;
     }
 
     return(ret);
@@ -3105,14 +3159,6 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
  *	Routines to parse Name, NCName and NmToken			*
  *									*
  ************************************************************************/
-#ifdef DEBUG
-static unsigned long nbParseName = 0;
-static unsigned long nbParseNmToken = 0;
-static unsigned long nbParseNCName = 0;
-static unsigned long nbParseNCNameComplex = 0;
-static unsigned long nbParseNameComplex = 0;
-static unsigned long nbParseStringName = 0;
-#endif
 
 /*
  * The two following functions are related to the change of accepted
@@ -3194,25 +3240,18 @@ xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
     return(0);
 }
 
-static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
-                                          int *len, int *alloc, int normalize);
-
 static const xmlChar *
 xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
+    const xmlChar *ret;
     int len = 0, l;
     int c;
-    int count = 0;
-
-#ifdef DEBUG
-    nbParseNameComplex++;
-#endif
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_TEXT_LENGTH :
+                    XML_MAX_NAME_LENGTH;
 
     /*
      * Handler for more complex cases
      */
-    GROW;
-    if (ctxt->instate == XML_PARSER_EOF)
-        return(NULL);
     c = CUR_CHAR(l);
     if ((ctxt->options & XML_PARSE_OLD10) == 0) {
         /*
@@ -3261,13 +3300,8 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
 	        ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
 	        ((c >= 0x10000) && (c <= 0xEFFFF))
 		)) {
-	    if (count++ > XML_PARSER_CHUNK_SIZE) {
-		count = 0;
-		GROW;
-                if (ctxt->instate == XML_PARSER_EOF)
-                    return(NULL);
-	    }
-	    len += l;
+            if (len <= INT_MAX - l)
+	        len += l;
 	    NEXTL(l);
 	    c = CUR_CHAR(l);
 	}
@@ -3287,19 +3321,13 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
 		(c == '_') || (c == ':') ||
 		(IS_COMBINING(c)) ||
 		(IS_EXTENDER(c)))) {
-	    if (count++ > XML_PARSER_CHUNK_SIZE) {
-		count = 0;
-		GROW;
-                if (ctxt->instate == XML_PARSER_EOF)
-                    return(NULL);
-	    }
-	    len += l;
+            if (len <= INT_MAX - l)
+	        len += l;
 	    NEXTL(l);
 	    c = CUR_CHAR(l);
 	}
     }
-    if ((len > XML_MAX_NAME_LENGTH) &&
-        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
+    if (len > maxLength) {
         xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
         return(NULL);
     }
@@ -3314,14 +3342,20 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
         return (NULL);
     }
     if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
-        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
-    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
+        ret = xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len);
+    else
+        ret = xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len);
+    if (ret == NULL)
+        xmlErrMemory(ctxt);
+    return(ret);
 }
 
 /**
  * xmlParseName:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an XML name.
  *
  * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
@@ -3338,14 +3372,13 @@ const xmlChar *
 xmlParseName(xmlParserCtxtPtr ctxt) {
     const xmlChar *in;
     const xmlChar *ret;
-    int count = 0;
+    size_t count = 0;
+    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                       XML_MAX_TEXT_LENGTH :
+                       XML_MAX_NAME_LENGTH;
 
     GROW;
 
-#ifdef DEBUG
-    nbParseName++;
-#endif
-
     /*
      * Accelerator for simple ASCII names
      */
@@ -3362,8 +3395,7 @@ xmlParseName(xmlParserCtxtPtr ctxt) {
 	    in++;
 	if ((*in > 0) && (*in < 0x80)) {
 	    count = in - ctxt->input->cur;
-            if ((count > XML_MAX_NAME_LENGTH) &&
-                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
+            if (count > maxLength) {
                 xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
                 return(NULL);
             }
@@ -3371,7 +3403,7 @@ xmlParseName(xmlParserCtxtPtr ctxt) {
 	    ctxt->input->cur = in;
 	    ctxt->input->col += count;
 	    if (ret == NULL)
-	        xmlErrMemory(ctxt, NULL);
+	        xmlErrMemory(ctxt);
 	    return(ret);
 	}
     }
@@ -3379,65 +3411,44 @@ xmlParseName(xmlParserCtxtPtr ctxt) {
     return(xmlParseNameComplex(ctxt));
 }
 
-static const xmlChar *
+static xmlHashedString
 xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
+    xmlHashedString ret;
     int len = 0, l;
     int c;
-    int count = 0;
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_TEXT_LENGTH :
+                    XML_MAX_NAME_LENGTH;
     size_t startPosition = 0;
 
-#ifdef DEBUG
-    nbParseNCNameComplex++;
-#endif
+    ret.name = NULL;
+    ret.hashValue = 0;
 
     /*
      * Handler for more complex cases
      */
-    GROW;
     startPosition = CUR_PTR - BASE_PTR;
     c = CUR_CHAR(l);
     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
 	(!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
-	return(NULL);
+	return(ret);
     }
 
     while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
 	   (xmlIsNameChar(ctxt, c) && (c != ':'))) {
-	if (count++ > XML_PARSER_CHUNK_SIZE) {
-            if ((len > XML_MAX_NAME_LENGTH) &&
-                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
-                return(NULL);
-            }
-	    count = 0;
-	    GROW;
-            if (ctxt->instate == XML_PARSER_EOF)
-                return(NULL);
-	}
-	len += l;
+        if (len <= INT_MAX - l)
+	    len += l;
 	NEXTL(l);
 	c = CUR_CHAR(l);
-	if (c == 0) {
-	    count = 0;
-	    /*
-	     * when shrinking to extend the buffer we really need to preserve
-	     * the part of the name we already parsed. Hence rolling back
-	     * by current length.
-	     */
-	    ctxt->input->cur -= l;
-	    GROW;
-            if (ctxt->instate == XML_PARSER_EOF)
-                return(NULL);
-	    ctxt->input->cur += l;
-	    c = CUR_CHAR(l);
-	}
     }
-    if ((len > XML_MAX_NAME_LENGTH) &&
-        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
+    if (len > maxLength) {
         xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
-        return(NULL);
+        return(ret);
     }
-    return(xmlDictLookup(ctxt->dict, (BASE_PTR + startPosition), len));
+    ret = xmlDictLookupHashed(ctxt->dict, (BASE_PTR + startPosition), len);
+    if (ret.name == NULL)
+        xmlErrMemory(ctxt);
+    return(ret);
 }
 
 /**
@@ -3455,15 +3466,16 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
  * Returns the Name parsed or NULL
  */
 
-static const xmlChar *
+static xmlHashedString
 xmlParseNCName(xmlParserCtxtPtr ctxt) {
     const xmlChar *in, *e;
-    const xmlChar *ret;
-    int count = 0;
+    xmlHashedString ret;
+    size_t count = 0;
+    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                       XML_MAX_TEXT_LENGTH :
+                       XML_MAX_NAME_LENGTH;
 
-#ifdef DEBUG
-    nbParseNCName++;
-#endif
+    ret.name = NULL;
 
     /*
      * Accelerator for simple ASCII names
@@ -3484,16 +3496,15 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) {
 	    goto complex;
 	if ((*in > 0) && (*in < 0x80)) {
 	    count = in - ctxt->input->cur;
-            if ((count > XML_MAX_NAME_LENGTH) &&
-                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
+            if (count > maxLength) {
                 xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
-                return(NULL);
+                return(ret);
             }
-	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
+	    ret = xmlDictLookupHashed(ctxt->dict, ctxt->input->cur, count);
 	    ctxt->input->cur = in;
 	    ctxt->input->col += count;
-	    if (ret == NULL) {
-	        xmlErrMemory(ctxt, NULL);
+	    if (ret.name == NULL) {
+	        xmlErrMemory(ctxt);
 	    }
 	    return(ret);
 	}
@@ -3520,8 +3531,6 @@ xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
     const xmlChar *ret;
 
     GROW;
-    if (ctxt->instate == XML_PARSER_EOF)
-        return(NULL);
 
     in = ctxt->input->cur;
     while (*in != 0 && *in == *cmp) {
@@ -3564,24 +3573,24 @@ xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
 static xmlChar *
 xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
     xmlChar buf[XML_MAX_NAMELEN + 5];
+    xmlChar *ret;
     const xmlChar *cur = *str;
     int len = 0, l;
     int c;
-
-#ifdef DEBUG
-    nbParseStringName++;
-#endif
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_TEXT_LENGTH :
+                    XML_MAX_NAME_LENGTH;
 
     c = CUR_SCHAR(cur, l);
     if (!xmlIsNameStartChar(ctxt, c)) {
 	return(NULL);
     }
 
-    COPY_BUF(l,buf,len,c);
+    COPY_BUF(buf, len, c);
     cur += l;
     c = CUR_SCHAR(cur, l);
     while (xmlIsNameChar(ctxt, c)) {
-	COPY_BUF(l,buf,len,c);
+	COPY_BUF(buf, len, c);
 	cur += l;
 	c = CUR_SCHAR(cur, l);
 	if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
@@ -3592,9 +3601,9 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
 	    xmlChar *buffer;
 	    int max = len * 2;
 
-	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
+	    buffer = (xmlChar *) xmlMallocAtomic(max);
 	    if (buffer == NULL) {
-	        xmlErrMemory(ctxt, NULL);
+	        xmlErrMemory(ctxt);
 		return(NULL);
 	    }
 	    memcpy(buffer, buf, len);
@@ -3602,44 +3611,46 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
 		if (len + 10 > max) {
 		    xmlChar *tmp;
 
-                    if ((len > XML_MAX_NAME_LENGTH) &&
-                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
-			xmlFree(buffer);
-                        return(NULL);
-                    }
 		    max *= 2;
-		    tmp = (xmlChar *) xmlRealloc(buffer,
-			                            max * sizeof(xmlChar));
+		    tmp = (xmlChar *) xmlRealloc(buffer, max);
 		    if (tmp == NULL) {
-			xmlErrMemory(ctxt, NULL);
+			xmlErrMemory(ctxt);
 			xmlFree(buffer);
 			return(NULL);
 		    }
 		    buffer = tmp;
 		}
-		COPY_BUF(l,buffer,len,c);
+		COPY_BUF(buffer, len, c);
 		cur += l;
 		c = CUR_SCHAR(cur, l);
+                if (len > maxLength) {
+                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
+                    xmlFree(buffer);
+                    return(NULL);
+                }
 	    }
 	    buffer[len] = 0;
 	    *str = cur;
 	    return(buffer);
 	}
     }
-    if ((len > XML_MAX_NAME_LENGTH) &&
-        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
+    if (len > maxLength) {
         xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
         return(NULL);
     }
     *str = cur;
-    return(xmlStrndup(buf, len));
+    ret = xmlStrndup(buf, len);
+    if (ret == NULL)
+        xmlErrMemory(ctxt);
+    return(ret);
 }
 
 /**
  * xmlParseNmtoken:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an XML Nmtoken.
  *
  * [7] Nmtoken ::= (NameChar)+
@@ -3652,34 +3663,19 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
 xmlChar *
 xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
     xmlChar buf[XML_MAX_NAMELEN + 5];
+    xmlChar *ret;
     int len = 0, l;
     int c;
-    int count = 0;
-
-#ifdef DEBUG
-    nbParseNmToken++;
-#endif
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_TEXT_LENGTH :
+                    XML_MAX_NAME_LENGTH;
 
-    GROW;
-    if (ctxt->instate == XML_PARSER_EOF)
-        return(NULL);
     c = CUR_CHAR(l);
 
     while (xmlIsNameChar(ctxt, c)) {
-	if (count++ > XML_PARSER_CHUNK_SIZE) {
-	    count = 0;
-	    GROW;
-	}
-	COPY_BUF(l,buf,len,c);
+	COPY_BUF(buf, len, c);
 	NEXTL(l);
 	c = CUR_CHAR(l);
-	if (c == 0) {
-	    count = 0;
-	    GROW;
-	    if (ctxt->instate == XML_PARSER_EOF)
-		return(NULL);
-            c = CUR_CHAR(l);
-	}
 	if (len >= XML_MAX_NAMELEN) {
 	    /*
 	     * Okay someone managed to make a huge token, so he's ready to pay
@@ -3688,41 +3684,31 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
 	    xmlChar *buffer;
 	    int max = len * 2;
 
-	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
+	    buffer = (xmlChar *) xmlMallocAtomic(max);
 	    if (buffer == NULL) {
-	        xmlErrMemory(ctxt, NULL);
+	        xmlErrMemory(ctxt);
 		return(NULL);
 	    }
 	    memcpy(buffer, buf, len);
 	    while (xmlIsNameChar(ctxt, c)) {
-		if (count++ > XML_PARSER_CHUNK_SIZE) {
-		    count = 0;
-		    GROW;
-                    if (ctxt->instate == XML_PARSER_EOF) {
-                        xmlFree(buffer);
-                        return(NULL);
-                    }
-		}
 		if (len + 10 > max) {
 		    xmlChar *tmp;
 
-                    if ((max > XML_MAX_NAME_LENGTH) &&
-                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
-                        xmlFree(buffer);
-                        return(NULL);
-                    }
 		    max *= 2;
-		    tmp = (xmlChar *) xmlRealloc(buffer,
-			                            max * sizeof(xmlChar));
+		    tmp = (xmlChar *) xmlRealloc(buffer, max);
 		    if (tmp == NULL) {
-			xmlErrMemory(ctxt, NULL);
+			xmlErrMemory(ctxt);
 			xmlFree(buffer);
 			return(NULL);
 		    }
 		    buffer = tmp;
 		}
-		COPY_BUF(l,buffer,len,c);
+		COPY_BUF(buffer, len, c);
+                if (len > maxLength) {
+                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
+                    xmlFree(buffer);
+                    return(NULL);
+                }
 		NEXTL(l);
 		c = CUR_CHAR(l);
 	    }
@@ -3732,408 +3718,815 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
     }
     if (len == 0)
         return(NULL);
-    if ((len > XML_MAX_NAME_LENGTH) &&
-        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
+    if (len > maxLength) {
         xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
         return(NULL);
     }
-    return(xmlStrndup(buf, len));
+    ret = xmlStrndup(buf, len);
+    if (ret == NULL)
+        xmlErrMemory(ctxt);
+    return(ret);
 }
 
 /**
- * xmlParseEntityValue:
- * @ctxt:  an XML parser context
- * @orig:  if non-NULL store a copy of the original entity value
- *
- * parse a value for ENTITY declarations
+ * xmlExpandPEsInEntityValue:
+ * @ctxt:  parser context
+ * @buf:  string buffer
+ * @str:  entity value
+ * @length:  size of entity value
+ * @depth:  nesting depth
  *
- * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
+ * Validate an entity value and expand parameter entities.
+ */
+static void
+xmlExpandPEsInEntityValue(xmlParserCtxtPtr ctxt, xmlSBuf *buf,
+                          const xmlChar *str, int length, int depth) {
+    int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20;
+    const xmlChar *end, *chunk;
+    int c, l;
+
+    if (str == NULL)
+        return;
+
+    depth += 1;
+    if (depth > maxDepth) {
+	xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
+                       "Maximum entity nesting depth exceeded");
+	return;
+    }
+
+    end = str + length;
+    chunk = str;
+
+    while ((str < end) && (!PARSER_STOPPED(ctxt))) {
+        c = *str;
+
+        if (c >= 0x80) {
+            l = xmlUTF8MultibyteLen(ctxt, str,
+                    "invalid character in entity value\n");
+            if (l == 0) {
+                if (chunk < str)
+                    xmlSBufAddString(buf, chunk, str - chunk);
+                xmlSBufAddReplChar(buf);
+                str += 1;
+                chunk = str;
+            } else {
+                str += l;
+            }
+        } else if (c == '&') {
+            if (str[1] == '#') {
+                if (chunk < str)
+                    xmlSBufAddString(buf, chunk, str - chunk);
+
+                c = xmlParseStringCharRef(ctxt, &str);
+                if (c == 0)
+                    return;
+
+                xmlSBufAddChar(buf, c);
+
+                chunk = str;
+            } else {
+                xmlChar *name;
+
+                /*
+                 * General entity references are checked for
+                 * syntactic validity.
+                 */
+                str++;
+                name = xmlParseStringName(ctxt, &str);
+
+                if ((name == NULL) || (*str++ != ';')) {
+                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
+                            "EntityValue: '&' forbidden except for entities "
+                            "references\n");
+                    xmlFree(name);
+                    return;
+                }
+
+                xmlFree(name);
+            }
+        } else if (c == '%') {
+            xmlEntityPtr ent;
+
+            if (chunk < str)
+                xmlSBufAddString(buf, chunk, str - chunk);
+
+            ent = xmlParseStringPEReference(ctxt, &str);
+            if (ent == NULL)
+                return;
+
+            if (!PARSER_EXTERNAL(ctxt)) {
+                xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
+                return;
+            }
+
+            if (ent->content == NULL) {
+                /*
+                 * Note: external parsed entities will not be loaded,
+                 * it is not required for a non-validating parser to
+                 * complete external PEReferences coming from the
+                 * internal subset
+                 */
+                if (((ctxt->options & XML_PARSE_NO_XXE) == 0) &&
+                    ((ctxt->replaceEntities) ||
+                     (ctxt->validate))) {
+                    xmlLoadEntityContent(ctxt, ent);
+                } else {
+                    xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
+                                  "not validating will not read content for "
+                                  "PE entity %s\n", ent->name, NULL);
+                }
+            }
+
+            /*
+             * TODO: Skip if ent->content is still NULL.
+             */
+
+            if (xmlParserEntityCheck(ctxt, ent->length))
+                return;
+
+            if (ent->flags & XML_ENT_EXPANDING) {
+                xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+                xmlHaltParser(ctxt);
+                return;
+            }
+
+            ent->flags |= XML_ENT_EXPANDING;
+            xmlExpandPEsInEntityValue(ctxt, buf, ent->content, ent->length,
+                                      depth);
+            ent->flags &= ~XML_ENT_EXPANDING;
+
+            chunk = str;
+        } else {
+            /* Normal ASCII char */
+            if (!IS_BYTE_CHAR(c)) {
+                xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
+                        "invalid character in entity value\n");
+                if (chunk < str)
+                    xmlSBufAddString(buf, chunk, str - chunk);
+                xmlSBufAddReplChar(buf);
+                str += 1;
+                chunk = str;
+            } else {
+                str += 1;
+            }
+        }
+    }
+
+    if (chunk < str)
+        xmlSBufAddString(buf, chunk, str - chunk);
+
+    return;
+}
+
+/**
+ * xmlParseEntityValue:
+ * @ctxt:  an XML parser context
+ * @orig:  if non-NULL store a copy of the original entity value
+ *
+ * DEPRECATED: Internal function, don't use.
+ *
+ * parse a value for ENTITY declarations
+ *
+ * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
  *	               "'" ([^%&'] | PEReference | Reference)* "'"
  *
  * Returns the EntityValue parsed with reference substituted or NULL
  */
-
 xmlChar *
 xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
-    xmlChar *buf = NULL;
-    int len = 0;
-    int size = XML_PARSER_BUFFER_SIZE;
-    int c, l;
-    xmlChar stop;
-    xmlChar *ret = NULL;
-    const xmlChar *cur = NULL;
-    xmlParserInputPtr input;
+    unsigned maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                         XML_MAX_HUGE_LENGTH :
+                         XML_MAX_TEXT_LENGTH;
+    xmlSBuf buf;
+    const xmlChar *start;
+    int quote, length;
 
-    if (RAW == '"') stop = '"';
-    else if (RAW == '\'') stop = '\'';
-    else {
-	xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
+    xmlSBufInit(&buf, maxLength);
+
+    GROW;
+
+    quote = CUR;
+    if ((quote != '"') && (quote != '\'')) {
+	xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
 	return(NULL);
     }
-    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
-    if (buf == NULL) {
-	xmlErrMemory(ctxt, NULL);
-	return(NULL);
+    CUR_PTR++;
+
+    length = 0;
+
+    /*
+     * Copy raw content of the entity into a buffer
+     */
+    while (1) {
+        int c;
+
+        if (PARSER_STOPPED(ctxt))
+            goto error;
+
+        if (CUR_PTR >= ctxt->input->end) {
+            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
+            goto error;
+        }
+
+        c = CUR;
+
+        if (c == 0) {
+            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
+                    "invalid character in entity value\n");
+            goto error;
+        }
+        if (c == quote)
+            break;
+        NEXTL(1);
+        length += 1;
+
+        /*
+         * TODO: Check growth threshold
+         */
+        if (ctxt->input->end - CUR_PTR < 10)
+            GROW;
+    }
+
+    start = CUR_PTR - length;
+
+    if (orig != NULL) {
+        *orig = xmlStrndup(start, length);
+        if (*orig == NULL)
+            xmlErrMemory(ctxt);
+    }
+
+    xmlExpandPEsInEntityValue(ctxt, &buf, start, length, ctxt->inputNr);
+
+    NEXTL(1);
+
+    return(xmlSBufFinish(&buf, NULL, ctxt, "entity length too long"));
+
+error:
+    xmlSBufCleanup(&buf, ctxt, "entity length too long");
+    return(NULL);
+}
+
+/**
+ * xmlCheckEntityInAttValue:
+ * @ctxt:  parser context
+ * @pent:  entity
+ * @depth:  nesting depth
+ *
+ * Check an entity reference in an attribute value for validity
+ * without expanding it.
+ */
+static void
+xmlCheckEntityInAttValue(xmlParserCtxtPtr ctxt, xmlEntityPtr pent, int depth) {
+    int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20;
+    const xmlChar *str;
+    unsigned long expandedSize = pent->length;
+    int c, flags;
+
+    depth += 1;
+    if (depth > maxDepth) {
+	xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
+                       "Maximum entity nesting depth exceeded");
+	return;
+    }
+
+    if (pent->flags & XML_ENT_EXPANDING) {
+        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+        xmlHaltParser(ctxt);
+        return;
     }
 
     /*
-     * The content of the entity definition is copied in a buffer.
+     * If we're parsing a default attribute value in DTD content,
+     * the entity might reference other entities which weren't
+     * defined yet, so the check isn't reliable.
      */
+    if (ctxt->inSubset == 0)
+        flags = XML_ENT_CHECKED | XML_ENT_VALIDATED;
+    else
+        flags = XML_ENT_VALIDATED;
+
+    str = pent->content;
+    if (str == NULL)
+        goto done;
 
-    ctxt->instate = XML_PARSER_ENTITY_VALUE;
-    input = ctxt->input;
-    GROW;
-    if (ctxt->instate == XML_PARSER_EOF)
-        goto error;
-    NEXT;
-    c = CUR_CHAR(l);
     /*
-     * NOTE: 4.4.5 Included in Literal
-     * When a parameter entity reference appears in a literal entity
-     * value, ... a single or double quote character in the replacement
-     * text is always treated as a normal data character and will not
-     * terminate the literal.
-     * In practice it means we stop the loop only when back at parsing
-     * the initial entity and the quote is found
+     * Note that entity values are already validated. We only check
+     * for illegal less-than signs and compute the expanded size
+     * of the entity. No special handling for multi-byte characters
+     * is needed.
      */
-    while (((IS_CHAR(c)) && ((c != stop) || /* checked */
-	    (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
-	if (len + 5 >= size) {
-	    xmlChar *tmp;
+    while (!PARSER_STOPPED(ctxt)) {
+        c = *str;
 
-	    size *= 2;
-	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
-	    if (tmp == NULL) {
-		xmlErrMemory(ctxt, NULL);
-                goto error;
-	    }
-	    buf = tmp;
-	}
-	COPY_BUF(l,buf,len,c);
-	NEXTL(l);
+	if (c != '&') {
+            if (c == 0)
+                break;
 
-	GROW;
-	c = CUR_CHAR(l);
-	if (c == 0) {
-	    GROW;
-	    c = CUR_CHAR(l);
-	}
+            if (c == '<')
+                xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
+                        "'<' in entity '%s' is not allowed in attributes "
+                        "values\n", pent->name);
+
+            str += 1;
+        } else if (str[1] == '#') {
+            int val;
+
+	    val = xmlParseStringCharRef(ctxt, &str);
+	    if (val == 0) {
+                pent->content[0] = 0;
+                break;
+            }
+	} else {
+            xmlChar *name;
+            xmlEntityPtr ent;
+
+	    name = xmlParseStringEntityRef(ctxt, &str);
+	    if (name == NULL) {
+                pent->content[0] = 0;
+                break;
+            }
+
+            ent = xmlLookupGeneralEntity(ctxt, name, /* inAttr */ 1);
+            xmlFree(name);
+
+            if ((ent != NULL) &&
+                (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
+                if ((ent->flags & flags) != flags) {
+                    pent->flags |= XML_ENT_EXPANDING;
+                    xmlCheckEntityInAttValue(ctxt, ent, depth);
+                    pent->flags &= ~XML_ENT_EXPANDING;
+                }
+
+                xmlSaturatedAdd(&expandedSize, ent->expandedSize);
+                xmlSaturatedAdd(&expandedSize, XML_ENT_FIXED_COST);
+            }
+        }
     }
-    buf[len] = 0;
-    if (ctxt->instate == XML_PARSER_EOF)
-        goto error;
-    if (c != stop) {
-        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
-        goto error;
+
+done:
+    if (ctxt->inSubset == 0)
+        pent->expandedSize = expandedSize;
+
+    pent->flags |= flags;
+}
+
+/**
+ * xmlExpandEntityInAttValue:
+ * @ctxt:  parser context
+ * @buf:  string buffer
+ * @str:  entity or attribute value
+ * @pent:  entity for entity value, NULL for attribute values
+ * @normalize:  whether to collapse whitespace
+ * @inSpace:  whitespace state
+ * @depth:  nesting depth
+ * @check:  whether to check for amplification
+ *
+ * Expand general entity references in an entity or attribute value.
+ * Perform attribute value normalization.
+ */
+static void
+xmlExpandEntityInAttValue(xmlParserCtxtPtr ctxt, xmlSBuf *buf,
+                          const xmlChar *str, xmlEntityPtr pent, int normalize,
+                          int *inSpace, int depth, int check) {
+    int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20;
+    int c, chunkSize;
+
+    if (str == NULL)
+        return;
+
+    depth += 1;
+    if (depth > maxDepth) {
+	xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
+                       "Maximum entity nesting depth exceeded");
+	return;
     }
-    NEXT;
+
+    if (pent != NULL) {
+        if (pent->flags & XML_ENT_EXPANDING) {
+            xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+            xmlHaltParser(ctxt);
+            return;
+        }
+
+        if (check) {
+            if (xmlParserEntityCheck(ctxt, pent->length))
+                return;
+        }
+    }
+
+    chunkSize = 0;
 
     /*
-     * Raise problem w.r.t. '&' and '%' being used in non-entities
-     * reference constructs. Note Charref will be handled in
-     * xmlStringDecodeEntities()
+     * Note that entity values are already validated. No special
+     * handling for multi-byte characters is needed.
      */
-    cur = buf;
-    while (*cur != 0) { /* non input consuming */
-	if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
-	    xmlChar *name;
-	    xmlChar tmp = *cur;
-            int nameOk = 0;
+    while (!PARSER_STOPPED(ctxt)) {
+        c = *str;
 
-	    cur++;
-	    name = xmlParseStringName(ctxt, &cur);
-            if (name != NULL) {
-                nameOk = 1;
-                xmlFree(name);
+	if (c != '&') {
+            if (c == 0)
+                break;
+
+            /*
+             * If this function is called without an entity, it is used to
+             * expand entities in an attribute content where less-than was
+             * already unscaped and is allowed.
+             */
+            if ((pent != NULL) && (c == '<')) {
+                xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
+                        "'<' in entity '%s' is not allowed in attributes "
+                        "values\n", pent->name);
+                break;
             }
-            if ((nameOk == 0) || (*cur != ';')) {
-		xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
-	    "EntityValue: '%c' forbidden except for entities references\n",
-	                          tmp);
-                goto error;
-	    }
-	    if ((tmp == '%') && (ctxt->inSubset == 1) &&
-		(ctxt->inputNr == 1)) {
-		xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
-                goto error;
+
+            if (c <= 0x20) {
+                if ((normalize) && (*inSpace)) {
+                    /* Skip char */
+                    if (chunkSize > 0) {
+                        xmlSBufAddString(buf, str - chunkSize, chunkSize);
+                        chunkSize = 0;
+                    }
+                } else if (c < 0x20) {
+                    if (chunkSize > 0) {
+                        xmlSBufAddString(buf, str - chunkSize, chunkSize);
+                        chunkSize = 0;
+                    }
+
+                    xmlSBufAddCString(buf, " ", 1);
+                } else {
+                    chunkSize += 1;
+                }
+
+                *inSpace = 1;
+            } else {
+                chunkSize += 1;
+                *inSpace = 0;
+            }
+
+            str += 1;
+        } else if (str[1] == '#') {
+            int val;
+
+            if (chunkSize > 0) {
+                xmlSBufAddString(buf, str - chunkSize, chunkSize);
+                chunkSize = 0;
+            }
+
+	    val = xmlParseStringCharRef(ctxt, &str);
+	    if (val == 0) {
+                if (pent != NULL)
+                    pent->content[0] = 0;
+                break;
+            }
+
+            if (val == ' ') {
+                if ((!normalize) || (!*inSpace))
+                    xmlSBufAddCString(buf, " ", 1);
+                *inSpace = 1;
+            } else {
+                xmlSBufAddChar(buf, val);
+                *inSpace = 0;
+            }
+	} else {
+            xmlChar *name;
+            xmlEntityPtr ent;
+
+            if (chunkSize > 0) {
+                xmlSBufAddString(buf, str - chunkSize, chunkSize);
+                chunkSize = 0;
+            }
+
+	    name = xmlParseStringEntityRef(ctxt, &str);
+            if (name == NULL) {
+                if (pent != NULL)
+                    pent->content[0] = 0;
+                break;
+            }
+
+            ent = xmlLookupGeneralEntity(ctxt, name, /* inAttr */ 1);
+            xmlFree(name);
+
+	    if ((ent != NULL) &&
+		(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
+		if (ent->content == NULL) {
+		    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
+			    "predefined entity has no content\n");
+                    break;
+                }
+
+                xmlSBufAddString(buf, ent->content, ent->length);
+
+                *inSpace = 0;
+	    } else if ((ent != NULL) && (ent->content != NULL)) {
+                if (pent != NULL)
+                    pent->flags |= XML_ENT_EXPANDING;
+		xmlExpandEntityInAttValue(ctxt, buf, ent->content, ent,
+                                          normalize, inSpace, depth, check);
+                if (pent != NULL)
+                    pent->flags &= ~XML_ENT_EXPANDING;
 	    }
-	    if (*cur == 0)
-	        break;
-	}
-	cur++;
+        }
     }
 
-    /*
-     * Then PEReference entities are substituted.
-     *
-     * NOTE: 4.4.7 Bypassed
-     * When a general entity reference appears in the EntityValue in
-     * an entity declaration, it is bypassed and left as is.
-     * so XML_SUBSTITUTE_REF is not set here.
-     */
-    ++ctxt->depth;
-    ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
-                                  0, 0, 0);
-    --ctxt->depth;
-    if (orig != NULL) {
-        *orig = buf;
-        buf = NULL;
-    }
+    if (chunkSize > 0)
+        xmlSBufAddString(buf, str - chunkSize, chunkSize);
 
-error:
-    if (buf != NULL)
-        xmlFree(buf);
-    return(ret);
+    return;
 }
 
 /**
- * xmlParseAttValueComplex:
+ * xmlExpandEntitiesInAttValue:
+ * @ctxt:  parser context
+ * @str:  entity or attribute value
+ * @normalize:  whether to collapse whitespace
+ *
+ * Expand general entity references in an entity or attribute value.
+ * Perform attribute value normalization.
+ *
+ * Returns the expanded attribtue value.
+ */
+xmlChar *
+xmlExpandEntitiesInAttValue(xmlParserCtxtPtr ctxt, const xmlChar *str,
+                            int normalize) {
+    unsigned maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                         XML_MAX_HUGE_LENGTH :
+                         XML_MAX_TEXT_LENGTH;
+    xmlSBuf buf;
+    int inSpace = 1;
+
+    xmlSBufInit(&buf, maxLength);
+
+    xmlExpandEntityInAttValue(ctxt, &buf, str, NULL, normalize, &inSpace,
+                              ctxt->inputNr, /* check */ 0);
+
+    if ((normalize) && (inSpace) && (buf.size > 0))
+        buf.size--;
+
+    return(xmlSBufFinish(&buf, NULL, ctxt, "AttValue length too long"));
+}
+
+/**
+ * xmlParseAttValueInternal:
  * @ctxt:  an XML parser context
- * @len:   the resulting attribute len
- * @normalize:  whether to apply the inner normalization
+ * @len:  attribute len result
+ * @alloc:  whether the attribute was reallocated as a new string
+ * @normalize:  if 1 then further non-CDATA normalization must be done
  *
- * parse a value for an attribute, this is the fallback function
- * of xmlParseAttValue() when the attribute parsing requires handling
- * of non-ASCII characters, or normalization compaction.
+ * parse a value for an attribute.
+ * NOTE: if no normalization is needed, the routine will return pointers
+ *       directly from the data buffer.
  *
- * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
+ * 3.3.3 Attribute-Value Normalization:
+ * Before the value of an attribute is passed to the application or
+ * checked for validity, the XML processor must normalize it as follows:
+ * - a character reference is processed by appending the referenced
+ *   character to the attribute value
+ * - an entity reference is processed by recursively processing the
+ *   replacement text of the entity
+ * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
+ *   appending #x20 to the normalized value, except that only a single
+ *   #x20 is appended for a "#xD#xA" sequence that is part of an external
+ *   parsed entity or the literal entity value of an internal parsed entity
+ * - other characters are processed by appending them to the normalized value
+ * If the declared value is not CDATA, then the XML processor must further
+ * process the normalized attribute value by discarding any leading and
+ * trailing space (#x20) characters, and by replacing sequences of space
+ * (#x20) characters by a single space (#x20) character.
+ * All attributes for which no declaration has been read should be treated
+ * by a non-validating parser as if declared CDATA.
+ *
+ * Returns the AttValue parsed or NULL. The value has to be freed by the
+ *     caller if it was copied, this can be detected by val[*len] == 0.
  */
 static xmlChar *
-xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
-    xmlChar limit = 0;
-    xmlChar *buf = NULL;
-    xmlChar *rep = NULL;
-    size_t len = 0;
-    size_t buf_size = 0;
-    int c, l, in_space = 0;
-    xmlChar *current = NULL;
-    xmlEntityPtr ent;
+xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *attlen, int *alloc,
+                         int normalize, int isNamespace) {
+    unsigned maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                         XML_MAX_HUGE_LENGTH :
+                         XML_MAX_TEXT_LENGTH;
+    xmlSBuf buf;
+    xmlChar *ret;
+    int c, l, quote, flags, chunkSize;
+    int inSpace = 1;
+    int replaceEntities;
 
-    if (NXT(0) == '"') {
-	ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
-	limit = '"';
-        NEXT;
-    } else if (NXT(0) == '\'') {
-	limit = '\'';
-	ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
-        NEXT;
-    } else {
+    /* Always expand namespace URIs */
+    replaceEntities = (ctxt->replaceEntities) || (isNamespace);
+
+    xmlSBufInit(&buf, maxLength);
+
+    GROW;
+
+    quote = CUR;
+    if ((quote != '"') && (quote != '\'')) {
 	xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
 	return(NULL);
     }
+    NEXTL(1);
 
-    /*
-     * allocate a translation buffer.
-     */
-    buf_size = XML_PARSER_BUFFER_SIZE;
-    buf = (xmlChar *) xmlMallocAtomic(buf_size);
-    if (buf == NULL) goto mem_error;
+    if (ctxt->inSubset == 0)
+        flags = XML_ENT_CHECKED | XML_ENT_VALIDATED;
+    else
+        flags = XML_ENT_VALIDATED;
 
-    /*
-     * OK loop until we reach one of the ending char or a size limit.
-     */
-    c = CUR_CHAR(l);
-    while (((NXT(0) != limit) && /* checked */
-            (IS_CHAR(c)) && (c != '<')) &&
-            (ctxt->instate != XML_PARSER_EOF)) {
-        /*
-         * Impose a reasonable limit on attribute size, unless XML_PARSE_HUGE
-         * special option is given
-         */
-        if ((len > XML_MAX_TEXT_LENGTH) &&
-            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
+    inSpace = 1;
+    chunkSize = 0;
+
+    while (1) {
+        if (PARSER_STOPPED(ctxt))
+            goto error;
+
+        if (CUR_PTR >= ctxt->input->end) {
             xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
-                           "AttValue length too long\n");
-            goto mem_error;
+                           "AttValue: ' expected\n");
+            goto error;
         }
-	if (c == '&') {
-	    in_space = 0;
-	    if (NXT(1) == '#') {
-		int val = xmlParseCharRef(ctxt);
-
-		if (val == '&') {
-		    if (ctxt->replaceEntities) {
-			if (len + 10 > buf_size) {
-			    growBuffer(buf, 10);
-			}
-			buf[len++] = '&';
-		    } else {
-			/*
-			 * The reparsing will be done in xmlStringGetNodeList()
-			 * called by the attribute() function in SAX.c
-			 */
-			if (len + 10 > buf_size) {
-			    growBuffer(buf, 10);
-			}
-			buf[len++] = '&';
-			buf[len++] = '#';
-			buf[len++] = '3';
-			buf[len++] = '8';
-			buf[len++] = ';';
-		    }
-		} else if (val != 0) {
-		    if (len + 10 > buf_size) {
-			growBuffer(buf, 10);
-		    }
-		    len += xmlCopyChar(0, &buf[len], val);
-		}
-	    } else {
-		ent = xmlParseEntityRef(ctxt);
-		ctxt->nbentities++;
-		if (ent != NULL)
-		    ctxt->nbentities += ent->owner;
-		if ((ent != NULL) &&
-		    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
-		    if (len + 10 > buf_size) {
-			growBuffer(buf, 10);
-		    }
-		    if ((ctxt->replaceEntities == 0) &&
-		        (ent->content[0] == '&')) {
-			buf[len++] = '&';
-			buf[len++] = '#';
-			buf[len++] = '3';
-			buf[len++] = '8';
-			buf[len++] = ';';
-		    } else {
-			buf[len++] = ent->content[0];
-		    }
-		} else if ((ent != NULL) &&
-		           (ctxt->replaceEntities != 0)) {
-		    if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
-			++ctxt->depth;
-			rep = xmlStringDecodeEntities(ctxt, ent->content,
-						      XML_SUBSTITUTE_REF,
-						      0, 0, 0);
-			--ctxt->depth;
-			if (rep != NULL) {
-			    current = rep;
-			    while (*current != 0) { /* non input consuming */
-                                if ((*current == 0xD) || (*current == 0xA) ||
-                                    (*current == 0x9)) {
-                                    buf[len++] = 0x20;
-                                    current++;
-                                } else
-                                    buf[len++] = *current++;
-				if (len + 10 > buf_size) {
-				    growBuffer(buf, 10);
-				}
-			    }
-			    xmlFree(rep);
-			    rep = NULL;
-			}
-		    } else {
-			if (len + 10 > buf_size) {
-			    growBuffer(buf, 10);
-			}
-			if (ent->content != NULL)
-			    buf[len++] = ent->content[0];
-		    }
-		} else if (ent != NULL) {
-		    int i = xmlStrlen(ent->name);
-		    const xmlChar *cur = ent->name;
 
-		    /*
-		     * This may look absurd but is needed to detect
-		     * entities problems
-		     */
-		    if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
-			(ent->content != NULL) && (ent->checked == 0)) {
-			unsigned long oldnbent = ctxt->nbentities, diff;
-
-			++ctxt->depth;
-			rep = xmlStringDecodeEntities(ctxt, ent->content,
-						  XML_SUBSTITUTE_REF, 0, 0, 0);
-			--ctxt->depth;
-
-                        diff = ctxt->nbentities - oldnbent + 1;
-                        if (diff > INT_MAX / 2)
-                            diff = INT_MAX / 2;
-                        ent->checked = diff * 2;
-			if (rep != NULL) {
-			    if (xmlStrchr(rep, '<'))
-			        ent->checked |= 1;
-			    xmlFree(rep);
-			    rep = NULL;
-			} else {
-                            ent->content[0] = 0;
-                        }
-		    }
+        /*
+         * TODO: Check growth threshold
+         */
+        if (ctxt->input->end - CUR_PTR < 10)
+            GROW;
+
+        c = CUR;
+
+        if (c >= 0x80) {
+            l = xmlUTF8MultibyteLen(ctxt, CUR_PTR,
+                    "invalid character in attribute value\n");
+            if (l == 0) {
+                if (chunkSize > 0) {
+                    xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
+                    chunkSize = 0;
+                }
+                xmlSBufAddReplChar(&buf);
+                NEXTL(1);
+            } else {
+                chunkSize += l;
+                NEXTL(l);
+            }
 
-		    /*
-		     * Just output the reference
-		     */
-		    buf[len++] = '&';
-		    while (len + i + 10 > buf_size) {
-			growBuffer(buf, i + 10);
-		    }
-		    for (;i > 0;i--)
-			buf[len++] = *cur++;
-		    buf[len++] = ';';
-		}
-	    }
-	} else {
-	    if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
-	        if ((len != 0) || (!normalize)) {
-		    if ((!normalize) || (!in_space)) {
-			COPY_BUF(l,buf,len,0x20);
-			while (len + 10 > buf_size) {
-			    growBuffer(buf, 10);
-			}
-		    }
-		    in_space = 1;
-		}
-	    } else {
-	        in_space = 0;
-		COPY_BUF(l,buf,len,c);
-		if (len + 10 > buf_size) {
-		    growBuffer(buf, 10);
-		}
-	    }
-	    NEXTL(l);
+            inSpace = 0;
+        } else if (c != '&') {
+            if (c > 0x20) {
+                if (c == quote)
+                    break;
+
+                if (c == '<')
+                    xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
+
+                chunkSize += 1;
+                inSpace = 0;
+            } else if (!IS_BYTE_CHAR(c)) {
+                xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
+                        "invalid character in attribute value\n");
+                if (chunkSize > 0) {
+                    xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
+                    chunkSize = 0;
+                }
+                xmlSBufAddReplChar(&buf);
+                inSpace = 0;
+            } else {
+                /* Whitespace */
+                if ((normalize) && (inSpace)) {
+                    /* Skip char */
+                    if (chunkSize > 0) {
+                        xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
+                        chunkSize = 0;
+                    }
+                } else if (c < 0x20) {
+                    /* Convert to space */
+                    if (chunkSize > 0) {
+                        xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
+                        chunkSize = 0;
+                    }
+
+                    xmlSBufAddCString(&buf, " ", 1);
+                } else {
+                    chunkSize += 1;
+                }
+
+                inSpace = 1;
+
+                if ((c == 0xD) && (NXT(1) == 0xA))
+                    CUR_PTR++;
+            }
+
+            NEXTL(1);
+        } else if (NXT(1) == '#') {
+            int val;
+
+            if (chunkSize > 0) {
+                xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
+                chunkSize = 0;
+            }
+
+            val = xmlParseCharRef(ctxt);
+            if (val == 0)
+                goto error;
+
+            if ((val == '&') && (!replaceEntities)) {
+                /*
+                 * The reparsing will be done in xmlStringGetNodeList()
+                 * called by the attribute() function in SAX.c
+                 */
+                xmlSBufAddCString(&buf, "&#38;", 5);
+                inSpace = 0;
+            } else if (val == ' ') {
+                if ((!normalize) || (!inSpace))
+                    xmlSBufAddCString(&buf, " ", 1);
+                inSpace = 1;
+            } else {
+                xmlSBufAddChar(&buf, val);
+                inSpace = 0;
+            }
+        } else {
+            const xmlChar *name;
+            xmlEntityPtr ent;
+
+            if (chunkSize > 0) {
+                xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
+                chunkSize = 0;
+            }
+
+            name = xmlParseEntityRefInternal(ctxt);
+            if (name == NULL) {
+                /*
+                 * Probably a literal '&' which wasn't escaped.
+                 * TODO: Handle gracefully in recovery mode.
+                 */
+                continue;
+            }
+
+            ent = xmlLookupGeneralEntity(ctxt, name, /* isAttr */ 1);
+            if (ent == NULL)
+                continue;
+
+            if (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY) {
+                if ((ent->content[0] == '&') && (!replaceEntities))
+                    xmlSBufAddCString(&buf, "&#38;", 5);
+                else
+                    xmlSBufAddString(&buf, ent->content, ent->length);
+                inSpace = 0;
+            } else if (replaceEntities) {
+                xmlExpandEntityInAttValue(ctxt, &buf, ent->content, ent,
+                                          normalize, &inSpace, ctxt->inputNr,
+                                          /* check */ 1);
+            } else {
+                if ((ent->flags & flags) != flags)
+                    xmlCheckEntityInAttValue(ctxt, ent, ctxt->inputNr);
+
+                if (xmlParserEntityCheck(ctxt, ent->expandedSize)) {
+                    ent->content[0] = 0;
+                    goto error;
+                }
+
+                /*
+                 * Just output the reference
+                 */
+                xmlSBufAddCString(&buf, "&", 1);
+                xmlSBufAddString(&buf, ent->name, xmlStrlen(ent->name));
+                xmlSBufAddCString(&buf, ";", 1);
+
+                inSpace = 0;
+            }
 	}
-	GROW;
-	c = CUR_CHAR(l);
     }
-    if (ctxt->instate == XML_PARSER_EOF)
-        goto error;
 
-    if ((in_space) && (normalize)) {
-        while ((len > 0) && (buf[len - 1] == 0x20)) len--;
-    }
-    buf[len] = 0;
-    if (RAW == '<') {
-	xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
-    } else if (RAW != limit) {
-	if ((c != 0) && (!IS_CHAR(c))) {
-	    xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
-			   "invalid character in attribute value\n");
-	} else {
-	    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
-			   "AttValue: ' expected\n");
-        }
-    } else
-	NEXT;
+    if ((buf.mem == NULL) && (alloc != NULL)) {
+        ret = (xmlChar *) CUR_PTR - chunkSize;
 
-    /*
-     * There we potentially risk an overflow, don't allow attribute value of
-     * length more than INT_MAX it is a very reasonable assumption !
-     */
-    if (len >= INT_MAX) {
-        xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
-                       "AttValue length too long\n");
-        goto mem_error;
+        if (attlen != NULL)
+            *attlen = chunkSize;
+        if ((normalize) && (inSpace) && (chunkSize > 0))
+            *attlen -= 1;
+        *alloc = 0;
+
+        /* Report potential error */
+        xmlSBufCleanup(&buf, ctxt, "AttValue length too long");
+    } else {
+        if (chunkSize > 0)
+            xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
+
+        if ((normalize) && (inSpace) && (buf.size > 0))
+            buf.size--;
+
+        ret = xmlSBufFinish(&buf, attlen, ctxt, "AttValue length too long");
+
+        if (ret != NULL) {
+            if (attlen != NULL)
+                *attlen = buf.size;
+            if (alloc != NULL)
+                *alloc = 1;
+        }
     }
 
-    if (attlen != NULL) *attlen = (int) len;
-    return(buf);
+    NEXTL(1);
+
+    return(ret);
 
-mem_error:
-    xmlErrMemory(ctxt, NULL);
 error:
-    if (buf != NULL)
-        xmlFree(buf);
-    if (rep != NULL)
-        xmlFree(rep);
+    xmlSBufCleanup(&buf, ctxt, "AttValue length too long");
     return(NULL);
 }
 
@@ -4141,6 +4534,8 @@ error:
  * xmlParseAttValue:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse a value for an attribute
  * Note: the parser won't do substitution of entities here, this
  * will be handled later in xmlStringGetNodeList
@@ -4174,13 +4569,15 @@ error:
 xmlChar *
 xmlParseAttValue(xmlParserCtxtPtr ctxt) {
     if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
-    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
+    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0, 0));
 }
 
 /**
  * xmlParseSystemLiteral:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an XML Literal
  *
  * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
@@ -4194,11 +4591,11 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
     int len = 0;
     int size = XML_PARSER_BUFFER_SIZE;
     int cur, l;
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_TEXT_LENGTH :
+                    XML_MAX_NAME_LENGTH;
     xmlChar stop;
-    int state = ctxt->instate;
-    int count = 0;
 
-    SHRINK;
     if (RAW == '"') {
         NEXT;
 	stop = '"';
@@ -4210,55 +4607,35 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
 	return(NULL);
     }
 
-    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+    buf = (xmlChar *) xmlMallocAtomic(size);
     if (buf == NULL) {
-        xmlErrMemory(ctxt, NULL);
+        xmlErrMemory(ctxt);
 	return(NULL);
     }
-    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
     cur = CUR_CHAR(l);
     while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
 	if (len + 5 >= size) {
 	    xmlChar *tmp;
 
-            if ((size > XML_MAX_NAME_LENGTH) &&
-                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
-                xmlFree(buf);
-		ctxt->instate = (xmlParserInputState) state;
-                return(NULL);
-            }
 	    size *= 2;
-	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+	    tmp = (xmlChar *) xmlRealloc(buf, size);
 	    if (tmp == NULL) {
 	        xmlFree(buf);
-		xmlErrMemory(ctxt, NULL);
-		ctxt->instate = (xmlParserInputState) state;
+		xmlErrMemory(ctxt);
 		return(NULL);
 	    }
 	    buf = tmp;
 	}
-	count++;
-	if (count > 50) {
-	    SHRINK;
-	    GROW;
-	    count = 0;
-            if (ctxt->instate == XML_PARSER_EOF) {
-	        xmlFree(buf);
-		return(NULL);
-            }
-	}
-	COPY_BUF(l,buf,len,cur);
+	COPY_BUF(buf, len, cur);
+        if (len > maxLength) {
+            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
+            xmlFree(buf);
+            return(NULL);
+        }
 	NEXTL(l);
 	cur = CUR_CHAR(l);
-	if (cur == 0) {
-	    GROW;
-	    SHRINK;
-	    cur = CUR_CHAR(l);
-	}
     }
     buf[len] = 0;
-    ctxt->instate = (xmlParserInputState) state;
     if (!IS_CHAR(cur)) {
 	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
     } else {
@@ -4271,6 +4648,8 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
  * xmlParsePubidLiteral:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an XML public literal
  *
  * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
@@ -4283,12 +4662,12 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
     xmlChar *buf = NULL;
     int len = 0;
     int size = XML_PARSER_BUFFER_SIZE;
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_TEXT_LENGTH :
+                    XML_MAX_NAME_LENGTH;
     xmlChar cur;
     xmlChar stop;
-    int count = 0;
-    xmlParserInputState oldstate = ctxt->instate;
 
-    SHRINK;
     if (RAW == '"') {
         NEXT;
 	stop = '"';
@@ -4299,62 +4678,45 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
 	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
 	return(NULL);
     }
-    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+    buf = (xmlChar *) xmlMallocAtomic(size);
     if (buf == NULL) {
-	xmlErrMemory(ctxt, NULL);
+	xmlErrMemory(ctxt);
 	return(NULL);
     }
-    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
     cur = CUR;
-    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
+    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop) &&
+           (PARSER_STOPPED(ctxt) == 0)) { /* checked */
 	if (len + 1 >= size) {
 	    xmlChar *tmp;
 
-            if ((size > XML_MAX_NAME_LENGTH) &&
-                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
-                xmlFree(buf);
-                return(NULL);
-            }
 	    size *= 2;
-	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+	    tmp = (xmlChar *) xmlRealloc(buf, size);
 	    if (tmp == NULL) {
-		xmlErrMemory(ctxt, NULL);
+		xmlErrMemory(ctxt);
 		xmlFree(buf);
 		return(NULL);
 	    }
 	    buf = tmp;
 	}
 	buf[len++] = cur;
-	count++;
-	if (count > 50) {
-	    SHRINK;
-	    GROW;
-	    count = 0;
-            if (ctxt->instate == XML_PARSER_EOF) {
-		xmlFree(buf);
-		return(NULL);
-            }
-	}
+        if (len > maxLength) {
+            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
+            xmlFree(buf);
+            return(NULL);
+        }
 	NEXT;
 	cur = CUR;
-	if (cur == 0) {
-	    GROW;
-	    SHRINK;
-	    cur = CUR;
-	}
     }
     buf[len] = 0;
     if (cur != stop) {
 	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
     } else {
-	NEXT;
+	NEXTL(1);
     }
-    ctxt->instate = oldstate;
     return(buf);
 }
 
-static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
+static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial);
 
 /*
  * used for the test in the inner loop of the char data testing
@@ -4395,12 +4757,12 @@ static const unsigned char test_char_data[256] = {
 };
 
 /**
- * xmlParseCharData:
+ * xmlParseCharDataInternal:
  * @ctxt:  an XML parser context
- * @cdata:  int indicating whether we are within a CDATA section
+ * @partial:  buffer may contain partial UTF-8 sequences
  *
- * parse a CharData section.
- * if we are within a CDATA section ']]>' marks an end of section.
+ * Parse character data. Always makes progress if the first char isn't
+ * '<' or '&'.
  *
  * The right angle bracket (>) may be represented using the string "&gt;",
  * and must, for compatibility, be escaped using "&gt;" or a character
@@ -4409,147 +4771,142 @@ static const unsigned char test_char_data[256] = {
  *
  * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
  */
-
-void
-xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
+static void
+xmlParseCharDataInternal(xmlParserCtxtPtr ctxt, int partial) {
     const xmlChar *in;
     int nbchar = 0;
     int line = ctxt->input->line;
     int col = ctxt->input->col;
     int ccol;
 
-    SHRINK;
     GROW;
     /*
      * Accelerated common case where input don't need to be
      * modified before passing it to the handler.
-     */
-    if (!cdata) {
-	in = ctxt->input->cur;
-	do {
-get_more_space:
-	    while (*in == 0x20) { in++; ctxt->input->col++; }
-	    if (*in == 0xA) {
-		do {
-		    ctxt->input->line++; ctxt->input->col = 1;
-		    in++;
-		} while (*in == 0xA);
-		goto get_more_space;
-	    }
-	    if (*in == '<') {
-		nbchar = in - ctxt->input->cur;
-		if (nbchar > 0) {
-		    const xmlChar *tmp = ctxt->input->cur;
-		    ctxt->input->cur = in;
-
-		    if ((ctxt->sax != NULL) &&
-		        (ctxt->sax->ignorableWhitespace !=
-		         ctxt->sax->characters)) {
-			if (areBlanks(ctxt, tmp, nbchar, 1)) {
-			    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);
-			    if (*ctxt->space == -1)
-			        *ctxt->space = -2;
-			}
-		    } else if ((ctxt->sax != NULL) &&
-		               (ctxt->sax->characters != NULL)) {
-			ctxt->sax->characters(ctxt->userData,
-					      tmp, nbchar);
-		    }
-		}
-		return;
-	    }
+     */
+    in = ctxt->input->cur;
+    do {
+get_more_space:
+        while (*in == 0x20) { in++; ctxt->input->col++; }
+        if (*in == 0xA) {
+            do {
+                ctxt->input->line++; ctxt->input->col = 1;
+                in++;
+            } while (*in == 0xA);
+            goto get_more_space;
+        }
+        if (*in == '<') {
+            nbchar = in - ctxt->input->cur;
+            if (nbchar > 0) {
+                const xmlChar *tmp = ctxt->input->cur;
+                ctxt->input->cur = in;
+
+                if ((ctxt->sax != NULL) &&
+                    (ctxt->disableSAX == 0) &&
+                    (ctxt->sax->ignorableWhitespace !=
+                     ctxt->sax->characters)) {
+                    if (areBlanks(ctxt, tmp, nbchar, 1)) {
+                        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);
+                        if (*ctxt->space == -1)
+                            *ctxt->space = -2;
+                    }
+                } else if ((ctxt->sax != NULL) &&
+                           (ctxt->disableSAX == 0) &&
+                           (ctxt->sax->characters != NULL)) {
+                    ctxt->sax->characters(ctxt->userData,
+                                          tmp, nbchar);
+                }
+            }
+            return;
+        }
 
 get_more:
-            ccol = ctxt->input->col;
-	    while (test_char_data[*in]) {
-		in++;
-		ccol++;
-	    }
-	    ctxt->input->col = ccol;
-	    if (*in == 0xA) {
-		do {
-		    ctxt->input->line++; ctxt->input->col = 1;
-		    in++;
-		} while (*in == 0xA);
-		goto get_more;
-	    }
-	    if (*in == ']') {
-		if ((in[1] == ']') && (in[2] == '>')) {
-		    xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
-		    ctxt->input->cur = in + 1;
-		    return;
-		}
-		in++;
-		ctxt->input->col++;
-		goto get_more;
-	    }
-	    nbchar = in - ctxt->input->cur;
-	    if (nbchar > 0) {
-		if ((ctxt->sax != NULL) &&
-		    (ctxt->sax->ignorableWhitespace !=
-		     ctxt->sax->characters) &&
-		    (IS_BLANK_CH(*ctxt->input->cur))) {
-		    const xmlChar *tmp = ctxt->input->cur;
-		    ctxt->input->cur = in;
-
-		    if (areBlanks(ctxt, tmp, nbchar, 0)) {
-		        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);
-			if (*ctxt->space == -1)
-			    *ctxt->space = -2;
-		    }
-                    line = ctxt->input->line;
-                    col = ctxt->input->col;
-		} else if (ctxt->sax != NULL) {
-		    if (ctxt->sax->characters != NULL)
-			ctxt->sax->characters(ctxt->userData,
-					      ctxt->input->cur, nbchar);
-                    line = ctxt->input->line;
-                    col = ctxt->input->col;
-		}
-                /* something really bad happened in the SAX callback */
-                if (ctxt->instate != XML_PARSER_CONTENT)
-                    return;
-	    }
-	    ctxt->input->cur = in;
-	    if (*in == 0xD) {
-		in++;
-		if (*in == 0xA) {
-		    ctxt->input->cur = in;
-		    in++;
-		    ctxt->input->line++; ctxt->input->col = 1;
-		    continue; /* while */
-		}
-		in--;
-	    }
-	    if (*in == '<') {
-		return;
-	    }
-	    if (*in == '&') {
-		return;
-	    }
-	    SHRINK;
-	    GROW;
-            if (ctxt->instate == XML_PARSER_EOF)
-		return;
-	    in = ctxt->input->cur;
-	} while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
-	nbchar = 0;
-    }
+        ccol = ctxt->input->col;
+        while (test_char_data[*in]) {
+            in++;
+            ccol++;
+        }
+        ctxt->input->col = ccol;
+        if (*in == 0xA) {
+            do {
+                ctxt->input->line++; ctxt->input->col = 1;
+                in++;
+            } while (*in == 0xA);
+            goto get_more;
+        }
+        if (*in == ']') {
+            if ((in[1] == ']') && (in[2] == '>')) {
+                xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
+                ctxt->input->cur = in + 1;
+                return;
+            }
+            in++;
+            ctxt->input->col++;
+            goto get_more;
+        }
+        nbchar = in - ctxt->input->cur;
+        if (nbchar > 0) {
+            if ((ctxt->sax != NULL) &&
+                (ctxt->disableSAX == 0) &&
+                (ctxt->sax->ignorableWhitespace !=
+                 ctxt->sax->characters) &&
+                (IS_BLANK_CH(*ctxt->input->cur))) {
+                const xmlChar *tmp = ctxt->input->cur;
+                ctxt->input->cur = in;
+
+                if (areBlanks(ctxt, tmp, nbchar, 0)) {
+                    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);
+                    if (*ctxt->space == -1)
+                        *ctxt->space = -2;
+                }
+                line = ctxt->input->line;
+                col = ctxt->input->col;
+            } else if ((ctxt->sax != NULL) &&
+                       (ctxt->disableSAX == 0)) {
+                if (ctxt->sax->characters != NULL)
+                    ctxt->sax->characters(ctxt->userData,
+                                          ctxt->input->cur, nbchar);
+                line = ctxt->input->line;
+                col = ctxt->input->col;
+            }
+        }
+        ctxt->input->cur = in;
+        if (*in == 0xD) {
+            in++;
+            if (*in == 0xA) {
+                ctxt->input->cur = in;
+                in++;
+                ctxt->input->line++; ctxt->input->col = 1;
+                continue; /* while */
+            }
+            in--;
+        }
+        if (*in == '<') {
+            return;
+        }
+        if (*in == '&') {
+            return;
+        }
+        SHRINK;
+        GROW;
+        in = ctxt->input->cur;
+    } while (((*in >= 0x20) && (*in <= 0x7F)) ||
+             (*in == 0x09) || (*in == 0x0a));
     ctxt->input->line = line;
     ctxt->input->col = col;
-    xmlParseCharDataComplex(ctxt, cdata);
+    xmlParseCharDataComplex(ctxt, partial);
 }
 
 /**
@@ -4557,34 +4914,28 @@ get_more:
  * @ctxt:  an XML parser context
  * @cdata:  int indicating whether we are within a CDATA section
  *
+ * Always makes progress if the first char isn't '<' or '&'.
+ *
  * parse a CharData section.this is the fallback function
  * of xmlParseCharData() when the parsing requires handling
  * of non-ASCII characters.
  */
 static void
-xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
+xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial) {
     xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
     int nbchar = 0;
     int cur, l;
-    int count = 0;
 
-    SHRINK;
-    GROW;
     cur = CUR_CHAR(l);
     while ((cur != '<') && /* checked */
            (cur != '&') &&
-	   (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
-	if ((cur == ']') && (NXT(1) == ']') &&
-	    (NXT(2) == '>')) {
-	    if (cdata) break;
-	    else {
-		xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
-	    }
+	   (IS_CHAR(cur))) {
+	if ((cur == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
+	    xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
 	}
-	COPY_BUF(l,buf,nbchar,cur);
+	COPY_BUF(buf, nbchar, cur);
 	/* move current position before possible calling of ctxt->sax->characters */
 	NEXTL(l);
-	cur = CUR_CHAR(l);
 	if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
 	    buf[nbchar] = 0;
 
@@ -4606,18 +4957,9 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
 		}
 	    }
 	    nbchar = 0;
-            /* something really bad happened in the SAX callback */
-            if (ctxt->instate != XML_PARSER_CONTENT)
-                return;
-	}
-	count++;
-	if (count > 50) {
-	    SHRINK;
-	    GROW;
-	    count = 0;
-            if (ctxt->instate == XML_PARSER_EOF)
-		return;
+            SHRINK;
 	}
+	cur = CUR_CHAR(l);
     }
     if (nbchar != 0) {
         buf[nbchar] = 0;
@@ -4637,15 +4979,41 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
 	    }
 	}
     }
-    if ((cur != 0) && (!IS_CHAR(cur))) {
-	/* Generate the error and skip the offending character */
-        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
-                          "PCDATA invalid Char value %d\n",
-	                  cur);
-	NEXTL(l);
+    /*
+     * cur == 0 can mean
+     *
+     * - End of buffer.
+     * - An actual 0 character.
+     * - An incomplete UTF-8 sequence. This is allowed if partial is set.
+     */
+    if (ctxt->input->cur < ctxt->input->end) {
+        if ((cur == 0) && (CUR != 0)) {
+            if (partial == 0) {
+                xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
+                        "Incomplete UTF-8 sequence starting with %02X\n", CUR);
+                NEXTL(1);
+            }
+        } else if ((cur != '<') && (cur != '&')) {
+            /* Generate the error and skip the offending character */
+            xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
+                              "PCDATA invalid Char value %d\n", cur);
+            NEXTL(l);
+        }
     }
 }
 
+/**
+ * xmlParseCharData:
+ * @ctxt:  an XML parser context
+ * @cdata:  unused
+ *
+ * DEPRECATED: Internal function, don't use.
+ */
+void
+xmlParseCharData(xmlParserCtxtPtr ctxt, ATTRIBUTE_UNUSED int cdata) {
+    xmlParseCharDataInternal(ctxt, 0);
+}
+
 /**
  * xmlParseExternalID:
  * @ctxt:  an XML parser context
@@ -4653,6 +5021,8 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
  * @strict: indicate whether we should restrict parsing to only
  *          production [75], see NOTE below
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Parse an External ID or a Public ID
  *
  * NOTE: Productions [75] and [83] interact badly since [75] can generate
@@ -4672,8 +5042,6 @@ xmlChar *
 xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
     xmlChar *URI = NULL;
 
-    SHRINK;
-
     *publicID = NULL;
     if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
         SKIP(6);
@@ -4741,21 +5109,19 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
     int q, ql;
     int r, rl;
     int cur, l;
-    size_t count = 0;
-    int inputid;
-
-    inputid = ctxt->input->id;
+    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                       XML_MAX_HUGE_LENGTH :
+                       XML_MAX_TEXT_LENGTH;
 
     if (buf == NULL) {
         len = 0;
 	size = XML_PARSER_BUFFER_SIZE;
-	buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+	buf = (xmlChar *) xmlMallocAtomic(size);
 	if (buf == NULL) {
-	    xmlErrMemory(ctxt, NULL);
+	    xmlErrMemory(ctxt);
 	    return;
 	}
     }
-    GROW;	/* Assure there's enough input data */
     q = CUR_CHAR(ql);
     if (q == 0)
         goto not_terminated;
@@ -4773,7 +5139,7 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
     if (!IS_CHAR(r)) {
         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
                           "xmlParseComment: invalid xmlChar value %d\n",
-	                  q);
+	                  r);
 	xmlFree (buf);
 	return;
     }
@@ -4787,13 +5153,6 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
 	if ((r == '-') && (q == '-')) {
 	    xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
 	}
-        if ((len > XML_MAX_TEXT_LENGTH) &&
-            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
-                         "Comment too big found", NULL);
-            xmlFree (buf);
-            return;
-        }
 	if (len + 5 >= size) {
 	    xmlChar *new_buf;
             size_t new_size;
@@ -4802,35 +5161,28 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
 	    new_buf = (xmlChar *) xmlRealloc(buf, new_size);
 	    if (new_buf == NULL) {
 		xmlFree (buf);
-		xmlErrMemory(ctxt, NULL);
+		xmlErrMemory(ctxt);
 		return;
 	    }
 	    buf = new_buf;
             size = new_size;
 	}
-	COPY_BUF(ql,buf,len,q);
+	COPY_BUF(buf, len, q);
+        if (len > maxLength) {
+            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
+                         "Comment too big found", NULL);
+            xmlFree (buf);
+            return;
+        }
+
 	q = r;
 	ql = rl;
 	r = cur;
 	rl = l;
 
-	count++;
-	if (count > 50) {
-	    SHRINK;
-	    GROW;
-	    count = 0;
-            if (ctxt->instate == XML_PARSER_EOF) {
-		xmlFree(buf);
-		return;
-            }
-	}
 	NEXTL(l);
 	cur = CUR_CHAR(l);
-	if (cur == 0) {
-	    SHRINK;
-	    GROW;
-	    cur = CUR_CHAR(l);
-	}
+
     }
     buf[len] = 0;
     if (cur == 0) {
@@ -4841,11 +5193,6 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
                           "xmlParseComment: invalid xmlChar value %d\n",
 	                  cur);
     } else {
-	if (inputid != ctxt->input->id) {
-	    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
-		           "Comment doesn't start and stop in the same"
-                           " entity\n");
-	}
         NEXT;
 	if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
 	    (!ctxt->disableSAX))
@@ -4864,7 +5211,10 @@ not_terminated:
  * xmlParseComment:
  * @ctxt:  an XML parser context
  *
- * Skip an XML (SGML) comment <!-- .... -->
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Parse an XML (SGML) comment. Always consumes '<!'.
+ *
  *  The spec says that "For compatibility, the string "--" (double-hyphen)
  *  must not occur within comments. "
  *
@@ -4875,22 +5225,22 @@ xmlParseComment(xmlParserCtxtPtr ctxt) {
     xmlChar *buf = NULL;
     size_t size = XML_PARSER_BUFFER_SIZE;
     size_t len = 0;
-    xmlParserInputState state;
+    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                       XML_MAX_HUGE_LENGTH :
+                       XML_MAX_TEXT_LENGTH;
     const xmlChar *in;
     size_t nbchar = 0;
     int ccol;
-    int inputid;
 
     /*
      * Check that there is a comment right here.
      */
-    if ((RAW != '<') || (NXT(1) != '!') ||
-        (NXT(2) != '-') || (NXT(3) != '-')) return;
-    state = ctxt->instate;
-    ctxt->instate = XML_PARSER_COMMENT;
-    inputid = ctxt->input->id;
-    SKIP(4);
-    SHRINK;
+    if ((RAW != '<') || (NXT(1) != '!'))
+        return;
+    SKIP(2);
+    if ((RAW != '-') || (NXT(1) != '-'))
+        return;
+    SKIP(2);
     GROW;
 
     /*
@@ -4926,40 +5276,33 @@ get_more:
 	 * save current set of data
 	 */
 	if (nbchar > 0) {
-	    if ((ctxt->sax != NULL) &&
-		(ctxt->sax->comment != NULL)) {
-		if (buf == NULL) {
-		    if ((*in == '-') && (in[1] == '-'))
-		        size = nbchar + 1;
-		    else
-		        size = XML_PARSER_BUFFER_SIZE + nbchar;
-		    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
-		    if (buf == NULL) {
-		        xmlErrMemory(ctxt, NULL);
-			ctxt->instate = state;
-			return;
-		    }
-		    len = 0;
-		} else if (len + nbchar + 1 >= size) {
-		    xmlChar *new_buf;
-		    size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
-		    new_buf = (xmlChar *) xmlRealloc(buf,
-		                                     size * sizeof(xmlChar));
-		    if (new_buf == NULL) {
-		        xmlFree (buf);
-			xmlErrMemory(ctxt, NULL);
-			ctxt->instate = state;
-			return;
-		    }
-		    buf = new_buf;
-		}
-		memcpy(&buf[len], ctxt->input->cur, nbchar);
-		len += nbchar;
-		buf[len] = 0;
-	    }
+            if (buf == NULL) {
+                if ((*in == '-') && (in[1] == '-'))
+                    size = nbchar + 1;
+                else
+                    size = XML_PARSER_BUFFER_SIZE + nbchar;
+                buf = (xmlChar *) xmlMallocAtomic(size);
+                if (buf == NULL) {
+                    xmlErrMemory(ctxt);
+                    return;
+                }
+                len = 0;
+            } else if (len + nbchar + 1 >= size) {
+                xmlChar *new_buf;
+                size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
+                new_buf = (xmlChar *) xmlRealloc(buf, size);
+                if (new_buf == NULL) {
+                    xmlFree (buf);
+                    xmlErrMemory(ctxt);
+                    return;
+                }
+                buf = new_buf;
+            }
+            memcpy(&buf[len], ctxt->input->cur, nbchar);
+            len += nbchar;
+            buf[len] = 0;
 	}
-        if ((len > XML_MAX_TEXT_LENGTH) &&
-            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
+        if (len > maxLength) {
             xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
                          "Comment too big found", NULL);
             xmlFree (buf);
@@ -4982,19 +5325,10 @@ get_more:
 	}
 	SHRINK;
 	GROW;
-        if (ctxt->instate == XML_PARSER_EOF) {
-            xmlFree(buf);
-            return;
-        }
 	in = ctxt->input->cur;
 	if (*in == '-') {
 	    if (in[1] == '-') {
 	        if (in[2] == '>') {
-		    if (ctxt->input->id != inputid) {
-			xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
-			               "comment doesn't start and stop in the"
-                                       " same entity\n");
-		    }
 		    SKIP(3);
 		    if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
 		        (!ctxt->disableSAX)) {
@@ -5005,8 +5339,6 @@ get_more:
 		    }
 		    if (buf != NULL)
 		        xmlFree(buf);
-		    if (ctxt->instate != XML_PARSER_EOF)
-			ctxt->instate = state;
 		    return;
 		}
 		if (buf != NULL) {
@@ -5017,10 +5349,6 @@ get_more:
 		} else
 		    xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
 		                      "Double hyphen within comment\n", NULL);
-                if (ctxt->instate == XML_PARSER_EOF) {
-                    xmlFree(buf);
-                    return;
-                }
 		in++;
 		ctxt->input->col++;
 	    }
@@ -5030,7 +5358,6 @@ get_more:
 	}
     } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
     xmlParseCommentComplex(ctxt, buf, len, size);
-    ctxt->instate = state;
     return;
 }
 
@@ -5039,6 +5366,8 @@ get_more:
  * xmlParsePITarget:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse the name of a PI
  *
  * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
@@ -5129,6 +5458,12 @@ xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
 	goto error;
 
     if (URL != NULL) {
+        /*
+         * Unfortunately, the catalog API doesn't report OOM errors.
+         * xmlGetLastError isn't very helpful since we don't know
+         * where the last error came from. We'd have to reset it
+         * before this call and restore it afterwards.
+         */
 	ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
 	xmlFree(URL);
     }
@@ -5147,6 +5482,8 @@ error:
  * xmlParsePI:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an XML Processing Instruction.
  *
  * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
@@ -5159,20 +5496,17 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
     xmlChar *buf = NULL;
     size_t len = 0;
     size_t size = XML_PARSER_BUFFER_SIZE;
+    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                       XML_MAX_HUGE_LENGTH :
+                       XML_MAX_TEXT_LENGTH;
     int cur, l;
     const xmlChar *target;
-    xmlParserInputState state;
-    int count = 0;
 
     if ((RAW == '<') && (NXT(1) == '?')) {
-	int inputid = ctxt->input->id;
-	state = ctxt->instate;
-        ctxt->instate = XML_PARSER_PI;
 	/*
 	 * this is a Processing Instruction.
 	 */
 	SKIP(2);
-	SHRINK;
 
 	/*
 	 * Parse the target name and check for special support like
@@ -5181,11 +5515,6 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
         target = xmlParsePITarget(ctxt);
 	if (target != NULL) {
 	    if ((RAW == '?') && (NXT(1) == '>')) {
-		if (inputid != ctxt->input->id) {
-		    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
-	                           "PI declaration doesn't start and stop in"
-                                   " the same entity\n");
-		}
 		SKIP(2);
 
 		/*
@@ -5195,14 +5524,11 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
 		    (ctxt->sax->processingInstruction != NULL))
 		    ctxt->sax->processingInstruction(ctxt->userData,
 		                                     target, NULL);
-		if (ctxt->instate != XML_PARSER_EOF)
-		    ctxt->instate = state;
 		return;
 	    }
-	    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+	    buf = (xmlChar *) xmlMallocAtomic(size);
 	    if (buf == NULL) {
-		xmlErrMemory(ctxt, NULL);
-		ctxt->instate = state;
+		xmlErrMemory(ctxt);
 		return;
 	    }
 	    if (SKIP_BLANKS == 0) {
@@ -5217,64 +5543,32 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
                     size_t new_size = size * 2;
 		    tmp = (xmlChar *) xmlRealloc(buf, new_size);
 		    if (tmp == NULL) {
-			xmlErrMemory(ctxt, NULL);
+			xmlErrMemory(ctxt);
 			xmlFree(buf);
-			ctxt->instate = state;
 			return;
 		    }
 		    buf = tmp;
                     size = new_size;
 		}
-		count++;
-		if (count > 50) {
-		    SHRINK;
-		    GROW;
-                    if (ctxt->instate == XML_PARSER_EOF) {
-                        xmlFree(buf);
-                        return;
-                    }
-		    count = 0;
-                    if ((len > XML_MAX_TEXT_LENGTH) &&
-                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                        xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
-                                          "PI %s too big found", target);
-                        xmlFree(buf);
-                        ctxt->instate = state;
-                        return;
-                    }
-		}
-		COPY_BUF(l,buf,len,cur);
+		COPY_BUF(buf, len, cur);
+                if (len > maxLength) {
+                    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
+                                      "PI %s too big found", target);
+                    xmlFree(buf);
+                    return;
+                }
 		NEXTL(l);
 		cur = CUR_CHAR(l);
-		if (cur == 0) {
-		    SHRINK;
-		    GROW;
-		    cur = CUR_CHAR(l);
-		}
 	    }
-            if ((len > XML_MAX_TEXT_LENGTH) &&
-                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
-                                  "PI %s too big found", target);
-                xmlFree(buf);
-                ctxt->instate = state;
-                return;
-            }
 	    buf[len] = 0;
 	    if (cur != '?') {
 		xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
 		      "ParsePI: PI %s never end ...\n", target);
 	    } else {
-		if (inputid != ctxt->input->id) {
-		    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
-	                           "PI declaration doesn't start and stop in"
-                                   " the same entity\n");
-		}
 		SKIP(2);
 
 #ifdef LIBXML_CATALOG_ENABLED
-		if (((state == XML_PARSER_MISC) ||
-	             (state == XML_PARSER_START)) &&
+		if ((ctxt->inSubset == 0) &&
 		    (xmlStrEqual(target, XML_CATALOG_PI))) {
 		    xmlCatalogAllow allow = xmlCatalogGetDefaults();
 		    if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
@@ -5296,8 +5590,6 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
 	} else {
 	    xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
 	}
-	if (ctxt->instate != XML_PARSER_EOF)
-	    ctxt->instate = state;
     }
 }
 
@@ -5305,7 +5597,9 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
  * xmlParseNotationDecl:
  * @ctxt:  an XML parser context
  *
- * parse a notation declaration
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Parse a notation declaration. Always consumes '<!'.
  *
  * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
  *
@@ -5323,11 +5617,14 @@ xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
     xmlChar *Pubid;
     xmlChar *Systemid;
 
-    if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
+    if ((CUR != '<') || (NXT(1) != '!'))
+        return;
+    SKIP(2);
+
+    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
 	int inputid = ctxt->input->id;
-	SHRINK;
-	SKIP(10);
-	if (SKIP_BLANKS == 0) {
+	SKIP(8);
+	if (SKIP_BLANKS_PE == 0) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 			   "Space required after '<!NOTATION'\n");
 	    return;
@@ -5343,7 +5640,7 @@ xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
 		     "colons are forbidden from notation names '%s'\n",
 		     name, NULL, NULL);
 	}
-	if (SKIP_BLANKS == 0) {
+	if (SKIP_BLANKS_PE == 0) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 		     "Space required after the NOTATION name'\n");
 	    return;
@@ -5353,7 +5650,7 @@ xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
 	 * Parse the IDs.
 	 */
 	Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
 
 	if (RAW == '>') {
 	    if (inputid != ctxt->input->id) {
@@ -5377,7 +5674,9 @@ xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
  * xmlParseEntityDecl:
  * @ctxt:  an XML parser context
  *
- * parse <!ENTITY declarations
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Parse an entity declaration. Always consumes '<!'.
  *
  * [70] EntityDecl ::= GEDecl | PEDecl
  *
@@ -5404,19 +5703,22 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
     int isParameter = 0;
     xmlChar *orig = NULL;
 
+    if ((CUR != '<') || (NXT(1) != '!'))
+        return;
+    SKIP(2);
+
     /* GROW; done in the caller */
-    if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
+    if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
 	int inputid = ctxt->input->id;
-	SHRINK;
-	SKIP(8);
-	if (SKIP_BLANKS == 0) {
+	SKIP(6);
+	if (SKIP_BLANKS_PE == 0) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 			   "Space required after '<!ENTITY'\n");
 	}
 
 	if (RAW == '%') {
 	    NEXT;
-	    if (SKIP_BLANKS == 0) {
+	    if (SKIP_BLANKS_PE == 0) {
 		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 			       "Space required after '%%'\n");
 	    }
@@ -5434,12 +5736,11 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
 		     "colons are forbidden from entities names '%s'\n",
 		     name, NULL, NULL);
 	}
-	if (SKIP_BLANKS == 0) {
+	if (SKIP_BLANKS_PE == 0) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 			   "Space required after the entity name\n");
 	}
 
-	ctxt->instate = XML_PARSER_ENTITY_DECL;
 	/*
 	 * handle the various case of definitions...
 	 */
@@ -5459,34 +5760,16 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
 		    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
 		}
 		if (URI) {
-		    xmlURIPtr uri;
-
-		    uri = xmlParseURI((const char *) URI);
-		    if (uri == NULL) {
-		        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
-				     "Invalid URI: %s\n", URI);
-			/*
-			 * This really ought to be a well formedness error
-			 * but the XML Core WG decided otherwise c.f. issue
-			 * E26 of the XML erratas.
-			 */
-		    } else {
-			if (uri->fragment != NULL) {
-			    /*
-			     * Okay this is foolish to block those but not
-			     * invalid URIs.
-			     */
-			    xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
-			} else {
-			    if ((ctxt->sax != NULL) &&
-				(!ctxt->disableSAX) &&
-				(ctxt->sax->entityDecl != NULL))
-				ctxt->sax->entityDecl(ctxt->userData, name,
-					    XML_EXTERNAL_PARAMETER_ENTITY,
-					    literal, URI, NULL);
-			}
-			xmlFreeURI(uri);
-		    }
+                    if (xmlStrchr(URI, '#')) {
+                        xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
+                    } else {
+                        if ((ctxt->sax != NULL) &&
+                            (!ctxt->disableSAX) &&
+                            (ctxt->sax->entityDecl != NULL))
+                            ctxt->sax->entityDecl(ctxt->userData, name,
+                                        XML_EXTERNAL_PARAMETER_ENTITY,
+                                        literal, URI, NULL);
+                    }
 		}
 	    }
 	} else {
@@ -5505,14 +5788,19 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
 		    if (ctxt->myDoc == NULL) {
 			ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
 			if (ctxt->myDoc == NULL) {
-			    xmlErrMemory(ctxt, "New Doc failed");
-			    return;
+			    xmlErrMemory(ctxt);
+			    goto done;
 			}
 			ctxt->myDoc->properties = XML_DOC_INTERNAL;
 		    }
-		    if (ctxt->myDoc->intSubset == NULL)
+		    if (ctxt->myDoc->intSubset == NULL) {
 			ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
 					    BAD_CAST "fake", NULL, NULL);
+                        if (ctxt->myDoc->intSubset == NULL) {
+                            xmlErrMemory(ctxt);
+                            goto done;
+                        }
+                    }
 
 		    xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
 			              NULL, NULL, value);
@@ -5523,35 +5811,17 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
 		    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
 		}
 		if (URI) {
-		    xmlURIPtr uri;
-
-		    uri = xmlParseURI((const char *)URI);
-		    if (uri == NULL) {
-		        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
-				     "Invalid URI: %s\n", URI);
-			/*
-			 * This really ought to be a well formedness error
-			 * but the XML Core WG decided otherwise c.f. issue
-			 * E26 of the XML erratas.
-			 */
-		    } else {
-			if (uri->fragment != NULL) {
-			    /*
-			     * Okay this is foolish to block those but not
-			     * invalid URIs.
-			     */
-			    xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
-			}
-			xmlFreeURI(uri);
-		    }
+                    if (xmlStrchr(URI, '#')) {
+                        xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
+                    }
 		}
-		if ((RAW != '>') && (SKIP_BLANKS == 0)) {
+		if ((RAW != '>') && (SKIP_BLANKS_PE == 0)) {
 		    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 				   "Space required before 'NDATA'\n");
 		}
 		if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
 		    SKIP(5);
-		    if (SKIP_BLANKS == 0) {
+		    if (SKIP_BLANKS_PE == 0) {
 			xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 				       "Space required after 'NDATA'\n");
 		    }
@@ -5576,15 +5846,20 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
 			if (ctxt->myDoc == NULL) {
 			    ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
 			    if (ctxt->myDoc == NULL) {
-			        xmlErrMemory(ctxt, "New Doc failed");
-				return;
+			        xmlErrMemory(ctxt);
+				goto done;
 			    }
 			    ctxt->myDoc->properties = XML_DOC_INTERNAL;
 			}
 
-			if (ctxt->myDoc->intSubset == NULL)
+			if (ctxt->myDoc->intSubset == NULL) {
 			    ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
 						BAD_CAST "fake", NULL, NULL);
+                            if (ctxt->myDoc->intSubset == NULL) {
+                                xmlErrMemory(ctxt);
+                                goto done;
+                            }
+                        }
 			xmlSAX2EntityDecl(ctxt, name,
 				          XML_EXTERNAL_GENERAL_PARSED_ENTITY,
 				          literal, URI, NULL);
@@ -5592,9 +5867,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
 		}
 	    }
 	}
-	if (ctxt->instate == XML_PARSER_EOF)
-	    goto done;
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
 	if (RAW != '>') {
 	    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
 	            "xmlParseEntityDecl: entity %s not terminated\n", name);
@@ -5644,6 +5917,8 @@ done:
  * @ctxt:  an XML parser context
  * @value:  Receive a possible fixed default value for the attribute
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Parse an attribute default declaration
  *
  * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
@@ -5686,13 +5961,12 @@ xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
     if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
 	SKIP(6);
 	val = XML_ATTRIBUTE_FIXED;
-	if (SKIP_BLANKS == 0) {
+	if (SKIP_BLANKS_PE == 0) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 			   "Space required after '#FIXED'\n");
 	}
     }
     ret = xmlParseAttValue(ctxt);
-    ctxt->instate = XML_PARSER_DTD;
     if (ret == NULL) {
 	xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
 		       "Attribute default value declaration error\n");
@@ -5705,6 +5979,8 @@ xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
  * xmlParseNotationType:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an Notation attribute type.
  *
  * Note: the leading 'NOTATION' S part has already being parsed...
@@ -5727,10 +6003,9 @@ xmlParseNotationType(xmlParserCtxtPtr ctxt) {
 	xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
 	return(NULL);
     }
-    SHRINK;
     do {
         NEXT;
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
         name = xmlParseName(ctxt);
 	if (name == NULL) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
@@ -5753,6 +6028,7 @@ xmlParseNotationType(xmlParserCtxtPtr ctxt) {
 	if (tmp == NULL) {
 	    cur = xmlCreateEnumeration(name);
 	    if (cur == NULL) {
+                xmlErrMemory(ctxt);
                 xmlFreeEnumeration(ret);
                 return(NULL);
             }
@@ -5762,7 +6038,7 @@ xmlParseNotationType(xmlParserCtxtPtr ctxt) {
 		last = cur;
 	    }
 	}
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
     } while (RAW == '|');
     if (RAW != ')') {
 	xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
@@ -5777,6 +6053,8 @@ xmlParseNotationType(xmlParserCtxtPtr ctxt) {
  * xmlParseEnumerationType:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an Enumeration attribute type.
  *
  * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
@@ -5797,10 +6075,9 @@ xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
 	xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
 	return(NULL);
     }
-    SHRINK;
     do {
         NEXT;
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
         name = xmlParseNmtoken(ctxt);
 	if (name == NULL) {
 	    xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
@@ -5823,6 +6100,7 @@ xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
 	    if (!xmlDictOwns(ctxt->dict, name))
 		xmlFree(name);
 	    if (cur == NULL) {
+                xmlErrMemory(ctxt);
                 xmlFreeEnumeration(ret);
                 return(NULL);
             }
@@ -5832,7 +6110,7 @@ xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
 		last = cur;
 	    }
 	}
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
     } while (RAW == '|');
     if (RAW != ')') {
 	xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
@@ -5847,6 +6125,8 @@ xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
  * @ctxt:  an XML parser context
  * @tree:  the enumeration tree built while parsing
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an Enumerated attribute type.
  *
  * [57] EnumeratedType ::= NotationType | Enumeration
@@ -5861,7 +6141,7 @@ int
 xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
     if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
 	SKIP(8);
-	if (SKIP_BLANKS == 0) {
+	if (SKIP_BLANKS_PE == 0) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 			   "Space required after 'NOTATION'\n");
 	    return(0);
@@ -5880,6 +6160,8 @@ xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
  * @ctxt:  an XML parser context
  * @tree:  the enumeration tree built while parsing
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse the Attribute list def for an element
  *
  * [54] AttType ::= StringType | TokenizedType | EnumeratedType
@@ -5922,7 +6204,6 @@ xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
  */
 int
 xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
-    SHRINK;
     if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
 	SKIP(5);
 	return(XML_ATTRIBUTE_CDATA);
@@ -5955,7 +6236,9 @@ xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
  * xmlParseAttributeListDecl:
  * @ctxt:  an XML parser context
  *
- * : parse the Attribute list def for an element
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Parse an attribute list declaration for an element. Always consumes '<!'.
  *
  * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
  *
@@ -5968,11 +6251,15 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
     const xmlChar *attrName;
     xmlEnumerationPtr tree;
 
-    if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
+    if ((CUR != '<') || (NXT(1) != '!'))
+        return;
+    SKIP(2);
+
+    if (CMP7(CUR_PTR, 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
 	int inputid = ctxt->input->id;
 
-	SKIP(9);
-	if (SKIP_BLANKS == 0) {
+	SKIP(7);
+	if (SKIP_BLANKS_PE == 0) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 		                 "Space required after '<!ATTLIST'\n");
 	}
@@ -5982,9 +6269,9 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
 			   "ATTLIST: no name for Element\n");
 	    return;
 	}
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
 	GROW;
-	while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
+	while ((RAW != '>') && (PARSER_STOPPED(ctxt) == 0)) {
 	    int type;
 	    int def;
 	    xmlChar *defaultValue = NULL;
@@ -5998,7 +6285,7 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
 		break;
 	    }
 	    GROW;
-	    if (SKIP_BLANKS == 0) {
+	    if (SKIP_BLANKS_PE == 0) {
 		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 		        "Space required after the attribute name\n");
 		break;
@@ -6010,7 +6297,7 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
 	    }
 
 	    GROW;
-	    if (SKIP_BLANKS == 0) {
+	    if (SKIP_BLANKS_PE == 0) {
 		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 			       "Space required after the attribute type\n");
 	        if (tree != NULL)
@@ -6031,7 +6318,7 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
 
 	    GROW;
             if (RAW != '>') {
-		if (SKIP_BLANKS == 0) {
+		if (SKIP_BLANKS_PE == 0) {
 		    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 			"Space required after the attribute default value\n");
 		    if (defaultValue != NULL)
@@ -6076,6 +6363,8 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
  * @ctxt:  an XML parser context
  * @inputchk:  the input used for the current entity, needed for boundary checks
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse the declaration for a Mixed Element content
  * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
  *
@@ -6098,8 +6387,7 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
     GROW;
     if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
 	SKIP(7);
-	SKIP_BLANKS;
-	SHRINK;
+	SKIP_BLANKS_PE;
 	if (RAW == ')') {
 	    if (ctxt->input->id != inputchk) {
 		xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
@@ -6109,7 +6397,7 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 	    NEXT;
 	    ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
 	    if (ret == NULL)
-	        return(NULL);
+                goto mem_error;
 	    if (RAW == '*') {
 		ret->ocur = XML_ELEMENT_CONTENT_MULT;
 		NEXT;
@@ -6118,35 +6406,29 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 	}
 	if ((RAW == '(') || (RAW == '|')) {
 	    ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
-	    if (ret == NULL) return(NULL);
+	    if (ret == NULL)
+                goto mem_error;
 	}
-	while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
+	while ((RAW == '|') && (PARSER_STOPPED(ctxt) == 0)) {
 	    NEXT;
+            n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
+            if (n == NULL)
+                goto mem_error;
 	    if (elem == NULL) {
-	        ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
-		if (ret == NULL) {
-		    xmlFreeDocElementContent(ctxt->myDoc, cur);
-                    return(NULL);
-                }
-		ret->c1 = cur;
+		n->c1 = cur;
 		if (cur != NULL)
-		    cur->parent = ret;
-		cur = ret;
+		    cur->parent = n;
+		ret = cur = n;
 	    } else {
-	        n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
-		if (n == NULL) {
-		    xmlFreeDocElementContent(ctxt->myDoc, ret);
-                    return(NULL);
-                }
-		n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
-		if (n->c1 != NULL)
-		    n->c1->parent = n;
 	        cur->c2 = n;
-		if (n != NULL)
-		    n->parent = cur;
+		n->parent = cur;
+		n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
+                if (n->c1 == NULL)
+                    goto mem_error;
+		n->c1->parent = n;
 		cur = n;
 	    }
-	    SKIP_BLANKS;
+	    SKIP_BLANKS_PE;
 	    elem = xmlParseName(ctxt);
 	    if (elem == NULL) {
 		xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
@@ -6154,15 +6436,16 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 		xmlFreeDocElementContent(ctxt->myDoc, ret);
 		return(NULL);
 	    }
-	    SKIP_BLANKS;
+	    SKIP_BLANKS_PE;
 	    GROW;
 	}
 	if ((RAW == ')') && (NXT(1) == '*')) {
 	    if (elem != NULL) {
 		cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
 		                               XML_ELEMENT_CONTENT_ELEMENT);
-		if (cur->c2 != NULL)
-		    cur->c2->parent = cur;
+		if (cur->c2 == NULL)
+                    goto mem_error;
+		cur->c2->parent = cur;
             }
             if (ret != NULL)
                 ret->ocur = XML_ELEMENT_CONTENT_MULT;
@@ -6182,6 +6465,11 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 	xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
     }
     return(ret);
+
+mem_error:
+    xmlErrMemory(ctxt);
+    xmlFreeDocElementContent(ctxt->myDoc, ret);
+    return(NULL);
 }
 
 /**
@@ -6219,30 +6507,30 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 static xmlElementContentPtr
 xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
                                        int depth) {
+    int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 2048 : 256;
     xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
     const xmlChar *elem;
     xmlChar type = 0;
 
-    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
-        (depth >  2048)) {
-        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
-"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
-                          depth);
+    if (depth > maxDepth) {
+        xmlFatalErrMsgInt(ctxt, XML_ERR_RESOURCE_LIMIT,
+                "xmlParseElementChildrenContentDecl : depth %d too deep, "
+                "use XML_PARSE_HUGE\n", depth);
 	return(NULL);
     }
-    SKIP_BLANKS;
+    SKIP_BLANKS_PE;
     GROW;
     if (RAW == '(') {
 	int inputid = ctxt->input->id;
 
         /* Recurse on first child */
 	NEXT;
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
         cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
                                                            depth + 1);
         if (cur == NULL)
             return(NULL);
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
 	GROW;
     } else {
 	elem = xmlParseName(ctxt);
@@ -6252,7 +6540,7 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
 	}
         cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 	if (cur == NULL) {
-	    xmlErrMemory(ctxt, NULL);
+	    xmlErrMemory(ctxt);
 	    return(NULL);
 	}
 	GROW;
@@ -6270,9 +6558,8 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
 	}
 	GROW;
     }
-    SKIP_BLANKS;
-    SHRINK;
-    while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
+    SKIP_BLANKS_PE;
+    while ((RAW != ')') && (PARSER_STOPPED(ctxt) == 0)) {
         /*
 	 * Each loop we parse one separator and one element.
 	 */
@@ -6296,6 +6583,7 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
 
 	    op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
 	    if (op == NULL) {
+                xmlErrMemory(ctxt);
 		if ((last != NULL) && (last != ret))
 		    xmlFreeDocElementContent(ctxt->myDoc, last);
 	        xmlFreeDocElementContent(ctxt->myDoc, ret);
@@ -6336,6 +6624,7 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
 
 	    op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
 	    if (op == NULL) {
+                xmlErrMemory(ctxt);
 		if ((last != NULL) && (last != ret))
 		    xmlFreeDocElementContent(ctxt->myDoc, last);
 		if (ret != NULL)
@@ -6366,13 +6655,13 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
 	    return(NULL);
 	}
 	GROW;
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
 	GROW;
 	if (RAW == '(') {
 	    int inputid = ctxt->input->id;
 	    /* Recurse on second child */
 	    NEXT;
-	    SKIP_BLANKS;
+	    SKIP_BLANKS_PE;
 	    last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
                                                           depth + 1);
             if (last == NULL) {
@@ -6380,7 +6669,7 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
 		    xmlFreeDocElementContent(ctxt->myDoc, ret);
 		return(NULL);
             }
-	    SKIP_BLANKS;
+	    SKIP_BLANKS_PE;
 	} else {
 	    elem = xmlParseName(ctxt);
 	    if (elem == NULL) {
@@ -6391,6 +6680,7 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
 	    }
 	    last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 	    if (last == NULL) {
+                xmlErrMemory(ctxt);
 		if (ret != NULL)
 		    xmlFreeDocElementContent(ctxt->myDoc, ret);
 		return(NULL);
@@ -6408,7 +6698,7 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
 		last->ocur = XML_ELEMENT_CONTENT_ONCE;
 	    }
 	}
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
 	GROW;
     }
     if ((cur != NULL) && (last != NULL)) {
@@ -6494,6 +6784,8 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
  * @ctxt:  an XML parser context
  * @inputchk:  the input used for the current entity, needed for boundary checks
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse the declaration for a Mixed Element content
  * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
  *
@@ -6531,6 +6823,8 @@ xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
  * @name:  the name of the element being defined.
  * @result:  the Element Content pointer will be stored here if any
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse the declaration for an Element content either Mixed or Children,
  * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
  *
@@ -6556,9 +6850,7 @@ xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
     }
     NEXT;
     GROW;
-    if (ctxt->instate == XML_PARSER_EOF)
-        return(-1);
-    SKIP_BLANKS;
+    SKIP_BLANKS_PE;
     if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
         tree = xmlParseElementMixedContentDecl(ctxt, inputid);
 	res = XML_ELEMENT_TYPE_MIXED;
@@ -6566,7 +6858,7 @@ xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
         tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
 	res = XML_ELEMENT_TYPE_ELEMENT;
     }
-    SKIP_BLANKS;
+    SKIP_BLANKS_PE;
     *result = tree;
     return(res);
 }
@@ -6575,7 +6867,9 @@ xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
  * xmlParseElementDecl:
  * @ctxt:  an XML parser context
  *
- * parse an Element declaration.
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Parse an element declaration. Always consumes '<!'.
  *
  * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
  *
@@ -6590,12 +6884,16 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
     int ret = -1;
     xmlElementContentPtr content  = NULL;
 
+    if ((CUR != '<') || (NXT(1) != '!'))
+        return(ret);
+    SKIP(2);
+
     /* GROW; done in the caller */
-    if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
+    if (CMP7(CUR_PTR, 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
 	int inputid = ctxt->input->id;
 
-	SKIP(9);
-	if (SKIP_BLANKS == 0) {
+	SKIP(7);
+	if (SKIP_BLANKS_PE == 0) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 		           "Space required after 'ELEMENT'\n");
 	    return(-1);
@@ -6606,7 +6904,7 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
 			   "xmlParseElementDecl: no name for Element\n");
 	    return(-1);
 	}
-	if (SKIP_BLANKS == 0) {
+	if (SKIP_BLANKS_PE == 0) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 			   "Space required after the element name\n");
 	}
@@ -6629,18 +6927,12 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
 	    /*
 	     * [ WFC: PEs in Internal Subset ] error handling.
 	     */
-	    if ((RAW == '%') && (ctxt->external == 0) &&
-	        (ctxt->inputNr == 1)) {
-		xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
-	  "PEReference: forbidden within markup decl in internal subset\n");
-	    } else {
-		xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
-		      "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
-            }
+            xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
+                  "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
 	    return(-1);
 	}
 
-	SKIP_BLANKS;
+	SKIP_BLANKS_PE;
 
 	if (RAW != '>') {
 	    xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
@@ -6682,6 +6974,8 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
  * xmlParseConditionalSections
  * @ctxt:  an XML parser context
  *
+ * Parse a conditional section. Always consumes '<!['.
+ *
  * [61] conditionalSect ::= includeSect | ignoreSect
  * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
  * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
@@ -6695,16 +6989,16 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
     size_t inputIdsSize = 0;
     size_t depth = 0;
 
-    while (ctxt->instate != XML_PARSER_EOF) {
+    while (PARSER_STOPPED(ctxt) == 0) {
         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
             int id = ctxt->input->id;
 
             SKIP(3);
-            SKIP_BLANKS;
+            SKIP_BLANKS_PE;
 
             if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
                 SKIP(7);
-                SKIP_BLANKS;
+                SKIP_BLANKS_PE;
                 if (RAW != '[') {
                     xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
                     xmlHaltParser(ctxt);
@@ -6724,7 +7018,7 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
                     tmp = (int *) xmlRealloc(inputIds,
                             inputIdsSize * sizeof(int));
                     if (tmp == NULL) {
-                        xmlErrMemory(ctxt, NULL);
+                        xmlErrMemory(ctxt);
                         goto error;
                     }
                     inputIds = tmp;
@@ -6732,12 +7026,10 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
                 inputIds[depth] = id;
                 depth++;
             } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
-                int state;
-                xmlParserInputState instate;
                 size_t ignoreDepth = 0;
 
                 SKIP(6);
-                SKIP_BLANKS;
+                SKIP_BLANKS_PE;
                 if (RAW != '[') {
                     xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
                     xmlHaltParser(ctxt);
@@ -6750,48 +7042,35 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
                 }
                 NEXT;
 
-                /*
-                 * Parse up to the end of the conditional section but disable
-                 * SAX event generating DTD building in the meantime
-                 */
-                state = ctxt->disableSAX;
-                instate = ctxt->instate;
-                if (ctxt->recovery == 0) ctxt->disableSAX = 1;
-                ctxt->instate = XML_PARSER_IGNORE;
-
-                while (RAW != 0) {
+                while (PARSER_STOPPED(ctxt) == 0) {
+                    if (RAW == 0) {
+                        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
+                        goto error;
+                    }
                     if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
                         SKIP(3);
                         ignoreDepth++;
                         /* Check for integer overflow */
                         if (ignoreDepth == 0) {
-                            xmlErrMemory(ctxt, NULL);
+                            xmlErrMemory(ctxt);
                             goto error;
                         }
                     } else if ((RAW == ']') && (NXT(1) == ']') &&
                                (NXT(2) == '>')) {
+                        SKIP(3);
                         if (ignoreDepth == 0)
                             break;
-                        SKIP(3);
                         ignoreDepth--;
                     } else {
                         NEXT;
                     }
                 }
 
-                ctxt->disableSAX = state;
-                ctxt->instate = instate;
-
-		if (RAW == 0) {
-		    xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
-                    goto error;
-		}
                 if (ctxt->input->id != id) {
                     xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
                                    "All markup of the conditional section is"
                                    " not in the same entity\n");
                 }
-                SKIP(3);
             } else {
                 xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
                 xmlHaltParser(ctxt);
@@ -6806,23 +7085,19 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
                                " in the same entity\n");
             }
             SKIP(3);
-        } else {
-            int id = ctxt->input->id;
-            unsigned long cons = CUR_CONSUMED;
-
+        } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
             xmlParseMarkupDecl(ctxt);
-
-            if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
-                xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
-                xmlHaltParser(ctxt);
-                goto error;
-            }
+        } else {
+            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+            xmlHaltParser(ctxt);
+            goto error;
         }
 
         if (depth == 0)
             break;
 
-        SKIP_BLANKS;
+        SKIP_BLANKS_PE;
+        SHRINK;
         GROW;
     }
 
@@ -6834,7 +7109,9 @@ error:
  * xmlParseMarkupDecl:
  * @ctxt:  an XML parser context
  *
- * parse Markup declarations
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Parse markup declarations. Always consumes '<!' or '<?'.
  *
  * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
  *                     NotationDecl | PI | Comment
@@ -6863,6 +7140,8 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
 			xmlParseElementDecl(ctxt);
 		    else if (NXT(3) == 'N')
 			xmlParseEntityDecl(ctxt);
+                    else
+                        SKIP(2);
 		    break;
 	        case 'A':
 		    xmlParseAttributeListDecl(ctxt);
@@ -6875,27 +7154,21 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
 		    break;
 		default:
 		    /* there is an error but it will be detected later */
+                    SKIP(2);
 		    break;
 	    }
 	} else if (NXT(1) == '?') {
 	    xmlParsePI(ctxt);
 	}
     }
-
-    /*
-     * detect requirement to exit there and act accordingly
-     * and avoid having instate overridden later on
-     */
-    if (ctxt->instate == XML_PARSER_EOF)
-        return;
-
-    ctxt->instate = XML_PARSER_DTD;
 }
 
 /**
  * xmlParseTextDecl:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an XML declaration header for external entities
  *
  * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
@@ -6904,8 +7177,6 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
 void
 xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
     xmlChar *version;
-    const xmlChar *encoding;
-    int oldstate;
 
     /*
      * We know that '<?xml' is here.
@@ -6917,10 +7188,6 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
 	return;
     }
 
-    /* Avoid expansion of parameter entities when skipping blanks. */
-    oldstate = ctxt->instate;
-    ctxt->instate = XML_PARSER_START;
-
     if (SKIP_BLANKS == 0) {
 	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 		       "Space needed after '<?xml'\n");
@@ -6930,9 +7197,13 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
      * We may have the VersionInfo here.
      */
     version = xmlParseVersionInfo(ctxt);
-    if (version == NULL)
+    if (version == NULL) {
 	version = xmlCharStrdup(XML_DEFAULT_VERSION);
-    else {
+        if (version == NULL) {
+            xmlErrMemory(ctxt);
+            return;
+        }
+    } else {
 	if (SKIP_BLANKS == 0) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 		           "Space needed here\n");
@@ -6943,18 +7214,7 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
     /*
      * We must have the encoding declaration
      */
-    encoding = xmlParseEncodingDecl(ctxt);
-    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
-	/*
-	 * The XML REC instructs us to stop parsing right here
-	 */
-        ctxt->instate = oldstate;
-        return;
-    }
-    if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
-	xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
-		       "Missing encoding in text declaration\n");
-    }
+    xmlParseEncodingDecl(ctxt);
 
     SKIP_BLANKS;
     if ((RAW == '?') && (NXT(1) == '>')) {
@@ -6964,12 +7224,15 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
 	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 	NEXT;
     } else {
+        int c;
+
 	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
-	MOVETO_ENDTAG(CUR_PTR);
-	NEXT;
+        while ((PARSER_STOPPED(ctxt) == 0) && ((c = CUR) != 0)) {
+            NEXT;
+            if (c == '>')
+                break;
+        }
     }
-
-    ctxt->instate = oldstate;
 }
 
 /**
@@ -6987,91 +7250,76 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
 void
 xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
                        const xmlChar *SystemID) {
-    xmlDetectSAX2(ctxt);
-    GROW;
+    int oldInputNr;
 
-    if ((ctxt->encoding == NULL) &&
-        (ctxt->input->end - ctxt->input->cur >= 4)) {
-        xmlChar start[4];
-	xmlCharEncoding enc;
+    xmlCtxtInitializeLate(ctxt);
 
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(start, 4);
-	if (enc != XML_CHAR_ENCODING_NONE)
-	    xmlSwitchEncoding(ctxt, enc);
-    }
+    xmlDetectEncoding(ctxt);
 
     if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
 	xmlParseTextDecl(ctxt);
-	if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
-	    /*
-	     * The XML REC instructs us to stop parsing right here
-	     */
-	    xmlHaltParser(ctxt);
-	    return;
-	}
     }
     if (ctxt->myDoc == NULL) {
         ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
 	if (ctxt->myDoc == NULL) {
-	    xmlErrMemory(ctxt, "New Doc failed");
+	    xmlErrMemory(ctxt);
 	    return;
 	}
 	ctxt->myDoc->properties = XML_DOC_INTERNAL;
     }
-    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
-        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
+    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL) &&
+        (xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID) == NULL)) {
+        xmlErrMemory(ctxt);
+    }
 
-    ctxt->instate = XML_PARSER_DTD;
-    ctxt->external = 1;
-    SKIP_BLANKS;
-    while (((RAW == '<') && (NXT(1) == '?')) ||
-           ((RAW == '<') && (NXT(1) == '!')) ||
-	   (RAW == '%')) {
-	int id = ctxt->input->id;
-	unsigned long cons = CUR_CONSUMED;
+    ctxt->inSubset = 2;
+    oldInputNr = ctxt->inputNr;
 
+    SKIP_BLANKS_PE;
+    while (((RAW != 0) || (ctxt->inputNr > oldInputNr)) &&
+           (!PARSER_STOPPED(ctxt))) {
 	GROW;
         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
-	    xmlParseConditionalSections(ctxt);
-	} else
-	    xmlParseMarkupDecl(ctxt);
-        SKIP_BLANKS;
-
-	if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
-	    xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
-	    break;
-	}
+            xmlParseConditionalSections(ctxt);
+        } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
+            xmlParseMarkupDecl(ctxt);
+        } else {
+            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+            xmlHaltParser(ctxt);
+            return;
+        }
+        SKIP_BLANKS_PE;
+        SHRINK;
     }
 
+    while (ctxt->inputNr > oldInputNr)
+        xmlPopPE(ctxt);
+
     if (RAW != 0) {
 	xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
     }
-
 }
 
 /**
  * xmlParseReference:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse and handle entity references in content, depending on the SAX
  * interface, this may end-up in a call to character() if this is a
  * CharRef, a predefined entity, if there is no reference() callback.
  * or if the parser was asked to switch to that mode.
  *
+ * Always consumes '&'.
+ *
  * [67] Reference ::= EntityRef | CharRef
  */
 void
 xmlParseReference(xmlParserCtxtPtr ctxt) {
-    xmlEntityPtr ent;
+    xmlEntityPtr ent = NULL;
+    const xmlChar *name;
     xmlChar *val;
-    int was_checked;
-    xmlNodePtr list = NULL;
-    xmlParserErrors ret = XML_ERR_OK;
-
 
     if (RAW != '&')
         return;
@@ -7082,53 +7330,43 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
     if (NXT(1) == '#') {
 	int i = 0;
 	xmlChar out[16];
-	int hex = NXT(2);
 	int value = xmlParseCharRef(ctxt);
 
 	if (value == 0)
 	    return;
-	if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
-	    /*
-	     * So we are using non-UTF-8 buffers
-	     * Check that the char fit on 8bits, if not
-	     * generate a CharRef.
-	     */
-	    if (value <= 0xFF) {
-		out[0] = value;
-		out[1] = 0;
-		if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
-		    (!ctxt->disableSAX))
-		    ctxt->sax->characters(ctxt->userData, out, 1);
-	    } else {
-		if ((hex == 'x') || (hex == 'X'))
-		    snprintf((char *)out, sizeof(out), "#x%X", value);
-		else
-		    snprintf((char *)out, sizeof(out), "#%d", value);
-		if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
-		    (!ctxt->disableSAX))
-		    ctxt->sax->reference(ctxt->userData, out);
-	    }
-	} else {
-	    /*
-	     * Just encode the value in UTF-8
-	     */
-	    COPY_BUF(0 ,out, i, value);
-	    out[i] = 0;
-	    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
-		(!ctxt->disableSAX))
-		ctxt->sax->characters(ctxt->userData, out, i);
-	}
+
+        /*
+         * Just encode the value in UTF-8
+         */
+        COPY_BUF(out, i, value);
+        out[i] = 0;
+        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
+            (!ctxt->disableSAX))
+            ctxt->sax->characters(ctxt->userData, out, i);
 	return;
     }
 
     /*
      * We are seeing an entity reference
      */
-    ent = xmlParseEntityRef(ctxt);
-    if (ent == NULL) return;
+    name = xmlParseEntityRefInternal(ctxt);
+    if (name == NULL)
+        return;
+    ent = xmlLookupGeneralEntity(ctxt, name, /* isAttr */ 0);
+    if (ent == NULL) {
+        /*
+         * Create a reference for undeclared entities.
+         */
+        if ((ctxt->replaceEntities == 0) &&
+            (ctxt->sax != NULL) &&
+            (ctxt->disableSAX == 0) &&
+            (ctxt->sax->reference != NULL)) {
+            ctxt->sax->reference(ctxt->userData, name);
+        }
+        return;
+    }
     if (!ctxt->wellFormed)
 	return;
-    was_checked = ent->checked;
 
     /* special case of predefined entities */
     if ((ent->name == NULL) ||
@@ -7144,6 +7382,14 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
 	return;
     }
 
+    /*
+     * Some users try to parse entities on their own and used to set
+     * the renamed "checked" member. Fix the flags to cover this
+     * case.
+     */
+    if (((ent->flags & XML_ENT_PARSED) == 0) && (ent->children != NULL))
+        ent->flags |= XML_ENT_PARSED;
+
     /*
      * The first reference to the entity trigger a parsing phase
      * where the ent->children is filled with the result from
@@ -7153,393 +7399,220 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
      * of validating, or substituting entities were given. Doing so is
      * far more secure as the parser will only process data coming from
      * the document entity by default.
-     */
-    if (((ent->checked == 0) ||
-         ((ent->children == NULL) && (ctxt->options & XML_PARSE_NOENT))) &&
-        ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
-         (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
-	unsigned long oldnbent = ctxt->nbentities, diff;
-
-	/*
-	 * This is a bit hackish but this seems the best
-	 * way to make sure both SAX and DOM entity support
-	 * behaves okay.
-	 */
-	void *user_data;
-	if (ctxt->userData == ctxt)
-	    user_data = NULL;
-	else
-	    user_data = ctxt->userData;
-
-	/*
-	 * Check that this entity is well formed
-	 * 4.3.2: An internal general parsed entity is well-formed
-	 * if its replacement text matches the production labeled
-	 * content.
-	 */
-	if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
-	    ctxt->depth++;
-	    ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
-	                                              user_data, &list);
-	    ctxt->depth--;
-
-	} else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
-	    ctxt->depth++;
-	    ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
-	                                   user_data, ctxt->depth, ent->URI,
-					   ent->ExternalID, &list);
-	    ctxt->depth--;
-	} else {
-	    ret = XML_ERR_ENTITY_PE_INTERNAL;
-	    xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
-			 "invalid entity type found\n", NULL);
-	}
-
-	/*
-	 * Store the number of entities needing parsing for this entity
-	 * content and do checkings
-	 */
-        diff = ctxt->nbentities - oldnbent + 1;
-        if (diff > INT_MAX / 2)
-            diff = INT_MAX / 2;
-        ent->checked = diff * 2;
-	if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
-	    ent->checked |= 1;
-	if (ret == XML_ERR_ENTITY_LOOP) {
-	    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
-            xmlHaltParser(ctxt);
-	    xmlFreeNodeList(list);
-	    return;
-	}
-	if (xmlParserEntityCheck(ctxt, 0, ent, 0)) {
-	    xmlFreeNodeList(list);
-	    return;
-	}
-
-	if ((ret == XML_ERR_OK) && (list != NULL)) {
-	    if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
-	     (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
-		(ent->children == NULL)) {
-		ent->children = list;
-                /*
-                 * Prune it directly in the generated document
-                 * except for single text nodes.
-                 */
-                if ((ctxt->replaceEntities == 0) ||
-                    (ctxt->parseMode == XML_PARSE_READER) ||
-                    ((list->type == XML_TEXT_NODE) &&
-                     (list->next == NULL))) {
-                    ent->owner = 1;
-                    while (list != NULL) {
-                        list->parent = (xmlNodePtr) ent;
-                        if (list->doc != ent->doc)
-                            xmlSetTreeDoc(list, ent->doc);
-                        if (list->next == NULL)
-                            ent->last = list;
-                        list = list->next;
-                    }
-                    list = NULL;
-                } else {
-                    ent->owner = 0;
-                    while (list != NULL) {
-                        list->parent = (xmlNodePtr) ctxt->node;
-                        list->doc = ctxt->myDoc;
-                        if (list->next == NULL)
-                            ent->last = list;
-                        list = list->next;
-                    }
-                    list = ent->children;
-#ifdef LIBXML_LEGACY_ENABLED
-                    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
-                        xmlAddEntityReference(ent, list, NULL);
-#endif /* LIBXML_LEGACY_ENABLED */
-                }
-	    } else {
-		xmlFreeNodeList(list);
-		list = NULL;
-	    }
-	} else if ((ret != XML_ERR_OK) &&
-		   (ret != XML_WAR_UNDECLARED_ENTITY)) {
-	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
-		     "Entity '%s' failed to parse\n", ent->name);
-            if (ent->content != NULL)
-                ent->content[0] = 0;
-	    xmlParserEntityCheck(ctxt, 0, ent, 0);
-	} else if (list != NULL) {
-	    xmlFreeNodeList(list);
-	    list = NULL;
-	}
-	if (ent->checked == 0)
-	    ent->checked = 2;
-
-        /* Prevent entity from being parsed and expanded twice (Bug 760367). */
-        was_checked = 0;
-    } else if (ent->checked != 1) {
-	ctxt->nbentities += ent->checked / 2;
+     *
+     * FIXME: This doesn't work correctly since entities can be
+     * expanded with different namespace declarations in scope.
+     * For example:
+     *
+     * <!DOCTYPE doc [
+     *   <!ENTITY ent "<ns:elem/>">
+     * ]>
+     * <doc>
+     *   <decl1 xmlns:ns="urn:ns1">
+     *     &ent;
+     *   </decl1>
+     *   <decl2 xmlns:ns="urn:ns2">
+     *     &ent;
+     *   </decl2>
+     * </doc>
+     *
+     * Proposed fix:
+     *
+     * - Ignore current namespace declarations when parsing the
+     *   entity. If a prefix can't be resolved, don't report an error
+     *   but mark it as unresolved.
+     * - Try to resolve these prefixes when expanding the entity.
+     *   This will require a specialized version of xmlStaticCopyNode
+     *   which can also make use of the namespace hash table to avoid
+     *   quadratic behavior.
+     *
+     * Alternatively, we could simply reparse the entity on each
+     * expansion like we already do with custom SAX callbacks.
+     * External entity content should be cached in this case.
+     */
+    if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
+        (((ctxt->options & XML_PARSE_NO_XXE) == 0) &&
+         ((ctxt->replaceEntities) ||
+          (ctxt->validate)))) {
+        if ((ent->flags & XML_ENT_PARSED) == 0) {
+            xmlCtxtParseEntity(ctxt, ent);
+        } else if (ent->children == NULL) {
+            /*
+             * Probably running in SAX mode and the callbacks don't
+             * build the entity content. Parse the entity again.
+             *
+             * This will also be triggered in normal tree builder mode
+             * if an entity happens to be empty, causing unnecessary
+             * reloads. It's hard to come up with a reliable check in
+             * which mode we're running.
+             */
+            xmlCtxtParseEntity(ctxt, ent);
+        }
     }
 
     /*
-     * Now that the entity content has been gathered
-     * provide it to the application, this can take different forms based
-     * on the parsing modes.
+     * We also check for amplification if entities aren't substituted.
+     * They might be expanded later.
      */
-    if (ent->children == NULL) {
-	/*
-	 * Probably running in SAX mode and the callbacks don't
-	 * build the entity content. So unless we already went
-	 * though parsing for first checking go though the entity
-	 * content to generate callbacks associated to the entity
-	 */
-	if (was_checked != 0) {
-	    void *user_data;
-	    /*
-	     * This is a bit hackish but this seems the best
-	     * way to make sure both SAX and DOM entity support
-	     * behaves okay.
-	     */
-	    if (ctxt->userData == ctxt)
-		user_data = NULL;
-	    else
-		user_data = ctxt->userData;
-
-	    if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
-		ctxt->depth++;
-		ret = xmlParseBalancedChunkMemoryInternal(ctxt,
-				   ent->content, user_data, NULL);
-		ctxt->depth--;
-	    } else if (ent->etype ==
-		       XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
-		ctxt->depth++;
-		ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
-			   ctxt->sax, user_data, ctxt->depth,
-			   ent->URI, ent->ExternalID, NULL);
-		ctxt->depth--;
-	    } else {
-		ret = XML_ERR_ENTITY_PE_INTERNAL;
-		xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
-			     "invalid entity type found\n", NULL);
-	    }
-	    if (ret == XML_ERR_ENTITY_LOOP) {
-		xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
-		return;
-	    }
-	}
-	if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
-	    (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
-	    /*
-	     * Entity reference callback comes second, it's somewhat
-	     * superfluous but a compatibility to historical behaviour
-	     */
-	    ctxt->sax->reference(ctxt->userData, ent->name);
-	}
-	return;
-    }
+    if (xmlParserEntityCheck(ctxt, ent->expandedSize))
+        return;
 
-    /*
-     * If we didn't get any children for the entity being built
-     */
-    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
-	(ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
+    if ((ctxt->sax == NULL) || (ctxt->disableSAX))
+        return;
+
+    if (ctxt->replaceEntities == 0) {
 	/*
-	 * Create a node.
+	 * Create a reference
 	 */
-	ctxt->sax->reference(ctxt->userData, ent->name);
-	return;
-    }
+        if (ctxt->sax->reference != NULL)
+	    ctxt->sax->reference(ctxt->userData, ent->name);
+    } else if ((ent->children != NULL) && (ctxt->node != NULL)) {
+        xmlNodePtr copy, cur;
 
-    if ((ctxt->replaceEntities) || (ent->children == NULL))  {
-	/*
-	 * There is a problem on the handling of _private for entities
-	 * (bug 155816): Should we copy the content of the field from
-	 * the entity (possibly overwriting some value set by the user
-	 * when a copy is created), should we leave it alone, or should
-	 * we try to take care of different situations?  The problem
-	 * is exacerbated by the usage of this field by the xmlReader.
-	 * To fix this bug, we look at _private on the created node
-	 * and, if it's NULL, we copy in whatever was in the entity.
-	 * If it's not NULL we leave it alone.  This is somewhat of a
-	 * hack - maybe we should have further tests to determine
-	 * what to do.
+        /*
+         * Seems we are generating the DOM content, copy the tree
 	 */
-	if ((ctxt->node != NULL) && (ent->children != NULL)) {
-	    /*
-	     * Seems we are generating the DOM content, do
-	     * a simple tree copy for all references except the first
-	     * In the first occurrence list contains the replacement.
-	     */
-	    if (((list == NULL) && (ent->owner == 0)) ||
-		(ctxt->parseMode == XML_PARSE_READER)) {
-		xmlNodePtr nw = NULL, cur, firstChild = NULL;
+        cur = ent->children;
 
-		/*
-		 * We are copying here, make sure there is no abuse
-		 */
-		ctxt->sizeentcopy += ent->length + 5;
-		if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
-		    return;
+        /*
+         * Handle first text node with SAX to coalesce text efficiently
+         */
+        if ((cur->type == XML_TEXT_NODE) ||
+            (cur->type == XML_CDATA_SECTION_NODE)) {
+            int len = xmlStrlen(cur->content);
+
+            if ((cur->type == XML_TEXT_NODE) ||
+                (ctxt->sax->cdataBlock == NULL)) {
+                if (ctxt->sax->characters != NULL)
+                    ctxt->sax->characters(ctxt, cur->content, len);
+            } else {
+                if (ctxt->sax->cdataBlock != NULL)
+                    ctxt->sax->cdataBlock(ctxt, cur->content, len);
+            }
 
-		/*
-		 * when operating on a reader, the entities definitions
-		 * are always owning the entities subtree.
-		if (ctxt->parseMode == XML_PARSE_READER)
-		    ent->owner = 1;
-		 */
+            cur = cur->next;
+        }
 
-		cur = ent->children;
-		while (cur != NULL) {
-		    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
-		    if (nw != NULL) {
-			if (nw->_private == NULL)
-			    nw->_private = cur->_private;
-			if (firstChild == NULL){
-			    firstChild = nw;
-			}
-			nw = xmlAddChild(ctxt->node, nw);
-		    }
-		    if (cur == ent->last) {
-			/*
-			 * needed to detect some strange empty
-			 * node cases in the reader tests
-			 */
-			if ((ctxt->parseMode == XML_PARSE_READER) &&
-			    (nw != NULL) &&
-			    (nw->type == XML_ELEMENT_NODE) &&
-			    (nw->children == NULL))
-			    nw->extra = 1;
+        while (cur != NULL) {
+            xmlNodePtr last;
 
-			break;
-		    }
-		    cur = cur->next;
-		}
-#ifdef LIBXML_LEGACY_ENABLED
-		if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
-		  xmlAddEntityReference(ent, firstChild, nw);
-#endif /* LIBXML_LEGACY_ENABLED */
-	    } else if ((list == NULL) || (ctxt->inputNr > 0)) {
-		xmlNodePtr nw = NULL, cur, next, last,
-			   firstChild = NULL;
+            /*
+             * Handle last text node with SAX to coalesce text efficiently
+             */
+            if ((cur->next == NULL) &&
+                ((cur->type == XML_TEXT_NODE) ||
+                 (cur->type == XML_CDATA_SECTION_NODE))) {
+                int len = xmlStrlen(cur->content);
+
+                if ((cur->type == XML_TEXT_NODE) ||
+                    (ctxt->sax->cdataBlock == NULL)) {
+                    if (ctxt->sax->characters != NULL)
+                        ctxt->sax->characters(ctxt, cur->content, len);
+                } else {
+                    if (ctxt->sax->cdataBlock != NULL)
+                        ctxt->sax->cdataBlock(ctxt, cur->content, len);
+                }
 
-		/*
-		 * We are copying here, make sure there is no abuse
-		 */
-		ctxt->sizeentcopy += ent->length + 5;
-		if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
-		    return;
+                break;
+            }
 
-		/*
-		 * Copy the entity child list and make it the new
-		 * entity child list. The goal is to make sure any
-		 * ID or REF referenced will be the one from the
-		 * document content and not the entity copy.
-		 */
-		cur = ent->children;
-		ent->children = NULL;
-		last = ent->last;
-		ent->last = NULL;
-		while (cur != NULL) {
-		    next = cur->next;
-		    cur->next = NULL;
-		    cur->parent = NULL;
-		    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
-		    if (nw != NULL) {
-			if (nw->_private == NULL)
-			    nw->_private = cur->_private;
-			if (firstChild == NULL){
-			    firstChild = cur;
-			}
-			xmlAddChild((xmlNodePtr) ent, nw);
-			xmlAddChild(ctxt->node, cur);
-		    }
-		    if (cur == last)
-			break;
-		    cur = next;
-		}
-		if (ent->owner == 0)
-		    ent->owner = 1;
-#ifdef LIBXML_LEGACY_ENABLED
-		if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
-		  xmlAddEntityReference(ent, firstChild, nw);
-#endif /* LIBXML_LEGACY_ENABLED */
-	    } else {
-		const xmlChar *nbktext;
+            /*
+             * Reset coalesce buffer stats only for non-text nodes.
+             */
+            ctxt->nodemem = 0;
+            ctxt->nodelen = 0;
 
-		/*
-		 * the name change is to avoid coalescing of the
-		 * node with a possible previous text one which
-		 * would make ent->children a dangling pointer
-		 */
-		nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
-					-1);
-		if (ent->children->type == XML_TEXT_NODE)
-		    ent->children->name = nbktext;
-		if ((ent->last != ent->children) &&
-		    (ent->last->type == XML_TEXT_NODE))
-		    ent->last->name = nbktext;
-		xmlAddChildList(ctxt->node, ent->children);
-	    }
+            copy = xmlDocCopyNode(cur, ctxt->myDoc, 1);
 
-	    /*
-	     * This is to avoid a nasty side effect, see
-	     * characters() in SAX.c
-	     */
-	    ctxt->nodemem = 0;
-	    ctxt->nodelen = 0;
-	    return;
-	}
-    }
-}
+            if (copy == NULL) {
+                xmlErrMemory(ctxt);
+                break;
+            }
 
-/**
- * xmlParseEntityRef:
- * @ctxt:  an XML parser context
- *
- * parse ENTITY references declarations
- *
- * [68] EntityRef ::= '&' Name ';'
- *
- * [ WFC: Entity Declared ]
- * In a document without any DTD, a document with only an internal DTD
- * subset which contains no parameter entity references, or a document
- * with "standalone='yes'", the Name given in the entity reference
- * must match that in an entity declaration, except that well-formed
- * documents need not declare any of the following entities: amp, lt,
- * gt, apos, quot.  The declaration of a parameter entity must precede
- * any reference to it.  Similarly, the declaration of a general entity
- * must precede any reference to it which appears in a default value in an
- * attribute-list declaration. Note that if entities are declared in the
- * external subset or in external parameter entities, a non-validating
- * processor is not obligated to read and process their declarations;
- * for such documents, the rule that an entity must be declared is a
- * well-formedness constraint only if standalone='yes'.
- *
- * [ WFC: Parsed Entity ]
- * An entity reference must not contain the name of an unparsed entity
- *
- * Returns the xmlEntityPtr if found, or NULL otherwise.
- */
-xmlEntityPtr
-xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
-    const xmlChar *name;
-    xmlEntityPtr ent = NULL;
+            if (ctxt->parseMode == XML_PARSE_READER) {
+                /* Needed for reader */
+                copy->extra = cur->extra;
+                /* Maybe needed for reader */
+                copy->_private = cur->_private;
+            }
 
-    GROW;
-    if (ctxt->instate == XML_PARSER_EOF)
-        return(NULL);
+            copy->parent = ctxt->node;
+            last = ctxt->node->last;
+            if (last == NULL) {
+                ctxt->node->children = copy;
+            } else {
+                last->next = copy;
+                copy->prev = last;
+            }
+            ctxt->node->last = copy;
 
-    if (RAW != '&')
-        return(NULL);
-    NEXT;
-    name = xmlParseName(ctxt);
-    if (name == NULL) {
-	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
-		       "xmlParseEntityRef: no name\n");
-        return(NULL);
+            cur = cur->next;
+        }
     }
-    if (RAW != ';') {
-	xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
-	return(NULL);
+}
+
+static void
+xmlHandleUndeclaredEntity(xmlParserCtxtPtr ctxt, const xmlChar *name) {
+    /*
+     * [ WFC: Entity Declared ]
+     * In a document without any DTD, a document with only an
+     * internal DTD subset which contains no parameter entity
+     * references, or a document with "standalone='yes'", the
+     * Name given in the entity reference must match that in an
+     * entity declaration, except that well-formed documents
+     * need not declare any of the following entities: amp, lt,
+     * gt, apos, quot.
+     * The declaration of a parameter entity must precede any
+     * reference to it.
+     * Similarly, the declaration of a general entity must
+     * precede any reference to it which appears in a default
+     * value in an attribute-list declaration. Note that if
+     * entities are declared in the external subset or in
+     * external parameter entities, a non-validating processor
+     * is not obligated to read and process their declarations;
+     * for such documents, the rule that an entity must be
+     * declared is a well-formedness constraint only if
+     * standalone='yes'.
+     */
+    if ((ctxt->standalone == 1) ||
+        ((ctxt->hasExternalSubset == 0) &&
+         (ctxt->hasPErefs == 0))) {
+        xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
+                          "Entity '%s' not defined\n", name);
+    } else if (ctxt->validate) {
+        /*
+         * [ VC: Entity Declared ]
+         * In a document with an external subset or external
+         * parameter entities with "standalone='no'", ...
+         * ... The declaration of a parameter entity must
+         * precede any reference to it...
+         */
+        xmlValidityError(ctxt, XML_ERR_UNDECLARED_ENTITY,
+                         "Entity '%s' not defined\n", name, NULL);
+    } else if ((ctxt->loadsubset) ||
+               ((ctxt->replaceEntities) &&
+                ((ctxt->options & XML_PARSE_NO_XXE) == 0))) {
+        /*
+         * Also raise a non-fatal error
+         *
+         * - if the external subset is loaded and all entity declarations
+         *   should be available, or
+         * - entity substition was requested without restricting
+         *   external entity access.
+         */
+        xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
+                     "Entity '%s' not defined\n", name);
+    } else {
+        xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
+                      "Entity '%s' not defined\n", name, NULL);
     }
-    NEXT;
+
+    ctxt->valid = 0;
+}
+
+static xmlEntityPtr
+xmlLookupGeneralEntity(xmlParserCtxtPtr ctxt, const xmlChar *name, int inAttr) {
+    xmlEntityPtr ent;
 
     /*
      * Predefined entities override any extra definition
@@ -7550,11 +7623,6 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
             return(ent);
     }
 
-    /*
-     * Increase the number of entity references parsed
-     */
-    ctxt->nbentities++;
-
     /*
      * Ask first SAX for entity resolution, otherwise try the
      * entities which may have stored in the parser context.
@@ -7570,46 +7638,9 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
 	    ent = xmlSAX2GetEntity(ctxt, name);
 	}
     }
-    if (ctxt->instate == XML_PARSER_EOF)
-	return(NULL);
-    /*
-     * [ WFC: Entity Declared ]
-     * In a document without any DTD, a document with only an
-     * internal DTD subset which contains no parameter entity
-     * references, or a document with "standalone='yes'", the
-     * Name given in the entity reference must match that in an
-     * entity declaration, except that well-formed documents
-     * need not declare any of the following entities: amp, lt,
-     * gt, apos, quot.
-     * The declaration of a parameter entity must precede any
-     * reference to it.
-     * Similarly, the declaration of a general entity must
-     * precede any reference to it which appears in a default
-     * value in an attribute-list declaration. Note that if
-     * entities are declared in the external subset or in
-     * external parameter entities, a non-validating processor
-     * is not obligated to read and process their declarations;
-     * for such documents, the rule that an entity must be
-     * declared is a well-formedness constraint only if
-     * standalone='yes'.
-     */
+
     if (ent == NULL) {
-	if ((ctxt->standalone == 1) ||
-	    ((ctxt->hasExternalSubset == 0) &&
-	     (ctxt->hasPErefs == 0))) {
-	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
-		     "Entity '%s' not defined\n", name);
-	} else {
-	    xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
-		     "Entity '%s' not defined\n", name);
-	    if ((ctxt->inSubset == 0) &&
-		(ctxt->sax != NULL) &&
-		(ctxt->sax->reference != NULL)) {
-		ctxt->sax->reference(ctxt->userData, name);
-	    }
-	}
-	xmlParserEntityCheck(ctxt, 0, ent, 0);
-	ctxt->valid = 0;
+        xmlHandleUndeclaredEntity(ctxt, name);
     }
 
     /*
@@ -7620,6 +7651,7 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
     else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
 	xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
 		 "Entity reference to unparsed entity %s\n", name);
+        ent = NULL;
     }
 
     /*
@@ -7627,50 +7659,72 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
      * Attribute values cannot contain direct or indirect
      * entity references to external entities.
      */
-    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
-	     (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
-	xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
-	     "Attribute references external entity '%s'\n", name);
-    }
-    /*
-     * [ WFC: No < in Attribute Values ]
-     * The replacement text of any entity referred to directly or
-     * indirectly in an attribute value (other than "&lt;") must
-     * not contain a <.
-     */
-    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
-	     (ent != NULL) && 
-	     (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
-	if (((ent->checked & 1) || (ent->checked == 0)) &&
-	     (ent->content != NULL) && (xmlStrchr(ent->content, '<'))) {
-	    xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
-	"'<' in entity '%s' is not allowed in attributes values\n", name);
+    else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
+        if (inAttr) {
+            xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
+                 "Attribute references external entity '%s'\n", name);
+            ent = NULL;
         }
     }
 
-    /*
-     * Internal check, no parameter entities here ...
-     */
-    else {
-	switch (ent->etype) {
-	    case XML_INTERNAL_PARAMETER_ENTITY:
-	    case XML_EXTERNAL_PARAMETER_ENTITY:
-	    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
-	     "Attempt to reference the parameter entity '%s'\n",
-			      name);
-	    break;
-	    default:
-	    break;
-	}
+    return(ent);
+}
+
+/**
+ * xmlParseEntityRefInternal:
+ * @ctxt:  an XML parser context
+ * @inAttr:  whether we are in an attribute value
+ *
+ * Parse an entity reference. Always consumes '&'.
+ *
+ * [68] EntityRef ::= '&' Name ';'
+ *
+ * Returns the name, or NULL in case of error.
+ */
+static const xmlChar *
+xmlParseEntityRefInternal(xmlParserCtxtPtr ctxt) {
+    const xmlChar *name;
+
+    GROW;
+
+    if (RAW != '&')
+        return(NULL);
+    NEXT;
+    name = xmlParseName(ctxt);
+    if (name == NULL) {
+	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+		       "xmlParseEntityRef: no name\n");
+        return(NULL);
+    }
+    if (RAW != ';') {
+	xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
+	return(NULL);
     }
+    NEXT;
 
-    /*
-     * [ WFC: No Recursion ]
-     * A parsed entity must not contain a recursive reference
-     * to itself, either directly or indirectly.
-     * Done somewhere else
-     */
-    return(ent);
+    return(name);
+}
+
+/**
+ * xmlParseEntityRef:
+ * @ctxt:  an XML parser context
+ *
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Returns the xmlEntityPtr if found, or NULL otherwise.
+ */
+xmlEntityPtr
+xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
+    const xmlChar *name;
+
+    if (ctxt == NULL)
+        return(NULL);
+
+    name = xmlParseEntityRefInternal(ctxt);
+    if (name == NULL)
+        return(NULL);
+
+    return(xmlLookupGeneralEntity(ctxt, name, /* inAttr */ 0));
 }
 
 /**
@@ -7704,12 +7758,11 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
  * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
  * is updated to the current location in the string.
  */
-static xmlEntityPtr
+static xmlChar *
 xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
     xmlChar *name;
     const xmlChar *ptr;
     xmlChar cur;
-    xmlEntityPtr ent = NULL;
 
     if ((str == NULL) || (*str == NULL))
         return(NULL);
@@ -7734,146 +7787,18 @@ xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
     }
     ptr++;
 
-
-    /*
-     * Predefined entities override any extra definition
-     */
-    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
-        ent = xmlGetPredefinedEntity(name);
-        if (ent != NULL) {
-            xmlFree(name);
-            *str = ptr;
-            return(ent);
-        }
-    }
-
-    /*
-     * Increase the number of entity references parsed
-     */
-    ctxt->nbentities++;
-
-    /*
-     * Ask first SAX for entity resolution, otherwise try the
-     * entities which may have stored in the parser context.
-     */
-    if (ctxt->sax != NULL) {
-	if (ctxt->sax->getEntity != NULL)
-	    ent = ctxt->sax->getEntity(ctxt->userData, name);
-	if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
-	    ent = xmlGetPredefinedEntity(name);
-	if ((ent == NULL) && (ctxt->userData==ctxt)) {
-	    ent = xmlSAX2GetEntity(ctxt, name);
-	}
-    }
-    if (ctxt->instate == XML_PARSER_EOF) {
-	xmlFree(name);
-	return(NULL);
-    }
-
-    /*
-     * [ WFC: Entity Declared ]
-     * In a document without any DTD, a document with only an
-     * internal DTD subset which contains no parameter entity
-     * references, or a document with "standalone='yes'", the
-     * Name given in the entity reference must match that in an
-     * entity declaration, except that well-formed documents
-     * need not declare any of the following entities: amp, lt,
-     * gt, apos, quot.
-     * The declaration of a parameter entity must precede any
-     * reference to it.
-     * Similarly, the declaration of a general entity must
-     * precede any reference to it which appears in a default
-     * value in an attribute-list declaration. Note that if
-     * entities are declared in the external subset or in
-     * external parameter entities, a non-validating processor
-     * is not obligated to read and process their declarations;
-     * for such documents, the rule that an entity must be
-     * declared is a well-formedness constraint only if
-     * standalone='yes'.
-     */
-    if (ent == NULL) {
-	if ((ctxt->standalone == 1) ||
-	    ((ctxt->hasExternalSubset == 0) &&
-	     (ctxt->hasPErefs == 0))) {
-	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
-		     "Entity '%s' not defined\n", name);
-	} else {
-	    xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
-			  "Entity '%s' not defined\n",
-			  name);
-	}
-	xmlParserEntityCheck(ctxt, 0, ent, 0);
-	/* TODO ? check regressions ctxt->valid = 0; */
-    }
-
-    /*
-     * [ WFC: Parsed Entity ]
-     * An entity reference must not contain the name of an
-     * unparsed entity
-     */
-    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
-	xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
-		 "Entity reference to unparsed entity %s\n", name);
-    }
-
-    /*
-     * [ WFC: No External Entity References ]
-     * Attribute values cannot contain direct or indirect
-     * entity references to external entities.
-     */
-    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
-	     (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
-	xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
-	 "Attribute references external entity '%s'\n", name);
-    }
-    /*
-     * [ WFC: No < in Attribute Values ]
-     * The replacement text of any entity referred to directly or
-     * indirectly in an attribute value (other than "&lt;") must
-     * not contain a <.
-     */
-    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
-	     (ent != NULL) && (ent->content != NULL) &&
-	     (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
-	     (xmlStrchr(ent->content, '<'))) {
-	xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
-     "'<' in entity '%s' is not allowed in attributes values\n",
-			  name);
-    }
-
-    /*
-     * Internal check, no parameter entities here ...
-     */
-    else {
-	switch (ent->etype) {
-	    case XML_INTERNAL_PARAMETER_ENTITY:
-	    case XML_EXTERNAL_PARAMETER_ENTITY:
-		xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
-	     "Attempt to reference the parameter entity '%s'\n",
-				  name);
-	    break;
-	    default:
-	    break;
-	}
-    }
-
-    /*
-     * [ WFC: No Recursion ]
-     * A parsed entity must not contain a recursive reference
-     * to itself, either directly or indirectly.
-     * Done somewhere else
-     */
-
-    xmlFree(name);
     *str = ptr;
-    return(ent);
+    return(name);
 }
 
 /**
  * xmlParsePEReference:
  * @ctxt:  an XML parser context
  *
- * parse PEReference declarations
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Parse a parameter entity reference. Always consumes '%'.
+ *
  * The entity content is handled directly by pushing it's content as
  * a new input stream.
  *
@@ -7913,9 +7838,6 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
 	xmlFatalErrMsg(ctxt, XML_ERR_PEREF_NO_NAME, "PEReference: no name\n");
 	return;
     }
-    if (xmlParserDebugEntities)
-	xmlGenericError(xmlGenericErrorContext,
-		"PEReference: %s\n", name);
     if (RAW != ';') {
 	xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
         return;
@@ -7923,10 +7845,8 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
 
     NEXT;
 
-    /*
-     * Increase the number of entity references parsed
-     */
-    ctxt->nbentities++;
+    /* Must be set before xmlHandleUndeclaredEntity */
+    ctxt->hasPErefs = 1;
 
     /*
      * Request the entity from SAX
@@ -7934,42 +7854,9 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
     if ((ctxt->sax != NULL) &&
 	(ctxt->sax->getParameterEntity != NULL))
 	entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
-    if (ctxt->instate == XML_PARSER_EOF)
-	return;
+
     if (entity == NULL) {
-	/*
-	 * [ WFC: Entity Declared ]
-	 * In a document without any DTD, a document with only an
-	 * internal DTD subset which contains no parameter entity
-	 * references, or a document with "standalone='yes'", ...
-	 * ... The declaration of a parameter entity must precede
-	 * any reference to it...
-	 */
-	if ((ctxt->standalone == 1) ||
-	    ((ctxt->hasExternalSubset == 0) &&
-	     (ctxt->hasPErefs == 0))) {
-	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
-			      "PEReference: %%%s; not found\n",
-			      name);
-	} else {
-	    /*
-	     * [ VC: Entity Declared ]
-	     * In a document with an external subset or external
-	     * parameter entities with "standalone='no'", ...
-	     * ... The declaration of a parameter entity must
-	     * precede any reference to it...
-	     */
-            if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
-                xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
-                                 "PEReference: %%%s; not found\n",
-                                 name, NULL);
-            } else
-                xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
-                              "PEReference: %%%s; not found\n",
-                              name, NULL);
-            ctxt->valid = 0;
-	}
-	xmlParserEntityCheck(ctxt, 0, NULL, 0);
+        xmlHandleUndeclaredEntity(ctxt, name);
     } else {
 	/*
 	 * Internal checking in case the entity quest barfed
@@ -7980,50 +7867,29 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
 		  "Internal: %%%s; is not a parameter entity\n",
 			  name, NULL);
 	} else {
-            xmlChar start[4];
-            xmlCharEncoding enc;
-
-	    if (xmlParserEntityCheck(ctxt, 0, entity, 0))
-	        return;
-
 	    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
-	        ((ctxt->options & XML_PARSE_NOENT) == 0) &&
-		((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
-		((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
-		((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
-		(ctxt->replaceEntities == 0) &&
-		(ctxt->validate == 0))
+                ((ctxt->options & XML_PARSE_NO_XXE) ||
+		 ((ctxt->loadsubset == 0) &&
+		  (ctxt->replaceEntities == 0) &&
+		  (ctxt->validate == 0))))
 		return;
 
+            if (entity->flags & XML_ENT_EXPANDING) {
+                xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+                xmlHaltParser(ctxt);
+                return;
+            }
+
 	    input = xmlNewEntityInputStream(ctxt, entity);
 	    if (xmlPushInput(ctxt, input) < 0) {
                 xmlFreeInputStream(input);
 		return;
             }
 
+            entity->flags |= XML_ENT_EXPANDING;
+
 	    if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
-                /*
-                 * Get the 4 first bytes and decode the charset
-                 * if enc != XML_CHAR_ENCODING_NONE
-                 * plug some encoding conversion routines.
-                 * Note that, since we may have some non-UTF8
-                 * encoding (like UTF16, bug 135229), the 'length'
-                 * is not known, but we can calculate based upon
-                 * the amount of data in the buffer.
-                 */
-                GROW
-                if (ctxt->instate == XML_PARSER_EOF)
-                    return;
-                if ((ctxt->input->end - ctxt->input->cur)>=4) {
-                    start[0] = RAW;
-                    start[1] = NXT(1);
-                    start[2] = NXT(2);
-                    start[3] = NXT(3);
-                    enc = xmlDetectCharEncoding(start, 4);
-                    if (enc != XML_CHAR_ENCODING_NONE) {
-                        xmlSwitchEncoding(ctxt, enc);
-                    }
-                }
+                xmlDetectEncoding(ctxt);
 
                 if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
                     (IS_BLANK_CH(NXT(5)))) {
@@ -8032,7 +7898,6 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
             }
 	}
     }
-    ctxt->hasPErefs = 1;
 }
 
 /**
@@ -8048,90 +7913,123 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
  */
 static int
 xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
-    xmlParserInputPtr input;
-    xmlBufferPtr buf;
-    int l, c;
-    int count = 0;
+    xmlParserInputPtr oldinput, input = NULL;
+    xmlParserInputPtr *oldinputTab;
+    const xmlChar *oldencoding;
+    xmlChar *content = NULL;
+    size_t length, i;
+    int oldinputNr, oldinputMax;
+    int ret = -1;
+    int res;
 
     if ((ctxt == NULL) || (entity == NULL) ||
         ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
 	 (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
 	(entity->content != NULL)) {
-	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+	xmlFatalErr(ctxt, XML_ERR_ARGUMENT,
 	            "xmlLoadEntityContent parameter error");
         return(-1);
     }
 
-    if (xmlParserDebugEntities)
-	xmlGenericError(xmlGenericErrorContext,
-		"Reading %s entity content input\n", entity->name);
-
-    buf = xmlBufferCreate();
-    if (buf == NULL) {
-	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-	            "xmlLoadEntityContent parameter error");
+    input = xmlLoadExternalEntity((char *) entity->URI,
+           (char *) entity->ExternalID, ctxt);
+    if (input == NULL)
         return(-1);
-    }
-    xmlBufferSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
 
-    input = xmlNewEntityInputStream(ctxt, entity);
-    if (input == NULL) {
-	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-	            "xmlLoadEntityContent input error");
-	xmlBufferFree(buf);
-        return(-1);
+    oldinput = ctxt->input;
+    oldinputNr = ctxt->inputNr;
+    oldinputMax = ctxt->inputMax;
+    oldinputTab = ctxt->inputTab;
+    oldencoding = ctxt->encoding;
+
+    ctxt->input = NULL;
+    ctxt->inputNr = 0;
+    ctxt->inputMax = 1;
+    ctxt->encoding = NULL;
+    ctxt->inputTab = xmlMalloc(sizeof(xmlParserInputPtr));
+    if (ctxt->inputTab == NULL) {
+        xmlErrMemory(ctxt);
+        xmlFreeInputStream(input);
+        goto error;
     }
 
+    xmlBufResetInput(input->buf->buffer, input);
+
+    inputPush(ctxt, input);
+
+    xmlDetectEncoding(ctxt);
+
     /*
-     * Push the entity as the current input, read char by char
-     * saving to the buffer until the end of the entity or an error
+     * Parse a possible text declaration first
      */
-    if (xmlPushInput(ctxt, input) < 0) {
-        xmlBufferFree(buf);
-	xmlFreeInputStream(input);
-	return(-1);
+    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
+	xmlParseTextDecl(ctxt);
+        /*
+         * An XML-1.0 document can't reference an entity not XML-1.0
+         */
+        if ((xmlStrEqual(ctxt->version, BAD_CAST "1.0")) &&
+            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
+            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
+                           "Version mismatch between document and entity\n");
+        }
     }
 
-    GROW;
-    c = CUR_CHAR(l);
-    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
-           (IS_CHAR(c))) {
-        xmlBufferAdd(buf, ctxt->input->cur, l);
-	if (count++ > XML_PARSER_CHUNK_SIZE) {
-	    count = 0;
-	    GROW;
-            if (ctxt->instate == XML_PARSER_EOF) {
-                xmlBufferFree(buf);
-                return(-1);
-            }
-	}
-	NEXTL(l);
-	c = CUR_CHAR(l);
-	if (c == 0) {
-	    count = 0;
-	    GROW;
-            if (ctxt->instate == XML_PARSER_EOF) {
-                xmlBufferFree(buf);
-                return(-1);
-            }
-	    c = CUR_CHAR(l);
-	}
+    length = input->cur - input->base;
+    xmlBufShrink(input->buf->buffer, length);
+    xmlSaturatedAdd(&ctxt->sizeentities, length);
+
+    while ((res = xmlParserInputBufferGrow(input->buf, 4096)) > 0)
+        ;
+
+    xmlBufResetInput(input->buf->buffer, input);
+
+    if (res < 0) {
+        xmlCtxtErrIO(ctxt, input->buf->error, NULL);
+        goto error;
     }
 
-    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
-        xmlPopInput(ctxt);
-    } else if (!IS_CHAR(c)) {
-        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
-                          "xmlLoadEntityContent: invalid char value %d\n",
-	                  c);
-	xmlBufferFree(buf);
-	return(-1);
+    length = xmlBufUse(input->buf->buffer);
+    content = xmlBufDetach(input->buf->buffer);
+
+    if (length > INT_MAX) {
+        xmlErrMemory(ctxt);
+        goto error;
     }
-    entity->content = buf->content;
-    buf->content = NULL;
-    xmlBufferFree(buf);
 
-    return(0);
+    for (i = 0; i < length; ) {
+        int clen = length - i;
+        int c = xmlGetUTF8Char(content + i, &clen);
+
+        if ((c < 0) || (!IS_CHAR(c))) {
+            xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
+                              "xmlLoadEntityContent: invalid char value %d\n",
+                              content[i]);
+            goto error;
+        }
+        i += clen;
+    }
+
+    xmlSaturatedAdd(&ctxt->sizeentities, length);
+    entity->content = content;
+    entity->length = length;
+    content = NULL;
+    ret = 0;
+
+error:
+    while (ctxt->inputNr > 0)
+        xmlFreeInputStream(inputPop(ctxt));
+    xmlFree(ctxt->inputTab);
+    xmlFree((xmlChar *) ctxt->encoding);
+
+    ctxt->input = oldinput;
+    ctxt->inputNr = oldinputNr;
+    ctxt->inputMax = oldinputMax;
+    ctxt->inputTab = oldinputTab;
+    ctxt->encoding = oldencoding;
+
+    xmlFree(content);
+
+    return(ret);
 }
 
 /**
@@ -8194,10 +8092,8 @@ xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
     }
     ptr++;
 
-    /*
-     * Increase the number of entity references parsed
-     */
-    ctxt->nbentities++;
+    /* Must be set before xmlHandleUndeclaredEntity */
+    ctxt->hasPErefs = 1;
 
     /*
      * Request the entity from SAX
@@ -8205,38 +8101,9 @@ xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
     if ((ctxt->sax != NULL) &&
 	(ctxt->sax->getParameterEntity != NULL))
 	entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
-    if (ctxt->instate == XML_PARSER_EOF) {
-	xmlFree(name);
-	*str = ptr;
-	return(NULL);
-    }
+
     if (entity == NULL) {
-	/*
-	 * [ WFC: Entity Declared ]
-	 * In a document without any DTD, a document with only an
-	 * internal DTD subset which contains no parameter entity
-	 * references, or a document with "standalone='yes'", ...
-	 * ... The declaration of a parameter entity must precede
-	 * any reference to it...
-	 */
-	if ((ctxt->standalone == 1) ||
-	    ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
-	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
-		 "PEReference: %%%s; not found\n", name);
-	} else {
-	    /*
-	     * [ VC: Entity Declared ]
-	     * In a document with an external subset or external
-	     * parameter entities with "standalone='no'", ...
-	     * ... The declaration of a parameter entity must
-	     * precede any reference to it...
-	     */
-	    xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
-			  "PEReference: %%%s; not found\n",
-			  name, NULL);
-	    ctxt->valid = 0;
-	}
-	xmlParserEntityCheck(ctxt, 0, NULL, 0);
+        xmlHandleUndeclaredEntity(ctxt, name);
     } else {
 	/*
 	 * Internal checking in case the entity quest barfed
@@ -8248,7 +8115,7 @@ xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
 			  name, NULL);
 	}
     }
-    ctxt->hasPErefs = 1;
+
     xmlFree(name);
     *str = ptr;
     return(entity);
@@ -8258,6 +8125,8 @@ xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
  * xmlParseDocTypeDecl:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse a DOCTYPE declaration
  *
  * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
@@ -8312,8 +8181,6 @@ xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
     if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
 	(!ctxt->disableSAX))
 	ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
-    if (ctxt->instate == XML_PARSER_EOF)
-	return;
 
     /*
      * Is there any internal subset declarations ?
@@ -8346,41 +8213,41 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
      * Is there any DTD definition ?
      */
     if (RAW == '[') {
-        int baseInputNr = ctxt->inputNr;
-        ctxt->instate = XML_PARSER_DTD;
+        int oldInputNr = ctxt->inputNr;
+
         NEXT;
 	/*
 	 * Parse the succession of Markup declarations and
 	 * PEReferences.
 	 * Subsequence (markupdecl | PEReference | S)*
 	 */
-	while (((RAW != ']') || (ctxt->inputNr > baseInputNr)) &&
-               (ctxt->instate != XML_PARSER_EOF)) {
-	    int id = ctxt->input->id;
-	    unsigned long cons = CUR_CONSUMED;
-
-	    SKIP_BLANKS;
-	    xmlParseMarkupDecl(ctxt);
-	    xmlParsePEReference(ctxt);
+	SKIP_BLANKS;
+	while (((RAW != ']') || (ctxt->inputNr > oldInputNr)) &&
+               (PARSER_STOPPED(ctxt) == 0)) {
 
             /*
              * Conditional sections are allowed from external entities included
              * by PE References in the internal subset.
              */
-            if ((ctxt->inputNr > 1) && (ctxt->input->filename != NULL) &&
+            if ((PARSER_EXTERNAL(ctxt)) &&
                 (RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
                 xmlParseConditionalSections(ctxt);
+            } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
+	        xmlParseMarkupDecl(ctxt);
+            } else if (RAW == '%') {
+	        xmlParsePEReference(ctxt);
+            } else {
+		xmlFatalErr(ctxt, XML_ERR_INT_SUBSET_NOT_FINISHED, NULL);
+                break;
             }
-
-	    if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
-		xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-	     "xmlParseInternalSubset: error detected in Markup declaration\n");
-                if (ctxt->inputNr > baseInputNr)
-                    xmlPopInput(ctxt);
-                else
-		    break;
-	    }
+	    SKIP_BLANKS_PE;
+            SHRINK;
+            GROW;
 	}
+
+        while (ctxt->inputNr > oldInputNr)
+            xmlPopPE(ctxt);
+
 	if (RAW == ']') {
 	    NEXT;
 	    SKIP_BLANKS;
@@ -8390,7 +8257,7 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
     /*
      * We should be at the end of the DOCTYPE declaration.
      */
-    if (RAW != '>') {
+    if ((ctxt->wellFormed) && (RAW != '>')) {
 	xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
 	return;
     }
@@ -8403,6 +8270,8 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
  * @ctxt:  an XML parser context
  * @value:  a xmlChar ** used to store the value of the attribute
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an attribute
  *
  * [41] Attribute ::= Name Eq AttValue
@@ -8453,11 +8322,10 @@ xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
         NEXT;
 	SKIP_BLANKS;
 	val = xmlParseAttValue(ctxt);
-	ctxt->instate = XML_PARSER_CONTENT;
     } else {
 	xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
 	       "Specification mandates value for attribute %s\n", name);
-	return(NULL);
+	return(name);
     }
 
     /*
@@ -8496,8 +8364,9 @@ xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
  * xmlParseStartTag:
  * @ctxt:  an XML parser context
  *
- * parse a start of tag either for rule element or
- * EmptyElement. In both case we don't parse the tag closing chars.
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Parse a start tag. Always consumes '<'.
  *
  * [40] STag ::= '<' Name (S Attribute)* S? '>'
  *
@@ -8550,12 +8419,11 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
 
     while (((RAW != '>') &&
 	   ((RAW != '/') || (NXT(1) != '>')) &&
-	   (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
-        int id = ctxt->input->id;
-	unsigned long cons = CUR_CONSUMED;
-
+	   (IS_BYTE_CHAR(RAW))) && (PARSER_STOPPED(ctxt) == 0)) {
 	attname = xmlParseAttribute(ctxt, &attvalue);
-        if ((attname != NULL) && (attvalue != NULL)) {
+        if (attname == NULL)
+	    break;
+        if (attvalue != NULL) {
 	    /*
 	     * [ WFC: Unique Att Spec ]
 	     * No attribute name may appear more than once in the same
@@ -8576,7 +8444,7 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
 	        atts = (const xmlChar **)
 		       xmlMalloc(maxatts * sizeof(xmlChar *));
 		if (atts == NULL) {
-		    xmlErrMemory(ctxt, NULL);
+		    xmlErrMemory(ctxt);
 		    if (attvalue != NULL)
 			xmlFree(attvalue);
 		    goto failed;
@@ -8590,7 +8458,7 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
 	        n = (const xmlChar **) xmlRealloc((void *) atts,
 					     maxatts * sizeof(const xmlChar *));
 		if (n == NULL) {
-		    xmlErrMemory(ctxt, NULL);
+		    xmlErrMemory(ctxt);
 		    if (attvalue != NULL)
 			xmlFree(attvalue);
 		    goto failed;
@@ -8617,12 +8485,6 @@ failed:
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 			   "attributes construct error\n");
 	}
-        if ((cons == CUR_CONSUMED) && (id == ctxt->input->id) &&
-            (attname == NULL) && (attvalue == NULL)) {
-	    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
-			   "xmlParseStartTag: problem parsing attributes\n");
-	    break;
-	}
 	SHRINK;
         GROW;
     }
@@ -8653,7 +8515,7 @@ failed:
  * @line:  line of the start tag
  * @nsNr:  number of namespaces on the start tag
  *
- * parse an end of tag
+ * Parse an end tag. Always consumes '</'.
  *
  * [42] ETag ::= '</' Name S? '>'
  *
@@ -8715,6 +8577,8 @@ xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
  * xmlParseEndTag:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an end of tag
  *
  * [42] ETag ::= '</' Name S? '>'
@@ -8736,28 +8600,62 @@ xmlParseEndTag(xmlParserCtxtPtr ctxt) {
  *									*
  ************************************************************************/
 
-/*
- * xmlGetNamespace:
+/**
+ * xmlParseQNameHashed:
  * @ctxt:  an XML parser context
- * @prefix:  the prefix to lookup
+ * @prefix:  pointer to store the prefix part
+ *
+ * parse an XML Namespace QName
  *
- * Lookup the namespace name for the @prefix (which ca be NULL)
- * The prefix must come from the @ctxt->dict dictionary
+ * [6]  QName  ::= (Prefix ':')? LocalPart
+ * [7]  Prefix  ::= NCName
+ * [8]  LocalPart  ::= NCName
  *
- * Returns the namespace name or NULL if not bound
+ * Returns the Name parsed or NULL
  */
-static const xmlChar *
-xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
-    int i;
 
-    if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
-    for (i = ctxt->nsNr - 2;i >= 0;i-=2)
-        if (ctxt->nsTab[i] == prefix) {
-	    if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
-	        return(NULL);
-	    return(ctxt->nsTab[i + 1]);
-	}
-    return(NULL);
+static xmlHashedString
+xmlParseQNameHashed(xmlParserCtxtPtr ctxt, xmlHashedString *prefix) {
+    xmlHashedString l, p;
+    int start, isNCName = 0;
+
+    l.name = NULL;
+    p.name = NULL;
+
+    GROW;
+    start = CUR_PTR - BASE_PTR;
+
+    l = xmlParseNCName(ctxt);
+    if (l.name != NULL) {
+        isNCName = 1;
+        if (CUR == ':') {
+            NEXT;
+            p = l;
+            l = xmlParseNCName(ctxt);
+        }
+    }
+    if ((l.name == NULL) || (CUR == ':')) {
+        xmlChar *tmp;
+
+        l.name = NULL;
+        p.name = NULL;
+        if ((isNCName == 0) && (CUR != ':'))
+            return(l);
+        tmp = xmlParseNmtoken(ctxt);
+        if (tmp != NULL)
+            xmlFree(tmp);
+        l = xmlDictLookupHashed(ctxt->dict, BASE_PTR + start,
+                                CUR_PTR - (BASE_PTR + start));
+        if (l.name == NULL) {
+            xmlErrMemory(ctxt);
+            return(l);
+        }
+        xmlNsErr(ctxt, XML_NS_ERR_QNAME,
+                 "Failed to parse QName '%s'\n", l.name, NULL, NULL);
+    }
+
+    *prefix = p;
+    return(l);
 }
 
 /**
@@ -8776,74 +8674,13 @@ xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
 
 static const xmlChar *
 xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
-    const xmlChar *l, *p;
-
-    GROW;
+    xmlHashedString n, p;
 
-    l = xmlParseNCName(ctxt);
-    if (l == NULL) {
-        if (CUR == ':') {
-	    l = xmlParseName(ctxt);
-	    if (l != NULL) {
-	        xmlNsErr(ctxt, XML_NS_ERR_QNAME,
-		         "Failed to parse QName '%s'\n", l, NULL, NULL);
-		*prefix = NULL;
-		return(l);
-	    }
-	}
+    n = xmlParseQNameHashed(ctxt, &p);
+    if (n.name == NULL)
         return(NULL);
-    }
-    if (CUR == ':') {
-        NEXT;
-	p = l;
-	l = xmlParseNCName(ctxt);
-	if (l == NULL) {
-	    xmlChar *tmp;
-
-            if (ctxt->instate == XML_PARSER_EOF)
-                return(NULL);
-            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
-	             "Failed to parse QName '%s:'\n", p, NULL, NULL);
-	    l = xmlParseNmtoken(ctxt);
-	    if (l == NULL) {
-                if (ctxt->instate == XML_PARSER_EOF)
-                    return(NULL);
-		tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
-            } else {
-		tmp = xmlBuildQName(l, p, NULL, 0);
-		xmlFree((char *)l);
-	    }
-	    p = xmlDictLookup(ctxt->dict, tmp, -1);
-	    if (tmp != NULL) xmlFree(tmp);
-	    *prefix = NULL;
-	    return(p);
-	}
-	if (CUR == ':') {
-	    xmlChar *tmp;
-
-            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
-	             "Failed to parse QName '%s:%s:'\n", p, l, NULL);
-	    NEXT;
-	    tmp = (xmlChar *) xmlParseName(ctxt);
-	    if (tmp != NULL) {
-	        tmp = xmlBuildQName(tmp, l, NULL, 0);
-		l = xmlDictLookup(ctxt->dict, tmp, -1);
-		if (tmp != NULL) xmlFree(tmp);
-		*prefix = p;
-		return(l);
-	    }
-            if (ctxt->instate == XML_PARSER_EOF)
-                return(NULL);
-	    tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
-	    l = xmlDictLookup(ctxt->dict, tmp, -1);
-	    if (tmp != NULL) xmlFree(tmp);
-	    *prefix = p;
-	    return(l);
-	}
-	*prefix = p;
-    } else
-        *prefix = NULL;
-    return(l);
+    *prefix = p.name;
+    return(n.name);
 }
 
 /**
@@ -8875,228 +8712,31 @@ xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
     cmp = prefix;
     while (*in != 0 && *in == *cmp) {
 	++in;
-	++cmp;
-    }
-    if ((*cmp == 0) && (*in == ':')) {
-        in++;
-	cmp = name;
-	while (*in != 0 && *in == *cmp) {
-	    ++in;
-	    ++cmp;
-	}
-	if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
-	    /* success */
-            ctxt->input->col += in - ctxt->input->cur;
-	    ctxt->input->cur = in;
-	    return((const xmlChar*) 1);
-	}
-    }
-    /*
-     * all strings coms from the dictionary, equality can be done directly
-     */
-    ret = xmlParseQName (ctxt, &prefix2);
-    if ((ret == name) && (prefix == prefix2))
-	return((const xmlChar*) 1);
-    return ret;
-}
-
-/**
- * xmlParseAttValueInternal:
- * @ctxt:  an XML parser context
- * @len:  attribute len result
- * @alloc:  whether the attribute was reallocated as a new string
- * @normalize:  if 1 then further non-CDATA normalization must be done
- *
- * parse a value for an attribute.
- * NOTE: if no normalization is needed, the routine will return pointers
- *       directly from the data buffer.
- *
- * 3.3.3 Attribute-Value Normalization:
- * Before the value of an attribute is passed to the application or
- * checked for validity, the XML processor must normalize it as follows:
- * - a character reference is processed by appending the referenced
- *   character to the attribute value
- * - an entity reference is processed by recursively processing the
- *   replacement text of the entity
- * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
- *   appending #x20 to the normalized value, except that only a single
- *   #x20 is appended for a "#xD#xA" sequence that is part of an external
- *   parsed entity or the literal entity value of an internal parsed entity
- * - other characters are processed by appending them to the normalized value
- * If the declared value is not CDATA, then the XML processor must further
- * process the normalized attribute value by discarding any leading and
- * trailing space (#x20) characters, and by replacing sequences of space
- * (#x20) characters by a single space (#x20) character.
- * All attributes for which no declaration has been read should be treated
- * by a non-validating parser as if declared CDATA.
- *
- * Returns the AttValue parsed or NULL. The value has to be freed by the
- *     caller if it was copied, this can be detected by val[*len] == 0.
- */
-
-#define GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) \
-    const xmlChar *oldbase = ctxt->input->base;\
-    GROW;\
-    if (ctxt->instate == XML_PARSER_EOF)\
-        return(NULL);\
-    if (oldbase != ctxt->input->base) {\
-        ptrdiff_t delta = ctxt->input->base - oldbase;\
-        start = start + delta;\
-        in = in + delta;\
-    }\
-    end = ctxt->input->end;
-
-static xmlChar *
-xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
-                         int normalize)
-{
-    xmlChar limit = 0;
-    const xmlChar *in = NULL, *start, *end, *last;
-    xmlChar *ret = NULL;
-    int line, col;
-
-    GROW;
-    in = (xmlChar *) CUR_PTR;
-    line = ctxt->input->line;
-    col = ctxt->input->col;
-    if (*in != '"' && *in != '\'') {
-        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
-        return (NULL);
-    }
-    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
-
-    /*
-     * try to handle in this routine the most common case where no
-     * allocation of a new string is required and where content is
-     * pure ASCII.
-     */
-    limit = *in++;
-    col++;
-    end = ctxt->input->end;
-    start = in;
-    if (in >= end) {
-        GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
-    }
-    if (normalize) {
-        /*
-	 * Skip any leading spaces
-	 */
-	while ((in < end) && (*in != limit) &&
-	       ((*in == 0x20) || (*in == 0x9) ||
-	        (*in == 0xA) || (*in == 0xD))) {
-	    if (*in == 0xA) {
-	        line++; col = 1;
-	    } else {
-	        col++;
-	    }
-	    in++;
-	    start = in;
-	    if (in >= end) {
-                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
-                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
-                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
-                                   "AttValue length too long\n");
-                    return(NULL);
-                }
-	    }
-	}
-	while ((in < end) && (*in != limit) && (*in >= 0x20) &&
-	       (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
-	    col++;
-	    if ((*in++ == 0x20) && (*in == 0x20)) break;
-	    if (in >= end) {
-                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
-                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
-                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
-                                   "AttValue length too long\n");
-                    return(NULL);
-                }
-	    }
-	}
-	last = in;
-	/*
-	 * skip the trailing blanks
-	 */
-	while ((last[-1] == 0x20) && (last > start)) last--;
-	while ((in < end) && (*in != limit) &&
-	       ((*in == 0x20) || (*in == 0x9) ||
-	        (*in == 0xA) || (*in == 0xD))) {
-	    if (*in == 0xA) {
-	        line++, col = 1;
-	    } else {
-	        col++;
-	    }
-	    in++;
-	    if (in >= end) {
-		const xmlChar *oldbase = ctxt->input->base;
-		GROW;
-                if (ctxt->instate == XML_PARSER_EOF)
-                    return(NULL);
-		if (oldbase != ctxt->input->base) {
-		    ptrdiff_t delta = ctxt->input->base - oldbase;
-		    start = start + delta;
-		    in = in + delta;
-		    last = last + delta;
-		}
-		end = ctxt->input->end;
-                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
-                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
-                                   "AttValue length too long\n");
-                    return(NULL);
-                }
-	    }
+	++cmp;
+    }
+    if ((*cmp == 0) && (*in == ':')) {
+        in++;
+	cmp = name;
+	while (*in != 0 && *in == *cmp) {
+	    ++in;
+	    ++cmp;
 	}
-        if (((in - start) > XML_MAX_TEXT_LENGTH) &&
-            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
-                           "AttValue length too long\n");
-            return(NULL);
-        }
-	if (*in != limit) goto need_complex;
-    } else {
-	while ((in < end) && (*in != limit) && (*in >= 0x20) &&
-	       (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
-	    in++;
-	    col++;
-	    if (in >= end) {
-                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
-                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
-                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
-                                   "AttValue length too long\n");
-                    return(NULL);
-                }
-	    }
+	if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
+	    /* success */
+            ctxt->input->col += in - ctxt->input->cur;
+	    ctxt->input->cur = in;
+	    return((const xmlChar*) 1);
 	}
-	last = in;
-        if (((in - start) > XML_MAX_TEXT_LENGTH) &&
-            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
-                           "AttValue length too long\n");
-            return(NULL);
-        }
-	if (*in != limit) goto need_complex;
     }
-    in++;
-    col++;
-    if (len != NULL) {
-        *len = last - start;
-        ret = (xmlChar *) start;
-    } else {
-        if (alloc) *alloc = 1;
-        ret = xmlStrndup(start, last - start);
-    }
-    CUR_PTR = in;
-    ctxt->input->line = line;
-    ctxt->input->col = col;
-    if (alloc) *alloc = 0;
+    /*
+     * all strings coms from the dictionary, equality can be done directly
+     */
+    ret = xmlParseQName (ctxt, &prefix2);
+    if (ret == NULL)
+        return(NULL);
+    if ((ret == name) && (prefix == prefix2))
+	return((const xmlChar*) 1);
     return ret;
-need_complex:
-    if (alloc) *alloc = 1;
-    return xmlParseAttValueComplex(ctxt, len, normalize);
 }
 
 /**
@@ -9114,24 +8754,31 @@ need_complex:
  * Returns the attribute name, and the value in *value, .
  */
 
-static const xmlChar *
+static xmlHashedString
 xmlParseAttribute2(xmlParserCtxtPtr ctxt,
                    const xmlChar * pref, const xmlChar * elem,
-                   const xmlChar ** prefix, xmlChar ** value,
+                   xmlHashedString * hprefix, xmlChar ** value,
                    int *len, int *alloc)
 {
-    const xmlChar *name;
-    xmlChar *val, *internal_val = NULL;
+    xmlHashedString hname;
+    const xmlChar *prefix, *name;
+    xmlChar *val = NULL, *internal_val = NULL;
     int normalize = 0;
+    int isNamespace;
 
     *value = NULL;
     GROW;
-    name = xmlParseQName(ctxt, prefix);
-    if (name == NULL) {
+    hname = xmlParseQNameHashed(ctxt, hprefix);
+    if (hname.name == NULL) {
         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
                        "error parsing attribute name\n");
-        return (NULL);
+        return(hname);
     }
+    name = hname.name;
+    if (hprefix->name != NULL)
+        prefix = hprefix->name;
+    else
+        prefix = NULL;
 
     /*
      * get the type if needed
@@ -9140,7 +8787,8 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt,
         int type;
 
         type = (int) (ptrdiff_t) xmlHashQLookup2(ctxt->attsSpecial,
-                                                 pref, elem, *prefix, name);
+                                                 pref, elem,
+                                                 prefix, name);
         if (type != 0)
             normalize = 1;
     }
@@ -9152,33 +8800,20 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt,
     if (RAW == '=') {
         NEXT;
         SKIP_BLANKS;
-        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
-	if (normalize) {
-	    /*
-	     * Sometimes a second normalisation pass for spaces is needed
-	     * but that only happens if charrefs or entities references
-	     * have been used in the attribute value, i.e. the attribute
-	     * value have been extracted in an allocated string already.
-	     */
-	    if (*alloc) {
-	        const xmlChar *val2;
-
-	        val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
-		if ((val2 != NULL) && (val2 != val)) {
-		    xmlFree(val);
-		    val = (xmlChar *) val2;
-		}
-	    }
-	}
-        ctxt->instate = XML_PARSER_CONTENT;
+        isNamespace = (((prefix == NULL) && (name == ctxt->str_xmlns)) ||
+                       (prefix == ctxt->str_xmlns));
+        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize,
+                                       isNamespace);
+        if (val == NULL)
+            goto error;
     } else {
         xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
                           "Specification mandates value for attribute %s\n",
                           name);
-        return (NULL);
+        goto error;
     }
 
-    if (*prefix == ctxt->str_xml) {
+    if (prefix == ctxt->str_xml) {
         /*
          * Check that xml:lang conforms to the specification
          * No more registered as an error, just generate a warning now
@@ -9186,6 +8821,8 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt,
          */
         if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
             internal_val = xmlStrndup(val, *len);
+            if (internal_val == NULL)
+                goto mem_error;
             if (!xmlCheckLanguageID(internal_val)) {
                 xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
                               "Malformed value for xml:lang : %s\n",
@@ -9198,6 +8835,8 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt,
          */
         if (xmlStrEqual(name, BAD_CAST "space")) {
             internal_val = xmlStrndup(val, *len);
+            if (internal_val == NULL)
+                goto mem_error;
             if (xmlStrEqual(internal_val, BAD_CAST "default"))
                 *(ctxt->space) = 0;
             else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
@@ -9214,14 +8853,71 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt,
     }
 
     *value = val;
-    return (name);
+    return (hname);
+
+mem_error:
+    xmlErrMemory(ctxt);
+error:
+    if ((val != NULL) && (*alloc != 0))
+        xmlFree(val);
+    return(hname);
+}
+
+/**
+ * xmlAttrHashInsert:
+ * @ctxt: parser context
+ * @size: size of the hash table
+ * @name: attribute name
+ * @uri: namespace uri
+ * @hashValue: combined hash value of name and uri
+ * @aindex: attribute index (this is a multiple of 5)
+ *
+ * Inserts a new attribute into the hash table.
+ *
+ * Returns INT_MAX if no existing attribute was found, the attribute
+ * index if an attribute was found, -1 if a memory allocation failed.
+ */
+static int
+xmlAttrHashInsert(xmlParserCtxtPtr ctxt, unsigned size, const xmlChar *name,
+                  const xmlChar *uri, unsigned hashValue, int aindex) {
+    xmlAttrHashBucket *table = ctxt->attrHash;
+    xmlAttrHashBucket *bucket;
+    unsigned hindex;
+
+    hindex = hashValue & (size - 1);
+    bucket = &table[hindex];
+
+    while (bucket->index >= 0) {
+        const xmlChar **atts = &ctxt->atts[bucket->index];
+
+        if (name == atts[0]) {
+            int nsIndex = (int) (ptrdiff_t) atts[2];
+
+            if ((nsIndex == NS_INDEX_EMPTY) ? (uri == NULL) :
+                (nsIndex == NS_INDEX_XML) ? (uri == ctxt->str_xml_ns) :
+                (uri == ctxt->nsTab[nsIndex * 2 + 1]))
+                return(bucket->index);
+        }
+
+        hindex++;
+        bucket++;
+        if (hindex >= size) {
+            hindex = 0;
+            bucket = table;
+        }
+    }
+
+    bucket->index = aindex;
+
+    return(INT_MAX);
 }
+
 /**
  * xmlParseStartTag2:
  * @ctxt:  an XML parser context
  *
- * parse a start of tag either for rule element or
- * EmptyElement. In both case we don't parse the tag closing chars.
+ * Parse a start tag. Always consumes '<'.
+ *
  * This routine is called when running SAX2 parsing
  *
  * [40] STag ::= '<' Name (S Attribute)* S? '>'
@@ -9247,48 +8943,47 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt,
 
 static const xmlChar *
 xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
-                  const xmlChar **URI, int *tlen) {
+                  const xmlChar **URI, int *nbNsPtr) {
+    xmlHashedString hlocalname;
+    xmlHashedString hprefix;
+    xmlHashedString hattname;
+    xmlHashedString haprefix;
     const xmlChar *localname;
     const xmlChar *prefix;
     const xmlChar *attname;
     const xmlChar *aprefix;
-    const xmlChar *nsname;
-    xmlChar *attvalue;
+    const xmlChar *uri;
+    xmlChar *attvalue = NULL;
     const xmlChar **atts = ctxt->atts;
+    unsigned attrHashSize = 0;
     int maxatts = ctxt->maxatts;
-    int nratts, nbatts, nbdef, inputid;
-    int i, j, nbNs, attval;
-    unsigned long cur;
-    int nsNr = ctxt->nsNr;
+    int nratts, nbatts, nbdef;
+    int i, j, nbNs, nbTotalDef, attval, nsIndex, maxAtts;
+    int alloc = 0;
 
     if (RAW != '<') return(NULL);
     NEXT1;
 
-    /*
-     * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
-     *       point since the attribute values may be stored as pointers to
-     *       the buffer and calling SHRINK would destroy them !
-     *       The Shrinking is only possible once the full set of attribute
-     *       callbacks have been done.
-     */
-    SHRINK;
-    cur = ctxt->input->cur - ctxt->input->base;
-    inputid = ctxt->input->id;
     nbatts = 0;
     nratts = 0;
     nbdef = 0;
     nbNs = 0;
+    nbTotalDef = 0;
     attval = 0;
-    /* Forget any namespaces added during an earlier parse of this element. */
-    ctxt->nsNr = nsNr;
 
-    localname = xmlParseQName(ctxt, &prefix);
-    if (localname == NULL) {
+    if (xmlParserNsStartElement(ctxt->nsdb) < 0) {
+        xmlErrMemory(ctxt);
+        return(NULL);
+    }
+
+    hlocalname = xmlParseQNameHashed(ctxt, &hprefix);
+    if (hlocalname.name == NULL) {
 	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 		       "StartTag: invalid element name\n");
         return(NULL);
     }
-    *tlen = ctxt->input->cur - ctxt->input->base - cur;
+    localname = hlocalname.name;
+    prefix = hprefix.name;
 
     /*
      * Now parse the attributes, it ends up with the ending
@@ -9298,45 +8993,74 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
     SKIP_BLANKS;
     GROW;
 
+    /*
+     * The ctxt->atts array will be ultimately passed to the SAX callback
+     * containing five xmlChar pointers for each attribute:
+     *
+     * [0] attribute name
+     * [1] attribute prefix
+     * [2] namespace URI
+     * [3] attribute value
+     * [4] end of attribute value
+     *
+     * To save memory, we reuse this array temporarily and store integers
+     * in these pointer variables.
+     *
+     * [0] attribute name
+     * [1] attribute prefix
+     * [2] hash value of attribute prefix, and later namespace index
+     * [3] for non-allocated values: ptrdiff_t offset into input buffer
+     * [4] for non-allocated values: ptrdiff_t offset into input buffer
+     *
+     * The ctxt->attallocs array contains an additional unsigned int for
+     * each attribute, containing the hash value of the attribute name
+     * and the alloc flag in bit 31.
+     */
+
     while (((RAW != '>') &&
 	   ((RAW != '/') || (NXT(1) != '>')) &&
-	   (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
-	int id = ctxt->input->id;
-	unsigned long cons = CUR_CONSUMED;
-	int len = -1, alloc = 0;
-
-	attname = xmlParseAttribute2(ctxt, prefix, localname,
-	                             &aprefix, &attvalue, &len, &alloc);
-        if ((attname == NULL) || (attvalue == NULL))
+	   (IS_BYTE_CHAR(RAW))) && (PARSER_STOPPED(ctxt) == 0)) {
+	int len = -1;
+
+	hattname = xmlParseAttribute2(ctxt, prefix, localname,
+                                          &haprefix, &attvalue, &len,
+                                          &alloc);
+        if (hattname.name == NULL)
+	    break;
+        if (attvalue == NULL)
             goto next_attr;
+        attname = hattname.name;
+        aprefix = haprefix.name;
 	if (len < 0) len = xmlStrlen(attvalue);
 
         if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
-            const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
-            xmlURIPtr uri;
-
-            if (URL == NULL) {
-                xmlErrMemory(ctxt, "dictionary allocation failure");
-                if ((attvalue != NULL) && (alloc != 0))
-                    xmlFree(attvalue);
-                localname = NULL;
-                goto done;
+            xmlHashedString huri;
+            xmlURIPtr parsedUri;
+
+            huri = xmlDictLookupHashed(ctxt->dict, attvalue, len);
+            uri = huri.name;
+            if (uri == NULL) {
+                xmlErrMemory(ctxt);
+                goto next_attr;
             }
-            if (*URL != 0) {
-                uri = xmlParseURI((const char *) URL);
-                if (uri == NULL) {
+            if (*uri != 0) {
+                if (xmlParseURISafe((const char *) uri, &parsedUri) < 0) {
+                    xmlErrMemory(ctxt);
+                    goto next_attr;
+                }
+                if (parsedUri == NULL) {
                     xmlNsErr(ctxt, XML_WAR_NS_URI,
                              "xmlns: '%s' is not a valid URI\n",
-                                       URL, NULL, NULL);
+                                       uri, NULL, NULL);
                 } else {
-                    if (uri->scheme == NULL) {
+                    if (parsedUri->scheme == NULL) {
                         xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
                                   "xmlns: URI %s is not absolute\n",
-                                  URL, NULL, NULL);
+                                  uri, NULL, NULL);
                     }
-                    xmlFreeURI(uri);
+                    xmlFreeURI(parsedUri);
                 }
-                if (URL == ctxt->str_xml_ns) {
+                if (uri == ctxt->str_xml_ns) {
                     if (attname != ctxt->str_xml) {
                         xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
                      "xml namespace URI cannot be the default namespace\n",
@@ -9345,7 +9069,7 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
                     goto next_attr;
                 }
                 if ((len == 29) &&
-                    (xmlStrEqual(URL,
+                    (xmlStrEqual(uri,
                              BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
                     xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
                          "reuse of the xmlns namespace name is forbidden\n",
@@ -9353,23 +9077,22 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
                     goto next_attr;
                 }
             }
-            /*
-             * check that it's not a defined namespace
-             */
-            for (j = 1;j <= nbNs;j++)
-                if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
-                    break;
-            if (j <= nbNs)
-                xmlErrAttributeDup(ctxt, NULL, attname);
-            else
-                if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
 
+            if (xmlParserNsPush(ctxt, NULL, &huri, NULL, 0) > 0)
+                nbNs++;
         } else if (aprefix == ctxt->str_xmlns) {
-            const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
-            xmlURIPtr uri;
+            xmlHashedString huri;
+            xmlURIPtr parsedUri;
+
+            huri = xmlDictLookupHashed(ctxt->dict, attvalue, len);
+            uri = huri.name;
+            if (uri == NULL) {
+                xmlErrMemory(ctxt);
+                goto next_attr;
+            }
 
             if (attname == ctxt->str_xml) {
-                if (URL != ctxt->str_xml_ns) {
+                if (uri != ctxt->str_xml_ns) {
                     xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
                              "xml namespace prefix mapped to wrong URI\n",
                              NULL, NULL, NULL);
@@ -9379,7 +9102,7 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
                  */
                 goto next_attr;
             }
-            if (URL == ctxt->str_xml_ns) {
+            if (uri == ctxt->str_xml_ns) {
                 if (attname != ctxt->str_xml) {
                     xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
                              "xml namespace URI mapped to wrong prefix\n",
@@ -9394,48 +9117,43 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
                 goto next_attr;
             }
             if ((len == 29) &&
-                (xmlStrEqual(URL,
+                (xmlStrEqual(uri,
                              BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
                 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
                          "reuse of the xmlns namespace name is forbidden\n",
                          NULL, NULL, NULL);
                 goto next_attr;
             }
-            if ((URL == NULL) || (URL[0] == 0)) {
+            if ((uri == NULL) || (uri[0] == 0)) {
                 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
                          "xmlns:%s: Empty XML namespace is not allowed\n",
                               attname, NULL, NULL);
                 goto next_attr;
             } else {
-                uri = xmlParseURI((const char *) URL);
-                if (uri == NULL) {
+                if (xmlParseURISafe((const char *) uri, &parsedUri) < 0) {
+                    xmlErrMemory(ctxt);
+                    goto next_attr;
+                }
+                if (parsedUri == NULL) {
                     xmlNsErr(ctxt, XML_WAR_NS_URI,
                          "xmlns:%s: '%s' is not a valid URI\n",
-                                       attname, URL, NULL);
+                                       attname, uri, NULL);
                 } else {
-                    if ((ctxt->pedantic) && (uri->scheme == NULL)) {
+                    if ((ctxt->pedantic) && (parsedUri->scheme == NULL)) {
                         xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
                                   "xmlns:%s: URI %s is not absolute\n",
-                                  attname, URL, NULL);
+                                  attname, uri, NULL);
                     }
-                    xmlFreeURI(uri);
+                    xmlFreeURI(parsedUri);
                 }
             }
 
-            /*
-             * check that it's not a defined namespace
-             */
-            for (j = 1;j <= nbNs;j++)
-                if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
-                    break;
-            if (j <= nbNs)
-                xmlErrAttributeDup(ctxt, aprefix, attname);
-            else
-                if (nsPush(ctxt, attname, URL) > 0) nbNs++;
-
+            if (xmlParserNsPush(ctxt, &hattname, &huri, NULL, 0) > 0)
+                nbNs++;
         } else {
             /*
-             * Add the pair to atts
+             * Populate attributes array, see above for repurposing
+             * of xmlChar pointers.
              */
             if ((atts == NULL) || (nbatts + 5 > maxatts)) {
                 if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
@@ -9444,22 +9162,25 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
                 maxatts = ctxt->maxatts;
                 atts = ctxt->atts;
             }
-            ctxt->attallocs[nratts++] = alloc;
+            ctxt->attallocs[nratts++] = (hattname.hashValue & 0x7FFFFFFF) |
+                                        ((unsigned) alloc << 31);
             atts[nbatts++] = attname;
             atts[nbatts++] = aprefix;
-            /*
-             * The namespace URI field is used temporarily to point at the
-             * base of the current input buffer for non-alloced attributes.
-             * When the input buffer is reallocated, all the pointers become
-             * invalid, but they can be reconstructed later.
-             */
-            if (alloc)
-                atts[nbatts++] = NULL;
-            else
-                atts[nbatts++] = ctxt->input->base;
-            atts[nbatts++] = attvalue;
-            attvalue += len;
-            atts[nbatts++] = attvalue;
+            atts[nbatts++] = (const xmlChar *) (size_t) haprefix.hashValue;
+            if (alloc) {
+                atts[nbatts++] = attvalue;
+                attvalue += len;
+                atts[nbatts++] = attvalue;
+            } else {
+                /*
+                 * attvalue points into the input buffer which can be
+                 * reallocated. Store differences to input->base instead.
+                 * The pointers will be reconstructed later.
+                 */
+                atts[nbatts++] = (void *) (attvalue - BASE_PTR);
+                attvalue += len;
+                atts[nbatts++] = (void *) (attvalue - BASE_PTR);
+            }
             /*
              * tag if some deallocation is needed
              */
@@ -9474,8 +9195,6 @@ next_attr:
         }
 
 	GROW
-        if (ctxt->instate == XML_PARSER_EOF)
-            break;
 	if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
 	    break;
 	if (SKIP_BLANKS == 0) {
@@ -9483,191 +9202,297 @@ next_attr:
 			   "attributes construct error\n");
 	    break;
 	}
-        if ((cons == CUR_CONSUMED) && (id == ctxt->input->id) &&
-            (attname == NULL) && (attvalue == NULL)) {
-	    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-	         "xmlParseStartTag: problem parsing attributes\n");
-	    break;
-	}
         GROW;
     }
 
-    if (ctxt->input->id != inputid) {
-        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-                    "Unexpected change of input\n");
-        localname = NULL;
-        goto done;
-    }
-
-    /* Reconstruct attribute value pointers. */
-    for (i = 0, j = 0; j < nratts; i += 5, j++) {
-        if (atts[i+2] != NULL) {
-            /*
-             * Arithmetic on dangling pointers is technically undefined
-             * behavior, but well...
-             */
-            ptrdiff_t offset = ctxt->input->base - atts[i+2];
-            atts[i+2]  = NULL;    /* Reset repurposed namespace URI */
-            atts[i+3] += offset;  /* value */
-            atts[i+4] += offset;  /* valuend */
-        }
-    }
-
     /*
-     * The attributes defaulting
+     * Namespaces from default attributes
      */
     if (ctxt->attsDefault != NULL) {
         xmlDefAttrsPtr defaults;
 
 	defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
 	if (defaults != NULL) {
-	    for (i = 0;i < defaults->nbAttrs;i++) {
-	        attname = defaults->values[5 * i];
-		aprefix = defaults->values[5 * i + 1];
+	    for (i = 0; i < defaults->nbAttrs; i++) {
+                xmlDefAttr *attr = &defaults->attrs[i];
+
+	        attname = attr->name.name;
+		aprefix = attr->prefix.name;
 
-                /*
-		 * special work for namespaces defaulted defs
-		 */
 		if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
-		    /*
-		     * check that it's not a defined namespace
-		     */
-		    for (j = 1;j <= nbNs;j++)
-		        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
-			    break;
-	            if (j <= nbNs) continue;
-
-		    nsname = xmlGetNamespace(ctxt, NULL);
-		    if (nsname != defaults->values[5 * i + 2]) {
-			if (nsPush(ctxt, NULL,
-			           defaults->values[5 * i + 2]) > 0)
-			    nbNs++;
-		    }
+                    xmlParserEntityCheck(ctxt, attr->expandedSize);
+
+                    if (xmlParserNsPush(ctxt, NULL, &attr->value, NULL, 1) > 0)
+                        nbNs++;
 		} else if (aprefix == ctxt->str_xmlns) {
-		    /*
-		     * check that it's not a defined namespace
-		     */
-		    for (j = 1;j <= nbNs;j++)
-		        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
-			    break;
-	            if (j <= nbNs) continue;
-
-		    nsname = xmlGetNamespace(ctxt, attname);
-		    if (nsname != defaults->values[2]) {
-			if (nsPush(ctxt, attname,
-			           defaults->values[5 * i + 2]) > 0)
-			    nbNs++;
-		    }
-		} else {
-		    /*
-		     * check that it's not a defined attribute
-		     */
-		    for (j = 0;j < nbatts;j+=5) {
-			if ((attname == atts[j]) && (aprefix == atts[j+1]))
-			    break;
-		    }
-		    if (j < nbatts) continue;
+                    xmlParserEntityCheck(ctxt, attr->expandedSize);
 
-		    if ((atts == NULL) || (nbatts + 5 > maxatts)) {
-			if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
-                            localname = NULL;
-                            goto done;
-			}
-			maxatts = ctxt->maxatts;
-			atts = ctxt->atts;
-		    }
-		    atts[nbatts++] = attname;
-		    atts[nbatts++] = aprefix;
-		    if (aprefix == NULL)
-			atts[nbatts++] = NULL;
-		    else
-		        atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
-		    atts[nbatts++] = defaults->values[5 * i + 2];
-		    atts[nbatts++] = defaults->values[5 * i + 3];
-		    if ((ctxt->standalone == 1) &&
-		        (defaults->values[5 * i + 4] != NULL)) {
-			xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
-	  "standalone: attribute %s on %s defaulted from external subset\n",
-	                                 attname, localname);
-		    }
-		    nbdef++;
-		}
+                    if (xmlParserNsPush(ctxt, &attr->name, &attr->value,
+                                      NULL, 1) > 0)
+                        nbNs++;
+		} else {
+                    nbTotalDef += 1;
+                }
 	    }
 	}
     }
 
     /*
-     * The attributes checkings
+     * Resolve attribute namespaces
      */
-    for (i = 0; i < nbatts;i += 5) {
+    for (i = 0; i < nbatts; i += 5) {
+        attname = atts[i];
+        aprefix = atts[i+1];
+
         /*
 	* The default namespace does not apply to attribute names.
 	*/
-	if (atts[i + 1] != NULL) {
-	    nsname = xmlGetNamespace(ctxt, atts[i + 1]);
-	    if (nsname == NULL) {
-		xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
+	if (aprefix == NULL) {
+            nsIndex = NS_INDEX_EMPTY;
+        } else if (aprefix == ctxt->str_xml) {
+            nsIndex = NS_INDEX_XML;
+        } else {
+            haprefix.name = aprefix;
+            haprefix.hashValue = (size_t) atts[i+2];
+            nsIndex = xmlParserNsLookup(ctxt, &haprefix, NULL);
+
+	    if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex)) {
+                xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
 		    "Namespace prefix %s for %s on %s is not defined\n",
-		    atts[i + 1], atts[i], localname);
-	    }
-	    atts[i + 2] = nsname;
-	} else
-	    nsname = NULL;
-	/*
-	 * [ WFC: Unique Att Spec ]
-	 * No attribute name may appear more than once in the same
-	 * start-tag or empty-element tag.
-	 * As extended by the Namespace in XML REC.
-	 */
-        for (j = 0; j < i;j += 5) {
-	    if (atts[i] == atts[j]) {
-	        if (atts[i+1] == atts[j+1]) {
-		    xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
-		    break;
-		}
-		if ((nsname != NULL) && (atts[j + 2] == nsname)) {
-		    xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
-			     "Namespaced Attribute %s in '%s' redefined\n",
-			     atts[i], nsname, NULL);
-		    break;
-		}
+		    aprefix, attname, localname);
+                nsIndex = NS_INDEX_EMPTY;
+            }
+        }
+
+        atts[i+2] = (const xmlChar *) (ptrdiff_t) nsIndex;
+    }
+
+    /*
+     * Maximum number of attributes including default attributes.
+     */
+    maxAtts = nratts + nbTotalDef;
+
+    /*
+     * Verify that attribute names are unique.
+     */
+    if (maxAtts > 1) {
+        attrHashSize = 4;
+        while (attrHashSize / 2 < (unsigned) maxAtts)
+            attrHashSize *= 2;
+
+        if (attrHashSize > ctxt->attrHashMax) {
+            xmlAttrHashBucket *tmp;
+
+            tmp = xmlRealloc(ctxt->attrHash, attrHashSize * sizeof(tmp[0]));
+            if (tmp == NULL) {
+                xmlErrMemory(ctxt);
+                goto done;
+            }
+
+            ctxt->attrHash = tmp;
+            ctxt->attrHashMax = attrHashSize;
+        }
+
+        memset(ctxt->attrHash, -1, attrHashSize * sizeof(ctxt->attrHash[0]));
+
+        for (i = 0, j = 0; j < nratts; i += 5, j++) {
+            const xmlChar *nsuri;
+            unsigned hashValue, nameHashValue, uriHashValue;
+            int res;
+
+            attname = atts[i];
+            aprefix = atts[i+1];
+            nsIndex = (ptrdiff_t) atts[i+2];
+            /* Hash values always have bit 31 set, see dict.c */
+            nameHashValue = ctxt->attallocs[j] | 0x80000000;
+
+            if (nsIndex == NS_INDEX_EMPTY) {
+                /*
+                 * Prefix with empty namespace means an undeclared
+                 * prefix which was already reported above.
+                 */
+                if (aprefix != NULL)
+                    continue;
+                nsuri = NULL;
+                uriHashValue = URI_HASH_EMPTY;
+            } else if (nsIndex == NS_INDEX_XML) {
+                nsuri = ctxt->str_xml_ns;
+                uriHashValue = URI_HASH_XML;
+            } else {
+                nsuri = ctxt->nsTab[nsIndex * 2 + 1];
+                uriHashValue = ctxt->nsdb->extra[nsIndex].uriHashValue;
+            }
+
+            hashValue = xmlDictCombineHash(nameHashValue, uriHashValue);
+            res = xmlAttrHashInsert(ctxt, attrHashSize, attname, nsuri,
+                                    hashValue, i);
+            if (res < 0)
+                continue;
+
+            /*
+             * [ WFC: Unique Att Spec ]
+             * No attribute name may appear more than once in the same
+             * start-tag or empty-element tag.
+             * As extended by the Namespace in XML REC.
+             */
+            if (res < INT_MAX) {
+                if (aprefix == atts[res+1]) {
+                    xmlErrAttributeDup(ctxt, aprefix, attname);
+                } else {
+                    xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
+                             "Namespaced Attribute %s in '%s' redefined\n",
+                             attname, nsuri, NULL);
+                }
+            }
+        }
+    }
+
+    /*
+     * Default attributes
+     */
+    if (ctxt->attsDefault != NULL) {
+        xmlDefAttrsPtr defaults;
+
+	defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
+	if (defaults != NULL) {
+	    for (i = 0; i < defaults->nbAttrs; i++) {
+                xmlDefAttr *attr = &defaults->attrs[i];
+                const xmlChar *nsuri;
+                unsigned hashValue, uriHashValue;
+                int res;
+
+	        attname = attr->name.name;
+		aprefix = attr->prefix.name;
+
+		if ((attname == ctxt->str_xmlns) && (aprefix == NULL))
+                    continue;
+		if (aprefix == ctxt->str_xmlns)
+                    continue;
+
+                if (aprefix == NULL) {
+                    nsIndex = NS_INDEX_EMPTY;
+                    nsuri = NULL;
+                    uriHashValue = URI_HASH_EMPTY;
+                } if (aprefix == ctxt->str_xml) {
+                    nsIndex = NS_INDEX_XML;
+                    nsuri = ctxt->str_xml_ns;
+                    uriHashValue = URI_HASH_XML;
+                } else if (aprefix != NULL) {
+                    nsIndex = xmlParserNsLookup(ctxt, &attr->prefix, NULL);
+                    if ((nsIndex == INT_MAX) ||
+                        (nsIndex < ctxt->nsdb->minNsIndex)) {
+                        xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
+                                 "Namespace prefix %s for %s on %s is not "
+                                 "defined\n",
+                                 aprefix, attname, localname);
+                        nsIndex = NS_INDEX_EMPTY;
+                        nsuri = NULL;
+                        uriHashValue = URI_HASH_EMPTY;
+                    } else {
+                        nsuri = ctxt->nsTab[nsIndex * 2 + 1];
+                        uriHashValue = ctxt->nsdb->extra[nsIndex].uriHashValue;
+                    }
+                }
+
+                /*
+                 * Check whether the attribute exists
+                 */
+                if (maxAtts > 1) {
+                    hashValue = xmlDictCombineHash(attr->name.hashValue,
+                                                   uriHashValue);
+                    res = xmlAttrHashInsert(ctxt, attrHashSize, attname, nsuri,
+                                            hashValue, nbatts);
+                    if (res < 0)
+                        continue;
+                    if (res < INT_MAX) {
+                        if (aprefix == atts[res+1])
+                            continue;
+                        xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
+                                 "Namespaced Attribute %s in '%s' redefined\n",
+                                 attname, nsuri, NULL);
+                    }
+                }
+
+                xmlParserEntityCheck(ctxt, attr->expandedSize);
+
+                if ((atts == NULL) || (nbatts + 5 > maxatts)) {
+                    if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
+                        localname = NULL;
+                        goto done;
+                    }
+                    maxatts = ctxt->maxatts;
+                    atts = ctxt->atts;
+                }
+
+                atts[nbatts++] = attname;
+                atts[nbatts++] = aprefix;
+                atts[nbatts++] = (const xmlChar *) (ptrdiff_t) nsIndex;
+                atts[nbatts++] = attr->value.name;
+                atts[nbatts++] = attr->valueEnd;
+                if ((ctxt->standalone == 1) && (attr->external != 0)) {
+                    xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
+                            "standalone: attribute %s on %s defaulted "
+                            "from external subset\n",
+                            attname, localname);
+                }
+                nbdef++;
 	    }
 	}
     }
 
-    nsname = xmlGetNamespace(ctxt, prefix);
-    if ((prefix != NULL) && (nsname == NULL)) {
+    /*
+     * Reconstruct attribute pointers
+     */
+    for (i = 0, j = 0; i < nbatts; i += 5, j++) {
+        /* namespace URI */
+        nsIndex = (ptrdiff_t) atts[i+2];
+        if (nsIndex == INT_MAX)
+            atts[i+2] = NULL;
+        else if (nsIndex == INT_MAX - 1)
+            atts[i+2] = ctxt->str_xml_ns;
+        else
+            atts[i+2] = ctxt->nsTab[nsIndex * 2 + 1];
+
+        if ((j < nratts) && (ctxt->attallocs[j] & 0x80000000) == 0) {
+            atts[i+3] = BASE_PTR + (ptrdiff_t) atts[i+3];  /* value */
+            atts[i+4] = BASE_PTR + (ptrdiff_t) atts[i+4];  /* valuend */
+        }
+    }
+
+    uri = xmlParserNsLookupUri(ctxt, &hprefix);
+    if ((prefix != NULL) && (uri == NULL)) {
 	xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
 	         "Namespace prefix %s on %s is not defined\n",
 		 prefix, localname, NULL);
     }
     *pref = prefix;
-    *URI = nsname;
+    *URI = uri;
 
     /*
-     * SAX: Start of Element !
+     * SAX callback
      */
     if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
 	(!ctxt->disableSAX)) {
 	if (nbNs > 0)
-	    ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
-			  nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
+	    ctxt->sax->startElementNs(ctxt->userData, localname, prefix, uri,
+                          nbNs, ctxt->nsTab + 2 * (ctxt->nsNr - nbNs),
 			  nbatts / 5, nbdef, atts);
 	else
-	    ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
-	                  nsname, 0, NULL, nbatts / 5, nbdef, atts);
+	    ctxt->sax->startElementNs(ctxt->userData, localname, prefix, uri,
+                          0, NULL, nbatts / 5, nbdef, atts);
     }
 
 done:
     /*
-     * Free up attribute allocated strings if needed
+     * Free allocated attribute values
      */
     if (attval != 0) {
-	for (i = 3,j = 0; j < nratts;i += 5,j++)
-	    if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
-	        xmlFree((xmlChar *) atts[i]);
+	for (i = 0, j = 0; j < nratts; i += 5, j++)
+	    if (ctxt->attallocs[j] & 0x80000000)
+	        xmlFree((xmlChar *) atts[i+3]);
     }
 
+    *nbNsPtr = nbNs;
     return(localname);
 }
 
@@ -9677,7 +9502,7 @@ done:
  * @line:  line of the start tag
  * @nsNr:  number of namespaces on the start tag
  *
- * parse an end of tag
+ * Parse an end tag. Always consumes '</'.
  *
  * [42] ETag ::= '</' Name S? '>'
  *
@@ -9706,8 +9531,6 @@ xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlStartTag *tag) {
      * We should definitely be at the ending "S? '>'" part
      */
     GROW;
-    if (ctxt->instate == XML_PARSER_EOF)
-        return;
     SKIP_BLANKS;
     if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
 	xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
@@ -9737,14 +9560,16 @@ xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlStartTag *tag) {
 
     spacePop(ctxt);
     if (tag->nsNr != 0)
-	nsPop(ctxt, tag->nsNr);
+	xmlParserNsPop(ctxt, tag->nsNr);
 }
 
 /**
  * xmlParseCDSect:
  * @ctxt:  an XML parser context
  *
- * Parse escaped pure raw content.
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Parse escaped pure raw content. Always consumes '<!['.
  *
  * [18] CDSect ::= CDStart CData CDEnd
  *
@@ -9762,81 +9587,67 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
     int r, rl;
     int	s, sl;
     int cur, l;
-    int count = 0;
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_HUGE_LENGTH :
+                    XML_MAX_TEXT_LENGTH;
 
-    /* Check 2.6.0 was NXT(0) not RAW */
-    if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
-	SKIP(9);
-    } else
+    if ((CUR != '<') || (NXT(1) != '!') || (NXT(2) != '['))
         return;
+    SKIP(3);
+
+    if (!CMP6(CUR_PTR, 'C', 'D', 'A', 'T', 'A', '['))
+        return;
+    SKIP(6);
 
-    ctxt->instate = XML_PARSER_CDATA_SECTION;
     r = CUR_CHAR(rl);
     if (!IS_CHAR(r)) {
 	xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
-	ctxt->instate = XML_PARSER_CONTENT;
-        return;
+        goto out;
     }
     NEXTL(rl);
     s = CUR_CHAR(sl);
     if (!IS_CHAR(s)) {
 	xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
-	ctxt->instate = XML_PARSER_CONTENT;
-        return;
+        goto out;
     }
     NEXTL(sl);
     cur = CUR_CHAR(l);
-    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+    buf = (xmlChar *) xmlMallocAtomic(size);
     if (buf == NULL) {
-	xmlErrMemory(ctxt, NULL);
-	return;
+	xmlErrMemory(ctxt);
+        goto out;
     }
     while (IS_CHAR(cur) &&
            ((r != ']') || (s != ']') || (cur != '>'))) {
 	if (len + 5 >= size) {
 	    xmlChar *tmp;
 
-            if ((size > XML_MAX_TEXT_LENGTH) &&
-                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-                xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
-                             "CData section too big found", NULL);
-                xmlFree (buf);
-                return;
-            }
-	    tmp = (xmlChar *) xmlRealloc(buf, size * 2 * sizeof(xmlChar));
+	    tmp = (xmlChar *) xmlRealloc(buf, size * 2);
 	    if (tmp == NULL) {
-	        xmlFree(buf);
-		xmlErrMemory(ctxt, NULL);
-		return;
+		xmlErrMemory(ctxt);
+                goto out;
 	    }
 	    buf = tmp;
 	    size *= 2;
 	}
-	COPY_BUF(rl,buf,len,r);
+	COPY_BUF(buf, len, r);
+        if (len > maxLength) {
+            xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED,
+                           "CData section too big found\n");
+            goto out;
+        }
 	r = s;
 	rl = sl;
 	s = cur;
 	sl = l;
-	count++;
-	if (count > 50) {
-	    SHRINK;
-	    GROW;
-            if (ctxt->instate == XML_PARSER_EOF) {
-		xmlFree(buf);
-		return;
-            }
-	    count = 0;
-	}
 	NEXTL(l);
 	cur = CUR_CHAR(l);
     }
     buf[len] = 0;
-    ctxt->instate = XML_PARSER_CONTENT;
     if (cur != '>') {
 	xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
 	                     "CData section not finished\n%.50s\n", buf);
-	xmlFree(buf);
-        return;
+        goto out;
     }
     NEXTL(l);
 
@@ -9849,6 +9660,8 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
 	else if (ctxt->sax->characters != NULL)
 	    ctxt->sax->characters(ctxt->userData, buf, len);
     }
+
+out:
     xmlFree(buf);
 }
 
@@ -9862,13 +9675,13 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
 
 static void
 xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
-    int nameNr = ctxt->nameNr;
+    int oldNameNr = ctxt->nameNr;
+    int oldSpaceNr = ctxt->spaceNr;
+    int oldNodeNr = ctxt->nodeNr;
 
     GROW;
-    while ((RAW != 0) &&
-	   (ctxt->instate != XML_PARSER_EOF)) {
-        int id = ctxt->input->id;
-	unsigned long cons = CUR_CONSUMED;
+    while ((ctxt->input->cur < ctxt->input->end) &&
+	   (PARSER_STOPPED(ctxt) == 0)) {
 	const xmlChar *cur = ctxt->input->cur;
 
 	/*
@@ -9892,7 +9705,6 @@ xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
 	else if ((*cur == '<') && (NXT(1) == '!') &&
 		 (NXT(2) == '-') && (NXT(3) == '-')) {
 	    xmlParseComment(ctxt);
-	    ctxt->instate = XML_PARSER_CONTENT;
 	}
 
 	/*
@@ -9900,7 +9712,7 @@ xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
 	 */
 	else if (*cur == '<') {
             if (NXT(1) == '/') {
-                if (ctxt->nameNr <= nameNr)
+                if (ctxt->nameNr <= oldNameNr)
                     break;
 	        xmlParseElementEnd(ctxt);
             } else {
@@ -9917,53 +9729,74 @@ xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
 	    xmlParseReference(ctxt);
 	}
 
-	/*
-	 * Last case, text. Note that References are handled directly.
-	 */
-	else {
-	    xmlParseCharData(ctxt, 0);
-	}
+	/*
+	 * Last case, text. Note that References are handled directly.
+	 */
+	else {
+	    xmlParseCharDataInternal(ctxt, 0);
+	}
+
+	SHRINK;
+	GROW;
+    }
+
+    if ((ctxt->nameNr > oldNameNr) &&
+        (ctxt->input->cur >= ctxt->input->end) &&
+        (ctxt->wellFormed)) {
+        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
+        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
+        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
+                "Premature end of data in tag %s line %d\n",
+                name, line, NULL);
+    }
+
+    /*
+     * Clean up in error case
+     */
+
+    while (ctxt->nodeNr > oldNodeNr)
+        nodePop(ctxt);
 
-	GROW;
-	SHRINK;
+    while (ctxt->nameNr > oldNameNr) {
+        xmlStartTag *tag = &ctxt->pushTab[ctxt->nameNr - 1];
 
-	if ((cons == CUR_CONSUMED) && (id == ctxt->input->id)) {
-	    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-	                "detected an error in element content\n");
-	    xmlHaltParser(ctxt);
-            break;
-	}
+        if (tag->nsNr != 0)
+            xmlParserNsPop(ctxt, tag->nsNr);
+
+        namePop(ctxt);
     }
+
+    while (ctxt->spaceNr > oldSpaceNr)
+        spacePop(ctxt);
 }
 
 /**
  * xmlParseContent:
  * @ctxt:  an XML parser context
  *
- * Parse a content sequence. Stops at EOF or '</'.
- *
- * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
+ * Parse XML element content. This is useful if you're only interested
+ * in custom SAX callbacks. If you want a node list, use
+ * xmlParseInNodeContext.
  */
-
 void
 xmlParseContent(xmlParserCtxtPtr ctxt) {
-    int nameNr = ctxt->nameNr;
+    if ((ctxt == NULL) || (ctxt->input == NULL))
+        return;
+
+    xmlCtxtInitializeLate(ctxt);
 
     xmlParseContentInternal(ctxt);
 
-    if ((ctxt->instate != XML_PARSER_EOF) && (ctxt->nameNr > nameNr)) {
-        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
-        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
-        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
-                "Premature end of data in tag %s line %d\n",
-		name, line, NULL);
-    }
+    if (ctxt->input->cur < ctxt->input->end)
+	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 }
 
 /**
  * xmlParseElement:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an XML element
  *
  * [39] element ::= EmptyElemTag | STag content ETag
@@ -9980,15 +9813,15 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
         return;
 
     xmlParseContentInternal(ctxt);
-    if (ctxt->instate == XML_PARSER_EOF)
-	return;
 
-    if (CUR == 0) {
-        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
-        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
-        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
-                "Premature end of data in tag %s line %d\n",
-		name, line, NULL);
+    if (ctxt->input->cur >= ctxt->input->end) {
+        if (ctxt->wellFormed) {
+            const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
+            int line = ctxt->pushTab[ctxt->nameNr - 1].line;
+            xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
+                    "Premature end of data in tag %s line %d\n",
+                    name, line, NULL);
+        }
         return;
     }
 
@@ -10001,22 +9834,24 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
  *
  * Parse the start of an XML element. Returns -1 in case of error, 0 if an
  * opening tag was parsed, 1 if an empty element was parsed.
+ *
+ * Always consumes '<'.
  */
 static int
 xmlParseElementStart(xmlParserCtxtPtr ctxt) {
+    int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 2048 : 256;
     const xmlChar *name;
     const xmlChar *prefix = NULL;
     const xmlChar *URI = NULL;
     xmlParserNodeInfo node_info;
-    int line, tlen = 0;
-    xmlNodePtr ret;
-    int nsNr = ctxt->nsNr;
+    int line;
+    xmlNodePtr cur;
+    int nbNs = 0;
 
-    if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
-        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-	xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
-		 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
-			  xmlParserMaxDepth);
+    if (ctxt->nameNr > maxDepth) {
+        xmlFatalErrMsgInt(ctxt, XML_ERR_RESOURCE_LIMIT,
+                "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
+                ctxt->nameNr);
 	xmlHaltParser(ctxt);
 	return(-1);
     }
@@ -10039,19 +9874,17 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) {
 #ifdef LIBXML_SAX1_ENABLED
     if (ctxt->sax2)
 #endif /* LIBXML_SAX1_ENABLED */
-        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
+        name = xmlParseStartTag2(ctxt, &prefix, &URI, &nbNs);
 #ifdef LIBXML_SAX1_ENABLED
     else
 	name = xmlParseStartTag(ctxt);
 #endif /* LIBXML_SAX1_ENABLED */
-    if (ctxt->instate == XML_PARSER_EOF)
-	return(-1);
     if (name == NULL) {
 	spacePop(ctxt);
         return(-1);
     }
-    nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
-    ret = ctxt->node;
+    nameNsPush(ctxt, name, prefix, URI, line, nbNs);
+    cur = ctxt->node;
 
 #ifdef LIBXML_VALID_ENABLED
     /*
@@ -10082,19 +9915,25 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) {
 	}
 	namePop(ctxt);
 	spacePop(ctxt);
-	if (nsNr != ctxt->nsNr)
-	    nsPop(ctxt, ctxt->nsNr - nsNr);
-	if ( ret != NULL && ctxt->record_info ) {
-	   node_info.end_pos = ctxt->input->consumed +
-			      (CUR_PTR - ctxt->input->base);
-	   node_info.end_line = ctxt->input->line;
-	   node_info.node = ret;
-	   xmlParserAddNodeInfo(ctxt, &node_info);
+	if (nbNs > 0)
+	    xmlParserNsPop(ctxt, nbNs);
+	if (cur != NULL && ctxt->record_info) {
+            node_info.node = cur;
+            node_info.end_pos = ctxt->input->consumed +
+                                (CUR_PTR - ctxt->input->base);
+            node_info.end_line = ctxt->input->line;
+            xmlParserAddNodeInfo(ctxt, &node_info);
 	}
 	return(1);
     }
     if (RAW == '>') {
         NEXT1;
+        if (cur != NULL && ctxt->record_info) {
+            node_info.node = cur;
+            node_info.end_pos = 0;
+            node_info.end_line = 0;
+            xmlParserAddNodeInfo(ctxt, &node_info);
+        }
     } else {
         xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
 		     "Couldn't find end of Start Tag %s line %d\n",
@@ -10106,19 +9945,8 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) {
 	nodePop(ctxt);
 	namePop(ctxt);
 	spacePop(ctxt);
-	if (nsNr != ctxt->nsNr)
-	    nsPop(ctxt, ctxt->nsNr - nsNr);
-
-	/*
-	 * Capture end position and add node
-	 */
-	if ( ret != NULL && ctxt->record_info ) {
-	   node_info.end_pos = ctxt->input->consumed +
-			      (CUR_PTR - ctxt->input->base);
-	   node_info.end_line = ctxt->input->line;
-	   node_info.node = ret;
-	   xmlParserAddNodeInfo(ctxt, &node_info);
-	}
+	if (nbNs > 0)
+	    xmlParserNsPop(ctxt, nbNs);
 	return(-1);
     }
 
@@ -10129,15 +9957,17 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) {
  * xmlParseElementEnd:
  * @ctxt:  an XML parser context
  *
- * Parse the end of an XML element.
+ * Parse the end of an XML element. Always consumes '</'.
  */
 static void
 xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
-    xmlParserNodeInfo node_info;
-    xmlNodePtr ret = ctxt->node;
+    xmlNodePtr cur = ctxt->node;
 
-    if (ctxt->nameNr <= 0)
+    if (ctxt->nameNr <= 0) {
+        if ((RAW == '<') && (NXT(1) == '/'))
+            SKIP(2);
         return;
+    }
 
     /*
      * parse the end of tag: '</' should be here.
@@ -10152,14 +9982,17 @@ xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
 #endif /* LIBXML_SAX1_ENABLED */
 
     /*
-     * Capture end position and add node
+     * Capture end position
      */
-    if ( ret != NULL && ctxt->record_info ) {
-       node_info.end_pos = ctxt->input->consumed +
-                          (CUR_PTR - ctxt->input->base);
-       node_info.end_line = ctxt->input->line;
-       node_info.node = ret;
-       xmlParserAddNodeInfo(ctxt, &node_info);
+    if (cur != NULL && ctxt->record_info) {
+        xmlParserNodeInfoPtr node_info;
+
+        node_info = (xmlParserNodeInfoPtr) xmlParserFindNodeInfo(ctxt, cur);
+        if (node_info != NULL) {
+            node_info->end_pos = ctxt->input->consumed +
+                                 (CUR_PTR - ctxt->input->base);
+            node_info->end_line = ctxt->input->line;
+        }
     }
 }
 
@@ -10167,6 +10000,8 @@ xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
  * xmlParseVersionNum:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse the XML version value.
  *
  * [26] VersionNum ::= '1.' [0-9]+
@@ -10182,9 +10017,9 @@ xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
     int size = 10;
     xmlChar cur;
 
-    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+    buf = (xmlChar *) xmlMallocAtomic(size);
     if (buf == NULL) {
-	xmlErrMemory(ctxt, NULL);
+	xmlErrMemory(ctxt);
 	return(NULL);
     }
     cur = CUR;
@@ -10207,10 +10042,10 @@ xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
 	    xmlChar *tmp;
 
 	    size *= 2;
-	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+	    tmp = (xmlChar *) xmlRealloc(buf, size);
 	    if (tmp == NULL) {
 	        xmlFree(buf);
-		xmlErrMemory(ctxt, NULL);
+		xmlErrMemory(ctxt);
 		return(NULL);
 	    }
 	    buf = tmp;
@@ -10227,6 +10062,8 @@ xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
  * xmlParseVersionInfo:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse the XML version.
  *
  * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
@@ -10274,6 +10111,8 @@ xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
  * xmlParseEncName:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse the XML encoding name
  *
  * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
@@ -10285,14 +10124,17 @@ xmlParseEncName(xmlParserCtxtPtr ctxt) {
     xmlChar *buf = NULL;
     int len = 0;
     int size = 10;
+    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                    XML_MAX_TEXT_LENGTH :
+                    XML_MAX_NAME_LENGTH;
     xmlChar cur;
 
     cur = CUR;
     if (((cur >= 'a') && (cur <= 'z')) ||
         ((cur >= 'A') && (cur <= 'Z'))) {
-	buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+	buf = (xmlChar *) xmlMallocAtomic(size);
 	if (buf == NULL) {
-	    xmlErrMemory(ctxt, NULL);
+	    xmlErrMemory(ctxt);
 	    return(NULL);
 	}
 
@@ -10308,22 +10150,22 @@ xmlParseEncName(xmlParserCtxtPtr ctxt) {
 	        xmlChar *tmp;
 
 		size *= 2;
-		tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+		tmp = (xmlChar *) xmlRealloc(buf, size);
 		if (tmp == NULL) {
-		    xmlErrMemory(ctxt, NULL);
+		    xmlErrMemory(ctxt);
 		    xmlFree(buf);
 		    return(NULL);
 		}
 		buf = tmp;
 	    }
 	    buf[len++] = cur;
+            if (len > maxLength) {
+                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "EncName");
+                xmlFree(buf);
+                return(NULL);
+            }
 	    NEXT;
 	    cur = CUR;
-	    if (cur == 0) {
-	        SHRINK;
-		GROW;
-		cur = CUR;
-	    }
         }
 	buf[len] = 0;
     } else {
@@ -10336,6 +10178,8 @@ xmlParseEncName(xmlParserCtxtPtr ctxt) {
  * xmlParseEncodingDecl:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse the XML encoding declaration
  *
  * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
@@ -10350,106 +10194,53 @@ xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
     xmlChar *encoding = NULL;
 
     SKIP_BLANKS;
-    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
-	SKIP(8);
-	SKIP_BLANKS;
-	if (RAW != '=') {
-	    xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
-	    return(NULL);
-        }
-	NEXT;
-	SKIP_BLANKS;
-	if (RAW == '"') {
-	    NEXT;
-	    encoding = xmlParseEncName(ctxt);
-	    if (RAW != '"') {
-		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
-		xmlFree((xmlChar *) encoding);
-		return(NULL);
-	    } else
-	        NEXT;
-	} else if (RAW == '\''){
-	    NEXT;
-	    encoding = xmlParseEncName(ctxt);
-	    if (RAW != '\'') {
-		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
-		xmlFree((xmlChar *) encoding);
-		return(NULL);
-	    } else
-	        NEXT;
-	} else {
-	    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
-	}
+    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g') == 0)
+        return(NULL);
 
-        /*
-         * Non standard parsing, allowing the user to ignore encoding
-         */
-        if (ctxt->options & XML_PARSE_IGNORE_ENC) {
-	    xmlFree((xmlChar *) encoding);
+    SKIP(8);
+    SKIP_BLANKS;
+    if (RAW != '=') {
+        xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
+        return(NULL);
+    }
+    NEXT;
+    SKIP_BLANKS;
+    if (RAW == '"') {
+        NEXT;
+        encoding = xmlParseEncName(ctxt);
+        if (RAW != '"') {
+            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+            xmlFree((xmlChar *) encoding);
             return(NULL);
-	}
-
-	/*
-	 * UTF-16 encoding switch has already taken place at this stage,
-	 * more over the little-endian/big-endian selection is already done
-	 */
-        if ((encoding != NULL) &&
-	    ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
-	     (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
-	    /*
-	     * If no encoding was passed to the parser, that we are
-	     * using UTF-16 and no decoder is present i.e. the
-	     * document is apparently UTF-8 compatible, then raise an
-	     * encoding mismatch fatal error
-	     */
-	    if ((ctxt->encoding == NULL) &&
-	        (ctxt->input->buf != NULL) &&
-	        (ctxt->input->buf->encoder == NULL)) {
-		xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
-		  "Document labelled UTF-16 but has UTF-8 content\n");
-	    }
-	    if (ctxt->encoding != NULL)
-		xmlFree((xmlChar *) ctxt->encoding);
-	    ctxt->encoding = encoding;
-	}
-	/*
-	 * UTF-8 encoding is handled natively
-	 */
-        else if ((encoding != NULL) &&
-	    ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
-	     (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
-	    if (ctxt->encoding != NULL)
-		xmlFree((xmlChar *) ctxt->encoding);
-	    ctxt->encoding = encoding;
-	}
-	else if (encoding != NULL) {
-	    xmlCharEncodingHandlerPtr handler;
-
-	    if (ctxt->input->encoding != NULL)
-		xmlFree((xmlChar *) ctxt->input->encoding);
-	    ctxt->input->encoding = encoding;
-
-            handler = xmlFindCharEncodingHandler((const char *) encoding);
-	    if (handler != NULL) {
-		if (xmlSwitchToEncoding(ctxt, handler) < 0) {
-		    /* failed to convert */
-		    ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
-		    return(NULL);
-		}
-	    } else {
-		xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
-			"Unsupported encoding %s\n", encoding);
-		return(NULL);
-	    }
-	}
+        } else
+            NEXT;
+    } else if (RAW == '\''){
+        NEXT;
+        encoding = xmlParseEncName(ctxt);
+        if (RAW != '\'') {
+            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+            xmlFree((xmlChar *) encoding);
+            return(NULL);
+        } else
+            NEXT;
+    } else {
+        xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
     }
-    return(encoding);
+
+    if (encoding == NULL)
+        return(NULL);
+
+    xmlSetDeclaredEncoding(ctxt, encoding);
+
+    return(ctxt->encoding);
 }
 
 /**
  * xmlParseSDDecl:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse the XML standalone declaration
  *
  * [32] SDDecl ::= S 'standalone' Eq
@@ -10534,6 +10325,8 @@ xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
  * xmlParseXMLDecl:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an XML declaration header
  *
  * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
@@ -10548,7 +10341,8 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
      * XML declaration but it does not have a standalone attribute.
      * It will be overwritten later if a standalone attribute is found.
      */
-    ctxt->input->standalone = -2;
+
+    ctxt->standalone = -2;
 
     /*
      * We know that '<?xml' is here.
@@ -10604,18 +10398,11 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
 	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
     }
     xmlParseEncodingDecl(ctxt);
-    if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
-         (ctxt->instate == XML_PARSER_EOF)) {
-	/*
-	 * The XML REC instructs us to stop parsing right here
-	 */
-        return;
-    }
 
     /*
      * We may have the standalone status.
      */
-    if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
+    if ((ctxt->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
         if ((RAW == '?') && (NXT(1) == '>')) {
 	    SKIP(2);
 	    return;
@@ -10629,7 +10416,7 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
     GROW;
 
     SKIP_BLANKS;
-    ctxt->input->standalone = xmlParseSDDecl(ctxt);
+    ctxt->standalone = xmlParseSDDecl(ctxt);
 
     SKIP_BLANKS;
     if ((RAW == '?') && (NXT(1) == '>')) {
@@ -10639,9 +10426,15 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
 	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 	NEXT;
     } else {
+        int c;
+
 	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
-	MOVETO_ENDTAG(CUR_PTR);
-	NEXT;
+        while ((PARSER_STOPPED(ctxt) == 0) &&
+               ((c = CUR) != 0)) {
+            NEXT;
+            if (c == '>')
+                break;
+        }
     }
 }
 
@@ -10649,6 +10442,8 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
  * xmlParseMisc:
  * @ctxt:  an XML parser context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * parse an XML Misc* optional field.
  *
  * [27] Misc ::= Comment | PI |  S
@@ -10656,7 +10451,7 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
 
 void
 xmlParseMisc(xmlParserCtxtPtr ctxt) {
-    while (ctxt->instate != XML_PARSER_EOF) {
+    while (PARSER_STOPPED(ctxt) == 0) {
         SKIP_BLANKS;
         GROW;
         if ((RAW == '<') && (NXT(1) == '?')) {
@@ -10669,28 +10464,52 @@ xmlParseMisc(xmlParserCtxtPtr ctxt) {
     }
 }
 
+static void
+xmlFinishDocument(xmlParserCtxtPtr ctxt) {
+    xmlDocPtr doc;
+
+    /*
+     * SAX: end of the document processing.
+     */
+    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
+        ctxt->sax->endDocument(ctxt->userData);
+
+    doc = ctxt->myDoc;
+    if (doc != NULL) {
+        if (ctxt->wellFormed) {
+            doc->properties |= XML_DOC_WELLFORMED;
+            if (ctxt->valid)
+                doc->properties |= XML_DOC_DTDVALID;
+            if (ctxt->nsWellFormed)
+                doc->properties |= XML_DOC_NSVALID;
+        }
+
+        if (ctxt->options & XML_PARSE_OLD10)
+            doc->properties |= XML_DOC_OLD10;
+
+        /*
+         * Remove locally kept entity definitions if the tree was not built
+         */
+	if (xmlStrEqual(doc->version, SAX_COMPAT_MODE)) {
+            xmlFreeDoc(doc);
+            ctxt->myDoc = NULL;
+        }
+    }
+}
+
 /**
  * xmlParseDocument:
  * @ctxt:  an XML parser context
  *
- * parse an XML document (and build a tree if using the standard SAX
- * interface).
- *
- * [1] document ::= prolog element Misc*
+ * Parse an XML document and invoke the SAX handlers. This is useful
+ * if you're only interested in custom SAX callbacks. If you want a
+ * document tree, use xmlCtxtParseDocument.
  *
- * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
- *
- * Returns 0, -1 in case of error. the parser context is augmented
- *                as a result of the parsing.
+ * Returns 0, -1 in case of error.
  */
 
 int
 xmlParseDocument(xmlParserCtxtPtr ctxt) {
-    xmlChar start[4];
-    xmlCharEncoding enc;
-
-    xmlInitParser();
-
     if ((ctxt == NULL) || (ctxt->input == NULL))
         return(-1);
 
@@ -10699,70 +10518,37 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
     /*
      * SAX: detecting the level.
      */
-    xmlDetectSAX2(ctxt);
-
-    /*
-     * SAX: beginning of the document processing.
-     */
-    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
-        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
-    if (ctxt->instate == XML_PARSER_EOF)
-	return(-1);
+    xmlCtxtInitializeLate(ctxt);
 
-    if ((ctxt->encoding == NULL) &&
-        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
-	/*
-	 * Get the 4 first bytes and decode the charset
-	 * if enc != XML_CHAR_ENCODING_NONE
-	 * plug some encoding conversion routines.
-	 */
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(&start[0], 4);
-	if (enc != XML_CHAR_ENCODING_NONE) {
-	    xmlSwitchEncoding(ctxt, enc);
-	}
+    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) {
+        ctxt->sax->setDocumentLocator(ctxt->userData,
+                (xmlSAXLocator *) &xmlDefaultSAXLocator);
     }
 
+    xmlDetectEncoding(ctxt);
 
     if (CUR == 0) {
 	xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 	return(-1);
     }
 
-    /*
-     * Check for the XMLDecl in the Prolog.
-     * do not GROW here to avoid the detected encoder to decode more
-     * than just the first line, unless the amount of data is really
-     * too small to hold "<?xml version="1.0" encoding="foo"
-     */
-    if ((ctxt->input->end - ctxt->input->cur) < 35) {
-       GROW;
-    }
+    GROW;
     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
 	/*
 	 * Note that we will switch encoding on the fly.
 	 */
 	xmlParseXMLDecl(ctxt);
-	if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
-	    (ctxt->instate == XML_PARSER_EOF)) {
-	    /*
-	     * The XML REC instructs us to stop parsing right here
-	     */
-	    return(-1);
-	}
-	ctxt->standalone = ctxt->input->standalone;
 	SKIP_BLANKS;
     } else {
 	ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
+        if (ctxt->version == NULL) {
+            xmlErrMemory(ctxt);
+            return(-1);
+        }
     }
     if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
         ctxt->sax->startDocument(ctxt->userData);
-    if (ctxt->instate == XML_PARSER_EOF)
-	return(-1);
     if ((ctxt->myDoc != NULL) && (ctxt->input != NULL) &&
         (ctxt->input->buf != NULL) && (ctxt->input->buf->compressed >= 0)) {
 	ctxt->myDoc->compression = ctxt->input->buf->compressed;
@@ -10783,10 +10569,7 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
 	ctxt->inSubset = 1;
 	xmlParseDocTypeDecl(ctxt);
 	if (RAW == '[') {
-	    ctxt->instate = XML_PARSER_DTD;
 	    xmlParseInternalSubset(ctxt);
-	    if (ctxt->instate == XML_PARSER_EOF)
-		return(-1);
 	}
 
 	/*
@@ -10797,13 +10580,10 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
 	    (!ctxt->disableSAX))
 	    ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
 	                              ctxt->extSubSystem, ctxt->extSubURI);
-	if (ctxt->instate == XML_PARSER_EOF)
-	    return(-1);
 	ctxt->inSubset = 0;
 
         xmlCleanSpecialAttr(ctxt);
 
-	ctxt->instate = XML_PARSER_PROLOG;
 	xmlParseMisc(ctxt);
     }
 
@@ -10812,53 +10592,37 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
      */
     GROW;
     if (RAW != '<') {
-	xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
-		       "Start tag expected, '<' not found\n");
+        if (ctxt->wellFormed)
+            xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
+                           "Start tag expected, '<' not found\n");
     } else {
-	ctxt->instate = XML_PARSER_CONTENT;
 	xmlParseElement(ctxt);
-	ctxt->instate = XML_PARSER_EPILOG;
-
 
 	/*
 	 * The Misc part at the end
 	 */
 	xmlParseMisc(ctxt);
 
-	if (RAW != 0) {
-	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
-	}
-	ctxt->instate = XML_PARSER_EOF;
+        if (ctxt->input->cur < ctxt->input->end) {
+            if (ctxt->wellFormed)
+	        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
+        } else if ((ctxt->input->buf != NULL) &&
+                   (ctxt->input->buf->encoder != NULL) &&
+                   (ctxt->input->buf->error == 0) &&
+                   (!xmlBufIsEmpty(ctxt->input->buf->raw))) {
+            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
+                           "Truncated multi-byte sequence at EOF\n");
+        }
     }
 
-    /*
-     * SAX: end of the document processing.
-     */
-    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
-        ctxt->sax->endDocument(ctxt->userData);
-
-    /*
-     * Remove locally kept entity definitions if the tree was not built
-     */
-    if ((ctxt->myDoc != NULL) &&
-	(xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
-	xmlFreeDoc(ctxt->myDoc);
-	ctxt->myDoc = NULL;
-    }
+    ctxt->instate = XML_PARSER_EOF;
+    xmlFinishDocument(ctxt);
 
-    if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
-        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
-	if (ctxt->valid)
-	    ctxt->myDoc->properties |= XML_DOC_DTDVALID;
-	if (ctxt->nsWellFormed)
-	    ctxt->myDoc->properties |= XML_DOC_NSVALID;
-	if (ctxt->options & XML_PARSE_OLD10)
-	    ctxt->myDoc->properties |= XML_DOC_OLD10;
-    }
     if (! ctxt->wellFormed) {
 	ctxt->valid = 0;
 	return(-1);
     }
+
     return(0);
 }
 
@@ -10878,38 +10642,17 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
 
 int
 xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
-    xmlChar start[4];
-    xmlCharEncoding enc;
-
     if ((ctxt == NULL) || (ctxt->input == NULL))
         return(-1);
 
-    xmlDetectSAX2(ctxt);
-
-    GROW;
-
-    /*
-     * SAX: beginning of the document processing.
-     */
-    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
-        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
+    xmlCtxtInitializeLate(ctxt);
 
-    /*
-     * Get the 4 first bytes and decode the charset
-     * if enc != XML_CHAR_ENCODING_NONE
-     * plug some encoding conversion routines.
-     */
-    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(start, 4);
-	if (enc != XML_CHAR_ENCODING_NONE) {
-	    xmlSwitchEncoding(ctxt, enc);
-	}
+    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) {
+        ctxt->sax->setDocumentLocator(ctxt->userData,
+                (xmlSAXLocator *) &xmlDefaultSAXLocator);
     }
 
+    xmlDetectEncoding(ctxt);
 
     if (CUR == 0) {
 	xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
@@ -10925,193 +10668,300 @@ xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
 	 * Note that we will switch encoding on the fly.
 	 */
 	xmlParseXMLDecl(ctxt);
-	if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
-	    /*
-	     * The XML REC instructs us to stop parsing right here
-	     */
-	    return(-1);
-	}
 	SKIP_BLANKS;
     } else {
 	ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
     }
     if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
         ctxt->sax->startDocument(ctxt->userData);
-    if (ctxt->instate == XML_PARSER_EOF)
-	return(-1);
 
     /*
      * Doing validity checking on chunk doesn't make sense
      */
-    ctxt->instate = XML_PARSER_CONTENT;
+    ctxt->options &= ~XML_PARSE_DTDVALID;
     ctxt->validate = 0;
-    ctxt->loadsubset = 0;
     ctxt->depth = 0;
 
-    xmlParseContent(ctxt);
-    if (ctxt->instate == XML_PARSER_EOF)
-	return(-1);
+    xmlParseContentInternal(ctxt);
 
-    if ((RAW == '<') && (NXT(1) == '/')) {
+    if (ctxt->input->cur < ctxt->input->end)
 	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
-    } else if (RAW != 0) {
-	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
+
+    /*
+     * SAX: end of the document processing.
+     */
+    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
+        ctxt->sax->endDocument(ctxt->userData);
+
+    if (! ctxt->wellFormed) return(-1);
+    return(0);
+}
+
+#ifdef LIBXML_PUSH_ENABLED
+/************************************************************************
+ *									*
+ *		Progressive parsing interfaces				*
+ *									*
+ ************************************************************************/
+
+/**
+ * xmlParseLookupChar:
+ * @ctxt:  an XML parser context
+ * @c:  character
+ *
+ * Check whether the input buffer contains a character.
+ */
+static int
+xmlParseLookupChar(xmlParserCtxtPtr ctxt, int c) {
+    const xmlChar *cur;
+
+    if (ctxt->checkIndex == 0) {
+        cur = ctxt->input->cur + 1;
+    } else {
+        cur = ctxt->input->cur + ctxt->checkIndex;
+    }
+
+    if (memchr(cur, c, ctxt->input->end - cur) == NULL) {
+        size_t index = ctxt->input->end - ctxt->input->cur;
+
+        if (index > LONG_MAX) {
+            ctxt->checkIndex = 0;
+            return(1);
+        }
+        ctxt->checkIndex = index;
+        return(0);
+    } else {
+        ctxt->checkIndex = 0;
+        return(1);
+    }
+}
+
+/**
+ * xmlParseLookupString:
+ * @ctxt:  an XML parser context
+ * @startDelta: delta to apply at the start
+ * @str:  string
+ * @strLen:  length of string
+ *
+ * Check whether the input buffer contains a string.
+ */
+static const xmlChar *
+xmlParseLookupString(xmlParserCtxtPtr ctxt, size_t startDelta,
+                     const char *str, size_t strLen) {
+    const xmlChar *cur, *term;
+
+    if (ctxt->checkIndex == 0) {
+        cur = ctxt->input->cur + startDelta;
+    } else {
+        cur = ctxt->input->cur + ctxt->checkIndex;
+    }
+
+    term = BAD_CAST strstr((const char *) cur, str);
+    if (term == NULL) {
+        const xmlChar *end = ctxt->input->end;
+        size_t index;
+
+        /* Rescan (strLen - 1) characters. */
+        if ((size_t) (end - cur) < strLen)
+            end = cur;
+        else
+            end -= strLen - 1;
+        index = end - ctxt->input->cur;
+        if (index > LONG_MAX) {
+            ctxt->checkIndex = 0;
+            return(ctxt->input->end - strLen);
+        }
+        ctxt->checkIndex = index;
+    } else {
+        ctxt->checkIndex = 0;
+    }
+
+    return(term);
+}
+
+/**
+ * xmlParseLookupCharData:
+ * @ctxt:  an XML parser context
+ *
+ * Check whether the input buffer contains terminated char data.
+ */
+static int
+xmlParseLookupCharData(xmlParserCtxtPtr ctxt) {
+    const xmlChar *cur = ctxt->input->cur + ctxt->checkIndex;
+    const xmlChar *end = ctxt->input->end;
+    size_t index;
+
+    while (cur < end) {
+        if ((*cur == '<') || (*cur == '&')) {
+            ctxt->checkIndex = 0;
+            return(1);
+        }
+        cur++;
     }
 
-    /*
-     * SAX: end of the document processing.
-     */
-    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
-        ctxt->sax->endDocument(ctxt->userData);
-
-    if (! ctxt->wellFormed) return(-1);
+    index = cur - ctxt->input->cur;
+    if (index > LONG_MAX) {
+        ctxt->checkIndex = 0;
+        return(1);
+    }
+    ctxt->checkIndex = index;
     return(0);
 }
 
-#ifdef LIBXML_PUSH_ENABLED
-/************************************************************************
- *									*
- *		Progressive parsing interfaces				*
- *									*
- ************************************************************************/
-
 /**
- * xmlParseLookupSequence:
+ * xmlParseLookupGt:
  * @ctxt:  an XML parser context
- * @first:  the first char to lookup
- * @next:  the next char to lookup or zero
- * @third:  the next char to lookup or zero
- *
- * Try to find if a sequence (first, next, third) or  just (first next) or
- * (first) is available in the input stream.
- * This function has a side effect of (possibly) incrementing ctxt->checkIndex
- * to avoid rescanning sequences of bytes, it DOES change the state of the
- * parser, do not use liberally.
  *
- * Returns the index to the current parsing point if the full sequence
- *      is available, -1 otherwise.
+ * Check whether there's enough data in the input buffer to finish parsing
+ * a start tag. This has to take quotes into account.
  */
 static int
-xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
-                       xmlChar next, xmlChar third) {
-    int base, len;
-    xmlParserInputPtr in;
-    const xmlChar *buf;
-
-    in = ctxt->input;
-    if (in == NULL) return(-1);
-    base = in->cur - in->base;
-    if (base < 0) return(-1);
-    if (ctxt->checkIndex > base)
-        base = ctxt->checkIndex;
-    if (in->buf == NULL) {
-	buf = in->base;
-	len = in->length;
-    } else {
-	buf = xmlBufContent(in->buf->buffer);
-	len = xmlBufUse(in->buf->buffer);
-    }
-    /* take into account the sequence length */
-    if (third) len -= 2;
-    else if (next) len --;
-    for (;base < len;base++) {
-        if (buf[base] == first) {
-	    if (third != 0) {
-		if ((buf[base + 1] != next) ||
-		    (buf[base + 2] != third)) continue;
-	    } else if (next != 0) {
-		if (buf[base + 1] != next) continue;
-	    }
-	    ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-	    if (next == 0)
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: lookup '%c' found at %d\n",
-			first, base);
-	    else if (third == 0)
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: lookup '%c%c' found at %d\n",
-			first, next, base);
-	    else
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: lookup '%c%c%c' found at %d\n",
-			first, next, third, base);
-#endif
-	    return(base - (in->cur - in->base));
-	}
-    }
-    ctxt->checkIndex = base;
-#ifdef DEBUG_PUSH
-    if (next == 0)
-	xmlGenericError(xmlGenericErrorContext,
-		"PP: lookup '%c' failed\n", first);
-    else if (third == 0)
-	xmlGenericError(xmlGenericErrorContext,
-		"PP: lookup '%c%c' failed\n", first, next);
+xmlParseLookupGt(xmlParserCtxtPtr ctxt) {
+    const xmlChar *cur;
+    const xmlChar *end = ctxt->input->end;
+    int state = ctxt->endCheckState;
+    size_t index;
+
+    if (ctxt->checkIndex == 0)
+        cur = ctxt->input->cur + 1;
     else
-	xmlGenericError(xmlGenericErrorContext,
-		"PP: lookup '%c%c%c' failed\n", first, next, third);
-#endif
-    return(-1);
+        cur = ctxt->input->cur + ctxt->checkIndex;
+
+    while (cur < end) {
+        if (state) {
+            if (*cur == state)
+                state = 0;
+        } else if (*cur == '\'' || *cur == '"') {
+            state = *cur;
+        } else if (*cur == '>') {
+            ctxt->checkIndex = 0;
+            ctxt->endCheckState = 0;
+            return(1);
+        }
+        cur++;
+    }
+
+    index = cur - ctxt->input->cur;
+    if (index > LONG_MAX) {
+        ctxt->checkIndex = 0;
+        ctxt->endCheckState = 0;
+        return(1);
+    }
+    ctxt->checkIndex = index;
+    ctxt->endCheckState = state;
+    return(0);
 }
 
 /**
- * xmlParseGetLasts:
+ * xmlParseLookupInternalSubset:
  * @ctxt:  an XML parser context
- * @lastlt:  pointer to store the last '<' from the input
- * @lastgt:  pointer to store the last '>' from the input
  *
- * Lookup the last < and > in the current chunk
+ * Check whether there's enough data in the input buffer to finish parsing
+ * the internal subset.
  */
-static void
-xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
-                 const xmlChar **lastgt) {
-    const xmlChar *tmp;
+static int
+xmlParseLookupInternalSubset(xmlParserCtxtPtr ctxt) {
+    /*
+     * Sorry, but progressive parsing of the internal subset is not
+     * supported. We first check that the full content of the internal
+     * subset is available and parsing is launched only at that point.
+     * Internal subset ends with "']' S? '>'" in an unescaped section and
+     * not in a ']]>' sequence which are conditional sections.
+     */
+    const xmlChar *cur, *start;
+    const xmlChar *end = ctxt->input->end;
+    int state = ctxt->endCheckState;
+    size_t index;
 
-    if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
-	xmlGenericError(xmlGenericErrorContext,
-		    "Internal error: xmlParseGetLasts\n");
-	return;
-    }
-    if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
-        tmp = ctxt->input->end;
-	tmp--;
-	while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
-	if (tmp < ctxt->input->base) {
-	    *lastlt = NULL;
-	    *lastgt = NULL;
-	} else {
-	    *lastlt = tmp;
-	    tmp++;
-	    while ((tmp < ctxt->input->end) && (*tmp != '>')) {
-	        if (*tmp == '\'') {
-		    tmp++;
-		    while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
-		    if (tmp < ctxt->input->end) tmp++;
-		} else if (*tmp == '"') {
-		    tmp++;
-		    while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
-		    if (tmp < ctxt->input->end) tmp++;
-		} else
-		    tmp++;
-	    }
-	    if (tmp < ctxt->input->end)
-	        *lastgt = tmp;
-	    else {
-	        tmp = *lastlt;
-		tmp--;
-		while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
-		if (tmp >= ctxt->input->base)
-		    *lastgt = tmp;
-		else
-		    *lastgt = NULL;
-	    }
-	}
+    if (ctxt->checkIndex == 0) {
+        cur = ctxt->input->cur + 1;
     } else {
-        *lastlt = NULL;
-	*lastgt = NULL;
+        cur = ctxt->input->cur + ctxt->checkIndex;
+    }
+    start = cur;
+
+    while (cur < end) {
+        if (state == '-') {
+            if ((*cur == '-') &&
+                (cur[1] == '-') &&
+                (cur[2] == '>')) {
+                state = 0;
+                cur += 3;
+                start = cur;
+                continue;
+            }
+        }
+        else if (state == ']') {
+            if (*cur == '>') {
+                ctxt->checkIndex = 0;
+                ctxt->endCheckState = 0;
+                return(1);
+            }
+            if (IS_BLANK_CH(*cur)) {
+                state = ' ';
+            } else if (*cur != ']') {
+                state = 0;
+                start = cur;
+                continue;
+            }
+        }
+        else if (state == ' ') {
+            if (*cur == '>') {
+                ctxt->checkIndex = 0;
+                ctxt->endCheckState = 0;
+                return(1);
+            }
+            if (!IS_BLANK_CH(*cur)) {
+                state = 0;
+                start = cur;
+                continue;
+            }
+        }
+        else if (state != 0) {
+            if (*cur == state) {
+                state = 0;
+                start = cur + 1;
+            }
+        }
+        else if (*cur == '<') {
+            if ((cur[1] == '!') &&
+                (cur[2] == '-') &&
+                (cur[3] == '-')) {
+                state = '-';
+                cur += 4;
+                /* Don't treat <!--> as comment */
+                start = cur;
+                continue;
+            }
+        }
+        else if ((*cur == '"') || (*cur == '\'') || (*cur == ']')) {
+            state = *cur;
+        }
+
+        cur++;
     }
+
+    /*
+     * Rescan the three last characters to detect "<!--" and "-->"
+     * split across chunks.
+     */
+    if ((state == 0) || (state == '-')) {
+        if (cur - start < 3)
+            cur = start;
+        else
+            cur -= 3;
+    }
+    index = cur - ctxt->input->cur;
+    if (index > LONG_MAX) {
+        ctxt->checkIndex = 0;
+        ctxt->endCheckState = 0;
+        return(1);
+    }
+    ctxt->checkIndex = index;
+    ctxt->endCheckState = state;
+    return(0);
 }
+
 /**
  * xmlCheckCdataPush:
  * @cur: pointer to the block of characters
@@ -11192,103 +11042,19 @@ xmlCheckCdataPush(const xmlChar *utf, int len, int complete) {
 static int
 xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
     int ret = 0;
-    int avail, tlen;
+    size_t avail;
     xmlChar cur, next;
-    const xmlChar *lastlt, *lastgt;
 
     if (ctxt->input == NULL)
         return(0);
 
-#ifdef DEBUG_PUSH
-    switch (ctxt->instate) {
-	case XML_PARSER_EOF:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try EOF\n"); break;
-	case XML_PARSER_START:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try START\n"); break;
-	case XML_PARSER_MISC:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try MISC\n");break;
-	case XML_PARSER_COMMENT:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try COMMENT\n");break;
-	case XML_PARSER_PROLOG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try PROLOG\n");break;
-	case XML_PARSER_START_TAG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try START_TAG\n");break;
-	case XML_PARSER_CONTENT:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try CONTENT\n");break;
-	case XML_PARSER_CDATA_SECTION:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try CDATA_SECTION\n");break;
-	case XML_PARSER_END_TAG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try END_TAG\n");break;
-	case XML_PARSER_ENTITY_DECL:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try ENTITY_DECL\n");break;
-	case XML_PARSER_ENTITY_VALUE:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try ENTITY_VALUE\n");break;
-	case XML_PARSER_ATTRIBUTE_VALUE:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try ATTRIBUTE_VALUE\n");break;
-	case XML_PARSER_DTD:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try DTD\n");break;
-	case XML_PARSER_EPILOG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try EPILOG\n");break;
-	case XML_PARSER_PI:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try PI\n");break;
-        case XML_PARSER_IGNORE:
-            xmlGenericError(xmlGenericErrorContext,
-		    "PP: try IGNORE\n");break;
-    }
-#endif
-
     if ((ctxt->input != NULL) &&
         (ctxt->input->cur - ctxt->input->base > 4096)) {
-	xmlSHRINK(ctxt);
-	ctxt->checkIndex = 0;
+        xmlParserShrink(ctxt);
     }
-    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
-
-    while (ctxt->instate != XML_PARSER_EOF) {
-	if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
-	    return(0);
 
-	if (ctxt->input == NULL) break;
-	if (ctxt->input->buf == NULL)
-	    avail = ctxt->input->length -
-	            (ctxt->input->cur - ctxt->input->base);
-	else {
-	    /*
-	     * If we are operating on converted input, try to flush
-	     * remaining chars to avoid them stalling in the non-converted
-	     * buffer. But do not do this in document start where
-	     * encoding="..." may not have been read and we work on a
-	     * guessed encoding.
-	     */
-	    if ((ctxt->instate != XML_PARSER_START) &&
-	        (ctxt->input->buf->raw != NULL) &&
-		(xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) {
-                size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
-                                                 ctxt->input);
-		size_t current = ctxt->input->cur - ctxt->input->base;
-
-		xmlParserInputBufferPush(ctxt->input->buf, 0, "");
-                xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
-                                      base, current);
-	    }
-	    avail = xmlBufUse(ctxt->input->buf->buffer) -
-		    (ctxt->input->cur - ctxt->input->base);
-	}
+    while (ctxt->disableSAX == 0) {
+        avail = ctxt->input->end - ctxt->input->cur;
         if (avail < 1)
 	    goto done;
         switch (ctxt->instate) {
@@ -11298,145 +11064,82 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 		 */
 	        goto done;
             case XML_PARSER_START:
-		if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
-		    xmlChar start[4];
-		    xmlCharEncoding enc;
+                /*
+                 * Very first chars read from the document flow.
+                 */
+                if ((!terminate) && (avail < 4))
+                    goto done;
 
-		    /*
-		     * Very first chars read from the document flow.
-		     */
-		    if (avail < 4)
-			goto done;
+                /*
+                 * We need more bytes to detect EBCDIC code pages.
+                 * See xmlDetectEBCDIC.
+                 */
+                if ((CMP4(CUR_PTR, 0x4C, 0x6F, 0xA7, 0x94)) &&
+                    (!terminate) && (avail < 200))
+                    goto done;
 
-		    /*
-		     * Get the 4 first bytes and decode the charset
-		     * if enc != XML_CHAR_ENCODING_NONE
-		     * plug some encoding conversion routines,
-		     * else xmlSwitchEncoding will set to (default)
-		     * UTF8.
-		     */
-		    start[0] = RAW;
-		    start[1] = NXT(1);
-		    start[2] = NXT(2);
-		    start[3] = NXT(3);
-		    enc = xmlDetectCharEncoding(start, 4);
-		    xmlSwitchEncoding(ctxt, enc);
-		    break;
-		}
+                xmlDetectEncoding(ctxt);
+                ctxt->instate = XML_PARSER_XML_DECL;
+		break;
 
-		if (avail < 2)
+            case XML_PARSER_XML_DECL:
+		if ((!terminate) && (avail < 2))
 		    goto done;
 		cur = ctxt->input->cur[0];
 		next = ctxt->input->cur[1];
-		if (cur == 0) {
-		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
-			ctxt->sax->setDocumentLocator(ctxt->userData,
-						      &xmlDefaultSAXLocator);
-		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
-		    xmlHaltParser(ctxt);
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering EOF\n");
-#endif
-		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
-			ctxt->sax->endDocument(ctxt->userData);
-		    goto done;
-		}
 	        if ((cur == '<') && (next == '?')) {
 		    /* PI or XML decl */
-		    if (avail < 5) return(ret);
 		    if ((!terminate) &&
-		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
-			return(ret);
-		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
-			ctxt->sax->setDocumentLocator(ctxt->userData,
-						      &xmlDefaultSAXLocator);
+                        (!xmlParseLookupString(ctxt, 2, "?>", 2)))
+			goto done;
 		    if ((ctxt->input->cur[2] == 'x') &&
 			(ctxt->input->cur[3] == 'm') &&
 			(ctxt->input->cur[4] == 'l') &&
 			(IS_BLANK_CH(ctxt->input->cur[5]))) {
 			ret += 5;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"PP: Parsing XML Decl\n");
-#endif
 			xmlParseXMLDecl(ctxt);
-			if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
-			    /*
-			     * The XML REC instructs us to stop parsing right
-			     * here
-			     */
-			    xmlHaltParser(ctxt);
-			    return(0);
-			}
-			ctxt->standalone = ctxt->input->standalone;
-			if ((ctxt->encoding == NULL) &&
-			    (ctxt->input->encoding != NULL))
-			    ctxt->encoding = xmlStrdup(ctxt->input->encoding);
-			if ((ctxt->sax) && (ctxt->sax->startDocument) &&
-			    (!ctxt->disableSAX))
-			    ctxt->sax->startDocument(ctxt->userData);
-			ctxt->instate = XML_PARSER_MISC;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"PP: entering MISC\n");
-#endif
 		    } else {
 			ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
-			if ((ctxt->sax) && (ctxt->sax->startDocument) &&
-			    (!ctxt->disableSAX))
-			    ctxt->sax->startDocument(ctxt->userData);
-			ctxt->instate = XML_PARSER_MISC;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"PP: entering MISC\n");
-#endif
+                        if (ctxt->version == NULL) {
+                            xmlErrMemory(ctxt);
+                            break;
+                        }
 		    }
 		} else {
-		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
-			ctxt->sax->setDocumentLocator(ctxt->userData,
-						      &xmlDefaultSAXLocator);
 		    ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 		    if (ctxt->version == NULL) {
-		        xmlErrMemory(ctxt, NULL);
+		        xmlErrMemory(ctxt);
 			break;
 		    }
-		    if ((ctxt->sax) && (ctxt->sax->startDocument) &&
-		        (!ctxt->disableSAX))
-			ctxt->sax->startDocument(ctxt->userData);
-		    ctxt->instate = XML_PARSER_MISC;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering MISC\n");
-#endif
 		}
+                if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) {
+                    ctxt->sax->setDocumentLocator(ctxt->userData,
+                            (xmlSAXLocator *) &xmlDefaultSAXLocator);
+                }
+                if ((ctxt->sax) && (ctxt->sax->startDocument) &&
+                    (!ctxt->disableSAX))
+                    ctxt->sax->startDocument(ctxt->userData);
+                ctxt->instate = XML_PARSER_MISC;
 		break;
             case XML_PARSER_START_TAG: {
 	        const xmlChar *name;
 		const xmlChar *prefix = NULL;
 		const xmlChar *URI = NULL;
                 int line = ctxt->input->line;
-		int nsNr = ctxt->nsNr;
+		int nbNs = 0;
 
-		if ((avail < 2) && (ctxt->inputNr == 1))
+		if ((!terminate) && (avail < 2))
 		    goto done;
 		cur = ctxt->input->cur[0];
 	        if (cur != '<') {
-		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
-		    xmlHaltParser(ctxt);
-		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
-			ctxt->sax->endDocument(ctxt->userData);
+		    xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
+                                   "Start tag expected, '<' not found");
+                    ctxt->instate = XML_PARSER_EOF;
+                    xmlFinishDocument(ctxt);
 		    goto done;
 		}
-		if (!terminate) {
-		    if (ctxt->progressive) {
-		        /* > can be found unescaped in attribute values */
-		        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
-			    goto done;
-		    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
-			goto done;
-		    }
-		}
+		if ((!terminate) && (!xmlParseLookupGt(ctxt)))
+                    goto done;
 		if (ctxt->spaceNr == 0)
 		    spacePush(ctxt, -1);
 		else if (*ctxt->space == -2)
@@ -11446,18 +11149,15 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 #ifdef LIBXML_SAX1_ENABLED
 		if (ctxt->sax2)
 #endif /* LIBXML_SAX1_ENABLED */
-		    name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
+		    name = xmlParseStartTag2(ctxt, &prefix, &URI, &nbNs);
 #ifdef LIBXML_SAX1_ENABLED
 		else
 		    name = xmlParseStartTag(ctxt);
 #endif /* LIBXML_SAX1_ENABLED */
-		if (ctxt->instate == XML_PARSER_EOF)
-		    goto done;
 		if (name == NULL) {
 		    spacePop(ctxt);
-		    xmlHaltParser(ctxt);
-		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
-			ctxt->sax->endDocument(ctxt->userData);
+                    ctxt->instate = XML_PARSER_EOF;
+                    xmlFinishDocument(ctxt);
 		    goto done;
 		}
 #ifdef LIBXML_VALID_ENABLED
@@ -11483,8 +11183,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 			    (!ctxt->disableSAX))
 			    ctxt->sax->endElementNs(ctxt->userData, name,
 			                            prefix, URI);
-			if (ctxt->nsNr - nsNr > 0)
-			    nsPop(ctxt, ctxt->nsNr - nsNr);
+			if (nbNs > 0)
+			    xmlParserNsPop(ctxt, nbNs);
 #ifdef LIBXML_SAX1_ENABLED
 		    } else {
 			if ((ctxt->sax != NULL) &&
@@ -11493,93 +11193,81 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 			    ctxt->sax->endElement(ctxt->userData, name);
 #endif /* LIBXML_SAX1_ENABLED */
 		    }
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
 		    spacePop(ctxt);
-		    if (ctxt->nameNr == 0) {
-			ctxt->instate = XML_PARSER_EPILOG;
-		    } else {
-			ctxt->instate = XML_PARSER_CONTENT;
-		    }
-                    ctxt->progressive = 1;
-		    break;
-		}
-		if (RAW == '>') {
+		} else if (RAW == '>') {
 		    NEXT;
+                    nameNsPush(ctxt, name, prefix, URI, line, nbNs);
 		} else {
 		    xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
 					 "Couldn't find end of Start Tag %s\n",
 					 name);
 		    nodePop(ctxt);
 		    spacePop(ctxt);
+                    if (nbNs > 0)
+                        xmlParserNsPop(ctxt, nbNs);
 		}
-                nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
 
-		ctxt->instate = XML_PARSER_CONTENT;
-                ctxt->progressive = 1;
+                if (ctxt->nameNr == 0)
+                    ctxt->instate = XML_PARSER_EPILOG;
+                else
+                    ctxt->instate = XML_PARSER_CONTENT;
                 break;
 	    }
             case XML_PARSER_CONTENT: {
-		int id;
-		unsigned long cons;
-		if ((avail < 2) && (ctxt->inputNr == 1))
-		    goto done;
 		cur = ctxt->input->cur[0];
-		next = ctxt->input->cur[1];
 
-		id = ctxt->input->id;
-	        cons = CUR_CONSUMED;
-		if ((cur == '<') && (next == '/')) {
-		    ctxt->instate = XML_PARSER_END_TAG;
-		    break;
-	        } else if ((cur == '<') && (next == '?')) {
-		    if ((!terminate) &&
-		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
-                        ctxt->progressive = XML_PARSER_PI;
-			goto done;
-                    }
-		    xmlParsePI(ctxt);
-		    ctxt->instate = XML_PARSER_CONTENT;
-                    ctxt->progressive = 1;
-		} else if ((cur == '<') && (next != '!')) {
-		    ctxt->instate = XML_PARSER_START_TAG;
-		    break;
-		} else if ((cur == '<') && (next == '!') &&
-		           (ctxt->input->cur[2] == '-') &&
-			   (ctxt->input->cur[3] == '-')) {
-		    int term;
-
-	            if (avail < 4)
-		        goto done;
-		    ctxt->input->cur += 4;
-		    term = xmlParseLookupSequence(ctxt, '-', '-', '>');
-		    ctxt->input->cur -= 4;
-		    if ((!terminate) && (term < 0)) {
-                        ctxt->progressive = XML_PARSER_COMMENT;
-			goto done;
+		if (cur == '<') {
+                    if ((!terminate) && (avail < 2))
+                        goto done;
+		    next = ctxt->input->cur[1];
+
+                    if (next == '/') {
+                        ctxt->instate = XML_PARSER_END_TAG;
+                        break;
+                    } else if (next == '?') {
+                        if ((!terminate) &&
+                            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
+                            goto done;
+                        xmlParsePI(ctxt);
+                        ctxt->instate = XML_PARSER_CONTENT;
+                        break;
+                    } else if (next == '!') {
+                        if ((!terminate) && (avail < 3))
+                            goto done;
+                        next = ctxt->input->cur[2];
+
+                        if (next == '-') {
+                            if ((!terminate) && (avail < 4))
+                                goto done;
+                            if (ctxt->input->cur[3] == '-') {
+                                if ((!terminate) &&
+                                    (!xmlParseLookupString(ctxt, 4, "-->", 3)))
+                                    goto done;
+                                xmlParseComment(ctxt);
+                                ctxt->instate = XML_PARSER_CONTENT;
+                                break;
+                            }
+                        } else if (next == '[') {
+                            if ((!terminate) && (avail < 9))
+                                goto done;
+                            if ((ctxt->input->cur[2] == '[') &&
+                                (ctxt->input->cur[3] == 'C') &&
+                                (ctxt->input->cur[4] == 'D') &&
+                                (ctxt->input->cur[5] == 'A') &&
+                                (ctxt->input->cur[6] == 'T') &&
+                                (ctxt->input->cur[7] == 'A') &&
+                                (ctxt->input->cur[8] == '[')) {
+                                SKIP(9);
+                                ctxt->instate = XML_PARSER_CDATA_SECTION;
+                                break;
+                            }
+                        }
                     }
-		    xmlParseComment(ctxt);
-		    ctxt->instate = XML_PARSER_CONTENT;
-                    ctxt->progressive = 1;
-		} else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
-		    (ctxt->input->cur[2] == '[') &&
-		    (ctxt->input->cur[3] == 'C') &&
-		    (ctxt->input->cur[4] == 'D') &&
-		    (ctxt->input->cur[5] == 'A') &&
-		    (ctxt->input->cur[6] == 'T') &&
-		    (ctxt->input->cur[7] == 'A') &&
-		    (ctxt->input->cur[8] == '[')) {
-		    SKIP(9);
-		    ctxt->instate = XML_PARSER_CDATA_SECTION;
-		    break;
-		} else if ((cur == '<') && (next == '!') &&
-		           (avail < 9)) {
-		    goto done;
 		} else if (cur == '&') {
-		    if ((!terminate) &&
-		        (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
+		    if ((!terminate) && (!xmlParseLookupChar(ctxt, ';')))
 			goto done;
 		    xmlParseReference(ctxt);
+                    break;
 		} else {
 		    /* TODO Avoid the extra copy, handle directly !!! */
 		    /*
@@ -11593,42 +11281,21 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 		     *    callbacks between the push and pull versions
 		     *    of the parser.
 		     */
-		    if ((ctxt->inputNr == 1) &&
-		        (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
-			if (!terminate) {
-			    if (ctxt->progressive) {
-				if ((lastlt == NULL) ||
-				    (ctxt->input->cur > lastlt))
-				    goto done;
-			    } else if (xmlParseLookupSequence(ctxt,
-			                                      '<', 0, 0) < 0) {
-				goto done;
-			    }
-			}
+		    if (avail < XML_PARSER_BIG_BUFFER_SIZE) {
+			if ((!terminate) && (!xmlParseLookupCharData(ctxt)))
+			    goto done;
                     }
-		    ctxt->checkIndex = 0;
-		    xmlParseCharData(ctxt, 0);
-		}
-		if ((cons == CUR_CONSUMED) && (id == ctxt->input->id)) {
-		    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		                "detected an error in element content\n");
-		    xmlHaltParser(ctxt);
-		    break;
+                    ctxt->checkIndex = 0;
+		    xmlParseCharDataInternal(ctxt, !terminate);
+                    break;
 		}
+
+                ctxt->instate = XML_PARSER_START_TAG;
 		break;
 	    }
             case XML_PARSER_END_TAG:
-		if (avail < 2)
+		if ((!terminate) && (!xmlParseLookupChar(ctxt, '>')))
 		    goto done;
-		if (!terminate) {
-		    if (ctxt->progressive) {
-		        /* > can be found unescaped in attribute values */
-		        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
-			    goto done;
-		    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
-			goto done;
-		    }
-		}
 		if (ctxt->sax2) {
 	            xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
 		    nameNsPop(ctxt);
@@ -11637,9 +11304,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 		  else
 		    xmlParseEndTag1(ctxt, 0);
 #endif /* LIBXML_SAX1_ENABLED */
-		if (ctxt->instate == XML_PARSER_EOF) {
-		    /* Nothing */
-		} else if (ctxt->nameNr == 0) {
+		if (ctxt->nameNr == 0) {
 		    ctxt->instate = XML_PARSER_EPILOG;
 		} else {
 		    ctxt->instate = XML_PARSER_CONTENT;
@@ -11650,35 +11315,49 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 		 * The Push mode need to have the SAX callback for
 		 * cdataBlock merge back contiguous callbacks.
 		 */
-		int base;
-
-		base = xmlParseLookupSequence(ctxt, ']', ']', '>');
-		if (base < 0) {
-		    if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
-		        int tmp;
-
-			tmp = xmlCheckCdataPush(ctxt->input->cur,
-			                        XML_PARSER_BIG_BUFFER_SIZE, 0);
-			if (tmp < 0) {
-			    tmp = -tmp;
-			    ctxt->input->cur += tmp;
-			    goto encoding_error;
-			}
-			if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
-			    if (ctxt->sax->cdataBlock != NULL)
-				ctxt->sax->cdataBlock(ctxt->userData,
-				                      ctxt->input->cur, tmp);
-			    else if (ctxt->sax->characters != NULL)
-				ctxt->sax->characters(ctxt->userData,
-				                      ctxt->input->cur, tmp);
-			}
-			if (ctxt->instate == XML_PARSER_EOF)
-			    goto done;
-			SKIPL(tmp);
-			ctxt->checkIndex = 0;
-		    }
-		    goto done;
+		const xmlChar *term;
+
+                if (terminate) {
+                    /*
+                     * Don't call xmlParseLookupString. If 'terminate'
+                     * is set, checkIndex is invalid.
+                     */
+                    term = BAD_CAST strstr((const char *) ctxt->input->cur,
+                                           "]]>");
+                } else {
+		    term = xmlParseLookupString(ctxt, 0, "]]>", 3);
+                }
+
+		if (term == NULL) {
+		    int tmp, size;
+
+                    if (terminate) {
+                        /* Unfinished CDATA section */
+                        size = ctxt->input->end - ctxt->input->cur;
+                    } else {
+                        if (avail < XML_PARSER_BIG_BUFFER_SIZE + 2)
+                            goto done;
+                        ctxt->checkIndex = 0;
+                        /* XXX: Why don't we pass the full buffer? */
+                        size = XML_PARSER_BIG_BUFFER_SIZE;
+                    }
+                    tmp = xmlCheckCdataPush(ctxt->input->cur, size, 0);
+                    if (tmp <= 0) {
+                        tmp = -tmp;
+                        ctxt->input->cur += tmp;
+                        goto encoding_error;
+                    }
+                    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
+                        if (ctxt->sax->cdataBlock != NULL)
+                            ctxt->sax->cdataBlock(ctxt->userData,
+                                                  ctxt->input->cur, tmp);
+                        else if (ctxt->sax->characters != NULL)
+                            ctxt->sax->characters(ctxt->userData,
+                                                  ctxt->input->cur, tmp);
+                    }
+                    SKIPL(tmp);
 		} else {
+                    int base = term - CUR_PTR;
 		    int tmp;
 
 		    tmp = xmlCheckCdataPush(ctxt->input->cur, base, 1);
@@ -11709,352 +11388,94 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 			    ctxt->sax->characters(ctxt->userData,
 						  ctxt->input->cur, base);
 		    }
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
 		    SKIPL(base + 3);
-		    ctxt->checkIndex = 0;
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering CONTENT\n");
-#endif
 		}
 		break;
 	    }
             case XML_PARSER_MISC:
-		SKIP_BLANKS;
-		if (ctxt->input->buf == NULL)
-		    avail = ctxt->input->length -
-		            (ctxt->input->cur - ctxt->input->base);
-		else
-		    avail = xmlBufUse(ctxt->input->buf->buffer) -
-		            (ctxt->input->cur - ctxt->input->base);
-		if (avail < 2)
-		    goto done;
-		cur = ctxt->input->cur[0];
-		next = ctxt->input->cur[1];
-	        if ((cur == '<') && (next == '?')) {
-		    if ((!terminate) &&
-		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
-                        ctxt->progressive = XML_PARSER_PI;
-			goto done;
-                    }
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: Parsing PI\n");
-#endif
-		    xmlParsePI(ctxt);
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
-		    ctxt->instate = XML_PARSER_MISC;
-                    ctxt->progressive = 1;
-		    ctxt->checkIndex = 0;
-		} else if ((cur == '<') && (next == '!') &&
-		    (ctxt->input->cur[2] == '-') &&
-		    (ctxt->input->cur[3] == '-')) {
-		    if ((!terminate) &&
-		        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
-                        ctxt->progressive = XML_PARSER_COMMENT;
-			goto done;
-                    }
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: Parsing Comment\n");
-#endif
-		    xmlParseComment(ctxt);
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
-		    ctxt->instate = XML_PARSER_MISC;
-                    ctxt->progressive = 1;
-		    ctxt->checkIndex = 0;
-		} else if ((cur == '<') && (next == '!') &&
-		    (ctxt->input->cur[2] == 'D') &&
-		    (ctxt->input->cur[3] == 'O') &&
-		    (ctxt->input->cur[4] == 'C') &&
-		    (ctxt->input->cur[5] == 'T') &&
-		    (ctxt->input->cur[6] == 'Y') &&
-		    (ctxt->input->cur[7] == 'P') &&
-		    (ctxt->input->cur[8] == 'E')) {
-		    if ((!terminate) &&
-		        (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0)) {
-                        ctxt->progressive = XML_PARSER_DTD;
-			goto done;
-                    }
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: Parsing internal subset\n");
-#endif
-		    ctxt->inSubset = 1;
-                    ctxt->progressive = 0;
-		    ctxt->checkIndex = 0;
-		    xmlParseDocTypeDecl(ctxt);
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
-		    if (RAW == '[') {
-			ctxt->instate = XML_PARSER_DTD;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"PP: entering DTD\n");
-#endif
-		    } else {
-			/*
-			 * Create and update the external subset.
-			 */
-			ctxt->inSubset = 2;
-			if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
-			    (ctxt->sax->externalSubset != NULL))
-			    ctxt->sax->externalSubset(ctxt->userData,
-				    ctxt->intSubName, ctxt->extSubSystem,
-				    ctxt->extSubURI);
-			ctxt->inSubset = 0;
-			xmlCleanSpecialAttr(ctxt);
-			ctxt->instate = XML_PARSER_PROLOG;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"PP: entering PROLOG\n");
-#endif
-		    }
-		} else if ((cur == '<') && (next == '!') &&
-		           (avail < 9)) {
-		    goto done;
-		} else {
-		    ctxt->instate = XML_PARSER_START_TAG;
-		    ctxt->progressive = XML_PARSER_START_TAG;
-		    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering START_TAG\n");
-#endif
-		}
-		break;
-            case XML_PARSER_PROLOG:
-		SKIP_BLANKS;
-		if (ctxt->input->buf == NULL)
-		    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
-		else
-		    avail = xmlBufUse(ctxt->input->buf->buffer) -
-                            (ctxt->input->cur - ctxt->input->base);
-		if (avail < 2)
-		    goto done;
-		cur = ctxt->input->cur[0];
-		next = ctxt->input->cur[1];
-	        if ((cur == '<') && (next == '?')) {
-		    if ((!terminate) &&
-		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
-                        ctxt->progressive = XML_PARSER_PI;
-			goto done;
-                    }
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: Parsing PI\n");
-#endif
-		    xmlParsePI(ctxt);
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
-		    ctxt->instate = XML_PARSER_PROLOG;
-                    ctxt->progressive = 1;
-		} else if ((cur == '<') && (next == '!') &&
-		    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
-		    if ((!terminate) &&
-		        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
-                        ctxt->progressive = XML_PARSER_COMMENT;
-			goto done;
-                    }
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: Parsing Comment\n");
-#endif
-		    xmlParseComment(ctxt);
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
-		    ctxt->instate = XML_PARSER_PROLOG;
-                    ctxt->progressive = 1;
-		} else if ((cur == '<') && (next == '!') &&
-		           (avail < 4)) {
-		    goto done;
-		} else {
-		    ctxt->instate = XML_PARSER_START_TAG;
-		    if (ctxt->progressive == 0)
-			ctxt->progressive = XML_PARSER_START_TAG;
-		    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering START_TAG\n");
-#endif
-		}
-		break;
-            case XML_PARSER_EPILOG:
-		SKIP_BLANKS;
-		if (ctxt->input->buf == NULL)
-		    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
-		else
-		    avail = xmlBufUse(ctxt->input->buf->buffer) -
-                            (ctxt->input->cur - ctxt->input->base);
-		if (avail < 2)
-		    goto done;
-		cur = ctxt->input->cur[0];
-		next = ctxt->input->cur[1];
-	        if ((cur == '<') && (next == '?')) {
-		    if ((!terminate) &&
-		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
-                        ctxt->progressive = XML_PARSER_PI;
-			goto done;
-                    }
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: Parsing PI\n");
-#endif
-		    xmlParsePI(ctxt);
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
-		    ctxt->instate = XML_PARSER_EPILOG;
-                    ctxt->progressive = 1;
-		} else if ((cur == '<') && (next == '!') &&
-		    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
-		    if ((!terminate) &&
-		        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
-                        ctxt->progressive = XML_PARSER_COMMENT;
-			goto done;
-                    }
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: Parsing Comment\n");
-#endif
-		    xmlParseComment(ctxt);
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
-		    ctxt->instate = XML_PARSER_EPILOG;
-                    ctxt->progressive = 1;
-		} else if ((cur == '<') && (next == '!') &&
-		           (avail < 4)) {
-		    goto done;
-		} else {
-		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
-		    xmlHaltParser(ctxt);
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering EOF\n");
-#endif
-		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
-			ctxt->sax->endDocument(ctxt->userData);
+            case XML_PARSER_PROLOG:
+            case XML_PARSER_EPILOG:
+		SKIP_BLANKS;
+                avail = ctxt->input->end - ctxt->input->cur;
+		if (avail < 1)
 		    goto done;
+		if (ctxt->input->cur[0] == '<') {
+                    if ((!terminate) && (avail < 2))
+                        goto done;
+                    next = ctxt->input->cur[1];
+                    if (next == '?') {
+                        if ((!terminate) &&
+                            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
+                            goto done;
+                        xmlParsePI(ctxt);
+                        break;
+                    } else if (next == '!') {
+                        if ((!terminate) && (avail < 3))
+                            goto done;
+
+                        if (ctxt->input->cur[2] == '-') {
+                            if ((!terminate) && (avail < 4))
+                                goto done;
+                            if (ctxt->input->cur[3] == '-') {
+                                if ((!terminate) &&
+                                    (!xmlParseLookupString(ctxt, 4, "-->", 3)))
+                                    goto done;
+                                xmlParseComment(ctxt);
+                                break;
+                            }
+                        } else if (ctxt->instate == XML_PARSER_MISC) {
+                            if ((!terminate) && (avail < 9))
+                                goto done;
+                            if ((ctxt->input->cur[2] == 'D') &&
+                                (ctxt->input->cur[3] == 'O') &&
+                                (ctxt->input->cur[4] == 'C') &&
+                                (ctxt->input->cur[5] == 'T') &&
+                                (ctxt->input->cur[6] == 'Y') &&
+                                (ctxt->input->cur[7] == 'P') &&
+                                (ctxt->input->cur[8] == 'E')) {
+                                if ((!terminate) && (!xmlParseLookupGt(ctxt)))
+                                    goto done;
+                                ctxt->inSubset = 1;
+                                xmlParseDocTypeDecl(ctxt);
+                                if (RAW == '[') {
+                                    ctxt->instate = XML_PARSER_DTD;
+                                } else {
+                                    /*
+                                     * Create and update the external subset.
+                                     */
+                                    ctxt->inSubset = 2;
+                                    if ((ctxt->sax != NULL) &&
+                                        (!ctxt->disableSAX) &&
+                                        (ctxt->sax->externalSubset != NULL))
+                                        ctxt->sax->externalSubset(
+                                                ctxt->userData,
+                                                ctxt->intSubName,
+                                                ctxt->extSubSystem,
+                                                ctxt->extSubURI);
+                                    ctxt->inSubset = 0;
+                                    xmlCleanSpecialAttr(ctxt);
+                                    ctxt->instate = XML_PARSER_PROLOG;
+                                }
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                if (ctxt->instate == XML_PARSER_EPILOG) {
+                    if (ctxt->errNo == XML_ERR_OK)
+                        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
+		    ctxt->instate = XML_PARSER_EOF;
+                    xmlFinishDocument(ctxt);
+                } else {
+		    ctxt->instate = XML_PARSER_START_TAG;
 		}
 		break;
             case XML_PARSER_DTD: {
-	        /*
-		 * Sorry but progressive parsing of the internal subset
-		 * is not expected to be supported. We first check that
-		 * the full content of the internal subset is available and
-		 * the parsing is launched only at that point.
-		 * Internal subset ends up with "']' S? '>'" in an unescaped
-		 * section and not in a ']]>' sequence which are conditional
-		 * sections (whoever argued to keep that crap in XML deserve
-		 * a place in hell !).
-		 */
-		int base, i;
-		xmlChar *buf;
-	        xmlChar quote = 0;
-                size_t use;
-
-		base = ctxt->input->cur - ctxt->input->base;
-		if (base < 0) return(0);
-		if (ctxt->checkIndex > base)
-		    base = ctxt->checkIndex;
-		buf = xmlBufContent(ctxt->input->buf->buffer);
-                use = xmlBufUse(ctxt->input->buf->buffer);
-		for (;(unsigned int) base < use; base++) {
-		    if (quote != 0) {
-		        if (buf[base] == quote)
-			    quote = 0;
-			continue;
-		    }
-		    if ((quote == 0) && (buf[base] == '<')) {
-		        int found  = 0;
-			/* special handling of comments */
-		        if (((unsigned int) base + 4 < use) &&
-			    (buf[base + 1] == '!') &&
-			    (buf[base + 2] == '-') &&
-			    (buf[base + 3] == '-')) {
-			    for (;(unsigned int) base + 3 < use; base++) {
-				if ((buf[base] == '-') &&
-				    (buf[base + 1] == '-') &&
-				    (buf[base + 2] == '>')) {
-				    found = 1;
-				    base += 2;
-				    break;
-				}
-		            }
-			    if (!found) {
-#if 0
-			        fprintf(stderr, "unfinished comment\n");
-#endif
-			        break; /* for */
-		            }
-		            continue;
-			}
-		    }
-		    if (buf[base] == '"') {
-		        quote = '"';
-			continue;
-		    }
-		    if (buf[base] == '\'') {
-		        quote = '\'';
-			continue;
-		    }
-		    if (buf[base] == ']') {
-#if 0
-		        fprintf(stderr, "%c%c%c%c: ", buf[base],
-			        buf[base + 1], buf[base + 2], buf[base + 3]);
-#endif
-		        if ((unsigned int) base +1 >= use)
-			    break;
-			if (buf[base + 1] == ']') {
-			    /* conditional crap, skip both ']' ! */
-			    base++;
-			    continue;
-			}
-		        for (i = 1; (unsigned int) base + i < use; i++) {
-			    if (buf[base + i] == '>') {
-#if 0
-			        fprintf(stderr, "found\n");
-#endif
-			        goto found_end_int_subset;
-			    }
-			    if (!IS_BLANK_CH(buf[base + i])) {
-#if 0
-			        fprintf(stderr, "not found\n");
-#endif
-			        goto not_end_of_int_subset;
-			    }
-			}
-#if 0
-			fprintf(stderr, "end of stream\n");
-#endif
-		        break;
-
-		    }
-not_end_of_int_subset:
-                    continue; /* for */
-		}
-		/*
-		 * We didn't found the end of the Internal subset
-		 */
-                if (quote == 0)
-                    ctxt->checkIndex = base;
-                else
-                    ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		if (next == 0)
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: lookup of int subset end filed\n");
-#endif
-	        goto done;
-
-found_end_int_subset:
-                ctxt->checkIndex = 0;
+                if ((!terminate) && (!xmlParseLookupInternalSubset(ctxt)))
+                    goto done;
 		xmlParseInternalSubset(ctxt);
-		if (ctxt->instate == XML_PARSER_EOF)
-		    goto done;
 		ctxt->inSubset = 2;
 		if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 		    (ctxt->sax->externalSubset != NULL))
@@ -12062,342 +11483,143 @@ found_end_int_subset:
 			    ctxt->extSubSystem, ctxt->extSubURI);
 		ctxt->inSubset = 0;
 		xmlCleanSpecialAttr(ctxt);
-		if (ctxt->instate == XML_PARSER_EOF)
-		    goto done;
 		ctxt->instate = XML_PARSER_PROLOG;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering PROLOG\n");
-#endif
                 break;
 	    }
-            case XML_PARSER_COMMENT:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == COMMENT\n");
-		ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_IGNORE:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == IGNORE");
-	        ctxt->instate = XML_PARSER_DTD;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering DTD\n");
-#endif
-	        break;
-            case XML_PARSER_PI:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == PI\n");
-		ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_ENTITY_DECL:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == ENTITY_DECL\n");
-		ctxt->instate = XML_PARSER_DTD;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering DTD\n");
-#endif
-		break;
-            case XML_PARSER_ENTITY_VALUE:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == ENTITY_VALUE\n");
-		ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering DTD\n");
-#endif
-		break;
-            case XML_PARSER_ATTRIBUTE_VALUE:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == ATTRIBUTE_VALUE\n");
-		ctxt->instate = XML_PARSER_START_TAG;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering START_TAG\n");
-#endif
-		break;
-            case XML_PARSER_SYSTEM_LITERAL:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == SYSTEM_LITERAL\n");
-		ctxt->instate = XML_PARSER_START_TAG;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering START_TAG\n");
-#endif
-		break;
-            case XML_PARSER_PUBLIC_LITERAL:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == PUBLIC_LITERAL\n");
-		ctxt->instate = XML_PARSER_START_TAG;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering START_TAG\n");
-#endif
+            default:
+                xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
+			"PP: internal error\n");
+		ctxt->instate = XML_PARSER_EOF;
 		break;
 	}
     }
 done:
-#ifdef DEBUG_PUSH
-    xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
-#endif
     return(ret);
 encoding_error:
-    {
-        char buffer[150];
-
-	snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
-			ctxt->input->cur[0], ctxt->input->cur[1],
-			ctxt->input->cur[2], ctxt->input->cur[3]);
-	__xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
-		     "Input is not proper UTF-8, indicate encoding !\n%s",
-		     BAD_CAST buffer, NULL);
+    /* Only report the first error */
+    if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) {
+        xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL);
+        ctxt->input->flags |= XML_INPUT_ENCODING_ERROR;
     }
     return(0);
 }
 
-/**
- * xmlParseCheckTransition:
- * @ctxt:  an XML parser context
- * @chunk:  a char array
- * @size:  the size in byte of the chunk
- *
- * Check depending on the current parser state if the chunk given must be
- * processed immediately or one need more data to advance on parsing.
- *
- * Returns -1 in case of error, 0 if the push is not needed and 1 if needed
- */
-static int
-xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
-    if ((ctxt == NULL) || (chunk == NULL) || (size < 0))
-        return(-1);
-    if (ctxt->instate == XML_PARSER_START_TAG) {
-        if (memchr(chunk, '>', size) != NULL)
-            return(1);
-        return(0);
-    }
-    if (ctxt->progressive == XML_PARSER_COMMENT) {
-        if (memchr(chunk, '>', size) != NULL)
-            return(1);
-        return(0);
-    }
-    if (ctxt->instate == XML_PARSER_CDATA_SECTION) {
-        if (memchr(chunk, '>', size) != NULL)
-            return(1);
-        return(0);
-    }
-    if (ctxt->progressive == XML_PARSER_PI) {
-        if (memchr(chunk, '>', size) != NULL)
-            return(1);
-        return(0);
-    }
-    if (ctxt->instate == XML_PARSER_END_TAG) {
-        if (memchr(chunk, '>', size) != NULL)
-            return(1);
-        return(0);
-    }
-    if ((ctxt->progressive == XML_PARSER_DTD) ||
-        (ctxt->instate == XML_PARSER_DTD)) {
-        if (memchr(chunk, '>', size) != NULL)
-            return(1);
-        return(0);
-    }
-    return(1);
-}
-
 /**
  * xmlParseChunk:
  * @ctxt:  an XML parser context
- * @chunk:  an char array
- * @size:  the size in byte of the chunk
+ * @chunk:  chunk of memory
+ * @size:  size of chunk in bytes
  * @terminate:  last chunk indicator
  *
- * Parse a Chunk of memory
+ * Parse a chunk of memory in push parser mode.
  *
- * Returns zero if no error, the xmlParserErrors otherwise.
+ * Assumes that the parser context was initialized with
+ * xmlCreatePushParserCtxt.
+ *
+ * The last chunk, which will often be empty, must be marked with
+ * the @terminate flag. With the default SAX callbacks, the resulting
+ * document will be available in ctxt->myDoc. This pointer will not
+ * be freed by the library.
+ *
+ * If the document isn't well-formed, ctxt->myDoc is set to NULL.
+ * The push parser doesn't support recovery mode.
+ *
+ * Returns an xmlParserErrors code (0 on success).
  */
 int
 xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
               int terminate) {
+    size_t curBase;
+    size_t maxLength;
     int end_in_lf = 0;
-    int remain = 0;
-    size_t old_avail = 0;
-    size_t avail = 0;
 
-    if (ctxt == NULL)
-        return(XML_ERR_INTERNAL_ERROR);
-    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+    if ((ctxt == NULL) || (size < 0))
+        return(XML_ERR_ARGUMENT);
+    if (ctxt->disableSAX != 0)
         return(ctxt->errNo);
-    if (ctxt->instate == XML_PARSER_EOF)
-        return(-1);
+    if (ctxt->input == NULL)
+        return(XML_ERR_INTERNAL_ERROR);
+
+    ctxt->input->flags |= XML_INPUT_PROGRESSIVE;
     if (ctxt->instate == XML_PARSER_START)
-        xmlDetectSAX2(ctxt);
+        xmlCtxtInitializeLate(ctxt);
     if ((size > 0) && (chunk != NULL) && (!terminate) &&
         (chunk[size - 1] == '\r')) {
 	end_in_lf = 1;
 	size--;
     }
 
-xmldecl_done:
-
     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
-        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
-	size_t cur = ctxt->input->cur - ctxt->input->base;
+        (ctxt->input->buf != NULL))  {
+	size_t pos = ctxt->input->cur - ctxt->input->base;
 	int res;
 
-        old_avail = xmlBufUse(ctxt->input->buf->buffer);
-        /*
-         * Specific handling if we autodetected an encoding, we should not
-         * push more than the first line ... which depend on the encoding
-         * And only push the rest once the final encoding was detected
-         */
-        if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) &&
-            (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) {
-            unsigned int len = 45;
-
-            if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
-                               BAD_CAST "UTF-16")) ||
-                (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
-                               BAD_CAST "UTF16")))
-                len = 90;
-            else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
-                                    BAD_CAST "UCS-4")) ||
-                     (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
-                                    BAD_CAST "UCS4")))
-                len = 180;
-
-            if (ctxt->input->buf->rawconsumed < len)
-                len -= ctxt->input->buf->rawconsumed;
-
-            /*
-             * Change size for reading the initial declaration only
-             * if size is greater than len. Otherwise, memmove in xmlBufferAdd
-             * will blindly copy extra bytes from memory.
-             */
-            if ((unsigned int) size > len) {
-                remain = size - len;
-                size = len;
-            } else {
-                remain = 0;
-            }
-        }
 	res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
+        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
 	if (res < 0) {
-	    ctxt->errNo = XML_PARSER_EOF;
+            xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL);
 	    xmlHaltParser(ctxt);
-	    return (XML_PARSER_EOF);
-	}
-#ifdef DEBUG_PUSH
-	xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
-#endif
-
-    } else if (ctxt->instate != XML_PARSER_EOF) {
-	if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
-	    xmlParserInputBufferPtr in = ctxt->input->buf;
-	    if ((in->encoder != NULL) && (in->buffer != NULL) &&
-		    (in->raw != NULL)) {
-		int nbchars;
-		size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
-		size_t current = ctxt->input->cur - ctxt->input->base;
-
-		nbchars = xmlCharEncInput(in, terminate);
-		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
-		if (nbchars < 0) {
-		    /* TODO 2.6.0 */
-		    xmlGenericError(xmlGenericErrorContext,
-				    "xmlParseChunk: encoder error\n");
-                    xmlHaltParser(ctxt);
-		    return(XML_ERR_INVALID_ENCODING);
-		}
-	    }
+	    return(ctxt->errNo);
 	}
     }
-    if (remain != 0) {
-        xmlParseTryOrFinish(ctxt, 0);
-    } else {
-        if ((ctxt->input != NULL) && (ctxt->input->buf != NULL))
-            avail = xmlBufUse(ctxt->input->buf->buffer);
-        /*
-         * Depending on the current state it may not be such
-         * a good idea to try parsing if there is nothing in the chunk
-         * which would be worth doing a parser state transition and we
-         * need to wait for more data
-         */
-        if ((terminate) || (avail > XML_MAX_TEXT_LENGTH) ||
-            (old_avail == 0) || (avail == 0) ||
-            (xmlParseCheckTransition(ctxt,
-                       (const char *)&ctxt->input->base[old_avail],
-                                     avail - old_avail)))
-            xmlParseTryOrFinish(ctxt, terminate);
-    }
-    if (ctxt->instate == XML_PARSER_EOF)
-        return(ctxt->errNo);
 
-    if ((ctxt->input != NULL) &&
-         (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
-         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
-        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
-        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
+    xmlParseTryOrFinish(ctxt, terminate);
+
+    curBase = ctxt->input->cur - ctxt->input->base;
+    maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                XML_MAX_HUGE_LENGTH :
+                XML_MAX_LOOKUP_LIMIT;
+    if (curBase > maxLength) {
+        xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT,
+                    "Buffer size limit exceeded, try XML_PARSE_HUGE\n");
         xmlHaltParser(ctxt);
     }
-    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+
+    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX != 0))
         return(ctxt->errNo);
 
-    if (remain != 0) {
-        chunk += size;
-        size = remain;
-        remain = 0;
-        goto xmldecl_done;
-    }
     if ((end_in_lf == 1) && (ctxt->input != NULL) &&
         (ctxt->input->buf != NULL)) {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
-					 ctxt->input);
-	size_t current = ctxt->input->cur - ctxt->input->base;
+	size_t pos = ctxt->input->cur - ctxt->input->base;
+        int res;
 
-	xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
-
-	xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
-			      base, current);
+	res = xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
+	xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
+        if (res < 0) {
+            xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL);
+            xmlHaltParser(ctxt);
+            return(ctxt->errNo);
+        }
     }
     if (terminate) {
 	/*
 	 * Check for termination
 	 */
-	int cur_avail = 0;
-
-	if (ctxt->input != NULL) {
-	    if (ctxt->input->buf == NULL)
-		cur_avail = ctxt->input->length -
-			    (ctxt->input->cur - ctxt->input->base);
-	    else
-		cur_avail = xmlBufUse(ctxt->input->buf->buffer) -
-			              (ctxt->input->cur - ctxt->input->base);
-	}
-
-	if ((ctxt->instate != XML_PARSER_EOF) &&
-	    (ctxt->instate != XML_PARSER_EPILOG)) {
-	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
-	}
-	if ((ctxt->instate == XML_PARSER_EPILOG) && (cur_avail > 0)) {
-	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
-	}
+        if ((ctxt->instate != XML_PARSER_EOF) &&
+            (ctxt->instate != XML_PARSER_EPILOG)) {
+            if (ctxt->nameNr > 0) {
+                const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
+                int line = ctxt->pushTab[ctxt->nameNr - 1].line;
+                xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
+                        "Premature end of data in tag %s line %d\n",
+                        name, line, NULL);
+            } else if (ctxt->instate == XML_PARSER_START) {
+                xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+            } else {
+                xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
+                               "Start tag expected, '<' not found\n");
+            }
+        } else if ((ctxt->input->buf != NULL) &&
+                   (ctxt->input->buf->encoder != NULL) &&
+                   (ctxt->input->buf->error == 0) &&
+                   (!xmlBufIsEmpty(ctxt->input->buf->raw))) {
+            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
+                           "Truncated multi-byte sequence at EOF\n");
+        }
 	if (ctxt->instate != XML_PARSER_EOF) {
-	    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
-		ctxt->sax->endDocument(ctxt->userData);
+            ctxt->instate = XML_PARSER_EOF;
+            xmlFinishDocument(ctxt);
 	}
-	ctxt->instate = XML_PARSER_EOF;
     }
     if (ctxt->wellFormed == 0)
 	return((xmlParserErrors) ctxt->errNo);
@@ -12413,157 +11635,47 @@ xmldecl_done:
 
 /**
  * xmlCreatePushParserCtxt:
- * @sax:  a SAX handler
- * @user_data:  The user data returned on SAX callbacks
- * @chunk:  a pointer to an array of chars
- * @size:  number of chars in the array
- * @filename:  an optional file name or URI
+ * @sax:  a SAX handler (optional)
+ * @user_data:  user data for SAX callbacks (optional)
+ * @chunk:  initial chunk (optional, deprecated)
+ * @size:  size of initial chunk in bytes
+ * @filename:  file name or URI (optional)
  *
  * Create a parser context for using the XML parser in push mode.
- * If @buffer and @size are non-NULL, the data is used to detect
- * the encoding.  The remaining characters will be parsed so they
- * don't need to be fed in again through xmlParseChunk.
- * To allow content encoding detection, @size should be >= 4
- * The value of @filename is used for fetching external entities
- * and error/warning reports.
+ * See xmlParseChunk.
  *
- * Returns the new parser context or NULL
+ * Passing an initial chunk is useless and deprecated.
+ *
+ * @filename is used as base URI to fetch external entities and for
+ * error reports.
+ *
+ * Returns the new parser context or NULL in case of error.
  */
 
 xmlParserCtxtPtr
 xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
                         const char *chunk, int size, const char *filename) {
     xmlParserCtxtPtr ctxt;
-    xmlParserInputPtr inputStream;
-    xmlParserInputBufferPtr buf;
-    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
-
-    /*
-     * plug some encoding conversion routines
-     */
-    if ((chunk != NULL) && (size >= 4))
-	enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
-
-    buf = xmlAllocParserInputBuffer(enc);
-    if (buf == NULL) return(NULL);
+    xmlParserInputPtr input;
 
-    ctxt = xmlNewParserCtxt();
-    if (ctxt == NULL) {
-        xmlErrMemory(NULL, "creating parser: out of memory\n");
-	xmlFreeParserInputBuffer(buf);
+    ctxt = xmlNewSAXParserCtxt(sax, user_data);
+    if (ctxt == NULL)
 	return(NULL);
-    }
+
+    ctxt->options &= ~XML_PARSE_NODICT;
     ctxt->dictNames = 1;
-    if (sax != NULL) {
-#ifdef LIBXML_SAX1_ENABLED
-	if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
-#endif /* LIBXML_SAX1_ENABLED */
-	    xmlFree(ctxt->sax);
-	ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
-	if (ctxt->sax == NULL) {
-	    xmlErrMemory(ctxt, NULL);
-	    xmlFreeParserInputBuffer(buf);
-	    xmlFreeParserCtxt(ctxt);
-	    return(NULL);
-	}
-	memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
-	if (sax->initialized == XML_SAX2_MAGIC)
-	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
-	else
-	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
-	if (user_data != NULL)
-	    ctxt->userData = user_data;
-    }
-    if (filename == NULL) {
-	ctxt->directory = NULL;
-    } else {
-        ctxt->directory = xmlParserGetDirectory(filename);
-    }
 
-    inputStream = xmlNewInputStream(ctxt);
-    if (inputStream == NULL) {
+    input = xmlNewInputPush(ctxt, filename, chunk, size, NULL);
+    if (input == NULL) {
 	xmlFreeParserCtxt(ctxt);
-	xmlFreeParserInputBuffer(buf);
 	return(NULL);
     }
-
-    if (filename == NULL)
-	inputStream->filename = NULL;
-    else {
-	inputStream->filename = (char *)
-	    xmlCanonicPath((const xmlChar *) filename);
-	if (inputStream->filename == NULL) {
-	    xmlFreeParserCtxt(ctxt);
-	    xmlFreeParserInputBuffer(buf);
-	    return(NULL);
-	}
-    }
-    inputStream->buf = buf;
-    xmlBufResetInput(inputStream->buf->buffer, inputStream);
-    inputPush(ctxt, inputStream);
-
-    /*
-     * If the caller didn't provide an initial 'chunk' for determining
-     * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
-     * that it can be automatically determined later
-     */
-    if ((size == 0) || (chunk == NULL)) {
-	ctxt->charset = XML_CHAR_ENCODING_NONE;
-    } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
-	size_t cur = ctxt->input->cur - ctxt->input->base;
-
-	xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
-#ifdef DEBUG_PUSH
-	xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
-#endif
-    }
-
-    if (enc != XML_CHAR_ENCODING_NONE) {
-        xmlSwitchEncoding(ctxt, enc);
-    }
+    inputPush(ctxt, input);
 
     return(ctxt);
 }
 #endif /* LIBXML_PUSH_ENABLED */
 
-/**
- * xmlHaltParser:
- * @ctxt:  an XML parser context
- *
- * Blocks further parser processing don't override error
- * for internal use
- */
-static void
-xmlHaltParser(xmlParserCtxtPtr ctxt) {
-    if (ctxt == NULL)
-        return;
-    ctxt->instate = XML_PARSER_EOF;
-    ctxt->disableSAX = 1;
-    while (ctxt->inputNr > 1)
-        xmlFreeInputStream(inputPop(ctxt));
-    if (ctxt->input != NULL) {
-        /*
-	 * in case there was a specific allocation deallocate before
-	 * overriding base
-	 */
-        if (ctxt->input->free != NULL) {
-	    ctxt->input->free((xmlChar *) ctxt->input->base);
-	    ctxt->input->free = NULL;
-	}
-        if (ctxt->input->buf != NULL) {
-            xmlFreeParserInputBuffer(ctxt->input->buf);
-            ctxt->input->buf = NULL;
-        }
-	ctxt->input->cur = BAD_CAST"";
-        ctxt->input->length = 0;
-	ctxt->input->base = ctxt->input->cur;
-        ctxt->input->end = ctxt->input->cur;
-    }
-}
-
 /**
  * xmlStopParser:
  * @ctxt:  an XML parser context
@@ -12575,17 +11687,18 @@ xmlStopParser(xmlParserCtxtPtr ctxt) {
     if (ctxt == NULL)
         return;
     xmlHaltParser(ctxt);
-    ctxt->errNo = XML_ERR_USER_STOP;
+    if (ctxt->errNo != XML_ERR_NO_MEMORY)
+        ctxt->errNo = XML_ERR_USER_STOP;
 }
 
 /**
  * xmlCreateIOParserCtxt:
- * @sax:  a SAX handler
- * @user_data:  The user data returned on SAX callbacks
+ * @sax:  a SAX handler (optional)
+ * @user_data:  user data for SAX callbacks (optional)
  * @ioread:  an I/O read function
- * @ioclose:  an I/O close function
+ * @ioclose:  an I/O close function (optional)
  * @ioctx:  an I/O handler
- * @enc:  the charset encoding if known
+ * @enc:  the charset encoding if known (deprecated)
  *
  * Create a parser context for using the XML parser with an existing
  * I/O stream
@@ -12594,53 +11707,24 @@ xmlStopParser(xmlParserCtxtPtr ctxt) {
  */
 xmlParserCtxtPtr
 xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
-	xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
-	void *ioctx, xmlCharEncoding enc) {
+                      xmlInputReadCallback ioread,
+                      xmlInputCloseCallback ioclose,
+                      void *ioctx, xmlCharEncoding enc) {
     xmlParserCtxtPtr ctxt;
-    xmlParserInputPtr inputStream;
-    xmlParserInputBufferPtr buf;
-
-    if (ioread == NULL) return(NULL);
-
-    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
-    if (buf == NULL) {
-        if (ioclose != NULL)
-            ioclose(ioctx);
-        return (NULL);
-    }
+    xmlParserInputPtr input;
+    const char *encoding;
 
-    ctxt = xmlNewParserCtxt();
-    if (ctxt == NULL) {
-	xmlFreeParserInputBuffer(buf);
+    ctxt = xmlNewSAXParserCtxt(sax, user_data);
+    if (ctxt == NULL)
 	return(NULL);
-    }
-    if (sax != NULL) {
-#ifdef LIBXML_SAX1_ENABLED
-	if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
-#endif /* LIBXML_SAX1_ENABLED */
-	    xmlFree(ctxt->sax);
-	ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
-	if (ctxt->sax == NULL) {
-	    xmlFreeParserInputBuffer(buf);
-	    xmlErrMemory(ctxt, NULL);
-	    xmlFreeParserCtxt(ctxt);
-	    return(NULL);
-	}
-	memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
-	if (sax->initialized == XML_SAX2_MAGIC)
-	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
-	else
-	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
-	if (user_data != NULL)
-	    ctxt->userData = user_data;
-    }
 
-    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
-    if (inputStream == NULL) {
+    encoding = xmlGetCharEncodingName(enc);
+    input = xmlNewInputIO(ctxt, NULL, ioread, ioclose, ioctx, encoding, 0);
+    if (input == NULL) {
 	xmlFreeParserCtxt(ctxt);
-	return(NULL);
+        return (NULL);
     }
-    inputPush(ctxt, inputStream);
+    inputPush(ctxt, input);
 
     return(ctxt);
 }
@@ -12670,38 +11754,22 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
     xmlDtdPtr ret = NULL;
     xmlParserCtxtPtr ctxt;
     xmlParserInputPtr pinput = NULL;
-    xmlChar start[4];
 
     if (input == NULL)
 	return(NULL);
 
-    ctxt = xmlNewParserCtxt();
+    ctxt = xmlNewSAXParserCtxt(sax, NULL);
     if (ctxt == NULL) {
         xmlFreeParserInputBuffer(input);
 	return(NULL);
     }
 
-    /* We are loading a DTD */
-    ctxt->options |= XML_PARSE_DTDLOAD;
-
-    /*
-     * Set-up the SAX context
-     */
-    if (sax != NULL) {
-	if (ctxt->sax != NULL)
-	    xmlFree(ctxt->sax);
-        ctxt->sax = sax;
-        ctxt->userData = ctxt;
-    }
-    xmlDetectSAX2(ctxt);
-
     /*
      * generate a parser input from the I/O handler
      */
 
     pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
     if (pinput == NULL) {
-        if (sax != NULL) ctxt->sax = NULL;
         xmlFreeParserInputBuffer(input);
 	xmlFreeParserCtxt(ctxt);
 	return(NULL);
@@ -12711,7 +11779,6 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
      * plug some encoding conversion routines here.
      */
     if (xmlPushInput(ctxt, pinput) < 0) {
-        if (sax != NULL) ctxt->sax = NULL;
 	xmlFreeParserCtxt(ctxt);
 	return(NULL);
     }
@@ -12719,43 +11786,18 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
         xmlSwitchEncoding(ctxt, enc);
     }
 
-    pinput->filename = NULL;
-    pinput->line = 1;
-    pinput->col = 1;
-    pinput->base = ctxt->input->cur;
-    pinput->cur = ctxt->input->cur;
-    pinput->free = NULL;
-
     /*
      * let's parse that entity knowing it's an external subset.
      */
-    ctxt->inSubset = 2;
     ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
     if (ctxt->myDoc == NULL) {
-	xmlErrMemory(ctxt, "New Doc failed");
+	xmlErrMemory(ctxt);
 	return(NULL);
     }
     ctxt->myDoc->properties = XML_DOC_INTERNAL;
     ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
 	                               BAD_CAST "none", BAD_CAST "none");
 
-    if ((enc == XML_CHAR_ENCODING_NONE) &&
-        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
-	/*
-	 * Get the 4 first bytes and decode the charset
-	 * if enc != XML_CHAR_ENCODING_NONE
-	 * plug some encoding conversion routines.
-	 */
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(start, 4);
-	if (enc != XML_CHAR_ENCODING_NONE) {
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-    }
-
     xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
 
     if (ctxt->myDoc != NULL) {
@@ -12778,7 +11820,6 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
         xmlFreeDoc(ctxt->myDoc);
         ctxt->myDoc = NULL;
     }
-    if (sax != NULL) ctxt->sax = NULL;
     xmlFreeParserCtxt(ctxt);
 
     return(ret);
@@ -12790,6 +11831,8 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
  * @ExternalID:  a NAME* containing the External ID of the DTD
  * @SystemID:  a NAME* containing the URL to the DTD
  *
+ * DEPRECATED: Don't use.
+ *
  * Load and parse an external subset.
  *
  * Returns the resulting xmlDtdPtr or NULL in case of error.
@@ -12801,29 +11844,15 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
     xmlDtdPtr ret = NULL;
     xmlParserCtxtPtr ctxt;
     xmlParserInputPtr input = NULL;
-    xmlCharEncoding enc;
     xmlChar* systemIdCanonic;
 
     if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
 
-    ctxt = xmlNewParserCtxt();
+    ctxt = xmlNewSAXParserCtxt(sax, NULL);
     if (ctxt == NULL) {
 	return(NULL);
     }
 
-    /* We are loading a DTD */
-    ctxt->options |= XML_PARSE_DTDLOAD;
-
-    /*
-     * Set-up the SAX context
-     */
-    if (sax != NULL) {
-	if (ctxt->sax != NULL)
-	    xmlFree(ctxt->sax);
-        ctxt->sax = sax;
-        ctxt->userData = ctxt;
-    }
-
     /*
      * Canonicalise the system ID
      */
@@ -12841,7 +11870,6 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
 	input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
 	                                 systemIdCanonic);
     if (input == NULL) {
-        if (sax != NULL) ctxt->sax = NULL;
 	xmlFreeParserCtxt(ctxt);
 	if (systemIdCanonic != NULL)
 	    xmlFree(systemIdCanonic);
@@ -12852,41 +11880,36 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
      * plug some encoding conversion routines here.
      */
     if (xmlPushInput(ctxt, input) < 0) {
-        if (sax != NULL) ctxt->sax = NULL;
 	xmlFreeParserCtxt(ctxt);
 	if (systemIdCanonic != NULL)
 	    xmlFree(systemIdCanonic);
 	return(NULL);
     }
-    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
-	enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
-	xmlSwitchEncoding(ctxt, enc);
-    }
+
+    xmlDetectEncoding(ctxt);
 
     if (input->filename == NULL)
 	input->filename = (char *) systemIdCanonic;
     else
 	xmlFree(systemIdCanonic);
-    input->line = 1;
-    input->col = 1;
-    input->base = ctxt->input->cur;
-    input->cur = ctxt->input->cur;
-    input->free = NULL;
 
     /*
      * let's parse that entity knowing it's an external subset.
      */
-    ctxt->inSubset = 2;
     ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
     if (ctxt->myDoc == NULL) {
-	xmlErrMemory(ctxt, "New Doc failed");
-        if (sax != NULL) ctxt->sax = NULL;
+	xmlErrMemory(ctxt);
 	xmlFreeParserCtxt(ctxt);
 	return(NULL);
     }
-    ctxt->myDoc->properties = XML_DOC_INTERNAL;
-    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
-	                               ExternalID, SystemID);
+    ctxt->myDoc->properties = XML_DOC_INTERNAL;
+    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
+	                               ExternalID, SystemID);
+    if (ctxt->myDoc->extSubset == NULL) {
+        xmlFreeDoc(ctxt->myDoc);
+        xmlFreeParserCtxt(ctxt);
+        return(NULL);
+    }
     xmlParseExternalSubset(ctxt, ExternalID, SystemID);
 
     if (ctxt->myDoc != NULL) {
@@ -12909,7 +11932,6 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
         xmlFreeDoc(ctxt->myDoc);
         ctxt->myDoc = NULL;
     }
-    if (sax != NULL) ctxt->sax = NULL;
     xmlFreeParserCtxt(ctxt);
 
     return(ret);
@@ -12938,293 +11960,211 @@ xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
  *									*
  ************************************************************************/
 
-/**
- * xmlParseCtxtExternalEntity:
- * @ctx:  the existing parsing context
- * @URL:  the URL for the entity to load
- * @ID:  the System ID for the entity to load
- * @lst:  the return value for the set of parsed nodes
- *
- * Parse an external general entity within an existing parsing context
- * An external general parsed entity is well-formed if it matches the
- * production labeled extParsedEnt.
- *
- * [78] extParsedEnt ::= TextDecl? content
- *
- * Returns 0 if the entity is well formed, -1 in case of args problem and
- *    the parser error code otherwise
- */
+static xmlNodePtr
+xmlCtxtParseContent(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
+                    int hasTextDecl, int buildTree) {
+    xmlNodePtr root = NULL;
+    xmlNodePtr list = NULL;
+    xmlChar *rootName = BAD_CAST "#root";
+    int result;
+
+    if (buildTree) {
+        root = xmlNewDocNode(ctxt->myDoc, NULL, rootName, NULL);
+        if (root == NULL) {
+            xmlErrMemory(ctxt);
+            goto error;
+        }
+    }
 
-int
-xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
-	               const xmlChar *ID, xmlNodePtr *lst) {
-    void *userData;
+    if (xmlPushInput(ctxt, input) < 0)
+        goto error;
 
-    if (ctx == NULL) return(-1);
-    /*
-     * If the user provided their own SAX callbacks, then reuse the
-     * userData callback field, otherwise the expected setup in a
-     * DOM builder is to have userData == ctxt
-     */
-    if (ctx->userData == ctx)
-        userData = NULL;
-    else
-        userData = ctx->userData;
-    return xmlParseExternalEntityPrivate(ctx->myDoc, ctx, ctx->sax,
-                                         userData, ctx->depth + 1,
-                                         URL, ID, lst);
-}
+    nameNsPush(ctxt, rootName, NULL, NULL, 0, 0);
+    spacePush(ctxt, -1);
 
-/**
- * xmlParseExternalEntityPrivate:
- * @doc:  the document the chunk pertains to
- * @oldctxt:  the previous parser context if available
- * @sax:  the SAX handler block (possibly NULL)
- * @user_data:  The user data returned on SAX callbacks (possibly NULL)
- * @depth:  Used for loop detection, use 0
- * @URL:  the URL for the entity to load
- * @ID:  the System ID for the entity to load
- * @list:  the return value for the set of parsed nodes
- *
- * Private version of xmlParseExternalEntity()
- *
- * Returns 0 if the entity is well formed, -1 in case of args problem and
- *    the parser error code otherwise
- */
+    if (buildTree)
+        nodePush(ctxt, root);
 
-static xmlParserErrors
-xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
-	              xmlSAXHandlerPtr sax,
-		      void *user_data, int depth, const xmlChar *URL,
-		      const xmlChar *ID, xmlNodePtr *list) {
-    xmlParserCtxtPtr ctxt;
-    xmlDocPtr newDoc;
-    xmlNodePtr newRoot;
-    xmlSAXHandlerPtr oldsax = NULL;
-    xmlParserErrors ret = XML_ERR_OK;
-    xmlChar start[4];
-    xmlCharEncoding enc;
+    if (hasTextDecl) {
+        xmlDetectEncoding(ctxt);
 
-    if (((depth > 40) &&
-	((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
-	(depth > 1024)) {
-	return(XML_ERR_ENTITY_LOOP);
+        /*
+         * Parse a possible text declaration first
+         */
+        if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
+            (IS_BLANK_CH(NXT(5)))) {
+            xmlParseTextDecl(ctxt);
+            /*
+             * An XML-1.0 document can't reference an entity not XML-1.0
+             */
+            if ((xmlStrEqual(ctxt->version, BAD_CAST "1.0")) &&
+                (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
+                xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
+                               "Version mismatch between document and "
+                               "entity\n");
+            }
+        }
     }
 
-    if (list != NULL)
-        *list = NULL;
-    if ((URL == NULL) && (ID == NULL))
-	return(XML_ERR_INTERNAL_ERROR);
-    if (doc == NULL)
-	return(XML_ERR_INTERNAL_ERROR);
+    xmlParseContentInternal(ctxt);
+
+    if (ctxt->input->cur < ctxt->input->end)
+	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
+    if ((ctxt->wellFormed) ||
+        ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) {
+        if (root != NULL) {
+            xmlNodePtr cur;
 
-    ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt);
-    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
-    ctxt->userData = ctxt;
-    if (sax != NULL) {
-	oldsax = ctxt->sax;
-        ctxt->sax = sax;
-	if (user_data != NULL)
-	    ctxt->userData = user_data;
-    }
-    xmlDetectSAX2(ctxt);
-    newDoc = xmlNewDoc(BAD_CAST "1.0");
-    if (newDoc == NULL) {
-	xmlFreeParserCtxt(ctxt);
-	return(XML_ERR_INTERNAL_ERROR);
-    }
-    newDoc->properties = XML_DOC_INTERNAL;
-    if (doc) {
-        newDoc->intSubset = doc->intSubset;
-        newDoc->extSubset = doc->extSubset;
-        if (doc->dict) {
-            newDoc->dict = doc->dict;
-            xmlDictReference(newDoc->dict);
-        }
-        if (doc->URL != NULL) {
-            newDoc->URL = xmlStrdup(doc->URL);
+            /*
+             * Return the newly created nodeset after unlinking it from
+             * its pseudo parent.
+             */
+            cur = root->children;
+            list = cur;
+            while (cur != NULL) {
+                cur->parent = NULL;
+                cur = cur->next;
+            }
+            root->children = NULL;
+            root->last = NULL;
         }
     }
-    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
-    if (newRoot == NULL) {
-	if (sax != NULL)
-	    ctxt->sax = oldsax;
-	xmlFreeParserCtxt(ctxt);
-	newDoc->intSubset = NULL;
-	newDoc->extSubset = NULL;
-        xmlFreeDoc(newDoc);
-	return(XML_ERR_INTERNAL_ERROR);
-    }
-    xmlAddChild((xmlNodePtr) newDoc, newRoot);
-    nodePush(ctxt, newDoc->children);
-    if (doc == NULL) {
-        ctxt->myDoc = newDoc;
-    } else {
-        ctxt->myDoc = doc;
-        newRoot->doc = doc;
-    }
 
     /*
-     * Get the 4 first bytes and decode the charset
-     * if enc != XML_CHAR_ENCODING_NONE
-     * plug some encoding conversion routines.
+     * Read the rest of the stream in case of errors. We want
+     * to account for the whole entity size.
      */
-    GROW;
-    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(start, 4);
-	if (enc != XML_CHAR_ENCODING_NONE) {
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-    }
+    do {
+        ctxt->input->cur = ctxt->input->end;
+        xmlParserShrink(ctxt);
+        result = xmlParserGrow(ctxt);
+    } while (result > 0);
 
-    /*
-     * Parse a possible text declaration first
-     */
-    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
-	xmlParseTextDecl(ctxt);
-        /*
-         * An XML-1.0 document can't reference an entity not XML-1.0
-         */
-        if ((xmlStrEqual(oldctxt->version, BAD_CAST "1.0")) &&
-            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
-            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
-                           "Version mismatch between document and entity\n");
-        }
-    }
+    if (buildTree)
+        nodePop(ctxt);
 
-    ctxt->instate = XML_PARSER_CONTENT;
-    ctxt->depth = depth;
-    if (oldctxt != NULL) {
-	ctxt->_private = oldctxt->_private;
-	ctxt->loadsubset = oldctxt->loadsubset;
-	ctxt->validate = oldctxt->validate;
-	ctxt->valid = oldctxt->valid;
-	ctxt->replaceEntities = oldctxt->replaceEntities;
-        if (oldctxt->validate) {
-            ctxt->vctxt.error = oldctxt->vctxt.error;
-            ctxt->vctxt.warning = oldctxt->vctxt.warning;
-            ctxt->vctxt.userData = oldctxt->vctxt.userData;
-        }
-	ctxt->external = oldctxt->external;
-        if (ctxt->dict) xmlDictFree(ctxt->dict);
-        ctxt->dict = oldctxt->dict;
-        ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
-        ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
-        ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
-        ctxt->dictNames = oldctxt->dictNames;
-        ctxt->attsDefault = oldctxt->attsDefault;
-        ctxt->attsSpecial = oldctxt->attsSpecial;
-        ctxt->linenumbers = oldctxt->linenumbers;
-	ctxt->record_info = oldctxt->record_info;
-	ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
-	ctxt->node_seq.length = oldctxt->node_seq.length;
-	ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
-    } else {
-	/*
-	 * Doing validity checking on chunk without context
-	 * doesn't make sense
-	 */
-	ctxt->_private = NULL;
-	ctxt->validate = 0;
-	ctxt->external = 2;
-	ctxt->loadsubset = 0;
-    }
+    namePop(ctxt);
+    spacePop(ctxt);
 
-    xmlParseContent(ctxt);
+    /* xmlPopInput would free the stream */
+    inputPop(ctxt);
 
-    if ((RAW == '<') && (NXT(1) == '/')) {
-	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
-    } else if (RAW != 0) {
-	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
-    }
-    if (ctxt->node != newDoc->children) {
-	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
-    }
+error:
+    xmlFreeNode(root);
 
-    if (!ctxt->wellFormed) {
-        if (ctxt->errNo == 0)
-	    ret = XML_ERR_INTERNAL_ERROR;
-	else
-	    ret = (xmlParserErrors)ctxt->errNo;
-    } else {
-	if (list != NULL) {
-	    xmlNodePtr cur;
+    return(list);
+}
 
-	    /*
-	     * Return the newly created nodeset after unlinking it from
-	     * they pseudo parent.
-	     */
-	    cur = newDoc->children->children;
-	    *list = cur;
-	    while (cur != NULL) {
-		cur->parent = NULL;
-		cur = cur->next;
-	    }
-            newDoc->children->children = NULL;
-	}
-	ret = XML_ERR_OK;
+static void
+xmlCtxtParseEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr ent) {
+    xmlParserInputPtr input;
+    xmlNodePtr list;
+    unsigned long consumed;
+    int isExternal;
+    int buildTree;
+    int oldMinNsIndex;
+    int oldNodelen, oldNodemem;
+
+    isExternal = (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY);
+    buildTree = (ctxt->node != NULL);
+
+    /*
+     * Recursion check
+     */
+    if (ent->flags & XML_ENT_EXPANDING) {
+        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+        xmlHaltParser(ctxt);
+        goto error;
     }
 
     /*
-     * Record in the parent context the number of entities replacement
-     * done when parsing that reference.
+     * Load entity
      */
-    if (oldctxt != NULL)
-        oldctxt->nbentities += ctxt->nbentities;
+    input = xmlNewEntityInputStream(ctxt, ent);
+    if (input == NULL)
+        goto error;
 
     /*
-     * Also record the size of the entity parsed
+     * When building a tree, we need to limit the scope of namespace
+     * declarations, so that entities don't reference xmlNs structs
+     * from the parent of a reference.
      */
-    if (ctxt->input != NULL && oldctxt != NULL) {
-	oldctxt->sizeentities += ctxt->input->consumed;
-	oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
-    }
+    oldMinNsIndex = ctxt->nsdb->minNsIndex;
+    if (buildTree)
+        ctxt->nsdb->minNsIndex = ctxt->nsNr;
+
+    oldNodelen = ctxt->nodelen;
+    oldNodemem = ctxt->nodemem;
+    ctxt->nodelen = 0;
+    ctxt->nodemem = 0;
+
     /*
-     * And record the last error if any
+     * Parse content
+     *
+     * This initiates a recursive call chain:
+     *
+     * - xmlCtxtParseContent
+     * - xmlParseContentInternal
+     * - xmlParseReference
+     * - xmlCtxtParseEntity
+     *
+     * The nesting depth is limited by the maximum number of inputs,
+     * see xmlPushInput.
+     *
+     * It's possible to make this non-recursive (minNsIndex must be
+     * stored in the input struct) at the expense of code readability.
      */
-    if ((oldctxt != NULL) && (ctxt->lastError.code != XML_ERR_OK))
-        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
 
-    if (sax != NULL)
-	ctxt->sax = oldsax;
-    if (oldctxt != NULL) {
-        ctxt->dict = NULL;
-        ctxt->attsDefault = NULL;
-        ctxt->attsSpecial = NULL;
-        oldctxt->validate = ctxt->validate;
-        oldctxt->valid = ctxt->valid;
-        oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
-        oldctxt->node_seq.length = ctxt->node_seq.length;
-        oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
-    }
-    ctxt->node_seq.maximum = 0;
-    ctxt->node_seq.length = 0;
-    ctxt->node_seq.buffer = NULL;
-    xmlFreeParserCtxt(ctxt);
-    newDoc->intSubset = NULL;
-    newDoc->extSubset = NULL;
-    xmlFreeDoc(newDoc);
+    ent->flags |= XML_ENT_EXPANDING;
 
-    return(ret);
+    list = xmlCtxtParseContent(ctxt, input, isExternal, buildTree);
+
+    ent->flags &= ~XML_ENT_EXPANDING;
+
+    ctxt->nsdb->minNsIndex = oldMinNsIndex;
+    ctxt->nodelen = oldNodelen;
+    ctxt->nodemem = oldNodemem;
+
+    /*
+     * Entity size accounting
+     */
+    consumed = input->consumed;
+    xmlSaturatedAddSizeT(&consumed, input->end - input->base);
+
+    if ((ent->flags & XML_ENT_CHECKED) == 0)
+        xmlSaturatedAdd(&ent->expandedSize, consumed);
+
+    if ((ent->flags & XML_ENT_PARSED) == 0) {
+        if (isExternal)
+            xmlSaturatedAdd(&ctxt->sizeentities, consumed);
+
+        ent->children = list;
+
+        while (list != NULL) {
+            list->parent = (xmlNodePtr) ent;
+            if (list->next == NULL)
+                ent->last = list;
+            list = list->next;
+        }
+    } else {
+        xmlFreeNodeList(list);
+    }
+
+    xmlFreeInputStream(input);
+
+error:
+    ent->flags |= XML_ENT_PARSED | XML_ENT_CHECKED;
 }
 
-#ifdef LIBXML_SAX1_ENABLED
 /**
- * xmlParseExternalEntity:
- * @doc:  the document the chunk pertains to
- * @sax:  the SAX handler block (possibly NULL)
- * @user_data:  The user data returned on SAX callbacks (possibly NULL)
- * @depth:  Used for loop detection, use 0
+ * xmlParseCtxtExternalEntity:
+ * @ctxt:  the existing parsing context
  * @URL:  the URL for the entity to load
  * @ID:  the System ID for the entity to load
- * @lst:  the return value for the set of parsed nodes
+ * @listOut:  the return value for the set of parsed nodes
  *
- * Parse an external general entity
+ * Parse an external general entity within an existing parsing context
  * An external general parsed entity is well-formed if it matches the
  * production labeled extParsedEnt.
  *
@@ -13235,235 +12175,108 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
  */
 
 int
-xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
-	  int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
-    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
-		                       ID, lst));
-}
-
-/**
- * xmlParseBalancedChunkMemory:
- * @doc:  the document the chunk pertains to (must not be NULL)
- * @sax:  the SAX handler block (possibly NULL)
- * @user_data:  The user data returned on SAX callbacks (possibly NULL)
- * @depth:  Used for loop detection, use 0
- * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
- * @lst:  the return value for the set of parsed nodes
- *
- * Parse a well-balanced chunk of an XML document
- * called by the parser
- * The allowed sequence for the Well Balanced Chunk is the one defined by
- * the content production in the XML grammar:
- *
- * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
- *
- * Returns 0 if the chunk is well balanced, -1 in case of args problem and
- *    the parser error code otherwise
- */
-
-int
-xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
-     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
-    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
-                                                depth, string, lst, 0 );
-}
-#endif /* LIBXML_SAX1_ENABLED */
-
-/**
- * xmlParseBalancedChunkMemoryInternal:
- * @oldctxt:  the existing parsing context
- * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
- * @user_data:  the user data field for the parser context
- * @lst:  the return value for the set of parsed nodes
- *
- *
- * Parse a well-balanced chunk of an XML document
- * called by the parser
- * The allowed sequence for the Well Balanced Chunk is the one defined by
- * the content production in the XML grammar:
- *
- * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
- *
- * Returns XML_ERR_OK if the chunk is well balanced, and the parser
- * error code otherwise
- *
- * In case recover is set to 1, the nodelist will not be empty even if
- * the parsed chunk is not well balanced.
- */
-static xmlParserErrors
-xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
-	const xmlChar *string, void *user_data, xmlNodePtr *lst) {
-    xmlParserCtxtPtr ctxt;
-    xmlDocPtr newDoc = NULL;
-    xmlNodePtr newRoot;
-    xmlSAXHandlerPtr oldsax = NULL;
-    xmlNodePtr content = NULL;
-    xmlNodePtr last = NULL;
-    int size;
-    xmlParserErrors ret = XML_ERR_OK;
-#ifdef SAX2
-    int i;
-#endif
+xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctxt, const xmlChar *URL,
+                           const xmlChar *ID, xmlNodePtr *listOut) {
+    xmlParserInputPtr input;
+    xmlNodePtr list;
 
-    if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
-        (oldctxt->depth >  1024)) {
-	return(XML_ERR_ENTITY_LOOP);
-    }
+    if (listOut != NULL)
+        *listOut = NULL;
 
+    if (ctxt == NULL)
+        return(XML_ERR_ARGUMENT);
 
-    if (lst != NULL)
-        *lst = NULL;
-    if (string == NULL)
-        return(XML_ERR_INTERNAL_ERROR);
+    input = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
+    if (input == NULL)
+        return(ctxt->errNo);
 
-    size = xmlStrlen(string);
+    xmlCtxtInitializeLate(ctxt);
 
-    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
-    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
-    if (user_data != NULL)
-	ctxt->userData = user_data;
+    list = xmlCtxtParseContent(ctxt, input, /* hasTextDecl */ 1, 1);
+    if (listOut != NULL)
+        *listOut = list;
     else
-	ctxt->userData = ctxt;
-    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
-    ctxt->dict = oldctxt->dict;
-    ctxt->input_id = oldctxt->input_id + 1;
-    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
-    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
-    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
-
-#ifdef SAX2
-    /* propagate namespaces down the entity */
-    for (i = 0;i < oldctxt->nsNr;i += 2) {
-        nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]);
-    }
-#endif
-
-    oldsax = ctxt->sax;
-    ctxt->sax = oldctxt->sax;
-    xmlDetectSAX2(ctxt);
-    ctxt->replaceEntities = oldctxt->replaceEntities;
-    ctxt->options = oldctxt->options;
-
-    ctxt->_private = oldctxt->_private;
-    if (oldctxt->myDoc == NULL) {
-	newDoc = xmlNewDoc(BAD_CAST "1.0");
-	if (newDoc == NULL) {
-	    ctxt->sax = oldsax;
-	    ctxt->dict = NULL;
-	    xmlFreeParserCtxt(ctxt);
-	    return(XML_ERR_INTERNAL_ERROR);
-	}
-	newDoc->properties = XML_DOC_INTERNAL;
-	newDoc->dict = ctxt->dict;
-	xmlDictReference(newDoc->dict);
-	ctxt->myDoc = newDoc;
-    } else {
-	ctxt->myDoc = oldctxt->myDoc;
-        content = ctxt->myDoc->children;
-	last = ctxt->myDoc->last;
-    }
-    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
-    if (newRoot == NULL) {
-	ctxt->sax = oldsax;
-	ctxt->dict = NULL;
-	xmlFreeParserCtxt(ctxt);
-	if (newDoc != NULL) {
-	    xmlFreeDoc(newDoc);
-	}
-	return(XML_ERR_INTERNAL_ERROR);
-    }
-    ctxt->myDoc->children = NULL;
-    ctxt->myDoc->last = NULL;
-    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
-    nodePush(ctxt, ctxt->myDoc->children);
-    ctxt->instate = XML_PARSER_CONTENT;
-    ctxt->depth = oldctxt->depth + 1;
+        xmlFreeNodeList(list);
 
-    ctxt->validate = 0;
-    ctxt->loadsubset = oldctxt->loadsubset;
-    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
-	/*
-	 * ID/IDREF registration will be done in xmlValidateElement below
-	 */
-	ctxt->loadsubset |= XML_SKIP_IDS;
-    }
-    ctxt->dictNames = oldctxt->dictNames;
-    ctxt->attsDefault = oldctxt->attsDefault;
-    ctxt->attsSpecial = oldctxt->attsSpecial;
+    xmlFreeInputStream(input);
+    return(ctxt->errNo);
+}
 
-    xmlParseContent(ctxt);
-    if ((RAW == '<') && (NXT(1) == '/')) {
-	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
-    } else if (RAW != 0) {
-	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
-    }
-    if (ctxt->node != ctxt->myDoc->children) {
-	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
-    }
+#ifdef LIBXML_SAX1_ENABLED
+/**
+ * xmlParseExternalEntity:
+ * @doc:  the document the chunk pertains to
+ * @sax:  the SAX handler block (possibly NULL)
+ * @user_data:  The user data returned on SAX callbacks (possibly NULL)
+ * @depth:  Used for loop detection, use 0
+ * @URL:  the URL for the entity to load
+ * @ID:  the System ID for the entity to load
+ * @list:  the return value for the set of parsed nodes
+ *
+ * DEPRECATED: Use xmlParseCtxtExternalEntity.
+ *
+ * Parse an external general entity
+ * An external general parsed entity is well-formed if it matches the
+ * production labeled extParsedEnt.
+ *
+ * [78] extParsedEnt ::= TextDecl? content
+ *
+ * Returns 0 if the entity is well formed, -1 in case of args problem and
+ *    the parser error code otherwise
+ */
 
-    if (!ctxt->wellFormed) {
-        if (ctxt->errNo == 0)
-	    ret = XML_ERR_INTERNAL_ERROR;
-	else
-	    ret = (xmlParserErrors)ctxt->errNo;
-    } else {
-      ret = XML_ERR_OK;
-    }
+int
+xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
+	  int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *list) {
+    xmlParserCtxtPtr ctxt;
+    int ret;
 
-    if ((lst != NULL) && (ret == XML_ERR_OK)) {
-	xmlNodePtr cur;
+    if (list != NULL)
+        *list = NULL;
 
-	/*
-	 * Return the newly created nodeset after unlinking it from
-	 * they pseudo parent.
-	 */
-	cur = ctxt->myDoc->children->children;
-	*lst = cur;
-	while (cur != NULL) {
-#ifdef LIBXML_VALID_ENABLED
-	    if ((oldctxt->validate) && (oldctxt->wellFormed) &&
-		(oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
-		(cur->type == XML_ELEMENT_NODE)) {
-		oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
-			oldctxt->myDoc, cur);
-	    }
-#endif /* LIBXML_VALID_ENABLED */
-	    cur->parent = NULL;
-	    cur = cur->next;
-	}
-	ctxt->myDoc->children->children = NULL;
-    }
-    if (ctxt->myDoc != NULL) {
-	xmlFreeNode(ctxt->myDoc->children);
-        ctxt->myDoc->children = content;
-        ctxt->myDoc->last = last;
-    }
+    if (doc == NULL)
+        return(XML_ERR_ARGUMENT);
 
-    /*
-     * Record in the parent context the number of entities replacement
-     * done when parsing that reference.
-     */
-    if (oldctxt != NULL)
-        oldctxt->nbentities += ctxt->nbentities;
+    ctxt = xmlNewSAXParserCtxt(sax, user_data);
+    if (ctxt == NULL)
+        return(XML_ERR_NO_MEMORY);
 
-    /*
-     * Also record the last error if any
-     */
-    if (ctxt->lastError.code != XML_ERR_OK)
-        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
+    ctxt->depth = depth;
+    ctxt->myDoc = doc;
+    ret = xmlParseCtxtExternalEntity(ctxt, URL, ID, list);
 
-    ctxt->sax = oldsax;
-    ctxt->dict = NULL;
-    ctxt->attsDefault = NULL;
-    ctxt->attsSpecial = NULL;
     xmlFreeParserCtxt(ctxt);
-    if (newDoc != NULL) {
-	xmlFreeDoc(newDoc);
-    }
-
     return(ret);
 }
 
+/**
+ * xmlParseBalancedChunkMemory:
+ * @doc:  the document the chunk pertains to (must not be NULL)
+ * @sax:  the SAX handler block (possibly NULL)
+ * @user_data:  The user data returned on SAX callbacks (possibly NULL)
+ * @depth:  Used for loop detection, use 0
+ * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
+ * @lst:  the return value for the set of parsed nodes
+ *
+ * Parse a well-balanced chunk of an XML document
+ * called by the parser
+ * The allowed sequence for the Well Balanced Chunk is the one defined by
+ * the content production in the XML grammar:
+ *
+ * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
+ *
+ * Returns 0 if the chunk is well balanced, -1 in case of args problem and
+ *    the parser error code otherwise
+ */
+
+int
+xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
+     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
+    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
+                                                depth, string, lst, 0 );
+}
+#endif /* LIBXML_SAX1_ENABLED */
+
 /**
  * xmlParseInNodeContext:
  * @node:  the context node
@@ -13486,7 +12299,6 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
 xmlParserErrors
 xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
                       int options, xmlNodePtr *lst) {
-#ifdef SAX2
     xmlParserCtxtPtr ctxt;
     xmlDocPtr doc = NULL;
     xmlNodePtr fake, cur;
@@ -13498,7 +12310,7 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
      * check all input parameters, grab the document
      */
     if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
-        return(XML_ERR_INTERNAL_ERROR);
+        return(XML_ERR_ARGUMENT);
     switch (node->type) {
         case XML_ELEMENT_NODE:
         case XML_ATTRIBUTE_NODE:
@@ -13551,37 +12363,30 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
 
     /*
      * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
-     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
+     * We need a dictionary for xmlCtxtInitializeLate, so if there's no doc dict
      * we must wait until the last moment to free the original one.
      */
     if (doc->dict != NULL) {
         if (ctxt->dict != NULL)
 	    xmlDictFree(ctxt->dict);
 	ctxt->dict = doc->dict;
-    } else
+    } else {
         options |= XML_PARSE_NODICT;
-
-    if (doc->encoding != NULL) {
-        xmlCharEncodingHandlerPtr hdlr;
-
-        if (ctxt->encoding != NULL)
-	    xmlFree((xmlChar *) ctxt->encoding);
-        ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
-
-        hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding);
-        if (hdlr != NULL) {
-            xmlSwitchToEncoding(ctxt, hdlr);
-	} else {
-            return(XML_ERR_UNSUPPORTED_ENCODING);
-        }
+        ctxt->dictNames = 0;
     }
 
-    xmlCtxtUseOptionsInternal(ctxt, options, NULL);
-    xmlDetectSAX2(ctxt);
+    if (doc->encoding != NULL)
+        xmlSwitchEncodingName(ctxt, (const char *) doc->encoding);
+
+    xmlCtxtUseOptions(ctxt, options);
+    xmlCtxtInitializeLate(ctxt);
     ctxt->myDoc = doc;
     /* parsing in context, i.e. as within existing content */
     ctxt->input_id = 2;
-    ctxt->instate = XML_PARSER_CONTENT;
+
+    /*
+     * TODO: Use xmlCtxtParseContent
+     */
 
     fake = xmlNewDocComment(node->doc, NULL);
     if (fake == NULL) {
@@ -13590,29 +12395,23 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
     }
     xmlAddChild(node, fake);
 
-    if (node->type == XML_ELEMENT_NODE) {
+    if (node->type == XML_ELEMENT_NODE)
 	nodePush(ctxt, node);
+
+    if ((ctxt->html == 0) && (node->type == XML_ELEMENT_NODE)) {
 	/*
 	 * initialize the SAX2 namespaces stack
 	 */
 	cur = node;
 	while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
 	    xmlNsPtr ns = cur->nsDef;
-	    const xmlChar *iprefix, *ihref;
+            xmlHashedString hprefix, huri;
 
 	    while (ns != NULL) {
-		if (ctxt->dict) {
-		    iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
-		    ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
-		} else {
-		    iprefix = ns->prefix;
-		    ihref = ns->href;
-		}
-
-	        if (xmlGetNamespace(ctxt, iprefix) == NULL) {
-		    nsPush(ctxt, iprefix, ihref);
-		    nsnr++;
-		}
+                hprefix = xmlDictLookupHashed(ctxt->dict, ns->prefix, -1);
+                huri = xmlDictLookupHashed(ctxt->dict, ns->href, -1);
+                if (xmlParserNsPush(ctxt, &hprefix, &huri, ns, 1) > 0)
+                    nsnr++;
 		ns = ns->next;
 	    }
 	    cur = cur->parent;
@@ -13631,26 +12430,18 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
         __htmlParseContent(ctxt);
     else
 #endif
-	xmlParseContent(ctxt);
+	xmlParseContentInternal(ctxt);
 
-    nsPop(ctxt, nsnr);
-    if ((RAW == '<') && (NXT(1) == '/')) {
-	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
-    } else if (RAW != 0) {
-	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
-    }
-    if ((ctxt->node != NULL) && (ctxt->node != node)) {
+    if (ctxt->input->cur < ctxt->input->end)
 	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
-	ctxt->wellFormed = 0;
-    }
 
-    if (!ctxt->wellFormed) {
-        if (ctxt->errNo == 0)
-	    ret = XML_ERR_INTERNAL_ERROR;
-	else
-	    ret = (xmlParserErrors)ctxt->errNo;
-    } else {
+    xmlParserNsPop(ctxt, nsnr);
+
+    if ((ctxt->wellFormed) ||
+        ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) {
         ret = XML_ERR_OK;
+    } else {
+	ret = (xmlParserErrors) ctxt->errNo;
     }
 
     /*
@@ -13687,9 +12478,6 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
     xmlFreeParserCtxt(ctxt);
 
     return(ret);
-#else /* !SAX2 */
-    return(XML_ERR_INTERNAL_ERROR);
-#endif
 }
 
 #ifdef LIBXML_SAX1_ENABLED
@@ -13700,19 +12488,18 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
  * @depth:  Used for loop detection, use 0
  * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
- * @lst:  the return value for the set of parsed nodes
+ * @listOut:  the return value for the set of parsed nodes
  * @recover: return nodes even if the data is broken (use 0)
  *
- *
  * Parse a well-balanced chunk of an XML document
- * called by the parser
+ *
  * The allowed sequence for the Well Balanced Chunk is the one defined by
  * the content production in the XML grammar:
  *
  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
  *
- * Returns 0 if the chunk is well balanced, -1 in case of args problem and
- *    the parser error code otherwise
+ * Returns 0 if the chunk is well balanced, or thehe parser error code
+ * otherwise.
  *
  * In case recover is set to 1, the nodelist will not be empty even if
  * the parsed chunk is not well balanced, assuming the parsing succeeded to
@@ -13720,144 +12507,49 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
  */
 int
 xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
-     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
+     void *user_data, int depth, const xmlChar *string, xmlNodePtr *listOut,
      int recover) {
     xmlParserCtxtPtr ctxt;
-    xmlDocPtr newDoc;
-    xmlSAXHandlerPtr oldsax = NULL;
-    xmlNodePtr content, newRoot;
-    int size;
-    int ret = 0;
-
-    if (depth > 40) {
-	return(XML_ERR_ENTITY_LOOP);
-    }
+    xmlParserInputPtr input;
+    xmlNodePtr list;
+    int ret;
 
+    if (listOut != NULL)
+        *listOut = NULL;
 
-    if (lst != NULL)
-        *lst = NULL;
     if (string == NULL)
-        return(-1);
+        return(XML_ERR_ARGUMENT);
 
-    size = xmlStrlen(string);
-
-    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
-    if (ctxt == NULL) return(-1);
-    ctxt->userData = ctxt;
-    if (sax != NULL) {
-	oldsax = ctxt->sax;
-        ctxt->sax = sax;
-	if (user_data != NULL)
-	    ctxt->userData = user_data;
-    }
-    newDoc = xmlNewDoc(BAD_CAST "1.0");
-    if (newDoc == NULL) {
-	xmlFreeParserCtxt(ctxt);
-	return(-1);
-    }
-    newDoc->properties = XML_DOC_INTERNAL;
-    if ((doc != NULL) && (doc->dict != NULL)) {
-        xmlDictFree(ctxt->dict);
-	ctxt->dict = doc->dict;
-	xmlDictReference(ctxt->dict);
-	ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
-	ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
-	ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
-	ctxt->dictNames = 1;
-    } else {
-	xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
-    }
-    /* doc == NULL is only supported for historic reasons */
-    if (doc != NULL) {
-	newDoc->intSubset = doc->intSubset;
-	newDoc->extSubset = doc->extSubset;
-    }
-    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
-    if (newRoot == NULL) {
-	if (sax != NULL)
-	    ctxt->sax = oldsax;
-	xmlFreeParserCtxt(ctxt);
-	newDoc->intSubset = NULL;
-	newDoc->extSubset = NULL;
-        xmlFreeDoc(newDoc);
-	return(-1);
-    }
-    xmlAddChild((xmlNodePtr) newDoc, newRoot);
-    nodePush(ctxt, newRoot);
-    /* doc == NULL is only supported for historic reasons */
-    if (doc == NULL) {
-	ctxt->myDoc = newDoc;
-    } else {
-	ctxt->myDoc = newDoc;
-	newDoc->children->doc = doc;
-	/* Ensure that doc has XML spec namespace */
-	xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
-	newDoc->oldNs = doc->oldNs;
-    }
-    ctxt->instate = XML_PARSER_CONTENT;
-    ctxt->input_id = 2;
-    ctxt->depth = depth;
+    ctxt = xmlNewSAXParserCtxt(sax, user_data);
+    if (ctxt == NULL)
+        return(XML_ERR_NO_MEMORY);
 
-    /*
-     * Doing validity checking on chunk doesn't make sense
-     */
-    ctxt->validate = 0;
-    ctxt->loadsubset = 0;
-    xmlDetectSAX2(ctxt);
+    xmlCtxtInitializeLate(ctxt);
 
-    if ( doc != NULL ){
-        content = doc->children;
-        doc->children = NULL;
-        xmlParseContent(ctxt);
-        doc->children = content;
-    }
-    else {
-        xmlParseContent(ctxt);
-    }
-    if ((RAW == '<') && (NXT(1) == '/')) {
-	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
-    } else if (RAW != 0) {
-	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
-    }
-    if (ctxt->node != newDoc->children) {
-	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+    ctxt->depth = depth;
+    ctxt->myDoc = doc;
+    if (recover) {
+        ctxt->options |= XML_PARSE_RECOVER;
+        ctxt->recovery = 1;
     }
 
-    if (!ctxt->wellFormed) {
-        if (ctxt->errNo == 0)
-	    ret = 1;
-	else
-	    ret = ctxt->errNo;
-    } else {
-      ret = 0;
-    }
+    input = xmlNewStringInputStream(ctxt, string);
+    if (input == NULL)
+        return(ctxt->errNo);
 
-    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
-	xmlNodePtr cur;
+    list = xmlCtxtParseContent(ctxt, input, /* hasTextDecl */ 0, 1);
+    if (listOut != NULL)
+        *listOut = list;
+    else
+        xmlFreeNodeList(list);
 
-	/*
-	 * Return the newly created nodeset after unlinking it from
-	 * they pseudo parent.
-	 */
-	cur = newDoc->children->children;
-	*lst = cur;
-	while (cur != NULL) {
-	    xmlSetTreeDoc(cur, doc);
-	    cur->parent = NULL;
-	    cur = cur->next;
-	}
-	newDoc->children->children = NULL;
-    }
+    if (!ctxt->wellFormed)
+        ret = ctxt->errNo;
+    else
+        ret = XML_ERR_OK;
 
-    if (sax != NULL)
-	ctxt->sax = oldsax;
+    xmlFreeInputStream(input);
     xmlFreeParserCtxt(ctxt);
-    newDoc->intSubset = NULL;
-    newDoc->extSubset = NULL;
-    /* This leaks the namespace list if doc == NULL */
-    newDoc->oldNs = NULL;
-    xmlFreeDoc(newDoc);
-
     return(ret);
 }
 
@@ -13866,6 +12558,8 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
  * @sax:  the SAX handler block
  * @filename:  the filename
  *
+ * DEPRECATED: Don't use.
+ *
  * parse an XML external entity out of context and build a tree.
  * It use the given SAX function block to handle the parsing callback.
  * If sax is NULL, fallback to the default DOM tree building routines.
@@ -13887,23 +12581,24 @@ xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
 	return(NULL);
     }
     if (sax != NULL) {
-	if (ctxt->sax != NULL)
-	    xmlFree(ctxt->sax);
-        ctxt->sax = sax;
+        if (sax->initialized == XML_SAX2_MAGIC) {
+            *ctxt->sax = *sax;
+        } else {
+            memset(ctxt->sax, 0, sizeof(*ctxt->sax));
+            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
+        }
         ctxt->userData = NULL;
     }
 
     xmlParseExtParsedEnt(ctxt);
 
-    if (ctxt->wellFormed)
+    if (ctxt->wellFormed) {
 	ret = ctxt->myDoc;
-    else {
+    } else {
         ret = NULL;
         xmlFreeDoc(ctxt->myDoc);
-        ctxt->myDoc = NULL;
     }
-    if (sax != NULL)
-        ctxt->sax = NULL;
+
     xmlFreeParserCtxt(ctxt);
 
     return(ret);
@@ -13929,11 +12624,12 @@ xmlParseEntity(const char *filename) {
 #endif /* LIBXML_SAX1_ENABLED */
 
 /**
- * xmlCreateEntityParserCtxtInternal:
+ * xmlCreateEntityParserCtxt:
  * @URL:  the entity URL
  * @ID:  the entity PUBLIC ID
  * @base:  a possible base for the target URI
- * @pctx:  parser context used to set options on new context
+ *
+ * DEPRECATED: Don't use.
  *
  * Create a parser context for an external entity
  * Automatic support for ZLIB/Compress compressed document is provided
@@ -13941,84 +12637,38 @@ xmlParseEntity(const char *filename) {
  *
  * Returns the new parser context or NULL
  */
-static xmlParserCtxtPtr
-xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
-	                  const xmlChar *base, xmlParserCtxtPtr pctx) {
+xmlParserCtxtPtr
+xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
+	                  const xmlChar *base) {
     xmlParserCtxtPtr ctxt;
-    xmlParserInputPtr inputStream;
-    char *directory = NULL;
-    xmlChar *uri;
+    xmlParserInputPtr input;
+    xmlChar *uri = NULL;
 
     ctxt = xmlNewParserCtxt();
-    if (ctxt == NULL) {
+    if (ctxt == NULL)
 	return(NULL);
-    }
 
-    if (pctx != NULL) {
-        ctxt->options = pctx->options;
-        ctxt->_private = pctx->_private;
-	/*
-	 * this is a subparser of pctx, so the input_id should be
-	 * incremented to distinguish from main entity
-	 */
-	ctxt->input_id = pctx->input_id + 1;
+    if (base != NULL) {
+        if (xmlBuildURISafe(URL, base, &uri) < 0)
+            goto error;
+        if (uri != NULL)
+            URL = uri;
     }
 
-    /* Don't read from stdin. */
-    if (xmlStrcmp(URL, BAD_CAST "-") == 0)
-        URL = BAD_CAST "./-";
-
-    uri = xmlBuildURI(URL, base);
-
-    if (uri == NULL) {
-	inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
-	if (inputStream == NULL) {
-	    xmlFreeParserCtxt(ctxt);
-	    return(NULL);
-	}
-
-	inputPush(ctxt, inputStream);
-
-	if ((ctxt->directory == NULL) && (directory == NULL))
-	    directory = xmlParserGetDirectory((char *)URL);
-	if ((ctxt->directory == NULL) && (directory != NULL))
-	    ctxt->directory = directory;
-    } else {
-	inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
-	if (inputStream == NULL) {
-	    xmlFree(uri);
-	    xmlFreeParserCtxt(ctxt);
-	    return(NULL);
-	}
+    input = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
+    if (input == NULL)
+        goto error;
 
-	inputPush(ctxt, inputStream);
+    if (inputPush(ctxt, input) < 0)
+        goto error;
 
-	if ((ctxt->directory == NULL) && (directory == NULL))
-	    directory = xmlParserGetDirectory((char *)uri);
-	if ((ctxt->directory == NULL) && (directory != NULL))
-	    ctxt->directory = directory;
-	xmlFree(uri);
-    }
+    xmlFree(uri);
     return(ctxt);
-}
-
-/**
- * xmlCreateEntityParserCtxt:
- * @URL:  the entity URL
- * @ID:  the entity PUBLIC ID
- * @base:  a possible base for the target URI
- *
- * Create a parser context for an external entity
- * Automatic support for ZLIB/Compress compressed document is provided
- * by default if found at compile-time.
- *
- * Returns the new parser context or NULL
- */
-xmlParserCtxtPtr
-xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
-	                  const xmlChar *base) {
-    return xmlCreateEntityParserCtxtInternal(URL, ID, base, NULL);
 
+error:
+    xmlFree(uri);
+    xmlFreeParserCtxt(ctxt);
+    return(NULL);
 }
 
 /************************************************************************
@@ -14032,6 +12682,8 @@ xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
  * @filename:  the filename or URL
  * @options:  a combination of xmlParserOption
  *
+ * DEPRECATED: Use xmlNewParserCtxt and xmlCtxtReadFile.
+ *
  * Create a parser context for a file or URL content.
  * Automatic support for ZLIB/Compress compressed document is provided
  * by default if found at compile-time and for file accesses
@@ -14042,30 +12694,21 @@ xmlParserCtxtPtr
 xmlCreateURLParserCtxt(const char *filename, int options)
 {
     xmlParserCtxtPtr ctxt;
-    xmlParserInputPtr inputStream;
-    char *directory = NULL;
+    xmlParserInputPtr input;
 
     ctxt = xmlNewParserCtxt();
-    if (ctxt == NULL) {
-	xmlErrMemory(NULL, "cannot allocate parser context");
+    if (ctxt == NULL)
 	return(NULL);
-    }
 
-    if (options)
-	xmlCtxtUseOptionsInternal(ctxt, options, NULL);
+    xmlCtxtUseOptions(ctxt, options);
     ctxt->linenumbers = 1;
 
-    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
-    if (inputStream == NULL) {
+    input = xmlLoadExternalEntity(filename, NULL, ctxt);
+    if (input == NULL) {
 	xmlFreeParserCtxt(ctxt);
 	return(NULL);
     }
-
-    inputPush(ctxt, inputStream);
-    if ((ctxt->directory == NULL) && (directory == NULL))
-        directory = xmlParserGetDirectory(filename);
-    if ((ctxt->directory == NULL) && (directory != NULL))
-        ctxt->directory = directory;
+    inputPush(ctxt, input);
 
     return(ctxt);
 }
@@ -14074,6 +12717,8 @@ xmlCreateURLParserCtxt(const char *filename, int options)
  * xmlCreateFileParserCtxt:
  * @filename:  the filename
  *
+ * DEPRECATED: Use xmlNewParserCtxt and xmlCtxtReadFile.
+ *
  * Create a parser context for a file content.
  * Automatic support for ZLIB/Compress compressed document is provided
  * by default if found at compile-time.
@@ -14095,6 +12740,8 @@ xmlCreateFileParserCtxt(const char *filename)
  *             documents
  * @data:  the userdata
  *
+ * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
+ *
  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
  * compressed document is provided by default if found at compile-time.
  * It use the given SAX function block to handle the parsing callback.
@@ -14111,48 +12758,28 @@ xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
                         int recovery, void *data) {
     xmlDocPtr ret;
     xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
 
-    xmlInitParser();
-
-    ctxt = xmlCreateFileParserCtxt(filename);
-    if (ctxt == NULL) {
+    ctxt = xmlNewSAXParserCtxt(sax, NULL);
+    if (ctxt == NULL)
 	return(NULL);
-    }
-    if (sax != NULL) {
-	if (ctxt->sax != NULL)
-	    xmlFree(ctxt->sax);
-        ctxt->sax = sax;
-    }
-    xmlDetectSAX2(ctxt);
-    if (data!=NULL) {
-	ctxt->_private = data;
-    }
-
-    if (ctxt->directory == NULL)
-        ctxt->directory = xmlParserGetDirectory(filename);
 
-    ctxt->recovery = recovery;
-
-    xmlParseDocument(ctxt);
+    if (data != NULL)
+	ctxt->_private = data;
 
-    if ((ctxt->wellFormed) || recovery) {
-        ret = ctxt->myDoc;
-	if ((ret != NULL) && (ctxt->input->buf != NULL)) {
-	    if (ctxt->input->buf->compressed > 0)
-		ret->compression = 9;
-	    else
-		ret->compression = ctxt->input->buf->compressed;
-	}
-    }
-    else {
-       ret = NULL;
-       xmlFreeDoc(ctxt->myDoc);
-       ctxt->myDoc = NULL;
+    if (recovery) {
+        ctxt->options |= XML_PARSE_RECOVER;
+        ctxt->recovery = 1;
     }
-    if (sax != NULL)
-        ctxt->sax = NULL;
-    xmlFreeParserCtxt(ctxt);
 
+    if ((filename != NULL) && (filename[0] == '-') && (filename[1] == 0))
+        input = xmlNewInputFd(ctxt, filename, STDIN_FILENO, NULL, 0);
+    else
+        input = xmlNewInputURL(ctxt, filename, NULL, NULL, 0);
+
+    ret = xmlCtxtParseDocument(ctxt, input);
+
+    xmlFreeParserCtxt(ctxt);
     return(ret);
 }
 
@@ -14163,6 +12790,8 @@ xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
  *             documents
  *
+ * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
+ *
  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
  * compressed document is provided by default if found at compile-time.
  * It use the given SAX function block to handle the parsing callback.
@@ -14181,6 +12810,8 @@ xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
  * xmlRecoverDoc:
  * @cur:  a pointer to an array of xmlChar
  *
+ * DEPRECATED: Use xmlReadDoc with XML_PARSE_RECOVER.
+ *
  * parse an XML in-memory document and build a tree.
  * In the case the document is not Well Formed, a attempt to build a
  * tree is tried anyway
@@ -14197,6 +12828,8 @@ xmlRecoverDoc(const xmlChar *cur) {
  * xmlParseFile:
  * @filename:  the filename
  *
+ * DEPRECATED: Use xmlReadFile.
+ *
  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
  * compressed document is provided by default if found at compile-time.
  *
@@ -14213,6 +12846,8 @@ xmlParseFile(const char *filename) {
  * xmlRecoverFile:
  * @filename:  the filename
  *
+ * DEPRECATED: Use xmlReadFile with XML_PARSE_RECOVER.
+ *
  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
  * compressed document is provided by default if found at compile-time.
  * In the case the document is not Well Formed, it attempts to build
@@ -14233,6 +12868,8 @@ xmlRecoverFile(const char *filename) {
  * @buffer:  a xmlChar * buffer
  * @filename:  a file name
  *
+ * DEPRECATED: Don't use.
+ *
  * Setup the parser context to parse a new buffer; Clears any prior
  * contents from the parser context. The buffer parameter must not be
  * NULL, but the filename parameter can be
@@ -14246,19 +12883,11 @@ xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
     if ((ctxt == NULL) || (buffer == NULL))
         return;
 
-    input = xmlNewInputStream(ctxt);
-    if (input == NULL) {
-        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
-        xmlClearParserCtxt(ctxt);
-        return;
-    }
-
     xmlClearParserCtxt(ctxt);
-    if (filename != NULL)
-        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
-    input->base = buffer;
-    input->cur = buffer;
-    input->end = &buffer[xmlStrlen(buffer)];
+
+    input = xmlNewInputString(ctxt, filename, (const char *) buffer, NULL, 0);
+    if (input == NULL)
+        return;
     inputPush(ctxt, input);
 }
 
@@ -14268,6 +12897,8 @@ xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
  * @user_data:  The user data returned on SAX callbacks
  * @filename:  a file name
  *
+ * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
+ *
  * parse an XML file and call the given SAX handler routines.
  * Automatic support for ZLIB/Compress compressed document is provided
  *
@@ -14281,13 +12912,15 @@ xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
 
     ctxt = xmlCreateFileParserCtxt(filename);
     if (ctxt == NULL) return -1;
-    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
-	xmlFree(ctxt->sax);
-    ctxt->sax = sax;
-    xmlDetectSAX2(ctxt);
-
-    if (user_data != NULL)
+    if (sax != NULL) {
+        if (sax->initialized == XML_SAX2_MAGIC) {
+            *ctxt->sax = *sax;
+        } else {
+            memset(ctxt->sax, 0, sizeof(*ctxt->sax));
+            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
+        }
 	ctxt->userData = user_data;
+    }
 
     xmlParseDocument(ctxt);
 
@@ -14299,8 +12932,6 @@ xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
 	else
 	    ret = -1;
     }
-    if (sax != NULL)
-	ctxt->sax = NULL;
     if (ctxt->myDoc != NULL) {
         xmlFreeDoc(ctxt->myDoc);
 	ctxt->myDoc = NULL;
@@ -14322,7 +12953,8 @@ xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
  * @buffer:  a pointer to a char array
  * @size:  the size of the array
  *
- * Create a parser context for an XML in-memory document.
+ * Create a parser context for an XML in-memory document. The input buffer
+ * must not contain a terminating null byte.
  *
  * Returns the new parser context or NULL
  */
@@ -14330,36 +12962,21 @@ xmlParserCtxtPtr
 xmlCreateMemoryParserCtxt(const char *buffer, int size) {
     xmlParserCtxtPtr ctxt;
     xmlParserInputPtr input;
-    xmlParserInputBufferPtr buf;
 
-    if (buffer == NULL)
-	return(NULL);
-    if (size <= 0)
+    if (size < 0)
 	return(NULL);
 
     ctxt = xmlNewParserCtxt();
     if (ctxt == NULL)
 	return(NULL);
 
-    /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
-    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
-    if (buf == NULL) {
-	xmlFreeParserCtxt(ctxt);
-	return(NULL);
-    }
-
-    input = xmlNewInputStream(ctxt);
+    input = xmlNewInputMemory(ctxt, NULL, buffer, size, NULL, 0);
     if (input == NULL) {
-	xmlFreeParserInputBuffer(buf);
 	xmlFreeParserCtxt(ctxt);
 	return(NULL);
     }
-
-    input->filename = NULL;
-    input->buf = buf;
-    xmlBufResetInput(input->buf->buffer, input);
-
     inputPush(ctxt, input);
+
     return(ctxt);
 }
 
@@ -14373,6 +12990,8 @@ xmlCreateMemoryParserCtxt(const char *buffer, int size) {
  *             documents
  * @data:  the userdata
  *
+ * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
+ *
  * parse an XML in-memory block and use the given SAX function block
  * to handle the parsing callback. If sax is NULL, fallback to the default
  * DOM tree building routines.
@@ -14385,38 +13004,32 @@ xmlCreateMemoryParserCtxt(const char *buffer, int size) {
 
 xmlDocPtr
 xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
-	          int size, int recovery, void *data) {
+                          int size, int recovery, void *data) {
     xmlDocPtr ret;
     xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
 
-    xmlInitParser();
+    if (size < 0)
+        return(NULL);
 
-    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
-    if (ctxt == NULL) return(NULL);
-    if (sax != NULL) {
-	if (ctxt->sax != NULL)
-	    xmlFree(ctxt->sax);
-        ctxt->sax = sax;
-    }
-    xmlDetectSAX2(ctxt);
-    if (data!=NULL) {
+    ctxt = xmlNewSAXParserCtxt(sax, NULL);
+    if (ctxt == NULL)
+        return(NULL);
+
+    if (data != NULL)
 	ctxt->_private=data;
+
+    if (recovery) {
+        ctxt->options |= XML_PARSE_RECOVER;
+        ctxt->recovery = 1;
     }
 
-    ctxt->recovery = recovery;
+    input = xmlNewInputMemory(ctxt, NULL, buffer, size, NULL,
+                              XML_INPUT_BUF_STATIC);
 
-    xmlParseDocument(ctxt);
+    ret = xmlCtxtParseDocument(ctxt, input);
 
-    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
-    else {
-       ret = NULL;
-       xmlFreeDoc(ctxt->myDoc);
-       ctxt->myDoc = NULL;
-    }
-    if (sax != NULL)
-	ctxt->sax = NULL;
     xmlFreeParserCtxt(ctxt);
-
     return(ret);
 }
 
@@ -14428,6 +13041,8 @@ xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
  * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
  *             documents
  *
+ * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
+ *
  * parse an XML in-memory block and use the given SAX function block
  * to handle the parsing callback. If sax is NULL, fallback to the default
  * DOM tree building routines.
@@ -14445,6 +13060,8 @@ xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
  * @buffer:  an pointer to a char array
  * @size:  the size of the array
  *
+ * DEPRECATED: Use xmlReadMemory.
+ *
  * parse an XML in-memory block and build a tree.
  *
  * Returns the resulting document tree
@@ -14459,6 +13076,8 @@ xmlDocPtr xmlParseMemory(const char *buffer, int size) {
  * @buffer:  an pointer to a char array
  * @size:  the size of the array
  *
+ * DEPRECATED: Use xmlReadMemory with XML_PARSE_RECOVER.
+ *
  * parse an XML in-memory block and build a tree.
  * In the case the document is not Well Formed, an attempt to
  * build a tree is tried anyway
@@ -14477,7 +13096,8 @@ xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
  * @buffer:  an in-memory XML document input
  * @size:  the length of the XML document in bytes
  *
- * A better SAX parsing routine.
+ * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
+ *
  * parse an XML in-memory buffer and call the given SAX handler routines.
  *
  * Returns 0 in case of success or a error number otherwise
@@ -14487,17 +13107,17 @@ int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
     int ret = 0;
     xmlParserCtxtPtr ctxt;
 
-    xmlInitParser();
-
     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
     if (ctxt == NULL) return -1;
-    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
-        xmlFree(ctxt->sax);
-    ctxt->sax = sax;
-    xmlDetectSAX2(ctxt);
-
-    if (user_data != NULL)
+    if (sax != NULL) {
+        if (sax->initialized == XML_SAX2_MAGIC) {
+            *ctxt->sax = *sax;
+        } else {
+            memset(ctxt->sax, 0, sizeof(*ctxt->sax));
+            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
+        }
 	ctxt->userData = user_data;
+    }
 
     xmlParseDocument(ctxt);
 
@@ -14509,8 +13129,6 @@ int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
 	else
 	    ret = -1;
     }
-    if (sax != NULL)
-        ctxt->sax = NULL;
     if (ctxt->myDoc != NULL) {
         xmlFreeDoc(ctxt->myDoc);
 	ctxt->myDoc = NULL;
@@ -14523,20 +13141,29 @@ int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
 
 /**
  * xmlCreateDocParserCtxt:
- * @cur:  a pointer to an array of xmlChar
+ * @str:  a pointer to an array of xmlChar
  *
  * Creates a parser context for an XML in-memory document.
  *
  * Returns the new parser context or NULL
  */
 xmlParserCtxtPtr
-xmlCreateDocParserCtxt(const xmlChar *cur) {
-    int len;
+xmlCreateDocParserCtxt(const xmlChar *str) {
+    xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
 
-    if (cur == NULL)
+    ctxt = xmlNewParserCtxt();
+    if (ctxt == NULL)
+	return(NULL);
+
+    input = xmlNewInputString(ctxt, NULL, (const char *) str, NULL, 0);
+    if (input == NULL) {
+	xmlFreeParserCtxt(ctxt);
 	return(NULL);
-    len = xmlStrlen(cur);
-    return(xmlCreateMemoryParserCtxt((const char *)cur, len));
+    }
+    inputPush(ctxt, input);
+
+    return(ctxt);
 }
 
 #ifdef LIBXML_SAX1_ENABLED
@@ -14547,6 +13174,8 @@ xmlCreateDocParserCtxt(const xmlChar *cur) {
  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
  *             documents
  *
+ * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadDoc.
+ *
  * parse an XML in-memory document and build a tree.
  * It use the given SAX function block to handle the parsing callback.
  * If sax is NULL, fallback to the default DOM tree building routines.
@@ -14570,7 +13199,6 @@ xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
         ctxt->sax = sax;
         ctxt->userData = NULL;
     }
-    xmlDetectSAX2(ctxt);
 
     xmlParseDocument(ctxt);
     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
@@ -14590,6 +13218,8 @@ xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
  * xmlParseDoc:
  * @cur:  a pointer to an array of xmlChar
  *
+ * DEPRECATED: Use xmlReadDoc.
+ *
  * parse an XML in-memory document and build a tree.
  *
  * Returns the resulting document tree
@@ -14601,169 +13231,6 @@ xmlParseDoc(const xmlChar *cur) {
 }
 #endif /* LIBXML_SAX1_ENABLED */
 
-#ifdef LIBXML_LEGACY_ENABLED
-/************************************************************************
- *									*
- *	Specific function to keep track of entities references		*
- *	and used by the XSLT debugger					*
- *									*
- ************************************************************************/
-
-static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
-
-/**
- * xmlAddEntityReference:
- * @ent : A valid entity
- * @firstNode : A valid first node for children of entity
- * @lastNode : A valid last node of children entity
- *
- * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
- */
-static void
-xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
-                      xmlNodePtr lastNode)
-{
-    if (xmlEntityRefFunc != NULL) {
-        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
-    }
-}
-
-
-/**
- * xmlSetEntityReferenceFunc:
- * @func: A valid function
- *
- * Set the function to call call back when a xml reference has been made
- */
-void
-xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
-{
-    xmlEntityRefFunc = func;
-}
-#endif /* LIBXML_LEGACY_ENABLED */
-
-/************************************************************************
- *									*
- *				Miscellaneous				*
- *									*
- ************************************************************************/
-
-#ifdef LIBXML_XPATH_ENABLED
-#include <libxml/xpath.h>
-#endif
-
-extern void XMLCDECL xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...);
-static int xmlParserInitialized = 0;
-
-/**
- * xmlInitParser:
- *
- * Initialization function for the XML parser.
- * This is not reentrant. Call once before processing in case of
- * use in multithreaded programs.
- */
-
-void
-xmlInitParser(void) {
-    if (xmlParserInitialized != 0)
-	return;
-
-#if defined(_WIN32) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
-    if (xmlFree == free)
-        atexit(xmlCleanupParser);
-#endif
-
-#ifdef LIBXML_THREAD_ENABLED
-    __xmlGlobalInitMutexLock();
-    if (xmlParserInitialized == 0) {
-#endif
-	xmlInitThreads();
-	xmlInitGlobals();
-	if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
-	    (xmlGenericError == NULL))
-	    initGenericErrorDefaultFunc(NULL);
-	xmlInitMemory();
-        xmlInitializeDict();
-	xmlInitCharEncodingHandlers();
-	xmlDefaultSAXHandlerInit();
-	xmlRegisterDefaultInputCallbacks();
-#ifdef LIBXML_OUTPUT_ENABLED
-	xmlRegisterDefaultOutputCallbacks();
-#endif /* LIBXML_OUTPUT_ENABLED */
-#ifdef LIBXML_HTML_ENABLED
-	htmlInitAutoClose();
-	htmlDefaultSAXHandlerInit();
-#endif
-#ifdef LIBXML_XPATH_ENABLED
-	xmlXPathInit();
-#endif
-	xmlParserInitialized = 1;
-#ifdef LIBXML_THREAD_ENABLED
-    }
-    __xmlGlobalInitMutexUnlock();
-#endif
-}
-
-/**
- * xmlCleanupParser:
- *
- * This function name is somewhat misleading. It does not clean up
- * parser state, it cleans up memory allocated by the library itself.
- * It is a cleanup function for the XML library. It tries to reclaim all
- * related global memory allocated for the library processing.
- * It doesn't deallocate any document related memory. One should
- * call xmlCleanupParser() only when the process has finished using
- * the library and all XML/HTML documents built with it.
- * See also xmlInitParser() which has the opposite function of preparing
- * the library for operations.
- *
- * WARNING: if your application is multithreaded or has plugin support
- *          calling this may crash the application if another thread or
- *          a plugin is still using libxml2. It's sometimes very hard to
- *          guess if libxml2 is in use in the application, some libraries
- *          or plugins may use it without notice. In case of doubt abstain
- *          from calling this function or do it just before calling exit()
- *          to avoid leak reports from valgrind !
- */
-
-void
-xmlCleanupParser(void) {
-    if (!xmlParserInitialized)
-	return;
-
-    xmlCleanupCharEncodingHandlers();
-#ifdef LIBXML_CATALOG_ENABLED
-    xmlCatalogCleanup();
-#endif
-    xmlDictCleanup();
-    xmlCleanupInputCallbacks();
-#ifdef LIBXML_OUTPUT_ENABLED
-    xmlCleanupOutputCallbacks();
-#endif
-#ifdef LIBXML_SCHEMAS_ENABLED
-    xmlSchemaCleanupTypes();
-    xmlRelaxNGCleanupTypes();
-#endif
-    xmlCleanupGlobals();
-    xmlCleanupThreads(); /* must be last if called not from the main thread */
-    xmlCleanupMemory();
-    xmlParserInitialized = 0;
-}
-
-#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && !defined(LIBXML_STATIC) && \
-    !defined(_WIN32)
-static void
-ATTRIBUTE_DESTRUCTOR
-xmlDestructor(void) {
-    /*
-     * Calling custom deallocation functions in a destructor can cause
-     * problems, for example with Nokogiri.
-     */
-    if (xmlFree == free)
-        xmlCleanupParser();
-}
-#endif
-
 /************************************************************************
  *									*
  *	New set (2.6.0) of simpler and more flexible APIs		*
@@ -14821,17 +13288,22 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
     ctxt->name = NULL;
 
     ctxt->nsNr = 0;
+    xmlParserNsReset(ctxt->nsdb);
 
     DICT_FREE(ctxt->version);
     ctxt->version = NULL;
     DICT_FREE(ctxt->encoding);
     ctxt->encoding = NULL;
-    DICT_FREE(ctxt->directory);
-    ctxt->directory = NULL;
     DICT_FREE(ctxt->extSubURI);
     ctxt->extSubURI = NULL;
     DICT_FREE(ctxt->extSubSystem);
     ctxt->extSubSystem = NULL;
+
+    if (ctxt->directory != NULL) {
+        xmlFree(ctxt->directory);
+        ctxt->directory = NULL;
+    }
+
     if (ctxt->myDoc != NULL)
         xmlFreeDoc(ctxt->myDoc);
     ctxt->myDoc = NULL;
@@ -14840,9 +13312,7 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
     ctxt->hasExternalSubset = 0;
     ctxt->hasPErefs = 0;
     ctxt->html = 0;
-    ctxt->external = 0;
     ctxt->instate = XML_PARSER_START;
-    ctxt->token = 0;
 
     ctxt->wellFormed = 1;
     ctxt->nsWellFormed = 1;
@@ -14855,12 +13325,11 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
 #endif
     ctxt->record_info = 0;
     ctxt->checkIndex = 0;
+    ctxt->endCheckState = 0;
     ctxt->inSubset = 0;
     ctxt->errNo = XML_ERR_OK;
     ctxt->depth = 0;
-    ctxt->charset = XML_CHAR_ENCODING_UTF8;
     ctxt->catalogs = NULL;
-    ctxt->nbentities = 0;
     ctxt->sizeentities = 0;
     ctxt->sizeentcopy = 0;
     xmlInitNodeInfoSeq(&ctxt->node_seq);
@@ -14878,6 +13347,8 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
     if (ctxt->catalogs != NULL)
 	xmlCatalogFreeLocal(ctxt->catalogs);
 #endif
+    ctxt->nbErrors = 0;
+    ctxt->nbWarnings = 0;
     if (ctxt->lastError.code != XML_ERR_OK)
         xmlResetError(&ctxt->lastError);
 }
@@ -14898,224 +13369,258 @@ int
 xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
                  int size, const char *filename, const char *encoding)
 {
-    xmlParserInputPtr inputStream;
-    xmlParserInputBufferPtr buf;
-    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
+    xmlParserInputPtr input;
 
     if (ctxt == NULL)
         return(1);
 
-    if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
-        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
-
-    buf = xmlAllocParserInputBuffer(enc);
-    if (buf == NULL)
-        return(1);
-
-    if (ctxt == NULL) {
-        xmlFreeParserInputBuffer(buf);
-        return(1);
-    }
-
     xmlCtxtReset(ctxt);
 
-    if (filename == NULL) {
-        ctxt->directory = NULL;
-    } else {
-        ctxt->directory = xmlParserGetDirectory(filename);
-    }
-
-    inputStream = xmlNewInputStream(ctxt);
-    if (inputStream == NULL) {
-        xmlFreeParserInputBuffer(buf);
+    input = xmlNewInputPush(ctxt, filename, chunk, size, encoding);
+    if (input == NULL)
         return(1);
-    }
-
-    if (filename == NULL)
-        inputStream->filename = NULL;
-    else
-        inputStream->filename = (char *)
-            xmlCanonicPath((const xmlChar *) filename);
-    inputStream->buf = buf;
-    xmlBufResetInput(buf->buffer, inputStream);
+    inputPush(ctxt, input);
 
-    inputPush(ctxt, inputStream);
+    return(0);
+}
 
-    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
-        (ctxt->input->buf != NULL)) {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
-        size_t cur = ctxt->input->cur - ctxt->input->base;
+static int
+xmlCtxtSetOptionsInternal(xmlParserCtxtPtr ctxt, int options, int keepMask)
+{
+    int allMask;
 
-        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
+    if (ctxt == NULL)
+        return(-1);
 
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
-#ifdef DEBUG_PUSH
-        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
+    /*
+     * XInclude options aren't handled by the parser.
+     *
+     * XML_PARSE_XINCLUDE
+     * XML_PARSE_NOXINCNODE
+     * XML_PARSE_NOBASEFIX
+     */
+    allMask = XML_PARSE_RECOVER |
+              XML_PARSE_NOENT |
+              XML_PARSE_DTDLOAD |
+              XML_PARSE_DTDATTR |
+              XML_PARSE_DTDVALID |
+              XML_PARSE_NOERROR |
+              XML_PARSE_NOWARNING |
+              XML_PARSE_PEDANTIC |
+              XML_PARSE_NOBLANKS |
+#ifdef LIBXML_SAX1_ENABLED
+              XML_PARSE_SAX1 |
 #endif
-    }
-
-    if (encoding != NULL) {
-        xmlCharEncodingHandlerPtr hdlr;
-
-        if (ctxt->encoding != NULL)
-	    xmlFree((xmlChar *) ctxt->encoding);
-        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
+              XML_PARSE_NONET |
+              XML_PARSE_NODICT |
+              XML_PARSE_NSCLEAN |
+              XML_PARSE_NOCDATA |
+              XML_PARSE_COMPACT |
+              XML_PARSE_OLD10 |
+              XML_PARSE_HUGE |
+              XML_PARSE_OLDSAX |
+              XML_PARSE_IGNORE_ENC |
+              XML_PARSE_BIG_LINES |
+              XML_PARSE_NO_XXE;
+
+    ctxt->options = (ctxt->options & keepMask) | (options & allMask);
+
+    /*
+     * For some options, struct members are historically the source
+     * of truth. The values are initalized from global variables and
+     * old code could also modify them directly. Several older API
+     * functions that don't take an options argument rely on these
+     * deprecated mechanisms.
+     *
+     * Once public access to struct members and the globals are
+     * disabled, we can use the options bitmask as source of
+     * truth, making all these struct members obsolete.
+     *
+     * The XML_DETECT_IDS flags is misnamed. It simply enables
+     * loading of the external subset.
+     */
+    ctxt->recovery = (options & XML_PARSE_RECOVER) ? 1 : 0;
+    ctxt->replaceEntities = (options & XML_PARSE_NOENT) ? 1 : 0;
+    ctxt->loadsubset = (options & XML_PARSE_DTDLOAD) ? XML_DETECT_IDS : 0;
+    ctxt->loadsubset |= (options & XML_PARSE_DTDATTR) ? XML_COMPLETE_ATTRS : 0;
+    ctxt->validate = (options & XML_PARSE_DTDVALID) ? 1 : 0;
+    ctxt->pedantic = (options & XML_PARSE_PEDANTIC) ? 1 : 0;
+    ctxt->keepBlanks = (options & XML_PARSE_NOBLANKS) ? 0 : 1;
+    ctxt->dictNames = (options & XML_PARSE_NODICT) ? 0 : 1;
 
-        hdlr = xmlFindCharEncodingHandler(encoding);
-        if (hdlr != NULL) {
-            xmlSwitchToEncoding(ctxt, hdlr);
-	} else {
-	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
-			      "Unsupported encoding %s\n", BAD_CAST encoding);
-        }
-    } else if (enc != XML_CHAR_ENCODING_NONE) {
-        xmlSwitchEncoding(ctxt, enc);
+    /*
+     * Changing SAX callbacks is a bad idea. This should be fixed.
+     */
+    if (options & XML_PARSE_NOBLANKS) {
+        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
+    }
+    if (options & XML_PARSE_NOCDATA) {
+        ctxt->sax->cdataBlock = NULL;
+    }
+    if (options & XML_PARSE_HUGE) {
+        if (ctxt->dict != NULL)
+            xmlDictSetLimit(ctxt->dict, 0);
     }
 
-    return(0);
-}
+    ctxt->linenumbers = 1;
 
+    return(options & ~allMask);
+}
 
 /**
- * xmlCtxtUseOptionsInternal:
+ * xmlCtxtSetOptions:
  * @ctxt: an XML parser context
- * @options:  a combination of xmlParserOption
- * @encoding:  the user provided encoding to use
+ * @options:  a bitmask of xmlParserOption values
+ *
+ * Applies the options to the parser context. Unset options are
+ * cleared.
+ *
+ * Available since 2.13.0. With older versions, you can use
+ * xmlCtxtUseOptions.
+ *
+ * XML_PARSE_RECOVER
+ *
+ * Enable "recovery" mode which allows non-wellformed documents.
+ * How this mode behaves exactly is unspecified and may change
+ * without further notice. Use of this feature is DISCOURAGED.
+ *
+ * XML_PARSE_NOENT
+ *
+ * Despite the confusing name, this option enables substitution
+ * of entities. The resulting tree won't contain any entity
+ * reference nodes.
+ *
+ * This option also enables loading of external entities (both
+ * general and parameter entities) which is dangerous. If you
+ * process untrusted data, it's recommended to set the
+ * XML_PARSE_NO_XXE option to disable loading of external
+ * entities.
+ *
+ * XML_PARSE_DTDLOAD
+ *
+ * Enables loading of an external DTD and the loading and
+ * substitution of external parameter entities. Has no effect
+ * if XML_PARSE_NO_XXE is set.
+ *
+ * XML_PARSE_DTDATTR
+ *
+ * Adds default attributes from the DTD to the result document.
+ *
+ * Implies XML_PARSE_DTDLOAD, but loading of external content
+ * can be disabled with XML_PARSE_NO_XXE.
+ *
+ * XML_PARSE_DTDVALID
+ *
+ * This option enables DTD validation which requires to load
+ * external DTDs and external entities (both general and
+ * parameter entities) unless XML_PARSE_NO_XXE was set.
+ *
+ * XML_PARSE_NO_XXE
+ *
+ * Disables loading of external DTDs or entities.
+ *
+ * XML_PARSE_NOERROR
+ *
+ * Disable error and warning reports to the error handlers.
+ * Errors are still accessible with xmlCtxtGetLastError.
+ *
+ * XML_PARSE_NOWARNING
+ *
+ * Disable warning reports.
+ *
+ * XML_PARSE_PEDANTIC
+ *
+ * Enable some pedantic warnings.
+ *
+ * XML_PARSE_NOBLANKS
+ *
+ * Remove some text nodes containing only whitespace from the
+ * result document. Which nodes are removed depends on DTD
+ * element declarations or a conservative heuristic. The
+ * reindenting feature of the serialization code relies on this
+ * option to be set when parsing. Use of this option is
+ * DISCOURAGED.
+ *
+ * XML_PARSE_SAX1
+ *
+ * Always invoke the deprecated SAX1 startElement and endElement
+ * handlers. This option is DEPRECATED.
+ *
+ * XML_PARSE_NONET
+ *
+ * Disable network access with the builtin HTTP and FTP clients.
+ *
+ * XML_PARSE_NODICT
+ *
+ * Create a document without interned strings, making all
+ * strings separate memory allocations.
+ *
+ * XML_PARSE_NSCLEAN
+ *
+ * Remove redundant namespace declarations from the result
+ * document.
+ *
+ * XML_PARSE_NOCDATA
+ *
+ * Output normal text nodes instead of CDATA nodes.
+ *
+ * XML_PARSE_COMPACT
+ *
+ * Store small strings directly in the node struct to save
+ * memory.
+ *
+ * XML_PARSE_OLD10
+ *
+ * Use old Name productions from before XML 1.0 Fifth Edition.
+ * This options is DEPRECATED.
+ *
+ * XML_PARSE_HUGE
+ *
+ * Relax some internal limits.
+ *
+ * Maximum size of text nodes, tags, comments, processing instructions,
+ * CDATA sections, entity values
+ *
+ * normal: 10M
+ * huge:    1B
+ *
+ * Maximum size of names, system literals, pubid literals
  *
- * Applies the options to the parser context
+ * normal: 50K
+ * huge:   10M
+ *
+ * Maximum nesting depth of elements
+ *
+ * normal:  256
+ * huge:   2048
+ *
+ * Maximum nesting depth of entities
+ *
+ * normal: 20
+ * huge:   40
+ *
+ * XML_PARSE_OLDSAX
+ *
+ * Enable an unspecified legacy mode for SAX parsers. This
+ * option is DEPRECATED.
+ *
+ * XML_PARSE_IGNORE_ENC
+ *
+ * Ignore the encoding in the XML declaration. This option is
+ * mostly unneeded these days. The only effect is to enforce
+ * UTF-8 decoding of ASCII-like data.
+ *
+ * XML_PARSE_BIG_LINES
+ *
+ * Enable reporting of line numbers larger than 65535.
  *
  * Returns 0 in case of success, the set of unknown or unimplemented options
  *         in case of error.
  */
-static int
-xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding)
+int
+xmlCtxtSetOptions(xmlParserCtxtPtr ctxt, int options)
 {
-    if (ctxt == NULL)
-        return(-1);
-    if (encoding != NULL) {
-        if (ctxt->encoding != NULL)
-	    xmlFree((xmlChar *) ctxt->encoding);
-        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
-    }
-    if (options & XML_PARSE_RECOVER) {
-        ctxt->recovery = 1;
-        options -= XML_PARSE_RECOVER;
-	ctxt->options |= XML_PARSE_RECOVER;
-    } else
-        ctxt->recovery = 0;
-    if (options & XML_PARSE_DTDLOAD) {
-        ctxt->loadsubset = XML_DETECT_IDS;
-        options -= XML_PARSE_DTDLOAD;
-	ctxt->options |= XML_PARSE_DTDLOAD;
-    } else
-        ctxt->loadsubset = 0;
-    if (options & XML_PARSE_DTDATTR) {
-        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
-        options -= XML_PARSE_DTDATTR;
-	ctxt->options |= XML_PARSE_DTDATTR;
-    }
-    if (options & XML_PARSE_NOENT) {
-        ctxt->replaceEntities = 1;
-        /* ctxt->loadsubset |= XML_DETECT_IDS; */
-        options -= XML_PARSE_NOENT;
-	ctxt->options |= XML_PARSE_NOENT;
-    } else
-        ctxt->replaceEntities = 0;
-    if (options & XML_PARSE_PEDANTIC) {
-        ctxt->pedantic = 1;
-        options -= XML_PARSE_PEDANTIC;
-	ctxt->options |= XML_PARSE_PEDANTIC;
-    } else
-        ctxt->pedantic = 0;
-    if (options & XML_PARSE_NOBLANKS) {
-        ctxt->keepBlanks = 0;
-        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
-        options -= XML_PARSE_NOBLANKS;
-	ctxt->options |= XML_PARSE_NOBLANKS;
-    } else
-        ctxt->keepBlanks = 1;
-    if (options & XML_PARSE_DTDVALID) {
-        ctxt->validate = 1;
-        if (options & XML_PARSE_NOWARNING)
-            ctxt->vctxt.warning = NULL;
-        if (options & XML_PARSE_NOERROR)
-            ctxt->vctxt.error = NULL;
-        options -= XML_PARSE_DTDVALID;
-	ctxt->options |= XML_PARSE_DTDVALID;
-    } else
-        ctxt->validate = 0;
-    if (options & XML_PARSE_NOWARNING) {
-        ctxt->sax->warning = NULL;
-        options -= XML_PARSE_NOWARNING;
-    }
-    if (options & XML_PARSE_NOERROR) {
-        ctxt->sax->error = NULL;
-        ctxt->sax->fatalError = NULL;
-        options -= XML_PARSE_NOERROR;
-    }
-#ifdef LIBXML_SAX1_ENABLED
-    if (options & XML_PARSE_SAX1) {
-        ctxt->sax->startElement = xmlSAX2StartElement;
-        ctxt->sax->endElement = xmlSAX2EndElement;
-        ctxt->sax->startElementNs = NULL;
-        ctxt->sax->endElementNs = NULL;
-        ctxt->sax->initialized = 1;
-        options -= XML_PARSE_SAX1;
-	ctxt->options |= XML_PARSE_SAX1;
-    }
-#endif /* LIBXML_SAX1_ENABLED */
-    if (options & XML_PARSE_NODICT) {
-        ctxt->dictNames = 0;
-        options -= XML_PARSE_NODICT;
-	ctxt->options |= XML_PARSE_NODICT;
-    } else {
-        ctxt->dictNames = 1;
-    }
-    if (options & XML_PARSE_NOCDATA) {
-        ctxt->sax->cdataBlock = NULL;
-        options -= XML_PARSE_NOCDATA;
-	ctxt->options |= XML_PARSE_NOCDATA;
-    }
-    if (options & XML_PARSE_NSCLEAN) {
-	ctxt->options |= XML_PARSE_NSCLEAN;
-        options -= XML_PARSE_NSCLEAN;
-    }
-    if (options & XML_PARSE_NONET) {
-	ctxt->options |= XML_PARSE_NONET;
-        options -= XML_PARSE_NONET;
-    }
-    if (options & XML_PARSE_COMPACT) {
-	ctxt->options |= XML_PARSE_COMPACT;
-        options -= XML_PARSE_COMPACT;
-    }
-    if (options & XML_PARSE_OLD10) {
-	ctxt->options |= XML_PARSE_OLD10;
-        options -= XML_PARSE_OLD10;
-    }
-    if (options & XML_PARSE_NOBASEFIX) {
-	ctxt->options |= XML_PARSE_NOBASEFIX;
-        options -= XML_PARSE_NOBASEFIX;
-    }
-    if (options & XML_PARSE_HUGE) {
-	ctxt->options |= XML_PARSE_HUGE;
-        options -= XML_PARSE_HUGE;
-        if (ctxt->dict != NULL)
-            xmlDictSetLimit(ctxt->dict, 0);
-    }
-    if (options & XML_PARSE_OLDSAX) {
-	ctxt->options |= XML_PARSE_OLDSAX;
-        options -= XML_PARSE_OLDSAX;
-    }
-    if (options & XML_PARSE_IGNORE_ENC) {
-	ctxt->options |= XML_PARSE_IGNORE_ENC;
-        options -= XML_PARSE_IGNORE_ENC;
-    }
-    if (options & XML_PARSE_BIG_LINES) {
-	ctxt->options |= XML_PARSE_BIG_LINES;
-        options -= XML_PARSE_BIG_LINES;
-    }
-    ctxt->linenumbers = 1;
-    return (options);
+    return(xmlCtxtSetOptionsInternal(ctxt, options, 0));
 }
 
 /**
@@ -15123,7 +13628,22 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi
  * @ctxt: an XML parser context
  * @options:  a combination of xmlParserOption
  *
- * Applies the options to the parser context
+ * DEPRECATED: Use xmlCtxtSetOptions.
+ *
+ * Applies the options to the parser context. The following options
+ * are never cleared and can only be enabled:
+ *
+ * XML_PARSE_NOERROR
+ * XML_PARSE_NOWARNING
+ * XML_PARSE_NONET
+ * XML_PARSE_NSCLEAN
+ * XML_PARSE_NOCDATA
+ * XML_PARSE_COMPACT
+ * XML_PARSE_OLD10
+ * XML_PARSE_HUGE
+ * XML_PARSE_OLDSAX
+ * XML_PARSE_IGNORE_ENC
+ * XML_PARSE_BIG_LINES
  *
  * Returns 0 in case of success, the set of unknown or unimplemented options
  *         in case of error.
@@ -15131,88 +13651,142 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi
 int
 xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
 {
-   return(xmlCtxtUseOptionsInternal(ctxt, options, NULL));
+    int keepMask;
+
+    /*
+     * For historic reasons, some options can only be enabled.
+     */
+    keepMask = XML_PARSE_NOERROR |
+               XML_PARSE_NOWARNING |
+               XML_PARSE_NONET |
+               XML_PARSE_NSCLEAN |
+               XML_PARSE_NOCDATA |
+               XML_PARSE_COMPACT |
+               XML_PARSE_OLD10 |
+               XML_PARSE_HUGE |
+               XML_PARSE_OLDSAX |
+               XML_PARSE_IGNORE_ENC |
+               XML_PARSE_BIG_LINES;
+
+    return(xmlCtxtSetOptionsInternal(ctxt, options, keepMask));
+}
+
+/**
+ * xmlCtxtSetMaxAmplification:
+ * @ctxt: an XML parser context
+ * @maxAmpl:  maximum amplification factor
+ *
+ * To protect against exponential entity expansion ("billion laughs"), the
+ * size of serialized output is (roughly) limited to the input size
+ * multiplied by this factor. The default value is 5.
+ *
+ * When working with documents making heavy use of entity expansion, it can
+ * be necessary to increase the value. For security reasons, this should only
+ * be considered when processing trusted input.
+ */
+void
+xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt, unsigned maxAmpl)
+{
+    ctxt->maxAmpl = maxAmpl;
 }
 
 /**
- * xmlDoRead:
+ * xmlCtxtParseDocument:
  * @ctxt:  an XML parser context
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
- * @options:  a combination of xmlParserOption
- * @reuse:  keep the context for reuse
+ * @input:  parser input
  *
- * Common front-end for the xmlRead functions
+ * Parse an XML document and return the resulting document tree.
+ * Takes ownership of the input object.
+ *
+ * Available since 2.13.0.
  *
  * Returns the resulting document tree or NULL
  */
-static xmlDocPtr
-xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
-          int options, int reuse)
+xmlDocPtr
+xmlCtxtParseDocument(xmlParserCtxtPtr ctxt, xmlParserInputPtr input)
 {
-    xmlDocPtr ret;
+    xmlDocPtr ret = NULL;
+
+    if ((ctxt == NULL) || (input == NULL))
+        return(NULL);
 
-    xmlCtxtUseOptionsInternal(ctxt, options, encoding);
-    if (encoding != NULL) {
-        xmlCharEncodingHandlerPtr hdlr;
+    /* assert(ctxt->inputNr == 0); */
+    while (ctxt->inputNr > 0)
+        xmlFreeInputStream(inputPop(ctxt));
 
-	hdlr = xmlFindCharEncodingHandler(encoding);
-	if (hdlr != NULL)
-	    xmlSwitchToEncoding(ctxt, hdlr);
+    if (inputPush(ctxt, input) < 0) {
+        xmlFreeInputStream(input);
+        return(NULL);
     }
-    if ((URL != NULL) && (ctxt->input != NULL) &&
-        (ctxt->input->filename == NULL))
-        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
+
     xmlParseDocument(ctxt);
-    if ((ctxt->wellFormed) || ctxt->recovery)
+
+    if ((ctxt->wellFormed) ||
+        ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) {
         ret = ctxt->myDoc;
-    else {
+    } else {
+        if (ctxt->errNo == XML_ERR_OK)
+            xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, "unknown error\n");
+
         ret = NULL;
-	if (ctxt->myDoc != NULL) {
-	    xmlFreeDoc(ctxt->myDoc);
-	}
+	xmlFreeDoc(ctxt->myDoc);
     }
     ctxt->myDoc = NULL;
-    if (!reuse) {
-	xmlFreeParserCtxt(ctxt);
-    }
 
-    return (ret);
+    /* assert(ctxt->inputNr == 1); */
+    while (ctxt->inputNr > 0)
+        xmlFreeInputStream(inputPop(ctxt));
+
+    return(ret);
 }
 
 /**
  * xmlReadDoc:
  * @cur:  a pointer to a zero terminated string
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
+ * @URL:  base URL (optional)
+ * @encoding:  the document encoding (optional)
  * @options:  a combination of xmlParserOption
  *
- * parse an XML in-memory document and build a tree.
+ * Convenience function to parse an XML document from a
+ * zero-terminated string.
+ *
+ * See xmlCtxtReadDoc for details.
  *
  * Returns the resulting document tree
  */
 xmlDocPtr
-xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
+xmlReadDoc(const xmlChar *cur, const char *URL, const char *encoding,
+           int options)
 {
     xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
+    xmlDocPtr doc;
 
-    if (cur == NULL)
-        return (NULL);
-    xmlInitParser();
-
-    ctxt = xmlCreateDocParserCtxt(cur);
+    ctxt = xmlNewParserCtxt();
     if (ctxt == NULL)
-        return (NULL);
-    return (xmlDoRead(ctxt, URL, encoding, options, 0));
+        return(NULL);
+
+    xmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputString(ctxt, URL, (const char *) cur, encoding,
+                              XML_INPUT_BUF_STATIC);
+
+    doc = xmlCtxtParseDocument(ctxt, input);
+
+    xmlFreeParserCtxt(ctxt);
+    return(doc);
 }
 
 /**
  * xmlReadFile:
  * @filename:  a file or URL
- * @encoding:  the document encoding, or NULL
+ * @encoding:  the document encoding (optional)
  * @options:  a combination of xmlParserOption
  *
- * parse an XML file from the filesystem or the network.
+ * Convenience function to parse an XML file from the filesystem,
+ * the network or a global user-define resource loader.
+ *
+ * See xmlCtxtReadFile for details.
  *
  * Returns the resulting document tree
  */
@@ -15220,48 +13794,85 @@ xmlDocPtr
 xmlReadFile(const char *filename, const char *encoding, int options)
 {
     xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
+    xmlDocPtr doc;
 
-    xmlInitParser();
-    ctxt = xmlCreateURLParserCtxt(filename, options);
+    ctxt = xmlNewParserCtxt();
     if (ctxt == NULL)
-        return (NULL);
-    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
+        return(NULL);
+
+    xmlCtxtUseOptions(ctxt, options);
+
+    /*
+     * Backward compatibility for users of command line utilities like
+     * xmlstarlet expecting "-" to mean stdin. This is dangerous and
+     * should be removed at some point.
+     */
+    if ((filename != NULL) && (filename[0] == '-') && (filename[1] == 0))
+        input = xmlNewInputFd(ctxt, filename, STDIN_FILENO, encoding, 0);
+    else
+        input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0);
+
+    doc = xmlCtxtParseDocument(ctxt, input);
+
+    xmlFreeParserCtxt(ctxt);
+    return(doc);
 }
 
 /**
  * xmlReadMemory:
  * @buffer:  a pointer to a char array
  * @size:  the size of the array
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
+ * @url:  base URL (optional)
+ * @encoding:  the document encoding (optional)
  * @options:  a combination of xmlParserOption
  *
- * parse an XML in-memory document and build a tree.
+ * Parse an XML in-memory document and build a tree. The input buffer must
+ * not contain a terminating null byte.
+ *
+ * See xmlCtxtReadMemory for details.
  *
  * Returns the resulting document tree
  */
 xmlDocPtr
-xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
+xmlReadMemory(const char *buffer, int size, const char *url,
+              const char *encoding, int options)
 {
     xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
+    xmlDocPtr doc;
 
-    xmlInitParser();
-    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
+    if (size < 0)
+	return(NULL);
+
+    ctxt = xmlNewParserCtxt();
     if (ctxt == NULL)
-        return (NULL);
-    return (xmlDoRead(ctxt, URL, encoding, options, 0));
+        return(NULL);
+
+    xmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputMemory(ctxt, url, buffer, size, encoding,
+                              XML_INPUT_BUF_STATIC);
+
+    doc = xmlCtxtParseDocument(ctxt, input);
+
+    xmlFreeParserCtxt(ctxt);
+    return(doc);
 }
 
 /**
  * xmlReadFd:
  * @fd:  an open file descriptor
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
+ * @URL:  base URL (optional)
+ * @encoding:  the document encoding (optional)
  * @options:  a combination of xmlParserOption
  *
- * parse an XML from a file descriptor and build a tree.
+ * Parse an XML from a file descriptor and build a tree.
+ *
+ * See xmlCtxtReadFd for details.
+ *
  * NOTE that the file descriptor will not be closed when the
- *      reader is closed or reset.
+ * context is freed or reset.
  *
  * Returns the resulting document tree
  */
@@ -15269,42 +13880,35 @@ xmlDocPtr
 xmlReadFd(int fd, const char *URL, const char *encoding, int options)
 {
     xmlParserCtxtPtr ctxt;
-    xmlParserInputBufferPtr input;
-    xmlParserInputPtr stream;
-
-    if (fd < 0)
-        return (NULL);
-    xmlInitParser();
+    xmlParserInputPtr input;
+    xmlDocPtr doc;
 
-    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
-    if (input == NULL)
-        return (NULL);
-    input->closecallback = NULL;
     ctxt = xmlNewParserCtxt();
-    if (ctxt == NULL) {
-        xmlFreeParserInputBuffer(input);
-        return (NULL);
-    }
-    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
-    if (stream == NULL) {
-        xmlFreeParserInputBuffer(input);
-	xmlFreeParserCtxt(ctxt);
-        return (NULL);
-    }
-    inputPush(ctxt, stream);
-    return (xmlDoRead(ctxt, URL, encoding, options, 0));
+    if (ctxt == NULL)
+        return(NULL);
+
+    xmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputFd(ctxt, URL, fd, encoding, 0);
+
+    doc = xmlCtxtParseDocument(ctxt, input);
+
+    xmlFreeParserCtxt(ctxt);
+    return(doc);
 }
 
 /**
  * xmlReadIO:
  * @ioread:  an I/O read function
- * @ioclose:  an I/O close function
+ * @ioclose:  an I/O close function (optional)
  * @ioctx:  an I/O handler
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
+ * @URL:  base URL (optional)
+ * @encoding:  the document encoding (optional)
  * @options:  a combination of xmlParserOption
  *
- * parse an XML document from I/O functions and source and build a tree.
+ * Parse an XML document from I/O functions and context and build a tree.
+ *
+ * See xmlCtxtReadIO for details.
  *
  * Returns the resulting document tree
  */
@@ -15313,67 +13917,67 @@ xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
           void *ioctx, const char *URL, const char *encoding, int options)
 {
     xmlParserCtxtPtr ctxt;
-    xmlParserInputBufferPtr input;
-    xmlParserInputPtr stream;
-
-    if (ioread == NULL)
-        return (NULL);
-    xmlInitParser();
+    xmlParserInputPtr input;
+    xmlDocPtr doc;
 
-    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
-                                         XML_CHAR_ENCODING_NONE);
-    if (input == NULL) {
-        if (ioclose != NULL)
-            ioclose(ioctx);
-        return (NULL);
-    }
     ctxt = xmlNewParserCtxt();
-    if (ctxt == NULL) {
-        xmlFreeParserInputBuffer(input);
-        return (NULL);
-    }
-    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
-    if (stream == NULL) {
-        xmlFreeParserInputBuffer(input);
-	xmlFreeParserCtxt(ctxt);
-        return (NULL);
-    }
-    inputPush(ctxt, stream);
-    return (xmlDoRead(ctxt, URL, encoding, options, 0));
+    if (ctxt == NULL)
+        return(NULL);
+
+    xmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0);
+
+    doc = xmlCtxtParseDocument(ctxt, input);
+
+    xmlFreeParserCtxt(ctxt);
+    return(doc);
 }
 
 /**
  * xmlCtxtReadDoc:
  * @ctxt:  an XML parser context
- * @cur:  a pointer to a zero terminated string
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
+ * @str:  a pointer to a zero terminated string
+ * @URL:  base URL (optional)
+ * @encoding:  the document encoding (optional)
  * @options:  a combination of xmlParserOption
  *
- * parse an XML in-memory document and build a tree.
- * This reuses the existing @ctxt parser context
+ * Parse an XML in-memory document and build a tree.
+ *
+ * @URL is used as base to resolve external entities and for error
+ * reporting.
+ *
+ * See xmlCtxtUseOptions for details.
  *
  * Returns the resulting document tree
  */
 xmlDocPtr
-xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
+xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar *str,
                const char *URL, const char *encoding, int options)
 {
-    if (cur == NULL)
-        return (NULL);
-    return (xmlCtxtReadMemory(ctxt, (const char *) cur, xmlStrlen(cur), URL,
-                              encoding, options));
+    xmlParserInputPtr input;
+
+    if (ctxt == NULL)
+        return(NULL);
+
+    xmlCtxtReset(ctxt);
+    xmlCtxtUseOptions(ctxt, options);
+
+    input = xmlNewInputString(ctxt, URL, (const char *) str, encoding,
+                              XML_INPUT_BUF_STATIC);
+
+    return(xmlCtxtParseDocument(ctxt, input));
 }
 
 /**
  * xmlCtxtReadFile:
  * @ctxt:  an XML parser context
  * @filename:  a file or URL
- * @encoding:  the document encoding, or NULL
+ * @encoding:  the document encoding (optional)
  * @options:  a combination of xmlParserOption
  *
- * parse an XML file from the filesystem or the network.
- * This reuses the existing @ctxt parser context
+ * Parse an XML file from the filesystem, the network or a user-defined
+ * resource loader.
  *
  * Returns the resulting document tree
  */
@@ -15381,22 +13985,17 @@ xmlDocPtr
 xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
                 const char *encoding, int options)
 {
-    xmlParserInputPtr stream;
+    xmlParserInputPtr input;
 
-    if (filename == NULL)
-        return (NULL);
     if (ctxt == NULL)
-        return (NULL);
-    xmlInitParser();
+        return(NULL);
 
     xmlCtxtReset(ctxt);
+    xmlCtxtUseOptions(ctxt, options);
 
-    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
-    if (stream == NULL) {
-        return (NULL);
-    }
-    inputPush(ctxt, stream);
-    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
+    input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0);
+
+    return(xmlCtxtParseDocument(ctxt, input));
 }
 
 /**
@@ -15404,12 +14003,17 @@ xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
  * @ctxt:  an XML parser context
  * @buffer:  a pointer to a char array
  * @size:  the size of the array
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
+ * @URL:  base URL (optional)
+ * @encoding:  the document encoding (optional)
  * @options:  a combination of xmlParserOption
  *
- * parse an XML in-memory document and build a tree.
- * This reuses the existing @ctxt parser context
+ * Parse an XML in-memory document and build a tree. The input buffer must
+ * not contain a terminating null byte.
+ *
+ * @URL is used as base to resolve external entities and for error
+ * reporting.
+ *
+ * See xmlCtxtUseOptions for details.
  *
  * Returns the resulting document tree
  */
@@ -15417,44 +14021,37 @@ xmlDocPtr
 xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
                   const char *URL, const char *encoding, int options)
 {
-    xmlParserInputBufferPtr input;
-    xmlParserInputPtr stream;
+    xmlParserInputPtr input;
 
-    if (ctxt == NULL)
-        return (NULL);
-    if (buffer == NULL)
-        return (NULL);
-    xmlInitParser();
+    if ((ctxt == NULL) || (size < 0))
+        return(NULL);
 
     xmlCtxtReset(ctxt);
+    xmlCtxtUseOptions(ctxt, options);
 
-    input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
-    if (input == NULL) {
-	return(NULL);
-    }
-
-    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
-    if (stream == NULL) {
-	xmlFreeParserInputBuffer(input);
-	return(NULL);
-    }
+    input = xmlNewInputMemory(ctxt, URL, buffer, size, encoding,
+                              XML_INPUT_BUF_STATIC);
 
-    inputPush(ctxt, stream);
-    return (xmlDoRead(ctxt, URL, encoding, options, 1));
+    return(xmlCtxtParseDocument(ctxt, input));
 }
 
 /**
  * xmlCtxtReadFd:
  * @ctxt:  an XML parser context
  * @fd:  an open file descriptor
- * @URL:  the base URL to use for the document
- * @encoding:  the document encoding, or NULL
+ * @URL:  base URL (optional)
+ * @encoding:  the document encoding (optional)
  * @options:  a combination of xmlParserOption
  *
- * parse an XML from a file descriptor and build a tree.
- * This reuses the existing @ctxt parser context
+ * Parse an XML document from a file descriptor and build a tree.
+ *
  * NOTE that the file descriptor will not be closed when the
- *      reader is closed or reset.
+ * context is freed or reset.
+ *
+ * @URL is used as base to resolve external entities and for error
+ * reporting.
+ *
+ * See xmlCtxtUseOptions for details.
  *
  * Returns the resulting document tree
  */
@@ -15462,29 +14059,17 @@ xmlDocPtr
 xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
               const char *URL, const char *encoding, int options)
 {
-    xmlParserInputBufferPtr input;
-    xmlParserInputPtr stream;
+    xmlParserInputPtr input;
 
-    if (fd < 0)
-        return (NULL);
     if (ctxt == NULL)
-        return (NULL);
-    xmlInitParser();
+        return(NULL);
 
     xmlCtxtReset(ctxt);
+    xmlCtxtUseOptions(ctxt, options);
 
+    input = xmlNewInputFd(ctxt, URL, fd, encoding, 0);
 
-    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
-    if (input == NULL)
-        return (NULL);
-    input->closecallback = NULL;
-    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
-    if (stream == NULL) {
-        xmlFreeParserInputBuffer(input);
-        return (NULL);
-    }
-    inputPush(ctxt, stream);
-    return (xmlDoRead(ctxt, URL, encoding, options, 1));
+    return(xmlCtxtParseDocument(ctxt, input));
 }
 
 /**
@@ -15500,6 +14085,11 @@ xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
  * parse an XML document from I/O functions and source and build a tree.
  * This reuses the existing @ctxt parser context
  *
+ * @URL is used as base to resolve external entities and for error
+ * reporting.
+ *
+ * See xmlCtxtUseOptions for details.
+ *
  * Returns the resulting document tree
  */
 xmlDocPtr
@@ -15508,30 +14098,16 @@ xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
 	      const char *URL,
               const char *encoding, int options)
 {
-    xmlParserInputBufferPtr input;
-    xmlParserInputPtr stream;
+    xmlParserInputPtr input;
 
-    if (ioread == NULL)
-        return (NULL);
     if (ctxt == NULL)
-        return (NULL);
-    xmlInitParser();
+        return(NULL);
 
     xmlCtxtReset(ctxt);
+    xmlCtxtUseOptions(ctxt, options);
 
-    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
-                                         XML_CHAR_ENCODING_NONE);
-    if (input == NULL) {
-        if (ioclose != NULL)
-            ioclose(ioctx);
-        return (NULL);
-    }
-    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
-    if (stream == NULL) {
-        xmlFreeParserInputBuffer(input);
-        return (NULL);
-    }
-    inputPush(ctxt, stream);
-    return (xmlDoRead(ctxt, URL, encoding, options, 1));
+    input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0);
+
+    return(xmlCtxtParseDocument(ctxt, input));
 }
 
diff --git a/parserInternals.c b/parserInternals.c
index 31d94680a5541165862a8ed0a1e8eae395e28368..6ddd28e78581f446ff2ec684591fd5de991479b9 100644
--- a/parserInternals.c
+++ b/parserInternals.c
@@ -24,27 +24,35 @@
 #include <libxml/tree.h>
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
-#include <libxml/valid.h>
 #include <libxml/entities.h>
 #include <libxml/xmlerror.h>
 #include <libxml/encoding.h>
-#include <libxml/valid.h>
 #include <libxml/xmlIO.h>
 #include <libxml/uri.h>
 #include <libxml/dict.h>
-#include <libxml/SAX.h>
+#include <libxml/xmlsave.h>
 #ifdef LIBXML_CATALOG_ENABLED
 #include <libxml/catalog.h>
 #endif
-#include <libxml/globals.h>
 #include <libxml/chvalid.h>
+#include <libxml/nanohttp.h>
 
 #define CUR(ctxt) ctxt->input->cur
 #define END(ctxt) ctxt->input->end
-#define VALID_CTXT(ctxt) (CUR(ctxt) <= END(ctxt))
 
-#include "buf.h"
-#include "enc.h"
+#include "private/buf.h"
+#include "private/enc.h"
+#include "private/error.h"
+#include "private/io.h"
+#include "private/parser.h"
+
+#define XML_MAX_ERRORS 100
+
+/*
+ * XML_MAX_AMPLIFICATION_DEFAULT is the default maximum allowed amplification
+ * factor of serialized output after entity expansion.
+ */
+#define XML_MAX_AMPLIFICATION_DEFAULT 5
 
 /*
  * Various global defaults for parsing
@@ -55,24 +63,19 @@
  * @version: the include version number
  *
  * check the compiled lib version against the include one.
- * This can warn or immediately kill the application
  */
 void
 xmlCheckVersion(int version) {
-    int myversion = (int) LIBXML_VERSION;
+    int myversion = LIBXML_VERSION;
 
     xmlInitParser();
 
     if ((myversion / 10000) != (version / 10000)) {
-	xmlGenericError(xmlGenericErrorContext,
-		"Fatal: program compiled against libxml %d using libxml %d\n",
-		(version / 10000), (myversion / 10000));
 	fprintf(stderr,
 		"Fatal: program compiled against libxml %d using libxml %d\n",
 		(version / 10000), (myversion / 10000));
-    }
-    if ((myversion / 100) < (version / 100)) {
-	xmlGenericError(xmlGenericErrorContext,
+    } else if ((myversion / 100) < (version / 100)) {
+	fprintf(stderr,
 		"Warning: program compiled against libxml %d using older %d\n",
 		(version / 100), (myversion / 100));
     }
@@ -87,116 +90,290 @@ xmlCheckVersion(int version) {
 
 
 /**
- * xmlErrMemory:
+ * xmlCtxtSetErrorHandler:
  * @ctxt:  an XML parser context
- * @extra:  extra information
+ * @handler:  error handler
+ * @data:  data for error handler
  *
- * Handle a redefinition of attribute error
+ * Register a callback function that will be called on errors and
+ * warnings. If handler is NULL, the error handler will be deactivated.
+ *
+ * This is the recommended way to collect errors from the parser and
+ * takes precedence over all other error reporting mechanisms.
+ * These are (in order of precedence):
+ *
+ * - per-context structured handler (xmlCtxtSetErrorHandler)
+ * - per-context structured "serror" SAX handler
+ * - global structured handler (xmlSetStructuredErrorFunc)
+ * - per-context generic "error" and "warning" SAX handlers
+ * - global generic handler (xmlSetGenericErrorFunc)
+ * - print to stderr
+ *
+ * Available since 2.13.0.
  */
 void
-xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra)
+xmlCtxtSetErrorHandler(xmlParserCtxtPtr ctxt, xmlStructuredErrorFunc handler,
+                       void *data)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL) {
-        ctxt->errNo = XML_ERR_NO_MEMORY;
-        ctxt->instate = XML_PARSER_EOF;
-        ctxt->disableSAX = 1;
-    }
-    if (extra)
-        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
-                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
-                        NULL, NULL, 0, 0,
-                        "Memory allocation failed : %s\n", extra);
-    else
-        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
-                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
-                        NULL, NULL, 0, 0, "Memory allocation failed\n");
+    if (ctxt == NULL)
+        return;
+    ctxt->errorHandler = handler;
+    ctxt->errorCtxt = data;
 }
 
 /**
- * __xmlErrEncoding:
+ * xmlCtxtErrMemory:
  * @ctxt:  an XML parser context
- * @xmlerr:  the error number
- * @msg:  the error message
- * @str1:  an string info
- * @str2:  an string info
  *
- * Handle an encoding error
+ * Handle an out-of-memory error.
+ *
+ * Available since 2.13.0.
  */
 void
-__xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr,
-                 const char *msg, const xmlChar * str1, const xmlChar * str2)
+xmlCtxtErrMemory(xmlParserCtxtPtr ctxt)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-        ctxt->errNo = xmlerr;
-    __xmlRaiseError(NULL, NULL, NULL,
-                    ctxt, NULL, XML_FROM_PARSER, xmlerr, XML_ERR_FATAL,
-                    NULL, 0, (const char *) str1, (const char *) str2,
-                    NULL, 0, 0, msg, str1, str2);
-    if (ctxt != NULL) {
-        ctxt->wellFormed = 0;
-        if (ctxt->recovery == 0)
-            ctxt->disableSAX = 1;
+    xmlStructuredErrorFunc schannel = NULL;
+    xmlGenericErrorFunc channel = NULL;
+    void *data;
+
+    if (ctxt == NULL)
+        return;
+
+    ctxt->errNo = XML_ERR_NO_MEMORY;
+    ctxt->instate = XML_PARSER_EOF; /* TODO: Remove after refactoring */
+    ctxt->wellFormed = 0;
+    ctxt->disableSAX = 2;
+
+    if (ctxt->errorHandler) {
+        schannel = ctxt->errorHandler;
+        data = ctxt->errorCtxt;
+    } else if ((ctxt->sax->initialized == XML_SAX2_MAGIC) &&
+        (ctxt->sax->serror != NULL)) {
+        schannel = ctxt->sax->serror;
+        data = ctxt->userData;
+    } else {
+        channel = ctxt->sax->error;
+        data = ctxt->userData;
     }
+
+    xmlRaiseMemoryError(schannel, channel, data, XML_FROM_PARSER,
+                        &ctxt->lastError);
 }
 
 /**
- * xmlErrInternal:
- * @ctxt:  an XML parser context
- * @msg:  the error message
- * @str:  error information
+ * xmlCtxtErrIO:
+ * @ctxt:  parser context
+ * @code:  xmlParserErrors code
+ * @uri:  filename or URI (optional)
+ *
+ * If filename is empty, use the one from context input if available.
  *
- * Handle an internal error
+ * Report an IO error to the parser context.
+ */
+void
+xmlCtxtErrIO(xmlParserCtxtPtr ctxt, int code, const char *uri)
+{
+    const char *errstr, *msg, *str1, *str2;
+    xmlErrorLevel level;
+
+    if (ctxt == NULL)
+        return;
+
+    /*
+     * Only report a warning if a file could not be found. This should
+     * only be done for external entities, but the external entity loader
+     * of xsltproc can try multiple paths and assumes that ENOENT doesn't
+     * raise an error and aborts parsing.
+     */
+    if (((code == XML_IO_ENOENT) ||
+         (code == XML_IO_NETWORK_ATTEMPT) ||
+         (code == XML_IO_UNKNOWN))) {
+        if (ctxt->validate == 0)
+            level = XML_ERR_WARNING;
+        else
+            level = XML_ERR_ERROR;
+    } else {
+        level = XML_ERR_FATAL;
+    }
+
+    errstr = xmlErrString(code);
+
+    if (uri == NULL) {
+        msg = "%s\n";
+        str1 = errstr;
+        str2 = NULL;
+    } else {
+        msg = "failed to load \"%s\": %s\n";
+        str1 = uri;
+        str2 = errstr;
+    }
+
+    xmlCtxtErr(ctxt, NULL, XML_FROM_IO, code, level,
+               (const xmlChar *) uri, NULL, NULL, 0,
+               msg, str1, str2);
+}
+
+/**
+ * xmlCtxtVErr:
+ * @ctxt:  a parser context
+ * @node: the current node or NULL
+ * @domain: the domain for the error
+ * @code: the code for the error
+ * @level: the xmlErrorLevel for the error
+ * @str1: extra string info
+ * @str2: extra string info
+ * @str3: extra string info
+ * @int1: extra int info
+ * @msg:  the message to display/transmit
+ * @ap:  extra parameters for the message display
+ *
+ * Raise a parser error.
  */
-static void LIBXML_ATTR_FORMAT(2,0)
-xmlErrInternal(xmlParserCtxtPtr ctxt, const char *msg, const xmlChar * str)
+void
+xmlCtxtVErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain,
+            xmlParserErrors code, xmlErrorLevel level,
+            const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
+            int int1, const char *msg, va_list ap)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
+    xmlStructuredErrorFunc schannel = NULL;
+    xmlGenericErrorFunc channel = NULL;
+    void *data = NULL;
+    const char *file = NULL;
+    int line = 0;
+    int col = 0;
+    int res;
+
+    if (code == XML_ERR_NO_MEMORY) {
+        xmlCtxtErrMemory(ctxt);
+        return;
+    }
+
+    if (PARSER_STOPPED(ctxt))
 	return;
-    if (ctxt != NULL)
-        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
-    __xmlRaiseError(NULL, NULL, NULL,
-                    ctxt, NULL, XML_FROM_PARSER, XML_ERR_INTERNAL_ERROR,
-                    XML_ERR_FATAL, NULL, 0, (const char *) str, NULL, NULL,
-                    0, 0, msg, str);
-    if (ctxt != NULL) {
+
+    if (level == XML_ERR_WARNING) {
+        if (ctxt->nbWarnings >= XML_MAX_ERRORS)
+            goto done;
+        ctxt->nbWarnings += 1;
+    } else {
+        /* Report at least one fatal error. */
+        if ((ctxt->nbErrors >= XML_MAX_ERRORS) &&
+            ((level < XML_ERR_FATAL) || (ctxt->wellFormed == 0)))
+            goto done;
+        ctxt->nbErrors += 1;
+    }
+
+    if (((ctxt->options & XML_PARSE_NOERROR) == 0) &&
+        ((level != XML_ERR_WARNING) ||
+         ((ctxt->options & XML_PARSE_NOWARNING) == 0))) {
+        if (ctxt->errorHandler) {
+            schannel = ctxt->errorHandler;
+            data = ctxt->errorCtxt;
+        } else if ((ctxt->sax->initialized == XML_SAX2_MAGIC) &&
+            (ctxt->sax->serror != NULL)) {
+            schannel = ctxt->sax->serror;
+            data = ctxt->userData;
+        } else if ((domain == XML_FROM_VALID) || (domain == XML_FROM_DTD)) {
+            if (level == XML_ERR_WARNING)
+                channel = ctxt->vctxt.warning;
+            else
+                channel = ctxt->vctxt.error;
+            data = ctxt->vctxt.userData;
+        } else {
+            if (level == XML_ERR_WARNING)
+                channel = ctxt->sax->warning;
+            else
+                channel = ctxt->sax->error;
+            data = ctxt->userData;
+        }
+    }
+
+    if (ctxt->input != NULL) {
+        xmlParserInputPtr input = ctxt->input;
+
+        if ((input->filename == NULL) &&
+            (ctxt->inputNr > 1)) {
+            input = ctxt->inputTab[ctxt->inputNr - 2];
+        }
+        file = input->filename;
+        line = input->line;
+        col = input->col;
+    }
+
+    res = xmlVRaiseError(schannel, channel, data, ctxt, node, domain, code,
+                         level, file, line, (const char *) str1,
+                         (const char *) str2, (const char *) str3, int1, col,
+                         msg, ap);
+
+    if (res < 0) {
+        xmlCtxtErrMemory(ctxt);
+        return;
+    }
+
+done:
+    if (level >= XML_ERR_ERROR)
+        ctxt->errNo = code;
+    if (level == XML_ERR_FATAL) {
         ctxt->wellFormed = 0;
         if (ctxt->recovery == 0)
             ctxt->disableSAX = 1;
     }
+
+    return;
+}
+
+/**
+ * xmlCtxtErr:
+ * @ctxt:  a parser context
+ * @node: the current node or NULL
+ * @domain: the domain for the error
+ * @code: the code for the error
+ * @level: the xmlErrorLevel for the error
+ * @str1: extra string info
+ * @str2: extra string info
+ * @str3: extra string info
+ * @int1: extra int info
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ *
+ * Raise a parser error.
+ */
+void
+xmlCtxtErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain,
+           xmlParserErrors code, xmlErrorLevel level,
+           const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
+           int int1, const char *msg, ...)
+{
+    va_list ap;
+
+    va_start(ap, msg);
+    xmlCtxtVErr(ctxt, node, domain, code, level,
+                str1, str2, str3, int1, msg, ap);
+    va_end(ap);
 }
 
 /**
- * xmlErrEncodingInt:
+ * xmlFatalErr:
  * @ctxt:  an XML parser context
- * @error:  the error number
- * @msg:  the error message
- * @val:  an integer value
+ * @code:  the error number
+ * @info:  extra information string
  *
- * n encoding error
+ * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void LIBXML_ATTR_FORMAT(3,0)
-xmlErrEncodingInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
-                  const char *msg, int val)
+void
+xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors code, const char *info)
 {
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if (ctxt != NULL)
-        ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL,
-                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
-                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
-    if (ctxt != NULL) {
-        ctxt->wellFormed = 0;
-        if (ctxt->recovery == 0)
-            ctxt->disableSAX = 1;
+    const char *errmsg;
+
+    errmsg = xmlErrString(code);
+
+    if (info == NULL) {
+        xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, code, XML_ERR_FATAL,
+                   NULL, NULL, NULL, 0, "%s\n", errmsg);
+    } else {
+        xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, code, XML_ERR_FATAL,
+                   (const xmlChar *) info, NULL, NULL, 0,
+                   "%s: %s\n", errmsg, info);
     }
 }
 
@@ -220,47 +397,30 @@ xmlIsLetter(int c) {
  *									*
  ************************************************************************/
 
-/* #define DEBUG_INPUT */
-/* #define DEBUG_STACK */
-/* #define DEBUG_PUSH */
-
-
 /* we need to keep enough input to show errors in context */
 #define LINE_LEN        80
 
-#ifdef DEBUG_INPUT
-#define CHECK_BUFFER(in) check_buffer(in)
-
-static
-void check_buffer(xmlParserInputPtr in) {
-    if (in->base != xmlBufContent(in->buf->buffer)) {
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlParserInput: base mismatch problem\n");
-    }
-    if (in->cur < in->base) {
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlParserInput: cur < base problem\n");
-    }
-    if (in->cur > in->base + xmlBufUse(in->buf->buffer)) {
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlParserInput: cur > base + use problem\n");
-    }
-    xmlGenericError(xmlGenericErrorContext,"buffer %x : content %x, cur %d, use %d\n",
-            (int) in, (int) xmlBufContent(in->buf->buffer), in->cur - in->base,
-	    xmlBufUse(in->buf->buffer));
+/**
+ * xmlHaltParser:
+ * @ctxt:  an XML parser context
+ *
+ * Blocks further parser processing don't override error
+ * for internal use
+ */
+void
+xmlHaltParser(xmlParserCtxtPtr ctxt) {
+    if (ctxt == NULL)
+        return;
+    ctxt->instate = XML_PARSER_EOF; /* TODO: Remove after refactoring */
+    ctxt->disableSAX = 2;
 }
 
-#else
-#define CHECK_BUFFER(in)
-#endif
-
-
 /**
  * xmlParserInputRead:
  * @in:  an XML parser input
  * @len:  an indicative size for the lookahead
  *
- * This function was internal and is deprecated.
+ * DEPRECATED: This function was internal and is deprecated.
  *
  * Returns -1 as this is an error to use it.
  */
@@ -269,11 +429,63 @@ xmlParserInputRead(xmlParserInputPtr in ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUS
     return(-1);
 }
 
+/**
+ * xmlParserGrow:
+ * @ctxt:  an XML parser context
+ *
+ * Grow the input buffer.
+ *
+ * Returns the number of bytes read or -1 in case of error.
+ */
+int
+xmlParserGrow(xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr in = ctxt->input;
+    xmlParserInputBufferPtr buf = in->buf;
+    size_t curEnd = in->end - in->cur;
+    size_t curBase = in->cur - in->base;
+    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
+                       XML_MAX_HUGE_LENGTH :
+                       XML_MAX_LOOKUP_LIMIT;
+    int ret;
+
+    if (buf == NULL)
+        return(0);
+    /* Don't grow push parser buffer. */
+    if (PARSER_PROGRESSIVE(ctxt))
+        return(0);
+    /* Don't grow memory buffers. */
+    if ((buf->encoder == NULL) && (buf->readcallback == NULL))
+        return(0);
+    if (buf->error != 0)
+        return(-1);
+
+    if (curBase > maxLength) {
+        xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT,
+                    "Buffer size limit exceeded, try XML_PARSE_HUGE\n");
+        xmlHaltParser(ctxt);
+	return(-1);
+    }
+
+    if (curEnd >= INPUT_CHUNK)
+        return(0);
+
+    ret = xmlParserInputBufferGrow(buf, INPUT_CHUNK);
+    xmlBufUpdateInput(buf->buffer, in, curBase);
+
+    if (ret < 0) {
+        xmlCtxtErrIO(ctxt, buf->error, NULL);
+    }
+
+    return(ret);
+}
+
 /**
  * xmlParserInputGrow:
  * @in:  an XML parser input
  * @len:  an indicative size for the lookahead
  *
+ * DEPRECATED: Don't use.
+ *
  * This function increase the input for the parser. It tries to
  * preserve pointers to the input buffer, and keep already read data
  *
@@ -286,41 +498,81 @@ xmlParserInputGrow(xmlParserInputPtr in, int len) {
     size_t indx;
 
     if ((in == NULL) || (len < 0)) return(-1);
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext, "Grow\n");
-#endif
     if (in->buf == NULL) return(-1);
     if (in->base == NULL) return(-1);
     if (in->cur == NULL) return(-1);
     if (in->buf->buffer == NULL) return(-1);
 
-    CHECK_BUFFER(in);
+    /* Don't grow memory buffers. */
+    if ((in->buf->encoder == NULL) && (in->buf->readcallback == NULL))
+        return(0);
 
     indx = in->cur - in->base;
     if (xmlBufUse(in->buf->buffer) > (unsigned int) indx + INPUT_CHUNK) {
-
-	CHECK_BUFFER(in);
-
         return(0);
     }
-    if (in->buf->readcallback != NULL) {
-	ret = xmlParserInputBufferGrow(in->buf, len);
-    } else
-        return(0);
+    ret = xmlParserInputBufferGrow(in->buf, len);
 
     in->base = xmlBufContent(in->buf->buffer);
+    if (in->base == NULL) {
+        in->base = BAD_CAST "";
+        in->cur = in->base;
+        in->end = in->base;
+        return(-1);
+    }
     in->cur = in->base + indx;
     in->end = xmlBufEnd(in->buf->buffer);
 
-    CHECK_BUFFER(in);
-
     return(ret);
 }
 
+/**
+ * xmlParserShrink:
+ * @ctxt:  an XML parser context
+ *
+ * Shrink the input buffer.
+ */
+void
+xmlParserShrink(xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr in = ctxt->input;
+    xmlParserInputBufferPtr buf = in->buf;
+    size_t used;
+
+    if (buf == NULL)
+        return;
+    /* Don't shrink pull parser memory buffers. */
+    if ((!PARSER_PROGRESSIVE(ctxt)) &&
+        (buf->encoder == NULL) &&
+        (buf->readcallback == NULL))
+        return;
+
+    used = in->cur - in->base;
+    /*
+     * Do not shrink on large buffers whose only a tiny fraction
+     * was consumed
+     */
+    if (used > INPUT_CHUNK) {
+	size_t res = xmlBufShrink(buf->buffer, used - LINE_LEN);
+
+	if (res > 0) {
+            used -= res;
+            if ((res > ULONG_MAX) ||
+                (in->consumed > ULONG_MAX - (unsigned long)res))
+                in->consumed = ULONG_MAX;
+            else
+                in->consumed += res;
+	}
+    }
+
+    xmlBufUpdateInput(buf->buffer, in, used);
+}
+
 /**
  * xmlParserInputShrink:
  * @in:  an XML parser input
  *
+ * DEPRECATED: Don't use.
+ *
  * This function removes used input for the parser.
  */
 void
@@ -328,17 +580,12 @@ xmlParserInputShrink(xmlParserInputPtr in) {
     size_t used;
     size_t ret;
 
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext, "Shrink\n");
-#endif
     if (in == NULL) return;
     if (in->buf == NULL) return;
     if (in->base == NULL) return;
     if (in->cur == NULL) return;
     if (in->buf->buffer == NULL) return;
 
-    CHECK_BUFFER(in);
-
     used = in->cur - in->base;
     /*
      * Do not shrink on large buffers whose only a tiny fraction
@@ -348,7 +595,11 @@ xmlParserInputShrink(xmlParserInputPtr in) {
 	ret = xmlBufShrink(in->buf->buffer, used - LINE_LEN);
 	if (ret > 0) {
             used -= ret;
-	    in->consumed += ret;
+            if ((ret > ULONG_MAX) ||
+                (in->consumed > ULONG_MAX - (unsigned long)ret))
+                in->consumed = ULONG_MAX;
+            else
+                in->consumed += ret;
 	}
     }
 
@@ -357,10 +608,15 @@ xmlParserInputShrink(xmlParserInputPtr in) {
     }
 
     in->base = xmlBufContent(in->buf->buffer);
+    if (in->base == NULL) {
+        /* TODO: raise error */
+        in->base = BAD_CAST "";
+        in->cur = in->base;
+        in->end = in->base;
+        return;
+    }
     in->cur = in->base + used;
     in->end = xmlBufEnd(in->buf->buffer);
-
-    CHECK_BUFFER(in);
 }
 
 /************************************************************************
@@ -373,149 +629,95 @@ xmlParserInputShrink(xmlParserInputPtr in) {
  * xmlNextChar:
  * @ctxt:  the XML parser context
  *
+ * DEPRECATED: Internal function, do not use.
+ *
  * Skip to the next char input char.
  */
 
 void
 xmlNextChar(xmlParserCtxtPtr ctxt)
 {
-    if ((ctxt == NULL) || (ctxt->instate == XML_PARSER_EOF) ||
-        (ctxt->input == NULL))
+    const unsigned char *cur;
+    size_t avail;
+    int c;
+
+    if ((ctxt == NULL) || (ctxt->input == NULL))
         return;
 
-    if (!(VALID_CTXT(ctxt))) {
-        xmlErrInternal(ctxt, "Parser input data memory error\n", NULL);
-	ctxt->errNo = XML_ERR_INTERNAL_ERROR;
-        xmlStopParser(ctxt);
-	return;
-    }
+    avail = ctxt->input->end - ctxt->input->cur;
 
-    if ((*ctxt->input->cur == 0) &&
-        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) {
-        return;
+    if (avail < INPUT_CHUNK) {
+        xmlParserGrow(ctxt);
+        if (ctxt->input->cur >= ctxt->input->end)
+            return;
+        avail = ctxt->input->end - ctxt->input->cur;
     }
 
-    if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
-        const unsigned char *cur;
-        unsigned char c;
+    cur = ctxt->input->cur;
+    c = *cur;
 
-        /*
-         *   2.11 End-of-Line Handling
-         *   the literal two-character sequence "#xD#xA" or a standalone
-         *   literal #xD, an XML processor must pass to the application
-         *   the single character #xA.
-         */
-        if (*(ctxt->input->cur) == '\n') {
-            ctxt->input->line++; ctxt->input->col = 1;
-        } else
+    if (c < 0x80) {
+        if (c == '\n') {
+            ctxt->input->cur++;
+            ctxt->input->line++;
+            ctxt->input->col = 1;
+        } else if (c == '\r') {
+            /*
+             *   2.11 End-of-Line Handling
+             *   the literal two-character sequence "#xD#xA" or a standalone
+             *   literal #xD, an XML processor must pass to the application
+             *   the single character #xA.
+             */
+            ctxt->input->cur += ((cur[1] == '\n') ? 2 : 1);
+            ctxt->input->line++;
+            ctxt->input->col = 1;
+            return;
+        } else {
+            ctxt->input->cur++;
             ctxt->input->col++;
+        }
+    } else {
+        ctxt->input->col++;
 
-        /*
-         * We are supposed to handle UTF8, check it's valid
-         * From rfc2044: encoding of the Unicode values on UTF-8:
-         *
-         * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
-         * 0000 0000-0000 007F   0xxxxxxx
-         * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
-         * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
-         *
-         * Check for the 0x110000 limit too
-         */
-        cur = ctxt->input->cur;
-
-        c = *cur;
-        if (c & 0x80) {
-            if (c == 0xC0)
-	        goto encoding_error;
-            if (cur[1] == 0) {
-                xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                cur = ctxt->input->cur;
-            }
-            if ((cur[1] & 0xc0) != 0x80)
+        if ((avail < 2) || (cur[1] & 0xc0) != 0x80)
+            goto encoding_error;
+
+        if (c < 0xe0) {
+            /* 2-byte code */
+            if (c < 0xc2)
                 goto encoding_error;
-            if ((c & 0xe0) == 0xe0) {
-                unsigned int val;
+            ctxt->input->cur += 2;
+        } else {
+            unsigned int val = (c << 8) | cur[1];
 
-                if (cur[2] == 0) {
-                    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                    cur = ctxt->input->cur;
-                }
-                if ((cur[2] & 0xc0) != 0x80)
+            if ((avail < 3) || (cur[2] & 0xc0) != 0x80)
+                goto encoding_error;
+
+            if (c < 0xf0) {
+                /* 3-byte code */
+                if ((val < 0xe0a0) || ((val >= 0xeda0) && (val < 0xee00)))
+                    goto encoding_error;
+                ctxt->input->cur += 3;
+            } else {
+                if ((avail < 4) || ((cur[3] & 0xc0) != 0x80))
                     goto encoding_error;
-                if ((c & 0xf0) == 0xf0) {
-                    if (cur[3] == 0) {
-                        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                        cur = ctxt->input->cur;
-                    }
-                    if (((c & 0xf8) != 0xf0) ||
-                        ((cur[3] & 0xc0) != 0x80))
-                        goto encoding_error;
-                    /* 4-byte code */
-                    ctxt->input->cur += 4;
-                    val = (cur[0] & 0x7) << 18;
-                    val |= (cur[1] & 0x3f) << 12;
-                    val |= (cur[2] & 0x3f) << 6;
-                    val |= cur[3] & 0x3f;
-                } else {
-                    /* 3-byte code */
-                    ctxt->input->cur += 3;
-                    val = (cur[0] & 0xf) << 12;
-                    val |= (cur[1] & 0x3f) << 6;
-                    val |= cur[2] & 0x3f;
-                }
-                if (((val > 0xd7ff) && (val < 0xe000)) ||
-                    ((val > 0xfffd) && (val < 0x10000)) ||
-                    (val >= 0x110000)) {
-		xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
-				  "Char 0x%X out of allowed range\n",
-				  val);
-                }
-            } else
-                /* 2-byte code */
-                ctxt->input->cur += 2;
-        } else
-            /* 1-byte code */
-            ctxt->input->cur++;
-    } else {
-        /*
-         * Assume it's a fixed length encoding (1) with
-         * a compatible encoding for the ASCII set, since
-         * XML constructs only use < 128 chars
-         */
 
-        if (*(ctxt->input->cur) == '\n') {
-            ctxt->input->line++; ctxt->input->col = 1;
-        } else
-            ctxt->input->col++;
-        ctxt->input->cur++;
+                /* 4-byte code */
+                if ((val < 0xf090) || (val >= 0xf490))
+                    goto encoding_error;
+                ctxt->input->cur += 4;
+            }
+        }
     }
-    if (*ctxt->input->cur == 0)
-        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+
     return;
-encoding_error:
-    /*
-     * If we detect an UTF8 error that probably mean that the
-     * input encoding didn't get properly advertised in the
-     * declaration header. Report the error and switch the encoding
-     * to ISO-Latin-1 (if you don't like this policy, just declare the
-     * encoding !)
-     */
-    if ((ctxt == NULL) || (ctxt->input == NULL) ||
-        (ctxt->input->end - ctxt->input->cur < 4)) {
-	__xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
-		     "Input is not proper UTF-8, indicate encoding !\n",
-		     NULL, NULL);
-    } else {
-        char buffer[150];
 
-	snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
-			ctxt->input->cur[0], ctxt->input->cur[1],
-			ctxt->input->cur[2], ctxt->input->cur[3]);
-	__xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
-		     "Input is not proper UTF-8, indicate encoding !\n%s",
-		     BAD_CAST buffer, NULL);
+encoding_error:
+    /* Only report the first error */
+    if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) {
+        xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL);
+        ctxt->input->flags |= XML_INPUT_ENCODING_ERROR;
     }
-    ctxt->charset = XML_CHAR_ENCODING_8859_1;
     ctxt->input->cur++;
     return;
 }
@@ -525,6 +727,8 @@ encoding_error:
  * @ctxt:  the XML parser context
  * @len:  pointer to the length of the char read
  *
+ * DEPRECATED: Internal function, do not use.
+ *
  * The current char value, if using UTF-8 this may actually span multiple
  * bytes in the input buffer. Implement the end of line normalization:
  * 2.11 End-of-Line Handling
@@ -540,260 +744,157 @@ encoding_error:
 
 int
 xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
+    const unsigned char *cur;
+    size_t avail;
+    int c;
+
     if ((ctxt == NULL) || (len == NULL) || (ctxt->input == NULL)) return(0);
-    if (ctxt->instate == XML_PARSER_EOF)
-	return(0);
 
-    if ((*ctxt->input->cur >= 0x20) && (*ctxt->input->cur <= 0x7F)) {
-	    *len = 1;
-	    return((int) *ctxt->input->cur);
+    avail = ctxt->input->end - ctxt->input->cur;
+
+    if (avail < INPUT_CHUNK) {
+        xmlParserGrow(ctxt);
+        avail = ctxt->input->end - ctxt->input->cur;
     }
-    if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
-	/*
-	 * We are supposed to handle UTF8, check it's valid
-	 * From rfc2044: encoding of the Unicode values on UTF-8:
-	 *
-	 * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
-	 * 0000 0000-0000 007F   0xxxxxxx
-	 * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
-	 * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
-	 *
-	 * Check for the 0x110000 limit too
-	 */
-	const unsigned char *cur = ctxt->input->cur;
-	unsigned char c;
-	unsigned int val;
-
-	c = *cur;
-	if (c & 0x80) {
-	    if (((c & 0x40) == 0) || (c == 0xC0))
-		goto encoding_error;
-	    if (cur[1] == 0) {
-		xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                cur = ctxt->input->cur;
-            }
-	    if ((cur[1] & 0xc0) != 0x80)
-		goto encoding_error;
-	    if ((c & 0xe0) == 0xe0) {
-		if (cur[2] == 0) {
-		    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                    cur = ctxt->input->cur;
+
+    cur = ctxt->input->cur;
+    c = *cur;
+
+    if (c < 0x80) {
+	/* 1-byte code */
+        if (c < 0x20) {
+            /*
+             *   2.11 End-of-Line Handling
+             *   the literal two-character sequence "#xD#xA" or a standalone
+             *   literal #xD, an XML processor must pass to the application
+             *   the single character #xA.
+             */
+            if (c == '\r') {
+                /*
+                 * TODO: This function shouldn't change the 'cur' pointer
+                 * as side effect, but the NEXTL macro in parser.c relies
+                 * on this behavior when incrementing line numbers.
+                 */
+                if (cur[1] == '\n')
+                    ctxt->input->cur++;
+                *len = 1;
+                c = '\n';
+            } else if (c == 0) {
+                if (ctxt->input->cur >= ctxt->input->end) {
+                    *len = 0;
+                } else {
+                    *len = 1;
+                    /*
+                     * TODO: Null bytes should be handled by callers,
+                     * but this can be tricky.
+                     */
+                    xmlFatalErr(ctxt, XML_ERR_INVALID_CHAR,
+                            "Char 0x0 out of allowed range\n");
                 }
-		if ((cur[2] & 0xc0) != 0x80)
-		    goto encoding_error;
-		if ((c & 0xf0) == 0xf0) {
-		    if (cur[3] == 0) {
-			xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                        cur = ctxt->input->cur;
-                    }
-		    if (((c & 0xf8) != 0xf0) ||
-			((cur[3] & 0xc0) != 0x80))
-			goto encoding_error;
-		    /* 4-byte code */
-		    *len = 4;
-		    val = (cur[0] & 0x7) << 18;
-		    val |= (cur[1] & 0x3f) << 12;
-		    val |= (cur[2] & 0x3f) << 6;
-		    val |= cur[3] & 0x3f;
-		    if (val < 0x10000)
-			goto encoding_error;
-		} else {
-		  /* 3-byte code */
-		    *len = 3;
-		    val = (cur[0] & 0xf) << 12;
-		    val |= (cur[1] & 0x3f) << 6;
-		    val |= cur[2] & 0x3f;
-		    if (val < 0x800)
-			goto encoding_error;
-		}
-	    } else {
-	      /* 2-byte code */
-		*len = 2;
-		val = (cur[0] & 0x1f) << 6;
-		val |= cur[1] & 0x3f;
-		if (val < 0x80)
-		    goto encoding_error;
-	    }
-	    if (!IS_CHAR(val)) {
-	        xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
-				  "Char 0x%X out of allowed range\n", val);
-	    }
-	    return(val);
-	} else {
-	    /* 1-byte code */
-	    *len = 1;
-	    if (*ctxt->input->cur == 0)
-		xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-	    if ((*ctxt->input->cur == 0) &&
-	        (ctxt->input->end > ctxt->input->cur)) {
-	        xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
-				  "Char 0x0 out of allowed range\n", 0);
-	    }
-	    if (*ctxt->input->cur == 0xD) {
-		if (ctxt->input->cur[1] == 0xA) {
-		    ctxt->input->cur++;
-		}
-		return(0xA);
-	    }
-	    return((int) *ctxt->input->cur);
-	}
-    }
-    /*
-     * Assume it's a fixed length encoding (1) with
-     * a compatible encoding for the ASCII set, since
-     * XML constructs only use < 128 chars
-     */
-    *len = 1;
-    if (*ctxt->input->cur == 0xD) {
-	if (ctxt->input->cur[1] == 0xA) {
-	    ctxt->input->cur++;
-	}
-	return(0xA);
-    }
-    return((int) *ctxt->input->cur);
-encoding_error:
-    /*
-     * An encoding problem may arise from a truncated input buffer
-     * splitting a character in the middle. In that case do not raise
-     * an error but return 0 to indicate an end of stream problem
-     */
-    if (ctxt->input->end - ctxt->input->cur < 4) {
-	*len = 0;
-	return(0);
-    }
+            } else {
+                *len = 1;
+            }
+        } else {
+            *len = 1;
+        }
 
-    /*
-     * If we detect an UTF8 error that probably mean that the
-     * input encoding didn't get properly advertised in the
-     * declaration header. Report the error and switch the encoding
-     * to ISO-Latin-1 (if you don't like this policy, just declare the
-     * encoding !)
-     */
-    {
-        char buffer[150];
+        return(c);
+    } else {
+        int val;
 
-	snprintf(&buffer[0], 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
-			ctxt->input->cur[0], ctxt->input->cur[1],
-			ctxt->input->cur[2], ctxt->input->cur[3]);
-	__xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
-		     "Input is not proper UTF-8, indicate encoding !\n%s",
-		     BAD_CAST buffer, NULL);
-    }
-    ctxt->charset = XML_CHAR_ENCODING_8859_1;
-    *len = 1;
-    return((int) *ctxt->input->cur);
-}
+        if (avail < 2)
+            goto incomplete_sequence;
+        if ((cur[1] & 0xc0) != 0x80)
+            goto encoding_error;
 
-/**
- * xmlStringCurrentChar:
- * @ctxt:  the XML parser context
- * @cur:  pointer to the beginning of the char
- * @len:  pointer to the length of the char read
- *
- * The current char value, if using UTF-8 this may actually span multiple
- * bytes in the input buffer.
- *
- * Returns the current char value and its length
- */
-
-int
-xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar * cur, int *len)
-{
-    if ((len == NULL) || (cur == NULL)) return(0);
-    if ((ctxt == NULL) || (ctxt->charset == XML_CHAR_ENCODING_UTF8)) {
-        /*
-         * We are supposed to handle UTF8, check it's valid
-         * From rfc2044: encoding of the Unicode values on UTF-8:
-         *
-         * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
-         * 0000 0000-0000 007F   0xxxxxxx
-         * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
-         * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
-         *
-         * Check for the 0x110000 limit too
-         */
-        unsigned char c;
-        unsigned int val;
-
-        c = *cur;
-        if (c & 0x80) {
-            if ((cur[1] & 0xc0) != 0x80)
+        if (c < 0xe0) {
+            /* 2-byte code */
+            if (c < 0xc2)
+                goto encoding_error;
+            val = (c & 0x1f) << 6;
+            val |= cur[1] & 0x3f;
+            *len = 2;
+        } else {
+            if (avail < 3)
+                goto incomplete_sequence;
+            if ((cur[2] & 0xc0) != 0x80)
                 goto encoding_error;
-            if ((c & 0xe0) == 0xe0) {
 
-                if ((cur[2] & 0xc0) != 0x80)
+            if (c < 0xf0) {
+                /* 3-byte code */
+                val = (c & 0xf) << 12;
+                val |= (cur[1] & 0x3f) << 6;
+                val |= cur[2] & 0x3f;
+                if ((val < 0x800) || ((val >= 0xd800) && (val < 0xe000)))
                     goto encoding_error;
-                if ((c & 0xf0) == 0xf0) {
-                    if (((c & 0xf8) != 0xf0) || ((cur[3] & 0xc0) != 0x80))
-                        goto encoding_error;
-                    /* 4-byte code */
-                    *len = 4;
-                    val = (cur[0] & 0x7) << 18;
-                    val |= (cur[1] & 0x3f) << 12;
-                    val |= (cur[2] & 0x3f) << 6;
-                    val |= cur[3] & 0x3f;
-                } else {
-                    /* 3-byte code */
-                    *len = 3;
-                    val = (cur[0] & 0xf) << 12;
-                    val |= (cur[1] & 0x3f) << 6;
-                    val |= cur[2] & 0x3f;
-                }
+                *len = 3;
             } else {
-                /* 2-byte code */
-                *len = 2;
-                val = (cur[0] & 0x1f) << 6;
-                val |= cur[1] & 0x3f;
-            }
-            if (!IS_CHAR(val)) {
-	        xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
-				  "Char 0x%X out of allowed range\n", val);
+                if (avail < 4)
+                    goto incomplete_sequence;
+                if ((cur[3] & 0xc0) != 0x80)
+                    goto encoding_error;
+
+                /* 4-byte code */
+                val = (c & 0x0f) << 18;
+                val |= (cur[1] & 0x3f) << 12;
+                val |= (cur[2] & 0x3f) << 6;
+                val |= cur[3] & 0x3f;
+                if ((val < 0x10000) || (val >= 0x110000))
+                    goto encoding_error;
+                *len = 4;
             }
-            return (val);
-        } else {
-            /* 1-byte code */
-            *len = 1;
-            return ((int) *cur);
         }
+
+        return(val);
     }
-    /*
-     * Assume it's a fixed length encoding (1) with
-     * a compatible encoding for the ASCII set, since
-     * XML constructs only use < 128 chars
-     */
-    *len = 1;
-    return ((int) *cur);
+
 encoding_error:
+    /* Only report the first error */
+    if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) {
+        xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL);
+        ctxt->input->flags |= XML_INPUT_ENCODING_ERROR;
+    }
+    *len = 1;
+    return(0xFFFD); /* U+FFFD Replacement Character */
 
+incomplete_sequence:
     /*
      * An encoding problem may arise from a truncated input buffer
      * splitting a character in the middle. In that case do not raise
-     * an error but return 0 to indicate an end of stream problem
+     * an error but return 0. This should only happen when push parsing
+     * char data.
      */
-    if ((ctxt == NULL) || (ctxt->input == NULL) ||
-        (ctxt->input->end - ctxt->input->cur < 4)) {
-	*len = 0;
-	return(0);
-    }
-    /*
-     * If we detect an UTF8 error that probably mean that the
-     * input encoding didn't get properly advertised in the
-     * declaration header. Report the error and switch the encoding
-     * to ISO-Latin-1 (if you don't like this policy, just declare the
-     * encoding !)
-     */
-    {
-        char buffer[150];
+    *len = 0;
+    return(0);
+}
 
-	snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
-			ctxt->input->cur[0], ctxt->input->cur[1],
-			ctxt->input->cur[2], ctxt->input->cur[3]);
-	__xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
-		     "Input is not proper UTF-8, indicate encoding !\n%s",
-		     BAD_CAST buffer, NULL);
-    }
-    *len = 1;
-    return ((int) *cur);
+/**
+ * xmlStringCurrentChar:
+ * @ctxt:  the XML parser context
+ * @cur:  pointer to the beginning of the char
+ * @len:  pointer to the length of the char read
+ *
+ * DEPRECATED: Internal function, do not use.
+ *
+ * The current char value, if using UTF-8 this may actually span multiple
+ * bytes in the input buffer.
+ *
+ * Returns the current char value and its length
+ */
+
+int
+xmlStringCurrentChar(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
+                     const xmlChar *cur, int *len) {
+    int c;
+
+    if ((cur == NULL) || (len == NULL))
+        return(0);
+
+    /* cur is zero-terminated, so we can lie about its length. */
+    *len = 4;
+    c = xmlGetUTF8Char(cur, len);
+
+    return((c < 0) ? 0 : c);
 }
 
 /**
@@ -807,7 +908,7 @@ encoding_error:
  */
 int
 xmlCopyCharMultiByte(xmlChar *out, int val) {
-    if (out == NULL) return(0);
+    if ((out == NULL) || (val < 0)) return(0);
     /*
      * We are supposed to handle UTF8, check it's valid
      * From rfc2044: encoding of the Unicode values on UTF-8:
@@ -824,16 +925,17 @@ xmlCopyCharMultiByte(xmlChar *out, int val) {
 	else if (val < 0x10000) { *out++= (val >> 12) | 0xE0;  bits=  6;}
 	else if (val < 0x110000)  { *out++= (val >> 18) | 0xF0;  bits=  12; }
 	else {
-	    xmlErrEncodingInt(NULL, XML_ERR_INVALID_CHAR,
-		    "Internal error, xmlCopyCharMultiByte 0x%X out of bound\n",
-			      val);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+            fprintf(stderr, "xmlCopyCharMultiByte: codepoint out of range\n");
+            abort();
+#endif
 	    return(0);
 	}
 	for ( ; bits >= 0; bits-= 6)
 	    *out++= ((val >> bits) & 0x3F) | 0x80 ;
 	return (out - savedout);
     }
-    *out = (xmlChar) val;
+    *out = val;
     return 1;
 }
 
@@ -850,12 +952,12 @@ xmlCopyCharMultiByte(xmlChar *out, int val) {
 
 int
 xmlCopyChar(int len ATTRIBUTE_UNUSED, xmlChar *out, int val) {
-    if (out == NULL) return(0);
+    if ((out == NULL) || (val < 0)) return(0);
     /* the len parameter is ignored */
     if  (val >= 0x80) {
 	return(xmlCopyCharMultiByte (out, val));
     }
-    *out = (xmlChar) val;
+    *out = val;
     return 1;
 }
 
@@ -866,314 +968,521 @@ xmlCopyChar(int len ATTRIBUTE_UNUSED, xmlChar *out, int val) {
  ************************************************************************/
 
 static int
-xmlSwitchInputEncodingInt(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
-                          xmlCharEncodingHandlerPtr handler, int len);
+xmlDetectEBCDIC(xmlParserInputPtr input, xmlCharEncodingHandlerPtr *hout) {
+    xmlChar out[200];
+    xmlCharEncodingHandlerPtr handler;
+    int inlen, outlen, res, i;
+
+    *hout = NULL;
+
+    /*
+     * To detect the EBCDIC code page, we convert the first 200 bytes
+     * to EBCDIC-US and try to find the encoding declaration.
+     */
+    res = xmlLookupCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC, &handler);
+    if (res != 0)
+        return(res);
+    outlen = sizeof(out) - 1;
+    inlen = input->end - input->cur;
+    res = xmlEncInputChunk(handler, out, &outlen, input->cur, &inlen);
+    /*
+     * Return the EBCDIC handler if decoding failed. The error will
+     * be reported later.
+     */
+    if (res < 0)
+        goto done;
+    out[outlen] = 0;
+
+    for (i = 0; i < outlen; i++) {
+        if (out[i] == '>')
+            break;
+        if ((out[i] == 'e') &&
+            (xmlStrncmp(out + i, BAD_CAST "encoding", 8) == 0)) {
+            int start, cur, quote;
+
+            i += 8;
+            while (IS_BLANK_CH(out[i]))
+                i += 1;
+            if (out[i++] != '=')
+                break;
+            while (IS_BLANK_CH(out[i]))
+                i += 1;
+            quote = out[i++];
+            if ((quote != '\'') && (quote != '"'))
+                break;
+            start = i;
+            cur = out[i];
+            while (((cur >= 'a') && (cur <= 'z')) ||
+                   ((cur >= 'A') && (cur <= 'Z')) ||
+                   ((cur >= '0') && (cur <= '9')) ||
+                   (cur == '.') || (cur == '_') ||
+                   (cur == '-'))
+                cur = out[++i];
+            if (cur != quote)
+                break;
+            out[i] = 0;
+            xmlCharEncCloseFunc(handler);
+            res = xmlOpenCharEncodingHandler((char *) out + start,
+                                             /* output */ 0, &handler);
+            if (res != 0)
+                return(res);
+            *hout = handler;
+            return(0);
+        }
+    }
+
+done:
+    /*
+     * Encoding handlers are stateful, so we have to recreate them.
+     */
+    xmlCharEncCloseFunc(handler);
+    res = xmlLookupCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC, &handler);
+    if (res != 0)
+        return(res);
+    *hout = handler;
+    return(0);
+}
+
 /**
  * xmlSwitchEncoding:
  * @ctxt:  the parser context
  * @enc:  the encoding value (number)
  *
- * change the input functions when discovering the character encoding
- * of a given entity.
+ * Use encoding specified by enum to decode input data. This overrides
+ * the encoding found in the XML declaration.
+ *
+ * This function can also be used to override the encoding of chunks
+ * passed to xmlParseChunk.
  *
  * Returns 0 in case of success, -1 otherwise
  */
 int
 xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
 {
-    xmlCharEncodingHandlerPtr handler;
-    int len = -1;
+    xmlCharEncodingHandlerPtr handler = NULL;
     int ret;
+    int res;
+
+    if ((ctxt == NULL) || (ctxt->input == NULL))
+        return(-1);
 
-    if (ctxt == NULL) return(-1);
     switch (enc) {
-	case XML_CHAR_ENCODING_ERROR:
-	    __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
-	                   "encoding unknown\n", NULL, NULL);
-	    return(-1);
 	case XML_CHAR_ENCODING_NONE:
-	    /* let's assume it's UTF-8 without the XML decl */
-	    ctxt->charset = XML_CHAR_ENCODING_UTF8;
-	    return(0);
 	case XML_CHAR_ENCODING_UTF8:
-	    /* default encoding, no conversion should be needed */
-	    ctxt->charset = XML_CHAR_ENCODING_UTF8;
-
-	    /*
-	     * Errata on XML-1.0 June 20 2001
-	     * Specific handling of the Byte Order Mark for
-	     * UTF-8
-	     */
-	    if ((ctxt->input != NULL) &&
-		(ctxt->input->cur[0] == 0xEF) &&
-		(ctxt->input->cur[1] == 0xBB) &&
-		(ctxt->input->cur[2] == 0xBF)) {
-		ctxt->input->cur += 3;
-	    }
-	    return(0);
-    case XML_CHAR_ENCODING_UTF16LE:
-    case XML_CHAR_ENCODING_UTF16BE:
-        /*The raw input characters are encoded
-         *in UTF-16. As we expect this function
-         *to be called after xmlCharEncInFunc, we expect
-         *ctxt->input->cur to contain UTF-8 encoded characters.
-         *So the raw UTF16 Byte Order Mark
-         *has also been converted into
-         *an UTF-8 BOM. Let's skip that BOM.
-         */
-        if ((ctxt->input != NULL) && (ctxt->input->cur != NULL) &&
-            (ctxt->input->cur[0] == 0xEF) &&
-            (ctxt->input->cur[1] == 0xBB) &&
-            (ctxt->input->cur[2] == 0xBF)) {
-            ctxt->input->cur += 3;
-        }
-        len = 90;
-	break;
-    case XML_CHAR_ENCODING_UCS2:
-        len = 90;
-	break;
-    case XML_CHAR_ENCODING_UCS4BE:
-    case XML_CHAR_ENCODING_UCS4LE:
-    case XML_CHAR_ENCODING_UCS4_2143:
-    case XML_CHAR_ENCODING_UCS4_3412:
-        len = 180;
-	break;
-    case XML_CHAR_ENCODING_EBCDIC:
-    case XML_CHAR_ENCODING_8859_1:
-    case XML_CHAR_ENCODING_8859_2:
-    case XML_CHAR_ENCODING_8859_3:
-    case XML_CHAR_ENCODING_8859_4:
-    case XML_CHAR_ENCODING_8859_5:
-    case XML_CHAR_ENCODING_8859_6:
-    case XML_CHAR_ENCODING_8859_7:
-    case XML_CHAR_ENCODING_8859_8:
-    case XML_CHAR_ENCODING_8859_9:
-    case XML_CHAR_ENCODING_ASCII:
-    case XML_CHAR_ENCODING_2022_JP:
-    case XML_CHAR_ENCODING_SHIFT_JIS:
-    case XML_CHAR_ENCODING_EUC_JP:
-        len = 45;
-	break;
-    }
-    handler = xmlGetCharEncodingHandler(enc);
-    if (handler == NULL) {
-	/*
-	 * Default handlers.
-	 */
-	switch (enc) {
-	    case XML_CHAR_ENCODING_ASCII:
-		/* default encoding, no conversion should be needed */
-		ctxt->charset = XML_CHAR_ENCODING_UTF8;
-		return(0);
-	    case XML_CHAR_ENCODING_8859_1:
-		if ((ctxt->inputNr == 1) &&
-		    (ctxt->encoding == NULL) &&
-		    (ctxt->input != NULL) &&
-		    (ctxt->input->encoding != NULL)) {
-		    ctxt->encoding = xmlStrdup(ctxt->input->encoding);
-		}
-		ctxt->charset = enc;
-		return(0);
-	    default:
-		__xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
-                        "encoding not supported: %s\n",
-			BAD_CAST xmlGetCharEncodingName(enc), NULL);
-                /*
-                 * TODO: We could recover from errors in external entities
-                 * if we didn't stop the parser. But most callers of this
-                 * function don't check the return value.
-                 */
-                xmlStopParser(ctxt);
-                return(-1);
-        }
+        case XML_CHAR_ENCODING_ASCII:
+            res = 0;
+            break;
+        case XML_CHAR_ENCODING_EBCDIC:
+            res = xmlDetectEBCDIC(ctxt->input, &handler);
+            break;
+        default:
+            res = xmlLookupCharEncodingHandler(enc, &handler);
+            break;
     }
-    ret = xmlSwitchInputEncodingInt(ctxt, ctxt->input, handler, len);
-    if ((ret < 0) || (ctxt->errNo == XML_I18N_CONV_FAILED)) {
-        /*
-	 * on encoding conversion errors, stop the parser
-	 */
-        xmlStopParser(ctxt);
-	ctxt->errNo = XML_I18N_CONV_FAILED;
+
+    if (res != 0) {
+        const char *name = xmlGetCharEncodingName(enc);
+
+        xmlFatalErr(ctxt, res, (name ? name : "<null>"));
+        return(-1);
+    }
+
+    ret = xmlSwitchInputEncoding(ctxt, ctxt->input, handler);
+
+    if ((ret >= 0) && (enc == XML_CHAR_ENCODING_NONE)) {
+        ctxt->input->flags &= ~XML_INPUT_HAS_ENCODING;
     }
+
     return(ret);
 }
 
 /**
- * xmlSwitchInputEncodingInt:
+ * xmlSwitchEncodingName:
+ * @ctxt:  the parser context, only for error reporting
+ * @input:  the input strea,
+ * @encoding:  the encoding name
+ *
+ * Available since 2.13.0.
+ *
+ * Returns 0 in case of success, -1 otherwise
+ */
+static int
+xmlSwitchInputEncodingName(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
+                           const char *encoding) {
+    xmlCharEncodingHandlerPtr handler;
+    int res;
+
+    if (encoding == NULL)
+        return(-1);
+
+    res = xmlOpenCharEncodingHandler(encoding, /* output */ 0, &handler);
+    if (res == XML_ERR_UNSUPPORTED_ENCODING) {
+        xmlWarningMsg(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+                      "Unsupported encoding: %s\n", BAD_CAST encoding, NULL);
+        return(-1);
+    } else if (res != XML_ERR_OK) {
+        xmlFatalErr(ctxt, res, encoding);
+        return(-1);
+    }
+
+    return(xmlSwitchInputEncoding(ctxt, input, handler));
+}
+
+/**
+ * xmlSwitchEncodingName:
  * @ctxt:  the parser context
+ * @encoding:  the encoding name
+ *
+ * Use specified encoding to decode input data. This overrides the
+ * encoding found in the XML declaration.
+ *
+ * This function can also be used to override the encoding of chunks
+ * passed to xmlParseChunk.
+ *
+ * Available since 2.13.0.
+ *
+ * Returns 0 in case of success, -1 otherwise
+ */
+int
+xmlSwitchEncodingName(xmlParserCtxtPtr ctxt, const char *encoding) {
+    if (ctxt == NULL)
+        return(-1);
+
+    return(xmlSwitchInputEncodingName(ctxt, ctxt->input, encoding));
+}
+
+/**
+ * xmlSwitchInputEncoding:
+ * @ctxt:  the parser context, only for error reporting
  * @input:  the input stream
  * @handler:  the encoding handler
- * @len:  the number of bytes to convert for the first line or -1
  *
- * change the input functions when discovering the character encoding
- * of a given entity.
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Use encoding handler to decode input data.
  *
  * Returns 0 in case of success, -1 otherwise
  */
-static int
-xmlSwitchInputEncodingInt(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
-                          xmlCharEncodingHandlerPtr handler, int len)
+int
+xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
+                       xmlCharEncodingHandlerPtr handler)
 {
     int nbchars;
+    xmlParserInputBufferPtr in;
 
-    if (handler == NULL)
-        return (-1);
-    if (input == NULL)
-        return (-1);
-    if (input->buf != NULL) {
-	ctxt->charset = XML_CHAR_ENCODING_UTF8;
+    if ((input == NULL) || (input->buf == NULL)) {
+        xmlCharEncCloseFunc(handler);
+	return (-1);
+    }
+    in = input->buf;
 
-        if (input->buf->encoder != NULL) {
-            /*
-             * Check in case the auto encoding detection triggered
-             * in already.
-             */
-            if (input->buf->encoder == handler)
-                return (0);
+    input->flags |= XML_INPUT_HAS_ENCODING;
 
-            /*
-             * "UTF-16" can be used for both LE and BE
-             if ((!xmlStrncmp(BAD_CAST input->buf->encoder->name,
-             BAD_CAST "UTF-16", 6)) &&
-             (!xmlStrncmp(BAD_CAST handler->name,
-             BAD_CAST "UTF-16", 6))) {
-             return(0);
-             }
-             */
+    /*
+     * UTF-8 requires no encoding handler.
+     */
+    if ((handler != NULL) &&
+        (xmlStrcasecmp(BAD_CAST handler->name, BAD_CAST "UTF-8") == 0)) {
+        xmlCharEncCloseFunc(handler);
+        handler = NULL;
+    }
 
-            /*
-             * Note: this is a bit dangerous, but that's what it
-             * takes to use nearly compatible signature for different
-             * encodings.
-             *
-             * FIXME: Encoders might buffer partial byte sequences, so
-             * this probably can't work. We should return an error and
-             * make sure that callers never try to switch the encoding
-             * twice.
-             */
-            xmlCharEncCloseFunc(input->buf->encoder);
-            input->buf->encoder = handler;
-            return (0);
-        }
-        input->buf->encoder = handler;
+    if (in->encoder == handler)
+        return (0);
 
+    if (in->encoder != NULL) {
         /*
-         * Is there already some content down the pipe to convert ?
+         * Switching encodings during parsing is a really bad idea,
+         * but Chromium can switch between ISO-8859-1 and UTF-16 before
+         * separate calls to xmlParseChunk.
+         *
+         * TODO: We should check whether the "raw" input buffer is empty and
+         * convert the old content using the old encoder.
          */
-        if (xmlBufIsEmpty(input->buf->buffer) == 0) {
-            int processed;
-	    unsigned int use;
 
-            /*
-             * Specific handling of the Byte Order Mark for
-             * UTF-16
-             */
-            if ((handler->name != NULL) &&
-                (!strcmp(handler->name, "UTF-16LE") ||
-                 !strcmp(handler->name, "UTF-16")) &&
-                (input->cur[0] == 0xFF) && (input->cur[1] == 0xFE)) {
-                input->cur += 2;
-            }
-            if ((handler->name != NULL) &&
-                (!strcmp(handler->name, "UTF-16BE")) &&
-                (input->cur[0] == 0xFE) && (input->cur[1] == 0xFF)) {
-                input->cur += 2;
-            }
-            /*
-             * Errata on XML-1.0 June 20 2001
-             * Specific handling of the Byte Order Mark for
-             * UTF-8
-             */
-            if ((handler->name != NULL) &&
-                (!strcmp(handler->name, "UTF-8")) &&
-                (input->cur[0] == 0xEF) &&
-                (input->cur[1] == 0xBB) && (input->cur[2] == 0xBF)) {
-                input->cur += 3;
-            }
+        xmlCharEncCloseFunc(in->encoder);
+        in->encoder = handler;
+        return (0);
+    }
 
-            /*
-             * Shrink the current input buffer.
-             * Move it as the raw buffer and create a new input buffer
-             */
-            processed = input->cur - input->base;
-            xmlBufShrink(input->buf->buffer, processed);
-            input->buf->raw = input->buf->buffer;
-            input->buf->buffer = xmlBufCreate();
-	    input->buf->rawconsumed = processed;
-	    use = xmlBufUse(input->buf->raw);
-
-            if (ctxt->html) {
-                /*
-                 * convert as much as possible of the buffer
-                 */
-                nbchars = xmlCharEncInput(input->buf, 1);
-            } else {
-                /*
-                 * convert just enough to get
-                 * '<?xml version="1.0" encoding="xxx"?>'
-                 * parsed with the autodetected encoding
-                 * into the parser reading buffer.
-                 */
-                nbchars = xmlCharEncFirstLineInput(input->buf, len);
-            }
-            xmlBufResetInput(input->buf->buffer, input);
-            if (nbchars < 0) {
-                xmlErrInternal(ctxt,
-                               "switching encoding: encoder error\n",
-                               NULL);
-                return (-1);
-            }
-	    input->buf->rawconsumed += use - xmlBufUse(input->buf->raw);
+    in->encoder = handler;
+
+    /*
+     * Is there already some content down the pipe to convert ?
+     */
+    if (xmlBufIsEmpty(in->buffer) == 0) {
+        xmlBufPtr buf;
+        size_t processed;
+
+        buf = xmlBufCreate();
+        if (buf == NULL) {
+            xmlCtxtErrMemory(ctxt);
+            return(-1);
         }
-        return (0);
-    } else {
-	xmlErrInternal(ctxt,
-                "static memory buffer doesn't support encoding\n", NULL);
+
         /*
-         * Callers assume that the input buffer takes ownership of the
-         * encoding handler. xmlCharEncCloseFunc frees unregistered
-         * handlers and avoids a memory leak.
+         * Shrink the current input buffer.
+         * Move it as the raw buffer and create a new input buffer
          */
-        xmlCharEncCloseFunc(handler);
-	return (-1);
+        processed = input->cur - input->base;
+        xmlBufShrink(in->buffer, processed);
+        input->consumed += processed;
+        in->raw = in->buffer;
+        in->buffer = buf;
+        in->rawconsumed = processed;
+
+        nbchars = xmlCharEncInput(in);
+        xmlBufResetInput(in->buffer, input);
+        if (nbchars == XML_ENC_ERR_MEMORY) {
+            xmlCtxtErrMemory(ctxt);
+        } else if (nbchars < 0) {
+            xmlCtxtErrIO(ctxt, in->error, NULL);
+            xmlHaltParser(ctxt);
+            return (-1);
+        }
     }
+    return (0);
 }
 
 /**
- * xmlSwitchInputEncoding:
+ * xmlSwitchToEncoding:
  * @ctxt:  the parser context
- * @input:  the input stream
  * @handler:  the encoding handler
  *
- * DEPRECATED: Use xmlSwitchToEncoding
+ * Use encoding handler to decode input data.
  *
- * change the input functions when discovering the character encoding
- * of a given entity.
+ * This function can be used to enforce the encoding of chunks passed
+ * to xmlParseChunk.
  *
  * Returns 0 in case of success, -1 otherwise
  */
 int
-xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
-                          xmlCharEncodingHandlerPtr handler) {
-    return(xmlSwitchInputEncodingInt(ctxt, input, handler, -1));
+xmlSwitchToEncoding(xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler)
+{
+    if (ctxt == NULL)
+        return(-1);
+    return(xmlSwitchInputEncoding(ctxt, ctxt->input, handler));
 }
 
 /**
- * xmlSwitchToEncoding:
+ * xmlDetectEncoding:
  * @ctxt:  the parser context
- * @handler:  the encoding handler
  *
- * change the input functions when discovering the character encoding
- * of a given entity.
+ * Handle optional BOM, detect and switch to encoding.
  *
- * Returns 0 in case of success, -1 otherwise
+ * Assumes that there are at least four bytes in the input buffer.
  */
-int
-xmlSwitchToEncoding(xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler)
-{
-    if (ctxt == NULL)
-        return(-1);
-    return(xmlSwitchInputEncodingInt(ctxt, ctxt->input, handler, -1));
+void
+xmlDetectEncoding(xmlParserCtxtPtr ctxt) {
+    const xmlChar *in;
+    xmlCharEncoding enc;
+    int bomSize;
+    int autoFlag = 0;
+
+    if (xmlParserGrow(ctxt) < 0)
+        return;
+    in = ctxt->input->cur;
+    if (ctxt->input->end - in < 4)
+        return;
+
+    if (ctxt->input->flags & XML_INPUT_HAS_ENCODING) {
+        /*
+         * If the encoding was already set, only skip the BOM which was
+         * possibly decoded to UTF-8.
+         */
+        if ((in[0] == 0xEF) && (in[1] == 0xBB) && (in[2] == 0xBF)) {
+            ctxt->input->cur += 3;
+        }
+
+        return;
+    }
+
+    enc = XML_CHAR_ENCODING_NONE;
+    bomSize = 0;
+
+    switch (in[0]) {
+        case 0x00:
+            if ((in[1] == 0x00) && (in[2] == 0x00) && (in[3] == 0x3C)) {
+                enc = XML_CHAR_ENCODING_UCS4BE;
+                autoFlag = XML_INPUT_AUTO_OTHER;
+            } else if ((in[1] == 0x3C) && (in[2] == 0x00) && (in[3] == 0x3F)) {
+                enc = XML_CHAR_ENCODING_UTF16BE;
+                autoFlag = XML_INPUT_AUTO_UTF16BE;
+            }
+            break;
+
+        case 0x3C:
+            if (in[1] == 0x00) {
+                if ((in[2] == 0x00) && (in[3] == 0x00)) {
+                    enc = XML_CHAR_ENCODING_UCS4LE;
+                    autoFlag = XML_INPUT_AUTO_OTHER;
+                } else if ((in[2] == 0x3F) && (in[3] == 0x00)) {
+                    enc = XML_CHAR_ENCODING_UTF16LE;
+                    autoFlag = XML_INPUT_AUTO_UTF16LE;
+                }
+            }
+            break;
+
+        case 0x4C:
+	    if ((in[1] == 0x6F) && (in[2] == 0xA7) && (in[3] == 0x94)) {
+	        enc = XML_CHAR_ENCODING_EBCDIC;
+                autoFlag = XML_INPUT_AUTO_OTHER;
+            }
+            break;
+
+        case 0xEF:
+            if ((in[1] == 0xBB) && (in[2] == 0xBF)) {
+                enc = XML_CHAR_ENCODING_UTF8;
+                autoFlag = XML_INPUT_AUTO_UTF8;
+                bomSize = 3;
+            }
+            break;
+
+        case 0xFE:
+            if (in[1] == 0xFF) {
+                enc = XML_CHAR_ENCODING_UTF16BE;
+                autoFlag = XML_INPUT_AUTO_UTF16BE;
+                bomSize = 2;
+            }
+            break;
+
+        case 0xFF:
+            if (in[1] == 0xFE) {
+                enc = XML_CHAR_ENCODING_UTF16LE;
+                autoFlag = XML_INPUT_AUTO_UTF16LE;
+                bomSize = 2;
+            }
+            break;
+    }
+
+    if (bomSize > 0) {
+        ctxt->input->cur += bomSize;
+    }
+
+    if (enc != XML_CHAR_ENCODING_NONE) {
+        ctxt->input->flags |= autoFlag;
+        xmlSwitchEncoding(ctxt, enc);
+    }
+}
+
+/**
+ * xmlSetDeclaredEncoding:
+ * @ctxt:  the parser context
+ * @encoding:  declared encoding
+ *
+ * Set the encoding from a declaration in the document.
+ *
+ * If no encoding was set yet, switch the encoding. Otherwise, only warn
+ * about encoding mismatches.
+ *
+ * Takes ownership of 'encoding'.
+ */
+void
+xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding) {
+    if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) &&
+        ((ctxt->options & XML_PARSE_IGNORE_ENC) == 0)) {
+        xmlCharEncodingHandlerPtr handler;
+        int res;
+
+        /*
+         * xmlSwitchInputEncodingName treats unsupported encodings as
+         * warnings, but we want it to be an error in an encoding
+         * declaration.
+         */
+        res = xmlOpenCharEncodingHandler((const char *) encoding,
+                /* output */ 0, &handler);
+        if (res != XML_ERR_OK) {
+            xmlFatalErr(ctxt, res, (const char *) encoding);
+            xmlFree(encoding);
+            return;
+        }
+
+        res  = xmlSwitchInputEncoding(ctxt, ctxt->input, handler);
+        if (res != XML_ERR_OK) {
+            xmlFree(encoding);
+            return;
+        }
+
+        ctxt->input->flags |= XML_INPUT_USES_ENC_DECL;
+    } else if (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) {
+        static const char *allowedUTF8[] = {
+            "UTF-8", "UTF8", NULL
+        };
+        static const char *allowedUTF16LE[] = {
+            "UTF-16", "UTF-16LE", "UTF16", NULL
+        };
+        static const char *allowedUTF16BE[] = {
+            "UTF-16", "UTF-16BE", "UTF16", NULL
+        };
+        const char **allowed = NULL;
+        const char *autoEnc = NULL;
+
+        switch (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) {
+            case XML_INPUT_AUTO_UTF8:
+                allowed = allowedUTF8;
+                autoEnc = "UTF-8";
+                break;
+            case XML_INPUT_AUTO_UTF16LE:
+                allowed = allowedUTF16LE;
+                autoEnc = "UTF-16LE";
+                break;
+            case XML_INPUT_AUTO_UTF16BE:
+                allowed = allowedUTF16BE;
+                autoEnc = "UTF-16BE";
+                break;
+        }
+
+        if (allowed != NULL) {
+            const char **p;
+            int match = 0;
+
+            for (p = allowed; *p != NULL; p++) {
+                if (xmlStrcasecmp(encoding, BAD_CAST *p) == 0) {
+                    match = 1;
+                    break;
+                }
+            }
+
+            if (match == 0) {
+                xmlWarningMsg(ctxt, XML_WAR_ENCODING_MISMATCH,
+                              "Encoding '%s' doesn't match "
+                              "auto-detected '%s'\n",
+                              encoding, BAD_CAST autoEnc);
+                xmlFree(encoding);
+                encoding = xmlStrdup(BAD_CAST autoEnc);
+                if (encoding == NULL)
+                    xmlCtxtErrMemory(ctxt);
+            }
+        }
+    }
+
+    if (ctxt->encoding != NULL)
+        xmlFree((xmlChar *) ctxt->encoding);
+    ctxt->encoding = encoding;
+}
+
+/**
+ * xmlGetActualEncoding:
+ * @ctxt:  the parser context
+ *
+ * Returns the actual used to parse the document. This can differ from
+ * the declared encoding.
+ */
+const xmlChar *
+xmlGetActualEncoding(xmlParserCtxtPtr ctxt) {
+    const xmlChar *encoding = NULL;
+
+    if ((ctxt->input->flags & XML_INPUT_USES_ENC_DECL) ||
+        (ctxt->input->flags & XML_INPUT_AUTO_ENCODING)) {
+        /* Preserve encoding exactly */
+        encoding = ctxt->encoding;
+    } else if ((ctxt->input->buf) && (ctxt->input->buf->encoder)) {
+        encoding = BAD_CAST ctxt->input->buf->encoder->name;
+    } else if (ctxt->input->flags & XML_INPUT_HAS_ENCODING) {
+        encoding = BAD_CAST "UTF-8";
+    }
+
+    return(encoding);
 }
 
 /************************************************************************
@@ -1193,8 +1502,6 @@ xmlFreeInputStream(xmlParserInputPtr input) {
     if (input == NULL) return;
 
     if (input->filename != NULL) xmlFree((char *) input->filename);
-    if (input->directory != NULL) xmlFree((char *) input->directory);
-    if (input->encoding != NULL) xmlFree((char *) input->encoding);
     if (input->version != NULL) xmlFree((char *) input->version);
     if ((input->free != NULL) && (input->base != NULL))
         input->free((xmlChar *) input->base);
@@ -1217,21 +1524,304 @@ xmlNewInputStream(xmlParserCtxtPtr ctxt) {
 
     input = (xmlParserInputPtr) xmlMalloc(sizeof(xmlParserInput));
     if (input == NULL) {
-        xmlErrMemory(ctxt,  "couldn't allocate a new input stream\n");
+        xmlCtxtErrMemory(ctxt);
+	return(NULL);
+    }
+    memset(input, 0, sizeof(xmlParserInput));
+    input->line = 1;
+    input->col = 1;
+
+    /*
+     * If the context is NULL the id cannot be initialized, but that
+     * should not happen while parsing which is the situation where
+     * the id is actually needed.
+     */
+    if (ctxt != NULL) {
+        if (input->id >= INT_MAX) {
+            xmlCtxtErrMemory(ctxt);
+            return(NULL);
+        }
+        input->id = ctxt->input_id++;
+    }
+
+    return(input);
+}
+
+/**
+ * xmlNewInputURL:
+ * @ctxt:  parser context
+ * @url:  filename or URL
+ * @publicId:  publid ID from doctype (optional)
+ * @encoding:  character encoding (optional)
+ * @flags:  unused, pass 0
+ *
+ * Creates a new parser input from the filesystem, the network or
+ * a user-defined resource loader.
+ *
+ * Returns a new parser input.
+ */
+xmlParserInputPtr
+xmlNewInputURL(xmlParserCtxtPtr ctxt, const char *url, const char *publicId,
+               const char *encoding, int flags ATTRIBUTE_UNUSED) {
+    xmlParserInputPtr input;
+
+    if ((ctxt == NULL) || (url == NULL))
+	return(NULL);
+
+    input = xmlLoadExternalEntity(url, publicId, ctxt);
+    if (input == NULL)
+        return(NULL);
+
+    if (encoding != NULL)
+        xmlSwitchInputEncodingName(ctxt, input, encoding);
+
+    return(input);
+}
+
+/**
+ * xmlNewInputInternal:
+ * @ctxt:  parser context
+ * @buf:  parser input buffer
+ * @filename:  filename or URL
+ * @encoding:  character encoding (optional)
+ *
+ * Internal helper function.
+ *
+ * Returns a new parser input.
+ */
+static xmlParserInputPtr
+xmlNewInputInternal(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr buf,
+                    const char *filename, const char *encoding) {
+    xmlParserInputPtr input;
+
+    input = xmlNewInputStream(ctxt);
+    if (input == NULL) {
+	xmlFreeParserInputBuffer(buf);
+	return(NULL);
+    }
+
+    input->buf = buf;
+    xmlBufResetInput(input->buf->buffer, input);
+
+    if (filename != NULL) {
+        input->filename = xmlMemStrdup(filename);
+        if (input->filename == NULL) {
+            xmlCtxtErrMemory(ctxt);
+            xmlFreeInputStream(input);
+            return(NULL);
+        }
+    }
+
+    if (encoding != NULL)
+        xmlSwitchInputEncodingName(ctxt, input, encoding);
+
+    return(input);
+}
+
+/**
+ * xmlNewInputMemory:
+ * @ctxt:  parser context
+ * @url:  base URL (optional)
+ * @mem:  pointer to char array
+ * @size:  size of array
+ * @encoding:  character encoding (optional)
+ * @flags:  optimization hints
+ *
+ * Creates a new parser input to read from a memory area.
+ *
+ * @url is used as base to resolve external entities and for
+ * error reporting.
+ *
+ * If the XML_INPUT_BUF_STATIC flag is set, the memory area must
+ * stay unchanged until parsing has finished. This can avoid
+ * temporary copies.
+ *
+ * If the XML_INPUT_BUF_ZERO_TERMINATED flag is set, the memory
+ * area must contain a zero byte after the buffer at position @size.
+ * This can avoid temporary copies.
+ *
+ * Returns a new parser input.
+ */
+xmlParserInputPtr
+xmlNewInputMemory(xmlParserCtxtPtr ctxt, const char *url,
+                  const void *mem, size_t size,
+                  const char *encoding, int flags) {
+    xmlParserInputBufferPtr buf;
+
+    if ((ctxt == NULL) || (mem == NULL))
+	return(NULL);
+
+    buf = xmlNewInputBufferMemory(mem, size, flags, XML_CHAR_ENCODING_NONE);
+    if (buf == NULL) {
+	xmlCtxtErrMemory(ctxt);
+        return(NULL);
+    }
+
+    return(xmlNewInputInternal(ctxt, buf, url, encoding));
+}
+
+/**
+ * xmlNewInputString:
+ * @ctxt:  parser context
+ * @url:  base URL (optional)
+ * @str:  zero-terminated string
+ * @encoding:  character encoding (optional)
+ * @flags:  optimization hints
+ *
+ * Creates a new parser input to read from a zero-terminated string.
+ *
+ * @url is used as base to resolve external entities and for
+ * error reporting.
+ *
+ * If the XML_INPUT_BUF_STATIC flag is set, the string must
+ * stay unchanged until parsing has finished. This can avoid
+ * temporary copies.
+ *
+ * Returns a new parser input.
+ */
+xmlParserInputPtr
+xmlNewInputString(xmlParserCtxtPtr ctxt, const char *url,
+                  const char *str, const char *encoding, int flags) {
+    xmlParserInputBufferPtr buf;
+
+    if ((ctxt == NULL) || (str == NULL))
+	return(NULL);
+
+    buf = xmlNewInputBufferString(str, flags);
+    if (buf == NULL) {
+	xmlCtxtErrMemory(ctxt);
+        return(NULL);
+    }
+
+    return(xmlNewInputInternal(ctxt, buf, url, encoding));
+}
+
+/**
+ * xmlNewInputFd:
+ * @ctxt:  parser context
+ * @url:  base URL (optional)
+ * @fd:  file descriptor
+ * @encoding:  character encoding (optional)
+ * @flags:  unused, pass 0
+ *
+ * Creates a new parser input to read from a zero-terminated string.
+ *
+ * @url is used as base to resolve external entities and for
+ * error reporting.
+ *
+ * @fd is closed after parsing has finished.
+ *
+ * Returns a new parser input.
+ */
+xmlParserInputPtr
+xmlNewInputFd(xmlParserCtxtPtr ctxt, const char *url,
+              int fd, const char *encoding, int flags ATTRIBUTE_UNUSED) {
+    xmlParserInputBufferPtr buf;
+
+    if ((ctxt == NULL) || (fd < 0))
+	return(NULL);
+
+    buf = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
+    if (buf == NULL) {
+	xmlCtxtErrMemory(ctxt);
+        return(NULL);
+    }
+
+    return(xmlNewInputInternal(ctxt, buf, url, encoding));
+}
+
+/**
+ * xmlNewInputIO:
+ * @ctxt:  parser context
+ * @url:  base URL (optional)
+ * @ioRead:  read callback
+ * @ioClose:  close callback (optional)
+ * @ioCtxt:  IO context
+ * @encoding:  character encoding (optional)
+ * @flags:  unused, pass 0
+ *
+ * Creates a new parser input to read from input callbacks and
+ * cintext.
+ *
+ * @url is used as base to resolve external entities and for
+ * error reporting.
+ *
+ * @ioRead is called to read new data into a provided buffer.
+ * It must return the number of bytes written into the buffer
+ * ot a negative xmlParserErrors code on failure.
+ *
+ * @ioClose is called after parsing has finished.
+ *
+ * @ioCtxt is an opaque pointer passed to the callbacks.
+ *
+ * Returns a new parser input.
+ */
+xmlParserInputPtr
+xmlNewInputIO(xmlParserCtxtPtr ctxt, const char *url,
+              xmlInputReadCallback ioRead, xmlInputCloseCallback ioClose,
+              void *ioCtxt,
+              const char *encoding, int flags ATTRIBUTE_UNUSED) {
+    xmlParserInputBufferPtr buf;
+
+    if ((ctxt == NULL) || (ioRead == NULL))
 	return(NULL);
+
+    buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
+    if (buf == NULL) {
+        xmlCtxtErrMemory(ctxt);
+        if (ioClose != NULL)
+            ioClose(ioCtxt);
+        return(NULL);
+    }
+
+    buf->context = ioCtxt;
+    buf->readcallback = ioRead;
+    buf->closecallback = ioClose;
+
+    return(xmlNewInputInternal(ctxt, buf, url, encoding));
+}
+
+/**
+ * xmlNewInputPush:
+ * @ctxt:  parser context
+ * @url:  base URL (optional)
+ * @chunk:  pointer to char array
+ * @size:  size of array
+ * @encoding:  character encoding (optional)
+ *
+ * Creates a new parser input for a push parser.
+ *
+ * Returns a new parser input.
+ */
+xmlParserInputPtr
+xmlNewInputPush(xmlParserCtxtPtr ctxt, const char *url,
+                const char *chunk, int size, const char *encoding) {
+    xmlParserInputBufferPtr buf;
+    xmlParserInputPtr input;
+
+    buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
+    if (buf == NULL) {
+        xmlCtxtErrMemory(ctxt);
+        return(NULL);
     }
-    memset(input, 0, sizeof(xmlParserInput));
-    input->line = 1;
-    input->col = 1;
-    input->standalone = -1;
 
-    /*
-     * If the context is NULL the id cannot be initialized, but that
-     * should not happen while parsing which is the situation where
-     * the id is actually needed.
-     */
-    if (ctxt != NULL)
-        input->id = ctxt->input_id++;
+    input = xmlNewInputInternal(ctxt, buf, url, encoding);
+    if (input == NULL)
+	return(NULL);
+
+    input->flags |= XML_INPUT_PROGRESSIVE;
+
+    if ((size > 0) && (chunk != NULL)) {
+        int res;
+
+	res = xmlParserInputBufferPush(input->buf, size, chunk);
+        xmlBufResetInput(input->buf->buffer, input);
+        if (res < 0) {
+            xmlCtxtErrIO(ctxt, input->buf->error, NULL);
+            xmlFreeInputStream(input);
+            return(NULL);
+        }
+    }
 
     return(input);
 }
@@ -1239,7 +1829,7 @@ xmlNewInputStream(xmlParserCtxtPtr ctxt) {
 /**
  * xmlNewIOInputStream:
  * @ctxt:  an XML parser context
- * @input:  an I/O Input
+ * @buf:  an input buffer
  * @enc:  the charset encoding if known
  *
  * Create a new input stream structure encapsulating the @input into
@@ -1248,89 +1838,50 @@ xmlNewInputStream(xmlParserCtxtPtr ctxt) {
  * Returns the new input stream or NULL
  */
 xmlParserInputPtr
-xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr input,
+xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr buf,
 	            xmlCharEncoding enc) {
-    xmlParserInputPtr inputStream;
-
-    if (input == NULL) return(NULL);
-    if (xmlParserDebugEntities)
-	xmlGenericError(xmlGenericErrorContext, "new input from I/O\n");
-    inputStream = xmlNewInputStream(ctxt);
-    if (inputStream == NULL) {
-	return(NULL);
-    }
-    inputStream->filename = NULL;
-    inputStream->buf = input;
-    xmlBufResetInput(inputStream->buf->buffer, inputStream);
+    const char *encoding;
 
-    if (enc != XML_CHAR_ENCODING_NONE) {
-        xmlSwitchEncoding(ctxt, enc);
-    }
+    if (buf == NULL)
+        return(NULL);
 
-    return(inputStream);
+    encoding = xmlGetCharEncodingName(enc);
+    return(xmlNewInputInternal(ctxt, buf, NULL, encoding));
 }
 
 /**
  * xmlNewEntityInputStream:
  * @ctxt:  an XML parser context
- * @entity:  an Entity pointer
+ * @ent:  an Entity pointer
+ *
+ * DEPRECATED: Internal function, do not use.
  *
  * Create a new input stream based on an xmlEntityPtr
  *
  * Returns the new input stream or NULL
  */
 xmlParserInputPtr
-xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
+xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr ent) {
     xmlParserInputPtr input;
 
-    if (entity == NULL) {
-        xmlErrInternal(ctxt, "xmlNewEntityInputStream entity = NULL\n",
-	               NULL);
-	return(NULL);
-    }
-    if (xmlParserDebugEntities)
-	xmlGenericError(xmlGenericErrorContext,
-		"new input from entity: %s\n", entity->name);
-    if (entity->content == NULL) {
-	switch (entity->etype) {
-            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
-	        xmlErrInternal(ctxt, "Cannot parse entity %s\n",
-		               entity->name);
-                break;
-            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
-            case XML_EXTERNAL_PARAMETER_ENTITY:
-		return(xmlLoadExternalEntity((char *) entity->URI,
-		       (char *) entity->ExternalID, ctxt));
-            case XML_INTERNAL_GENERAL_ENTITY:
-	        xmlErrInternal(ctxt,
-		      "Internal entity %s without content !\n",
-		               entity->name);
-                break;
-            case XML_INTERNAL_PARAMETER_ENTITY:
-	        xmlErrInternal(ctxt,
-		      "Internal parameter entity %s without content !\n",
-		               entity->name);
-                break;
-            case XML_INTERNAL_PREDEFINED_ENTITY:
-	        xmlErrInternal(ctxt,
-		      "Predefined entity %s without content !\n",
-		               entity->name);
-                break;
-	}
-	return(NULL);
-    }
-    input = xmlNewInputStream(ctxt);
-    if (input == NULL) {
+    if ((ctxt == NULL) || (ent == NULL))
 	return(NULL);
+
+    if (ent->content != NULL) {
+        input = xmlNewInputString(ctxt, NULL, (const char *) ent->content,
+                                  NULL, XML_INPUT_BUF_STATIC);
+    } else if (ent->URI != NULL) {
+        input = xmlLoadExternalEntity((char *) ent->URI,
+                                      (char *) ent->ExternalID, ctxt);
+    } else {
+        return(NULL);
     }
-    if (entity->URI != NULL)
-	input->filename = (char *) xmlStrdup((xmlChar *) entity->URI);
-    input->base = entity->content;
-    if (entity->length == 0)
-        entity->length = xmlStrlen(entity->content);
-    input->cur = entity->content;
-    input->length = entity->length;
-    input->end = &entity->content[input->length];
+
+    if (input == NULL)
+        return(NULL);
+
+    input->entity = ent;
+
     return(input);
 }
 
@@ -1340,30 +1891,159 @@ xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
  * @buffer:  an memory buffer
  *
  * Create a new input stream based on a memory buffer.
+ *
  * Returns the new input stream
  */
 xmlParserInputPtr
 xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) {
-    xmlParserInputPtr input;
+    return(xmlNewInputString(ctxt, NULL, (const char *) buffer, NULL, 0));
+}
 
-    if (buffer == NULL) {
-        xmlErrInternal(ctxt, "xmlNewStringInputStream string = NULL\n",
-	               NULL);
-	return(NULL);
+
+/****************************************************************
+ *								*
+ *		External entities loading			*
+ *								*
+ ****************************************************************/
+
+#ifdef LIBXML_CATALOG_ENABLED
+
+/**
+ * xmlResolveResourceFromCatalog:
+ * @URL:  the URL for the entity to load
+ * @ID:  the System ID for the entity to load
+ * @ctxt:  the context in which the entity is called or NULL
+ *
+ * Resolves the URL and ID against the appropriate catalog.
+ * This function is used by xmlDefaultExternalEntityLoader and
+ * xmlNoNetExternalEntityLoader.
+ *
+ * Returns a new allocated URL, or NULL.
+ */
+static xmlChar *
+xmlResolveResourceFromCatalog(const char *URL, const char *ID,
+                              xmlParserCtxtPtr ctxt) {
+    xmlChar *resource = NULL;
+    xmlCatalogAllow pref;
+
+    /*
+     * If the resource doesn't exists as a file,
+     * try to load it from the resource pointed in the catalogs
+     */
+    pref = xmlCatalogGetDefaults();
+
+    if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) {
+	/*
+	 * Do a local lookup
+	 */
+	if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
+	    ((pref == XML_CATA_ALLOW_ALL) ||
+	     (pref == XML_CATA_ALLOW_DOCUMENT))) {
+	    resource = xmlCatalogLocalResolve(ctxt->catalogs,
+					      (const xmlChar *)ID,
+					      (const xmlChar *)URL);
+        }
+	/*
+	 * Try a global lookup
+	 */
+	if ((resource == NULL) &&
+	    ((pref == XML_CATA_ALLOW_ALL) ||
+	     (pref == XML_CATA_ALLOW_GLOBAL))) {
+	    resource = xmlCatalogResolve((const xmlChar *)ID,
+					 (const xmlChar *)URL);
+	}
+	if ((resource == NULL) && (URL != NULL))
+	    resource = xmlStrdup((const xmlChar *) URL);
+
+	/*
+	 * TODO: do an URI lookup on the reference
+	 */
+	if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) {
+	    xmlChar *tmp = NULL;
+
+	    if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
+		((pref == XML_CATA_ALLOW_ALL) ||
+		 (pref == XML_CATA_ALLOW_DOCUMENT))) {
+		tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
+	    }
+	    if ((tmp == NULL) &&
+		((pref == XML_CATA_ALLOW_ALL) ||
+	         (pref == XML_CATA_ALLOW_GLOBAL))) {
+		tmp = xmlCatalogResolveURI(resource);
+	    }
+
+	    if (tmp != NULL) {
+		xmlFree(resource);
+		resource = tmp;
+	    }
+	}
     }
-    if (xmlParserDebugEntities)
-	xmlGenericError(xmlGenericErrorContext,
-		"new fixed input: %.30s\n", buffer);
-    input = xmlNewInputStream(ctxt);
-    if (input == NULL) {
-        xmlErrMemory(ctxt,  "couldn't allocate a new input stream\n");
-	return(NULL);
+
+    return resource;
+}
+
+#endif
+
+/**
+ * xmlCheckHTTPInput:
+ * @ctxt: an XML parser context
+ * @ret: an XML parser input
+ *
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Check an input in case it was created from an HTTP stream, in that
+ * case it will handle encoding and update of the base URL in case of
+ * redirection. It also checks for HTTP errors in which case the input
+ * is cleanly freed up and an appropriate error is raised in context
+ *
+ * Returns the input or NULL in case of HTTP error.
+ */
+xmlParserInputPtr
+xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
+    /* Avoid unused variable warning if features are disabled. */
+    (void) ctxt;
+
+#ifdef LIBXML_HTTP_ENABLED
+    if ((ret != NULL) && (ret->buf != NULL) &&
+        (ret->buf->readcallback == xmlIOHTTPRead) &&
+        (ret->buf->context != NULL)) {
+        const char *encoding;
+        const char *redir;
+        const char *mime;
+        int code;
+
+        code = xmlNanoHTTPReturnCode(ret->buf->context);
+        if (code >= 400) {
+            /* fatal error */
+	    if (ret->filename != NULL)
+                xmlCtxtErrIO(ctxt, XML_IO_LOAD_ERROR, ret->filename);
+	    else
+                xmlCtxtErrIO(ctxt, XML_IO_LOAD_ERROR, "<null>");
+            xmlFreeInputStream(ret);
+            ret = NULL;
+        } else {
+
+            mime = xmlNanoHTTPMimeType(ret->buf->context);
+            if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
+                (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
+                encoding = xmlNanoHTTPEncoding(ret->buf->context);
+                if (encoding != NULL)
+                    xmlSwitchEncodingName(ctxt, encoding);
+#if 0
+            } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
+#endif
+            }
+            redir = xmlNanoHTTPRedir(ret->buf->context);
+            if (redir != NULL) {
+                if (ret->filename != NULL)
+                    xmlFree((xmlChar *) ret->filename);
+                ret->filename =
+                    (char *) xmlStrdup((const xmlChar *) redir);
+            }
+        }
     }
-    input->base = buffer;
-    input->cur = buffer;
-    input->length = xmlStrlen(buffer);
-    input->end = &buffer[input->length];
-    return(input);
+#endif
+    return(ret);
 }
 
 /**
@@ -1379,22 +2059,17 @@ xmlParserInputPtr
 xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
     xmlParserInputBufferPtr buf;
     xmlParserInputPtr inputStream;
-    char *directory = NULL;
-    xmlChar *URI = NULL;
-
-    if (xmlParserDebugEntities)
-	xmlGenericError(xmlGenericErrorContext,
-		"new input from file: %s\n", filename);
-    if (ctxt == NULL) return(NULL);
-    buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
+    const xmlChar *URI;
+    xmlChar *canonic;
+    int code;
+
+    if ((ctxt == NULL) || (filename == NULL))
+        return(NULL);
+
+    code = xmlParserInputBufferCreateFilenameSafe(filename,
+                                                  XML_CHAR_ENCODING_NONE, &buf);
     if (buf == NULL) {
-	if (filename == NULL)
-	    __xmlLoaderErr(ctxt,
-	                   "failed to load external entity: NULL filename \n",
-			   NULL);
-	else
-	    __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n",
-			   (const char *) filename);
+        xmlCtxtErrIO(ctxt, code, filename);
 	return(NULL);
     }
 
@@ -1410,21 +2085,189 @@ xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
         return(NULL);
 
     if (inputStream->filename == NULL)
-	URI = xmlStrdup((xmlChar *) filename);
+	URI = (xmlChar *) filename;
     else
-	URI = xmlStrdup((xmlChar *) inputStream->filename);
-    directory = xmlParserGetDirectory((const char *) URI);
-    if (inputStream->filename != NULL) xmlFree((char *)inputStream->filename);
-    inputStream->filename = (char *) xmlCanonicPath((const xmlChar *) URI);
-    if (URI != NULL) xmlFree((char *) URI);
-    inputStream->directory = directory;
+	URI = (xmlChar *) inputStream->filename;
+    canonic = xmlCanonicPath(URI);
+    if (canonic == NULL) {
+        xmlCtxtErrMemory(ctxt);
+        xmlFreeInputStream(inputStream);
+        return(NULL);
+    }
+    if (inputStream->filename != NULL)
+        xmlFree((char *) inputStream->filename);
+    inputStream->filename = (char *) canonic;
 
     xmlBufResetInput(inputStream->buf->buffer, inputStream);
-    if ((ctxt->directory == NULL) && (directory != NULL))
-        ctxt->directory = (char *) xmlStrdup((const xmlChar *) directory);
+
     return(inputStream);
 }
 
+/**
+ * xmlDefaultExternalEntityLoader:
+ * @URL:  the URL for the entity to load
+ * @ID:  the System ID for the entity to load
+ * @ctxt:  the context in which the entity is called or NULL
+ *
+ * By default we don't load external entities, yet.
+ *
+ * Returns a new allocated xmlParserInputPtr, or NULL.
+ */
+static xmlParserInputPtr
+xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
+                               xmlParserCtxtPtr ctxt)
+{
+    xmlParserInputPtr ret = NULL;
+    xmlChar *resource = NULL;
+
+    if (URL == NULL)
+        return(NULL);
+
+    if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
+        int options = ctxt->options;
+
+	ctxt->options -= XML_PARSE_NONET;
+        ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+	ctxt->options = options;
+	return(ret);
+    }
+#ifdef LIBXML_CATALOG_ENABLED
+    resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
+#endif
+
+    if (resource == NULL)
+        resource = (xmlChar *) URL;
+
+    ret = xmlNewInputFromFile(ctxt, (const char *) resource);
+    if ((resource != NULL) && (resource != (xmlChar *) URL))
+        xmlFree(resource);
+    return (ret);
+}
+
+/**
+ * xmlNoNetExternalEntityLoader:
+ * @URL:  the URL for the entity to load
+ * @ID:  the System ID for the entity to load
+ * @ctxt:  the context in which the entity is called or NULL
+ *
+ * A specific entity loader disabling network accesses, though still
+ * allowing local catalog accesses for resolution.
+ *
+ * Returns a new allocated xmlParserInputPtr, or NULL.
+ */
+xmlParserInputPtr
+xmlNoNetExternalEntityLoader(const char *URL, const char *ID,
+                             xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr input = NULL;
+    xmlChar *resource = NULL;
+
+#ifdef LIBXML_CATALOG_ENABLED
+    resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
+#endif
+
+    if (resource == NULL)
+	resource = (xmlChar *) URL;
+
+    if (resource != NULL) {
+        if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
+            (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
+            xmlCtxtErrIO(ctxt, XML_IO_NETWORK_ATTEMPT,
+                         (const char *) resource);
+            /*
+             * Also forward the error directly to the global error
+             * handler, which the XML::LibXML test suite expects.
+             */
+            __xmlIOErr(XML_FROM_IO, XML_IO_NETWORK_ATTEMPT,
+                       (const char *) resource);
+	    if (resource != (xmlChar *) URL)
+		xmlFree(resource);
+	    return(NULL);
+	}
+    }
+    input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt);
+    if (resource != (xmlChar *) URL)
+	xmlFree(resource);
+    return(input);
+}
+
+/*
+ * This global has to die eventually
+ */
+static xmlExternalEntityLoader
+xmlCurrentExternalEntityLoader = xmlDefaultExternalEntityLoader;
+
+/**
+ * xmlSetExternalEntityLoader:
+ * @f:  the new entity resolver function
+ *
+ * Changes the defaultexternal entity resolver function for the application
+ */
+void
+xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
+    xmlCurrentExternalEntityLoader = f;
+}
+
+/**
+ * xmlGetExternalEntityLoader:
+ *
+ * Get the default external entity resolver function for the application
+ *
+ * Returns the xmlExternalEntityLoader function pointer
+ */
+xmlExternalEntityLoader
+xmlGetExternalEntityLoader(void) {
+    return(xmlCurrentExternalEntityLoader);
+}
+
+/**
+ * xmlLoadExternalEntity:
+ * @URL:  the URL for the entity to load
+ * @ID:  the Public ID for the entity to load
+ * @ctxt:  the context in which the entity is called or NULL
+ *
+ * @URL is a filename or URL. If if contains the substring "://",
+ * it is assumed to be a Legacy Extended IRI. Otherwise, it is
+ * treated as a filesystem path.
+ *
+ * @ID is an optional XML public ID, typically from a doctype
+ * declaration. It is used for catalog lookups.
+ *
+ * The following resource loaders will be called if they were
+ * registered (in order of precedence):
+ *
+ * - the global external entity loader set with
+ *   xmlSetExternalEntityLoader
+ * - the per-thread xmlParserInputBufferCreateFilenameFunc set with
+ *   xmlParserInputBufferCreateFilenameDefault
+ * - the default loader which will return
+ *   - the result from a matching global input callback set with
+ *     xmlRegisterInputCallbacks
+ *   - a HTTP resource if support is compiled in.
+ *   - a file opened from the filesystem, with automatic detection
+ *     of compressed files if support is compiled in.
+ *
+ * Returns the xmlParserInputPtr or NULL
+ */
+xmlParserInputPtr
+xmlLoadExternalEntity(const char *URL, const char *ID,
+                      xmlParserCtxtPtr ctxt) {
+    char *canonicFilename;
+    xmlParserInputPtr ret;
+
+    if (URL == NULL)
+        return(NULL);
+
+    canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
+    if (canonicFilename == NULL) {
+        xmlCtxtErrMemory(ctxt);
+        return(NULL);
+    }
+
+    ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
+    xmlFree(canonicFilename);
+    return(ret);
+}
+
 /************************************************************************
  *									*
  *		Commodity functions to handle parser contexts		*
@@ -1432,42 +2275,48 @@ xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
  ************************************************************************/
 
 /**
- * xmlInitParserCtxt:
- * @ctxt:  an XML parser context
+ * xmlInitSAXParserCtxt:
+ * @ctxt:  XML parser context
+ * @sax:  SAX handlert
+ * @userData:  user data
  *
- * Initialize a parser context
+ * Initialize a SAX parser context
  *
  * Returns 0 in case of success and -1 in case of error
  */
 
-int
-xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
+static int
+xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax,
+                     void *userData)
 {
     xmlParserInputPtr input;
 
-    if(ctxt==NULL) {
-        xmlErrInternal(NULL, "Got NULL parser context\n", NULL);
+    if (ctxt == NULL)
         return(-1);
-    }
-
-    xmlInitParser();
 
     if (ctxt->dict == NULL)
 	ctxt->dict = xmlDictCreate();
-    if (ctxt->dict == NULL) {
-        xmlErrMemory(NULL, "cannot initialize parser context\n");
+    if (ctxt->dict == NULL)
 	return(-1);
-    }
     xmlDictSetLimit(ctxt->dict, XML_MAX_DICTIONARY_LIMIT);
 
     if (ctxt->sax == NULL)
 	ctxt->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
-    if (ctxt->sax == NULL) {
-        xmlErrMemory(NULL, "cannot initialize parser context\n");
+    if (ctxt->sax == NULL)
 	return(-1);
-    }
-    else
+    if (sax == NULL) {
+	memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
         xmlSAXVersion(ctxt->sax, 2);
+        ctxt->userData = ctxt;
+    } else {
+	if (sax->initialized == XML_SAX2_MAGIC) {
+	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
+        } else {
+	    memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
+	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
+        }
+        ctxt->userData = userData ? userData : ctxt;
+    }
 
     ctxt->maxatts = 0;
     ctxt->atts = NULL;
@@ -1477,13 +2326,8 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
 		    xmlMalloc(5 * sizeof(xmlParserInputPtr));
 	ctxt->inputMax = 5;
     }
-    if (ctxt->inputTab == NULL) {
-        xmlErrMemory(NULL, "cannot initialize parser context\n");
-	ctxt->inputNr = 0;
-	ctxt->inputMax = 0;
-	ctxt->input = NULL;
+    if (ctxt->inputTab == NULL)
 	return(-1);
-    }
     while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
         xmlFreeInputStream(input);
     }
@@ -1496,26 +2340,15 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
     ctxt->hasExternalSubset = 0;
     ctxt->hasPErefs = 0;
     ctxt->html = 0;
-    ctxt->external = 0;
     ctxt->instate = XML_PARSER_START;
-    ctxt->token = 0;
-    ctxt->directory = NULL;
 
     /* Allocate the Node stack */
     if (ctxt->nodeTab == NULL) {
 	ctxt->nodeTab = (xmlNodePtr *) xmlMalloc(10 * sizeof(xmlNodePtr));
 	ctxt->nodeMax = 10;
     }
-    if (ctxt->nodeTab == NULL) {
-        xmlErrMemory(NULL, "cannot initialize parser context\n");
-	ctxt->nodeNr = 0;
-	ctxt->nodeMax = 0;
-	ctxt->node = NULL;
-	ctxt->inputNr = 0;
-	ctxt->inputMax = 0;
-	ctxt->input = NULL;
+    if (ctxt->nodeTab == NULL)
 	return(-1);
-    }
     ctxt->nodeNr = 0;
     ctxt->node = NULL;
 
@@ -1524,19 +2357,8 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
 	ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *));
 	ctxt->nameMax = 10;
     }
-    if (ctxt->nameTab == NULL) {
-        xmlErrMemory(NULL, "cannot initialize parser context\n");
-	ctxt->nodeNr = 0;
-	ctxt->nodeMax = 0;
-	ctxt->node = NULL;
-	ctxt->inputNr = 0;
-	ctxt->inputMax = 0;
-	ctxt->input = NULL;
-	ctxt->nameNr = 0;
-	ctxt->nameMax = 0;
-	ctxt->name = NULL;
+    if (ctxt->nameTab == NULL)
 	return(-1);
-    }
     ctxt->nameNr = 0;
     ctxt->name = NULL;
 
@@ -1545,36 +2367,33 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
 	ctxt->spaceTab = (int *) xmlMalloc(10 * sizeof(int));
 	ctxt->spaceMax = 10;
     }
-    if (ctxt->spaceTab == NULL) {
-        xmlErrMemory(NULL, "cannot initialize parser context\n");
-	ctxt->nodeNr = 0;
-	ctxt->nodeMax = 0;
-	ctxt->node = NULL;
-	ctxt->inputNr = 0;
-	ctxt->inputMax = 0;
-	ctxt->input = NULL;
-	ctxt->nameNr = 0;
-	ctxt->nameMax = 0;
-	ctxt->name = NULL;
-	ctxt->spaceNr = 0;
-	ctxt->spaceMax = 0;
-	ctxt->space = NULL;
+    if (ctxt->spaceTab == NULL)
 	return(-1);
-    }
     ctxt->spaceNr = 1;
     ctxt->spaceMax = 10;
     ctxt->spaceTab[0] = -1;
     ctxt->space = &ctxt->spaceTab[0];
-    ctxt->userData = ctxt;
     ctxt->myDoc = NULL;
     ctxt->wellFormed = 1;
     ctxt->nsWellFormed = 1;
     ctxt->valid = 1;
+
+    ctxt->options = XML_PARSE_NODICT;
+
+    /*
+     * Initialize some parser options from deprecated global variables.
+     * Note that the "modern" API taking options arguments or
+     * xmlCtxtSetOptions will ignore these defaults. They're only
+     * relevant if old API functions like xmlParseFile are used.
+     */
     ctxt->loadsubset = xmlLoadExtDtdDefaultValue;
     if (ctxt->loadsubset) {
         ctxt->options |= XML_PARSE_DTDLOAD;
     }
     ctxt->validate = xmlDoValidityCheckingDefaultValue;
+    if (ctxt->validate) {
+        ctxt->options |= XML_PARSE_DTDVALID;
+    }
     ctxt->pedantic = xmlPedanticParserDefaultValue;
     if (ctxt->pedantic) {
         ctxt->options |= XML_PARSE_PEDANTIC;
@@ -1585,38 +2404,59 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
 	ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
 	ctxt->options |= XML_PARSE_NOBLANKS;
     }
+    ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue;
+    if (ctxt->replaceEntities) {
+        ctxt->options |= XML_PARSE_NOENT;
+    }
+    if (xmlGetWarningsDefaultValue == 0)
+        ctxt->options |= XML_PARSE_NOWARNING;
 
     ctxt->vctxt.flags = XML_VCTXT_USE_PCTXT;
     ctxt->vctxt.userData = ctxt;
     ctxt->vctxt.error = xmlParserValidityError;
     ctxt->vctxt.warning = xmlParserValidityWarning;
-    if (ctxt->validate) {
-	if (xmlGetWarningsDefaultValue == 0)
-	    ctxt->vctxt.warning = NULL;
-	else
-	    ctxt->vctxt.warning = xmlParserValidityWarning;
-	ctxt->vctxt.nodeMax = 0;
-        ctxt->options |= XML_PARSE_DTDVALID;
-    }
-    ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue;
-    if (ctxt->replaceEntities) {
-        ctxt->options |= XML_PARSE_NOENT;
-    }
+
     ctxt->record_info = 0;
     ctxt->checkIndex = 0;
     ctxt->inSubset = 0;
     ctxt->errNo = XML_ERR_OK;
     ctxt->depth = 0;
-    ctxt->charset = XML_CHAR_ENCODING_UTF8;
     ctxt->catalogs = NULL;
-    ctxt->nbentities = 0;
     ctxt->sizeentities = 0;
     ctxt->sizeentcopy = 0;
     ctxt->input_id = 1;
+    ctxt->maxAmpl = XML_MAX_AMPLIFICATION_DEFAULT;
     xmlInitNodeInfoSeq(&ctxt->node_seq);
+
+    if (ctxt->nsdb == NULL) {
+        ctxt->nsdb = xmlParserNsCreate();
+        if (ctxt->nsdb == NULL) {
+            xmlCtxtErrMemory(ctxt);
+            return(-1);
+        }
+    }
+
     return(0);
 }
 
+/**
+ * xmlInitParserCtxt:
+ * @ctxt:  an XML parser context
+ *
+ * DEPRECATED: Internal function which will be made private in a future
+ * version.
+ *
+ * Initialize a parser context
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+
+int
+xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
+{
+    return(xmlInitSAXParserCtxt(ctxt, NULL, NULL));
+}
+
 /**
  * xmlFreeParserCtxt:
  * @ctxt:  an XML parser context
@@ -1651,11 +2491,13 @@ xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
     if (ctxt->sax != NULL)
 #endif /* LIBXML_SAX1_ENABLED */
         xmlFree(ctxt->sax);
-    if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
+    if (ctxt->directory != NULL) xmlFree(ctxt->directory);
     if (ctxt->vctxt.nodeTab != NULL) xmlFree(ctxt->vctxt.nodeTab);
     if (ctxt->atts != NULL) xmlFree((xmlChar * *)ctxt->atts);
     if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
-    if (ctxt->nsTab != NULL) xmlFree((char *) ctxt->nsTab);
+    if (ctxt->nsTab != NULL) xmlFree(ctxt->nsTab);
+    if (ctxt->nsdb != NULL) xmlParserNsFree(ctxt->nsdb);
+    if (ctxt->attrHash != NULL) xmlFree(ctxt->attrHash);
     if (ctxt->pushTab != NULL) xmlFree(ctxt->pushTab);
     if (ctxt->attallocs != NULL) xmlFree(ctxt->attallocs);
     if (ctxt->attsDefault != NULL)
@@ -1713,16 +2555,37 @@ xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
 
 xmlParserCtxtPtr
 xmlNewParserCtxt(void)
+{
+    return(xmlNewSAXParserCtxt(NULL, NULL));
+}
+
+/**
+ * xmlNewSAXParserCtxt:
+ * @sax:  SAX handler
+ * @userData:  user data
+ *
+ * Allocate and initialize a new SAX parser context. If userData is NULL,
+ * the parser context will be passed as user data.
+ *
+ * Available since 2.11.0. If you want support older versions,
+ * it's best to invoke xmlNewParserCtxt and set ctxt->sax with
+ * struct assignment.
+ *
+ * Returns the xmlParserCtxtPtr or NULL if memory allocation failed.
+ */
+
+xmlParserCtxtPtr
+xmlNewSAXParserCtxt(const xmlSAXHandler *sax, void *userData)
 {
     xmlParserCtxtPtr ctxt;
 
+    xmlInitParser();
+
     ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
-    if (ctxt == NULL) {
-	xmlErrMemory(NULL, "cannot allocate parser context\n");
+    if (ctxt == NULL)
 	return(NULL);
-    }
     memset(ctxt, 0, sizeof(xmlParserCtxt));
-    if (xmlInitParserCtxt(ctxt) < 0) {
+    if (xmlInitSAXParserCtxt(ctxt, sax, userData) < 0) {
         xmlFreeParserCtxt(ctxt);
 	return(NULL);
     }
@@ -1757,12 +2620,14 @@ xmlClearParserCtxt(xmlParserCtxtPtr ctxt)
  * @ctx:  an XML parser context
  * @node:  an XML node within the tree
  *
+ * DEPRECATED: Don't use.
+ *
  * Find the parser node info struct for a given node
  *
  * Returns an xmlParserNodeInfo block pointer or NULL
  */
 const xmlParserNodeInfo *
-xmlParserFindNodeInfo(const xmlParserCtxtPtr ctx, const xmlNodePtr node)
+xmlParserFindNodeInfo(xmlParserCtxtPtr ctx, xmlNodePtr node)
 {
     unsigned long pos;
 
@@ -1782,6 +2647,8 @@ xmlParserFindNodeInfo(const xmlParserCtxtPtr ctx, const xmlNodePtr node)
  * xmlInitNodeInfoSeq:
  * @seq:  a node info sequence pointer
  *
+ * DEPRECATED: Don't use.
+ *
  * -- Initialize (set to initial state) node info sequence
  */
 void
@@ -1798,6 +2665,8 @@ xmlInitNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
  * xmlClearNodeInfoSeq:
  * @seq:  a node info sequence pointer
  *
+ * DEPRECATED: Don't use.
+ *
  * -- Clear (release memory and reinitialize) node
  *   info sequence
  */
@@ -1816,6 +2685,7 @@ xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
  * @seq:  a node info sequence pointer
  * @node:  an XML node pointer
  *
+ * DEPRECATED: Don't use.
  *
  * xmlParserFindNodeInfoIndex : Find the index that the info record for
  *   the given node is or should be at in a sorted sequence
@@ -1823,8 +2693,8 @@ xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
  * Returns a long indicating the position of the record
  */
 unsigned long
-xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq,
-                           const xmlNodePtr node)
+xmlParserFindNodeInfoIndex(xmlParserNodeInfoSeqPtr seq,
+                           xmlNodePtr node)
 {
     unsigned long upper, lower, middle;
     int found = 0;
@@ -1859,11 +2729,13 @@ xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq,
  * @ctxt:  an XML parser context
  * @info:  a node info sequence pointer
  *
+ * DEPRECATED: Don't use.
+ *
  * Insert node info record into the sorted sequence
  */
 void
 xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt,
-                     const xmlParserNodeInfoPtr info)
+                     xmlParserNodeInfoPtr info)
 {
     unsigned long pos;
 
@@ -1899,7 +2771,7 @@ xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt,
                                                      byte_size);
 
             if (tmp_buffer == NULL) {
-		xmlErrMemory(ctxt, "failed to allocate buffer\n");
+		xmlCtxtErrMemory(ctxt);
                 return;
             }
             ctxt->node_seq.buffer = tmp_buffer;
@@ -1929,6 +2801,8 @@ xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt,
  * xmlPedanticParserDefault:
  * @val:  int 0 or 1
  *
+ * DEPRECATED: Use the modern options API with XML_PARSE_PEDANTIC.
+ *
  * Set and return the previous value for enabling pedantic warnings.
  *
  * Returns the last value for 0 for no substitution, 1 for substitution.
@@ -1946,6 +2820,8 @@ xmlPedanticParserDefault(int val) {
  * xmlLineNumbersDefault:
  * @val:  int 0 or 1
  *
+ * DEPRECATED: The modern options API always enables line numbers.
+ *
  * Set and return the previous value for enabling line numbers in elements
  * contents. This may break on old application and is turned off by default.
  *
@@ -1964,6 +2840,8 @@ xmlLineNumbersDefault(int val) {
  * xmlSubstituteEntitiesDefault:
  * @val:  int 0 or 1
  *
+ * DEPRECATED: Use the modern options API with XML_PARSE_NOENT.
+ *
  * Set and return the previous value for default entity support.
  * Initially the parser always keep entity references instead of substituting
  * entity values in the output. This function has to be used to change the
@@ -1986,6 +2864,8 @@ xmlSubstituteEntitiesDefault(int val) {
  * xmlKeepBlanksDefault:
  * @val:  int 0 or 1
  *
+ * DEPRECATED: Use the modern options API with XML_PARSE_NOBLANKS.
+ *
  * Set and return the previous value for default blanks text nodes support.
  * The 1.x version of the parser used an heuristic to try to detect
  * ignorable white spaces. As a result the SAX callback was generating
@@ -2011,7 +2891,10 @@ xmlKeepBlanksDefault(int val) {
     int old = xmlKeepBlanksDefaultValue;
 
     xmlKeepBlanksDefaultValue = val;
-    if (!val) xmlIndentTreeOutput = 1;
+#ifdef LIBXML_OUTPUT_ENABLED
+    if (!val)
+        xmlIndentTreeOutput = 1;
+#endif
     return(old);
 }
 
diff --git a/pattern.c b/pattern.c
index cff4469c61daa62a9ae513b236a147aaa8c402c3..23b52744ac5a99334454521180d7aba3450056de 100644
--- a/pattern.c
+++ b/pattern.c
@@ -27,18 +27,15 @@
 #include "libxml.h"
 
 #include <string.h>
+#include <libxml/pattern.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
-#include <libxml/hash.h>
 #include <libxml/dict.h>
 #include <libxml/xmlerror.h>
 #include <libxml/parserInternals.h>
-#include <libxml/pattern.h>
 
 #ifdef LIBXML_PATTERN_ENABLED
 
-/* #define DEBUG_STREAMING */
-
 #ifdef ERROR
 #undef ERROR
 #endif
@@ -347,9 +344,8 @@ xmlFreePatParserContext(xmlPatParserContextPtr ctxt) {
  * Returns -1 in case of failure, 0 otherwise.
  */
 static int
-xmlPatternAdd(xmlPatParserContextPtr ctxt ATTRIBUTE_UNUSED,
-                xmlPatternPtr comp,
-                xmlPatOp op, xmlChar * value, xmlChar * value2)
+xmlPatternAdd(xmlPatParserContextPtr ctxt, xmlPatternPtr comp,
+              xmlPatOp op, xmlChar * value, xmlChar * value2)
 {
     if (comp->nbStep >= comp->maxStep) {
         xmlStepOpPtr temp;
@@ -358,6 +354,7 @@ xmlPatternAdd(xmlPatParserContextPtr ctxt ATTRIBUTE_UNUSED,
         if (temp == NULL) {
 	    ERROR(ctxt, NULL, NULL,
 			     "xmlPatternAdd: realloc failed\n");
+            ctxt->error = -1;
 	    return (-1);
 	}
 	comp->steps = temp;
@@ -700,10 +697,6 @@ rollback:
  *									*
  ************************************************************************/
 
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
 #define CUR (*ctxt->cur)
 #define SKIP(val) ctxt->cur += (val)
 #define NXT(val) ctxt->cur[(val)]
@@ -720,14 +713,6 @@ rollback:
 #define PUSH(op, val, val2)						\
     if (xmlPatternAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error;
 
-#define XSLT_ERROR(X)							\
-    { xsltError(ctxt, __FILE__, __LINE__, X);				\
-      ctxt->error = (X); return; }
-
-#define XSLT_ERROR0(X)							\
-    { xsltError(ctxt, __FILE__, __LINE__, X);				\
-      ctxt->error = (X); return(0); }
-
 #if 0
 /**
  * xmlPatScanLiteral:
@@ -872,6 +857,8 @@ xmlPatScanNCName(xmlPatParserContextPtr ctxt) {
 	ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
     else
 	ret = xmlStrndup(q, cur - q);
+    if (ret == NULL)
+        ctxt->error = -1;
     CUR_PTR = cur;
     return(ret);
 }
@@ -916,6 +903,8 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
 
     SKIP_BLANKS;
     name = xmlPatScanNCName(ctxt);
+    if (ctxt->error < 0)
+        return;
     if (name == NULL) {
 	if (CUR == '*') {
 	    PUSH(XML_OP_ATTR, NULL, NULL);
@@ -935,7 +924,6 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
 
 	if (IS_BLANK_CH(CUR)) {
 	    ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
-	    XML_PAT_FREE_STRING(ctxt, prefix);
 	    ctxt->error = 1;
 	    goto error;
 	}
@@ -960,12 +948,12 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
 		ERROR5(NULL, NULL, NULL,
 		    "xmlCompileAttributeTest : no namespace bound to prefix %s\n",
 		    prefix);
-	        XML_PAT_FREE_STRING(ctxt, prefix);
 		ctxt->error = 1;
 		goto error;
 	    }
 	}
-	XML_PAT_FREE_STRING(ctxt, prefix);
+        XML_PAT_FREE_STRING(ctxt, name);
+        name = NULL;
 	if (token == NULL) {
 	    if (CUR == '*') {
 		NEXT;
@@ -984,6 +972,8 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
     }
     return;
 error:
+    if (name != NULL)
+	XML_PAT_FREE_STRING(ctxt, name);
     if (URL != NULL)
 	XML_PAT_FREE_STRING(ctxt, URL)
     if (token != NULL)
@@ -1034,6 +1024,8 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
 	return;
     }
     name = xmlPatScanNCName(ctxt);
+    if (ctxt->error < 0)
+        return;
     if (name == NULL) {
 	if (CUR == '*') {
 	    NEXT;
@@ -1250,6 +1242,8 @@ xmlCompilePathPattern(xmlPatParserContextPtr ctxt) {
     if (CUR == '@') {
 	NEXT;
 	xmlCompileAttributeTest(ctxt);
+        if (ctxt->error != 0)
+            goto error;
 	SKIP_BLANKS;
 	/* TODO: check for incompleteness */
 	if (CUR != 0) {
@@ -1415,62 +1409,6 @@ error_unfinished:
  *									*
  ************************************************************************/
 
-#ifdef DEBUG_STREAMING
-static void
-xmlDebugStreamComp(xmlStreamCompPtr stream) {
-    int i;
-
-    if (stream == NULL) {
-        printf("Stream: NULL\n");
-	return;
-    }
-    printf("Stream: %d steps\n", stream->nbStep);
-    for (i = 0;i < stream->nbStep;i++) {
-	if (stream->steps[i].ns != NULL) {
-	    printf("{%s}", stream->steps[i].ns);
-	}
-        if (stream->steps[i].name == NULL) {
-	    printf("* ");
-	} else {
-	    printf("%s ", stream->steps[i].name);
-	}
-	if (stream->steps[i].flags & XML_STREAM_STEP_ROOT)
-	    printf("root ");
-	if (stream->steps[i].flags & XML_STREAM_STEP_DESC)
-	    printf("// ");
-	if (stream->steps[i].flags & XML_STREAM_STEP_FINAL)
-	    printf("final ");
-	printf("\n");
-    }
-}
-static void
-xmlDebugStreamCtxt(xmlStreamCtxtPtr ctxt, int match) {
-    int i;
-
-    if (ctxt == NULL) {
-        printf("Stream: NULL\n");
-	return;
-    }
-    printf("Stream: level %d, %d states: ", ctxt->level, ctxt->nbState);
-    if (match)
-        printf("matches\n");
-    else
-        printf("\n");
-    for (i = 0;i < ctxt->nbState;i++) {
-        if (ctxt->states[2 * i] < 0)
-	    printf(" %d: free\n", i);
-	else {
-	    printf(" %d: step %d, level %d", i, ctxt->states[2 * i],
-	           ctxt->states[(2 * i) + 1]);
-            if (ctxt->comp->steps[ctxt->states[2 * i]].flags &
-	        XML_STREAM_STEP_DESC)
-	        printf(" //\n");
-	    else
-	        printf("\n");
-	}
-    }
-}
-#endif
 /**
  * xmlNewStreamComp:
  * @size: the number of expected steps
@@ -1729,9 +1667,6 @@ xmlStreamCompile(xmlPatternPtr comp) {
     stream->steps[s].flags |= XML_STREAM_STEP_FINAL;
     if (root)
 	stream->steps[0].flags |= XML_STREAM_STEP_ROOT;
-#ifdef DEBUG_STREAMING
-    xmlDebugStreamComp(stream);
-#endif
     comp->stream = stream;
     return(0);
 error:
@@ -1849,12 +1784,9 @@ static int
 xmlStreamPushInternal(xmlStreamCtxtPtr stream,
 		      const xmlChar *name, const xmlChar *ns,
 		      int nodeType) {
-    int ret = 0, err = 0, final = 0, tmp, i, m, match, stepNr, desc;
+    int ret = 0, final = 0, tmp, i, m, match, stepNr, desc;
     xmlStreamCompPtr comp;
     xmlStreamStep step;
-#ifdef DEBUG_STREAMING
-    xmlStreamCtxtPtr orig = stream;
-#endif
 
     if ((stream == NULL) || (stream->nbState < 0))
         return(-1);
@@ -1883,10 +1815,8 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream,
 			*/
 			ret = 1;
 		    } else if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) {
-			/* TODO: Do we need this ? */
-			tmp = xmlStreamCtxtAddState(stream, 0, 0);
-			if (tmp < 0)
-			    err++;
+			if (xmlStreamCtxtAddState(stream, 0, 0) < 0)
+                            return(-1);
 		    }
 		}
 	    }
@@ -2039,22 +1969,12 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream,
 #endif /* if 0 ------------------------------------------------------- */
 	    if (match) {
 		final = step.flags & XML_STREAM_STEP_FINAL;
-		if (desc) {
-		    if (final) {
-			ret = 1;
-		    } else {
-			/* descending match create a new state */
-			xmlStreamCtxtAddState(stream, stepNr + 1,
-			                      stream->level + 1);
-		    }
-		} else {
-		    if (final) {
-			ret = 1;
-		    } else {
-			xmlStreamCtxtAddState(stream, stepNr + 1,
-			                      stream->level + 1);
-		    }
-		}
+                if (final) {
+                    ret = 1;
+                } else if (xmlStreamCtxtAddState(stream, stepNr + 1,
+                                                 stream->level + 1) < 0) {
+                    return(-1);
+                }
 		if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
 		    /*
 		    * Check if we have a special case like "foo/bar//.", where
@@ -2155,10 +2075,11 @@ compare:
 	}
 	final = step.flags & XML_STREAM_STEP_FINAL;
 	if (match) {
-	    if (final)
+	    if (final) {
 		ret = 1;
-	    else
-		xmlStreamCtxtAddState(stream, 1, stream->level);
+            } else if (xmlStreamCtxtAddState(stream, 1, stream->level) < 0) {
+                return(-1);
+            }
 	    if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
 		/*
 		* Check if we have a special case like "foo//.", where
@@ -2180,11 +2101,6 @@ stream_next:
         stream = stream->next;
     } /* while stream != NULL */
 
-    if (err > 0)
-        ret = -1;
-#ifdef DEBUG_STREAMING
-    xmlDebugStreamCtxt(orig, ret);
-#endif
     return(ret);
 }
 
@@ -2207,7 +2123,7 @@ stream_next:
 int
 xmlStreamPush(xmlStreamCtxtPtr stream,
               const xmlChar *name, const xmlChar *ns) {
-    return (xmlStreamPushInternal(stream, name, ns, (int) XML_ELEMENT_NODE));
+    return (xmlStreamPushInternal(stream, name, ns, XML_ELEMENT_NODE));
 }
 
 /**
@@ -2257,7 +2173,7 @@ xmlStreamPushNode(xmlStreamCtxtPtr stream,
 int
 xmlStreamPushAttr(xmlStreamCtxtPtr stream,
 		  const xmlChar *name, const xmlChar *ns) {
-    return (xmlStreamPushInternal(stream, name, ns, (int) XML_ATTRIBUTE_NODE));
+    return (xmlStreamPushInternal(stream, name, ns, XML_ATTRIBUTE_NODE));
 }
 
 /**
@@ -2336,28 +2252,37 @@ xmlStreamWantsAnyNode(xmlStreamCtxtPtr streamCtxt)
  ************************************************************************/
 
 /**
- * xmlPatterncompile:
+ * xmlPatternCompileSafe:
  * @pattern: the pattern to compile
  * @dict: an optional dictionary for interned strings
  * @flags: compilation flags, see xmlPatternFlags
  * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
+ * @patternOut: output pattern
  *
  * Compile a pattern.
  *
- * Returns the compiled form of the pattern or NULL in case of error
+ * Available since 2.13.0.
+ *
+ * Returns 0 on success, 1 on error, -1 if a memory allocation failed.
  */
-xmlPatternPtr
-xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
-                  const xmlChar **namespaces) {
+int
+xmlPatternCompileSafe(const xmlChar *pattern, xmlDict *dict, int flags,
+                      const xmlChar **namespaces, xmlPatternPtr *patternOut) {
     xmlPatternPtr ret = NULL, cur;
     xmlPatParserContextPtr ctxt = NULL;
     const xmlChar *or, *start;
     xmlChar *tmp = NULL;
     int type = 0;
     int streamable = 1;
+    int error;
 
-    if (pattern == NULL)
-        return(NULL);
+    if (patternOut == NULL)
+        return(1);
+
+    if (pattern == NULL) {
+        error = 1;
+        goto error;
+    }
 
     start = pattern;
     or = start;
@@ -2373,9 +2298,15 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
 	    }
 	    or++;
 	}
-	if (ctxt == NULL) goto error;
+	if (ctxt == NULL) {
+            error = -1;
+            goto error;
+        }
 	cur = xmlNewPattern();
-	if (cur == NULL) goto error;
+	if (cur == NULL) {
+            error = -1;
+            goto error;
+        }
 	/*
 	* Assign string dict.
 	*/
@@ -2396,8 +2327,10 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
 	    xmlCompileIDCXPathPath(ctxt);
 	else
 	    xmlCompilePathPattern(ctxt);
-	if (ctxt->error != 0)
+	if (ctxt->error != 0) {
+            error = ctxt->error;
 	    goto error;
+        }
 	xmlFreePatParserContext(ctxt);
 	ctxt = NULL;
 
@@ -2413,9 +2346,13 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
 		    streamable = 0;
 	    }
 	}
-	if (streamable)
-	    xmlStreamCompile(cur);
-	if (xmlReversePattern(cur) < 0)
+	if (streamable) {
+	    error = xmlStreamCompile(cur);
+            if (error != 0)
+                goto error;
+        }
+	error = xmlReversePattern(cur);
+        if (error != 0)
 	    goto error;
 	if (tmp != NULL) {
 	    xmlFree(tmp);
@@ -2434,12 +2371,33 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
 	}
     }
 
-    return(ret);
+    *patternOut = ret;
+    return(0);
 error:
     if (ctxt != NULL) xmlFreePatParserContext(ctxt);
     if (ret != NULL) xmlFreePattern(ret);
     if (tmp != NULL) xmlFree(tmp);
-    return(NULL);
+    *patternOut = NULL;
+    return(error);
+}
+
+/**
+ * xmlPatterncompile:
+ * @pattern: the pattern to compile
+ * @dict: an optional dictionary for interned strings
+ * @flags: compilation flags, see xmlPatternFlags
+ * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
+ *
+ * Compile a pattern.
+ *
+ * Returns the compiled form of the pattern or NULL in case of error
+ */
+xmlPatternPtr
+xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
+                  const xmlChar **namespaces) {
+    xmlPatternPtr ret;
+    xmlPatternCompileSafe(pattern, dict, flags, namespaces, &ret);
+    return(ret);
 }
 
 /**
diff --git a/relaxng.c b/relaxng.c
index 7f0f2e741ed180b5341c738d8bb0c6b7adea7ad4..24c3e51056cd840377afa3d41de79dab8e3c4a38 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -34,6 +34,10 @@
 #include <libxml/xmlregexp.h>
 #include <libxml/xmlschemastypes.h>
 
+#include "private/error.h"
+#include "private/regexp.h"
+#include "private/string.h"
+
 /*
  * The Relax-NG namespace
  */
@@ -47,37 +51,8 @@ static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
     (xmlStrEqual(node->ns->href, xmlRelaxNGNs)))
 
 
-#if 0
-#define DEBUG 1
-
-#define DEBUG_GRAMMAR 1
-
-#define DEBUG_CONTENT 1
-
-#define DEBUG_TYPE 1
-
-#define DEBUG_VALID 1
-
-#define DEBUG_INTERLEAVE 1
-
-#define DEBUG_LIST 1
-
-#define DEBUG_INCLUDE 1
-
-#define DEBUG_ERROR 1
-
-#define DEBUG_COMPILE 1
-
-#define DEBUG_PROGRESSIVE 1
-#endif
-
 #define MAX_ERROR 5
 
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
-
 typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema;
 typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr;
 
@@ -435,7 +410,7 @@ struct _xmlRelaxNGDocument {
  * Handle a redefinition of attribute error
  */
 static void
-xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)
+xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt)
 {
     xmlStructuredErrorFunc schannel = NULL;
     xmlGenericErrorFunc channel = NULL;
@@ -449,17 +424,8 @@ xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)
         data = ctxt->userData;
         ctxt->nbErrors++;
     }
-    if (extra)
-        __xmlRaiseError(schannel, channel, data,
-                        NULL, NULL, XML_FROM_RELAXNGP,
-                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
-                        NULL, NULL, 0, 0,
-                        "Memory allocation failed : %s\n", extra);
-    else
-        __xmlRaiseError(schannel, channel, data,
-                        NULL, NULL, XML_FROM_RELAXNGP,
-                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
-                        NULL, NULL, 0, 0, "Memory allocation failed\n");
+
+    xmlRaiseMemoryError(schannel, channel, data, XML_FROM_RELAXNGP, NULL);
 }
 
 /**
@@ -470,7 +436,7 @@ xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)
  * Handle a redefinition of attribute error
  */
 static void
-xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra)
+xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt)
 {
     xmlStructuredErrorFunc schannel = NULL;
     xmlGenericErrorFunc channel = NULL;
@@ -484,17 +450,8 @@ xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra)
         data = ctxt->userData;
         ctxt->nbErrors++;
     }
-    if (extra)
-        __xmlRaiseError(schannel, channel, data,
-                        NULL, NULL, XML_FROM_RELAXNGV,
-                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
-                        NULL, NULL, 0, 0,
-                        "Memory allocation failed : %s\n", extra);
-    else
-        __xmlRaiseError(schannel, channel, data,
-                        NULL, NULL, XML_FROM_RELAXNGV,
-                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
-                        NULL, NULL, 0, 0, "Memory allocation failed\n");
+
+    xmlRaiseMemoryError(schannel, channel, data, XML_FROM_RELAXNGV, NULL);
 }
 
 /**
@@ -515,6 +472,7 @@ xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error,
     xmlStructuredErrorFunc schannel = NULL;
     xmlGenericErrorFunc channel = NULL;
     void *data = NULL;
+    int res;
 
     if (ctxt != NULL) {
         if (ctxt->serror != NULL)
@@ -524,11 +482,18 @@ xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error,
         data = ctxt->userData;
         ctxt->nbErrors++;
     }
-    __xmlRaiseError(schannel, channel, data,
-                    NULL, node, XML_FROM_RELAXNGP,
-                    error, XML_ERR_ERROR, NULL, 0,
-                    (const char *) str1, (const char *) str2, NULL, 0, 0,
-                    msg, str1, str2);
+
+    if ((channel == NULL) && (schannel == NULL)) {
+        channel = xmlGenericError;
+        data = xmlGenericErrorContext;
+    }
+
+    res = __xmlRaiseError(schannel, channel, data, NULL, node,
+                          XML_FROM_RELAXNGP, error, XML_ERR_ERROR, NULL, 0,
+                          (const char *) str1, (const char *) str2, NULL, 0, 0,
+                          msg, str1, str2);
+    if (res < 0)
+        xmlRngPErrMemory(ctxt);
 }
 
 /**
@@ -549,6 +514,7 @@ xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error,
     xmlStructuredErrorFunc schannel = NULL;
     xmlGenericErrorFunc channel = NULL;
     void *data = NULL;
+    int res;
 
     if (ctxt != NULL) {
         if (ctxt->serror != NULL)
@@ -558,11 +524,18 @@ xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error,
         data = ctxt->userData;
         ctxt->nbErrors++;
     }
-    __xmlRaiseError(schannel, channel, data,
-                    NULL, node, XML_FROM_RELAXNGV,
-                    error, XML_ERR_ERROR, NULL, 0,
-                    (const char *) str1, (const char *) str2, NULL, 0, 0,
-                    msg, str1, str2);
+
+    if ((channel == NULL) && (schannel == NULL)) {
+        channel = xmlGenericError;
+        data = xmlGenericErrorContext;
+    }
+
+    res = __xmlRaiseError(schannel, channel, data, NULL, node,
+                          XML_FROM_RELAXNGV, error, XML_ERR_ERROR, NULL, 0,
+                          (const char *) str1, (const char *) str2, NULL, 0, 0,
+                          msg, str1, str2);
+    if (res < 0)
+        xmlRngVErrMemory(ctxt);
 }
 
 /************************************************************************
@@ -764,7 +737,7 @@ xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt)
 
     ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG));
     if (ret == NULL) {
-        xmlRngPErrMemory(ctxt, NULL);
+        xmlRngPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlRelaxNG));
@@ -843,7 +816,7 @@ xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt)
 
     ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar));
     if (ret == NULL) {
-        xmlRngPErrMemory(ctxt, NULL);
+        xmlRngPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlRelaxNGGrammar));
@@ -899,7 +872,7 @@ xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
         ctxt->defTab = (xmlRelaxNGDefinePtr *)
             xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
         if (ctxt->defTab == NULL) {
-            xmlRngPErrMemory(ctxt, "allocating define\n");
+            xmlRngPErrMemory(ctxt);
             return (NULL);
         }
     } else if (ctxt->defMax <= ctxt->defNr) {
@@ -911,14 +884,14 @@ xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
                                                  sizeof
                                                  (xmlRelaxNGDefinePtr));
         if (tmp == NULL) {
-            xmlRngPErrMemory(ctxt, "allocating define\n");
+            xmlRngPErrMemory(ctxt);
             return (NULL);
         }
         ctxt->defTab = tmp;
     }
     ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine));
     if (ret == NULL) {
-        xmlRngPErrMemory(ctxt, "allocating define\n");
+        xmlRngPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlRelaxNGDefine));
@@ -1024,7 +997,7 @@ xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size)
                                            1) *
                                           sizeof(xmlRelaxNGValidStatePtr));
     if (ret == NULL) {
-        xmlRngVErrMemory(ctxt, "allocating states\n");
+        xmlRngVErrMemory(ctxt);
         return (NULL);
     }
     ret->nbState = 0;
@@ -1033,7 +1006,7 @@ xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size)
                                                           sizeof
                                                           (xmlRelaxNGValidStatePtr));
     if (ret->tabState == NULL) {
-        xmlRngVErrMemory(ctxt, "allocating states\n");
+        xmlRngVErrMemory(ctxt);
         xmlFree(ret);
         return (NULL);
     }
@@ -1069,7 +1042,7 @@ xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt,
                                                      sizeof
                                                      (xmlRelaxNGValidStatePtr));
         if (tmp == NULL) {
-            xmlRngVErrMemory(ctxt, "adding states\n");
+            xmlRngVErrMemory(ctxt);
             return (-1);
         }
         states->tabState = tmp;
@@ -1109,7 +1082,7 @@ xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt,
                                                      sizeof
                                                      (xmlRelaxNGValidStatePtr));
         if (tmp == NULL) {
-            xmlRngVErrMemory(ctxt, "adding states\n");
+            xmlRngVErrMemory(ctxt);
             return (-1);
         }
         states->tabState = tmp;
@@ -1144,7 +1117,7 @@ xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt,
         ctxt->freeStates = (xmlRelaxNGStatesPtr *)
             xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr));
         if (ctxt->freeStates == NULL) {
-            xmlRngVErrMemory(ctxt, "storing states\n");
+            xmlRngVErrMemory(ctxt);
         }
     } else if ((ctxt != NULL)
                && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) {
@@ -1155,7 +1128,7 @@ xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt,
                                                  sizeof
                                                  (xmlRelaxNGStatesPtr));
         if (tmp == NULL) {
-            xmlRngVErrMemory(ctxt, "storing states\n");
+            xmlRngVErrMemory(ctxt);
             xmlFree(states->tabState);
             xmlFree(states);
             return;
@@ -1211,7 +1184,7 @@ xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)
             (xmlRelaxNGValidStatePtr)
             xmlMalloc(sizeof(xmlRelaxNGValidState));
         if (ret == NULL) {
-            xmlRngVErrMemory(ctxt, "allocating states\n");
+            xmlRngVErrMemory(ctxt);
             return (NULL);
         }
         memset(ret, 0, sizeof(xmlRelaxNGValidState));
@@ -1235,7 +1208,7 @@ xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)
             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
                                                   sizeof(xmlAttrPtr));
             if (ret->attrs == NULL) {
-                xmlRngVErrMemory(ctxt, "allocating states\n");
+                xmlRngVErrMemory(ctxt);
                 return (ret);
             }
         } else if (ret->maxAttrs < nbAttrs) {
@@ -1244,7 +1217,7 @@ xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)
             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs *
                                             sizeof(xmlAttrPtr));
             if (tmp == NULL) {
-                xmlRngVErrMemory(ctxt, "allocating states\n");
+                xmlRngVErrMemory(ctxt);
                 return (ret);
             }
             ret->attrs = tmp;
@@ -1293,7 +1266,7 @@ xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,
             (xmlRelaxNGValidStatePtr)
             xmlMalloc(sizeof(xmlRelaxNGValidState));
         if (ret == NULL) {
-            xmlRngVErrMemory(ctxt, "allocating states\n");
+            xmlRngVErrMemory(ctxt);
             return (NULL);
         }
         memset(ret, 0, sizeof(xmlRelaxNGValidState));
@@ -1309,7 +1282,7 @@ xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,
             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
                                                   sizeof(xmlAttrPtr));
             if (ret->attrs == NULL) {
-                xmlRngVErrMemory(ctxt, "allocating states\n");
+                xmlRngVErrMemory(ctxt);
                 ret->nbAttrs = 0;
                 return (ret);
             }
@@ -1319,7 +1292,7 @@ xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,
             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs *
                                             sizeof(xmlAttrPtr));
             if (tmp == NULL) {
-                xmlRngVErrMemory(ctxt, "allocating states\n");
+                xmlRngVErrMemory(ctxt);
                 ret->nbAttrs = 0;
                 return (ret);
             }
@@ -1438,6 +1411,42 @@ xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags)
 static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt,
                                       xmlDocPtr doc);
 
+static xmlDoc *
+xmlRelaxReadFile(xmlRelaxNGParserCtxtPtr ctxt, const char *filename) {
+    xmlParserCtxtPtr pctxt;
+    xmlDocPtr doc;
+
+    pctxt = xmlNewParserCtxt();
+    if (pctxt == NULL) {
+        xmlRngPErrMemory(ctxt);
+        return(NULL);
+    }
+    if (ctxt->serror != NULL)
+        xmlCtxtSetErrorHandler(pctxt, ctxt->serror, ctxt->userData);
+    doc = xmlCtxtReadFile(pctxt, filename, NULL, 0);
+    xmlFreeParserCtxt(pctxt);
+
+    return(doc);
+}
+
+static xmlDoc *
+xmlRelaxReadMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *buf, int size) {
+    xmlParserCtxtPtr pctxt;
+    xmlDocPtr doc;
+
+    pctxt = xmlNewParserCtxt();
+    if (pctxt == NULL) {
+        xmlRngPErrMemory(ctxt);
+        return(NULL);
+    }
+    if (ctxt->serror != NULL)
+        xmlCtxtSetErrorHandler(pctxt, ctxt->serror, ctxt->userData);
+    doc = xmlCtxtReadMemory(pctxt, buf, size, NULL, NULL, 0);
+    xmlFreeParserCtxt(pctxt);
+
+    return(doc);
+}
+
 /**
  * xmlRelaxNGIncludePush:
  * @ctxt:  the parser context
@@ -1458,7 +1467,7 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
             (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax *
                                                sizeof(ctxt->incTab[0]));
         if (ctxt->incTab == NULL) {
-            xmlRngPErrMemory(ctxt, "allocating include\n");
+            xmlRngPErrMemory(ctxt);
             return (0);
         }
     }
@@ -1469,7 +1478,7 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
                                                 ctxt->incMax *
                                                 sizeof(ctxt->incTab[0]));
         if (ctxt->incTab == NULL) {
-            xmlRngPErrMemory(ctxt, "allocating include\n");
+            xmlRngPErrMemory(ctxt);
             return (0);
         }
     }
@@ -1523,15 +1532,6 @@ xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,
     xmlNodePtr tmp, tmp2;
     xmlChar *name2;
 
-#ifdef DEBUG_INCLUDE
-    if (name == NULL)
-        xmlGenericError(xmlGenericErrorContext,
-                        "Elimination of <include> start from %s\n", URL);
-    else
-        xmlGenericError(xmlGenericErrorContext,
-                        "Elimination of <include> define %s from %s\n",
-                        name, URL);
-#endif
     tmp = target;
     while (tmp != NULL) {
         tmp2 = tmp->next;
@@ -1559,18 +1559,11 @@ xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,
 
                 if (xmlStrEqual
                     (inc->doc->children->name, BAD_CAST "grammar")) {
-#ifdef DEBUG_INCLUDE
-                    href = xmlGetProp(tmp, BAD_CAST "href");
-#endif
                     if (xmlRelaxNGRemoveRedefine(ctxt, href,
                                                  xmlDocGetRootElement(inc->doc)->children,
                                                  name) == 1) {
                         found = 1;
                     }
-#ifdef DEBUG_INCLUDE
-                    if (href != NULL)
-                        xmlFree(href);
-#endif
                 }
             }
             if (xmlRelaxNGRemoveRedefine(ctxt, URL, tmp->children, name) == 1) {
@@ -1604,11 +1597,6 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
     int i;
     xmlNodePtr root, cur;
 
-#ifdef DEBUG_INCLUDE
-    xmlGenericError(xmlGenericErrorContext,
-                    "xmlRelaxNGLoadInclude(%s)\n", URL);
-#endif
-
     /*
      * check against recursion in the stack
      */
@@ -1624,22 +1612,19 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
     /*
      * load the document
      */
-    doc = xmlReadFile((const char *) URL,NULL,0);
+    doc = xmlRelaxReadFile(ctxt, (const char *) URL);
     if (doc == NULL) {
         xmlRngPErr(ctxt, node, XML_RNGP_PARSE_ERROR,
                    "xmlRelaxNG: could not load %s\n", URL, NULL);
         return (NULL);
     }
-#ifdef DEBUG_INCLUDE
-    xmlGenericError(xmlGenericErrorContext, "Parsed %s Okay\n", URL);
-#endif
 
     /*
      * Allocate the document structures and register it first.
      */
     ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude));
     if (ret == NULL) {
-        xmlRngPErrMemory(ctxt, "allocating include\n");
+        xmlRngPErrMemory(ctxt);
         xmlFreeDoc(doc);
         return (NULL);
     }
@@ -1670,9 +1655,6 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
      * Some preprocessing of the document content, this include recursing
      * in the include stack.
      */
-#ifdef DEBUG_INCLUDE
-    xmlGenericError(xmlGenericErrorContext, "cleanup of %s\n", URL);
-#endif
 
     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
     if (doc == NULL) {
@@ -1685,9 +1667,6 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
      */
     xmlRelaxNGIncludePop(ctxt);
 
-#ifdef DEBUG_INCLUDE
-    xmlGenericError(xmlGenericErrorContext, "Checking of %s\n", URL);
-#endif
     /*
      * Check that the top element is a grammar
      */
@@ -1779,10 +1758,6 @@ xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,
 {
     xmlRelaxNGValidErrorPtr cur;
 
-#ifdef DEBUG_ERROR
-    xmlGenericError(xmlGenericErrorContext,
-                    "Pushing error %d at %d on stack\n", err, ctxt->errNr);
-#endif
     if (ctxt->errTab == NULL) {
         ctxt->errMax = 8;
         ctxt->errNr = 0;
@@ -1791,7 +1766,7 @@ xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,
                                                 sizeof
                                                 (xmlRelaxNGValidError));
         if (ctxt->errTab == NULL) {
-            xmlRngVErrMemory(ctxt, "pushing error\n");
+            xmlRngVErrMemory(ctxt);
             return (0);
         }
         ctxt->err = NULL;
@@ -1804,7 +1779,7 @@ xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,
                                                  sizeof
                                                  (xmlRelaxNGValidError));
         if (ctxt->errTab == NULL) {
-            xmlRngVErrMemory(ctxt, "pushing error\n");
+            xmlRngVErrMemory(ctxt);
             return (0);
         }
         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
@@ -1886,7 +1861,7 @@ xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,
             (xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax *
                                                 sizeof(ctxt->docTab[0]));
         if (ctxt->docTab == NULL) {
-            xmlRngPErrMemory(ctxt, "adding document\n");
+            xmlRngPErrMemory(ctxt);
             return (0);
         }
     }
@@ -1897,7 +1872,7 @@ xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,
                                                  ctxt->docMax *
                                                  sizeof(ctxt->docTab[0]));
         if (ctxt->docTab == NULL) {
-            xmlRngPErrMemory(ctxt, "adding document\n");
+            xmlRngPErrMemory(ctxt);
             return (0);
         }
     }
@@ -1967,7 +1942,7 @@ xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt,
     /*
      * load the document
      */
-    doc = xmlReadFile((const char *) URL,NULL,0);
+    doc = xmlRelaxReadFile(ctxt, (const char *) URL);
     if (doc == NULL) {
         xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
                    "xmlRelaxNG: could not load %s\n", URL, NULL);
@@ -1979,8 +1954,7 @@ xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt,
      */
     ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument));
     if (ret == NULL) {
-        xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY,
-                   "xmlRelaxNG: allocate memory for doc %s\n", URL, NULL);
+        xmlRngPErrMemory(ctxt);
         xmlFreeDoc(doc);
         return (NULL);
     }
@@ -2257,9 +2231,6 @@ xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt,
     if (ctxt->flags & FLAGS_NOERROR)
         return;
 
-#ifdef DEBUG_ERROR
-    xmlGenericError(xmlGenericErrorContext, "Show error %d\n", err);
-#endif
     msg = xmlRelaxNGGetErrorString(err, arg1, arg2);
     if (msg == NULL)
         return;
@@ -2284,10 +2255,6 @@ xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level)
     int i;
     xmlRelaxNGValidErrorPtr err;
 
-#ifdef DEBUG_ERROR
-    xmlGenericError(xmlGenericErrorContext,
-                    "Pop errors till level %d\n", level);
-#endif
     for (i = level; i < ctxt->errNr; i++) {
         err = &ctxt->errTab[i];
         if (err->flags & ERROR_IS_DUP) {
@@ -2317,10 +2284,6 @@ xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt)
     int i, j, k;
     xmlRelaxNGValidErrorPtr err, dup;
 
-#ifdef DEBUG_ERROR
-    xmlGenericError(xmlGenericErrorContext,
-                    "Dumping error stack %d errors\n", ctxt->errNr);
-#endif
     for (i = 0, k = 0; i < ctxt->errNr; i++) {
         err = &ctxt->errTab[i];
         if (k < MAX_ERROR) {
@@ -2371,9 +2334,6 @@ xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt,
     if (ctxt->flags & FLAGS_NOERROR)
         return;
 
-#ifdef DEBUG_ERROR
-    xmlGenericError(xmlGenericErrorContext, "Adding error %d\n", err);
-#endif
     /*
      * generate the error directly
      */
@@ -2780,17 +2740,13 @@ xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data,
     if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||
         (check == NULL) || (comp == NULL))
         return (-1);
-    if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-                        "Relax-NG types library '%s' already registered\n",
-                        namespace);
+    if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL)
         return (-1);
-    }
     lib =
         (xmlRelaxNGTypeLibraryPtr)
         xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));
     if (lib == NULL) {
-        xmlRngVErrMemory(NULL, "adding types library\n");
+        xmlRngVErrMemory(NULL);
         return (-1);
     }
     memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));
@@ -2803,9 +2759,6 @@ xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data,
     lib->freef = freef;
     ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
     if (ret < 0) {
-        xmlGenericError(xmlGenericErrorContext,
-                        "Relax-NG types library failed to register '%s'\n",
-                        namespace);
         xmlRelaxNGFreeTypeLibrary(lib, namespace);
         return (-1);
     }
@@ -2825,11 +2778,8 @@ xmlRelaxNGInitTypes(void)
     if (xmlRelaxNGTypeInitialized != 0)
         return (0);
     xmlRelaxNGRegisteredTypes = xmlHashCreate(10);
-    if (xmlRelaxNGRegisteredTypes == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-                        "Failed to allocate sh table for Relax-NG types\n");
+    if (xmlRelaxNGRegisteredTypes == NULL)
         return (-1);
-    }
     xmlRelaxNGRegisterTypeLibrary(BAD_CAST
                                   "http://www.w3.org/2001/XMLSchema-datatypes",
                                   NULL, xmlRelaxNGSchemaTypeHave,
@@ -2875,10 +2825,6 @@ xmlRelaxNGCleanupTypes(void)
  *									*
  ************************************************************************/
 
-/* from automata.c but not exported */
-void xmlAutomataSetFlags(xmlAutomataPtr am, int flags);
-
-
 static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt,
                                 xmlRelaxNGDefinePtr def);
 
@@ -2937,21 +2883,6 @@ xmlRelaxNGIsCompilable(xmlRelaxNGDefinePtr def)
 		}
                 if ((ret == 1) && !(def->dflags &= IS_NOT_COMPILABLE))
                     def->dflags |= IS_COMPILABLE;
-#ifdef DEBUG_COMPILE
-                if (ret == 1) {
-                    xmlGenericError(xmlGenericErrorContext,
-                                    "element content for %s is compilable\n",
-                                    def->name);
-                } else if (ret == 0) {
-                    xmlGenericError(xmlGenericErrorContext,
-                                    "element content for %s is not compilable\n",
-                                    def->name);
-                } else {
-                    xmlGenericError(xmlGenericErrorContext,
-                                    "Problem in RelaxNGIsCompilable for element %s\n",
-                                    def->name);
-                }
-#endif
             }
             /*
              * All elements return a compilable status unless they
@@ -3013,21 +2944,6 @@ xmlRelaxNGIsCompilable(xmlRelaxNGDefinePtr def)
         def->dflags |= IS_NOT_COMPILABLE;
     if (ret == 1)
         def->dflags |= IS_COMPILABLE;
-#ifdef DEBUG_COMPILE
-    if (ret == 1) {
-        xmlGenericError(xmlGenericErrorContext,
-                        "RelaxNGIsCompilable %s : true\n",
-                        xmlRelaxNGDefName(def));
-    } else if (ret == 0) {
-        xmlGenericError(xmlGenericErrorContext,
-                        "RelaxNGIsCompilable %s : false\n",
-                        xmlRelaxNGDefName(def));
-    } else {
-        xmlGenericError(xmlGenericErrorContext,
-                        "Problem in RelaxNGIsCompilable %s\n",
-                        xmlRelaxNGDefName(def));
-    }
-#endif
     return (ret);
 }
 
@@ -3113,11 +3029,6 @@ xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
                 def->contModel = xmlAutomataCompile(ctxt->am);
                 if (!xmlRegexpIsDeterminist(def->contModel)) {
-#ifdef DEBUG_COMPILE
-                    xmlGenericError(xmlGenericErrorContext,
-                        "Content model not determinist %s\n",
-                                    def->name);
-#endif
                     /*
                      * we can only use the automata if it is determinist
                      */
@@ -3282,24 +3193,6 @@ xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
         if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
             ctxt->am = NULL;
             ret = xmlRelaxNGCompile(ctxt, def);
-#ifdef DEBUG_PROGRESSIVE
-            if (ret == 0) {
-                if (def->type == XML_RELAXNG_START)
-                    xmlGenericError(xmlGenericErrorContext,
-                                    "compiled the start\n");
-                else
-                    xmlGenericError(xmlGenericErrorContext,
-                                    "compiled element %s\n", def->name);
-            } else {
-                if (def->type == XML_RELAXNG_START)
-                    xmlGenericError(xmlGenericErrorContext,
-                                    "failed to compile the start\n");
-                else
-                    xmlGenericError(xmlGenericErrorContext,
-                                    "failed to compile element %s\n",
-                                    def->name);
-            }
-#endif
             return (ret);
         }
     }
@@ -3848,7 +3741,8 @@ xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1,
 	else if (ret == 1)
 	    ret = 0;
     } else {
-        TODO ret = 0;
+        /* TODO */
+        ret = 0;
     }
     if (ret == 0)
         return (ret);
@@ -3879,7 +3773,8 @@ xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1,
             ret = 1;
         }
     } else {
-        TODO ret = 0;
+        /* TODO */
+        ret = 0;
     }
 
     return (ret);
@@ -4036,7 +3931,7 @@ xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt,
                 ret = (xmlRelaxNGDefinePtr *)
                     xmlMalloc((max + 1) * sizeof(xmlRelaxNGDefinePtr));
                 if (ret == NULL) {
-                    xmlRngPErrMemory(ctxt, "getting element list\n");
+                    xmlRngPErrMemory(ctxt);
                     return (NULL);
                 }
             } else if (max <= len) {
@@ -4046,7 +3941,7 @@ xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt,
                 temp = xmlRealloc(ret,
                                (max + 1) * sizeof(xmlRelaxNGDefinePtr));
                 if (temp == NULL) {
-                    xmlRngPErrMemory(ctxt, "getting element list\n");
+                    xmlRngPErrMemory(ctxt);
 		    xmlFree(ret);
                     return (NULL);
                 }
@@ -4144,7 +4039,7 @@ xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt,
                                               sizeof(xmlRelaxNGDefinePtr
                                                      *));
     if (list == NULL) {
-        xmlRngPErrMemory(ctxt, "building choice\n");
+        xmlRngPErrMemory(ctxt);
         return;
     }
     i = 0;
@@ -4281,7 +4176,7 @@ xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt,
                                               sizeof(xmlRelaxNGDefinePtr
                                                      *));
     if (list == NULL) {
-        xmlRngPErrMemory(ctxt, "building group\n");
+        xmlRngPErrMemory(ctxt);
         return;
     }
     i = 0;
@@ -4359,19 +4254,12 @@ xmlRelaxNGComputeInterleaves(void *payload, void *data,
     if (ctxt->nbErrors != 0)
         return;
 
-#ifdef DEBUG_INTERLEAVE
-    xmlGenericError(xmlGenericErrorContext,
-                    "xmlRelaxNGComputeInterleaves(%s)\n", name);
-#endif
     cur = def->content;
     while (cur != NULL) {
         nbchild++;
         cur = cur->next;
     }
 
-#ifdef DEBUG_INTERLEAVE
-    xmlGenericError(xmlGenericErrorContext, "  %d child\n", nbchild);
-#endif
     groups = (xmlRelaxNGInterleaveGroupPtr *)
         xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr));
     if (groups == NULL)
@@ -4390,9 +4278,6 @@ xmlRelaxNGComputeInterleaves(void *payload, void *data,
         nbgroups++;
         cur = cur->next;
     }
-#ifdef DEBUG_INTERLEAVE
-    xmlGenericError(xmlGenericErrorContext, "  %d groups\n", nbgroups);
-#endif
 
     /*
      * Let's check that all rules makes a partitions according to 7.4
@@ -4483,7 +4368,7 @@ xmlRelaxNGComputeInterleaves(void *payload, void *data,
     return;
 
   error:
-    xmlRngPErrMemory(ctxt, "in interleave computation\n");
+    xmlRngPErrMemory(ctxt);
     if (groups != NULL) {
         for (i = 0; i < nbgroups; i++)
             if (groups[i] != NULL) {
@@ -4521,7 +4406,7 @@ xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
     if (ctxt->interleaves == NULL)
         ctxt->interleaves = xmlHashCreate(10);
     if (ctxt->interleaves == NULL) {
-        xmlRngPErrMemory(ctxt, "create interleaves\n");
+        xmlRngPErrMemory(ctxt);
     } else {
         char name[32];
 
@@ -5019,11 +4904,6 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
         xmlRelaxNGGrammarPtr grammar, old;
         xmlRelaxNGGrammarPtr oldparent;
 
-#ifdef DEBUG_GRAMMAR
-        xmlGenericError(xmlGenericErrorContext,
-                        "Found <grammar> pattern\n");
-#endif
-
         oldparent = ctxt->parentgrammar;
         old = ctxt->grammar;
         ctxt->parentgrammar = old;
@@ -5393,7 +5273,7 @@ xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
                 if (tmp != NULL) {
                     if (last == NULL) {
                         last = tmp;
-                    } else {
+                    } else if (tmp != ret) {
                         last->next = tmp;
                         last = tmp;
                     }
@@ -5809,11 +5689,6 @@ xmlRelaxNGCheckCombine(void *payload, void *data, const xmlChar * name)
 
         cur = cur->nextHash;
     }
-#ifdef DEBUG
-    xmlGenericError(xmlGenericErrorContext,
-                    "xmlRelaxNGCheckCombine(): merging %s defines: %d\n",
-                    name, choiceOrInterleave);
-#endif
     if (choiceOrInterleave == -1)
         choiceOrInterleave = 0;
     cur = xmlRelaxNGNewDefine(ctxt, define->node);
@@ -5939,11 +5814,6 @@ xmlRelaxNGCombineStart(xmlRelaxNGParserCtxtPtr ctxt,
 
         cur = cur->next;
     }
-#ifdef DEBUG
-    xmlGenericError(xmlGenericErrorContext,
-                    "xmlRelaxNGCombineStart(): merging <start>: %d\n",
-                    choiceOrInterleave);
-#endif
     if (choiceOrInterleave == -1)
         choiceOrInterleave = 0;
     cur = xmlRelaxNGNewDefine(ctxt, starts->node);
@@ -6609,10 +6479,6 @@ xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
 {
     xmlRelaxNGGrammarPtr ret, tmp, old;
 
-#ifdef DEBUG_GRAMMAR
-    xmlGenericError(xmlGenericErrorContext, "Parsing a new grammar\n");
-#endif
-
     ret = xmlRelaxNGNewGrammar(ctxt);
     if (ret == NULL)
         return (NULL);
@@ -6741,11 +6607,6 @@ xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
                                  XML_RELAXNG_IN_START, XML_RELAXNG_NOOP);
         }
     }
-#ifdef DEBUG
-    if (schema == NULL)
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlRelaxNGParseDocument() failed\n");
-#endif
 
     return (schema);
 }
@@ -6776,13 +6637,11 @@ xmlRelaxNGNewParserCtxt(const char *URL)
     ret =
         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
     if (ret == NULL) {
-        xmlRngPErrMemory(NULL, "building parser\n");
+        xmlRngPErrMemory(NULL);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
     ret->URL = xmlStrdup((const xmlChar *) URL);
-    ret->error = xmlGenericError;
-    ret->userData = xmlGenericErrorContext;
     return (ret);
 }
 
@@ -6807,14 +6666,12 @@ xmlRelaxNGNewMemParserCtxt(const char *buffer, int size)
     ret =
         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
     if (ret == NULL) {
-        xmlRngPErrMemory(NULL, "building parser\n");
+        xmlRngPErrMemory(NULL);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
     ret->buffer = buffer;
     ret->size = size;
-    ret->error = xmlGenericError;
-    ret->userData = xmlGenericErrorContext;
     return (ret);
 }
 
@@ -6843,7 +6700,7 @@ xmlRelaxNGNewDocParserCtxt(xmlDocPtr doc)
     ret =
         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
     if (ret == NULL) {
-        xmlRngPErrMemory(NULL, "building parser\n");
+        xmlRngPErrMemory(NULL);
         xmlFreeDoc(copy);
         return (NULL);
     }
@@ -7525,7 +7382,7 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
      * First step is to parse the input document into an DOM/Infoset
      */
     if (ctxt->URL != NULL) {
-        doc = xmlReadFile((const char *) ctxt->URL,NULL,0);
+        doc = xmlRelaxReadFile(ctxt, (const char *) ctxt->URL);
         if (doc == NULL) {
             xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
                        "xmlRelaxNGParse: could not load %s\n", ctxt->URL,
@@ -7533,7 +7390,7 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
             return (NULL);
         }
     } else if (ctxt->buffer != NULL) {
-        doc = xmlReadMemory(ctxt->buffer, ctxt->size,NULL,NULL,0);
+        doc = xmlRelaxReadMemory(ctxt, ctxt->buffer, ctxt->size);
         if (doc == NULL) {
             xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
                        "xmlRelaxNGParse: could not parse schemas\n", NULL,
@@ -7644,6 +7501,8 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
  * @warn:  the warning callback
  * @ctx:  contextual data for the callbacks
  *
+ * DEPRECATED: Use xmlRelaxNGSetParserStructuredErrors.
+ *
  * Set the callback functions used to handle errors for a validation context
  */
 void
@@ -7838,11 +7697,13 @@ xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define)
             break;
         case XML_RELAXNG_DATATYPE:
         case XML_RELAXNG_VALUE:
-            TODO break;
+            /* TODO */
+            break;
         case XML_RELAXNG_START:
         case XML_RELAXNG_EXCEPT:
         case XML_RELAXNG_PARAM:
-            TODO break;
+            /* TODO */
+            break;
         case XML_RELAXNG_NOOP:
             xmlRelaxNGDumpDefines(output, define->content);
             break;
@@ -7971,10 +7832,6 @@ xmlRelaxNGValidateCompiledCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
     xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;
     int ret;
 
-#ifdef DEBUG_COMPILE
-    xmlGenericError(xmlGenericErrorContext,
-                    "Compiled callback for: '%s'\n", token);
-#endif
     if (ctxt == NULL) {
         fprintf(stderr, "callback on %s missing context\n", token);
         return;
@@ -7987,12 +7844,7 @@ xmlRelaxNGValidateCompiledCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
         return;
     }
-    if ((ctxt == NULL) || (define == NULL)) {
-        fprintf(stderr, "callback on %s missing info\n", token);
-        if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
-            ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
-        return;
-    } else if (define->type != XML_RELAXNG_ELEMENT) {
+    if (define->type != XML_RELAXNG_ELEMENT) {
         fprintf(stderr, "callback on %s define is not element\n", token);
         if (ctxt->errNo == XML_RELAXNG_OK)
             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
@@ -8119,7 +7971,7 @@ xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec)
                                                         sizeof
                                                         (xmlRegExecCtxtPtr));
         if (ctxt->elemTab == NULL) {
-            xmlRngVErrMemory(ctxt, "validating\n");
+            xmlRngVErrMemory(ctxt);
             return (-1);
         }
     }
@@ -8130,7 +7982,7 @@ xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec)
                                                          sizeof
                                                          (xmlRegExecCtxtPtr));
         if (ctxt->elemTab == NULL) {
-            xmlRngVErrMemory(ctxt, "validating\n");
+            xmlRngVErrMemory(ctxt);
             return (-1);
         }
     }
@@ -8186,10 +8038,6 @@ xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec
     xmlNodePtr node;
     int ret = 0, oldflags;
 
-#ifdef DEBUG_PROGRESSIVE
-    xmlGenericError(xmlGenericErrorContext,
-                    "Progressive callback for: '%s'\n", token);
-#endif
     if (ctxt == NULL) {
         fprintf(stderr, "callback on %s missing context\n", token);
         return;
@@ -8205,13 +8053,7 @@ xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec
         ctxt->pstate = -1;
         return;
     }
-    if ((ctxt == NULL) || (define == NULL)) {
-        fprintf(stderr, "callback on %s missing info\n", token);
-        if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
-            ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
-        ctxt->pstate = -1;
-        return;
-    } else if (define->type != XML_RELAXNG_ELEMENT) {
+    if (define->type != XML_RELAXNG_ELEMENT) {
         fprintf(stderr, "callback on %s define is not element\n", token);
         if (ctxt->errNo == XML_RELAXNG_OK)
             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
@@ -8229,11 +8071,6 @@ xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec
         /*
          * this node cannot be validated in a streamable fashion
          */
-#ifdef DEBUG_PROGRESSIVE
-        xmlGenericError(xmlGenericErrorContext,
-                        "Element '%s' validation is not streamable\n",
-                        token);
-#endif
         ctxt->pstate = 0;
         ctxt->pdef = define;
         return;
@@ -8330,9 +8167,6 @@ xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt,
     if ((ctxt == NULL) || (elem == NULL))
         return (-1);
 
-#ifdef DEBUG_PROGRESSIVE
-    xmlGenericError(xmlGenericErrorContext, "PushElem %s\n", elem->name);
-#endif
     if (ctxt->elem == 0) {
         xmlRelaxNGPtr schema;
         xmlRelaxNGGrammarPtr grammar;
@@ -8381,11 +8215,6 @@ xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt,
         else
             ret = 1;
     }
-#ifdef DEBUG_PROGRESSIVE
-    if (ret < 0)
-        xmlGenericError(xmlGenericErrorContext, "PushElem %s failed\n",
-                        elem->name);
-#endif
     return (ret);
 }
 
@@ -8408,10 +8237,6 @@ xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt,
     if ((ctxt == NULL) || (ctxt->elem == NULL) || (data == NULL))
         return (-1);
 
-#ifdef DEBUG_PROGRESSIVE
-    xmlGenericError(xmlGenericErrorContext, "CDATA %s %d\n", data, len);
-#endif
-
     while (*data != 0) {
         if (!IS_BLANK_CH(*data))
             break;
@@ -8423,9 +8248,6 @@ xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt,
     ret = xmlRegExecPushString(ctxt->elem, BAD_CAST "#text", ctxt);
     if (ret < 0) {
         VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, BAD_CAST " TODO ");
-#ifdef DEBUG_PROGRESSIVE
-        xmlGenericError(xmlGenericErrorContext, "CDATA failed\n");
-#endif
 
         return (-1);
     }
@@ -8452,9 +8274,6 @@ xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt,
 
     if ((ctxt == NULL) || (ctxt->elem == NULL) || (elem == NULL))
         return (-1);
-#ifdef DEBUG_PROGRESSIVE
-    xmlGenericError(xmlGenericErrorContext, "PopElem %s\n", elem->name);
-#endif
     /*
      * verify that we reached a terminal state of the content model.
      */
@@ -8472,11 +8291,6 @@ xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt,
         ret = 1;
     }
     xmlRegFreeExecCtxt(exec);
-#ifdef DEBUG_PROGRESSIVE
-    if (ret < 0)
-        xmlGenericError(xmlGenericErrorContext, "PopElem %s failed\n",
-                        elem->name);
-#endif
     return (ret);
 }
 
@@ -8501,9 +8315,6 @@ xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt,
 
     if ((ctxt == NULL) || (ctxt->pdef == NULL) || (elem == NULL))
         return (-1);
-#ifdef DEBUG_PROGRESSIVE
-    xmlGenericError(xmlGenericErrorContext, "FullElem %s\n", elem->name);
-#endif
     state = xmlRelaxNGNewValidState(ctxt, elem->parent);
     if (state == NULL) {
         return (-1);
@@ -8518,11 +8329,6 @@ xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt,
         ret = 1;
     xmlRelaxNGFreeValidState(ctxt, ctxt->state);
     ctxt->state = NULL;
-#ifdef DEBUG_PROGRESSIVE
-    if (ret < 0)
-        xmlGenericError(xmlGenericErrorContext, "FullElem %s failed\n",
-                        elem->name);
-#endif
     return (ret);
 }
 
@@ -8588,9 +8394,9 @@ xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar * str)
         tmp++;
     len = tmp - str;
 
-    ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar));
+    ret = (xmlChar *) xmlMallocAtomic(len + 1);
     if (ret == NULL) {
-        xmlRngVErrMemory(ctxt, "validating\n");
+        xmlRngVErrMemory(ctxt);
         return (NULL);
     }
     p = ret;
@@ -8852,10 +8658,6 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
                 xmlRelaxNGDefinePtr list = define->content;
                 xmlChar *oldvalue, *oldend, *val, *cur;
 
-#ifdef DEBUG_LIST
-                int nb_values = 0;
-#endif
-
                 oldvalue = ctxt->state->value;
                 oldend = ctxt->state->endvalue;
 
@@ -8872,20 +8674,11 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
                     if (IS_BLANK_CH(*cur)) {
                         *cur = 0;
                         cur++;
-#ifdef DEBUG_LIST
-                        nb_values++;
-#endif
                         while (IS_BLANK_CH(*cur))
                             *cur++ = 0;
                     } else
                         cur++;
                 }
-#ifdef DEBUG_LIST
-                xmlGenericError(xmlGenericErrorContext,
-                                "list value: '%s' found %d items\n",
-                                oldvalue, nb_values);
-                nb_values = 0;
-#endif
                 ctxt->state->endvalue = cur;
                 cur = val;
                 while ((*cur == 0) && (cur != ctxt->state->endvalue))
@@ -8898,16 +8691,8 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
                         ctxt->state->value = NULL;
                     ret = xmlRelaxNGValidateValue(ctxt, list);
                     if (ret != 0) {
-#ifdef DEBUG_LIST
-                        xmlGenericError(xmlGenericErrorContext,
-                                        "Failed to validate value: '%s' with %d rule\n",
-                                        ctxt->state->value, nb_values);
-#endif
                         break;
                     }
-#ifdef DEBUG_LIST
-                    nb_values++;
-#endif
                     list = list->next;
                 }
 
@@ -9022,7 +8807,8 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
             }
             break;
         default:
-            TODO ret = -1;
+            /* TODO */
+            ret = -1;
     }
     return (ret);
 }
@@ -9110,7 +8896,9 @@ xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt,
         }
         return (0);
     } else {
-    TODO}
+        /* TODO */
+        return (0);
+    }
     return (1);
 }
 
@@ -9171,11 +8959,6 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
         } else {
             ret = -1;
         }
-#ifdef DEBUG
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlRelaxNGValidateAttribute(%s): %d\n",
-                        define->name, ret);
-#endif
     } else {
         for (i = 0; i < ctxt->state->nbAttrs; i++) {
             tmp = ctxt->state->attrs[i];
@@ -9208,17 +8991,6 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
         } else {
             ret = -1;
         }
-#ifdef DEBUG
-        if (define->ns != NULL) {
-            xmlGenericError(xmlGenericErrorContext,
-                            "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n",
-                            define->ns, ret);
-        } else {
-            xmlGenericError(xmlGenericErrorContext,
-                            "xmlRelaxNGValidateAttribute(anyName): %d\n",
-                            ret);
-        }
-#endif
     }
 
     return (ret);
@@ -9378,13 +9150,13 @@ xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt,
      */
     list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
     if (list == NULL) {
-        xmlRngVErrMemory(ctxt, "validating\n");
+        xmlRngVErrMemory(ctxt);
         return (-1);
     }
     memset(list, 0, nbgroups * sizeof(xmlNodePtr));
     lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
     if (lasts == NULL) {
-        xmlRngVErrMemory(ctxt, "validating\n");
+        xmlRngVErrMemory(ctxt);
         return (-1);
     }
     memset(lasts, 0, nbgroups * sizeof(xmlNodePtr));
@@ -9761,7 +9533,8 @@ xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
             ctxt->flags = oldflags;
         }
     } else {
-        TODO ret = -1;
+        /* TODO */
+        ret = -1;
     }
     return (ret);
 }
@@ -9900,18 +9673,6 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
     } else {
         node = NULL;
     }
-#ifdef DEBUG
-    for (i = 0; i < ctxt->depth; i++)
-        xmlGenericError(xmlGenericErrorContext, " ");
-    xmlGenericError(xmlGenericErrorContext,
-                    "Start validating %s ", xmlRelaxNGDefName(define));
-    if (define->name != NULL)
-        xmlGenericError(xmlGenericErrorContext, "%s ", define->name);
-    if ((node != NULL) && (node->name != NULL))
-        xmlGenericError(xmlGenericErrorContext, "on %s\n", node->name);
-    else
-        xmlGenericError(xmlGenericErrorContext, "\n");
-#endif
     ctxt->depth++;
     switch (define->type) {
         case XML_RELAXNG_EMPTY:
@@ -10030,11 +9791,6 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
                 ctxt->states = tmpstates;
                 xmlRelaxNGFreeValidState(ctxt, nstate);
 
-#ifdef DEBUG_COMPILE
-                xmlGenericError(xmlGenericErrorContext,
-                                "Validating content of '%s' : %d\n",
-                                define->name, tmp);
-#endif
                 if (tmp != 0)
                     ret = -1;
 
@@ -10152,21 +9908,6 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
                     xmlRelaxNGPopErrors(ctxt, errNr);
             }
 
-#ifdef DEBUG
-            xmlGenericError(xmlGenericErrorContext,
-                            "xmlRelaxNGValidateDefinition(): validated %s : %d",
-                            node->name, ret);
-            if (oldstate == NULL)
-                xmlGenericError(xmlGenericErrorContext, ": no state\n");
-            else if (oldstate->seq == NULL)
-                xmlGenericError(xmlGenericErrorContext, ": done\n");
-            else if (oldstate->seq->type == XML_ELEMENT_NODE)
-                xmlGenericError(xmlGenericErrorContext, ": next elem %s\n",
-                                oldstate->seq->name);
-            else
-                xmlGenericError(xmlGenericErrorContext, ": next %s %d\n",
-                                oldstate->seq->name, oldstate->seq->type);
-#endif
             break;
         case XML_RELAXNG_OPTIONAL:{
                 errNr = ctxt->errNr;
@@ -10503,7 +10244,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
                 if (content == NULL) {
                     content = xmlStrdup(BAD_CAST "");
                     if (content == NULL) {
-                        xmlRngVErrMemory(ctxt, "validating\n");
+                        xmlRngVErrMemory(ctxt);
                         ret = -1;
                         break;
                     }
@@ -10546,7 +10287,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
                 if (content == NULL) {
                     content = xmlStrdup(BAD_CAST "");
                     if (content == NULL) {
-                        xmlRngVErrMemory(ctxt, "validating\n");
+                        xmlRngVErrMemory(ctxt);
                         ret = -1;
                         break;
                     }
@@ -10597,7 +10338,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
                 if (content == NULL) {
                     content = xmlStrdup(BAD_CAST "");
                     if (content == NULL) {
-                        xmlRngVErrMemory(ctxt, "validating\n");
+                        xmlRngVErrMemory(ctxt);
                         ret = -1;
                         break;
                     }
@@ -10621,22 +10362,11 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
             }
         case XML_RELAXNG_EXCEPT:
         case XML_RELAXNG_PARAM:
-            TODO ret = -1;
+            /* TODO */
+            ret = -1;
             break;
     }
     ctxt->depth--;
-#ifdef DEBUG
-    for (i = 0; i < ctxt->depth; i++)
-        xmlGenericError(xmlGenericErrorContext, " ");
-    xmlGenericError(xmlGenericErrorContext,
-                    "Validating %s ", xmlRelaxNGDefName(define));
-    if (define->name != NULL)
-        xmlGenericError(xmlGenericErrorContext, "%s ", define->name);
-    if (ret == 0)
-        xmlGenericError(xmlGenericErrorContext, "succeeded\n");
-    else
-        xmlGenericError(xmlGenericErrorContext, "failed\n");
-#endif
     return (ret);
 }
 
@@ -10660,7 +10390,8 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
      * We should NOT have both ctxt->state and ctxt->states
      */
     if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
-        TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
+        /* TODO */
+        xmlRelaxNGFreeValidState(ctxt, ctxt->state);
         ctxt->state = NULL;
     }
 
@@ -10672,7 +10403,8 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
         }
         ret = xmlRelaxNGValidateState(ctxt, define);
         if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
-            TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
+            /* TODO */
+            xmlRelaxNGFreeValidState(ctxt, ctxt->state);
             ctxt->state = NULL;
         }
         if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) {
@@ -10697,7 +10429,8 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
          * We should NOT have both ctxt->state and ctxt->states
          */
         if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
-            TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
+            /* TODO */
+            xmlRelaxNGFreeValidState(ctxt, ctxt->state);
             ctxt->state = NULL;
         }
         if (ret == 0) {
@@ -10763,7 +10496,8 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
         }
     }
     if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
-        TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
+        /* TODO */
+        xmlRelaxNGFreeValidState(ctxt, ctxt->state);
         ctxt->state = NULL;
     }
     return (ret);
@@ -10835,23 +10569,22 @@ xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
     }
     if (ret != 0)
         xmlRelaxNGDumpValidError(ctxt);
-#ifdef DEBUG
-    else if (ctxt->errNr != 0) {
-        ctxt->error(ctxt->userData,
-                    "%d Extra error messages left on stack !\n",
-                    ctxt->errNr);
-        xmlRelaxNGDumpValidError(ctxt);
-    }
-#endif
 #ifdef LIBXML_VALID_ENABLED
     if (ctxt->idref == 1) {
         xmlValidCtxt vctxt;
 
         memset(&vctxt, 0, sizeof(xmlValidCtxt));
         vctxt.valid = 1;
-        vctxt.error = ctxt->error;
-        vctxt.warning = ctxt->warning;
-        vctxt.userData = ctxt->userData;
+
+        if (ctxt->error == NULL) {
+            vctxt.error = xmlGenericError;
+            vctxt.warning = xmlGenericError;
+            vctxt.userData = xmlGenericErrorContext;
+        } else {
+            vctxt.error = ctxt->error;
+            vctxt.warning = ctxt->warning;
+            vctxt.userData = ctxt->userData;
+        }
 
         if (xmlValidateDocumentFinal(&vctxt, doc) != 1)
             ret = -1;
@@ -10938,13 +10671,11 @@ xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema)
 
     ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt));
     if (ret == NULL) {
-        xmlRngVErrMemory(NULL, "building context\n");
+        xmlRngVErrMemory(NULL);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlRelaxNGValidCtxt));
     ret->schema = schema;
-    ret->error = xmlGenericError;
-    ret->userData = xmlGenericErrorContext;
     ret->errNr = 0;
     ret->errMax = 0;
     ret->err = NULL;
@@ -11007,6 +10738,8 @@ xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt)
  * @warn: the warning function
  * @ctx: the functions context
  *
+ * DEPRECATED: Use xmlRelaxNGSetValidStructuredErrors.
+ *
  * Set the error and warning callback information
  */
 void
diff --git a/rngparser.c b/rngparser.c
new file mode 100644
index 0000000000000000000000000000000000000000..799a60e6347a3ba15ab5da45b99808e4a64ebea8
--- /dev/null
+++ b/rngparser.c
@@ -0,0 +1,1588 @@
+/**
+ * rngparser.c: parser for the Relax-NG compact syntax.
+ *
+ * Based on:
+ *   RELAX NG Compact Syntax
+ *   Committee Specification 21 November 2002
+ *   http://www.oasis-open.org/committees/relax-ng/compact-20021121.html
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+#include <string.h>
+
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/relaxng.h>
+#include <libxml/dict.h>
+
+#define MAX_TOKEN 10
+
+typedef enum {
+    CRNG_NONE = 0,
+    CRNG_OP = 1,
+    CRNG_KEYWORD,
+    CRNG_IDENTIFIER,
+    CRNG_LITERAL_SEGMENT,
+    CRNG_CNAME,
+    CRNG_QNAME,
+    CRNG_NSNAME,
+    CRNG_DOCUMENTATION
+} xmlCRNGTokType;
+
+typedef enum {
+    CRNG_OKAY = 0,
+    CRNG_MEMORY_ERROR,
+    CRNG_INVALID_CHAR_ERROR,
+    CRNG_END_ERROR,
+    CRNG_ENCODING_ERROR
+} xmlCRNGError;
+
+typedef enum {
+    XML_CRNG_ERROR = -1,
+    XML_CRNG_OK = 0,
+    XML_CRNG_EOF = 1
+} xmlCRelaxNGParserState;
+
+typedef struct _token _token;
+typedef _token *tokenPtr;
+struct _token {
+    xmlCRNGTokType toktype;
+    int toklen;
+    const xmlChar *token;
+    const xmlChar *prefix;
+};
+
+typedef struct _xmlCRelaxNGParserCtxt xmlCRelaxNGParserCtxt;
+typedef xmlCRelaxNGParserCtxt *xmlCRelaxNGParserCtxtPtr;
+struct _xmlCRelaxNGParserCtxt {
+    void *userData;			/* user specific data block */
+    xmlRelaxNGValidityErrorFunc error;	/* the callback in case of errors */
+    xmlRelaxNGValidityWarningFunc warning;/* the callback in case of warning */
+    xmlRelaxNGValidErr err;
+
+    const xmlChar *compact;
+    const xmlChar *end;
+    const xmlChar *cur;
+    int isElem;
+    int lineno;
+    const xmlChar *linestart;
+    const char *filename;
+
+    int  nbTokens;
+    int  firstToken;
+    _token tokens[MAX_TOKEN];
+    int  totalToken;
+
+    xmlCRelaxNGParserState state;
+
+    int            nbErrors;
+
+    xmlDocPtr      res;			/* the result */
+    xmlNodePtr     ins;			/* the current insertion node */
+
+    xmlNsPtr       nsDef;
+    tokenPtr token;
+
+    xmlHashTablePtr namespaces;
+    xmlHashTablePtr datatypes;
+
+    /*
+     * dictionary and keywords
+     */
+    xmlDictPtr     dict;
+    const xmlChar *key_attribute;
+    const xmlChar *key_default;
+    const xmlChar *key_datatypes;
+    const xmlChar *key_div;
+    const xmlChar *key_element;
+    const xmlChar *key_empty;
+    const xmlChar *key_external;
+    const xmlChar *key_grammar;
+    const xmlChar *key_include;
+    const xmlChar *key_inherit;
+    const xmlChar *key_list;
+    const xmlChar *key_mixed;
+    const xmlChar *key_namespace;
+    const xmlChar *key_notAllowed;
+    const xmlChar *key_parent;
+    const xmlChar *key_start;
+    const xmlChar *key_string;
+    const xmlChar *key_text;
+    const xmlChar *key_token;
+    const xmlChar *key_equal;
+    const xmlChar *key_orequal;
+    const xmlChar *key_andequal;
+    const xmlChar *key_combine;
+    const xmlChar *key_or;
+    const xmlChar *key_comma;
+    const xmlChar *key_and;
+    const xmlChar *key_choice;
+    const xmlChar *key_group;
+    const xmlChar *key_interleave;
+    const xmlChar *key_ref;
+    const xmlChar *key_define;
+
+    /* results */
+    xmlDocPtr doc;	/* the resulting doc */
+    xmlNodePtr insert;	/* the insertion point */
+    xmlAttrPtr attrs;   /* pending attributes */
+};
+
+static const xmlChar *xmlCRelaxNGInherit = BAD_CAST "Inherit string";
+static const xmlChar *xmlCRelaxNGDefault = BAD_CAST "Default string";
+
+#define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)
+/**
+ * IS_BLANK:
+ * @c:  an UNICODE value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ * [3] S ::= (#x20 | #x9 | #xD | #xA)+
+ */
+#ifndef IS_BLANK
+#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) ||	\
+                     ((c) == 0x0D))
+#endif
+#define IS_SEPARATOR(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \
+                     ((c) == 0x0D) || (c == '#'))
+
+#define CRNG_ERROR0(X)							\
+    { xmlCRNGErr(ctxt, X, NULL); return(0); }
+#define CRNG_ERROR(X)							\
+    { xmlCRNGErr(ctxt, X, NULL); }
+
+#define CRNG_MEM_ERROR0()						\
+    { xmlCRNGErr(ctxt, CRNG_MEMORY_ERROR, NULL); return(0); }
+#define CRNG_MEM_ERROR()						\
+    { xmlCRNGErr(ctxt, CRNG_MEMORY_ERROR, NULL); }
+
+#define ERROR(str) xmlCRNGErr(ctxt, 0, str);
+
+static void
+xmlCRNGErr(xmlCRelaxNGParserCtxtPtr ctxt, int err_no, const char *err_msg) {
+    const xmlChar *cur;
+    xmlChar buffer[150];
+    int i, l;
+
+    if (ctxt != NULL) {
+        if (ctxt->filename != NULL)
+	    fprintf(stderr, "%s:%d ", ctxt->filename, ctxt->lineno);
+    }
+    if (err_msg != NULL) {
+	fprintf(stderr, "error: %s\n", err_msg);
+    } else if (err_no != 0)
+	fprintf(stderr, "error %d\n", err_no);
+    cur = ctxt->cur;
+    while ((*cur != '\n') && (*cur != '\r') && (ctxt->cur - cur < 80)) cur--;
+    l = ctxt->cur - cur;
+    cur++;
+    for (i = 0; i < 100;i++) {
+        if ((*cur == '\n') || (*cur == '\r')) break;
+        buffer[i] = *cur++;
+    }
+    buffer[i] = 0;
+    fprintf(stderr, "%s\n", buffer);
+    for (i = 0; i < l;i++) buffer[i] = ' ';
+    buffer[i++] = '^';
+    buffer[i++] = 0;
+    fprintf(stderr, "%s\n", buffer);
+}
+
+/**
+ * IS_OP
+ * @c:  an UNICODE value (int)
+ *
+ * Macro to check for operator value
+ */
+#ifndef IS_OP
+#define IS_OP(c) (((c) == ',') || ((c) == '&') || ((c) == '|') ||	\
+		  ((c) == '?') || ((c) == '-') || ((c) == '*') ||	\
+		  ((c) == '{') || ((c) == '}') || ((c) == '(') ||	\
+		  ((c) == ')') || ((c) == '+') || ((c) == '=') ||	\
+		  ((c) == ':'))
+#endif
+
+static int
+xmlCRNGIsKeyword(xmlCRelaxNGParserCtxtPtr ctxt, const xmlChar *str) {
+    if ((str == ctxt->key_attribute) ||
+        (str == ctxt->key_default) ||
+        (str == ctxt->key_datatypes) ||
+        (str == ctxt->key_div) ||
+        (str == ctxt->key_element) ||
+        (str == ctxt->key_empty) ||
+        (str == ctxt->key_external) ||
+        (str == ctxt->key_grammar) ||
+        (str == ctxt->key_include) ||
+        (str == ctxt->key_inherit) ||
+        (str == ctxt->key_list) ||
+        (str == ctxt->key_mixed) ||
+        (str == ctxt->key_namespace) ||
+        (str == ctxt->key_notAllowed) ||
+        (str == ctxt->key_parent) ||
+        (str == ctxt->key_start) ||
+        (str == ctxt->key_string) ||
+        (str == ctxt->key_text) ||
+        (str == ctxt->key_token))
+	return(1);
+    return(0);
+
+}
+
+/*
+ * xmlCRNGNextToken:
+ * ctxt:  a compact RNG parser context
+ *
+ * Scan the schema to get the next token
+ *
+ * Return 0 if success and -1 in case of error
+ */
+
+static int
+xmlCRNGNextToken(xmlCRelaxNGParserCtxtPtr ctxt) {
+    const xmlChar *cur;
+    tokenPtr token;
+
+    if (ctxt == NULL) return(-1);
+    if (ctxt->nbTokens >= MAX_TOKEN) return(-1);
+    token = &(ctxt->tokens[(ctxt->firstToken + ctxt->nbTokens) % MAX_TOKEN]);
+    token->toktype = CRNG_NONE;
+
+    if (ctxt->cur == NULL) {
+        ctxt->cur = ctxt->compact;
+    }
+retry:
+    if (ctxt->cur >= ctxt->end) {
+	ctxt->state = XML_CRNG_EOF;
+	return(-1);
+    }
+    while ((ctxt->cur < ctxt->end) &&
+           (IS_BLANK(*ctxt->cur))) ctxt->cur++;
+    if (ctxt->cur >= ctxt->end) {
+	ctxt->state = XML_CRNG_EOF;
+	return(-1);
+    }
+    if (*ctxt->cur == '#') {
+        cur = ctxt->cur;
+	cur++;
+	while ((cur < ctxt->end) && (*cur != '\n') && (*cur != '\r'))
+	    cur++;
+        ctxt->cur = cur;
+	goto retry;
+    } else if (*ctxt->cur == '"') {
+        /* string, check for '"""' */
+	ctxt->cur++;
+	if (ctxt->cur >= ctxt->end) goto eof;
+	cur = ctxt->cur;
+        if ((ctxt->end - ctxt->end > 2) &&
+	    (*cur == '"') && (cur[1] == '"')) {
+	    /* TODO */
+	} else {
+	    while ((cur < ctxt->end) && (*cur != '"')) cur++;
+	    if (cur >= ctxt->end) goto eof;
+	    token->toklen = cur - ctxt->cur;
+	    token->token = xmlDictLookup(ctxt->dict, ctxt->cur, token->toklen);
+	    token->toktype = CRNG_LITERAL_SEGMENT;
+	    token->prefix = NULL;
+	    cur++;
+	    ctxt->cur = cur;
+	}
+    } else if (*ctxt->cur == '\'') {
+        /* string, check for "'''" */
+	/* TODO */
+    } else if ((IS_OP(*ctxt->cur)) || (*ctxt->cur == ':')) {
+        cur = ctxt->cur;
+	cur++;
+	if ((cur < ctxt->end) &&
+	    (((*cur == '=') &&
+	      ((*ctxt->cur == '|') || (*ctxt->cur == '&'))) ||
+	     ((*cur == '*') && (*ctxt->cur == ':')))) {
+	    token->toklen = 2;
+	} else {
+	    token->toklen = 1;
+	}
+	token->token = xmlDictLookup(ctxt->dict, ctxt->cur, token->toklen);
+	token->toktype = CRNG_OP;
+	token->prefix = NULL;
+	ctxt->cur += token->toklen;
+    } else {
+        int escape = 0;
+
+        cur = ctxt->cur;
+        if (*cur == '\\') {
+	    escape = 1;
+	    cur++;
+	    ctxt->cur++;
+	}
+	while ((cur < ctxt->end) &&
+	       (!(IS_SEPARATOR(*cur))) && (!(IS_OP(*cur)))) cur++;
+
+	token->toklen = cur - ctxt->cur;
+	token->token = xmlDictLookup(ctxt->dict, ctxt->cur, token->toklen);
+	token->prefix = NULL;
+	ctxt->cur = cur;
+	if ((escape == 0) && (xmlCRNGIsKeyword(ctxt, token->token)))
+	    token->toktype = CRNG_KEYWORD;
+	else {
+	    token->toktype = CRNG_IDENTIFIER;
+	}
+	if (*ctxt->cur == ':') {
+	    ctxt->cur++;
+	    if (*ctxt->cur == '*') {
+		ctxt->cur++;
+		token->toktype = CRNG_NSNAME;
+	    } else {
+	        cur = ctxt->cur;
+		while ((cur < ctxt->end) &&
+		       (!(IS_SEPARATOR(*cur))) && (!(IS_OP(*cur)))) cur++;
+		token->prefix = token->token;
+		token->toklen = cur - ctxt->cur;
+		token->token = xmlDictLookup(ctxt->dict, ctxt->cur,
+		                             token->toklen);
+		ctxt->cur = cur;
+		if (xmlValidateNCName(token->token, 0) == 0)
+		    token->toktype = CRNG_QNAME;
+		else {
+		    /* TODO: sounds like an error ! */
+		    token->toktype = CRNG_IDENTIFIER;
+		}
+	    }
+	}
+    }
+    ctxt->nbTokens++;
+    return(0);
+eof:
+    ctxt->state = XML_CRNG_EOF;
+    CRNG_ERROR(CRNG_END_ERROR);
+    return(-1);
+}
+
+/**
+ * xmlParseCRNGGetToken:
+ * @ctxt: a compact RNG parser context
+ * @no: the number of the token from 1 for the first one
+ *      and 2, 3 ... for read-ahead
+ *
+ * Token reading interface
+ *
+ * returns a pointer to the new token, or NULL in case of error or EOF
+ */
+static tokenPtr
+xmlParseCRNGGetToken(xmlCRelaxNGParserCtxtPtr ctxt, int no) {
+    tokenPtr ret;
+    int res;
+
+    if ((no <= 0) || (no >= MAX_TOKEN)) return(NULL);
+    no--;
+    while (ctxt->nbTokens <= no) {
+        res = xmlCRNGNextToken(ctxt);
+	if (res < 0)
+	    return(NULL);
+    }
+    ret = &(ctxt->tokens[(ctxt->firstToken + no) % MAX_TOKEN]);
+    return(ret);
+}
+
+/**
+ * xmlParseCRNGDropTokens:
+ * @ctxt: a compact RNG parser context
+ * @nr: the number of token marked as read
+ *
+ * mark a number of token as read and consumed.
+ *
+ * Returns -1 in case of error and 0 otherwise
+ */
+static int
+xmlParseCRNGDropTokens(xmlCRelaxNGParserCtxtPtr ctxt, int nr) {
+    if ((nr <= 0) || (nr >= MAX_TOKEN)) return(-1);
+    while ((ctxt->nbTokens >0) && (nr > 0)) {
+        ctxt->firstToken++;
+	nr--;
+	ctxt->nbTokens--;
+	ctxt->totalToken++;
+	if (ctxt->totalToken == 384)
+	    fprintf(stderr, "found\n");
+    }
+    ctxt->firstToken = ctxt->firstToken % MAX_TOKEN;
+    return(0);
+}
+
+static void
+xmlParseCRNGTokenize(xmlCRelaxNGParserCtxtPtr ctxt) {
+    tokenPtr token;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    while (token != NULL) {
+        switch (token->toktype) {
+            case CRNG_NONE: printf("none"); break;
+            case CRNG_OP: printf("op"); break;
+            case CRNG_KEYWORD: printf("keyword"); break;
+            case CRNG_IDENTIFIER: printf("identifier"); break;
+            case CRNG_LITERAL_SEGMENT: printf("literal"); break;
+            case CRNG_CNAME: printf("cname"); break;
+            case CRNG_QNAME: printf("qname"); break;
+            case CRNG_NSNAME: printf("nsname"); break;
+            case CRNG_DOCUMENTATION: printf("doc"); break;
+	}
+        printf(":%s\n", token->token);
+	xmlParseCRNGDropTokens(ctxt, 1);
+	token = xmlParseCRNGGetToken(ctxt, 1);
+    }
+}
+
+/**
+ * xmlParseCRNG_attribute:
+ * @ctxt: a compact RNG parser context
+ * @name: the attribute name
+ * @ns: the attribute namespace
+ * @value: the attribute value
+ *
+ * implements attribute of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_attribute(xmlCRelaxNGParserCtxtPtr ctxt,
+                       const xmlChar *name,
+                       xmlNsPtr ns,
+		       const xmlChar *value)
+{
+    xmlAttrPtr attr;
+
+    attr = xmlNewNsPropEatName(NULL, ns, (xmlChar *) name, value);
+    if (attr == NULL) CRNG_MEM_ERROR0();
+    attr->next = ctxt->attrs;
+    if (ctxt->attrs != NULL)
+        ctxt->attrs->prev = attr;
+    ctxt->attrs = attr;
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_bindPrefix:
+ * @ctxt: a compact RNG parser context
+ * @prefix: the namespace prefix or NULL
+ * @namespace: the namespace name
+ *
+ * implements bindPrefix of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_bindPrefix(xmlCRelaxNGParserCtxtPtr ctxt,
+                        const xmlChar *prefix,
+			const xmlChar *namespace)
+{
+    int ret;
+
+    if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))  &&
+        (!xmlStrEqual(namespace, XML_XML_NAMESPACE))) {
+	ERROR("The \"xml\" prefix must be bound to \"http://www.w3.org/XML/1998/namespace\"");
+	return(-1);
+    } else if ((xmlStrEqual(namespace, XML_XML_NAMESPACE)) &&
+               (!xmlStrEqual(prefix, BAD_CAST "xml"))) {
+	ERROR("The \"http://www.w3.org/XML/1998/namespace\" name must be bound to \"xml\" prefix");
+	return(-1);
+    }
+    if (ctxt->namespaces == NULL)
+        ctxt->namespaces = xmlHashCreate(10);
+    if (ctxt->namespaces == NULL) {
+        ERROR("Failed to create namespace hash table");
+	return(-1);
+    }
+    if (prefix == NULL)
+        ret = xmlHashAddEntry(ctxt->namespaces, xmlCRelaxNGDefault,
+	                      (void *) namespace);
+    else
+        ret = xmlHashAddEntry(ctxt->namespaces, prefix,
+	                      (void *) namespace);
+    if (ret < 0) {
+        if (prefix == NULL) {
+	    ERROR("Redefinition of default namespace");
+	} else {
+	    ERROR("Redefinition of namespace");
+	}
+	return(-1);
+    }
+
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_bindDatatypePrefix:
+ * @ctxt: a compact RNG parser context
+ * @prefix: the datatype prefix
+ * @namespace: the datatype identifier
+ *
+ * implements bindDatatypePrefix of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_bindDatatypePrefix(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
+                                const xmlChar *prefix,
+			        const xmlChar *namespace)
+{
+    int ret;
+
+    if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xsd"))  &&
+        (!xmlStrEqual(namespace,
+		  BAD_CAST "http://www.w3.org/2001/XMLSchema-datatypes"))) {
+	ERROR("The \"xsd\" prefix must be bound to \"http://www.w3.org/2001/XMLSchema-datatypes\"");
+	return(-1);
+    }
+    if (ctxt->datatypes == NULL)
+        ctxt->datatypes = xmlHashCreate(10);
+    if (ctxt->datatypes == NULL) {
+        ERROR("Failed to create namespace hash table");
+	return(-1);
+    }
+    ret = xmlHashAddEntry(ctxt->datatypes, prefix,
+                          (void *) namespace);
+    if (ret < 0) {
+	ERROR("Redefinition of datatype");
+	return(-1);
+    }
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_lookupPrefix:
+ * @ctxt: a compact RNG parser context
+ * @prefix: the namespace prefix or NULL
+ *
+ * implements lookupPrefix of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns the prefix in case of success or NULL in case of error
+ */
+static const xmlChar *
+xmlParseCRNG_lookupPrefix(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
+                        const xmlChar *prefix)
+{
+    const xmlChar *ret;
+
+    if (prefix == NULL)
+        ret = xmlHashLookup(ctxt->namespaces, xmlCRelaxNGDefault);
+    else
+        ret = xmlHashLookup(ctxt->namespaces, prefix);
+    return(ret);
+}
+
+/**
+ * xmlParseCRNG_lookupDatatypePrefix:
+ * @ctxt: a compact RNG parser context
+ * @prefix: the namespace prefix or NULL
+ *
+ * implements lookupDatatypePrefix of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns the prefix in case of success or NULL in case of error
+ */
+static const xmlChar *
+xmlParseCRNG_lookupDatatypePrefix(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
+                        const xmlChar *prefix)
+{
+    const xmlChar *ret;
+    ret = xmlHashLookup(ctxt->datatypes, prefix);
+    return(ret);
+}
+
+/**
+ * xmlParseCRNG_datatypeAttributes:
+ * @ctxt: a compact RNG parser context
+ * @prefix: the namespace prefix or NULL
+ *
+ * implements lookupPrefix of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns the prefix in case of success or NULL in case of error
+ */
+static xmlAttrPtr
+xmlParseCRNG_datatypeAttributes(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
+                        const xmlChar *library, const xmlChar *type)
+{
+    xmlAttrPtr lib, typ;
+
+    lib = xmlNewNsProp(NULL, NULL, BAD_CAST "datatypeLibrary", library);
+    if (lib == NULL) {
+        CRNG_MEM_ERROR();
+	return(NULL);
+    }
+    typ = xmlNewNsProp(NULL, NULL, BAD_CAST "type", type);
+    if (typ == NULL) {
+        CRNG_MEM_ERROR();
+	return(lib);
+    }
+    lib->next = typ;
+
+    return(lib);
+}
+
+/**
+ * xmlParseCRNG_XXX:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse XXX of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_XXX(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
+{
+    return(0);
+}
+
+static int xmlParseCRNG_pattern(xmlCRelaxNGParserCtxtPtr ctxt);
+static int xmlParseCRNG_nameClass(xmlCRelaxNGParserCtxtPtr ctxt);
+
+/**
+ * xmlParseCRNG_params:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse params of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_params(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
+{
+    /* TODO */
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_exceptNameClass:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse exceptNameClass of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_exceptNameClass(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
+{
+    tokenPtr token;
+    xmlNodePtr insert = ctxt->insert, cur;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if ((token->toktype == CRNG_OP) &&
+        (token->token[0] == '-') && (token->token[1] == 0)) {
+	xmlParseCRNGDropTokens(ctxt, 1);
+	cur = xmlNewNode(NULL, BAD_CAST "except");
+	if (cur == NULL) CRNG_MEM_ERROR0();
+	if (ctxt->insert != NULL)
+	    xmlAddChild(ctxt->insert, cur);
+	ctxt->insert = cur;
+	xmlParseCRNG_nameClass(ctxt);
+    }
+    ctxt->insert = insert;
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_innerNameClass:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse innerNameClass of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_innerNameClass(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    tokenPtr token;
+    xmlNodePtr cur;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if (token->toktype == CRNG_OP) {
+        if ((token->token[0] == '(') && (token->token[1] == 0)) {
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    xmlParseCRNG_nameClass(ctxt);
+	    token = xmlParseCRNGGetToken(ctxt, 1);
+	    if ((token->toktype != CRNG_OP) ||
+	        (token->token[0] != ')') || (token->token[1] != 0)) {
+		ERROR("Expecting \")\" here");
+	    }
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	} else if ((token->token[0] == '*') && (token->token[1] == 0)) {
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    cur = xmlNewNode(NULL, BAD_CAST "anyName");
+	    if (cur == NULL) CRNG_MEM_ERROR0();
+	    if (ctxt->insert != NULL)
+		xmlAddChild(ctxt->insert, cur);
+	    ctxt->insert = cur;
+	    xmlParseCRNG_exceptNameClass(ctxt);
+	} else {
+	    /* TODO */
+	}
+    } else if ((token->toktype == CRNG_IDENTIFIER) ||
+               (token->toktype == CRNG_KEYWORD)) {
+	cur = xmlNewNode(NULL, BAD_CAST "name");
+	if (cur == NULL) CRNG_MEM_ERROR0();
+	if (ctxt->isElem) {
+	    xmlSetProp(cur, BAD_CAST "ns",
+	               xmlParseCRNG_lookupPrefix(ctxt, NULL));
+	} else {
+	    xmlSetProp(cur, BAD_CAST "ns", BAD_CAST "");
+	}
+	xmlNodeAddContent(cur, token->token);
+	if (ctxt->insert != NULL)
+	    xmlAddChild(ctxt->insert, cur);
+	ctxt->insert = cur;
+	xmlParseCRNGDropTokens(ctxt, 1);
+    } else if (token->toktype == CRNG_CNAME) {
+        /* TODO */
+    } else if (token->toktype == CRNG_NSNAME) {
+	cur = xmlNewNode(NULL, BAD_CAST "nsName");
+	if (cur == NULL) CRNG_MEM_ERROR0();
+        xmlSetProp(cur, BAD_CAST "ns",
+	           xmlParseCRNG_lookupPrefix(ctxt, token->token));
+	if (ctxt->insert != NULL)
+	    xmlAddChild(ctxt->insert, cur);
+	ctxt->insert = cur;
+	xmlParseCRNGDropTokens(ctxt, 1);
+	xmlParseCRNG_exceptNameClass(ctxt);
+    } else {
+        /* TODO: probably an error */
+    }
+
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_nameClass:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse nameClass of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_nameClass(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    tokenPtr token;
+    xmlNodePtr insert = ctxt->insert, last, choice;
+
+    ctxt->insert = NULL;
+    xmlParseCRNG_innerNameClass(ctxt);
+    last = ctxt->insert;
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    while ((token->toktype == CRNG_OP) &&
+        (token->token[0] == '|') && (token->token[1] == 0)) {
+	choice = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_choice);
+	xmlParseCRNGDropTokens(ctxt, 1);
+	if (choice == NULL) CRNG_MEM_ERROR0();
+	ctxt->insert = NULL;
+	xmlParseCRNG_innerNameClass(ctxt);
+	xmlAddChild(choice, last);
+	xmlAddChild(choice, ctxt->insert);
+	last = choice;
+	token = xmlParseCRNGGetToken(ctxt, 1);
+    }
+    xmlAddChild(insert, last);
+
+    ctxt->insert = insert;
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_patternBlock:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse a pattern block of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_patternBlock(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    tokenPtr token;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if ((token->toktype != CRNG_OP) ||
+	(token->token[0] != '{') || (token->token[1] != 0)) {
+	ERROR("Expecting \"{\" here");
+    }
+    xmlParseCRNGDropTokens(ctxt, 1);
+    xmlParseCRNG_pattern(ctxt);
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if ((token->toktype != CRNG_OP) ||
+	(token->token[0] != '}') || (token->token[1] != 0)) {
+	ERROR("Expecting \"}\" here");
+    }
+    xmlParseCRNGDropTokens(ctxt, 1);
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_datatype:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse datatype of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_datatype(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
+{
+    tokenPtr token;
+    xmlAttrPtr attrs = NULL;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if (token->toktype == CRNG_KEYWORD) {
+	if (token->token == ctxt->key_string) {
+	    attrs = xmlParseCRNG_datatypeAttributes(ctxt, BAD_CAST "",
+	                                            token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	} else if (token->token == ctxt->key_token) {
+	    attrs = xmlParseCRNG_datatypeAttributes(ctxt, BAD_CAST "",
+	                                            token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	} else {
+	    /* TODO: probably an error */
+	}
+    } else if (token->toktype == CRNG_LITERAL_SEGMENT) {
+	ctxt->insert = xmlNewNode(NULL, BAD_CAST "value");
+	xmlParseCRNGDropTokens(ctxt, 1);
+	if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	xmlNodeAddContent(ctxt->insert, token->token);
+    } else if (token->toktype == CRNG_QNAME) {
+	attrs = xmlParseCRNG_datatypeAttributes(ctxt,
+	            xmlParseCRNG_lookupDatatypePrefix(ctxt, token->prefix),
+		    token->token);
+    } else {
+        /* TODO */
+    }
+    if (attrs != NULL) {
+	token = xmlParseCRNGGetToken(ctxt, 1);
+	if (token->toktype == CRNG_LITERAL_SEGMENT) {
+	    ctxt->insert = xmlNewNode(NULL, BAD_CAST "value");
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) {
+	        xmlFreePropList(attrs);
+		CRNG_MEM_ERROR0();
+	    }
+	    ctxt->insert->properties = attrs;
+	    xmlNodeAddContent(ctxt->insert, token->token);
+	} else if ((token->toktype == CRNG_OP) &&
+	           (token->token[0] == '{') && (token->token[0] == 0)) {
+	    ctxt->insert = xmlNewNode(NULL, BAD_CAST "data");
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) {
+	        xmlFreePropList(attrs);
+		CRNG_MEM_ERROR0();
+	    }
+	    ctxt->insert->properties = attrs;
+	    xmlParseCRNG_params(ctxt);
+        } else {
+	    ctxt->insert = xmlNewNode(NULL, BAD_CAST "data");
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) {
+	        xmlFreePropList(attrs);
+		CRNG_MEM_ERROR0();
+	    }
+	    ctxt->insert->properties = attrs;
+	    xmlNodeAddContent(ctxt->insert, token->token);
+	}
+    }
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_primary:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse primary of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_primary(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
+{
+    tokenPtr token;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if (token == NULL)
+        return(0);
+    if (token->toktype == CRNG_KEYWORD) {
+        if (token->token == ctxt->key_element) {
+	    ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	    ctxt->isElem = 1;
+	    xmlParseCRNG_nameClass(ctxt);
+	    xmlParseCRNG_patternBlock(ctxt);
+	} else if (token->token == ctxt->key_attribute) {
+	    ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	    ctxt->isElem = 0;
+	    xmlParseCRNG_nameClass(ctxt);
+	    xmlParseCRNG_patternBlock(ctxt);
+	} else if (token->token == ctxt->key_mixed) {
+	    ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	    xmlParseCRNG_patternBlock(ctxt);
+	} else if (token->token == ctxt->key_list) {
+	    ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	    xmlParseCRNG_patternBlock(ctxt);
+	} else if (token->token == ctxt->key_empty) {
+	    ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	} else if (token->token == ctxt->key_notAllowed) {
+	    ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	} else if (token->token == ctxt->key_text) {
+	    ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	} else if (token->token == ctxt->key_parent) {
+	    ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	    /* TODO */
+	} else if (token->token == ctxt->key_grammar) {
+	    ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token);
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	    /* TODO */
+	} else if (token->token == ctxt->key_external) {
+	    ctxt->insert = xmlNewNode(NULL, BAD_CAST "externalRef");
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	    if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	    /* TODO */
+	} else {
+	   /* TODO */
+	}
+    } else if (token->toktype == CRNG_IDENTIFIER) {
+	ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_ref);
+	if (ctxt->insert == NULL) CRNG_MEM_ERROR0();
+	xmlSetProp(ctxt->insert, BAD_CAST "name", token->token);
+	xmlParseCRNGDropTokens(ctxt, 1);
+    } else if (token->toktype == CRNG_QNAME) {
+        xmlParseCRNG_datatype(ctxt);
+    } else if (token->toktype == CRNG_LITERAL_SEGMENT) {
+        xmlParseCRNG_datatype(ctxt);
+    } else if ((token->toktype == CRNG_OP) &&
+               (token->token[0] == '(') && (token->token[1] == 0)) {
+	xmlParseCRNGDropTokens(ctxt, 1);
+	xmlParseCRNG_pattern(ctxt);
+	token = xmlParseCRNGGetToken(ctxt, 1);
+	if ((token->toktype != CRNG_OP) ||
+	    (token->token[0] != ')') || (token->token[1] != 0)) {
+	    ERROR("Expecting \")\" here");
+	}
+	xmlParseCRNGDropTokens(ctxt, 1);
+    }
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_particle:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse particle of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_particle(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    tokenPtr token;
+    xmlNodePtr insert = ctxt->insert, res, tmp = NULL;
+
+    ctxt->insert = NULL;
+    xmlParseCRNG_primary(ctxt);
+    res = ctxt->insert;
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if ((token != NULL) && (token->toktype == CRNG_OP)) {
+        if ((token->token[0] == '*') && (token->token[1] == 0)) {
+	    tmp = xmlNewNode(NULL, BAD_CAST "zeroOrMore");
+	    if (tmp == NULL) CRNG_MEM_ERROR0();
+	} else if ((token->token[0] == '+') && (token->token[1] == 0)) {
+	    tmp = xmlNewNode(NULL, BAD_CAST "oneOrMore");
+	    if (tmp == NULL) CRNG_MEM_ERROR0();
+	} else if ((token->token[0] == '?') && (token->token[1] == 0)) {
+	    tmp = xmlNewNode(NULL, BAD_CAST "optional");
+	    if (tmp == NULL) CRNG_MEM_ERROR0();
+	}
+	if (tmp != NULL) {
+	    xmlAddChild(tmp, res);
+	    res = tmp;
+	    xmlParseCRNGDropTokens(ctxt, 1);
+	}
+    }
+    if (insert != NULL) {
+        xmlAddChild(insert, res);
+	ctxt->insert = insert;
+    } else
+        ctxt->insert = res;
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_pattern:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse pattern of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_pattern(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    tokenPtr token;
+    xmlNodePtr insert = ctxt->insert, prev, grp;
+
+    ctxt->insert = NULL;
+    xmlParseCRNG_particle(ctxt);
+    prev = ctxt->insert;
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    while ((prev != NULL) && (token != NULL) && (token->toktype == CRNG_OP)) {
+        if (token->token == ctxt->key_or) {
+	    grp = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_choice);
+	    if (grp == NULL) CRNG_MEM_ERROR0();
+	} else if (token->token == ctxt->key_and) {
+	    grp = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_interleave);
+	    if (grp == NULL) CRNG_MEM_ERROR0();
+	} else if (token->token == ctxt->key_comma) {
+	    grp = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_group);
+	    if (grp == NULL) CRNG_MEM_ERROR0();
+	} else
+	   break;
+	xmlParseCRNGDropTokens(ctxt, 1);
+        ctxt->insert = NULL;
+	xmlParseCRNG_particle(ctxt);
+	xmlAddChild(grp, prev);
+	xmlAddChild(grp, ctxt->insert);
+	prev = grp;
+	token = xmlParseCRNGGetToken(ctxt, 1);
+    }
+    if (insert != NULL) {
+	xmlAddChild(insert, prev);
+	ctxt->insert = insert;
+    } else {
+	ctxt->insert = prev;
+    }
+
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_component:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse component of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_component(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    tokenPtr token, tok2;
+    xmlNodePtr insert = ctxt->insert;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if (token == NULL)
+        return(0);
+    if (token->toktype == CRNG_KEYWORD) {
+        if (token->token == ctxt->key_start) {
+	    xmlNodePtr start;
+
+	    start = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_start);
+	    if (start == NULL) CRNG_MEM_ERROR0();
+	    if (ctxt->insert != NULL)
+	        xmlAddChild(ctxt->insert, start);
+	    ctxt->insert = start;
+            xmlParseCRNGDropTokens(ctxt, 1);
+	    token = xmlParseCRNGGetToken(ctxt, 1);
+
+            if ((token->toktype == CRNG_OP) &&
+	        (token->token == ctxt->key_equal)) {
+	    } else if ((token->toktype == CRNG_OP) &&
+	               (token->token == ctxt->key_orequal)) {
+		xmlParseCRNG_attribute(ctxt, ctxt->key_combine, NULL,
+		                       BAD_CAST "choice");
+	    } else if ((token->toktype == CRNG_OP) &&
+	               (token->token == ctxt->key_andequal)) {
+		xmlParseCRNG_attribute(ctxt, ctxt->key_combine, NULL,
+		                       BAD_CAST "interleave");
+	    } else {
+	        ERROR("expecting \"=\" or \"&=\" or \"|=\" here")
+		return(-1);
+	    }
+	    start->properties = ctxt->attrs;
+	    ctxt->attrs = NULL;
+            xmlParseCRNGDropTokens(ctxt, 1);
+	    xmlParseCRNG_pattern(ctxt);
+
+	} else if (token->token == ctxt->key_include) {
+	    /* TODO */
+	} else if (token->token == ctxt->key_div) {
+	    /* TODO */
+	} else {
+	    return(-1);
+	}
+    } else if (token->toktype == CRNG_IDENTIFIER) {
+        xmlNodePtr define;
+	const xmlChar *identifier;
+
+        identifier = token->token;
+	tok2 = xmlParseCRNGGetToken(ctxt, 2);
+	if ((tok2->toktype == CRNG_OP) &&
+	    (tok2->token == ctxt->key_equal)) {
+	} else if ((tok2->toktype == CRNG_OP) &&
+		   (tok2->token == ctxt->key_orequal)) {
+	    xmlParseCRNG_attribute(ctxt, ctxt->key_combine, NULL,
+				   BAD_CAST "choice");
+	} else if ((tok2->toktype == CRNG_OP) &&
+		   (tok2->token == ctxt->key_andequal)) {
+	    xmlParseCRNG_attribute(ctxt, ctxt->key_combine, NULL,
+				   BAD_CAST "interleave");
+	} else {
+	    ERROR("expecting \"=\" or \"&=\" or \"|=\" here")
+	    return(-1);
+	}
+	xmlParseCRNGDropTokens(ctxt, 2);
+
+	define = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_define);
+	if (define == NULL) CRNG_MEM_ERROR0();
+	define->properties = ctxt->attrs;
+	ctxt->attrs = NULL;
+	xmlSetProp(define, BAD_CAST "name", identifier);
+	if (ctxt->insert != NULL)
+	    xmlAddChild(ctxt->insert, define);
+	ctxt->insert = define;
+	xmlParseCRNG_pattern(ctxt);
+    } else {
+	return(-1);
+    }
+    ctxt->insert = insert;
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_grammar:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse grammar of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_grammar(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
+{
+    tokenPtr token;
+    int ret;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    while (token != NULL) {
+        ret = xmlParseCRNG_component(ctxt);
+	if (ret != 0)
+	    break;
+	token = xmlParseCRNGGetToken(ctxt, 1);
+    }
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_topLevelBody:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse topLevelBody of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_topLevelBody(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    tokenPtr token, tok2;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if (token->toktype == CRNG_KEYWORD) {
+        if ((token->token == ctxt->key_start) ||
+	    (token->token == ctxt->key_include) ||
+	    (token->token == ctxt->key_div)) {
+	    xmlNodePtr grammar;
+
+	    grammar = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_grammar);
+	    if (grammar == NULL) CRNG_MEM_ERROR0();
+	    xmlDocSetRootElement(ctxt->doc, grammar);
+	    ctxt->insert = grammar;
+
+	    xmlParseCRNG_grammar(ctxt);
+	} else {
+	    xmlParseCRNG_pattern(ctxt);
+	}
+    } else {
+        tok2 = xmlParseCRNGGetToken(ctxt, 2);
+	if ((tok2->toktype == CRNG_OP) &&
+	    ((tok2->token == ctxt->key_equal) ||
+	     (tok2->token == ctxt->key_orequal) ||
+	     (tok2->token == ctxt->key_andequal))) {
+	    xmlNodePtr grammar;
+
+	    grammar = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_grammar);
+	    if (grammar == NULL) CRNG_MEM_ERROR0();
+	    xmlDocSetRootElement(ctxt->doc, grammar);
+	    ctxt->insert = grammar;
+
+	    xmlParseCRNG_grammar(ctxt);
+	} else {
+	    xmlParseCRNG_pattern(ctxt);
+	}
+    }
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_namespacePrefix:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse namespacePrefix of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns the prefix or NULL in case of error
+ */
+static const xmlChar *
+xmlParseCRNG_namespacePrefix(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    tokenPtr token;
+    const xmlChar *prefix = NULL;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if (token->toktype == CRNG_IDENTIFIER) {
+        prefix = token->token;
+    } else if (token->toktype == CRNG_OP) {
+	if ((token->token[0] == '=') && (token->token[1] == 0))
+	    return(NULL);
+        prefix = token->token;
+    } else {
+	ERROR("Expecting a namespace prefix");
+	return(NULL);
+    }
+    xmlParseCRNGDropTokens(ctxt, 1);
+
+    if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
+	ERROR("Namespace prefix \"xmlns\" is forbidden");
+    }
+    return(prefix);
+}
+
+/**
+ * xmlParseCRNG_decl:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse decl of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_decl(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    const xmlChar *prefix = NULL;
+    const xmlChar *namespace = NULL;
+    tokenPtr token;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    if (token->toktype != CRNG_KEYWORD) return(-1);
+    if (token->token == ctxt->key_default) {
+        xmlParseCRNGDropTokens(ctxt, 1);
+        token = xmlParseCRNGGetToken(ctxt, 1);
+        if ((token->toktype != CRNG_KEYWORD) ||
+	    (token->token != ctxt->key_namespace)) {
+	    ERROR("Expecting keyword \"namespace\" after \"default\"");
+	}
+        xmlParseCRNGDropTokens(ctxt, 1);
+	prefix = xmlParseCRNG_namespacePrefix(ctxt);
+        token = xmlParseCRNGGetToken(ctxt, 1);
+        if ((token->toktype != CRNG_OP) ||
+	    (token->token[0] != '=') || (token->token[1] != 0)) {
+	    ERROR("Expecting keyword \"=\" here");
+	}
+        xmlParseCRNGDropTokens(ctxt, 1);
+        token = xmlParseCRNGGetToken(ctxt, 1);
+        if ((token->toktype == CRNG_KEYWORD) &&
+	    (token->token == ctxt->key_inherit)) {
+	    namespace = xmlCRelaxNGInherit;
+	} else if (token->toktype == CRNG_LITERAL_SEGMENT) {
+	    namespace = token->token;
+	} else {
+	    ERROR("Expecting an URI or \"inherit\" value");
+	}
+        xmlParseCRNGDropTokens(ctxt, 1);
+        if (namespace != NULL) {
+	    if (prefix != NULL)
+		xmlParseCRNG_bindPrefix(ctxt, prefix, namespace);
+            xmlParseCRNG_bindPrefix(ctxt, NULL, namespace);
+	}
+    } else if (token->token == ctxt->key_namespace) {
+        xmlParseCRNGDropTokens(ctxt, 1);
+	prefix = xmlParseCRNG_namespacePrefix(ctxt);
+        token = xmlParseCRNGGetToken(ctxt, 1);
+        if ((token->toktype != CRNG_OP) ||
+	    (token->token[0] != '=') || (token->token[1] != 0)) {
+	    ERROR("Expecting keyword \"=\" here");
+	}
+        xmlParseCRNGDropTokens(ctxt, 1);
+        token = xmlParseCRNGGetToken(ctxt, 1);
+        if ((token->toktype == CRNG_KEYWORD) &&
+	    (token->token == ctxt->key_inherit)) {
+	    namespace = xmlCRelaxNGInherit;
+	} else if (token->toktype == CRNG_LITERAL_SEGMENT) {
+	    namespace = token->token;
+	} else {
+	    ERROR("Expecting an URI or \"inherit\" value");
+	}
+        xmlParseCRNGDropTokens(ctxt, 1);
+        if (namespace != NULL)
+	    xmlParseCRNG_bindPrefix(ctxt, prefix, namespace);
+    } else if (token->token == ctxt->key_datatypes) {
+        xmlParseCRNGDropTokens(ctxt, 1);
+
+        token = xmlParseCRNGGetToken(ctxt, 1);
+	if ((token->toktype != CRNG_KEYWORD) &&
+	    (token->toktype != CRNG_IDENTIFIER)) {
+	    ERROR("Expecting a datatype prefix identifier here");
+	} else
+	    prefix = token->token;
+        xmlParseCRNGDropTokens(ctxt, 1);
+        token = xmlParseCRNGGetToken(ctxt, 1);
+        if ((token->toktype != CRNG_OP) ||
+	    (token->token[0] != '=') || (token->token[1] != 0)) {
+	    ERROR("Expecting keyword \"=\" here");
+	}
+        xmlParseCRNGDropTokens(ctxt, 1);
+        token = xmlParseCRNGGetToken(ctxt, 1);
+	if (token->toktype == CRNG_LITERAL_SEGMENT) {
+	    namespace = token->token;
+	} else {
+	    ERROR("Expecting a literal value for the datatype identifier");
+	}
+        xmlParseCRNGDropTokens(ctxt, 1);
+        if ((namespace != NULL) && (prefix != NULL))
+	    xmlParseCRNG_bindDatatypePrefix(ctxt, prefix, namespace);
+    }
+
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_preamble:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse preamble of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_preamble(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    tokenPtr token;
+
+    token = xmlParseCRNGGetToken(ctxt, 1);
+    while (token != NULL) {
+	if (token == NULL) return(-1);
+	if ((token->toktype == CRNG_KEYWORD) &&
+	    ((token->token == ctxt->key_default) ||
+	     (token->token == ctxt->key_namespace) ||
+	     (token->token == ctxt->key_datatypes))) {
+	    xmlParseCRNG_decl(ctxt);
+	} else
+	    break;
+	token = xmlParseCRNGGetToken(ctxt, 1);
+    }
+    return(0);
+}
+
+/**
+ * xmlParseCRNG_topLevel:
+ * @ctxt: a compact RNG parser context
+ *
+ * Parse topLevel of the RELAX NG Compact Syntax Appendix A
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xmlParseCRNG_topLevel(xmlCRelaxNGParserCtxtPtr ctxt)
+{
+    xmlParseCRNG_preamble(ctxt);
+    xmlParseCRNG_topLevelBody(ctxt);
+    return(0);
+}
+
+/**
+ * xmlConvertCRNG:
+ * @schemas:  pointer to the text of the compact schemas
+ * @len:  length of the schemas in bytes (or 0)
+ * @encoding:  encoding indicated by the context or NULL
+ *
+ * Compiles the schemas into the equivalent Relax-NG XML structure
+ *
+ * Returns the xmlDocPtr resulting from the compilation or
+ *         NULL in case of error
+ */
+xmlDocPtr
+xmlConvertCRNG(const char *schemas, int len, const char *encoding) {
+    struct _xmlCRelaxNGParserCtxt ctxt;
+    xmlDocPtr ret = NULL;
+
+    if (schemas == NULL) return(NULL);
+    if (len <= 5) len = xmlStrlen((const unsigned char *) schemas);
+    if (len <= 0) return(NULL);
+
+    memset(&ctxt, 0, sizeof(ctxt));
+    ctxt.compact = (const unsigned char *) schemas;
+    ctxt.cur = (const unsigned char *) schemas;
+    ctxt.end = (const unsigned char *) &schemas[len];
+    ctxt.dict = xmlDictCreate();
+    if (ctxt.dict == NULL)
+        return(NULL);
+    ctxt.doc = xmlNewDoc(NULL);
+    if (ctxt.doc == NULL) {
+	xmlDictFree(ctxt.dict);
+	return(NULL);
+    }
+    ctxt.doc->dict = ctxt.dict;
+    xmlDictReference(ctxt.dict);
+
+    ctxt.nbTokens = 0;
+    ctxt.firstToken = 0;
+    ctxt.key_attribute = xmlDictLookup(ctxt.dict, BAD_CAST "attribute", -1);
+    ctxt.key_default = xmlDictLookup(ctxt.dict, BAD_CAST "default", -1);
+    ctxt.key_datatypes = xmlDictLookup(ctxt.dict, BAD_CAST "datatypes", -1);
+    ctxt.key_div = xmlDictLookup(ctxt.dict, BAD_CAST "div", -1);
+    ctxt.key_element = xmlDictLookup(ctxt.dict, BAD_CAST "element", -1);
+    ctxt.key_empty = xmlDictLookup(ctxt.dict, BAD_CAST "empty", -1);
+    ctxt.key_external = xmlDictLookup(ctxt.dict, BAD_CAST "external", -1);
+    ctxt.key_grammar = xmlDictLookup(ctxt.dict, BAD_CAST "grammar", -1);
+    ctxt.key_include = xmlDictLookup(ctxt.dict, BAD_CAST "include", -1);
+    ctxt.key_inherit = xmlDictLookup(ctxt.dict, BAD_CAST "inherit", -1);
+    ctxt.key_list = xmlDictLookup(ctxt.dict, BAD_CAST "list", -1);
+    ctxt.key_mixed = xmlDictLookup(ctxt.dict, BAD_CAST "mixed", -1);
+    ctxt.key_namespace = xmlDictLookup(ctxt.dict, BAD_CAST "namespace", -1);
+    ctxt.key_notAllowed = xmlDictLookup(ctxt.dict, BAD_CAST "notAllowed", -1);
+    ctxt.key_parent = xmlDictLookup(ctxt.dict, BAD_CAST "parent", -1);
+    ctxt.key_start = xmlDictLookup(ctxt.dict, BAD_CAST "start", -1);
+    ctxt.key_string = xmlDictLookup(ctxt.dict, BAD_CAST "string", -1);
+    ctxt.key_text = xmlDictLookup(ctxt.dict, BAD_CAST "text", -1);
+    ctxt.key_token = xmlDictLookup(ctxt.dict, BAD_CAST "token", -1);
+    ctxt.key_equal = xmlDictLookup(ctxt.dict, BAD_CAST "=", 1);
+    ctxt.key_orequal = xmlDictLookup(ctxt.dict, BAD_CAST "|=", 2);
+    ctxt.key_andequal = xmlDictLookup(ctxt.dict, BAD_CAST "&=", 2);
+    ctxt.key_combine = xmlDictLookup(ctxt.dict, BAD_CAST "&=", 2);
+    ctxt.key_or = xmlDictLookup(ctxt.dict, BAD_CAST "|", 1);
+    ctxt.key_comma = xmlDictLookup(ctxt.dict, BAD_CAST ",", 1);
+    ctxt.key_and = xmlDictLookup(ctxt.dict, BAD_CAST "&", 1);
+    ctxt.key_choice = xmlDictLookup(ctxt.dict, BAD_CAST "choice", -1);
+    ctxt.key_group = xmlDictLookup(ctxt.dict, BAD_CAST "group", -1);
+    ctxt.key_interleave = xmlDictLookup(ctxt.dict, BAD_CAST "interleave", -1);
+    ctxt.key_ref = xmlDictLookup(ctxt.dict, BAD_CAST "ref", 3);
+    ctxt.key_define = xmlDictLookup(ctxt.dict, BAD_CAST "define", 6);
+
+    /* xmlConvertCRNGTokenize(&ctxt); */
+    xmlConvertCRNG_topLevel(&ctxt);
+
+    xmlDictFree(ctxt.dict);
+
+    ret = ctxt.doc;
+    return(ret);
+}
+
+/**
+ * xmlConvertCRNGFile:
+ * @URL: URL or filename for the resource
+ * @encoding:  encoding indicated by the context or NULL
+ *
+ * Compiles the schemas into the equivalent Relax-NG XML structure
+ *
+ * Returns the xmlDocPtr resulting from the compilation or
+ *         NULL in case of error
+ */
+xmlDocPtr
+xmlConvertCRNGFile(const char *URL, const char *encoding) {
+}
+
+#ifdef STANDALONE
+const xmlChar *schemas =
+"# RELAX NG XML syntax specified in compact syntax.\n\
+\n\
+default namespace rng = \"http://relaxng.org/ns/structure/1.0\"\n\
+namespace local = \"\"\n\
+datatypes xsd = \"http://www.w3.org/2001/XMLSchema-datatypes\"\n\
+\n\
+start = pattern\n\
+\n\
+pattern =\n\
+  element element { (nameQName | nameClass), (common & pattern+) }\n\
+  | element attribute { (nameQName | nameClass), (common & pattern?) }\n\
+  | element group|interleave|choice|optional\n\
+            |zeroOrMore|oneOrMore|list|mixed { common & pattern+ }\n\
+  | element ref|parentRef { nameNCName, common }\n\
+  | element empty|notAllowed|text { common }\n\
+  | element data { type, param*, (common & exceptPattern?) }\n\
+  | element value { commonAttributes, type?, xsd:string }\n\
+  | element externalRef { href, common }\n\
+  | element grammar { common & grammarContent* }\n\
+\n\
+param = element param { commonAttributes, nameNCName, xsd:string }\n\
+\n\
+exceptPattern = element except { common & pattern+ }\n\
+\n\
+grammarContent =\n\
+  definition\n\
+  | element div { common & grammarContent* }\n\
+  | element include { href, (common & includeContent*) }\n\
+\n\
+includeContent =\n\
+  definition\n\
+  | element div { common & includeContent* }\n\
+\n\
+definition =\n\
+  element start { combine?, (common & pattern+) }\n\
+  | element define { nameNCName, combine?, (common & pattern+) }\n\
+\n\
+combine = attribute combine { \"choice\" | \"interleave\" }\n\
+\n\
+nameClass =\n\
+  element name { commonAttributes, xsd:QName }\n\
+  | element anyName { common & exceptNameClass? }\n\
+  | element nsName { common & exceptNameClass? }\n\
+  | element choice { common & nameClass+ }\n\
+\n\
+exceptNameClass = element except { common & nameClass+ }\n\
+\n\
+nameQName = attribute name { xsd:QName }\n\
+nameNCName = attribute name { xsd:NCName }\n\
+href = attribute href { xsd:anyURI }\n\
+type = attribute type { xsd:NCName }\n\
+\n\
+common = commonAttributes, foreignElement*\n\
+\n\
+commonAttributes =\n\
+  attribute ns { xsd:string }?,\n\
+  attribute datatypeLibrary { xsd:anyURI }?,\n\
+  foreignAttribute*\n\
+\n\
+foreignElement = element * - rng:* { (anyAttribute | text | anyElement)* }\n\
+foreignAttribute = attribute * - (rng:*|local:*) { text }\n\
+anyElement = element * { (anyAttribute | text | anyElement)* }\n\
+anyAttribute = attribute * { text }\n\
+";
+
+int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    xmlDocPtr res;
+
+    res = xmlConvertCRNG(schemas, -1);
+    if (res != NULL) {
+        xmlDocFormatDump(stdout, res, 1);
+	xmlFreeDoc(res);
+    }
+    return(0);
+}
+#endif
diff --git a/runsuite.c b/runsuite.c
new file mode 100644
index 0000000000000000000000000000000000000000..75b8f3ad79707abb816bf5c3d1d38dfcabd11071
--- /dev/null
+++ b/runsuite.c
@@ -0,0 +1,1166 @@
+/*
+ * runsuite.c: C program to run libxml2 against published testsuites
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/tree.h>
+#include <libxml/uri.h>
+#if defined(LIBXML_SCHEMAS_ENABLED) && defined(LIBXML_XPATH_ENABLED)
+#include <libxml/xmlreader.h>
+
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <libxml/relaxng.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/xmlschemastypes.h>
+
+#define LOGFILE "runsuite.log"
+static FILE *logfile = NULL;
+static int verbose = 0;
+
+
+/************************************************************************
+ *									*
+ *		File name and path utilities				*
+ *									*
+ ************************************************************************/
+
+static int checkTestFile(const char *filename) {
+    struct stat buf;
+
+    if (stat(filename, &buf) == -1)
+        return(0);
+
+#if defined(_WIN32)
+    if (!(buf.st_mode & _S_IFREG))
+        return(0);
+#else
+    if (!S_ISREG(buf.st_mode))
+        return(0);
+#endif
+
+    return(1);
+}
+
+static xmlChar *composeDir(const xmlChar *dir, const xmlChar *path) {
+    char buf[500];
+
+    if (dir == NULL) return(xmlStrdup(path));
+    if (path == NULL) return(NULL);
+
+    snprintf(buf, 500, "%s/%s", (const char *) dir, (const char *) path);
+    return(xmlStrdup((const xmlChar *) buf));
+}
+
+/************************************************************************
+ *									*
+ *		Libxml2 specific routines				*
+ *									*
+ ************************************************************************/
+
+static int nb_tests = 0;
+static int nb_errors = 0;
+static int nb_internals = 0;
+static int nb_schematas = 0;
+static int nb_unimplemented = 0;
+static int nb_leaks = 0;
+static int extraMemoryFromResolver = 0;
+
+static int
+fatalError(void) {
+    fprintf(stderr, "Exitting tests on fatal error\n");
+    exit(1);
+}
+
+/*
+ * that's needed to implement <resource>
+ */
+#define MAX_ENTITIES 20
+static char *testEntitiesName[MAX_ENTITIES];
+static char *testEntitiesValue[MAX_ENTITIES];
+static int nb_entities = 0;
+static void resetEntities(void) {
+    int i;
+
+    for (i = 0;i < nb_entities;i++) {
+        if (testEntitiesName[i] != NULL)
+	    xmlFree(testEntitiesName[i]);
+        if (testEntitiesValue[i] != NULL)
+	    xmlFree(testEntitiesValue[i]);
+    }
+    nb_entities = 0;
+}
+static int addEntity(char *name, char *content) {
+    if (nb_entities >= MAX_ENTITIES) {
+	fprintf(stderr, "Too many entities defined\n");
+	return(-1);
+    }
+    testEntitiesName[nb_entities] = name;
+    testEntitiesValue[nb_entities] = content;
+    nb_entities++;
+    return(0);
+}
+
+/*
+ * We need to trap calls to the resolver to not account memory for the catalog
+ * which is shared to the current running test. We also don't want to have
+ * network downloads modifying tests.
+ */
+static xmlParserInputPtr
+testExternalEntityLoader(const char *URL, const char *ID,
+			 xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr ret;
+    int i;
+
+    for (i = 0;i < nb_entities;i++) {
+        if (!strcmp(testEntitiesName[i], URL)) {
+	    ret = xmlNewStringInputStream(ctxt,
+	                (const xmlChar *) testEntitiesValue[i]);
+	    if (ret != NULL) {
+	        ret->filename = (const char *)
+		                xmlStrdup((xmlChar *)testEntitiesName[i]);
+	    }
+	    return(ret);
+	}
+    }
+    if (checkTestFile(URL)) {
+	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+    } else {
+	int memused = xmlMemUsed();
+	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+	extraMemoryFromResolver += xmlMemUsed() - memused;
+    }
+#if 0
+    if (ret == NULL) {
+        fprintf(stderr, "Failed to find resource %s\n", URL);
+    }
+#endif
+
+    return(ret);
+}
+
+/*
+ * Trapping the error messages at the generic level to grab the equivalent of
+ * stderr messages on CLI tools.
+ */
+static char testErrors[32769];
+static int testErrorsSize = 0;
+
+static void test_log(const char *msg, ...) {
+    va_list args;
+    if (logfile != NULL) {
+        fprintf(logfile, "\n------------\n");
+	va_start(args, msg);
+	vfprintf(logfile, msg, args);
+	va_end(args);
+	fprintf(logfile, "%s", testErrors);
+	testErrorsSize = 0; testErrors[0] = 0;
+    }
+    if (verbose) {
+	va_start(args, msg);
+	vfprintf(stderr, msg, args);
+	va_end(args);
+    }
+}
+
+static void
+testErrorHandler(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
+    va_list args;
+    int res;
+
+    if (testErrorsSize >= 32768)
+        return;
+    va_start(args, msg);
+    res = vsnprintf(&testErrors[testErrorsSize],
+                    32768 - testErrorsSize,
+		    msg, args);
+    va_end(args);
+    if (testErrorsSize + res >= 32768) {
+        /* buffer is full */
+	testErrorsSize = 32768;
+	testErrors[testErrorsSize] = 0;
+    } else {
+        testErrorsSize += res;
+    }
+    testErrors[testErrorsSize] = 0;
+}
+
+static xmlXPathContextPtr ctxtXPath;
+
+static void
+initializeLibxml2(void) {
+    xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
+    xmlInitParser();
+    xmlSetExternalEntityLoader(testExternalEntityLoader);
+    ctxtXPath = xmlXPathNewContext(NULL);
+    /*
+    * Deactivate the cache if created; otherwise we have to create/free it
+    * for every test, since it will confuse the memory leak detection.
+    * Note that normally this need not be done, since the cache is not
+    * created until set explicitly with xmlXPathContextSetCache();
+    * but for test purposes it is sometimes useful to activate the
+    * cache by default for the whole library.
+    */
+    if (ctxtXPath->cache != NULL)
+	xmlXPathContextSetCache(ctxtXPath, 0, -1, 0);
+    /* used as default namespace in xstc tests */
+    xmlXPathRegisterNs(ctxtXPath, BAD_CAST "ts", BAD_CAST "TestSuite");
+    xmlXPathRegisterNs(ctxtXPath, BAD_CAST "xlink",
+                       BAD_CAST "http://www.w3.org/1999/xlink");
+    xmlSetGenericErrorFunc(NULL, testErrorHandler);
+#ifdef LIBXML_SCHEMAS_ENABLED
+    xmlSchemaInitTypes();
+    xmlRelaxNGInitTypes();
+#endif
+}
+
+static xmlNodePtr
+getNext(xmlNodePtr cur, const char *xpath) {
+    xmlNodePtr ret = NULL;
+    xmlXPathObjectPtr res;
+    xmlXPathCompExprPtr comp;
+
+    if ((cur == NULL)  || (cur->doc == NULL) || (xpath == NULL))
+        return(NULL);
+    ctxtXPath->doc = cur->doc;
+    ctxtXPath->node = cur;
+    comp = xmlXPathCompile(BAD_CAST xpath);
+    if (comp == NULL) {
+        fprintf(stderr, "Failed to compile %s\n", xpath);
+	return(NULL);
+    }
+    res = xmlXPathCompiledEval(comp, ctxtXPath);
+    xmlXPathFreeCompExpr(comp);
+    if (res == NULL)
+        return(NULL);
+    if ((res->type == XPATH_NODESET) &&
+        (res->nodesetval != NULL) &&
+	(res->nodesetval->nodeNr > 0) &&
+	(res->nodesetval->nodeTab != NULL))
+	ret = res->nodesetval->nodeTab[0];
+    xmlXPathFreeObject(res);
+    return(ret);
+}
+
+static xmlChar *
+getString(xmlNodePtr cur, const char *xpath) {
+    xmlChar *ret = NULL;
+    xmlXPathObjectPtr res;
+    xmlXPathCompExprPtr comp;
+
+    if ((cur == NULL)  || (cur->doc == NULL) || (xpath == NULL))
+        return(NULL);
+    ctxtXPath->doc = cur->doc;
+    ctxtXPath->node = cur;
+    comp = xmlXPathCompile(BAD_CAST xpath);
+    if (comp == NULL) {
+        fprintf(stderr, "Failed to compile %s\n", xpath);
+	return(NULL);
+    }
+    res = xmlXPathCompiledEval(comp, ctxtXPath);
+    xmlXPathFreeCompExpr(comp);
+    if (res == NULL)
+        return(NULL);
+    if (res->type == XPATH_STRING) {
+        ret = res->stringval;
+	res->stringval = NULL;
+    }
+    xmlXPathFreeObject(res);
+    return(ret);
+}
+
+/************************************************************************
+ *									*
+ *		Test test/xsdtest/xsdtestsuite.xml			*
+ *									*
+ ************************************************************************/
+
+static int
+xsdIncorrectTestCase(xmlNodePtr cur) {
+    xmlNodePtr test;
+    xmlBufferPtr buf;
+    xmlRelaxNGParserCtxtPtr pctxt;
+    xmlRelaxNGPtr rng = NULL;
+    int ret = 0, memt;
+
+    cur = getNext(cur, "./incorrect[1]");
+    if (cur == NULL) {
+        return(0);
+    }
+
+    test = getNext(cur, "./*");
+    if (test == NULL) {
+        test_log("Failed to find test in correct line %ld\n",
+	        xmlGetLineNo(cur));
+        return(1);
+    }
+
+    memt = xmlMemUsed();
+    extraMemoryFromResolver = 0;
+    /*
+     * dump the schemas to a buffer, then reparse it and compile the schemas
+     */
+    buf = xmlBufferCreate();
+    if (buf == NULL) {
+        fprintf(stderr, "out of memory !\n");
+	fatalError();
+    }
+    xmlBufferSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
+    xmlNodeDump(buf, test->doc, test, 0, 0);
+    pctxt = xmlRelaxNGNewMemParserCtxt((const char *)buf->content, buf->use);
+    xmlRelaxNGSetParserErrors(pctxt, testErrorHandler, testErrorHandler,
+            pctxt);
+    rng = xmlRelaxNGParse(pctxt);
+    xmlRelaxNGFreeParserCtxt(pctxt);
+    if (rng != NULL) {
+	test_log("Failed to detect incorrect RNG line %ld\n",
+		    xmlGetLineNo(test));
+        ret = 1;
+	goto done;
+    }
+
+done:
+    if (buf != NULL)
+	xmlBufferFree(buf);
+    if (rng != NULL)
+        xmlRelaxNGFree(rng);
+    xmlResetLastError();
+    if ((memt < xmlMemUsed()) && (extraMemoryFromResolver == 0)) {
+	test_log("Validation of tests starting line %ld leaked %d\n",
+		xmlGetLineNo(cur), xmlMemUsed() - memt);
+	nb_leaks++;
+    }
+    return(ret);
+}
+
+static void
+installResources(xmlNodePtr tst, const xmlChar *base) {
+    xmlNodePtr test;
+    xmlBufferPtr buf;
+    xmlChar *name, *content, *res;
+
+    buf = xmlBufferCreate();
+    if (buf == NULL) {
+        fprintf(stderr, "out of memory !\n");
+	fatalError();
+    }
+    xmlBufferSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
+    xmlNodeDump(buf, tst->doc, tst, 0, 0);
+
+    while (tst != NULL) {
+	test = getNext(tst, "./*");
+	if (test != NULL) {
+	    xmlBufferEmpty(buf);
+	    xmlNodeDump(buf, test->doc, test, 0, 0);
+	    name = getString(tst, "string(@name)");
+	    content = xmlStrdup(buf->content);
+	    if ((name != NULL) && (content != NULL)) {
+	        res = composeDir(base, name);
+		xmlFree(name);
+	        addEntity((char *) res, (char *) content);
+	    } else {
+	        if (name != NULL) xmlFree(name);
+	        if (content != NULL) xmlFree(content);
+	    }
+	}
+	tst = getNext(tst, "following-sibling::resource[1]");
+    }
+    if (buf != NULL)
+	xmlBufferFree(buf);
+}
+
+static void
+installDirs(xmlNodePtr tst, const xmlChar *base) {
+    xmlNodePtr test;
+    xmlChar *name, *res;
+
+    name = getString(tst, "string(@name)");
+    if (name == NULL)
+        return;
+    res = composeDir(base, name);
+    xmlFree(name);
+    if (res == NULL) {
+	return;
+    }
+    /* Now process resources and subdir recursively */
+    test = getNext(tst, "./resource[1]");
+    if (test != NULL) {
+        installResources(test, res);
+    }
+    test = getNext(tst, "./dir[1]");
+    while (test != NULL) {
+        installDirs(test, res);
+	test = getNext(test, "following-sibling::dir[1]");
+    }
+    xmlFree(res);
+}
+
+static int
+xsdTestCase(xmlNodePtr tst) {
+    xmlNodePtr test, tmp, cur;
+    xmlBufferPtr buf;
+    xmlDocPtr doc = NULL;
+    xmlRelaxNGParserCtxtPtr pctxt;
+    xmlRelaxNGValidCtxtPtr ctxt;
+    xmlRelaxNGPtr rng = NULL;
+    int ret = 0, mem, memt;
+    xmlChar *dtd;
+
+    resetEntities();
+    testErrorsSize = 0; testErrors[0] = 0;
+
+    tmp = getNext(tst, "./dir[1]");
+    if (tmp != NULL) {
+        installDirs(tmp, NULL);
+    }
+    tmp = getNext(tst, "./resource[1]");
+    if (tmp != NULL) {
+        installResources(tmp, NULL);
+    }
+
+    cur = getNext(tst, "./correct[1]");
+    if (cur == NULL) {
+        return(xsdIncorrectTestCase(tst));
+    }
+
+    test = getNext(cur, "./*");
+    if (test == NULL) {
+        fprintf(stderr, "Failed to find test in correct line %ld\n",
+	        xmlGetLineNo(cur));
+        return(1);
+    }
+
+    memt = xmlMemUsed();
+    extraMemoryFromResolver = 0;
+    /*
+     * dump the schemas to a buffer, then reparse it and compile the schemas
+     */
+    buf = xmlBufferCreate();
+    if (buf == NULL) {
+        fprintf(stderr, "out of memory !\n");
+	fatalError();
+    }
+    xmlBufferSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
+    xmlNodeDump(buf, test->doc, test, 0, 0);
+    pctxt = xmlRelaxNGNewMemParserCtxt((const char *)buf->content, buf->use);
+    xmlRelaxNGSetParserErrors(pctxt, testErrorHandler, testErrorHandler,
+            pctxt);
+    rng = xmlRelaxNGParse(pctxt);
+    xmlRelaxNGFreeParserCtxt(pctxt);
+    if (extraMemoryFromResolver)
+        memt = 0;
+
+    if (rng == NULL) {
+        test_log("Failed to parse RNGtest line %ld\n",
+	        xmlGetLineNo(test));
+	nb_errors++;
+        ret = 1;
+	goto done;
+    }
+    /*
+     * now scan all the siblings of correct to process the <valid> tests
+     */
+    tmp = getNext(cur, "following-sibling::valid[1]");
+    while (tmp != NULL) {
+	dtd = xmlGetProp(tmp, BAD_CAST "dtd");
+	test = getNext(tmp, "./*");
+	if (test == NULL) {
+	    fprintf(stderr, "Failed to find test in <valid> line %ld\n",
+		    xmlGetLineNo(tmp));
+
+	} else {
+	    xmlBufferEmpty(buf);
+	    if (dtd != NULL)
+		xmlBufferAdd(buf, dtd, -1);
+	    xmlNodeDump(buf, test->doc, test, 0, 0);
+
+	    /*
+	     * We are ready to run the test
+	     */
+	    mem = xmlMemUsed();
+	    extraMemoryFromResolver = 0;
+            doc = xmlReadMemory((const char *)buf->content, buf->use,
+	                        "test", NULL, 0);
+	    if (doc == NULL) {
+		test_log("Failed to parse valid instance line %ld\n",
+			xmlGetLineNo(tmp));
+		nb_errors++;
+	    } else {
+		nb_tests++;
+	        ctxt = xmlRelaxNGNewValidCtxt(rng);
+		xmlRelaxNGSetValidErrors(ctxt,
+                        testErrorHandler, testErrorHandler, ctxt);
+		ret = xmlRelaxNGValidateDoc(ctxt, doc);
+		xmlRelaxNGFreeValidCtxt(ctxt);
+		if (ret > 0) {
+		    test_log("Failed to validate valid instance line %ld\n",
+				xmlGetLineNo(tmp));
+		    nb_errors++;
+		} else if (ret < 0) {
+		    test_log("Internal error validating instance line %ld\n",
+			    xmlGetLineNo(tmp));
+		    nb_errors++;
+		}
+		xmlFreeDoc(doc);
+	    }
+	    xmlResetLastError();
+	    if ((mem != xmlMemUsed()) && (extraMemoryFromResolver == 0)) {
+	        test_log("Validation of instance line %ld leaked %d\n",
+		        xmlGetLineNo(tmp), xmlMemUsed() - mem);
+	        nb_leaks++;
+	    }
+	}
+	if (dtd != NULL)
+	    xmlFree(dtd);
+	tmp = getNext(tmp, "following-sibling::valid[1]");
+    }
+    /*
+     * now scan all the siblings of correct to process the <invalid> tests
+     */
+    tmp = getNext(cur, "following-sibling::invalid[1]");
+    while (tmp != NULL) {
+	test = getNext(tmp, "./*");
+	if (test == NULL) {
+	    fprintf(stderr, "Failed to find test in <invalid> line %ld\n",
+		    xmlGetLineNo(tmp));
+
+	} else {
+	    xmlBufferEmpty(buf);
+	    xmlNodeDump(buf, test->doc, test, 0, 0);
+
+	    /*
+	     * We are ready to run the test
+	     */
+	    mem = xmlMemUsed();
+	    extraMemoryFromResolver = 0;
+            doc = xmlReadMemory((const char *)buf->content, buf->use,
+	                        "test", NULL, 0);
+	    if (doc == NULL) {
+		test_log("Failed to parse valid instance line %ld\n",
+			xmlGetLineNo(tmp));
+		nb_errors++;
+	    } else {
+		nb_tests++;
+	        ctxt = xmlRelaxNGNewValidCtxt(rng);
+		xmlRelaxNGSetValidErrors(ctxt,
+                        testErrorHandler, testErrorHandler, ctxt);
+		ret = xmlRelaxNGValidateDoc(ctxt, doc);
+		xmlRelaxNGFreeValidCtxt(ctxt);
+		if (ret == 0) {
+		    test_log("Failed to detect invalid instance line %ld\n",
+				xmlGetLineNo(tmp));
+		    nb_errors++;
+		} else if (ret < 0) {
+		    test_log("Internal error validating instance line %ld\n",
+			    xmlGetLineNo(tmp));
+		    nb_errors++;
+		}
+		xmlFreeDoc(doc);
+	    }
+	    xmlResetLastError();
+	    if ((mem != xmlMemUsed()) && (extraMemoryFromResolver == 0)) {
+	        test_log("Validation of instance line %ld leaked %d\n",
+		        xmlGetLineNo(tmp), xmlMemUsed() - mem);
+	        nb_leaks++;
+	    }
+	}
+	tmp = getNext(tmp, "following-sibling::invalid[1]");
+    }
+
+done:
+    if (buf != NULL)
+	xmlBufferFree(buf);
+    if (rng != NULL)
+        xmlRelaxNGFree(rng);
+    xmlResetLastError();
+    if ((memt != xmlMemUsed()) && (memt != 0)) {
+	test_log("Validation of tests starting line %ld leaked %d\n",
+		xmlGetLineNo(cur), xmlMemUsed() - memt);
+	nb_leaks++;
+    }
+    return(ret);
+}
+
+static int
+xsdTestSuite(xmlNodePtr cur) {
+    if (verbose) {
+	xmlChar *doc = getString(cur, "string(documentation)");
+
+	if (doc != NULL) {
+	    printf("Suite %s\n", doc);
+	    xmlFree(doc);
+	}
+    }
+    cur = getNext(cur, "./testCase[1]");
+    while (cur != NULL) {
+        xsdTestCase(cur);
+	cur = getNext(cur, "following-sibling::testCase[1]");
+    }
+
+    return(0);
+}
+
+static int
+xsdTest(void) {
+    xmlDocPtr doc;
+    xmlNodePtr cur;
+    const char *filename = "test/xsdtest/xsdtestsuite.xml";
+    int ret = 0;
+
+    doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT);
+    if (doc == NULL) {
+        fprintf(stderr, "Failed to parse %s\n", filename);
+	return(-1);
+    }
+    printf("## XML Schemas datatypes test suite from James Clark\n");
+
+    cur = xmlDocGetRootElement(doc);
+    if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
+        fprintf(stderr, "Unexpected format %s\n", filename);
+	ret = -1;
+	goto done;
+    }
+
+    cur = getNext(cur, "./testSuite[1]");
+    if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
+        fprintf(stderr, "Unexpected format %s\n", filename);
+	ret = -1;
+	goto done;
+    }
+    while (cur != NULL) {
+        xsdTestSuite(cur);
+	cur = getNext(cur, "following-sibling::testSuite[1]");
+    }
+
+done:
+    if (doc != NULL)
+	xmlFreeDoc(doc);
+    return(ret);
+}
+
+static int
+rngTestSuite(xmlNodePtr cur) {
+    if (verbose) {
+	xmlChar *doc = getString(cur, "string(documentation)");
+
+	if (doc != NULL) {
+	    printf("Suite %s\n", doc);
+	    xmlFree(doc);
+	} else {
+	    doc = getString(cur, "string(section)");
+	    if (doc != NULL) {
+		printf("Section %s\n", doc);
+		xmlFree(doc);
+	    }
+	}
+    }
+    cur = getNext(cur, "./testSuite[1]");
+    while (cur != NULL) {
+        xsdTestSuite(cur);
+	cur = getNext(cur, "following-sibling::testSuite[1]");
+    }
+
+    return(0);
+}
+
+static int
+rngTest1(void) {
+    xmlDocPtr doc;
+    xmlNodePtr cur;
+    const char *filename = "test/relaxng/OASIS/spectest.xml";
+    int ret = 0;
+
+    doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT);
+    if (doc == NULL) {
+        fprintf(stderr, "Failed to parse %s\n", filename);
+	return(-1);
+    }
+    printf("## Relax NG test suite from James Clark\n");
+
+    cur = xmlDocGetRootElement(doc);
+    if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
+        fprintf(stderr, "Unexpected format %s\n", filename);
+	ret = -1;
+	goto done;
+    }
+
+    cur = getNext(cur, "./testSuite[1]");
+    if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
+        fprintf(stderr, "Unexpected format %s\n", filename);
+	ret = -1;
+	goto done;
+    }
+    while (cur != NULL) {
+        rngTestSuite(cur);
+	cur = getNext(cur, "following-sibling::testSuite[1]");
+    }
+
+done:
+    if (doc != NULL)
+	xmlFreeDoc(doc);
+    return(ret);
+}
+
+static int
+rngTest2(void) {
+    xmlDocPtr doc;
+    xmlNodePtr cur;
+    const char *filename = "test/relaxng/testsuite.xml";
+    int ret = 0;
+
+    doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT);
+    if (doc == NULL) {
+        fprintf(stderr, "Failed to parse %s\n", filename);
+	return(-1);
+    }
+    printf("## Relax NG test suite for libxml2\n");
+
+    cur = xmlDocGetRootElement(doc);
+    if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
+        fprintf(stderr, "Unexpected format %s\n", filename);
+	ret = -1;
+	goto done;
+    }
+
+    cur = getNext(cur, "./testSuite[1]");
+    if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
+        fprintf(stderr, "Unexpected format %s\n", filename);
+	ret = -1;
+	goto done;
+    }
+    while (cur != NULL) {
+        xsdTestSuite(cur);
+	cur = getNext(cur, "following-sibling::testSuite[1]");
+    }
+
+done:
+    if (doc != NULL)
+	xmlFreeDoc(doc);
+    return(ret);
+}
+
+/************************************************************************
+ *									*
+ *		Schemas test suites from W3C/NIST/MS/Sun		*
+ *									*
+ ************************************************************************/
+
+static int
+xstcTestInstance(xmlNodePtr cur, xmlSchemaPtr schemas,
+                 const xmlChar *spath, const char *base) {
+    xmlChar *href = NULL;
+    xmlChar *path = NULL;
+    xmlChar *validity = NULL;
+    xmlSchemaValidCtxtPtr ctxt = NULL;
+    xmlDocPtr doc = NULL;
+    int ret = 0, mem;
+
+    xmlResetLastError();
+    testErrorsSize = 0; testErrors[0] = 0;
+    mem = xmlMemUsed();
+    href = getString(cur,
+                     "string(ts:instanceDocument/@xlink:href)");
+    if ((href == NULL) || (href[0] == 0)) {
+	test_log("testGroup line %ld misses href for schemaDocument\n",
+		    xmlGetLineNo(cur));
+	ret = -1;
+	goto done;
+    }
+    path = xmlBuildURI(href, BAD_CAST base);
+    if (path == NULL) {
+	fprintf(stderr,
+	        "Failed to build path to schemas testGroup line %ld : %s\n",
+		xmlGetLineNo(cur), href);
+	ret = -1;
+	goto done;
+    }
+    if (checkTestFile((const char *) path) <= 0) {
+	test_log("schemas for testGroup line %ld is missing: %s\n",
+		xmlGetLineNo(cur), path);
+	ret = -1;
+	goto done;
+    }
+    validity = getString(cur,
+                         "string(ts:expected/@validity)");
+    if (validity == NULL) {
+        fprintf(stderr, "instanceDocument line %ld misses expected validity\n",
+	        xmlGetLineNo(cur));
+	ret = -1;
+	goto done;
+    }
+    nb_tests++;
+    doc = xmlReadFile((const char *) path, NULL, XML_PARSE_NOENT);
+    if (doc == NULL) {
+        fprintf(stderr, "instance %s fails to parse\n", path);
+	ret = -1;
+	nb_errors++;
+	goto done;
+    }
+
+    ctxt = xmlSchemaNewValidCtxt(schemas);
+    xmlSchemaSetValidErrors(ctxt, testErrorHandler, testErrorHandler, ctxt);
+    ret = xmlSchemaValidateDoc(ctxt, doc);
+
+    if (xmlStrEqual(validity, BAD_CAST "valid")) {
+	if (ret > 0) {
+	    test_log("valid instance %s failed to validate against %s\n",
+			path, spath);
+	    nb_errors++;
+	} else if (ret < 0) {
+	    test_log("valid instance %s got internal error validating %s\n",
+			path, spath);
+	    nb_internals++;
+	    nb_errors++;
+	}
+    } else if (xmlStrEqual(validity, BAD_CAST "invalid")) {
+	if (ret == 0) {
+	    test_log("Failed to detect invalid instance %s against %s\n",
+			path, spath);
+	    nb_errors++;
+	}
+    } else {
+        test_log("instanceDocument line %ld has unexpected validity value%s\n",
+	        xmlGetLineNo(cur), validity);
+	ret = -1;
+	goto done;
+    }
+
+done:
+    if (href != NULL) xmlFree(href);
+    if (path != NULL) xmlFree(path);
+    if (validity != NULL) xmlFree(validity);
+    if (ctxt != NULL) xmlSchemaFreeValidCtxt(ctxt);
+    if (doc != NULL) xmlFreeDoc(doc);
+    xmlResetLastError();
+    if (mem != xmlMemUsed()) {
+	test_log("Validation of tests starting line %ld leaked %d\n",
+		xmlGetLineNo(cur), xmlMemUsed() - mem);
+	nb_leaks++;
+    }
+    return(ret);
+}
+
+static int
+xstcTestGroup(xmlNodePtr cur, const char *base) {
+    xmlChar *href = NULL;
+    xmlChar *path = NULL;
+    xmlChar *validity = NULL;
+    xmlSchemaPtr schemas = NULL;
+    xmlSchemaParserCtxtPtr ctxt;
+    xmlNodePtr instance;
+    int ret = 0, mem;
+
+    xmlResetLastError();
+    testErrorsSize = 0; testErrors[0] = 0;
+    mem = xmlMemUsed();
+    href = getString(cur,
+                     "string(ts:schemaTest/ts:schemaDocument/@xlink:href)");
+    if ((href == NULL) || (href[0] == 0)) {
+        test_log("testGroup line %ld misses href for schemaDocument\n",
+		    xmlGetLineNo(cur));
+	ret = -1;
+	goto done;
+    }
+    path = xmlBuildURI(href, BAD_CAST base);
+    if (path == NULL) {
+	test_log("Failed to build path to schemas testGroup line %ld : %s\n",
+		xmlGetLineNo(cur), href);
+	ret = -1;
+	goto done;
+    }
+    if (checkTestFile((const char *) path) <= 0) {
+	test_log("schemas for testGroup line %ld is missing: %s\n",
+		xmlGetLineNo(cur), path);
+	ret = -1;
+	goto done;
+    }
+    validity = getString(cur,
+                         "string(ts:schemaTest/ts:expected/@validity)");
+    if (validity == NULL) {
+        test_log("testGroup line %ld misses expected validity\n",
+	        xmlGetLineNo(cur));
+	ret = -1;
+	goto done;
+    }
+    nb_tests++;
+    if (xmlStrEqual(validity, BAD_CAST "valid")) {
+        nb_schematas++;
+	ctxt = xmlSchemaNewParserCtxt((const char *) path);
+	xmlSchemaSetParserErrors(ctxt, testErrorHandler, testErrorHandler,
+                ctxt);
+	schemas = xmlSchemaParse(ctxt);
+	xmlSchemaFreeParserCtxt(ctxt);
+	if (schemas == NULL) {
+	    test_log("valid schemas %s failed to parse\n",
+			path);
+	    ret = 1;
+	    nb_errors++;
+	}
+	if ((ret == 0) && (strstr(testErrors, "nimplemented") != NULL)) {
+	    test_log("valid schemas %s hit an unimplemented block\n",
+			path);
+	    ret = 1;
+	    nb_unimplemented++;
+	    nb_errors++;
+	}
+	instance = getNext(cur, "./ts:instanceTest[1]");
+	while (instance != NULL) {
+	    if (schemas != NULL) {
+		xstcTestInstance(instance, schemas, path, base);
+	    } else {
+		/*
+		* We'll automatically mark the instances as failed
+		* if the schema was broken.
+		*/
+		nb_errors++;
+	    }
+	    instance = getNext(instance,
+		"following-sibling::ts:instanceTest[1]");
+	}
+    } else if (xmlStrEqual(validity, BAD_CAST "invalid")) {
+        nb_schematas++;
+	ctxt = xmlSchemaNewParserCtxt((const char *) path);
+	xmlSchemaSetParserErrors(ctxt, testErrorHandler, testErrorHandler,
+                ctxt);
+	schemas = xmlSchemaParse(ctxt);
+	xmlSchemaFreeParserCtxt(ctxt);
+	if (schemas != NULL) {
+	    test_log("Failed to detect error in schemas %s\n",
+			path);
+	    nb_errors++;
+	    ret = 1;
+	}
+	if ((ret == 0) && (strstr(testErrors, "nimplemented") != NULL)) {
+	    nb_unimplemented++;
+	    test_log("invalid schemas %s hit an unimplemented block\n",
+			path);
+	    ret = 1;
+	    nb_errors++;
+	}
+    } else {
+        test_log("testGroup line %ld misses unexpected validity value%s\n",
+	        xmlGetLineNo(cur), validity);
+	ret = -1;
+	goto done;
+    }
+
+done:
+    if (href != NULL) xmlFree(href);
+    if (path != NULL) xmlFree(path);
+    if (validity != NULL) xmlFree(validity);
+    if (schemas != NULL) xmlSchemaFree(schemas);
+    xmlResetLastError();
+    if ((mem != xmlMemUsed()) && (extraMemoryFromResolver == 0)) {
+	test_log("Processing test line %ld %s leaked %d\n",
+		xmlGetLineNo(cur), path, xmlMemUsed() - mem);
+	nb_leaks++;
+    }
+    return(ret);
+}
+
+static int
+xstcMetadata(const char *metadata, const char *base) {
+    xmlDocPtr doc;
+    xmlNodePtr cur;
+    xmlChar *contributor;
+    xmlChar *name;
+    int ret = 0;
+
+    doc = xmlReadFile(metadata, NULL, XML_PARSE_NOENT);
+    if (doc == NULL) {
+        fprintf(stderr, "Failed to parse %s\n", metadata);
+	return(-1);
+    }
+
+    cur = xmlDocGetRootElement(doc);
+    if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSet"))) {
+        fprintf(stderr, "Unexpected format %s\n", metadata);
+	return(-1);
+    }
+    contributor = xmlGetProp(cur, BAD_CAST "contributor");
+    if (contributor == NULL) {
+        contributor = xmlStrdup(BAD_CAST "Unknown");
+    }
+    name = xmlGetProp(cur, BAD_CAST "name");
+    if (name == NULL) {
+        name = xmlStrdup(BAD_CAST "Unknown");
+    }
+    printf("## %s test suite for Schemas version %s\n", contributor, name);
+    xmlFree(contributor);
+    xmlFree(name);
+
+    cur = getNext(cur, "./ts:testGroup[1]");
+    if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testGroup"))) {
+        fprintf(stderr, "Unexpected format %s\n", metadata);
+	ret = -1;
+	goto done;
+    }
+    while (cur != NULL) {
+        xstcTestGroup(cur, base);
+	cur = getNext(cur, "following-sibling::ts:testGroup[1]");
+    }
+
+done:
+    xmlFreeDoc(doc);
+    return(ret);
+}
+
+/************************************************************************
+ *									*
+ *		The driver for the tests				*
+ *									*
+ ************************************************************************/
+
+int
+main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    int ret = 0;
+    int old_errors, old_tests, old_leaks, expected_errors;
+
+    logfile = fopen(LOGFILE, "w");
+    if (logfile == NULL) {
+        fprintf(stderr,
+	        "Could not open the log file, running in verbose mode\n");
+	verbose = 1;
+    }
+    initializeLibxml2();
+
+    if ((argc >= 2) && (!strcmp(argv[1], "-v")))
+        verbose = 1;
+
+
+    old_errors = nb_errors;
+    old_tests = nb_tests;
+    old_leaks = nb_leaks;
+    xsdTest();
+    expected_errors = 3;
+    printf("Ran %d tests, %d errors, %d leaks\n",
+           nb_tests - old_tests,
+           nb_errors - old_errors,
+           nb_leaks - old_leaks);
+    if (nb_errors - old_errors == expected_errors) {
+        printf("%d errors were expected\n", expected_errors);
+        nb_errors = old_errors;
+    } else {
+        printf("%d errors were expected, got %d errors\n",
+               expected_errors, nb_errors - old_errors);
+        nb_errors = old_errors + 1;
+    }
+
+    old_errors = nb_errors;
+    old_tests = nb_tests;
+    old_leaks = nb_leaks;
+    rngTest1();
+    if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
+	printf("Ran %d tests, no errors\n", nb_tests - old_tests);
+    else
+	printf("Ran %d tests, %d errors, %d leaks\n",
+	       nb_tests - old_tests,
+	       nb_errors - old_errors,
+	       nb_leaks - old_leaks);
+
+    old_errors = nb_errors;
+    old_tests = nb_tests;
+    old_leaks = nb_leaks;
+    rngTest2();
+    if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
+	printf("Ran %d tests, no errors\n", nb_tests - old_tests);
+    else
+	printf("Ran %d tests, %d errors, %d leaks\n",
+	       nb_tests - old_tests,
+	       nb_errors - old_errors,
+	       nb_leaks - old_leaks);
+
+    old_errors = nb_errors;
+    old_tests = nb_tests;
+    old_leaks = nb_leaks;
+    nb_internals = 0;
+    nb_schematas = 0;
+    xstcMetadata("xstc/Tests/Metadata/NISTXMLSchemaDatatypes.testSet",
+		 "xstc/Tests/Metadata/");
+    if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
+	printf("Ran %d tests (%d schemata), no errors\n",
+	       nb_tests - old_tests, nb_schematas);
+    else
+	printf("Ran %d tests (%d schemata), %d errors (%d internals), %d leaks\n",
+	       nb_tests - old_tests,
+	       nb_schematas,
+	       nb_errors - old_errors,
+	       nb_internals,
+	       nb_leaks - old_leaks);
+
+    old_errors = nb_errors;
+    old_tests = nb_tests;
+    old_leaks = nb_leaks;
+    nb_internals = 0;
+    nb_schematas = 0;
+    xstcMetadata("xstc/Tests/Metadata/SunXMLSchema1-0-20020116.testSet",
+		 "xstc/Tests/");
+    if ((nb_errors == old_errors) && (nb_leaks == old_leaks)) {
+	printf("Ran %d tests (%d schemata), no errors\n",
+	       nb_tests - old_tests, nb_schematas);
+    } else {
+	printf("Ran %d tests (%d schemata), %d errors (%d internals), %d leaks\n",
+	       nb_tests - old_tests,
+	       nb_schematas,
+	       nb_errors - old_errors,
+	       nb_internals,
+	       nb_leaks - old_leaks);
+        printf("Some errors were expected.\n");
+        nb_errors = old_errors;
+    }
+
+    old_errors = nb_errors;
+    old_tests = nb_tests;
+    old_leaks = nb_leaks;
+    nb_internals = 0;
+    nb_schematas = 0;
+    xstcMetadata("xstc/Tests/Metadata/MSXMLSchema1-0-20020116.testSet",
+		 "xstc/Tests/");
+    if ((nb_errors == old_errors) && (nb_leaks == old_leaks)) {
+	printf("Ran %d tests (%d schemata), no errors\n",
+	       nb_tests - old_tests, nb_schematas);
+    } else {
+	printf("Ran %d tests (%d schemata), %d errors (%d internals), %d leaks\n",
+	       nb_tests - old_tests,
+	       nb_schematas,
+	       nb_errors - old_errors,
+	       nb_internals,
+	       nb_leaks - old_leaks);
+        printf("Some errors were expected.\n");
+        nb_errors = old_errors;
+    }
+
+    if ((nb_errors == 0) && (nb_leaks == 0)) {
+        ret = 0;
+	printf("Total %d tests, no errors\n",
+	       nb_tests);
+    } else {
+        ret = 1;
+	printf("Total %d tests, %d errors, %d leaks\n",
+	       nb_tests, nb_errors, nb_leaks);
+    }
+    xmlXPathFreeContext(ctxtXPath);
+    xmlCleanupParser();
+
+    if (logfile != NULL)
+        fclose(logfile);
+    return(ret);
+}
+#else /* !SCHEMAS */
+int
+main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    fprintf(stderr, "runsuite requires support for schemas and xpath in libxml2\n");
+}
+#endif
diff --git a/runtest.c b/runtest.c
new file mode 100644
index 0000000000000000000000000000000000000000..26681a3c207cbc038e1ae58fea608179dced03d1
--- /dev/null
+++ b/runtest.c
@@ -0,0 +1,5129 @@
+/*
+ * runtest.c: C program to run libxml2 regression tests without
+ *            requiring make or Python, and reducing platform dependencies
+ *            to a strict minimum.
+ *
+ * To compile on Unixes:
+ * cc -o runtest `xml2-config --cflags` runtest.c `xml2-config --libs` -lpthread
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define XML_DEPRECATED
+
+#include "libxml.h"
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#elif defined (_WIN32)
+#include <io.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/tree.h>
+#include <libxml/uri.h>
+#include <libxml/encoding.h>
+
+#ifdef LIBXML_OUTPUT_ENABLED
+#ifdef LIBXML_READER_ENABLED
+#include <libxml/xmlreader.h>
+#endif
+
+#ifdef LIBXML_XINCLUDE_ENABLED
+#include <libxml/xinclude.h>
+#endif
+
+#ifdef LIBXML_XPATH_ENABLED
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#ifdef LIBXML_XPTR_ENABLED
+#include <libxml/xpointer.h>
+#endif
+#endif
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/relaxng.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/xmlschemastypes.h>
+#endif
+
+#ifdef LIBXML_PATTERN_ENABLED
+#include <libxml/pattern.h>
+#endif
+
+#ifdef LIBXML_C14N_ENABLED
+#include <libxml/c14n.h>
+#endif
+
+#ifdef LIBXML_HTML_ENABLED
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+#endif
+
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
+#include <libxml/threads.h>
+#include <libxml/parser.h>
+#include <libxml/catalog.h>
+#endif
+
+/*
+ * pseudo flag for the unification of HTML and XML tests
+ */
+#define XML_PARSE_HTML 1 << 24
+
+/*
+ * O_BINARY is just for Windows compatibility - if it isn't defined
+ * on this system, avoid any compilation error
+ */
+#ifdef	O_BINARY
+#define RD_FLAGS	O_RDONLY | O_BINARY
+#define WR_FLAGS	O_WRONLY | O_CREAT | O_TRUNC | O_BINARY
+#else
+#define RD_FLAGS	O_RDONLY
+#define WR_FLAGS	O_WRONLY | O_CREAT | O_TRUNC
+#endif
+
+typedef int (*functest) (const char *filename, const char *result,
+                         const char *error, int options);
+
+typedef struct testDesc testDesc;
+typedef testDesc *testDescPtr;
+struct testDesc {
+    const char *desc; /* description of the test */
+    functest    func; /* function implementing the test */
+    const char *in;   /* glob to path for input files */
+    const char *out;  /* output directory */
+    const char *suffix;/* suffix for output files */
+    const char *err;  /* suffix for error output files */
+    int     options;  /* parser options for the test */
+};
+
+static int update_results = 0;
+static char* temp_directory = NULL;
+static int checkTestFile(const char *filename);
+
+#if defined(_WIN32)
+
+#include <windows.h>
+
+typedef struct
+{
+      size_t gl_pathc;    /* Count of paths matched so far  */
+      char **gl_pathv;    /* List of matched pathnames.  */
+      size_t gl_offs;     /* Slots to reserve in 'gl_pathv'.  */
+} glob_t;
+
+#define GLOB_DOOFFS 0
+static int glob(const char *pattern, ATTRIBUTE_UNUSED int flags,
+                ATTRIBUTE_UNUSED int errfunc(const char *epath, int eerrno),
+                glob_t *pglob) {
+    glob_t *ret;
+    WIN32_FIND_DATA FindFileData;
+    HANDLE hFind;
+    unsigned int nb_paths = 0;
+    char directory[500];
+    int len;
+
+    if ((pattern == NULL) || (pglob == NULL)) return(-1);
+
+    strncpy(directory, pattern, 499);
+    for (len = strlen(directory);len >= 0;len--) {
+        if (directory[len] == '/') {
+	    len++;
+	    directory[len] = 0;
+	    break;
+	}
+    }
+    if (len <= 0)
+        len = 0;
+
+
+    ret = pglob;
+    memset(ret, 0, sizeof(glob_t));
+
+    hFind = FindFirstFileA(pattern, &FindFileData);
+    if (hFind == INVALID_HANDLE_VALUE)
+        return(0);
+    nb_paths = 20;
+    ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
+    if (ret->gl_pathv == NULL) {
+	FindClose(hFind);
+        return(-1);
+    }
+    strncpy(directory + len, FindFileData.cFileName, 499 - len);
+    ret->gl_pathv[ret->gl_pathc] = strdup(directory);
+    if (ret->gl_pathv[ret->gl_pathc] == NULL)
+        goto done;
+    ret->gl_pathc++;
+    while(FindNextFileA(hFind, &FindFileData)) {
+        if (FindFileData.cFileName[0] == '.')
+	    continue;
+        if (ret->gl_pathc + 2 > nb_paths) {
+            char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
+            if (tmp == NULL)
+                break;
+            ret->gl_pathv = tmp;
+            nb_paths *= 2;
+	}
+	strncpy(directory + len, FindFileData.cFileName, 499 - len);
+	ret->gl_pathv[ret->gl_pathc] = strdup(directory);
+        if (ret->gl_pathv[ret->gl_pathc] == NULL)
+            break;
+        ret->gl_pathc++;
+    }
+    ret->gl_pathv[ret->gl_pathc] = NULL;
+
+done:
+    FindClose(hFind);
+    return(0);
+}
+
+
+
+static void globfree(glob_t *pglob) {
+    unsigned int i;
+    if (pglob == NULL)
+        return;
+
+    for (i = 0;i < pglob->gl_pathc;i++) {
+         if (pglob->gl_pathv[i] != NULL)
+             free(pglob->gl_pathv[i]);
+    }
+}
+
+#else
+#include <glob.h>
+#endif
+
+/************************************************************************
+ *									*
+ *		Libxml2 specific routines				*
+ *									*
+ ************************************************************************/
+
+static int nb_tests = 0;
+static int nb_errors = 0;
+static int nb_leaks = 0;
+static int extraMemoryFromResolver = 0;
+
+static int
+fatalError(void) {
+    fprintf(stderr, "Exitting tests on fatal error\n");
+    exit(1);
+}
+
+/*
+ * We need to trap calls to the resolver to not account memory for the catalog
+ * which is shared to the current running test. We also don't want to have
+ * network downloads modifying tests.
+ */
+static xmlParserInputPtr
+testExternalEntityLoader(const char *URL, const char *ID,
+			 xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr ret;
+
+    if (checkTestFile(URL)) {
+	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+    } else {
+	int memused = xmlMemUsed();
+	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+	extraMemoryFromResolver += xmlMemUsed() - memused;
+    }
+
+    return(ret);
+}
+
+/*
+ * Trapping the error messages at the generic level to grab the equivalent of
+ * stderr messages on CLI tools.
+ */
+static char testErrors[32769];
+static int testErrorsSize = 0;
+
+static void
+testErrorHandler(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
+    va_list args;
+    int res;
+
+    if (testErrorsSize >= 32768)
+        return;
+    va_start(args, msg);
+    res = vsnprintf(&testErrors[testErrorsSize],
+                    32768 - testErrorsSize,
+		    msg, args);
+    va_end(args);
+    if (testErrorsSize + res >= 32768) {
+        /* buffer is full */
+	testErrorsSize = 32768;
+	testErrors[testErrorsSize] = 0;
+    } else {
+        testErrorsSize += res;
+    }
+    testErrors[testErrorsSize] = 0;
+}
+
+static void
+testStructuredErrorHandler(void *ctx ATTRIBUTE_UNUSED, const xmlError *err) {
+    xmlFormatError(err, testErrorHandler, NULL);
+}
+
+static void
+initializeLibxml2(void) {
+    /*
+     * This verifies that xmlInitParser doesn't allocate memory with
+     * xmlMalloc
+     */
+    xmlFree = NULL;
+    xmlMalloc = NULL;
+    xmlRealloc = NULL;
+    xmlMemStrdup = NULL;
+    xmlInitParser();
+    xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
+    xmlSetExternalEntityLoader(testExternalEntityLoader);
+#ifdef LIBXML_SCHEMAS_ENABLED
+    xmlSchemaInitTypes();
+    xmlRelaxNGInitTypes();
+#endif
+}
+
+
+/************************************************************************
+ *									*
+ *		File name and path utilities				*
+ *									*
+ ************************************************************************/
+
+static const char *baseFilename(const char *filename) {
+    const char *cur;
+    if (filename == NULL)
+        return(NULL);
+    cur = &filename[strlen(filename)];
+    while ((cur > filename) && (*cur != '/'))
+        cur--;
+    if (*cur == '/')
+        return(cur + 1);
+    return(cur);
+}
+
+static char *resultFilename(const char *filename, const char *out,
+                            const char *suffix) {
+    const char *base;
+    char res[500];
+    char suffixbuff[500];
+
+/*************
+    if ((filename[0] == 't') && (filename[1] == 'e') &&
+        (filename[2] == 's') && (filename[3] == 't') &&
+	(filename[4] == '/'))
+	filename = &filename[5];
+ *************/
+
+    base = baseFilename(filename);
+    if (suffix == NULL)
+        suffix = ".tmp";
+    if (out == NULL)
+        out = "";
+
+    strncpy(suffixbuff,suffix,499);
+
+    if (snprintf(res, 499, "%s%s%s", out, base, suffixbuff) >= 499)
+        res[499] = 0;
+    return(strdup(res));
+}
+
+static int checkTestFile(const char *filename) {
+    struct stat buf;
+
+    if (stat(filename, &buf) == -1)
+        return(0);
+
+#if defined(_WIN32)
+    if (!(buf.st_mode & _S_IFREG))
+        return(0);
+#else
+    if (!S_ISREG(buf.st_mode))
+        return(0);
+#endif
+
+    return(1);
+}
+
+static int compareFiles(const char *r1 /* temp */, const char *r2 /* result */) {
+    int res1, res2, total;
+    int fd1, fd2;
+    char bytes1[4096];
+    char bytes2[4096];
+
+    if (update_results) {
+        fd1 = open(r1, RD_FLAGS);
+        if (fd1 < 0)
+            return(-1);
+        fd2 = open(r2, WR_FLAGS, 0644);
+        if (fd2 < 0) {
+            close(fd1);
+            return(-1);
+        }
+        total = 0;
+        do {
+            res1 = read(fd1, bytes1, 4096);
+            if (res1 <= 0)
+                break;
+            total += res1;
+            res2 = write(fd2, bytes1, res1);
+            if (res2 <= 0 || res2 != res1)
+                break;
+        } while (1);
+        close(fd2);
+        close(fd1);
+        if (total == 0)
+            unlink(r2);
+        return(res1 != 0);
+    }
+
+    fd1 = open(r1, RD_FLAGS);
+    if (fd1 < 0)
+        return(-1);
+    fd2 = open(r2, RD_FLAGS);
+    while (1) {
+        res1 = read(fd1, bytes1, 4096);
+        res2 = fd2 >= 0 ? read(fd2, bytes2, 4096) : 0;
+	if ((res1 != res2) || (res1 < 0)) {
+	    close(fd1);
+            if (fd2 >= 0)
+                close(fd2);
+	    return(1);
+	}
+	if (res1 == 0)
+	    break;
+	if (memcmp(bytes1, bytes2, res1) != 0) {
+	    close(fd1);
+            if (fd2 >= 0)
+                close(fd2);
+	    return(1);
+	}
+    }
+    close(fd1);
+    if (fd2 >= 0)
+        close(fd2);
+    return(0);
+}
+
+static int compareFileMem(const char *filename, const char *mem, int size) {
+    int res;
+    int fd;
+    char bytes[4096];
+    int idx = 0;
+    struct stat info;
+
+    if (update_results) {
+        if (size == 0) {
+            unlink(filename);
+            return(0);
+        }
+        fd = open(filename, WR_FLAGS, 0644);
+        if (fd < 0) {
+	    fprintf(stderr, "failed to open %s for writing", filename);
+            return(-1);
+	}
+        res = write(fd, mem, size);
+        close(fd);
+        return(res != size);
+    }
+
+    if (stat(filename, &info) < 0) {
+        if (size == 0)
+            return(0);
+        fprintf(stderr, "failed to stat %s\n", filename);
+	return(-1);
+    }
+    if (info.st_size != size) {
+        fprintf(stderr, "file %s is %ld bytes, result is %d bytes\n",
+	        filename, (long) info.st_size, size);
+        return(-1);
+    }
+    fd = open(filename, RD_FLAGS);
+    if (fd < 0) {
+	fprintf(stderr, "failed to open %s for reading", filename);
+        return(-1);
+    }
+    while (idx < size) {
+        res = read(fd, bytes, 4096);
+	if (res <= 0)
+	    break;
+	if (res + idx > size)
+	    break;
+	if (memcmp(bytes, &mem[idx], res) != 0) {
+	    int ix;
+	    for (ix=0; ix<res; ix++)
+		if (bytes[ix] != mem[idx+ix])
+			break;
+	    fprintf(stderr,"Compare error at position %d\n", idx+ix);
+	    close(fd);
+	    return(1);
+	}
+	idx += res;
+    }
+    close(fd);
+    if (idx != size) {
+	fprintf(stderr,"Compare error index %d, size %d\n", idx, size);
+    }
+    return(idx != size);
+}
+
+static int loadMem(const char *filename, const char **mem, int *size) {
+    int fd, res;
+    struct stat info;
+    char *base;
+    int siz = 0;
+    if (stat(filename, &info) < 0)
+	return(-1);
+    base = malloc(info.st_size + 1);
+    if (base == NULL)
+	return(-1);
+    if ((fd = open(filename, RD_FLAGS)) < 0) {
+        free(base);
+	return(-1);
+    }
+    while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
+        siz += res;
+    }
+    close(fd);
+#if !defined(_WIN32)
+    if (siz != info.st_size) {
+        free(base);
+	return(-1);
+    }
+#endif
+    base[siz] = 0;
+    *mem = base;
+    *size = siz;
+    return(0);
+}
+
+static int unloadMem(const char *mem) {
+    free((char *)mem);
+    return(0);
+}
+
+/************************************************************************
+ *									*
+ *		Tests implementations					*
+ *									*
+ ************************************************************************/
+
+/************************************************************************
+ *									*
+ *		Parse to SAX based tests				*
+ *									*
+ ************************************************************************/
+
+static FILE *SAXdebug = NULL;
+
+/*
+ * empty SAX block
+ */
+static xmlSAXHandler emptySAXHandlerStruct = {
+    NULL, /* internalSubset */
+    NULL, /* isStandalone */
+    NULL, /* hasInternalSubset */
+    NULL, /* hasExternalSubset */
+    NULL, /* resolveEntity */
+    NULL, /* getEntity */
+    NULL, /* entityDecl */
+    NULL, /* notationDecl */
+    NULL, /* attributeDecl */
+    NULL, /* elementDecl */
+    NULL, /* unparsedEntityDecl */
+    NULL, /* setDocumentLocator */
+    NULL, /* startDocument */
+    NULL, /* endDocument */
+    NULL, /* startElement */
+    NULL, /* endElement */
+    NULL, /* reference */
+    NULL, /* characters */
+    NULL, /* ignorableWhitespace */
+    NULL, /* processingInstruction */
+    NULL, /* comment */
+    NULL, /* xmlParserWarning */
+    NULL, /* xmlParserError */
+    NULL, /* xmlParserError */
+    NULL, /* getParameterEntity */
+    NULL, /* cdataBlock; */
+    NULL, /* externalSubset; */
+    1,
+    NULL,
+    NULL, /* startElementNs */
+    NULL, /* endElementNs */
+    NULL  /* xmlStructuredErrorFunc */
+};
+
+typedef struct {
+    const char *filename;
+    xmlHashTablePtr generalEntities;
+    xmlHashTablePtr parameterEntities;
+} debugContext;
+
+static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
+static int callbacks = 0;
+static int quiet = 0;
+
+/**
+ * isStandaloneDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Is this document tagged standalone ?
+ *
+ * Returns 1 if true
+ */
+static int
+isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (quiet)
+	return(0);
+    fprintf(SAXdebug, "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 (quiet)
+	return(0);
+    fprintf(SAXdebug, "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 (quiet)
+	return(0);
+    fprintf(SAXdebug, "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 (quiet)
+	return;
+    if (name == NULL)
+        name = BAD_CAST "(null)";
+    fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
+    if (ExternalID == NULL)
+	fprintf(SAXdebug, " ,");
+    else
+	fprintf(SAXdebug, " %s,", ExternalID);
+    if (SystemID == NULL)
+	fprintf(SAXdebug, " )\n");
+    else
+	fprintf(SAXdebug, " %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 (quiet)
+	return;
+    fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
+    if (ExternalID == NULL)
+	fprintf(SAXdebug, " ,");
+    else
+	fprintf(SAXdebug, " %s,", ExternalID);
+    if (SystemID == NULL)
+	fprintf(SAXdebug, " )\n");
+    else
+	fprintf(SAXdebug, " %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 (quiet)
+	return(NULL);
+    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
+
+
+    fprintf(SAXdebug, "SAX.resolveEntity(");
+    if (publicId != NULL)
+	fprintf(SAXdebug, "%s", (char *)publicId);
+    else
+	fprintf(SAXdebug, " ");
+    if (systemId != NULL)
+	fprintf(SAXdebug, ", %s)\n", (char *)systemId);
+    else
+	fprintf(SAXdebug, ", )\n");
+/*********
+    if (systemId != NULL) {
+        return(xmlNewInputFromFile(ctxt, (char *) systemId));
+    }
+ *********/
+    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, const xmlChar *name)
+{
+    debugContext *ctxt = ctx;
+
+    callbacks++;
+    if (quiet)
+	return(NULL);
+    fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
+
+    return(xmlHashLookup(ctxt->generalEntities, name));
+}
+
+/**
+ * getParameterEntityDebug:
+ * @ctxt:  An XML parser context
+ * @name: The entity name
+ *
+ * Get a parameter entity by name
+ *
+ * Returns the xmlParserInputPtr
+ */
+static xmlEntityPtr
+getParameterEntityDebug(void *ctx, const xmlChar *name)
+{
+    debugContext *ctxt = ctx;
+
+    callbacks++;
+    if (quiet)
+	return(NULL);
+    fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
+
+    return(xmlHashLookup(ctxt->parameterEntities, name));
+}
+
+
+/**
+ * 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, const xmlChar *name, int type,
+          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
+{
+    debugContext *ctxt = ctx;
+    xmlEntityPtr ent;
+    const xmlChar *nullstr = BAD_CAST "(null)";
+
+    ent = xmlNewEntity(NULL, name, type, publicId, systemId, content);
+    if (systemId != NULL)
+        ent->URI = xmlBuildURI(systemId, (const xmlChar *) ctxt->filename);
+
+    if ((type == XML_INTERNAL_PARAMETER_ENTITY) ||
+        (type == XML_EXTERNAL_PARAMETER_ENTITY))
+        xmlHashAddEntry(ctxt->parameterEntities, name, ent);
+    else
+        xmlHashAddEntry(ctxt->generalEntities, name, ent);
+
+    /* 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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 (quiet)
+        return;
+    if (defaultValue == NULL)
+        fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
+                elem, name, type, def);
+    else
+        fprintf(SAXdebug, "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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 (quiet)
+	return;
+    fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
+    if (atts != NULL) {
+        for (i = 0;(atts[i] != NULL);i++) {
+	    fprintf(SAXdebug, ", %s='", atts[i++]);
+	    if (atts[i] != NULL)
+	        fprintf(SAXdebug, "%s'", atts[i]);
+	}
+    }
+    fprintf(SAXdebug, ")\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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 output[40];
+    int i;
+
+    callbacks++;
+    if (quiet)
+	return;
+    for (i = 0;(i<len) && (i < 30);i++)
+	output[i] = (char) ch[i];
+    output[i] = 0;
+
+    fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, 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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 output[40];
+    int i;
+
+    callbacks++;
+    if (quiet)
+	return;
+    for (i = 0;(i<len) && (i < 30);i++)
+	output[i] = (char) ch[i];
+    output[i] = 0;
+    fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, 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 (quiet)
+	return;
+    if (data != NULL)
+	fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
+		(char *) target, (char *) data);
+    else
+	fprintf(SAXdebug, "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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 (quiet)
+	return;
+    fprintf(SAXdebug, "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 (quiet)
+	return;
+    va_start(args, msg);
+    fprintf(SAXdebug, "SAX.warning: ");
+    vfprintf(SAXdebug, 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 (quiet)
+	return;
+    va_start(args, msg);
+    fprintf(SAXdebug, "SAX.error: ");
+    vfprintf(SAXdebug, 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 (quiet)
+	return;
+    va_start(args, msg);
+    fprintf(SAXdebug, "SAX.fatalError: ");
+    vfprintf(SAXdebug, msg, args);
+    va_end(args);
+}
+
+static xmlSAXHandler debugSAXHandlerStruct = {
+    internalSubsetDebug,
+    isStandaloneDebug,
+    hasInternalSubsetDebug,
+    hasExternalSubsetDebug,
+    resolveEntityDebug,
+    getEntityDebug,
+    entityDeclDebug,
+    notationDeclDebug,
+    attributeDeclDebug,
+    elementDeclDebug,
+    unparsedEntityDeclDebug,
+    setDocumentLocatorDebug,
+    startDocumentDebug,
+    endDocumentDebug,
+    startElementDebug,
+    endElementDebug,
+    referenceDebug,
+    charactersDebug,
+    ignorableWhitespaceDebug,
+    processingInstructionDebug,
+    commentDebug,
+    warningDebug,
+    errorDebug,
+    fatalErrorDebug,
+    getParameterEntityDebug,
+    cdataBlockDebug,
+    externalSubsetDebug,
+    1,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+static 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 (quiet)
+	return;
+    fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
+    if (prefix == NULL)
+	fprintf(SAXdebug, ", NULL");
+    else
+	fprintf(SAXdebug, ", %s", (char *) prefix);
+    if (URI == NULL)
+	fprintf(SAXdebug, ", NULL");
+    else
+	fprintf(SAXdebug, ", '%s'", (char *) URI);
+    fprintf(SAXdebug, ", %d", nb_namespaces);
+
+    if (namespaces != NULL) {
+        for (i = 0;i < nb_namespaces * 2;i++) {
+	    fprintf(SAXdebug, ", xmlns");
+	    if (namespaces[i] != NULL)
+	        fprintf(SAXdebug, ":%s", namespaces[i]);
+	    i++;
+	    fprintf(SAXdebug, "='%s'", namespaces[i]);
+	}
+    }
+    fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
+    if (attributes != NULL) {
+        for (i = 0;i < nb_attributes * 5;i += 5) {
+	    if (attributes[i + 1] != NULL)
+		fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
+	    else
+		fprintf(SAXdebug, ", %s='", attributes[i]);
+	    fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
+		    (int)(attributes[i + 4] - attributes[i + 3]));
+	}
+    }
+    fprintf(SAXdebug, ")\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 (quiet)
+	return;
+    fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
+    if (prefix == NULL)
+	fprintf(SAXdebug, ", NULL");
+    else
+	fprintf(SAXdebug, ", %s", (char *) prefix);
+    if (URI == NULL)
+	fprintf(SAXdebug, ", NULL)\n");
+    else
+	fprintf(SAXdebug, ", '%s')\n", (char *) URI);
+}
+
+static xmlSAXHandler debugSAX2HandlerStruct = {
+    internalSubsetDebug,
+    isStandaloneDebug,
+    hasInternalSubsetDebug,
+    hasExternalSubsetDebug,
+    resolveEntityDebug,
+    getEntityDebug,
+    entityDeclDebug,
+    notationDeclDebug,
+    attributeDeclDebug,
+    elementDeclDebug,
+    unparsedEntityDeclDebug,
+    setDocumentLocatorDebug,
+    startDocumentDebug,
+    endDocumentDebug,
+    NULL,
+    NULL,
+    referenceDebug,
+    charactersDebug,
+    ignorableWhitespaceDebug,
+    processingInstructionDebug,
+    commentDebug,
+    warningDebug,
+    errorDebug,
+    fatalErrorDebug,
+    getParameterEntityDebug,
+    cdataBlockDebug,
+    externalSubsetDebug,
+    XML_SAX2_MAGIC,
+    NULL,
+    startElementNsDebug,
+    endElementNsDebug,
+    NULL
+};
+
+static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
+
+#ifdef LIBXML_HTML_ENABLED
+/**
+ * htmlstartElementDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The element name
+ *
+ * called when an opening tag has been processed.
+ */
+static void
+htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
+{
+    int i;
+
+    fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
+    if (atts != NULL) {
+        for (i = 0;(atts[i] != NULL);i++) {
+	    fprintf(SAXdebug, ", %s", atts[i++]);
+	    if (atts[i] != NULL) {
+		unsigned char output[40];
+		const unsigned char *att = atts[i];
+		int outlen, attlen;
+	        fprintf(SAXdebug, "='");
+		while ((attlen = strlen((char*)att)) > 0) {
+		    outlen = sizeof output - 1;
+		    htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
+		    output[outlen] = 0;
+		    fprintf(SAXdebug, "%s", (char *) output);
+		    att += attlen;
+		}
+		fprintf(SAXdebug, "'");
+	    }
+	}
+    }
+    fprintf(SAXdebug, ")\n");
+}
+
+/**
+ * htmlcharactersDebug:
+ * @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
+htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+    unsigned char output[40];
+    int inlen = len, outlen = 30;
+
+    htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
+    output[outlen] = 0;
+
+    fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
+}
+
+/**
+ * htmlcdataDebug:
+ * @ctxt:  An XML parser context
+ * @ch:  a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some cdata chars from the parser.
+ * Question: how much at a time ???
+ */
+static void
+htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+    unsigned char output[40];
+    int inlen = len, outlen = 30;
+
+    htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
+    output[outlen] = 0;
+
+    fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
+}
+
+static xmlSAXHandler debugHTMLSAXHandlerStruct = {
+    internalSubsetDebug,
+    isStandaloneDebug,
+    hasInternalSubsetDebug,
+    hasExternalSubsetDebug,
+    resolveEntityDebug,
+    getEntityDebug,
+    entityDeclDebug,
+    notationDeclDebug,
+    attributeDeclDebug,
+    elementDeclDebug,
+    unparsedEntityDeclDebug,
+    setDocumentLocatorDebug,
+    startDocumentDebug,
+    endDocumentDebug,
+    htmlstartElementDebug,
+    endElementDebug,
+    referenceDebug,
+    htmlcharactersDebug,
+    ignorableWhitespaceDebug,
+    processingInstructionDebug,
+    commentDebug,
+    warningDebug,
+    errorDebug,
+    fatalErrorDebug,
+    getParameterEntityDebug,
+    htmlcdataDebug,
+    externalSubsetDebug,
+    1,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+static xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
+#endif /* LIBXML_HTML_ENABLED */
+
+static void
+hashFreeEntity(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
+    xmlEntityPtr ent = payload;
+
+    xmlFreeEntity(ent);
+}
+
+/**
+ * saxParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the SAX API and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+saxParseTest(const char *filename, const char *result,
+             const char *err ATTRIBUTE_UNUSED,
+             int options) {
+    int ret;
+    char *temp;
+
+    nb_tests++;
+    temp = resultFilename(filename, temp_directory, ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "out of memory\n");
+        fatalError();
+    }
+    SAXdebug = fopen(temp, "wb");
+    if (SAXdebug == NULL) {
+        fprintf(stderr, "Failed to write to %s\n", temp);
+	free(temp);
+	return(-1);
+    }
+
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML) {
+        htmlParserCtxtPtr ctxt;
+
+        ctxt = htmlNewSAXParserCtxt(emptySAXHandler, NULL);
+        htmlCtxtReadFile(ctxt, filename, NULL, options);
+        htmlFreeParserCtxt(ctxt);
+	ret = 0;
+    } else
+#endif
+    {
+        xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename);
+        memcpy(ctxt->sax, emptySAXHandler, sizeof(xmlSAXHandler));
+        xmlCtxtUseOptions(ctxt, options);
+        xmlParseDocument(ctxt);
+        ret = ctxt->wellFormed ? 0 : ctxt->errNo;
+        xmlFreeDoc(ctxt->myDoc);
+        xmlFreeParserCtxt(ctxt);
+    }
+    if (ret == XML_ERR_UNDECLARED_ENTITY) {
+        fprintf(SAXdebug, "xmlParseDocument returned error %d\n", ret);
+        ret = 0;
+    }
+    if (ret != 0) {
+        fprintf(stderr, "Failed to parse %s\n", filename);
+	ret = 1;
+	goto done;
+    }
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML) {
+        htmlParserCtxtPtr ctxt;
+
+        ctxt = htmlNewSAXParserCtxt(debugHTMLSAXHandler, NULL);
+        htmlCtxtReadFile(ctxt, filename, NULL, options);
+        htmlFreeParserCtxt(ctxt);
+	ret = 0;
+    } else
+#endif
+    {
+        debugContext userData;
+        xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename);
+
+        if (options & XML_PARSE_SAX1) {
+            memcpy(ctxt->sax, debugSAXHandler, sizeof(xmlSAXHandler));
+            options -= XML_PARSE_SAX1;
+        } else {
+            memcpy(ctxt->sax, debugSAX2Handler, sizeof(xmlSAXHandler));
+        }
+        userData.filename = filename;
+        userData.generalEntities = xmlHashCreate(0);
+        userData.parameterEntities = xmlHashCreate(0);
+        ctxt->userData = &userData;
+        xmlCtxtUseOptions(ctxt, options);
+        xmlParseDocument(ctxt);
+        ret = ctxt->wellFormed ? 0 : ctxt->errNo;
+        xmlHashFree(userData.generalEntities, hashFreeEntity);
+        xmlHashFree(userData.parameterEntities, hashFreeEntity);
+        xmlFreeDoc(ctxt->myDoc);
+        xmlFreeParserCtxt(ctxt);
+    }
+    fclose(SAXdebug);
+    if (compareFiles(temp, result)) {
+        fprintf(stderr, "Got a difference for %s\n", filename);
+        ret = 1;
+    }
+
+done:
+    if (temp != NULL) {
+        unlink(temp);
+        free(temp);
+    }
+
+    return(ret);
+}
+
+/************************************************************************
+ *									*
+ *		Parse to tree based tests				*
+ *									*
+ ************************************************************************/
+/**
+ * oldParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file using the old xmlParseFile API, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+oldParseTest(const char *filename, const char *result,
+             const char *err ATTRIBUTE_UNUSED,
+	     int options ATTRIBUTE_UNUSED) {
+    xmlDocPtr doc;
+    char *temp;
+    int res = 0;
+
+    nb_tests++;
+    /*
+     * base of the test, parse with the old API
+     */
+#ifdef LIBXML_SAX1_ENABLED
+    xmlGetWarningsDefaultValue = 0;
+    doc = xmlParseFile(filename);
+    xmlGetWarningsDefaultValue = 1;
+#else
+    doc = xmlReadFile(filename, NULL, XML_PARSE_NOWARNING);
+#endif
+    if (doc == NULL)
+        return(1);
+    temp = resultFilename(filename, temp_directory, ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "out of memory\n");
+        fatalError();
+    }
+    xmlSaveFile(temp, doc);
+    if (compareFiles(temp, result)) {
+        res = 1;
+    }
+    xmlFreeDoc(doc);
+
+    /*
+     * Parse the saved result to make sure the round trip is okay
+     */
+#ifdef LIBXML_SAX1_ENABLED
+    xmlGetWarningsDefaultValue = 0;
+    doc = xmlParseFile(temp);
+    xmlGetWarningsDefaultValue = 1;
+#else
+    doc = xmlReadFile(temp, NULL, XML_PARSE_NOWARNING);
+#endif
+    if (doc == NULL)
+        return(1);
+    xmlSaveFile(temp, doc);
+    if (compareFiles(temp, result)) {
+        res = 1;
+    }
+    xmlFreeDoc(doc);
+
+    if (temp != NULL) {
+        unlink(temp);
+        free(temp);
+    }
+
+    return(res);
+}
+
+#ifdef LIBXML_PUSH_ENABLED
+/**
+ * pushParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file using the Push API, then serialize back
+ * to check for content.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+pushParseTest(const char *filename, const char *result,
+             const char *err ATTRIBUTE_UNUSED,
+	     int options) {
+    xmlParserCtxtPtr ctxt;
+    xmlDocPtr doc;
+    const char *base;
+    int size, res;
+    int cur = 0;
+    int chunkSize = 4;
+
+    nb_tests++;
+    /*
+     * load the document in memory and work from there.
+     */
+    if (loadMem(filename, &base, &size) != 0) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+
+    if (chunkSize > size)
+        chunkSize = size;
+
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML)
+	ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, chunkSize, filename,
+	                                XML_CHAR_ENCODING_NONE);
+    else
+#endif
+    ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, chunkSize, filename);
+    xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL);
+    xmlCtxtUseOptions(ctxt, options);
+    cur += chunkSize;
+    chunkSize = 1024;
+    do {
+        if (cur + chunkSize >= size) {
+#ifdef LIBXML_HTML_ENABLED
+	    if (options & XML_PARSE_HTML)
+		htmlParseChunk(ctxt, base + cur, size - cur, 1);
+	    else
+#endif
+	    xmlParseChunk(ctxt, base + cur, size - cur, 1);
+	    break;
+	} else {
+#ifdef LIBXML_HTML_ENABLED
+	    if (options & XML_PARSE_HTML)
+		htmlParseChunk(ctxt, base + cur, chunkSize, 0);
+	    else
+#endif
+	    xmlParseChunk(ctxt, base + cur, chunkSize, 0);
+	    cur += chunkSize;
+	}
+    } while (cur < size);
+    doc = ctxt->myDoc;
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML)
+        res = 1;
+    else
+#endif
+    res = ctxt->wellFormed;
+    xmlFreeParserCtxt(ctxt);
+    free((char *)base);
+    if (!res) {
+	xmlFreeDoc(doc);
+	fprintf(stderr, "Failed to parse %s\n", filename);
+	return(-1);
+    }
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML)
+	htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+    else
+#endif
+    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+    xmlFreeDoc(doc);
+    res = compareFileMem(result, base, size);
+    if ((base == NULL) || (res != 0)) {
+	if (base != NULL)
+	    xmlFree((char *)base);
+        fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+	return(-1);
+    }
+    xmlFree((char *)base);
+    if (err != NULL) {
+	res = compareFileMem(err, testErrors, testErrorsSize);
+	if (res != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    return(-1);
+	}
+    }
+    return(0);
+}
+
+static int pushBoundaryCount;
+static int pushBoundaryRefCount;
+static int pushBoundaryCharsCount;
+static int pushBoundaryCDataCount;
+
+static void
+internalSubsetBnd(void *ctx, const xmlChar *name, const xmlChar *externalID,
+                  const xmlChar *systemID) {
+    pushBoundaryCount++;
+    xmlSAX2InternalSubset(ctx, name, externalID, systemID);
+}
+
+static void
+referenceBnd(void *ctx, const xmlChar *name) {
+    pushBoundaryRefCount++;
+    xmlSAX2Reference(ctx, name);
+}
+
+static void
+charactersBnd(void *ctx, const xmlChar *ch, int len) {
+    pushBoundaryCount++;
+    pushBoundaryCharsCount++;
+    xmlSAX2Characters(ctx, ch, len);
+}
+
+static void
+cdataBlockBnd(void *ctx, const xmlChar *ch, int len) {
+    pushBoundaryCount++;
+    pushBoundaryCDataCount++;
+    xmlSAX2CDataBlock(ctx, ch, len);
+}
+
+static void
+processingInstructionBnd(void *ctx, const xmlChar *target,
+                         const xmlChar *data) {
+    pushBoundaryCount++;
+    xmlSAX2ProcessingInstruction(ctx, target, data);
+}
+
+static void
+commentBnd(void *ctx, const xmlChar *value) {
+    xmlParserCtxtPtr ctxt = ctx;
+    if (ctxt->inSubset == 0)
+        pushBoundaryCount++;
+    xmlSAX2Comment(ctx, value);
+}
+
+static void
+startElementBnd(void *ctx, const xmlChar *xname, const xmlChar **atts) {
+    const char *name = (const char *)xname;
+
+    /* Some elements might be created automatically. */
+    if ((strcmp(name, "html") != 0) &&
+        (strcmp(name, "body") != 0) &&
+        (strcmp(name, "head") != 0) &&
+        (strcmp(name, "p") != 0)) {
+        pushBoundaryCount++;
+    }
+    xmlSAX2StartElement(ctx, xname, atts);
+}
+
+static void
+endElementBnd(void *ctx, const xmlChar *name) {
+    /*pushBoundaryCount++;*/
+    xmlSAX2EndElement(ctx, name);
+}
+
+static void
+startElementNsBnd(void *ctx, const xmlChar *localname, const xmlChar *prefix,
+                  const xmlChar *URI, int nb_namespaces,
+                  const xmlChar **namespaces, int nb_attributes,
+                  int nb_defaulted, const xmlChar **attributes) {
+    pushBoundaryCount++;
+    xmlSAX2StartElementNs(ctx, localname, prefix, URI, nb_namespaces,
+                          namespaces, nb_attributes, nb_defaulted, attributes);
+}
+
+static void
+endElementNsBnd(void *ctx, const xmlChar *localname, const xmlChar *prefix,
+                const xmlChar *URI) {
+    /*pushBoundaryCount++;*/
+    xmlSAX2EndElementNs(ctx, localname, prefix, URI);
+}
+
+/**
+ * pushBoundaryTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Test whether the push parser detects boundaries between syntactical
+ * elements correctly.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+pushBoundaryTest(const char *filename, const char *result,
+                 const char *err ATTRIBUTE_UNUSED,
+                 int options) {
+    xmlParserCtxtPtr ctxt;
+    xmlDocPtr doc;
+    xmlSAXHandler bndSAX;
+    const char *base;
+    int size, res, numCallbacks;
+    int cur = 0;
+    unsigned long avail, oldConsumed, consumed;
+
+    /*
+     * HTML encoding detection doesn't work when data is fed bytewise.
+     */
+    if (strcmp(filename, "./test/HTML/xml-declaration-1.html") == 0)
+        return(0);
+
+    /*
+     * If the parser made progress, check that exactly one construct was
+     * processed and that the input buffer is (almost) empty.
+     * Since we use a chunk size of 1, this tests whether content is
+     * processed as early as possible.
+     */
+
+    nb_tests++;
+
+    memset(&bndSAX, 0, sizeof(bndSAX));
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML) {
+        xmlSAX2InitHtmlDefaultSAXHandler(&bndSAX);
+        bndSAX.startElement = startElementBnd;
+        bndSAX.endElement = endElementBnd;
+    } else
+#endif
+    {
+        xmlSAXVersion(&bndSAX, 2);
+        bndSAX.startElementNs = startElementNsBnd;
+        bndSAX.endElementNs = endElementNsBnd;
+    }
+
+    bndSAX.internalSubset = internalSubsetBnd;
+    bndSAX.reference = referenceBnd;
+    bndSAX.characters = charactersBnd;
+    bndSAX.cdataBlock = cdataBlockBnd;
+    bndSAX.processingInstruction = processingInstructionBnd;
+    bndSAX.comment = commentBnd;
+
+    /*
+     * load the document in memory and work from there.
+     */
+    if (loadMem(filename, &base, &size) != 0) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML)
+	ctxt = htmlCreatePushParserCtxt(&bndSAX, NULL, base, 1, filename,
+	                                XML_CHAR_ENCODING_NONE);
+    else
+#endif
+    ctxt = xmlCreatePushParserCtxt(&bndSAX, NULL, base, 1, filename);
+    xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL);
+    xmlCtxtUseOptions(ctxt, options);
+    cur = 1;
+    consumed = 0;
+    numCallbacks = 0;
+    avail = 0;
+    while ((cur < size) && (numCallbacks <= 1) && (avail <= 0)) {
+        int terminate = (cur + 1 >= size);
+        int isText = 0;
+
+        if (ctxt->instate == XML_PARSER_CONTENT) {
+            int firstChar = (ctxt->input->end > ctxt->input->cur) ?
+                            *ctxt->input->cur :
+                            base[cur];
+
+            if ((firstChar != '<') &&
+                ((options & XML_PARSE_HTML) || (firstChar != '&')))
+                isText = 1;
+        }
+
+        oldConsumed = ctxt->input->consumed +
+                      (unsigned long) (ctxt->input->cur - ctxt->input->base);
+
+        pushBoundaryCount = 0;
+        pushBoundaryRefCount = 0;
+        pushBoundaryCharsCount = 0;
+        pushBoundaryCDataCount = 0;
+
+#ifdef LIBXML_HTML_ENABLED
+        if (options & XML_PARSE_HTML)
+            htmlParseChunk(ctxt, base + cur, 1, terminate);
+        else
+#endif
+        xmlParseChunk(ctxt, base + cur, 1, terminate);
+	cur += 1;
+
+        /*
+         * Callback check: Check that only a single construct was parsed.
+         */
+        if (pushBoundaryRefCount > 0) {
+            numCallbacks = 1;
+        } else {
+            numCallbacks = pushBoundaryCount;
+            if (pushBoundaryCharsCount > 1) {
+                if (options & XML_PARSE_HTML) {
+                    /*
+                     * The HTML parser can generate a mix of chars and
+                     * references.
+                     */
+                    numCallbacks -= pushBoundaryCharsCount - 1;
+                } else {
+                    /*
+                     * Allow two chars callbacks. This can happen when
+                     * multi-byte chars are split across buffer boundaries.
+                     */
+                    numCallbacks -= 1;
+                }
+            }
+            if (options & XML_PARSE_HTML) {
+                /*
+                 * Allow multiple cdata callbacks in HTML mode.
+                 */
+                if (pushBoundaryCDataCount > 1)
+                    numCallbacks -= pushBoundaryCDataCount - 1;
+            }
+        }
+
+        /*
+         * Buffer check: If input was consumed, check that the input
+         * buffer is (almost) empty.
+         */
+        consumed = ctxt->input->consumed +
+                   (unsigned long) (ctxt->input->cur - ctxt->input->base);
+        if ((ctxt->instate != XML_PARSER_DTD) &&
+            (consumed >= 4) &&
+            (consumed != oldConsumed)) {
+            size_t max = 0;
+
+            avail = ctxt->input->end - ctxt->input->cur;
+
+            if ((options & XML_PARSE_HTML) &&
+                (ctxt->instate == XML_PARSER_END_TAG)) {
+                /* Something related to script parsing. */
+                max = 3;
+            } else if (isText) {
+                int c = *ctxt->input->cur;
+
+                /* 3 bytes for partial UTF-8 */
+                max = ((c == '<') || (c == '&')) ? 1 : 3;
+            } else if (ctxt->instate == XML_PARSER_CDATA_SECTION) {
+                /* 2 bytes for terminator, 3 bytes for UTF-8 */
+                max = 5;
+            }
+
+            if (avail <= max)
+                avail = 0;
+        }
+    }
+    doc = ctxt->myDoc;
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML)
+        res = 1;
+    else
+#endif
+    res = ctxt->wellFormed;
+    xmlFreeParserCtxt(ctxt);
+    free((char *)base);
+    if (numCallbacks > 1) {
+	xmlFreeDoc(doc);
+	fprintf(stderr, "Failed push boundary callback test (%d@%lu-%lu): %s\n",
+                numCallbacks, oldConsumed, consumed, filename);
+	return(-1);
+    }
+    if (avail > 0) {
+	xmlFreeDoc(doc);
+	fprintf(stderr, "Failed push boundary buffer test (%lu@%lu): %s\n",
+                avail, consumed, filename);
+	return(-1);
+    }
+    if (!res) {
+	xmlFreeDoc(doc);
+	fprintf(stderr, "Failed to parse %s\n", filename);
+	return(-1);
+    }
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML)
+	htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+    else
+#endif
+    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+    xmlFreeDoc(doc);
+    res = compareFileMem(result, base, size);
+    if ((base == NULL) || (res != 0)) {
+	if (base != NULL)
+	    xmlFree((char *)base);
+        fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+	return(-1);
+    }
+    xmlFree((char *)base);
+    if (err != NULL) {
+	res = compareFileMem(err, testErrors, testErrorsSize);
+	if (res != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    return(-1);
+	}
+    }
+    return(0);
+}
+#endif
+
+/**
+ * memParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file using the old xmlReadMemory API, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+memParseTest(const char *filename, const char *result,
+             const char *err ATTRIBUTE_UNUSED,
+	     int options ATTRIBUTE_UNUSED) {
+    xmlDocPtr doc;
+    const char *base;
+    int size, res;
+
+    nb_tests++;
+    /*
+     * load and parse the memory
+     */
+    if (loadMem(filename, &base, &size) != 0) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+
+    doc = xmlReadMemory(base, size, filename, NULL, XML_PARSE_NOWARNING);
+    unloadMem(base);
+    if (doc == NULL) {
+        return(1);
+    }
+    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+    xmlFreeDoc(doc);
+    res = compareFileMem(result, base, size);
+    if ((base == NULL) || (res != 0)) {
+	if (base != NULL)
+	    xmlFree((char *)base);
+        fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+	return(-1);
+    }
+    xmlFree((char *)base);
+    return(0);
+}
+
+/**
+ * noentParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file with entity resolution, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+noentParseTest(const char *filename, const char *result,
+               const char *err  ATTRIBUTE_UNUSED,
+	       int options) {
+    xmlDocPtr doc;
+    char *temp;
+    int res = 0;
+
+    nb_tests++;
+    /*
+     * base of the test, parse with the old API
+     */
+    doc = xmlReadFile(filename, NULL,
+                      options | XML_PARSE_NOWARNING | XML_PARSE_NOERROR);
+    if (doc == NULL)
+        return(1);
+    temp = resultFilename(filename, temp_directory, ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    xmlSaveFile(temp, doc);
+    if (compareFiles(temp, result)) {
+        res = 1;
+    }
+    xmlFreeDoc(doc);
+
+    /*
+     * Parse the saved result to make sure the round trip is okay
+     */
+    doc = xmlReadFile(filename, NULL,
+                      options | XML_PARSE_NOWARNING | XML_PARSE_NOERROR);
+    if (doc == NULL)
+        return(1);
+    xmlSaveFile(temp, doc);
+    if (compareFiles(temp, result)) {
+        res = 1;
+    }
+    xmlFreeDoc(doc);
+
+    if (temp != NULL) {
+        unlink(temp);
+        free(temp);
+    }
+    return(res);
+}
+
+/**
+ * errParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the xmlReadFile API and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+errParseTest(const char *filename, const char *result, const char *err,
+             int options) {
+    xmlParserCtxtPtr ctxt;
+    xmlDocPtr doc;
+    const char *base = NULL;
+    int size, res = 0;
+
+    nb_tests++;
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML) {
+        ctxt = htmlNewParserCtxt();
+        xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL);
+        doc = htmlCtxtReadFile(ctxt, filename, NULL, options);
+        htmlFreeParserCtxt(ctxt);
+    } else
+#endif
+    {
+        ctxt = xmlNewParserCtxt();
+        xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL);
+	doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
+        xmlFreeParserCtxt(ctxt);
+#ifdef LIBXML_XINCLUDE_ENABLED
+        if (options & XML_PARSE_XINCLUDE) {
+            xmlXIncludeCtxtPtr xinc = NULL;
+
+            xinc = xmlXIncludeNewContext(doc);
+            xmlXIncludeSetErrorHandler(xinc, testStructuredErrorHandler, NULL);
+            xmlXIncludeSetFlags(xinc, options);
+            if (xmlXIncludeProcessNode(xinc, (xmlNodePtr) doc) < 0) {
+                testErrorHandler(NULL, "%s : failed to parse\n", filename);
+                xmlFreeDoc(doc);
+                doc = NULL;
+            }
+            xmlXIncludeFreeContext(xinc);
+        }
+#endif
+    }
+    if (result) {
+	if (doc == NULL) {
+	    base = "";
+	    size = 0;
+	} else {
+#ifdef LIBXML_HTML_ENABLED
+	    if (options & XML_PARSE_HTML) {
+		htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+	    } else
+#endif
+	    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+	}
+	res = compareFileMem(result, base, size);
+    }
+    if (doc != NULL) {
+	if (base != NULL)
+	    xmlFree((char *)base);
+	xmlFreeDoc(doc);
+    }
+    if (res != 0) {
+        fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+        return(-1);
+    }
+    if (err != NULL) {
+	res = compareFileMem(err, testErrors, testErrorsSize);
+	if (res != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    return(-1);
+	}
+    } else if (options & XML_PARSE_DTDVALID) {
+        if (testErrorsSize != 0)
+	    fprintf(stderr, "Validation for %s failed\n", filename);
+    }
+
+    return(0);
+}
+
+#if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_HTML_ENABLED)
+/**
+ * fdParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the xmlReadFd API and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+fdParseTest(const char *filename, const char *result, const char *err,
+             int options) {
+    xmlParserCtxtPtr ctxt;
+    xmlDocPtr doc;
+    const char *base = NULL;
+    int size, res = 0, fd;
+
+    nb_tests++;
+    fd = open(filename, RD_FLAGS);
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML) {
+        ctxt = htmlNewParserCtxt();
+        xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL);
+        doc = htmlCtxtReadFd(ctxt, fd, filename, NULL, options);
+        htmlFreeParserCtxt(ctxt);
+    } else
+#endif
+    {
+        ctxt = xmlNewParserCtxt();
+        xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL);
+	doc = xmlCtxtReadFd(ctxt, fd, filename, NULL, options);
+        xmlFreeParserCtxt(ctxt);
+    }
+    close(fd);
+    if (result) {
+	if (doc == NULL) {
+	    base = "";
+	    size = 0;
+	} else {
+#ifdef LIBXML_HTML_ENABLED
+	    if (options & XML_PARSE_HTML) {
+		htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+	    } else
+#endif
+	    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+	}
+	res = compareFileMem(result, base, size);
+    }
+    if (doc != NULL) {
+	if (base != NULL)
+	    xmlFree((char *)base);
+	xmlFreeDoc(doc);
+    }
+    if (res != 0) {
+        fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+        return(-1);
+    }
+    if (err != NULL) {
+	res = compareFileMem(err, testErrors, testErrorsSize);
+	if (res != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    return(-1);
+	}
+    } else if (options & XML_PARSE_DTDVALID) {
+        if (testErrorsSize != 0)
+	    fprintf(stderr, "Validation for %s failed\n", filename);
+    }
+
+    return(0);
+}
+#endif
+
+
+#ifdef LIBXML_READER_ENABLED
+/************************************************************************
+ *									*
+ *		Reader based tests					*
+ *									*
+ ************************************************************************/
+
+static void processNode(FILE *out, xmlTextReaderPtr reader) {
+    const xmlChar *name, *value;
+    int type, empty;
+
+    type = xmlTextReaderNodeType(reader);
+    empty = xmlTextReaderIsEmptyElement(reader);
+
+    name = xmlTextReaderConstName(reader);
+    if (name == NULL)
+	name = BAD_CAST "--";
+
+    value = xmlTextReaderConstValue(reader);
+
+
+    fprintf(out, "%d %d %s %d %d",
+	    xmlTextReaderDepth(reader),
+	    type,
+	    name,
+	    empty,
+	    xmlTextReaderHasValue(reader));
+    if (value == NULL)
+	fprintf(out, "\n");
+    else {
+	fprintf(out, " %s\n", value);
+    }
+}
+static int
+streamProcessTest(const char *filename, const char *result, const char *err,
+                  xmlTextReaderPtr reader, const char *rng,
+                  int options ATTRIBUTE_UNUSED) {
+    int ret;
+    char *temp = NULL;
+    FILE *t = NULL;
+
+    if (reader == NULL)
+        return(-1);
+
+    nb_tests++;
+    if (result != NULL) {
+	temp = resultFilename(filename, temp_directory, ".res");
+	if (temp == NULL) {
+	    fprintf(stderr, "Out of memory\n");
+	    fatalError();
+	}
+	t = fopen(temp, "wb");
+	if (t == NULL) {
+	    fprintf(stderr, "Can't open temp file %s\n", temp);
+	    free(temp);
+	    return(-1);
+	}
+    }
+#ifdef LIBXML_SCHEMAS_ENABLED
+    if (rng != NULL) {
+	ret = xmlTextReaderRelaxNGValidate(reader, rng);
+	if (ret < 0) {
+	    testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
+	                     rng);
+	    fclose(t);
+            if (temp != NULL) {
+                unlink(temp);
+                free(temp);
+            }
+	    return(0);
+	}
+    }
+#endif
+    ret = xmlTextReaderRead(reader);
+    while (ret == 1) {
+	if ((t != NULL) && (rng == NULL))
+	    processNode(t, reader);
+        ret = xmlTextReaderRead(reader);
+    }
+    if (ret != 0) {
+        testErrorHandler(NULL, "%s : failed to parse\n", filename);
+    }
+    if (rng != NULL) {
+        if (xmlTextReaderIsValid(reader) != 1) {
+	    testErrorHandler(NULL, "%s fails to validate\n", filename);
+	} else {
+	    testErrorHandler(NULL, "%s validates\n", filename);
+	}
+    }
+    if (t != NULL) {
+        fclose(t);
+	ret = compareFiles(temp, result);
+        if (temp != NULL) {
+            unlink(temp);
+            free(temp);
+        }
+	if (ret) {
+	    fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+	    return(-1);
+	}
+    }
+    if (err != NULL) {
+	ret = compareFileMem(err, testErrors, testErrorsSize);
+	if (ret != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    printf("%s", testErrors);
+	    return(-1);
+	}
+    }
+
+    return(0);
+}
+
+/**
+ * streamParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the reader API and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+streamParseTest(const char *filename, const char *result, const char *err,
+                int options) {
+    xmlTextReaderPtr reader;
+    int ret;
+
+    reader = xmlReaderForFile(filename, NULL, options);
+    xmlTextReaderSetStructuredErrorHandler(reader, testStructuredErrorHandler,
+                                           NULL);
+    ret = streamProcessTest(filename, result, err, reader, NULL, options);
+    xmlFreeTextReader(reader);
+    return(ret);
+}
+
+/**
+ * walkerParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the walker, i.e. a reader built from a atree.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+walkerParseTest(const char *filename, const char *result, const char *err,
+                int options) {
+    xmlDocPtr doc;
+    xmlTextReaderPtr reader;
+    int ret;
+
+    doc = xmlReadFile(filename, NULL, options | XML_PARSE_NOWARNING);
+    if (doc == NULL) {
+        fprintf(stderr, "Failed to parse %s\n", filename);
+	return(-1);
+    }
+    reader = xmlReaderWalker(doc);
+    ret = streamProcessTest(filename, result, err, reader, NULL, options);
+    xmlFreeTextReader(reader);
+    xmlFreeDoc(doc);
+    return(ret);
+}
+
+/**
+ * streamMemParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the reader API from memory and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+streamMemParseTest(const char *filename, const char *result, const char *err,
+                   int options) {
+    xmlTextReaderPtr reader;
+    int ret;
+    const char *base;
+    int size;
+
+    /*
+     * load and parse the memory
+     */
+    if (loadMem(filename, &base, &size) != 0) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+    reader = xmlReaderForMemory(base, size, filename, NULL, options);
+    xmlTextReaderSetStructuredErrorHandler(reader, testStructuredErrorHandler,
+                                           NULL);
+    ret = streamProcessTest(filename, result, err, reader, NULL, options);
+    free((char *)base);
+    xmlFreeTextReader(reader);
+    return(ret);
+}
+#endif
+
+#ifdef LIBXML_XPATH_ENABLED
+#ifdef LIBXML_DEBUG_ENABLED
+/************************************************************************
+ *									*
+ *		XPath and XPointer based tests				*
+ *									*
+ ************************************************************************/
+
+static FILE *xpathOutput;
+static xmlDocPtr xpathDocument;
+
+static void
+testXPath(const char *str, int xptr, int expr) {
+    xmlXPathObjectPtr res;
+    xmlXPathContextPtr ctxt;
+
+    nb_tests++;
+#if defined(LIBXML_XPTR_ENABLED)
+    if (xptr) {
+	ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
+        xmlXPathSetErrorHandler(ctxt, testStructuredErrorHandler, NULL);
+	res = xmlXPtrEval(BAD_CAST str, ctxt);
+    } else {
+#endif
+	ctxt = xmlXPathNewContext(xpathDocument);
+        xmlXPathSetErrorHandler(ctxt, testStructuredErrorHandler, NULL);
+	ctxt->node = xmlDocGetRootElement(xpathDocument);
+	if (expr)
+	    res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
+	else {
+	    /* res = xmlXPathEval(BAD_CAST str, ctxt); */
+	    xmlXPathCompExprPtr comp;
+
+	    comp = xmlXPathCompile(BAD_CAST str);
+	    if (comp != NULL) {
+		res = xmlXPathCompiledEval(comp, ctxt);
+		xmlXPathFreeCompExpr(comp);
+	    } else
+		res = NULL;
+	}
+#if defined(LIBXML_XPTR_ENABLED)
+    }
+#endif
+    xmlXPathDebugDumpObject(xpathOutput, res, 0);
+    xmlXPathFreeObject(res);
+    xmlXPathFreeContext(ctxt);
+}
+
+/**
+ * xpathExprTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath standalone expressions and evaluate them
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xpathCommonTest(const char *filename, const char *result,
+                int xptr, int expr) {
+    FILE *input;
+    char expression[5000];
+    int len, ret = 0;
+    char *temp;
+
+    temp = resultFilename(filename, temp_directory, ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    xpathOutput = fopen(temp, "wb");
+    if (xpathOutput == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+        free(temp);
+	return(-1);
+    }
+
+    input = fopen(filename, "rb");
+    if (input == NULL) {
+        fprintf(stderr,
+		"Cannot open %s for reading\n", filename);
+        free(temp);
+	return(-1);
+    }
+    while (fgets(expression, 4500, input) != NULL) {
+	len = strlen(expression);
+	len--;
+	while ((len >= 0) &&
+	       ((expression[len] == '\n') || (expression[len] == '\t') ||
+		(expression[len] == '\r') || (expression[len] == ' '))) len--;
+	expression[len + 1] = 0;
+	if (len >= 0) {
+	    fprintf(xpathOutput,
+	            "\n========================\nExpression: %s\n",
+		    expression) ;
+	    testXPath(expression, xptr, expr);
+	}
+    }
+
+    fclose(input);
+    fclose(xpathOutput);
+    if (result != NULL) {
+	ret = compareFiles(temp, result);
+	if (ret) {
+	    fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+	}
+    }
+
+    if (temp != NULL) {
+        unlink(temp);
+        free(temp);
+    }
+    return(ret);
+}
+
+/**
+ * xpathExprTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath standalone expressions and evaluate them
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xpathExprTest(const char *filename, const char *result,
+              const char *err ATTRIBUTE_UNUSED,
+              int options ATTRIBUTE_UNUSED) {
+    return(xpathCommonTest(filename, result, 0, 1));
+}
+
+/**
+ * xpathDocTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath expressions and evaluate them against
+ * a set of corresponding documents.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xpathDocTest(const char *filename,
+             const char *resul ATTRIBUTE_UNUSED,
+             const char *err ATTRIBUTE_UNUSED,
+             int options) {
+
+    char pattern[500];
+    char result[500];
+    glob_t globbuf;
+    size_t i;
+    int ret = 0, res;
+
+    xpathDocument = xmlReadFile(filename, NULL,
+                                options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
+    if (xpathDocument == NULL) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+
+    res = snprintf(pattern, 499, "./test/XPath/tests/%s*",
+            baseFilename(filename));
+    if (res >= 499)
+        pattern[499] = 0;
+    globbuf.gl_offs = 0;
+    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+    for (i = 0;i < globbuf.gl_pathc;i++) {
+        res = snprintf(result, 499, "result/XPath/tests/%s",
+	         baseFilename(globbuf.gl_pathv[i]));
+        if (res >= 499)
+            result[499] = 0;
+	res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
+	if (res != 0)
+	    ret = res;
+    }
+    globfree(&globbuf);
+
+    xmlFreeDoc(xpathDocument);
+    return(ret);
+}
+
+#ifdef LIBXML_XPTR_ENABLED
+/**
+ * xptrDocTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath expressions and evaluate them against
+ * a set of corresponding documents.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xptrDocTest(const char *filename,
+            const char *resul ATTRIBUTE_UNUSED,
+            const char *err ATTRIBUTE_UNUSED,
+            int options) {
+
+    char pattern[500];
+    char result[500];
+    glob_t globbuf;
+    size_t i;
+    int ret = 0, res;
+    const char *subdir = options == -1 ? "xptr-xp1" : "xptr";
+
+    xpathDocument = xmlReadFile(filename, NULL,
+                                XML_PARSE_DTDATTR | XML_PARSE_NOENT);
+    if (xpathDocument == NULL) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+
+    res = snprintf(pattern, 499, "./test/XPath/%s/%s*",
+            subdir, baseFilename(filename));
+    if (res >= 499)
+        pattern[499] = 0;
+    globbuf.gl_offs = 0;
+    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+    for (i = 0;i < globbuf.gl_pathc;i++) {
+        res = snprintf(result, 499, "result/XPath/%s/%s",
+	         subdir, baseFilename(globbuf.gl_pathv[i]));
+        if (res >= 499)
+            result[499] = 0;
+	res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
+	if (res != 0)
+	    ret = res;
+    }
+    globfree(&globbuf);
+
+    xmlFreeDoc(xpathDocument);
+    return(ret);
+}
+#endif /* LIBXML_XPTR_ENABLED */
+
+#ifdef LIBXML_VALID_ENABLED
+/**
+ * xmlidDocTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing xml:id and check for errors and verify
+ * that XPath queries will work on them as expected.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xmlidDocTest(const char *filename,
+             const char *result,
+             const char *err,
+             int options) {
+    xmlParserCtxtPtr ctxt;
+    int res = 0;
+    int ret = 0;
+    char *temp;
+
+    ctxt = xmlNewParserCtxt();
+    xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL);
+    xpathDocument = xmlCtxtReadFile(ctxt, filename, NULL,
+            options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
+    xmlFreeParserCtxt(ctxt);
+    if (xpathDocument == NULL) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+
+    temp = resultFilename(filename, temp_directory, ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    xpathOutput = fopen(temp, "wb");
+    if (xpathOutput == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+        xmlFreeDoc(xpathDocument);
+        free(temp);
+	return(-1);
+    }
+
+    testXPath("id('bar')", 0, 0);
+
+    fclose(xpathOutput);
+    if (result != NULL) {
+	ret = compareFiles(temp, result);
+	if (ret) {
+	    fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+	    res = 1;
+	}
+    }
+
+    if (temp != NULL) {
+        unlink(temp);
+        free(temp);
+    }
+    xmlFreeDoc(xpathDocument);
+
+    if (err != NULL) {
+	ret = compareFileMem(err, testErrors, testErrorsSize);
+	if (ret != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    res = 1;
+	}
+    }
+    return(res);
+}
+#endif /* LIBXML_VALID_ENABLED */
+
+#endif /* LIBXML_DEBUG_ENABLED */
+#endif /* XPATH */
+/************************************************************************
+ *									*
+ *			URI based tests					*
+ *									*
+ ************************************************************************/
+
+static void
+handleURI(const char *str, const char *base, FILE *o) {
+    int ret;
+    xmlURIPtr uri;
+    xmlChar *res = NULL;
+
+    uri = xmlCreateURI();
+
+    if (base == NULL) {
+	ret = xmlParseURIReference(uri, str);
+	if (ret != 0)
+	    fprintf(o, "%s : error %d\n", str, ret);
+	else {
+	    xmlNormalizeURIPath(uri->path);
+	    xmlPrintURI(o, uri);
+	    fprintf(o, "\n");
+	}
+    } else {
+	res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
+	if (res != NULL) {
+	    fprintf(o, "%s\n", (char *) res);
+	}
+	else
+	    fprintf(o, "::ERROR::\n");
+    }
+    if (res != NULL)
+	xmlFree(res);
+    xmlFreeURI(uri);
+}
+
+/**
+ * uriCommonTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI and check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+uriCommonTest(const char *filename,
+             const char *result,
+             const char *err,
+             const char *base) {
+    char *temp;
+    FILE *o, *f;
+    char str[1024];
+    int res = 0, i, ret;
+
+    temp = resultFilename(filename, temp_directory, ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    o = fopen(temp, "wb");
+    if (o == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+        free(temp);
+	return(-1);
+    }
+    f = fopen(filename, "rb");
+    if (f == NULL) {
+	fprintf(stderr, "failed to open input file %s\n", filename);
+	fclose(o);
+        if (temp != NULL) {
+            unlink(temp);
+            free(temp);
+        }
+	return(-1);
+    }
+
+    while (1) {
+	/*
+	 * read one line in string buffer.
+	 */
+	if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
+	   break;
+
+	/*
+	 * remove the ending spaces
+	 */
+	i = strlen(str);
+	while ((i > 0) &&
+	       ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
+		(str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
+	    i--;
+	    str[i] = 0;
+	}
+	nb_tests++;
+	handleURI(str, base, o);
+    }
+
+    fclose(f);
+    fclose(o);
+
+    if (result != NULL) {
+	ret = compareFiles(temp, result);
+	if (ret) {
+	    fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+	    res = 1;
+	}
+    }
+    if (err != NULL) {
+	ret = compareFileMem(err, testErrors, testErrorsSize);
+	if (ret != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    res = 1;
+	}
+    }
+
+    if (temp != NULL) {
+        unlink(temp);
+        free(temp);
+    }
+    return(res);
+}
+
+/**
+ * uriParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI and check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+uriParseTest(const char *filename,
+             const char *result,
+             const char *err,
+             int options ATTRIBUTE_UNUSED) {
+    return(uriCommonTest(filename, result, err, NULL));
+}
+
+/**
+ * uriBaseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI, compose them against a fixed base and
+ * check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+uriBaseTest(const char *filename,
+             const char *result,
+             const char *err,
+             int options ATTRIBUTE_UNUSED) {
+    return(uriCommonTest(filename, result, err,
+                         "http://foo.com/path/to/index.html?orig#help"));
+}
+
+static int urip_success = 1;
+static int urip_current = 0;
+static const char *urip_testURLs[] = {
+    "urip://example.com/a b.html",
+    "urip://example.com/a%20b.html",
+    "file:///path/to/a b.html",
+    "file:///path/to/a%20b.html",
+    "/path/to/a b.html",
+    "/path/to/a%20b.html",
+    "urip://example.com/r" "\xe9" "sum" "\xe9" ".html",
+    "urip://example.com/test?a=1&b=2%263&c=4#foo",
+    NULL
+};
+static const char *urip_rcvsURLs[] = {
+    /* it is an URI the strings must be escaped */
+    "urip://example.com/a%20b.html",
+    /* check that % escaping is not broken */
+    "urip://example.com/a%20b.html",
+    /* it's an URI path the strings must be escaped */
+    "file:///path/to/a%20b.html",
+    /* check that % escaping is not broken */
+    "file:///path/to/a%20b.html",
+    /* this is not an URI, this is a path, so this should not be escaped */
+    "/path/to/a b.html",
+    /* check that paths with % are not broken */
+    "/path/to/a%20b.html",
+    /* out of context the encoding can't be guessed byte by byte conversion */
+    "urip://example.com/r%E9sum%E9.html",
+    /* verify we don't destroy URIs especially the query part */
+    "urip://example.com/test?a=1&b=2%263&c=4#foo",
+    NULL
+};
+static const char *urip_res = "<list/>";
+static const char *urip_cur = NULL;
+static int urip_rlen;
+
+/**
+ * uripMatch:
+ * @URI: an URI to test
+ *
+ * Check for an urip: query
+ *
+ * Returns 1 if yes and 0 if another Input module should be used
+ */
+static int
+uripMatch(const char * URI) {
+    if ((URI == NULL) || (!strcmp(URI, "file://" SYSCONFDIR "/xml/catalog")))
+        return(0);
+    /* Verify we received the escaped URL */
+    if (strcmp(urip_rcvsURLs[urip_current], URI))
+	urip_success = 0;
+    return(1);
+}
+
+/**
+ * uripOpen:
+ * @URI: an URI to test
+ *
+ * Return a pointer to the urip: query handler, in this example simply
+ * the urip_current pointer...
+ *
+ * Returns an Input context or NULL in case or error
+ */
+static void *
+uripOpen(const char * URI) {
+    if ((URI == NULL) || (!strcmp(URI, "file://" SYSCONFDIR "/xml/catalog")))
+        return(NULL);
+    /* Verify we received the escaped URL */
+    if (strcmp(urip_rcvsURLs[urip_current], URI))
+	urip_success = 0;
+    urip_cur = urip_res;
+    urip_rlen = strlen(urip_res);
+    return((void *) urip_cur);
+}
+
+/**
+ * uripClose:
+ * @context: the read context
+ *
+ * Close the urip: query handler
+ *
+ * Returns 0 or -1 in case of error
+ */
+static int
+uripClose(void * context) {
+    if (context == NULL) return(-1);
+    urip_cur = NULL;
+    urip_rlen = 0;
+    return(0);
+}
+
+/**
+ * uripRead:
+ * @context: the read context
+ * @buffer: where to store data
+ * @len: number of bytes to read
+ *
+ * Implement an urip: query read.
+ *
+ * Returns the number of bytes read or -1 in case of error
+ */
+static int
+uripRead(void * context, char * buffer, int len) {
+   const char *ptr = (const char *) context;
+
+   if ((context == NULL) || (buffer == NULL) || (len < 0))
+       return(-1);
+
+   if (len > urip_rlen) len = urip_rlen;
+   memcpy(buffer, ptr, len);
+   urip_rlen -= len;
+   return(len);
+}
+
+static int
+urip_checkURL(const char *URL) {
+    xmlDocPtr doc;
+
+    doc = xmlReadFile(URL, NULL, 0);
+    if (doc == NULL)
+        return(-1);
+    xmlFreeDoc(doc);
+    return(1);
+}
+
+/**
+ * uriPathTest:
+ * @filename: ignored
+ * @result: ignored
+ * @err: ignored
+ *
+ * Run a set of tests to check how Path and URI are handled before
+ * being passed to the I/O layer
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+uriPathTest(const char *filename ATTRIBUTE_UNUSED,
+             const char *result ATTRIBUTE_UNUSED,
+             const char *err ATTRIBUTE_UNUSED,
+             int options ATTRIBUTE_UNUSED) {
+    int parsed;
+    int failures = 0;
+
+    /*
+     * register the new I/O handlers
+     */
+    if (xmlRegisterInputCallbacks(uripMatch, uripOpen, uripRead, uripClose) < 0)
+    {
+        fprintf(stderr, "failed to register HTTP handler\n");
+	return(-1);
+    }
+
+    for (urip_current = 0;urip_testURLs[urip_current] != NULL;urip_current++) {
+        urip_success = 1;
+        parsed = urip_checkURL(urip_testURLs[urip_current]);
+	if (urip_success != 1) {
+	    fprintf(stderr, "failed the URL passing test for %s",
+	            urip_testURLs[urip_current]);
+	    failures++;
+	} else if (parsed != 1) {
+	    fprintf(stderr, "failed the parsing test for %s",
+	            urip_testURLs[urip_current]);
+	    failures++;
+	}
+	nb_tests++;
+    }
+
+    xmlPopInputCallbacks();
+    return(failures);
+}
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+/************************************************************************
+ *									*
+ *			Schemas tests					*
+ *									*
+ ************************************************************************/
+static int
+schemasOneTest(const char *sch,
+               const char *filename,
+               const char *result,
+               const char *err,
+	       int options,
+	       xmlSchemaPtr schemas) {
+    int ret = 0;
+    int i;
+    char *temp;
+    int parseErrorsSize = testErrorsSize;
+
+    temp = resultFilename(result, temp_directory, ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+        return(-1);
+    }
+
+    /*
+     * Test both memory and streaming validation.
+     */
+    for (i = 0; i < 2; i++) {
+        xmlSchemaValidCtxtPtr ctxt;
+        int validResult = 0;
+        FILE *schemasOutput;
+
+        testErrorsSize = parseErrorsSize;
+        testErrors[parseErrorsSize] = 0;
+
+        if (schemas == NULL)
+            goto done;
+
+        ctxt = xmlSchemaNewValidCtxt(schemas);
+        xmlSchemaSetValidStructuredErrors(ctxt, testStructuredErrorHandler,
+                                          NULL);
+
+        schemasOutput = fopen(temp, "wb");
+        if (schemasOutput == NULL) {
+            fprintf(stderr, "failed to open output file %s\n", temp);
+            free(temp);
+            return(-1);
+        }
+
+        if (i == 0) {
+            xmlDocPtr doc;
+
+            doc = xmlReadFile(filename, NULL, options);
+            if (doc == NULL) {
+                fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
+                return(-1);
+            }
+            validResult = xmlSchemaValidateDoc(ctxt, doc);
+            xmlFreeDoc(doc);
+        } else {
+            validResult = xmlSchemaValidateFile(ctxt, filename, options);
+        }
+
+        if (validResult == 0) {
+            fprintf(schemasOutput, "%s validates\n", filename);
+        } else if (validResult > 0) {
+            fprintf(schemasOutput, "%s fails to validate\n", filename);
+        } else {
+            fprintf(schemasOutput, "%s validation generated an internal error\n",
+                   filename);
+        }
+        fclose(schemasOutput);
+
+        if (result) {
+            if (compareFiles(temp, result)) {
+                fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
+                ret = 1;
+            }
+        }
+
+        xmlSchemaFreeValidCtxt(ctxt);
+
+done:
+        if (compareFileMem(err, testErrors, testErrorsSize)) {
+            fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
+            ret = 1;
+        }
+
+        unlink(temp);
+    }
+
+    free(temp);
+    return(ret);
+}
+/**
+ * schemasTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI, compose them against a fixed base and
+ * check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+schemasTest(const char *filename,
+            const char *resul ATTRIBUTE_UNUSED,
+            const char *errr ATTRIBUTE_UNUSED,
+            int options) {
+    const char *base = baseFilename(filename);
+    const char *base2;
+    const char *instance;
+    xmlSchemaParserCtxtPtr ctxt;
+    xmlSchemaPtr schemas;
+    int res = 0, len, ret;
+    int parseErrorsSize;
+    char pattern[500];
+    char prefix[500];
+    char result[500];
+    char err[500];
+    glob_t globbuf;
+    size_t i;
+    char count = 0;
+
+    /* first compile the schemas if possible */
+    ctxt = xmlSchemaNewParserCtxt(filename);
+    xmlSchemaSetParserStructuredErrors(ctxt, testStructuredErrorHandler, NULL);
+    schemas = xmlSchemaParse(ctxt);
+    xmlSchemaFreeParserCtxt(ctxt);
+    parseErrorsSize = testErrorsSize;
+
+    /*
+     * most of the mess is about the output filenames generated by the Makefile
+     */
+    len = strlen(base);
+    if ((len > 499) || (len < 5)) {
+        xmlSchemaFree(schemas);
+	return(-1);
+    }
+    len -= 4; /* remove trailing .xsd */
+    if (base[len - 2] == '_') {
+        len -= 2; /* remove subtest number */
+    }
+    if (base[len - 2] == '_') {
+        len -= 2; /* remove subtest number */
+    }
+    memcpy(prefix, base, len);
+    prefix[len] = 0;
+
+    if (snprintf(pattern, 499, "./test/schemas/%s_*.xml", prefix) >= 499)
+        pattern[499] = 0;
+
+    if (base[len] == '_') {
+        len += 2;
+	memcpy(prefix, base, len);
+	prefix[len] = 0;
+    }
+
+    globbuf.gl_offs = 0;
+    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+    for (i = 0;i < globbuf.gl_pathc;i++) {
+        testErrorsSize = parseErrorsSize;
+        testErrors[parseErrorsSize] = 0;
+        instance = globbuf.gl_pathv[i];
+	base2 = baseFilename(instance);
+	len = strlen(base2);
+	if ((len > 6) && (base2[len - 6] == '_')) {
+	    count = base2[len - 5];
+	    ret = snprintf(result, 499, "result/schemas/%s_%c",
+		     prefix, count);
+            if (ret >= 499)
+	        result[499] = 0;
+	    ret = snprintf(err, 499, "result/schemas/%s_%c.err",
+		     prefix, count);
+            if (ret >= 499)
+	        err[499] = 0;
+	} else {
+	    fprintf(stderr, "don't know how to process %s\n", instance);
+	    continue;
+	}
+
+        nb_tests++;
+        ret = schemasOneTest(filename, instance, result, err,
+                             options, schemas);
+        if (ret != 0)
+            res = ret;
+    }
+    globfree(&globbuf);
+    xmlSchemaFree(schemas);
+
+    return(res);
+}
+
+/************************************************************************
+ *									*
+ *			Schemas tests					*
+ *									*
+ ************************************************************************/
+static int
+rngOneTest(const char *sch,
+               const char *filename,
+               const char *result,
+	       int options,
+	       xmlRelaxNGPtr schemas) {
+    xmlDocPtr doc;
+    xmlRelaxNGValidCtxtPtr ctxt;
+    int ret = 0;
+    char *temp;
+    FILE *schemasOutput;
+
+    doc = xmlReadFile(filename, NULL, options);
+    if (doc == NULL) {
+        fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
+	return(-1);
+    }
+
+    temp = resultFilename(result, temp_directory, ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    schemasOutput = fopen(temp, "wb");
+    if (schemasOutput == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+	xmlFreeDoc(doc);
+        free(temp);
+	return(-1);
+    }
+
+    ctxt = xmlRelaxNGNewValidCtxt(schemas);
+    xmlRelaxNGSetValidStructuredErrors(ctxt, testStructuredErrorHandler, NULL);
+    ret = xmlRelaxNGValidateDoc(ctxt, doc);
+    if (ret == 0) {
+	testErrorHandler(NULL, "%s validates\n", filename);
+    } else if (ret > 0) {
+	testErrorHandler(NULL, "%s fails to validate\n", filename);
+    } else {
+	testErrorHandler(NULL, "%s validation generated an internal error\n",
+	       filename);
+    }
+    fclose(schemasOutput);
+    ret = 0;
+    if (result) {
+	if (compareFiles(temp, result)) {
+	    fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
+	    ret = 1;
+	}
+    }
+    if (temp != NULL) {
+        unlink(temp);
+        free(temp);
+    }
+
+    xmlRelaxNGFreeValidCtxt(ctxt);
+    xmlFreeDoc(doc);
+    return(ret);
+}
+/**
+ * rngTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse an RNG schemas and then apply it to the related .xml
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+rngTest(const char *filename,
+            const char *resul ATTRIBUTE_UNUSED,
+            const char *errr ATTRIBUTE_UNUSED,
+            int options) {
+    const char *base = baseFilename(filename);
+    const char *base2;
+    const char *instance;
+    xmlRelaxNGParserCtxtPtr ctxt;
+    xmlRelaxNGPtr schemas;
+    int res = 0, len, ret = 0;
+    int parseErrorsSize;
+    char pattern[500];
+    char prefix[500];
+    char result[500];
+    char err[500];
+    glob_t globbuf;
+    size_t i;
+    char count = 0;
+
+    /* first compile the schemas if possible */
+    ctxt = xmlRelaxNGNewParserCtxt(filename);
+    xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler,
+                                        NULL);
+    schemas = xmlRelaxNGParse(ctxt);
+    xmlRelaxNGFreeParserCtxt(ctxt);
+    if (schemas == NULL)
+        testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
+                         filename);
+    parseErrorsSize = testErrorsSize;
+
+    /*
+     * most of the mess is about the output filenames generated by the Makefile
+     */
+    len = strlen(base);
+    if ((len > 499) || (len < 5)) {
+        xmlRelaxNGFree(schemas);
+	return(-1);
+    }
+    len -= 4; /* remove trailing .rng */
+    memcpy(prefix, base, len);
+    prefix[len] = 0;
+
+    if (snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix) >= 499)
+        pattern[499] = 0;
+
+    globbuf.gl_offs = 0;
+    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+    for (i = 0;i < globbuf.gl_pathc;i++) {
+        testErrorsSize = parseErrorsSize;
+        testErrors[parseErrorsSize] = 0;
+        instance = globbuf.gl_pathv[i];
+	base2 = baseFilename(instance);
+	len = strlen(base2);
+	if ((len > 6) && (base2[len - 6] == '_')) {
+	    count = base2[len - 5];
+	    res = snprintf(result, 499, "result/relaxng/%s_%c",
+		     prefix, count);
+            if (res >= 499)
+	        result[499] = 0;
+	    res = snprintf(err, 499, "result/relaxng/%s_%c.err",
+		     prefix, count);
+            if (res >= 499)
+	        err[499] = 0;
+	} else {
+	    fprintf(stderr, "don't know how to process %s\n", instance);
+	    continue;
+	}
+	if (schemas != NULL) {
+	    nb_tests++;
+	    res = rngOneTest(filename, instance, result, options, schemas);
+	    if (res != 0)
+		ret = res;
+	}
+        if (compareFileMem(err, testErrors, testErrorsSize)) {
+            fprintf(stderr, "Error for %s on %s failed\n", instance,
+                    filename);
+            ret = 1;
+        }
+    }
+    globfree(&globbuf);
+    xmlRelaxNGFree(schemas);
+
+    return(ret);
+}
+
+#ifdef LIBXML_READER_ENABLED
+/**
+ * rngStreamTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a set of files with streaming, applying an RNG schemas
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+rngStreamTest(const char *filename,
+            const char *resul ATTRIBUTE_UNUSED,
+            const char *errr ATTRIBUTE_UNUSED,
+            int options) {
+    const char *base = baseFilename(filename);
+    const char *base2;
+    const char *instance;
+    int res = 0, len, ret;
+    char pattern[500];
+    char prefix[500];
+    char result[500];
+    char err[500];
+    glob_t globbuf;
+    size_t i;
+    char count = 0;
+    xmlTextReaderPtr reader;
+    int disable_err = 0;
+
+    /*
+     * most of the mess is about the output filenames generated by the Makefile
+     */
+    len = strlen(base);
+    if ((len > 499) || (len < 5)) {
+	fprintf(stderr, "len(base) == %d !\n", len);
+	return(-1);
+    }
+    len -= 4; /* remove trailing .rng */
+    memcpy(prefix, base, len);
+    prefix[len] = 0;
+
+    /*
+     * strictly unifying the error messages is nearly impossible this
+     * hack is also done in the Makefile
+     */
+    if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
+        (!strcmp(prefix, "tutor3_2")) || (!strcmp(prefix, "307377")) ||
+        (!strcmp(prefix, "tutor8_2")))
+	disable_err = 1;
+
+    if (snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix) >= 499)
+        pattern[499] = 0;
+
+    globbuf.gl_offs = 0;
+    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+    for (i = 0;i < globbuf.gl_pathc;i++) {
+        testErrorsSize = 0;
+	testErrors[0] = 0;
+        instance = globbuf.gl_pathv[i];
+	base2 = baseFilename(instance);
+	len = strlen(base2);
+	if ((len > 6) && (base2[len - 6] == '_')) {
+	    count = base2[len - 5];
+	    ret = snprintf(result, 499, "result/relaxng/%s_%c",
+		     prefix, count);
+            if (ret >= 499)
+	        result[499] = 0;
+	    ret = snprintf(err, 499, "result/relaxng/%s_%c.err",
+		     prefix, count);
+            if (ret >= 499)
+	        err[499] = 0;
+	} else {
+	    fprintf(stderr, "don't know how to process %s\n", instance);
+	    continue;
+	}
+	reader = xmlReaderForFile(instance, NULL, options);
+        xmlTextReaderSetStructuredErrorHandler(reader,
+                testStructuredErrorHandler, NULL);
+	if (reader == NULL) {
+	    fprintf(stderr, "Failed to build reader for %s\n", instance);
+	}
+	if (disable_err == 1)
+	    ret = streamProcessTest(instance, result, NULL, reader, filename,
+	                            options);
+	else
+	    ret = streamProcessTest(instance, result, err, reader, filename,
+	                            options);
+	xmlFreeTextReader(reader);
+	if (ret != 0) {
+	    fprintf(stderr, "instance %s failed\n", instance);
+	    res = ret;
+	}
+    }
+    globfree(&globbuf);
+
+    return(res);
+}
+#endif /* READER */
+
+#endif
+
+#ifdef LIBXML_PATTERN_ENABLED
+#ifdef LIBXML_READER_ENABLED
+/************************************************************************
+ *									*
+ *			Patterns tests					*
+ *									*
+ ************************************************************************/
+static void patternNode(FILE *out, xmlTextReaderPtr reader,
+                        const char *pattern, xmlPatternPtr patternc,
+			xmlStreamCtxtPtr patstream) {
+    xmlChar *path = NULL;
+    int match = -1;
+    int type, empty;
+
+    type = xmlTextReaderNodeType(reader);
+    empty = xmlTextReaderIsEmptyElement(reader);
+
+    if (type == XML_READER_TYPE_ELEMENT) {
+	/* do the check only on element start */
+	match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
+
+	if (match) {
+	    path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
+	    fprintf(out, "Node %s matches pattern %s\n", path, pattern);
+	}
+    }
+    if (patstream != NULL) {
+	int ret;
+
+	if (type == XML_READER_TYPE_ELEMENT) {
+	    ret = xmlStreamPush(patstream,
+				xmlTextReaderConstLocalName(reader),
+				xmlTextReaderConstNamespaceUri(reader));
+	    if (ret < 0) {
+		fprintf(out, "xmlStreamPush() failure\n");
+		xmlFreeStreamCtxt(patstream);
+		patstream = NULL;
+	    } else if (ret != match) {
+		if (path == NULL) {
+		    path = xmlGetNodePath(
+				   xmlTextReaderCurrentNode(reader));
+		}
+		fprintf(out,
+			"xmlPatternMatch and xmlStreamPush disagree\n");
+		fprintf(out,
+			"  pattern %s node %s\n",
+			pattern, path);
+	    }
+
+
+	}
+	if ((type == XML_READER_TYPE_END_ELEMENT) ||
+	    ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
+	    ret = xmlStreamPop(patstream);
+	    if (ret < 0) {
+		fprintf(out, "xmlStreamPop() failure\n");
+		xmlFreeStreamCtxt(patstream);
+		patstream = NULL;
+	    }
+	}
+    }
+    if (path != NULL)
+	xmlFree(path);
+}
+
+/**
+ * patternTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a set of files with streaming, applying an RNG schemas
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+patternTest(const char *filename,
+            const char *resul ATTRIBUTE_UNUSED,
+            const char *err ATTRIBUTE_UNUSED,
+            int options) {
+    xmlPatternPtr patternc = NULL;
+    xmlStreamCtxtPtr patstream = NULL;
+    FILE *o, *f;
+    char str[1024];
+    char xml[500];
+    char result[500];
+    int len, i;
+    int ret = 0, res;
+    char *temp;
+    xmlTextReaderPtr reader;
+    xmlDocPtr doc;
+
+    len = strlen(filename);
+    len -= 4;
+    memcpy(xml, filename, len);
+    xml[len] = 0;
+    if (snprintf(result, 499, "result/pattern/%s", baseFilename(xml)) >= 499)
+        result[499] = 0;
+    memcpy(xml + len, ".xml", 5);
+
+    if (!checkTestFile(xml) && !update_results) {
+	fprintf(stderr, "Missing xml file %s\n", xml);
+	return(-1);
+    }
+    f = fopen(filename, "rb");
+    if (f == NULL) {
+        fprintf(stderr, "Failed to open %s\n", filename);
+	return(-1);
+    }
+    temp = resultFilename(filename, temp_directory, ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    o = fopen(temp, "wb");
+    if (o == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+	fclose(f);
+        free(temp);
+	return(-1);
+    }
+    while (1) {
+	/*
+	 * read one line in string buffer.
+	 */
+	if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
+	   break;
+
+	/*
+	 * remove the ending spaces
+	 */
+	i = strlen(str);
+	while ((i > 0) &&
+	       ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
+		(str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
+	    i--;
+	    str[i] = 0;
+	}
+	doc = xmlReadFile(xml, NULL, options);
+	if (doc == NULL) {
+	    fprintf(stderr, "Failed to parse %s\n", xml);
+	    ret = 1;
+	} else {
+	    xmlNodePtr root;
+	    const xmlChar *namespaces[22];
+	    int j;
+	    xmlNsPtr ns;
+
+	    root = xmlDocGetRootElement(doc);
+	    for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
+		namespaces[j++] = ns->href;
+		namespaces[j++] = ns->prefix;
+	    }
+	    namespaces[j++] = NULL;
+	    namespaces[j] = NULL;
+
+	    patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
+					 0, &namespaces[0]);
+	    if (patternc == NULL) {
+		testErrorHandler(NULL,
+			"Pattern %s failed to compile\n", str);
+		xmlFreeDoc(doc);
+		ret = 1;
+		continue;
+	    }
+	    patstream = xmlPatternGetStreamCtxt(patternc);
+	    if (patstream != NULL) {
+		ret = xmlStreamPush(patstream, NULL, NULL);
+		if (ret < 0) {
+		    fprintf(stderr, "xmlStreamPush() failure\n");
+		    xmlFreeStreamCtxt(patstream);
+		    patstream = NULL;
+		}
+	    }
+	    nb_tests++;
+
+	    reader = xmlReaderWalker(doc);
+	    res = xmlTextReaderRead(reader);
+	    while (res == 1) {
+		patternNode(o, reader, str, patternc, patstream);
+		res = xmlTextReaderRead(reader);
+	    }
+	    if (res != 0) {
+		fprintf(o, "%s : failed to parse\n", filename);
+	    }
+	    xmlFreeTextReader(reader);
+	    xmlFreeDoc(doc);
+	    xmlFreeStreamCtxt(patstream);
+	    patstream = NULL;
+	    xmlFreePattern(patternc);
+
+	}
+    }
+
+    fclose(f);
+    fclose(o);
+
+    ret = compareFiles(temp, result);
+    if (ret) {
+	fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+	ret = 1;
+    }
+    if (temp != NULL) {
+        unlink(temp);
+        free(temp);
+    }
+    return(ret);
+}
+#endif /* READER */
+#endif /* PATTERN */
+#ifdef LIBXML_C14N_ENABLED
+/************************************************************************
+ *									*
+ *			Canonicalization tests				*
+ *									*
+ ************************************************************************/
+static xmlXPathObjectPtr
+load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
+    xmlXPathObjectPtr xpath;
+    xmlDocPtr doc;
+    xmlChar *expr;
+    xmlXPathContextPtr ctx;
+    xmlNodePtr node;
+    xmlNsPtr ns;
+
+    /*
+     * load XPath expr as a file
+     */
+    doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
+    if (doc == NULL) {
+	fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
+	return(NULL);
+    }
+
+    /*
+     * Check the document is of the right kind
+     */
+    if(xmlDocGetRootElement(doc) == NULL) {
+        fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
+	xmlFreeDoc(doc);
+	return(NULL);
+    }
+
+    node = doc->children;
+    while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
+	node = node->next;
+    }
+
+    if(node == NULL) {
+        fprintf(stderr,"Error: XPath element expected in the file  \"%s\"\n", filename);
+	xmlFreeDoc(doc);
+	return(NULL);
+    }
+
+    expr = xmlNodeGetContent(node);
+    if(expr == NULL) {
+        fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
+	xmlFreeDoc(doc);
+	return(NULL);
+    }
+
+    ctx = xmlXPathNewContext(parent_doc);
+    if(ctx == NULL) {
+        fprintf(stderr,"Error: unable to create new context\n");
+        xmlFree(expr);
+        xmlFreeDoc(doc);
+        return(NULL);
+    }
+
+    /*
+     * Register namespaces
+     */
+    ns = node->nsDef;
+    while(ns != NULL) {
+	if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
+	    fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
+    xmlFree(expr);
+	    xmlXPathFreeContext(ctx);
+	    xmlFreeDoc(doc);
+	    return(NULL);
+	}
+	ns = ns->next;
+    }
+
+    /*
+     * Evaluate xpath
+     */
+    xpath = xmlXPathEvalExpression(expr, ctx);
+    if(xpath == NULL) {
+        fprintf(stderr,"Error: unable to evaluate xpath expression\n");
+xmlFree(expr);
+        xmlXPathFreeContext(ctx);
+        xmlFreeDoc(doc);
+        return(NULL);
+    }
+
+    /* print_xpath_nodes(xpath->nodesetval); */
+
+    xmlFree(expr);
+    xmlXPathFreeContext(ctx);
+    xmlFreeDoc(doc);
+    return(xpath);
+}
+
+/*
+ * Macro used to grow the current buffer.
+ */
+#define xxx_growBufferReentrant() {						\
+    buffer_size *= 2;							\
+    buffer = (xmlChar **)						\
+	xmlRealloc(buffer, buffer_size * sizeof(xmlChar*));	\
+    if (buffer == NULL) {						\
+	perror("realloc failed");					\
+	return(NULL);							\
+    }									\
+}
+
+static xmlChar **
+parse_list(xmlChar *str) {
+    xmlChar **buffer;
+    xmlChar **out = NULL;
+    int buffer_size = 0;
+    int len;
+
+    if(str == NULL) {
+	return(NULL);
+    }
+
+    len = xmlStrlen(str);
+    if((str[0] == '\'') && (str[len - 1] == '\'')) {
+	str[len - 1] = '\0';
+	str++;
+    }
+    /*
+     * allocate an translation buffer.
+     */
+    buffer_size = 1000;
+    buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
+    if (buffer == NULL) {
+	perror("malloc failed");
+	return(NULL);
+    }
+    out = buffer;
+
+    while(*str != '\0') {
+	if (out - buffer > buffer_size - 10) {
+	    int indx = out - buffer;
+
+	    xxx_growBufferReentrant();
+	    out = &buffer[indx];
+	}
+	(*out++) = str;
+	while(*str != ',' && *str != '\0') ++str;
+	if(*str == ',') *(str++) = '\0';
+    }
+    (*out) = NULL;
+    return buffer;
+}
+
+static int
+c14nRunTest(const char* xml_filename, int with_comments, int mode,
+	    const char* xpath_filename, const char *ns_filename,
+	    const char* result_file) {
+    xmlDocPtr doc;
+    xmlXPathObjectPtr xpath = NULL;
+    xmlChar *result = NULL;
+    int ret;
+    xmlChar **inclusive_namespaces = NULL;
+    const char *nslist = NULL;
+    int nssize;
+
+
+    /*
+     * build an XML tree from a the file; we need to add default
+     * attributes and resolve all character and entities references
+     */
+    doc = xmlReadFile(xml_filename, NULL,
+            XML_PARSE_DTDATTR | XML_PARSE_NOENT | XML_PARSE_NOWARNING);
+    if (doc == NULL) {
+	fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
+	return(-1);
+    }
+
+    /*
+     * Check the document is of the right kind
+     */
+    if(xmlDocGetRootElement(doc) == NULL) {
+        fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
+	xmlFreeDoc(doc);
+	return(-1);
+    }
+
+    /*
+     * load xpath file if specified
+     */
+    if(xpath_filename) {
+	xpath = load_xpath_expr(doc, xpath_filename);
+	if(xpath == NULL) {
+	    fprintf(stderr,"Error: unable to evaluate xpath expression\n");
+	    xmlFreeDoc(doc);
+	    return(-1);
+	}
+    }
+
+    if (ns_filename != NULL) {
+        if (loadMem(ns_filename, &nslist, &nssize)) {
+	    fprintf(stderr,"Error: unable to evaluate xpath expression\n");
+	    if(xpath != NULL) xmlXPathFreeObject(xpath);
+	    xmlFreeDoc(doc);
+	    return(-1);
+	}
+        inclusive_namespaces = parse_list((xmlChar *) nslist);
+    }
+
+    /*
+     * Canonical form
+     */
+    /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
+    ret = xmlC14NDocDumpMemory(doc,
+	    (xpath) ? xpath->nodesetval : NULL,
+	    mode, inclusive_namespaces,
+	    with_comments, &result);
+    if (ret >= 0) {
+	if(result != NULL) {
+	    if (compareFileMem(result_file, (const char *) result, ret)) {
+		fprintf(stderr, "Result mismatch for %s\n", xml_filename);
+		fprintf(stderr, "RESULT:\n%s\n", (const char*)result);
+	        ret = -1;
+	    }
+	}
+    } else {
+	fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
+	ret = -1;
+    }
+
+    /*
+     * Cleanup
+     */
+    if (result != NULL) xmlFree(result);
+    if(xpath != NULL) xmlXPathFreeObject(xpath);
+    if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
+    if (nslist != NULL) free((char *) nslist);
+    xmlFreeDoc(doc);
+
+    return(ret);
+}
+
+static int
+c14nCommonTest(const char *filename, int with_comments, int mode,
+               const char *subdir) {
+    char buf[500];
+    char prefix[500];
+    const char *base;
+    int len;
+    char *result = NULL;
+    char *xpath = NULL;
+    char *ns = NULL;
+    int ret = 0;
+
+    base = baseFilename(filename);
+    len = strlen(base);
+    len -= 4;
+    memcpy(prefix, base, len);
+    prefix[len] = 0;
+
+    if (snprintf(buf, 499, "result/c14n/%s/%s", subdir, prefix) >= 499)
+        buf[499] = 0;
+    result = strdup(buf);
+    if (snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir, prefix) >= 499)
+        buf[499] = 0;
+    if (checkTestFile(buf)) {
+	xpath = strdup(buf);
+    }
+    if (snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir, prefix) >= 499)
+        buf[499] = 0;
+    if (checkTestFile(buf)) {
+	ns = strdup(buf);
+    }
+
+    nb_tests++;
+    if (c14nRunTest(filename, with_comments, mode,
+                    xpath, ns, result) < 0)
+        ret = 1;
+
+    if (result != NULL) free(result);
+    if (xpath != NULL) free(xpath);
+    if (ns != NULL) free(ns);
+    return(ret);
+}
+
+static int
+c14nWithCommentTest(const char *filename,
+                    const char *resul ATTRIBUTE_UNUSED,
+		    const char *err ATTRIBUTE_UNUSED,
+		    int options ATTRIBUTE_UNUSED) {
+    return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments"));
+}
+static int
+c14nWithoutCommentTest(const char *filename,
+                    const char *resul ATTRIBUTE_UNUSED,
+		    const char *err ATTRIBUTE_UNUSED,
+		    int options ATTRIBUTE_UNUSED) {
+    return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments"));
+}
+static int
+c14nExcWithoutCommentTest(const char *filename,
+                    const char *resul ATTRIBUTE_UNUSED,
+		    const char *err ATTRIBUTE_UNUSED,
+		    int options ATTRIBUTE_UNUSED) {
+    return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments"));
+}
+static int
+c14n11WithoutCommentTest(const char *filename,
+                    const char *resul ATTRIBUTE_UNUSED,
+		    const char *err ATTRIBUTE_UNUSED,
+		    int options ATTRIBUTE_UNUSED) {
+    return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments"));
+}
+#endif
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
+/************************************************************************
+ *									*
+ *			Catalog and threads test			*
+ *									*
+ ************************************************************************/
+
+/*
+ * mostly a cut and paste from testThreads.c
+ */
+#define	MAX_ARGC	20
+
+typedef struct {
+    const char *filename;
+    int okay;
+} xmlThreadParams;
+
+static const char *catalog = "test/threads/complex.xml";
+static xmlThreadParams threadParams[] = {
+    { "test/threads/abc.xml", 0 },
+    { "test/threads/acb.xml", 0 },
+    { "test/threads/bac.xml", 0 },
+    { "test/threads/bca.xml", 0 },
+    { "test/threads/cab.xml", 0 },
+    { "test/threads/cba.xml", 0 },
+    { "test/threads/invalid.xml", 0 }
+};
+static const unsigned int num_threads = sizeof(threadParams) /
+                                        sizeof(threadParams[0]);
+
+static void *
+thread_specific_data(void *private_data)
+{
+    xmlDocPtr myDoc;
+    xmlThreadParams *params = (xmlThreadParams *) private_data;
+    const char *filename = params->filename;
+    int okay = 1;
+
+#ifdef LIBXML_THREAD_ALLOC_ENABLED
+    xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
+#endif
+
+    myDoc = xmlReadFile(filename, NULL, XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
+    if (myDoc) {
+        xmlFreeDoc(myDoc);
+    } else {
+        printf("parse failed\n");
+        okay = 0;
+    }
+    params->okay = okay;
+    return(NULL);
+}
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <string.h>
+
+#define TEST_REPEAT_COUNT 500
+
+static HANDLE tid[MAX_ARGC];
+
+static DWORD WINAPI
+win32_thread_specific_data(void *private_data)
+{
+    thread_specific_data(private_data);
+    return(0);
+}
+
+static int
+testThread(void)
+{
+    unsigned int i, repeat;
+    BOOL ret;
+    int res = 0;
+
+    xmlInitParser();
+    for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
+        xmlLoadCatalog(catalog);
+        nb_tests++;
+
+        for (i = 0; i < num_threads; i++) {
+            tid[i] = (HANDLE) - 1;
+        }
+
+        for (i = 0; i < num_threads; i++) {
+            DWORD useless;
+
+            tid[i] = CreateThread(NULL, 0,
+                                  win32_thread_specific_data,
+				  (void *) &threadParams[i], 0,
+                                  &useless);
+            if (tid[i] == NULL) {
+                fprintf(stderr, "CreateThread failed\n");
+                return(1);
+            }
+        }
+
+        if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
+            WAIT_FAILED) {
+            fprintf(stderr, "WaitForMultipleObjects failed\n");
+	    return(1);
+	}
+
+        for (i = 0; i < num_threads; i++) {
+            DWORD exitCode;
+            ret = GetExitCodeThread(tid[i], &exitCode);
+            if (ret == 0) {
+                fprintf(stderr, "GetExitCodeThread failed\n");
+                return(1);
+            }
+            CloseHandle(tid[i]);
+        }
+
+        xmlCatalogCleanup();
+        for (i = 0; i < num_threads; i++) {
+            if (threadParams[i].okay == 0) {
+                fprintf(stderr, "Thread %d handling %s failed\n",
+		        i, threadParams[i].filename);
+	        res = 1;
+	    }
+        }
+    }
+
+    return (res);
+}
+
+#elif defined HAVE_PTHREAD_H
+#include <pthread.h>
+
+static pthread_t tid[MAX_ARGC];
+
+static int
+testThread(void)
+{
+    unsigned int i, repeat;
+    int ret;
+    int res = 0;
+
+    xmlInitParser();
+
+    for (repeat = 0; repeat < 500; repeat++) {
+        xmlLoadCatalog(catalog);
+        nb_tests++;
+
+        for (i = 0; i < num_threads; i++) {
+            tid[i] = (pthread_t) - 1;
+        }
+
+        for (i = 0; i < num_threads; i++) {
+            ret = pthread_create(&tid[i], 0, thread_specific_data,
+                                 (void *) &threadParams[i]);
+            if (ret != 0) {
+                fprintf(stderr, "pthread_create failed\n");
+                return (1);
+            }
+        }
+        for (i = 0; i < num_threads; i++) {
+            void *result;
+            ret = pthread_join(tid[i], &result);
+            if (ret != 0) {
+                fprintf(stderr, "pthread_join failed\n");
+                return (1);
+            }
+        }
+
+        xmlCatalogCleanup();
+        for (i = 0; i < num_threads; i++)
+            if (threadParams[i].okay == 0) {
+                fprintf(stderr, "Thread %d handling %s failed\n",
+                        i, threadParams[i].filename);
+                res = 1;
+            }
+    }
+    return (res);
+}
+
+#else
+static int
+testThread(void)
+{
+    fprintf(stderr,
+            "Specific platform thread support not detected\n");
+    return (-1);
+}
+#endif
+static int
+threadsTest(const char *filename ATTRIBUTE_UNUSED,
+	    const char *resul ATTRIBUTE_UNUSED,
+	    const char *err ATTRIBUTE_UNUSED,
+	    int options ATTRIBUTE_UNUSED) {
+    return(testThread());
+}
+#endif
+
+#if defined(LIBXML_REGEXP_ENABLED)
+/************************************************************************
+ *									*
+ *			Regexp tests					*
+ *									*
+ ************************************************************************/
+
+static void testRegexp(FILE *output, xmlRegexpPtr comp, const char *value) {
+    int ret;
+
+    ret = xmlRegexpExec(comp, (const xmlChar *) value);
+    if (ret == 1)
+	fprintf(output, "%s: Ok\n", value);
+    else if (ret == 0)
+	fprintf(output, "%s: Fail\n", value);
+    else
+	fprintf(output, "%s: Error: %d\n", value, ret);
+}
+
+static int
+regexpTest(const char *filename, const char *result, const char *err,
+	   int options ATTRIBUTE_UNUSED) {
+    xmlRegexpPtr comp = NULL;
+    FILE *input, *output;
+    char *temp;
+    char expression[5000];
+    int len, ret, res = 0;
+
+    /*
+     * TODO: Custom error handler for regexp
+     */
+    xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
+
+    nb_tests++;
+
+    input = fopen(filename, "rb");
+    if (input == NULL) {
+        fprintf(stderr,
+		"Cannot open %s for reading\n", filename);
+	ret = -1;
+        goto done;
+    }
+    temp = resultFilename(filename, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    output = fopen(temp, "wb");
+    if (output == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+        free(temp);
+	ret = -1;
+        goto done;
+    }
+    while (fgets(expression, 4500, input) != NULL) {
+	len = strlen(expression);
+	len--;
+	while ((len >= 0) &&
+	       ((expression[len] == '\n') || (expression[len] == '\t') ||
+		(expression[len] == '\r') || (expression[len] == ' '))) len--;
+	expression[len + 1] = 0;
+	if (len >= 0) {
+	    if (expression[0] == '#')
+		continue;
+	    if ((expression[0] == '=') && (expression[1] == '>')) {
+		char *pattern = &expression[2];
+
+		if (comp != NULL) {
+		    xmlRegFreeRegexp(comp);
+		    comp = NULL;
+		}
+		fprintf(output, "Regexp: %s\n", pattern) ;
+		comp = xmlRegexpCompile((const xmlChar *) pattern);
+		if (comp == NULL) {
+		    fprintf(output, "   failed to compile\n");
+		    break;
+		}
+	    } else if (comp == NULL) {
+		fprintf(output, "Regexp: %s\n", expression) ;
+		comp = xmlRegexpCompile((const xmlChar *) expression);
+		if (comp == NULL) {
+		    fprintf(output, "   failed to compile\n");
+		    break;
+		}
+	    } else if (comp != NULL) {
+		testRegexp(output, comp, expression);
+	    }
+	}
+    }
+    fclose(output);
+    fclose(input);
+    if (comp != NULL)
+	xmlRegFreeRegexp(comp);
+
+    ret = compareFiles(temp, result);
+    if (ret) {
+        fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+        res = 1;
+    }
+    if (temp != NULL) {
+        unlink(temp);
+        free(temp);
+    }
+
+    ret = compareFileMem(err, testErrors, testErrorsSize);
+    if (ret != 0) {
+        fprintf(stderr, "Error for %s failed\n", filename);
+        res = 1;
+    }
+
+done:
+    xmlSetStructuredErrorFunc(NULL, NULL);
+
+    return(res);
+}
+
+#endif /* LIBXML_REGEXPS_ENABLED */
+
+#ifdef LIBXML_AUTOMATA_ENABLED
+/************************************************************************
+ *									*
+ *			Automata tests					*
+ *									*
+ ************************************************************************/
+
+static int scanNumber(char **ptr) {
+    int ret = 0;
+    char *cur;
+
+    cur = *ptr;
+    while ((*cur >= '0') && (*cur <= '9')) {
+	ret = ret * 10 + (*cur - '0');
+	cur++;
+    }
+    *ptr = cur;
+    return(ret);
+}
+
+static int
+automataTest(const char *filename, const char *result,
+             const char *err ATTRIBUTE_UNUSED, int options ATTRIBUTE_UNUSED) {
+    FILE *input, *output;
+    char *temp;
+    char expr[5000];
+    int len;
+    int ret;
+    int i;
+    int res = 0;
+    xmlAutomataPtr am;
+    xmlAutomataStatePtr states[1000];
+    xmlRegexpPtr regexp = NULL;
+    xmlRegExecCtxtPtr exec = NULL;
+
+    nb_tests++;
+
+    for (i = 0;i<1000;i++)
+	states[i] = NULL;
+
+    input = fopen(filename, "rb");
+    if (input == NULL) {
+        fprintf(stderr,
+		"Cannot open %s for reading\n", filename);
+	return(-1);
+    }
+    temp = resultFilename(filename, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    output = fopen(temp, "wb");
+    if (output == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+        free(temp);
+	return(-1);
+    }
+
+    am = xmlNewAutomata();
+    if (am == NULL) {
+        fprintf(stderr,
+		"Cannot create automata\n");
+	fclose(input);
+	return(-1);
+    }
+    states[0] = xmlAutomataGetInitState(am);
+    if (states[0] == NULL) {
+        fprintf(stderr,
+		"Cannot get start state\n");
+	xmlFreeAutomata(am);
+	fclose(input);
+	return(-1);
+    }
+    ret = 0;
+
+    while (fgets(expr, 4500, input) != NULL) {
+	if (expr[0] == '#')
+	    continue;
+	len = strlen(expr);
+	len--;
+	while ((len >= 0) &&
+	       ((expr[len] == '\n') || (expr[len] == '\t') ||
+		(expr[len] == '\r') || (expr[len] == ' '))) len--;
+	expr[len + 1] = 0;
+	if (len >= 0) {
+	    if ((am != NULL) && (expr[0] == 't') && (expr[1] == ' ')) {
+		char *ptr = &expr[2];
+		int from, to;
+
+		from = scanNumber(&ptr);
+		if (*ptr != ' ') {
+		    fprintf(stderr,
+			    "Bad line %s\n", expr);
+		    break;
+		}
+		if (states[from] == NULL)
+		    states[from] = xmlAutomataNewState(am);
+		ptr++;
+		to = scanNumber(&ptr);
+		if (*ptr != ' ') {
+		    fprintf(stderr,
+			    "Bad line %s\n", expr);
+		    break;
+		}
+		if (states[to] == NULL)
+		    states[to] = xmlAutomataNewState(am);
+		ptr++;
+		xmlAutomataNewTransition(am, states[from], states[to],
+			                 BAD_CAST ptr, NULL);
+	    } else if ((am != NULL) && (expr[0] == 'e') && (expr[1] == ' ')) {
+		char *ptr = &expr[2];
+		int from, to;
+
+		from = scanNumber(&ptr);
+		if (*ptr != ' ') {
+		    fprintf(stderr,
+			    "Bad line %s\n", expr);
+		    break;
+		}
+		if (states[from] == NULL)
+		    states[from] = xmlAutomataNewState(am);
+		ptr++;
+		to = scanNumber(&ptr);
+		if (states[to] == NULL)
+		    states[to] = xmlAutomataNewState(am);
+		xmlAutomataNewEpsilon(am, states[from], states[to]);
+	    } else if ((am != NULL) && (expr[0] == 'f') && (expr[1] == ' ')) {
+		char *ptr = &expr[2];
+		int state;
+
+		state = scanNumber(&ptr);
+		if (states[state] == NULL) {
+		    fprintf(stderr,
+			    "Bad state %d : %s\n", state, expr);
+		    break;
+		}
+		xmlAutomataSetFinalState(am, states[state]);
+	    } else if ((am != NULL) && (expr[0] == 'c') && (expr[1] == ' ')) {
+		char *ptr = &expr[2];
+		int from, to;
+		int min, max;
+
+		from = scanNumber(&ptr);
+		if (*ptr != ' ') {
+		    fprintf(stderr,
+			    "Bad line %s\n", expr);
+		    break;
+		}
+		if (states[from] == NULL)
+		    states[from] = xmlAutomataNewState(am);
+		ptr++;
+		to = scanNumber(&ptr);
+		if (*ptr != ' ') {
+		    fprintf(stderr,
+			    "Bad line %s\n", expr);
+		    break;
+		}
+		if (states[to] == NULL)
+		    states[to] = xmlAutomataNewState(am);
+		ptr++;
+		min = scanNumber(&ptr);
+		if (*ptr != ' ') {
+		    fprintf(stderr,
+			    "Bad line %s\n", expr);
+		    break;
+		}
+		ptr++;
+		max = scanNumber(&ptr);
+		if (*ptr != ' ') {
+		    fprintf(stderr,
+			    "Bad line %s\n", expr);
+		    break;
+		}
+		ptr++;
+		xmlAutomataNewCountTrans(am, states[from], states[to],
+			                 BAD_CAST ptr, min, max, NULL);
+	    } else if ((am != NULL) && (expr[0] == '-') && (expr[1] == '-')) {
+		/* end of the automata */
+		regexp = xmlAutomataCompile(am);
+		xmlFreeAutomata(am);
+		am = NULL;
+		if (regexp == NULL) {
+		    fprintf(stderr,
+			    "Failed to compile the automata");
+		    break;
+		}
+	    } else if ((expr[0] == '=') && (expr[1] == '>')) {
+		if (regexp == NULL) {
+		    fprintf(output, "=> failed not compiled\n");
+		} else {
+		    if (exec == NULL)
+			exec = xmlRegNewExecCtxt(regexp, NULL, NULL);
+		    if (ret == 0) {
+			ret = xmlRegExecPushString(exec, NULL, NULL);
+		    }
+		    if (ret == 1)
+			fprintf(output, "=> Passed\n");
+		    else if ((ret == 0) || (ret == -1))
+			fprintf(output, "=> Failed\n");
+		    else if (ret < 0)
+			fprintf(output, "=> Error\n");
+		    xmlRegFreeExecCtxt(exec);
+		    exec = NULL;
+		}
+		ret = 0;
+	    } else if (regexp != NULL) {
+		if (exec == NULL)
+		    exec = xmlRegNewExecCtxt(regexp, NULL, NULL);
+		ret = xmlRegExecPushString(exec, BAD_CAST expr, NULL);
+	    } else {
+		fprintf(stderr,
+			"Unexpected line %s\n", expr);
+	    }
+	}
+    }
+    fclose(output);
+    fclose(input);
+    if (regexp != NULL)
+	xmlRegFreeRegexp(regexp);
+    if (exec != NULL)
+	xmlRegFreeExecCtxt(exec);
+    if (am != NULL)
+	xmlFreeAutomata(am);
+
+    ret = compareFiles(temp, result);
+    if (ret) {
+        fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+        res = 1;
+    }
+    if (temp != NULL) {
+        unlink(temp);
+        free(temp);
+    }
+
+    return(res);
+}
+
+#endif /* LIBXML_AUTOMATA_ENABLED */
+
+/************************************************************************
+ *									*
+ *			Tests Descriptions				*
+ *									*
+ ************************************************************************/
+
+static
+testDesc testDescriptions[] = {
+    { "XML regression tests" ,
+      oldParseTest, "./test/*", "result/", "", NULL,
+      0 },
+    { "XML regression tests on memory" ,
+      memParseTest, "./test/*", "result/", "", NULL,
+      0 },
+    { "XML entity subst regression tests" ,
+      noentParseTest, "./test/*", "result/noent/", "", NULL,
+      XML_PARSE_NOENT },
+    { "XML Namespaces regression tests",
+      errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
+      0 },
+#ifdef LIBXML_VALID_ENABLED
+    { "Error cases regression tests",
+      errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
+      0 },
+    { "Error cases regression tests from file descriptor",
+      fdParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
+      0 },
+    { "Error cases regression tests with entity substitution",
+      errParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".ent",
+      XML_PARSE_NOENT },
+    { "Error cases regression tests (old 1.0)",
+      errParseTest, "./test/errors10/*.xml", "result/errors10/", "", ".err",
+      XML_PARSE_OLD10 },
+#endif
+#ifdef LIBXML_READER_ENABLED
+#ifdef LIBXML_VALID_ENABLED
+    { "Error cases stream regression tests",
+      streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
+      0 },
+#endif
+    { "Reader regression tests",
+      streamParseTest, "./test/*", "result/", ".rdr", NULL,
+      0 },
+    { "Reader entities substitution regression tests",
+      streamParseTest, "./test/*", "result/", ".rde", NULL,
+      XML_PARSE_NOENT },
+    { "Reader on memory regression tests",
+      streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
+      0 },
+    { "Walker regression tests",
+      walkerParseTest, "./test/*", "result/", ".rdr", NULL,
+      0 },
+#endif
+#ifdef LIBXML_SAX1_ENABLED
+    { "SAX1 callbacks regression tests" ,
+      saxParseTest, "./test/*", "result/", ".sax", NULL,
+      XML_PARSE_SAX1 },
+#endif
+    { "SAX2 callbacks regression tests" ,
+      saxParseTest, "./test/*", "result/", ".sax2", NULL,
+      0 },
+    { "SAX2 callbacks regression tests with entity substitution" ,
+      saxParseTest, "./test/*", "result/noent/", ".sax2", NULL,
+      XML_PARSE_NOENT },
+#ifdef LIBXML_PUSH_ENABLED
+    { "XML push regression tests" ,
+      pushParseTest, "./test/*", "result/", "", NULL,
+      0 },
+    { "XML push boundary tests" ,
+      pushBoundaryTest, "./test/*", "result/", "", NULL,
+      0 },
+#endif
+#ifdef LIBXML_HTML_ENABLED
+    { "HTML regression tests" ,
+      errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
+      XML_PARSE_HTML },
+    { "HTML regression tests from file descriptor",
+      fdParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
+      XML_PARSE_HTML },
+#ifdef LIBXML_PUSH_ENABLED
+    { "Push HTML regression tests" ,
+      pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
+      XML_PARSE_HTML },
+    { "Push HTML boundary tests" ,
+      pushBoundaryTest, "./test/HTML/*", "result/HTML/", "", NULL,
+      XML_PARSE_HTML },
+#endif
+    { "HTML SAX regression tests" ,
+      saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
+      XML_PARSE_HTML },
+#endif
+#ifdef LIBXML_VALID_ENABLED
+    { "Valid documents regression tests" ,
+      errParseTest, "./test/VCM/*", NULL, NULL, NULL,
+      XML_PARSE_DTDVALID },
+    { "Validity checking regression tests" ,
+      errParseTest, "./test/VC/*", "result/VC/", NULL, "",
+      XML_PARSE_DTDVALID },
+#ifdef LIBXML_READER_ENABLED
+    { "Streaming validity checking regression tests" ,
+      streamParseTest, "./test/valid/*.xml", "result/valid/", NULL, ".err.rdr",
+      XML_PARSE_DTDVALID },
+    { "Streaming validity error checking regression tests" ,
+      streamParseTest, "./test/VC/*", "result/VC/", NULL, ".rdr",
+      XML_PARSE_DTDVALID },
+#endif
+    { "General documents valid regression tests" ,
+      errParseTest, "./test/valid/*", "result/valid/", "", ".err",
+      XML_PARSE_DTDVALID },
+#endif
+#ifdef LIBXML_XINCLUDE_ENABLED
+    { "XInclude regression tests" ,
+      errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", ".err",
+      XML_PARSE_XINCLUDE },
+#ifdef LIBXML_READER_ENABLED
+    { "XInclude xmlReader regression tests",
+      streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
+      ".err", XML_PARSE_XINCLUDE },
+#endif
+    { "XInclude regression tests stripping include nodes" ,
+      errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", ".err",
+      XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
+#ifdef LIBXML_READER_ENABLED
+    { "XInclude xmlReader regression tests stripping include nodes",
+      streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
+      ".err", XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
+#endif
+    { "XInclude regression tests without reader",
+      errParseTest, "./test/XInclude/without-reader/*", "result/XInclude/", "",
+      ".err", XML_PARSE_XINCLUDE },
+#endif
+#ifdef LIBXML_XPATH_ENABLED
+#ifdef LIBXML_DEBUG_ENABLED
+    { "XPath expressions regression tests" ,
+      xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
+      0 },
+    { "XPath document queries regression tests" ,
+      xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
+      0 },
+#ifdef LIBXML_XPTR_ENABLED
+    { "XPointer document queries regression tests" ,
+      xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
+      -1 },
+#endif
+#ifdef LIBXML_XPTR_LOCS_ENABLED
+    { "XPointer xpointer() queries regression tests" ,
+      xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
+      0 },
+#endif
+#ifdef LIBXML_VALID_ENABLED
+    { "xml:id regression tests" ,
+      xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
+      0 },
+#endif
+#endif
+#endif
+    { "URI parsing tests" ,
+      uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
+      0 },
+    { "URI base composition tests" ,
+      uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
+      0 },
+    { "Path URI conversion tests" ,
+      uriPathTest, NULL, NULL, NULL, NULL,
+      0 },
+#ifdef LIBXML_SCHEMAS_ENABLED
+    { "Schemas regression tests" ,
+      schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
+      0 },
+    { "Relax-NG regression tests" ,
+      rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
+      XML_PARSE_DTDATTR | XML_PARSE_NOENT },
+#ifdef LIBXML_READER_ENABLED
+    { "Relax-NG streaming regression tests" ,
+      rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
+      XML_PARSE_DTDATTR | XML_PARSE_NOENT },
+#endif
+#endif
+#ifdef LIBXML_PATTERN_ENABLED
+#ifdef LIBXML_READER_ENABLED
+    { "Pattern regression tests" ,
+      patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
+      0 },
+#endif
+#endif
+#ifdef LIBXML_C14N_ENABLED
+    { "C14N with comments regression tests" ,
+      c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
+      0 },
+    { "C14N without comments regression tests" ,
+      c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
+      0 },
+    { "C14N exclusive without comments regression tests" ,
+      c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
+      0 },
+    { "C14N 1.1 without comments regression tests" ,
+      c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL,
+      0 },
+#endif
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
+    { "Catalog and Threads regression tests" ,
+      threadsTest, NULL, NULL, NULL, NULL,
+      0 },
+#endif
+    { "SVG parsing regression tests" ,
+      oldParseTest, "./test/SVG/*.xml", "result/SVG/", "", NULL,
+      0 },
+#if defined(LIBXML_REGEXP_ENABLED)
+    { "Regexp regression tests" ,
+      regexpTest, "./test/regexp/*", "result/regexp/", "", ".err",
+      0 },
+#endif
+#if defined(LIBXML_AUTOMATA_ENABLED)
+    { "Automata regression tests" ,
+      automataTest, "./test/automata/*", "result/automata/", "", NULL,
+      0 },
+#endif
+    {NULL, NULL, NULL, NULL, NULL, NULL, 0}
+};
+
+/************************************************************************
+ *									*
+ *		The main code driving the tests				*
+ *									*
+ ************************************************************************/
+
+static int
+launchTests(testDescPtr tst) {
+    int res = 0, err = 0;
+    size_t i;
+    char *result;
+    char *error;
+    int mem;
+    xmlCharEncodingHandlerPtr ebcdicHandler, ibm1141Handler, eucJpHandler;
+
+    ebcdicHandler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC);
+    ibm1141Handler = xmlFindCharEncodingHandler("IBM-1141");
+
+    /*
+     * When decoding EUC-JP, musl doesn't seem to support 0x8F control
+     * codes.
+     */
+    eucJpHandler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EUC_JP);
+    if (eucJpHandler != NULL) {
+        xmlBufferPtr in, out;
+
+        in = xmlBufferCreateSize(10);
+        xmlBufferCCat(in, "\x8f\xe9\xae");
+        out = xmlBufferCreateSize(10);
+        if (xmlCharEncInFunc(eucJpHandler, out, in) != 3) {
+            xmlCharEncCloseFunc(eucJpHandler);
+            eucJpHandler = NULL;
+        }
+        xmlBufferFree(out);
+        xmlBufferFree(in);
+    }
+
+    if (tst == NULL) return(-1);
+    if (tst->in != NULL) {
+	glob_t globbuf;
+
+	globbuf.gl_offs = 0;
+	glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
+	for (i = 0;i < globbuf.gl_pathc;i++) {
+	    if (!checkTestFile(globbuf.gl_pathv[i]))
+	        continue;
+            if ((((ebcdicHandler == NULL) || (ibm1141Handler == NULL)) &&
+                 (strstr(globbuf.gl_pathv[i], "ebcdic") != NULL)) ||
+                ((eucJpHandler == NULL) &&
+                 (strstr(globbuf.gl_pathv[i], "icu_parse_test") != NULL)))
+                continue;
+	    if (tst->suffix != NULL) {
+		result = resultFilename(globbuf.gl_pathv[i], tst->out,
+					tst->suffix);
+		if (result == NULL) {
+		    fprintf(stderr, "Out of memory !\n");
+		    fatalError();
+		}
+	    } else {
+	        result = NULL;
+	    }
+	    if (tst->err != NULL) {
+		error = resultFilename(globbuf.gl_pathv[i], tst->out,
+		                        tst->err);
+		if (error == NULL) {
+		    fprintf(stderr, "Out of memory !\n");
+		    fatalError();
+		}
+	    } else {
+	        error = NULL;
+	    }
+            mem = xmlMemUsed();
+            extraMemoryFromResolver = 0;
+            testErrorsSize = 0;
+            testErrors[0] = 0;
+            res = tst->func(globbuf.gl_pathv[i], result, error,
+                            tst->options | XML_PARSE_COMPACT);
+            xmlResetLastError();
+            if (res != 0) {
+                fprintf(stderr, "File %s generated an error\n",
+                        globbuf.gl_pathv[i]);
+                nb_errors++;
+                err++;
+            }
+            else if (xmlMemUsed() != mem) {
+                if ((xmlMemUsed() != mem) &&
+                    (extraMemoryFromResolver == 0)) {
+                    fprintf(stderr, "File %s leaked %d bytes\n",
+                            globbuf.gl_pathv[i], xmlMemUsed() - mem);
+                    nb_leaks++;
+                    err++;
+                }
+            }
+            testErrorsSize = 0;
+	    if (result)
+		free(result);
+	    if (error)
+		free(error);
+	}
+	globfree(&globbuf);
+    } else {
+        testErrorsSize = 0;
+	testErrors[0] = 0;
+	extraMemoryFromResolver = 0;
+        res = tst->func(NULL, NULL, NULL, tst->options);
+	if (res != 0) {
+	    nb_errors++;
+	    err++;
+	}
+    }
+
+    xmlCharEncCloseFunc(ebcdicHandler);
+    xmlCharEncCloseFunc(ibm1141Handler);
+    xmlCharEncCloseFunc(eucJpHandler);
+
+    return(err);
+}
+
+static int verbose = 0;
+static int tests_quiet = 0;
+
+static int
+runtest(int i) {
+    int ret = 0, res;
+    int old_errors, old_tests, old_leaks;
+
+    old_errors = nb_errors;
+    old_tests = nb_tests;
+    old_leaks = nb_leaks;
+    if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
+	printf("## %s\n", testDescriptions[i].desc);
+    res = launchTests(&testDescriptions[i]);
+    if (res != 0)
+	ret++;
+    if (verbose) {
+	if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
+	    printf("Ran %d tests, no errors\n", nb_tests - old_tests);
+	else
+	    printf("Ran %d tests, %d errors, %d leaks\n",
+		   nb_tests - old_tests,
+		   nb_errors - old_errors,
+		   nb_leaks - old_leaks);
+    }
+    return(ret);
+}
+
+int
+main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    int i, a, ret = 0;
+    int subset = 0;
+
+#if defined(_WIN32)
+    setvbuf(stdout, NULL, _IONBF, 0);
+    setvbuf(stderr, NULL, _IONBF, 0);
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1900
+    _set_output_format(_TWO_DIGIT_EXPONENT);
+#endif
+
+    initializeLibxml2();
+
+    for (a = 1; a < argc;a++) {
+        if (!strcmp(argv[a], "-v"))
+	    verbose = 1;
+        else if (!strcmp(argv[a], "-u"))
+	    update_results = 1;
+        else if (!strcmp(argv[a], "-quiet"))
+	    tests_quiet = 1;
+        else if (!strcmp(argv[a], "--out"))
+	    temp_directory = argv[++a];
+	else {
+	    for (i = 0; testDescriptions[i].func != NULL; i++) {
+	        if (strstr(testDescriptions[i].desc, argv[a])) {
+		    ret += runtest(i);
+		    subset++;
+		}
+	    }
+	}
+    }
+    if (subset == 0) {
+	for (i = 0; testDescriptions[i].func != NULL; i++) {
+	    ret += runtest(i);
+	}
+    }
+    if ((nb_errors == 0) && (nb_leaks == 0)) {
+        ret = 0;
+	printf("Total %d tests, no errors\n",
+	       nb_tests);
+    } else {
+        ret = 1;
+	printf("Total %d tests, %d errors, %d leaks\n",
+	       nb_tests, nb_errors, nb_leaks);
+    }
+    xmlCleanupParser();
+
+    return(ret);
+}
+
+#else /* ! LIBXML_OUTPUT_ENABLED */
+int
+main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    fprintf(stderr, "runtest requires output to be enabled in libxml2\n");
+    return(0);
+}
+#endif
diff --git a/runxmlconf.c b/runxmlconf.c
new file mode 100644
index 0000000000000000000000000000000000000000..18893039da2e25017fb3c12b923430fefeb277fb
--- /dev/null
+++ b/runxmlconf.c
@@ -0,0 +1,609 @@
+/*
+ * runxmlconf.c: C program to run XML W3C conformance testsuites
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <libxml/xmlversion.h>
+
+#if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_VALID_ENABLED)
+
+#include <string.h>
+#include <sys/stat.h>
+
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/tree.h>
+#include <libxml/uri.h>
+#include <libxml/xmlreader.h>
+
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#define LOGFILE "runxmlconf.log"
+static FILE *logfile = NULL;
+static int verbose = 0;
+
+#define NB_EXPECTED_ERRORS 15
+
+
+const char *skipped_tests[] = {
+/* http://lists.w3.org/Archives/Public/public-xml-testsuite/2008Jul/0000.html */
+    "rmt-ns10-035",
+    NULL
+};
+
+/************************************************************************
+ *									*
+ *		File name and path utilities				*
+ *									*
+ ************************************************************************/
+
+static int checkTestFile(const char *filename) {
+    struct stat buf;
+
+    if (stat(filename, &buf) == -1)
+        return(0);
+
+#if defined(_WIN32)
+    if (!(buf.st_mode & _S_IFREG))
+        return(0);
+#else
+    if (!S_ISREG(buf.st_mode))
+        return(0);
+#endif
+
+    return(1);
+}
+
+static xmlChar *composeDir(const xmlChar *dir, const xmlChar *path) {
+    char buf[500];
+
+    if (dir == NULL) return(xmlStrdup(path));
+    if (path == NULL) return(NULL);
+
+    snprintf(buf, 500, "%s/%s", (const char *) dir, (const char *) path);
+    return(xmlStrdup((const xmlChar *) buf));
+}
+
+/************************************************************************
+ *									*
+ *		Libxml2 specific routines				*
+ *									*
+ ************************************************************************/
+
+static int nb_skipped = 0;
+static int nb_tests = 0;
+static int nb_errors = 0;
+static int nb_leaks = 0;
+
+/*
+ * We need to trap calls to the resolver to not account memory for the catalog
+ * and not rely on any external resources.
+ */
+static xmlParserInputPtr
+testExternalEntityLoader(const char *URL, const char *ID ATTRIBUTE_UNUSED,
+			 xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr ret;
+
+    ret = xmlNewInputFromFile(ctxt, (const char *) URL);
+
+    return(ret);
+}
+
+/*
+ * Trapping the error messages at the generic level to grab the equivalent of
+ * stderr messages on CLI tools.
+ */
+static char testErrors[32769];
+static int testErrorsSize = 0;
+static int nbError = 0;
+static int nbFatal = 0;
+
+static void test_log(const char *msg, ...) {
+    va_list args;
+    if (logfile != NULL) {
+        fprintf(logfile, "\n------------\n");
+	va_start(args, msg);
+	vfprintf(logfile, msg, args);
+	va_end(args);
+	fprintf(logfile, "%s", testErrors);
+	testErrorsSize = 0; testErrors[0] = 0;
+    }
+    if (verbose) {
+	va_start(args, msg);
+	vfprintf(stderr, msg, args);
+	va_end(args);
+    }
+}
+
+static void
+testErrorHandler(void *userData ATTRIBUTE_UNUSED, const xmlError *error) {
+    int res;
+
+    if (testErrorsSize >= 32768)
+        return;
+    res = snprintf(&testErrors[testErrorsSize],
+                    32768 - testErrorsSize,
+		   "%s:%d: %s\n", (error->file ? error->file : "entity"),
+		   error->line, error->message);
+    if (error->level == XML_ERR_FATAL)
+        nbFatal++;
+    else if (error->level == XML_ERR_ERROR)
+        nbError++;
+    if (testErrorsSize + res >= 32768) {
+        /* buffer is full */
+	testErrorsSize = 32768;
+	testErrors[testErrorsSize] = 0;
+    } else {
+        testErrorsSize += res;
+    }
+    testErrors[testErrorsSize] = 0;
+}
+
+static xmlXPathContextPtr ctxtXPath;
+
+static void
+initializeLibxml2(void) {
+    xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
+    xmlInitParser();
+    xmlSetExternalEntityLoader(testExternalEntityLoader);
+    ctxtXPath = xmlXPathNewContext(NULL);
+    /*
+    * Deactivate the cache if created; otherwise we have to create/free it
+    * for every test, since it will confuse the memory leak detection.
+    * Note that normally this need not be done, since the cache is not
+    * created until set explicitly with xmlXPathContextSetCache();
+    * but for test purposes it is sometimes useful to activate the
+    * cache by default for the whole library.
+    */
+    if (ctxtXPath->cache != NULL)
+	xmlXPathContextSetCache(ctxtXPath, 0, -1, 0);
+}
+
+/************************************************************************
+ *									*
+ *		Run the xmlconf test if found				*
+ *									*
+ ************************************************************************/
+
+static int
+xmlconfTestInvalid(const char *id, const char *filename, int options) {
+    xmlDocPtr doc;
+    xmlParserCtxtPtr ctxt;
+    int ret = 1;
+
+    ctxt = xmlNewParserCtxt();
+    if (ctxt == NULL) {
+        test_log("test %s : %s out of memory\n",
+	         id, filename);
+        return(0);
+    }
+    xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL);
+    doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
+    if (doc == NULL) {
+        test_log("test %s : %s invalid document turned not well-formed too\n",
+	         id, filename);
+    } else {
+    /* invalidity should be reported both in the context and in the document */
+        if ((ctxt->valid != 0) || (doc->properties & XML_DOC_DTDVALID)) {
+	    test_log("test %s : %s failed to detect invalid document\n",
+		     id, filename);
+	    nb_errors++;
+	    ret = 0;
+	}
+	xmlFreeDoc(doc);
+    }
+    xmlFreeParserCtxt(ctxt);
+    return(ret);
+}
+
+static int
+xmlconfTestValid(const char *id, const char *filename, int options) {
+    xmlDocPtr doc;
+    xmlParserCtxtPtr ctxt;
+    int ret = 1;
+
+    ctxt = xmlNewParserCtxt();
+    if (ctxt == NULL) {
+        test_log("test %s : %s out of memory\n",
+	         id, filename);
+        return(0);
+    }
+    xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL);
+    doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
+    if (doc == NULL) {
+        test_log("test %s : %s failed to parse a valid document\n",
+	         id, filename);
+        nb_errors++;
+	ret = 0;
+    } else {
+    /* validity should be reported both in the context and in the document */
+        if ((ctxt->valid == 0) || ((doc->properties & XML_DOC_DTDVALID) == 0)) {
+	    test_log("test %s : %s failed to validate a valid document\n",
+		     id, filename);
+	    nb_errors++;
+	    ret = 0;
+	}
+	xmlFreeDoc(doc);
+    }
+    xmlFreeParserCtxt(ctxt);
+    return(ret);
+}
+
+static int
+xmlconfTestNotNSWF(const char *id, const char *filename, int options) {
+    xmlParserCtxtPtr ctxt;
+    xmlDocPtr doc;
+    int ret = 1;
+
+    ctxt = xmlNewParserCtxt();
+    xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL);
+    /*
+     * In case of Namespace errors, libxml2 will still parse the document
+     * but log a Namespace error.
+     */
+    doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
+    if (doc == NULL) {
+        test_log("test %s : %s failed to parse the XML\n",
+	         id, filename);
+        nb_errors++;
+	ret = 0;
+    } else {
+        const xmlError *error = xmlGetLastError();
+
+	if ((error->code == XML_ERR_OK) ||
+	    (error->domain != XML_FROM_NAMESPACE)) {
+	    test_log("test %s : %s failed to detect namespace error\n",
+		     id, filename);
+	    nb_errors++;
+	    ret = 0;
+	}
+	xmlFreeDoc(doc);
+    }
+    xmlFreeParserCtxt(ctxt);
+    return(ret);
+}
+
+static int
+xmlconfTestNotWF(const char *id, const char *filename, int options) {
+    xmlParserCtxtPtr ctxt;
+    xmlDocPtr doc;
+    int ret = 1;
+
+    ctxt = xmlNewParserCtxt();
+    xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL);
+    doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
+    if (doc != NULL) {
+        test_log("test %s : %s failed to detect not well formedness\n",
+	         id, filename);
+        nb_errors++;
+	xmlFreeDoc(doc);
+	ret = 0;
+    }
+    xmlFreeParserCtxt(ctxt);
+    return(ret);
+}
+
+static int
+xmlconfTestItem(xmlDocPtr doc, xmlNodePtr cur) {
+    int ret = -1;
+    xmlChar *type = NULL;
+    xmlChar *filename = NULL;
+    xmlChar *uri = NULL;
+    xmlChar *base = NULL;
+    xmlChar *id = NULL;
+    xmlChar *rec = NULL;
+    xmlChar *version = NULL;
+    xmlChar *entities = NULL;
+    xmlChar *edition = NULL;
+    int options = 0;
+    int nstest = 0;
+    int mem, final;
+    int i;
+
+    testErrorsSize = 0; testErrors[0] = 0;
+    nbError = 0;
+    nbFatal = 0;
+    id = xmlGetProp(cur, BAD_CAST "ID");
+    if (id == NULL) {
+        test_log("test missing ID, line %ld\n", xmlGetLineNo(cur));
+	goto error;
+    }
+    for (i = 0;skipped_tests[i] != NULL;i++) {
+        if (!strcmp(skipped_tests[i], (char *) id)) {
+	    test_log("Skipping test %s from skipped list\n", (char *) id);
+	    ret = 0;
+	    nb_skipped++;
+	    goto error;
+	}
+    }
+    type = xmlGetProp(cur, BAD_CAST "TYPE");
+    if (type == NULL) {
+        test_log("test %s missing TYPE\n", (char *) id);
+	goto error;
+    }
+    uri = xmlGetProp(cur, BAD_CAST "URI");
+    if (uri == NULL) {
+        test_log("test %s missing URI\n", (char *) id);
+	goto error;
+    }
+    base = xmlNodeGetBase(doc, cur);
+    filename = composeDir(base, uri);
+    if (!checkTestFile((char *) filename)) {
+        test_log("test %s missing file %s \n", id,
+	         (filename ? (char *)filename : "NULL"));
+	goto error;
+    }
+
+    version = xmlGetProp(cur, BAD_CAST "VERSION");
+
+    entities = xmlGetProp(cur, BAD_CAST "ENTITIES");
+    if (!xmlStrEqual(entities, BAD_CAST "none")) {
+        options |= XML_PARSE_DTDLOAD;
+        options |= XML_PARSE_NOENT;
+    }
+    rec = xmlGetProp(cur, BAD_CAST "RECOMMENDATION");
+    if ((rec == NULL) ||
+        (xmlStrEqual(rec, BAD_CAST "XML1.0")) ||
+	(xmlStrEqual(rec, BAD_CAST "XML1.0-errata2e")) ||
+	(xmlStrEqual(rec, BAD_CAST "XML1.0-errata3e")) ||
+	(xmlStrEqual(rec, BAD_CAST "XML1.0-errata4e"))) {
+	if ((version != NULL) && (!xmlStrEqual(version, BAD_CAST "1.0"))) {
+	    test_log("Skipping test %s for %s\n", (char *) id,
+	             (char *) version);
+	    ret = 0;
+	    nb_skipped++;
+	    goto error;
+	}
+	ret = 1;
+    } else if ((xmlStrEqual(rec, BAD_CAST "NS1.0")) ||
+	       (xmlStrEqual(rec, BAD_CAST "NS1.0-errata1e"))) {
+	ret = 1;
+	nstest = 1;
+    } else {
+        test_log("Skipping test %s for REC %s\n", (char *) id, (char *) rec);
+	ret = 0;
+	nb_skipped++;
+	goto error;
+    }
+    edition = xmlGetProp(cur, BAD_CAST "EDITION");
+    if ((edition != NULL) && (xmlStrchr(edition, '5') == NULL)) {
+        /* test limited to all versions before 5th */
+	options |= XML_PARSE_OLD10;
+    }
+
+    /*
+     * Reset errors and check memory usage before the test
+     */
+    xmlResetLastError();
+    testErrorsSize = 0; testErrors[0] = 0;
+    mem = xmlMemUsed();
+
+    if (xmlStrEqual(type, BAD_CAST "not-wf")) {
+        if (nstest == 0)
+	    xmlconfTestNotWF((char *) id, (char *) filename, options);
+        else
+	    xmlconfTestNotNSWF((char *) id, (char *) filename, options);
+    } else if (xmlStrEqual(type, BAD_CAST "valid")) {
+        options |= XML_PARSE_DTDVALID;
+	xmlconfTestValid((char *) id, (char *) filename, options);
+    } else if (xmlStrEqual(type, BAD_CAST "invalid")) {
+        options |= XML_PARSE_DTDVALID;
+	xmlconfTestInvalid((char *) id, (char *) filename, options);
+    } else if (xmlStrEqual(type, BAD_CAST "error")) {
+        test_log("Skipping error test %s \n", (char *) id);
+	ret = 0;
+	nb_skipped++;
+	goto error;
+    } else {
+        test_log("test %s unknown TYPE value %s\n", (char *) id, (char *)type);
+	ret = -1;
+	goto error;
+    }
+
+    /*
+     * Reset errors and check memory usage after the test
+     */
+    xmlResetLastError();
+    final = xmlMemUsed();
+    if (final > mem) {
+        test_log("test %s : %s leaked %d bytes\n",
+	         id, filename, final - mem);
+        nb_leaks++;
+    }
+    nb_tests++;
+
+error:
+    if (type != NULL)
+        xmlFree(type);
+    if (entities != NULL)
+        xmlFree(entities);
+    if (edition != NULL)
+        xmlFree(edition);
+    if (version != NULL)
+        xmlFree(version);
+    if (filename != NULL)
+        xmlFree(filename);
+    if (uri != NULL)
+        xmlFree(uri);
+    if (base != NULL)
+        xmlFree(base);
+    if (id != NULL)
+        xmlFree(id);
+    if (rec != NULL)
+        xmlFree(rec);
+    return(ret);
+}
+
+static int
+xmlconfTestCases(xmlDocPtr doc, xmlNodePtr cur, int level) {
+    xmlChar *profile;
+    int ret = 0;
+    int tests = 0;
+    int output = 0;
+
+    if (level == 1) {
+	profile = xmlGetProp(cur, BAD_CAST "PROFILE");
+	if (profile != NULL) {
+	    output = 1;
+	    level++;
+	    printf("Test cases: %s\n", (char *) profile);
+	    xmlFree(profile);
+	}
+    }
+    cur = cur->children;
+    while (cur != NULL) {
+        /* look only at elements we ignore everything else */
+        if (cur->type == XML_ELEMENT_NODE) {
+	    if (xmlStrEqual(cur->name, BAD_CAST "TESTCASES")) {
+	        ret += xmlconfTestCases(doc, cur, level);
+	    } else if (xmlStrEqual(cur->name, BAD_CAST "TEST")) {
+	        if (xmlconfTestItem(doc, cur) >= 0)
+		    ret++;
+		tests++;
+	    } else {
+	        fprintf(stderr, "Unhandled element %s\n", (char *)cur->name);
+	    }
+	}
+        cur = cur->next;
+    }
+    if (output == 1) {
+	if (tests > 0)
+	    printf("Test cases: %d tests\n", tests);
+    }
+    return(ret);
+}
+
+static int
+xmlconfTestSuite(xmlDocPtr doc, xmlNodePtr cur) {
+    xmlChar *profile;
+    int ret = 0;
+
+    profile = xmlGetProp(cur, BAD_CAST "PROFILE");
+    if (profile != NULL) {
+        printf("Test suite: %s\n", (char *) profile);
+	xmlFree(profile);
+    } else
+        printf("Test suite\n");
+    cur = cur->children;
+    while (cur != NULL) {
+        /* look only at elements we ignore everything else */
+        if (cur->type == XML_ELEMENT_NODE) {
+	    if (xmlStrEqual(cur->name, BAD_CAST "TESTCASES")) {
+	        ret += xmlconfTestCases(doc, cur, 1);
+	    } else {
+	        fprintf(stderr, "Unhandled element %s\n", (char *)cur->name);
+	    }
+	}
+        cur = cur->next;
+    }
+    return(ret);
+}
+
+static void
+xmlconfInfo(void) {
+    fprintf(stderr, "  you need to fetch and extract the\n");
+    fprintf(stderr, "  latest XML Conformance Test Suites\n");
+    fprintf(stderr, "  http://www.w3.org/XML/Test/xmlts20080827.tar.gz\n");
+    fprintf(stderr, "  see http://www.w3.org/XML/Test/ for information\n");
+}
+
+static int
+xmlconfTest(void) {
+    const char *confxml = "xmlconf/xmlconf.xml";
+    xmlDocPtr doc;
+    xmlNodePtr cur;
+    int ret = 0;
+
+    if (!checkTestFile(confxml)) {
+        fprintf(stderr, "%s is missing \n", confxml);
+	xmlconfInfo();
+	return(-1);
+    }
+    doc = xmlReadFile(confxml, NULL, XML_PARSE_NOENT);
+    if (doc == NULL) {
+        fprintf(stderr, "%s is corrupted \n", confxml);
+	xmlconfInfo();
+	return(-1);
+    }
+
+    cur = xmlDocGetRootElement(doc);
+    if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "TESTSUITE"))) {
+        fprintf(stderr, "Unexpected format %s\n", confxml);
+	xmlconfInfo();
+	ret = -1;
+    } else {
+        ret = xmlconfTestSuite(doc, cur);
+    }
+    xmlFreeDoc(doc);
+    return(ret);
+}
+
+/************************************************************************
+ *									*
+ *		The driver for the tests				*
+ *									*
+ ************************************************************************/
+
+int
+main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    int ret = 0;
+    int old_errors, old_tests, old_leaks;
+
+    logfile = fopen(LOGFILE, "w");
+    if (logfile == NULL) {
+        fprintf(stderr,
+	        "Could not open the log file, running in verbose mode\n");
+	verbose = 1;
+    }
+    initializeLibxml2();
+
+    if ((argc >= 2) && (!strcmp(argv[1], "-v")))
+        verbose = 1;
+
+
+    old_errors = nb_errors;
+    old_tests = nb_tests;
+    old_leaks = nb_leaks;
+    xmlconfTest();
+    if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
+	printf("Ran %d tests, no errors\n", nb_tests - old_tests);
+    else
+	printf("Ran %d tests, %d errors, %d leaks\n",
+	       nb_tests - old_tests,
+	       nb_errors - old_errors,
+	       nb_leaks - old_leaks);
+    if ((nb_errors == 0) && (nb_leaks == 0)) {
+        ret = 0;
+	printf("Total %d tests, no errors\n",
+	       nb_tests);
+    } else {
+	ret = 1;
+	printf("Total %d tests, %d errors, %d leaks\n",
+	       nb_tests, nb_errors, nb_leaks);
+	printf("See %s for detailed output\n", LOGFILE);
+	if ((nb_leaks == 0) && (nb_errors == NB_EXPECTED_ERRORS)) {
+	    printf("%d errors were expected\n", nb_errors);
+	    ret = 0;
+	}
+    }
+    xmlXPathFreeContext(ctxtXPath);
+    xmlCleanupParser();
+
+    if (logfile != NULL)
+        fclose(logfile);
+    return(ret);
+}
+
+#else /* ! LIBXML_XPATH_ENABLED */
+int
+main(int argc ATTRIBUTE_UNUSED, char **argv) {
+    fprintf(stderr, "%s need XPath and validation support\n", argv[0]);
+    return(0);
+}
+#endif
diff --git a/save.h b/save.h
deleted file mode 100644
index 192b6741335800e62d55d92dd69bb87a42465f5f..0000000000000000000000000000000000000000
--- a/save.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Summary: Internal Interfaces for saving in libxml2
- * Description: this module describes a few interfaces which were
- *              added along with the API changes in 2.9.0
- *              those are private routines at this point
- *
- * Copy: See Copyright for the status of this software.
- *
- * Author: Daniel Veillard
- */
-
-#ifndef __XML_SAVE_H__
-#define __XML_SAVE_H__
-
-#include <libxml/tree.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef LIBXML_OUTPUT_ENABLED
-void xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc,
-                                   xmlAttrPtr attr, const xmlChar * string);
-void xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table);
-void xmlBufDumpElementDecl(xmlBufPtr buf, xmlElementPtr elem);
-void xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr);
-void xmlBufDumpEntityDecl(xmlBufPtr buf, xmlEntityPtr ent);
-#endif
-
-xmlChar *xmlEncodeAttributeEntities(xmlDocPtr doc, const xmlChar *input);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* __XML_SAVE_H__ */
-
diff --git a/schematron.c b/schematron.c
index 68a4c622ebd346d749432962f8e7b8e06531f02d..1de25deb971cbac6addbf6841994d8b1c87fc5c6 100644
--- a/schematron.c
+++ b/schematron.c
@@ -25,6 +25,7 @@
 
 #ifdef LIBXML_SCHEMATRON_ENABLED
 
+#include <stdlib.h>
 #include <string.h>
 #include <libxml/parser.h>
 #include <libxml/tree.h>
@@ -34,6 +35,8 @@
 #include <libxml/pattern.h>
 #include <libxml/schematron.h>
 
+#include "private/error.h"
+
 #define SCHEMATRON_PARSE_OPTIONS XML_PARSE_NOENT
 
 #define SCT_OLD_NS BAD_CAST "http://www.ascc.net/xml/schematron"
@@ -60,16 +63,6 @@ static const xmlChar *xmlOldSchematronNs = SCT_OLD_NS;
        node = node->next;                                               \
    }
 
-/**
- * TODO:
- *
- * macro to flag unimplemented blocks
- */
-#define TODO                                                            \
-    xmlGenericError(xmlGenericErrorContext,                             \
-            "Unimplemented block at %s:%d\n",                           \
-            __FILE__, __LINE__);
-
 typedef enum {
     XML_SCHEMATRON_ASSERT=1,
     XML_SCHEMATRON_REPORT=2
@@ -239,13 +232,11 @@ struct _xmlSchematronParserCtxt {
  * Handle an out of memory condition
  */
 static void
-xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt,
-                        const char *extra, xmlNodePtr node)
+xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt)
 {
     if (ctxt != NULL)
         ctxt->nberrors++;
-    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
-                     extra);
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_SCHEMASP, NULL);
 }
 
 /**
@@ -266,6 +257,7 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
     xmlGenericErrorFunc channel = NULL;
     xmlStructuredErrorFunc schannel = NULL;
     void *data = NULL;
+    int res;
 
     if (ctxt != NULL) {
         ctxt->nberrors++;
@@ -273,10 +265,18 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
         data = ctxt->userData;
         schannel = ctxt->serror;
     }
-    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
-                    error, XML_ERR_ERROR, NULL, 0,
-                    (const char *) str1, (const char *) str2, NULL, 0, 0,
-                    msg, str1, str2);
+
+    if ((channel == NULL) && (schannel == NULL)) {
+        channel = xmlGenericError;
+        data = xmlGenericErrorContext;
+    }
+
+    res = __xmlRaiseError(schannel, channel, data, ctxt, node,
+                          XML_FROM_SCHEMASP, error, XML_ERR_ERROR, NULL, 0,
+                          (const char *) str1, (const char *) str2, NULL, 0, 0,
+                          msg, str1, str2);
+    if (res < 0)
+        xmlSchematronPErrMemory(ctxt);
 }
 
 /**
@@ -287,15 +287,53 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
  * Handle an out of memory condition
  */
 static void
-xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt,
-                        const char *extra, xmlNodePtr node)
+xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt)
 {
     if (ctxt != NULL) {
         ctxt->nberrors++;
         ctxt->err = XML_SCHEMAV_INTERNAL;
     }
-    __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
-                     extra);
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_SCHEMASV, NULL);
+}
+
+/**
+ * xmlSchematronVErr:
+ * @ctxt: the parsing context
+ * @node: the context node
+ * @error: the error code
+ * @msg: the error message
+ * @str1: extra data
+ * @str2: extra data
+ *
+ * Handle a validation error
+ */
+static void LIBXML_ATTR_FORMAT(3,0)
+xmlSchematronVErr(xmlSchematronValidCtxtPtr ctxt, int error,
+                  const char *msg, const xmlChar * str1)
+{
+    xmlGenericErrorFunc channel = NULL;
+    xmlStructuredErrorFunc schannel = NULL;
+    void *data = NULL;
+    int res;
+
+    if (ctxt != NULL) {
+        ctxt->nberrors++;
+        channel = ctxt->error;
+        data = ctxt->userData;
+        schannel = ctxt->serror;
+    }
+
+    if ((channel == NULL) && (schannel == NULL)) {
+        channel = xmlGenericError;
+        data = xmlGenericErrorContext;
+    }
+
+    res = __xmlRaiseError(schannel, channel, data, ctxt, NULL,
+                          XML_FROM_SCHEMASV, error, XML_ERR_ERROR, NULL, 0,
+                          (const char *) str1, NULL, NULL, 0, 0,
+                          msg, str1);
+    if (res < 0)
+        xmlSchematronVErrMemory(ctxt);
 }
 
 /************************************************************************
@@ -344,7 +382,7 @@ xmlSchematronAddTest(xmlSchematronParserCtxtPtr ctxt,
 
     ret = (xmlSchematronTestPtr) xmlMalloc(sizeof(xmlSchematronTest));
     if (ret == NULL) {
-        xmlSchematronPErrMemory(ctxt, "allocating schema test", node);
+        xmlSchematronPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchematronTest));
@@ -448,7 +486,7 @@ xmlSchematronAddRule(xmlSchematronParserCtxtPtr ctxt, xmlSchematronPtr schema,
 
     ret = (xmlSchematronRulePtr) xmlMalloc(sizeof(xmlSchematronRule));
     if (ret == NULL) {
-        xmlSchematronPErrMemory(ctxt, "allocating schema rule", node);
+        xmlSchematronPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchematronRule));
@@ -529,7 +567,7 @@ xmlSchematronAddPattern(xmlSchematronParserCtxtPtr ctxt,
 
     ret = (xmlSchematronPatternPtr) xmlMalloc(sizeof(xmlSchematronPattern));
     if (ret == NULL) {
-        xmlSchematronPErrMemory(ctxt, "allocating schema pattern", node);
+        xmlSchematronPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchematronPattern));
@@ -581,7 +619,7 @@ xmlSchematronNewSchematron(xmlSchematronParserCtxtPtr ctxt)
 
     ret = (xmlSchematronPtr) xmlMalloc(sizeof(xmlSchematron));
     if (ret == NULL) {
-        xmlSchematronPErrMemory(ctxt, "allocating schema", NULL);
+        xmlSchematronPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchematron));
@@ -636,8 +674,7 @@ xmlSchematronNewParserCtxt(const char *URL)
         (xmlSchematronParserCtxtPtr)
         xmlMalloc(sizeof(xmlSchematronParserCtxt));
     if (ret == NULL) {
-        xmlSchematronPErrMemory(NULL, "allocating schema parser context",
-                                NULL);
+        xmlSchematronPErrMemory(NULL);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchematronParserCtxt));
@@ -647,8 +684,7 @@ xmlSchematronNewParserCtxt(const char *URL)
     ret->includes = NULL;
     ret->xctxt = xmlXPathNewContext(NULL);
     if (ret->xctxt == NULL) {
-        xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
-                                NULL);
+        xmlSchematronPErrMemory(NULL);
         xmlSchematronFreeParserCtxt(ret);
         return (NULL);
     }
@@ -678,8 +714,7 @@ xmlSchematronNewMemParserCtxt(const char *buffer, int size)
         (xmlSchematronParserCtxtPtr)
         xmlMalloc(sizeof(xmlSchematronParserCtxt));
     if (ret == NULL) {
-        xmlSchematronPErrMemory(NULL, "allocating schema parser context",
-                                NULL);
+        xmlSchematronPErrMemory(NULL);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchematronParserCtxt));
@@ -688,8 +723,7 @@ xmlSchematronNewMemParserCtxt(const char *buffer, int size)
     ret->dict = xmlDictCreate();
     ret->xctxt = xmlXPathNewContext(NULL);
     if (ret->xctxt == NULL) {
-        xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
-                                NULL);
+        xmlSchematronPErrMemory(NULL);
         xmlSchematronFreeParserCtxt(ret);
         return (NULL);
     }
@@ -717,8 +751,7 @@ xmlSchematronNewDocParserCtxt(xmlDocPtr doc)
         (xmlSchematronParserCtxtPtr)
         xmlMalloc(sizeof(xmlSchematronParserCtxt));
     if (ret == NULL) {
-        xmlSchematronPErrMemory(NULL, "allocating schema parser context",
-                                NULL);
+        xmlSchematronPErrMemory(NULL);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchematronParserCtxt));
@@ -728,8 +761,7 @@ xmlSchematronNewDocParserCtxt(xmlDocPtr doc)
     ret->preserve = 1;
     ret->xctxt = xmlXPathNewContext(doc);
     if (ret->xctxt == NULL) {
-        xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
-                                NULL);
+        xmlSchematronPErrMemory(NULL);
         xmlSchematronFreeParserCtxt(ret);
         return (NULL);
     }
@@ -777,8 +809,7 @@ xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt,
         ctxt->includes = (xmlNodePtr *)
             xmlMalloc(ctxt->maxIncludes * 2 * sizeof(xmlNodePtr));
         if (ctxt->includes == NULL) {
-            xmlSchematronPErrMemory(NULL, "allocating parser includes",
-                                    NULL);
+            xmlSchematronPErrMemory(NULL);
             return;
         }
         ctxt->nbIncludes = 0;
@@ -789,8 +820,7 @@ xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt,
             xmlRealloc(ctxt->includes, ctxt->maxIncludes * 4 *
                        sizeof(xmlNodePtr));
         if (tmp == NULL) {
-            xmlSchematronPErrMemory(NULL, "allocating parser includes",
-                                    NULL);
+            xmlSchematronPErrMemory(NULL);
             return;
         }
         ctxt->includes = tmp;
@@ -847,8 +877,7 @@ xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt,
         ctxt->namespaces = (const xmlChar **)
             xmlMalloc(ctxt->maxNamespaces * 2 * sizeof(const xmlChar *));
         if (ctxt->namespaces == NULL) {
-            xmlSchematronPErrMemory(NULL, "allocating parser namespaces",
-                                    NULL);
+            xmlSchematronPErrMemory(NULL);
             return;
         }
         ctxt->nbNamespaces = 0;
@@ -859,8 +888,7 @@ xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt,
             xmlRealloc((xmlChar **) ctxt->namespaces, ctxt->maxNamespaces * 4 *
                        sizeof(const xmlChar *));
         if (tmp == NULL) {
-            xmlSchematronPErrMemory(NULL, "allocating parser namespaces",
-                                    NULL);
+            xmlSchematronPErrMemory(NULL);
             return;
         }
         ctxt->namespaces = tmp;
@@ -1490,9 +1518,6 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
                             ret = xmlStrcat(ret, spacer);
                         ret = xmlStrcat(ret, eval->nodesetval->nodeTab[indx]->name);
                     }
-                } else {
-                    xmlGenericError(xmlGenericErrorContext,
-                                    "Empty node set\n");
                 }
                 break;
             }
@@ -1506,19 +1531,20 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
                 int size;
 
                 size = snprintf(NULL, 0, "%0g", eval->floatval);
-                buf = (xmlChar*) malloc(size * sizeof(xmlChar));
-                /* xmlStrPrintf(buf, size, "%0g", eval->floatval); // doesn't work */
-                sprintf((char*) buf, "%0g", eval->floatval);
-                ret = xmlStrcat(ret, buf);
-                free(buf);
+                buf = (xmlChar *) xmlMalloc(size + 1);
+                if (buf != NULL) {
+                    snprintf((char *) buf, size + 1, "%0g", eval->floatval);
+                    ret = xmlStrcat(ret, buf);
+                    xmlFree(buf);
+                }
                 break;
             }
             case XPATH_STRING:
                 ret = xmlStrcat(ret, eval->stringval);
                 break;
             default:
-                xmlGenericError(xmlGenericErrorContext,
-                                "Unsupported XPATH Type: %d\n", eval->type);
+                xmlSchematronVErr(ctxt, XML_ERR_INTERNAL_ERROR,
+                                  "Unsupported XPATH Type\n", NULL);
             }
             xmlXPathFreeObject(eval);
             xmlXPathFreeCompExpr(comp);
@@ -1577,15 +1603,15 @@ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt,
         (test->type == XML_SCHEMATRON_REPORT))
         return;
     if (ctxt->flags & XML_SCHEMATRON_OUT_XML) {
-        TODO
+        /* TODO */
     } else {
         xmlChar *path;
         char msg[1000];
         long line;
         const xmlChar *report = NULL;
 
-        if (((test->type == XML_SCHEMATRON_REPORT) & (!success)) ||
-            ((test->type == XML_SCHEMATRON_ASSERT) & (success)))
+        if (((test->type == XML_SCHEMATRON_REPORT) && (!success)) ||
+            ((test->type == XML_SCHEMATRON_ASSERT) && (success)))
             return;
         line = xmlGetLineNo(cur);
         path = xmlGetNodePath(cur);
@@ -1608,26 +1634,33 @@ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt,
                      line, (const char *) report);
 
     if (ctxt->flags & XML_SCHEMATRON_OUT_ERROR) {
-        xmlStructuredErrorFunc schannel = NULL;
-        xmlGenericErrorFunc channel = NULL;
-        void *data = NULL;
-
-        if (ctxt != NULL) {
-            if (ctxt->serror != NULL)
-                schannel = ctxt->serror;
-            else
-                channel = ctxt->error;
-            data = ctxt->userData;
+        xmlStructuredErrorFunc schannel;
+        xmlGenericErrorFunc channel;
+        void *data;
+        int res;
+
+        schannel = ctxt->serror;
+        channel = ctxt->error;
+        data = ctxt->userData;
+
+        if ((channel == NULL) && (schannel == NULL)) {
+            channel = xmlGenericError;
+            data = xmlGenericErrorContext;
         }
 
-        __xmlRaiseError(schannel, channel, data,
-                        NULL, cur, XML_FROM_SCHEMATRONV,
-                        (test->type == XML_SCHEMATRON_ASSERT)?XML_SCHEMATRONV_ASSERT:XML_SCHEMATRONV_REPORT,
-                        XML_ERR_ERROR, NULL, line,
-                        (pattern == NULL)?NULL:((const char *) pattern->name),
-                        (const char *) path,
-                        (const char *) report, 0, 0,
-                        "%s", msg);
+        res = __xmlRaiseError(schannel, channel, data, NULL, cur,
+                              XML_FROM_SCHEMATRONV,
+                              (test->type == XML_SCHEMATRON_ASSERT) ?
+                                  XML_SCHEMATRONV_ASSERT :
+                                  XML_SCHEMATRONV_REPORT,
+                              XML_ERR_ERROR, NULL, line,
+                              (pattern == NULL) ?
+                                  NULL :
+                                  (const char *) pattern->name,
+                              (const char *) path, (const char *) report, 0, 0,
+                              "%s", msg);
+        if (res < 0)
+            xmlSchematronVErrMemory(ctxt);
     } else {
         xmlSchematronReportOutput(ctxt, cur, &msg[0]);
     }
@@ -1654,7 +1687,7 @@ xmlSchematronReportPattern(xmlSchematronValidCtxtPtr ctxt,
     if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) || (ctxt->flags & XML_SCHEMATRON_OUT_ERROR)) /* Error gives pattern name as part of error */
         return;
     if (ctxt->flags & XML_SCHEMATRON_OUT_XML) {
-        TODO
+        /* TODO */
     } else {
         char msg[1000];
 
@@ -1709,8 +1742,7 @@ xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options)
 
     ret = (xmlSchematronValidCtxtPtr) xmlMalloc(sizeof(xmlSchematronValidCtxt));
     if (ret == NULL) {
-        xmlSchematronVErrMemory(NULL, "allocating validation context",
-                                NULL);
+        xmlSchematronVErrMemory(NULL);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchematronValidCtxt));
@@ -1719,8 +1751,7 @@ xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options)
     ret->xctxt = xmlXPathNewContext(NULL);
     ret->flags = options;
     if (ret->xctxt == NULL) {
-        xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
-                                NULL);
+        xmlSchematronPErrMemory(NULL);
         xmlSchematronFreeValidCtxt(ret);
         return (NULL);
     }
@@ -1866,7 +1897,9 @@ xmlSchematronRunTest(xmlSchematronValidCtxtPtr ctxt,
  * Returns -1 in case of errors, otherwise 0
  */
 static int
-xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let,
+xmlSchematronRegisterVariables(xmlSchematronValidCtxtPtr vctxt,
+                               xmlXPathContextPtr ctxt,
+                               xmlSchematronLetPtr let,
                                xmlDocPtr instance, xmlNodePtr cur)
 {
     xmlXPathObjectPtr let_eval;
@@ -1876,13 +1909,14 @@ xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let,
     while (let != NULL) {
         let_eval = xmlXPathCompiledEval(let->comp, ctxt);
         if (let_eval == NULL) {
-            xmlGenericError(xmlGenericErrorContext,
-                            "Evaluation of compiled expression failed\n");
+            xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR,
+                              "Evaluation of compiled expression failed\n",
+                              NULL);
             return -1;
         }
         if(xmlXPathRegisterVariableNS(ctxt, let->name, NULL, let_eval)) {
-            xmlGenericError(xmlGenericErrorContext,
-                            "Registering a let variable failed\n");
+            xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR,
+                              "Registering a let variable failed\n", NULL);
             return -1;
         }
         let = let->next;
@@ -1900,12 +1934,14 @@ xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let,
  * Returns -1 in case of errors, otherwise 0
  */
 static int
-xmlSchematronUnregisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let)
+xmlSchematronUnregisterVariables(xmlSchematronValidCtxtPtr vctxt,
+                                 xmlXPathContextPtr ctxt,
+                                 xmlSchematronLetPtr let)
 {
     while (let != NULL) {
         if (xmlXPathRegisterVariableNS(ctxt, let->name, NULL, NULL)) {
-            xmlGenericError(xmlGenericErrorContext,
-                            "Unregistering a let variable failed\n");
+            xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR,
+                              "Unregistering a let variable failed\n", NULL);
             return -1;
         }
         let = let->next;
@@ -1937,7 +1973,7 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
     ctxt->nberrors = 0;
     root = xmlDocGetRootElement(instance);
     if (root == NULL) {
-        TODO
+        /* TODO */
         ctxt->nberrors++;
         return(1);
     }
@@ -1954,7 +1990,8 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
                 if (xmlPatternMatch(rule->pattern, cur) == 1) {
                     test = rule->tests;
 
-                    if (xmlSchematronRegisterVariables(ctxt->xctxt, rule->lets, instance, cur))
+                    if (xmlSchematronRegisterVariables(ctxt, ctxt->xctxt,
+                                rule->lets, instance, cur))
                         return -1;
 
                     while (test != NULL) {
@@ -1962,7 +1999,8 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
                         test = test->next;
                     }
 
-                    if (xmlSchematronUnregisterVariables(ctxt->xctxt, rule->lets))
+                    if (xmlSchematronUnregisterVariables(ctxt, ctxt->xctxt,
+                                rule->lets))
                         return -1;
 
                 }
@@ -1992,15 +2030,16 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
                 while (rule != NULL) {
                     if (xmlPatternMatch(rule->pattern, cur) == 1) {
                         test = rule->tests;
-                        xmlSchematronRegisterVariables(ctxt->xctxt, rule->lets,
-                                                       instance, cur);
+                        xmlSchematronRegisterVariables(ctxt, ctxt->xctxt,
+                                rule->lets, instance, cur);
 
                         while (test != NULL) {
                             xmlSchematronRunTest(ctxt, test, instance, cur, pattern);
                             test = test->next;
                         }
 
-                        xmlSchematronUnregisterVariables(ctxt->xctxt, rule->lets);
+                        xmlSchematronUnregisterVariables(ctxt, ctxt->xctxt,
+                                rule->lets);
                     }
                     rule = rule->patnext;
                 }
@@ -2051,7 +2090,6 @@ main(void)
     xmlFreeDoc(instance);
 
     xmlCleanupParser();
-    xmlMemoryDump();
 
     return (0);
 }
diff --git a/threads.c b/threads.c
index 06191f2052f59c4b3844f20e51f89c5352b6f11d..9ecfd81319bb616d6bb8f1795168fa14b3c700a7 100644
--- a/threads.c
+++ b/threads.c
@@ -14,43 +14,62 @@
 #include <stdlib.h>
 
 #include <libxml/threads.h>
-#include <libxml/globals.h>
-
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-#elif defined HAVE_WIN32_THREADS
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#ifndef HAVE_COMPILER_TLS
-#include <process.h>
+#include <libxml/parser.h>
+#ifdef LIBXML_CATALOG_ENABLED
+#include <libxml/catalog.h>
 #endif
-#endif
-
-#ifdef HAVE_BEOS_THREADS
-#include <OS.h>
-#include <TLS.h>
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/xmlschemastypes.h>
+#include <libxml/relaxng.h>
 #endif
 
 #if defined(SOLARIS)
 #include <note.h>
 #endif
 
-/* #define DEBUG_THREADS */
+#include "private/dict.h"
+#include "private/enc.h"
+#include "private/globals.h"
+#include "private/io.h"
+#include "private/memory.h"
+#include "private/threads.h"
+#include "private/xpath.h"
 
-#ifdef HAVE_PTHREAD_H
+#if defined(HAVE_POSIX_THREADS) && \
+    defined(__GLIBC__) && \
+    __GLIBC__ * 100 + __GLIBC_MINOR__ >= 234
 
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 303) && \
-    defined(__GLIBC__) && defined(__linux__)
+/*
+ * The modern way available since glibc 2.32.
+ *
+ * The check above is for glibc 2.34 which merged the pthread symbols into
+ * libc. Since we still allow linking without pthread symbols (see below),
+ * this only works if pthread symbols are guaranteed to be available.
+ */
 
-static int libxml_is_threaded = -1;
+#include <sys/single_threaded.h>
 
-#define XML_PTHREAD_WEAK
+#define XML_IS_THREADED() (!__libc_single_threaded)
+#define XML_IS_NEVER_THREADED() 0
+
+#elif defined(HAVE_POSIX_THREADS) && \
+      defined(__GLIBC__) && \
+      defined(__GNUC__)
+
+/*
+ * The traditional way to check for single-threaded applications with
+ * glibc was to check whether the separate libpthread library is
+ * linked in. This works by not linking libxml2 with libpthread (see
+ * BASE_THREAD_LIBS in configure.ac and Makefile.am) and declaring
+ * pthread functions as weak symbols.
+ *
+ * In glibc 2.34, the pthread symbols were moved from libpthread to libc,
+ * so this doesn't work anymore.
+ *
+ * At some point, this legacy code and the BASE_THREAD_LIBS hack in
+ * configure.ac can probably be removed.
+ */
 
-#pragma weak pthread_once
-#pragma weak pthread_getspecific
-#pragma weak pthread_setspecific
-#pragma weak pthread_key_create
-#pragma weak pthread_key_delete
 #pragma weak pthread_mutex_init
 #pragma weak pthread_mutex_destroy
 #pragma weak pthread_mutex_lock
@@ -60,17 +79,20 @@ static int libxml_is_threaded = -1;
 #pragma weak pthread_cond_wait
 #pragma weak pthread_equal
 #pragma weak pthread_self
-#pragma weak pthread_key_create
-#pragma weak pthread_key_delete
 #pragma weak pthread_cond_signal
 
-#else /* __GNUC__, __GLIBC__, __linux__ */
+#define XML_PTHREAD_WEAK
+#define XML_IS_THREADED() libxml_is_threaded
+#define XML_IS_NEVER_THREADED() (!libxml_is_threaded)
+
+static int libxml_is_threaded = -1;
 
-static int libxml_is_threaded = 1;
+#else /* other POSIX platforms */
 
-#endif /* __GNUC__, __GLIBC__, __linux__ */
+#define XML_IS_THREADED() 1
+#define XML_IS_NEVER_THREADED() 0
 
-#endif /* HAVE_PTHREAD_H */
+#endif
 
 /*
  * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree
@@ -78,27 +100,11 @@ static int libxml_is_threaded = 1;
  *       be hosted on allocated blocks needing them for the allocation ...
  */
 
-/*
- * xmlMutex are a simple mutual exception locks
- */
-struct _xmlMutex {
-#ifdef HAVE_PTHREAD_H
-    pthread_mutex_t lock;
-#elif defined HAVE_WIN32_THREADS
-    CRITICAL_SECTION cs;
-#elif defined HAVE_BEOS_THREADS
-    sem_id sem;
-    thread_id tid;
-#else
-    int empty;
-#endif
-};
-
 /*
  * xmlRMutex are reentrant mutual exception locks
  */
 struct _xmlRMutex {
-#ifdef HAVE_PTHREAD_H
+#ifdef HAVE_POSIX_THREADS
     pthread_mutex_t lock;
     unsigned int held;
     unsigned int waiters;
@@ -106,55 +112,31 @@ struct _xmlRMutex {
     pthread_cond_t cv;
 #elif defined HAVE_WIN32_THREADS
     CRITICAL_SECTION cs;
-#elif defined HAVE_BEOS_THREADS
-    xmlMutexPtr lock;
-    thread_id tid;
-    int32 count;
 #else
     int empty;
 #endif
 };
 
-/*
- * This module still has some internal static data.
- *   - xmlLibraryLock a global lock
- *   - globalkey used for per-thread data
- */
-
-#ifdef HAVE_PTHREAD_H
-static pthread_key_t globalkey;
-static pthread_t mainthread;
-static pthread_once_t once_control = PTHREAD_ONCE_INIT;
-static pthread_once_t once_control_init = PTHREAD_ONCE_INIT;
-static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
-#elif defined HAVE_WIN32_THREADS
-#if defined(HAVE_COMPILER_TLS)
-static __declspec(thread) xmlGlobalState tlstate;
-static __declspec(thread) int tlstate_inited = 0;
-#else /* HAVE_COMPILER_TLS */
-static DWORD globalkey = TLS_OUT_OF_INDEXES;
-#endif /* HAVE_COMPILER_TLS */
-static DWORD mainthread;
-static struct {
-    DWORD done;
-    LONG control;
-} run_once = { 0, 0};
-static volatile LPCRITICAL_SECTION global_init_lock = NULL;
-
-/* endif HAVE_WIN32_THREADS */
-#elif defined HAVE_BEOS_THREADS
-int32 globalkey = 0;
-thread_id mainthread = 0;
-int32 run_once_init = 0;
-static int32 global_init_lock = -1;
-static vint32 global_init_count = 0;
-#endif
-
 static xmlRMutexPtr xmlLibraryLock = NULL;
 
-#ifdef LIBXML_THREAD_ENABLED
-static void xmlOnceInit(void);
+/**
+ * xmlInitMutex:
+ * @mutex:  the mutex
+ *
+ * Initialize a mutex.
+ */
+void
+xmlInitMutex(xmlMutexPtr mutex)
+{
+#ifdef HAVE_POSIX_THREADS
+    if (XML_IS_NEVER_THREADED() == 0)
+        pthread_mutex_init(&mutex->lock, NULL);
+#elif defined HAVE_WIN32_THREADS
+    InitializeCriticalSection(&mutex->cs);
+#else
+    (void) mutex;
 #endif
+}
 
 /**
  * xmlNewMutex:
@@ -171,27 +153,34 @@ xmlNewMutex(void)
 
     if ((tok = malloc(sizeof(xmlMutex))) == NULL)
         return (NULL);
-#ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded != 0)
-        pthread_mutex_init(&tok->lock, NULL);
+    xmlInitMutex(tok);
+    return (tok);
+}
+
+/**
+ * xmlCleanupMutex:
+ * @mutex:  the simple mutex
+ *
+ * Reclaim resources associated with a mutex.
+ */
+void
+xmlCleanupMutex(xmlMutexPtr mutex)
+{
+#ifdef HAVE_POSIX_THREADS
+    if (XML_IS_NEVER_THREADED() == 0)
+        pthread_mutex_destroy(&mutex->lock);
 #elif defined HAVE_WIN32_THREADS
-    InitializeCriticalSection(&tok->cs);
-#elif defined HAVE_BEOS_THREADS
-    if ((tok->sem = create_sem(1, "xmlMutex")) < B_OK) {
-        free(tok);
-        return NULL;
-    }
-    tok->tid = -1;
+    DeleteCriticalSection(&mutex->cs);
+#else
+    (void) mutex;
 #endif
-    return (tok);
 }
 
 /**
  * xmlFreeMutex:
  * @tok:  the simple mutex
  *
- * xmlFreeMutex() is used to reclaim resources associated with a libxml2 token
- * struct.
+ * Free a mutex.
  */
 void
 xmlFreeMutex(xmlMutexPtr tok)
@@ -199,14 +188,7 @@ xmlFreeMutex(xmlMutexPtr tok)
     if (tok == NULL)
         return;
 
-#ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded != 0)
-        pthread_mutex_destroy(&tok->lock);
-#elif defined HAVE_WIN32_THREADS
-    DeleteCriticalSection(&tok->cs);
-#elif defined HAVE_BEOS_THREADS
-    delete_sem(tok->sem);
-#endif
+    xmlCleanupMutex(tok);
     free(tok);
 }
 
@@ -221,19 +203,15 @@ xmlMutexLock(xmlMutexPtr tok)
 {
     if (tok == NULL)
         return;
-#ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded != 0)
+#ifdef HAVE_POSIX_THREADS
+    /*
+     * This assumes that __libc_single_threaded won't change while the
+     * lock is held.
+     */
+    if (XML_IS_THREADED() != 0)
         pthread_mutex_lock(&tok->lock);
 #elif defined HAVE_WIN32_THREADS
     EnterCriticalSection(&tok->cs);
-#elif defined HAVE_BEOS_THREADS
-    if (acquire_sem(tok->sem) != B_NO_ERROR) {
-#ifdef DEBUG_THREADS
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlMutexLock():BeOS:Couldn't acquire semaphore\n");
-#endif
-    }
-    tok->tid = find_thread(NULL);
 #endif
 
 }
@@ -249,16 +227,11 @@ xmlMutexUnlock(xmlMutexPtr tok)
 {
     if (tok == NULL)
         return;
-#ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded != 0)
+#ifdef HAVE_POSIX_THREADS
+    if (XML_IS_THREADED() != 0)
         pthread_mutex_unlock(&tok->lock);
 #elif defined HAVE_WIN32_THREADS
     LeaveCriticalSection(&tok->cs);
-#elif defined HAVE_BEOS_THREADS
-    if (tok->tid == find_thread(NULL)) {
-        tok->tid = -1;
-        release_sem(tok->sem);
-    }
 #endif
 }
 
@@ -279,8 +252,8 @@ xmlNewRMutex(void)
 
     if ((tok = malloc(sizeof(xmlRMutex))) == NULL)
         return (NULL);
-#ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded != 0) {
+#ifdef HAVE_POSIX_THREADS
+    if (XML_IS_NEVER_THREADED() == 0) {
         pthread_mutex_init(&tok->lock, NULL);
         tok->held = 0;
         tok->waiters = 0;
@@ -288,12 +261,6 @@ xmlNewRMutex(void)
     }
 #elif defined HAVE_WIN32_THREADS
     InitializeCriticalSection(&tok->cs);
-#elif defined HAVE_BEOS_THREADS
-    if ((tok->lock = xmlNewMutex()) == NULL) {
-        free(tok);
-        return NULL;
-    }
-    tok->count = 0;
 #endif
     return (tok);
 }
@@ -310,15 +277,13 @@ xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
 {
     if (tok == NULL)
         return;
-#ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded != 0) {
+#ifdef HAVE_POSIX_THREADS
+    if (XML_IS_NEVER_THREADED() == 0) {
         pthread_mutex_destroy(&tok->lock);
         pthread_cond_destroy(&tok->cv);
     }
 #elif defined HAVE_WIN32_THREADS
     DeleteCriticalSection(&tok->cs);
-#elif defined HAVE_BEOS_THREADS
-    xmlFreeMutex(tok->lock);
 #endif
     free(tok);
 }
@@ -334,8 +299,8 @@ xmlRMutexLock(xmlRMutexPtr tok)
 {
     if (tok == NULL)
         return;
-#ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded == 0)
+#ifdef HAVE_POSIX_THREADS
+    if (XML_IS_THREADED() == 0)
         return;
 
     pthread_mutex_lock(&tok->lock);
@@ -356,14 +321,6 @@ xmlRMutexLock(xmlRMutexPtr tok)
     pthread_mutex_unlock(&tok->lock);
 #elif defined HAVE_WIN32_THREADS
     EnterCriticalSection(&tok->cs);
-#elif defined HAVE_BEOS_THREADS
-    if (tok->lock->tid == find_thread(NULL)) {
-        tok->count++;
-        return;
-    } else {
-        xmlMutexLock(tok->lock);
-        tok->count = 1;
-    }
 #endif
 }
 
@@ -378,8 +335,8 @@ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
 {
     if (tok == NULL)
         return;
-#ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded == 0)
+#ifdef HAVE_POSIX_THREADS
+    if (XML_IS_THREADED() == 0)
         return;
 
     pthread_mutex_lock(&tok->lock);
@@ -392,342 +349,6 @@ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
     pthread_mutex_unlock(&tok->lock);
 #elif defined HAVE_WIN32_THREADS
     LeaveCriticalSection(&tok->cs);
-#elif defined HAVE_BEOS_THREADS
-    if (tok->lock->tid == find_thread(NULL)) {
-        tok->count--;
-        if (tok->count == 0) {
-            xmlMutexUnlock(tok->lock);
-        }
-        return;
-    }
-#endif
-}
-
-/**
- * xmlGlobalInitMutexLock
- *
- * Makes sure that the global initialization mutex is initialized and
- * locks it.
- */
-void
-__xmlGlobalInitMutexLock(void)
-{
-    /* Make sure the global init lock is initialized and then lock it. */
-#ifdef HAVE_PTHREAD_H
-    /* The mutex is statically initialized, so we just lock it. */
-#ifdef XML_PTHREAD_WEAK
-    if (&pthread_mutex_lock == NULL)
-        return;
-#endif /* XML_PTHREAD_WEAK */
-    pthread_mutex_lock(&global_init_lock);
-#elif defined HAVE_WIN32_THREADS
-    LPCRITICAL_SECTION cs;
-
-    /* Create a new critical section */
-    if (global_init_lock == NULL) {
-        cs = malloc(sizeof(CRITICAL_SECTION));
-        if (cs == NULL) {
-            xmlGenericError(xmlGenericErrorContext,
-                            "xmlGlobalInitMutexLock: out of memory\n");
-            return;
-        }
-        InitializeCriticalSection(cs);
-
-        /* Swap it into the global_init_lock */
-#ifdef InterlockedCompareExchangePointer
-        InterlockedCompareExchangePointer((void **) &global_init_lock,
-                                          cs, NULL);
-#else /* Use older void* version */
-        InterlockedCompareExchange((void **) &global_init_lock,
-                                   (void *) cs, NULL);
-#endif /* InterlockedCompareExchangePointer */
-
-        /* If another thread successfully recorded its critical
-         * section in the global_init_lock then discard the one
-         * allocated by this thread. */
-        if (global_init_lock != cs) {
-            DeleteCriticalSection(cs);
-            free(cs);
-        }
-    }
-
-    /* Lock the chosen critical section */
-    EnterCriticalSection(global_init_lock);
-#elif defined HAVE_BEOS_THREADS
-    int32 sem;
-
-    /* Allocate a new semaphore */
-    sem = create_sem(1, "xmlGlobalinitMutex");
-
-    while (global_init_lock == -1) {
-        if (atomic_add(&global_init_count, 1) == 0) {
-            global_init_lock = sem;
-        } else {
-            snooze(1);
-            atomic_add(&global_init_count, -1);
-        }
-    }
-
-    /* If another thread successfully recorded its critical
-     * section in the global_init_lock then discard the one
-     * allocated by this thread. */
-    if (global_init_lock != sem)
-        delete_sem(sem);
-
-    /* Acquire the chosen semaphore */
-    if (acquire_sem(global_init_lock) != B_NO_ERROR) {
-#ifdef DEBUG_THREADS
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlGlobalInitMutexLock():BeOS:Couldn't acquire semaphore\n");
-#endif
-    }
-#endif
-}
-
-void
-__xmlGlobalInitMutexUnlock(void)
-{
-#ifdef HAVE_PTHREAD_H
-#ifdef XML_PTHREAD_WEAK
-    if (&pthread_mutex_unlock == NULL)
-        return;
-#endif /* XML_PTHREAD_WEAK */
-    pthread_mutex_unlock(&global_init_lock);
-#elif defined HAVE_WIN32_THREADS
-    if (global_init_lock != NULL) {
-	LeaveCriticalSection(global_init_lock);
-    }
-#elif defined HAVE_BEOS_THREADS
-    release_sem(global_init_lock);
-#endif
-}
-
-/**
- * xmlGlobalInitMutexDestroy
- *
- * Makes sure that the global initialization mutex is destroyed before
- * application termination.
- */
-void
-__xmlGlobalInitMutexDestroy(void)
-{
-#ifdef HAVE_PTHREAD_H
-#elif defined HAVE_WIN32_THREADS
-    if (global_init_lock != NULL) {
-        DeleteCriticalSection(global_init_lock);
-        free(global_init_lock);
-        global_init_lock = NULL;
-    }
-#endif
-}
-
-/************************************************************************
- *									*
- *			Per thread global state handling		*
- *									*
- ************************************************************************/
-
-#ifdef LIBXML_THREAD_ENABLED
-#ifdef xmlLastError
-#undef xmlLastError
-#endif
-
-/**
- * xmlFreeGlobalState:
- * @state:  a thread global state
- *
- * xmlFreeGlobalState() is called when a thread terminates with a non-NULL
- * global state. It is is used here to reclaim memory resources.
- */
-static void
-xmlFreeGlobalState(void *state)
-{
-    xmlGlobalState *gs = (xmlGlobalState *) state;
-
-    /* free any memory allocated in the thread's xmlLastError */
-    xmlResetError(&(gs->xmlLastError));
-    free(state);
-}
-
-/**
- * xmlNewGlobalState:
- *
- * xmlNewGlobalState() allocates a global state. This structure is used to
- * hold all data for use by a thread when supporting backwards compatibility
- * of libxml2 to pre-thread-safe behaviour.
- *
- * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
- */
-static xmlGlobalStatePtr
-xmlNewGlobalState(void)
-{
-    xmlGlobalState *gs;
-
-    gs = malloc(sizeof(xmlGlobalState));
-    if (gs == NULL) {
-	xmlGenericError(xmlGenericErrorContext,
-			"xmlGetGlobalState: out of memory\n");
-        return (NULL);
-    }
-
-    memset(gs, 0, sizeof(xmlGlobalState));
-    xmlInitializeGlobalState(gs);
-    return (gs);
-}
-#endif /* LIBXML_THREAD_ENABLED */
-
-#ifdef HAVE_PTHREAD_H
-#elif defined HAVE_WIN32_THREADS
-#if !defined(HAVE_COMPILER_TLS)
-#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
-typedef struct _xmlGlobalStateCleanupHelperParams {
-    HANDLE thread;
-    void *memory;
-} xmlGlobalStateCleanupHelperParams;
-
-static void XMLCDECL
-xmlGlobalStateCleanupHelper(void *p)
-{
-    xmlGlobalStateCleanupHelperParams *params =
-        (xmlGlobalStateCleanupHelperParams *) p;
-    WaitForSingleObject(params->thread, INFINITE);
-    CloseHandle(params->thread);
-    xmlFreeGlobalState(params->memory);
-    free(params);
-    _endthread();
-}
-#else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */
-
-typedef struct _xmlGlobalStateCleanupHelperParams {
-    void *memory;
-    struct _xmlGlobalStateCleanupHelperParams *prev;
-    struct _xmlGlobalStateCleanupHelperParams *next;
-} xmlGlobalStateCleanupHelperParams;
-
-static xmlGlobalStateCleanupHelperParams *cleanup_helpers_head = NULL;
-static CRITICAL_SECTION cleanup_helpers_cs;
-
-#endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */
-#endif /* HAVE_COMPILER_TLS */
-#endif /* HAVE_WIN32_THREADS */
-
-#if defined HAVE_BEOS_THREADS
-
-/**
- * xmlGlobalStateCleanup:
- * @data: unused parameter
- *
- * Used for Beos only
- */
-void
-xmlGlobalStateCleanup(void *data)
-{
-    void *globalval = tls_get(globalkey);
-
-    if (globalval != NULL)
-        xmlFreeGlobalState(globalval);
-}
-#endif
-
-/**
- * xmlGetGlobalState:
- *
- * xmlGetGlobalState() is called to retrieve the global state for a thread.
- *
- * Returns the thread global state or NULL in case of error
- */
-xmlGlobalStatePtr
-xmlGetGlobalState(void)
-{
-#ifdef HAVE_PTHREAD_H
-    xmlGlobalState *globalval;
-
-    if (libxml_is_threaded == 0)
-        return (NULL);
-
-    pthread_once(&once_control, xmlOnceInit);
-
-    if ((globalval = (xmlGlobalState *)
-         pthread_getspecific(globalkey)) == NULL) {
-        xmlGlobalState *tsd = xmlNewGlobalState();
-	if (tsd == NULL)
-	    return(NULL);
-
-        pthread_setspecific(globalkey, tsd);
-        return (tsd);
-    }
-    return (globalval);
-#elif defined HAVE_WIN32_THREADS
-#if defined(HAVE_COMPILER_TLS)
-    if (!tlstate_inited) {
-        tlstate_inited = 1;
-        xmlInitializeGlobalState(&tlstate);
-    }
-    return &tlstate;
-#else /* HAVE_COMPILER_TLS */
-    xmlGlobalState *globalval;
-    xmlGlobalStateCleanupHelperParams *p;
-
-    xmlOnceInit();
-#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
-    globalval = (xmlGlobalState *) TlsGetValue(globalkey);
-#else
-    p = (xmlGlobalStateCleanupHelperParams *) TlsGetValue(globalkey);
-    globalval = (xmlGlobalState *) (p ? p->memory : NULL);
-#endif
-    if (globalval == NULL) {
-        xmlGlobalState *tsd = xmlNewGlobalState();
-
-        if (tsd == NULL)
-	    return(NULL);
-        p = (xmlGlobalStateCleanupHelperParams *)
-            malloc(sizeof(xmlGlobalStateCleanupHelperParams));
-	if (p == NULL) {
-            xmlGenericError(xmlGenericErrorContext,
-                            "xmlGetGlobalState: out of memory\n");
-            xmlFreeGlobalState(tsd);
-	    return(NULL);
-	}
-        p->memory = tsd;
-#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
-        DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
-                        GetCurrentProcess(), &p->thread, 0, TRUE,
-                        DUPLICATE_SAME_ACCESS);
-        TlsSetValue(globalkey, tsd);
-        _beginthread(xmlGlobalStateCleanupHelper, 0, p);
-#else
-        EnterCriticalSection(&cleanup_helpers_cs);
-        if (cleanup_helpers_head != NULL) {
-            cleanup_helpers_head->prev = p;
-        }
-        p->next = cleanup_helpers_head;
-        p->prev = NULL;
-        cleanup_helpers_head = p;
-        TlsSetValue(globalkey, p);
-        LeaveCriticalSection(&cleanup_helpers_cs);
-#endif
-
-        return (tsd);
-    }
-    return (globalval);
-#endif /* HAVE_COMPILER_TLS */
-#elif defined HAVE_BEOS_THREADS
-    xmlGlobalState *globalval;
-
-    xmlOnceInit();
-
-    if ((globalval = (xmlGlobalState *) tls_get(globalkey)) == NULL) {
-        xmlGlobalState *tsd = xmlNewGlobalState();
-	if (tsd == NULL)
-	    return (NULL);
-
-        tls_set(globalkey, tsd);
-        on_exit_thread(xmlGlobalStateCleanup, NULL);
-        return (tsd);
-    }
-    return (globalval);
-#else
-    return (NULL);
 #endif
 }
 
@@ -740,6 +361,8 @@ xmlGetGlobalState(void)
 /**
  * xmlGetThreadId:
  *
+ * DEPRECATED: Internal function, do not use.
+ *
  * xmlGetThreadId() find the current thread ID number
  * Note that this is likely to be broken on some platforms using pthreads
  * as the specification doesn't mandate pthread_t to be an integer type
@@ -749,11 +372,11 @@ xmlGetGlobalState(void)
 int
 xmlGetThreadId(void)
 {
-#ifdef HAVE_PTHREAD_H
+#ifdef HAVE_POSIX_THREADS
     pthread_t id;
     int ret;
 
-    if (libxml_is_threaded == 0)
+    if (XML_IS_THREADED() == 0)
         return (0);
     id = pthread_self();
     /* horrible but preserves compat, see warning above */
@@ -761,49 +384,11 @@ xmlGetThreadId(void)
     return (ret);
 #elif defined HAVE_WIN32_THREADS
     return GetCurrentThreadId();
-#elif defined HAVE_BEOS_THREADS
-    return find_thread(NULL);
 #else
     return ((int) 0);
 #endif
 }
 
-/**
- * xmlIsMainThread:
- *
- * xmlIsMainThread() check whether the current thread is the main thread.
- *
- * Returns 1 if the current thread is the main thread, 0 otherwise
- */
-int
-xmlIsMainThread(void)
-{
-#ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded == -1)
-        xmlInitThreads();
-    if (libxml_is_threaded == 0)
-        return (1);
-    pthread_once(&once_control, xmlOnceInit);
-#elif defined HAVE_WIN32_THREADS
-    xmlOnceInit();
-#elif defined HAVE_BEOS_THREADS
-    xmlOnceInit();
-#endif
-
-#ifdef DEBUG_THREADS
-    xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n");
-#endif
-#ifdef HAVE_PTHREAD_H
-    return (pthread_equal(mainthread,pthread_self()));
-#elif defined HAVE_WIN32_THREADS
-    return (mainthread == GetCurrentThreadId());
-#elif defined HAVE_BEOS_THREADS
-    return (mainthread == find_thread(NULL));
-#else
-    return (1);
-#endif
-}
-
 /**
  * xmlLockLibrary:
  *
@@ -813,9 +398,6 @@ xmlIsMainThread(void)
 void
 xmlLockLibrary(void)
 {
-#ifdef DEBUG_THREADS
-    xmlGenericError(xmlGenericErrorContext, "xmlLockLibrary()\n");
-#endif
     xmlRMutexLock(xmlLibraryLock);
 }
 
@@ -828,32 +410,67 @@ xmlLockLibrary(void)
 void
 xmlUnlockLibrary(void)
 {
-#ifdef DEBUG_THREADS
-    xmlGenericError(xmlGenericErrorContext, "xmlUnlockLibrary()\n");
-#endif
     xmlRMutexUnlock(xmlLibraryLock);
 }
 
 /**
  * xmlInitThreads:
  *
- * DEPRECATED: This function will be made private. Call xmlInitParser to
- * initialize the library.
- *
- * xmlInitThreads() is used to to initialize all the thread related
- * data of the libxml2 library.
+ * DEPRECATED: Alias for xmlInitParser.
  */
 void
 xmlInitThreads(void)
 {
-#ifdef HAVE_PTHREAD_H
+    xmlInitParser();
+}
+
+/**
+ * xmlCleanupThreads:
+ *
+ * DEPRECATED: This function is a no-op. Call xmlCleanupParser
+ * to free global state but see the warnings there. xmlCleanupParser
+ * should be only called once at program exit. In most cases, you don't
+ * have call cleanup functions at all.
+ */
+void
+xmlCleanupThreads(void)
+{
+}
+
+/************************************************************************
+ *									*
+ *			Library wide initialization			*
+ *									*
+ ************************************************************************/
+
+static int xmlParserInitialized = 0;
+static int xmlParserInnerInitialized = 0;
+
+
+#ifdef HAVE_POSIX_THREADS
+static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
+#elif defined HAVE_WIN32_THREADS
+static volatile LPCRITICAL_SECTION global_init_lock = NULL;
+#endif
+
+/**
+ * xmlGlobalInitMutexLock
+ *
+ * Makes sure that the global initialization mutex is initialized and
+ * locks it.
+ */
+static void
+xmlGlobalInitMutexLock(void) {
+#ifdef HAVE_POSIX_THREADS
+
 #ifdef XML_PTHREAD_WEAK
-    if (libxml_is_threaded == -1) {
-        if ((&pthread_once != NULL) &&
-            (&pthread_getspecific != NULL) &&
-            (&pthread_setspecific != NULL) &&
-            (&pthread_key_create != NULL) &&
-            (&pthread_key_delete != NULL) &&
+    /*
+     * This is somewhat unreliable since libpthread could be loaded
+     * later with dlopen() and threads could be created. But it's
+     * long-standing behavior and hard to work around.
+     */
+    if (libxml_is_threaded == -1)
+        libxml_is_threaded =
             (&pthread_mutex_init != NULL) &&
             (&pthread_mutex_destroy != NULL) &&
             (&pthread_mutex_lock != NULL) &&
@@ -861,189 +478,196 @@ xmlInitThreads(void)
             (&pthread_cond_init != NULL) &&
             (&pthread_cond_destroy != NULL) &&
             (&pthread_cond_wait != NULL) &&
-            (&pthread_equal != NULL) &&
+            /*
+             * pthread_equal can be inline, resuting in -Waddress warnings.
+             * Let's assume it's available if all the other functions are.
+             */
+            /* (pthread_equal != NULL) && */
             (&pthread_self != NULL) &&
-            (&pthread_cond_signal != NULL)) {
-            libxml_is_threaded = 1;
+            (&pthread_cond_signal != NULL);
+#endif
 
-/* fprintf(stderr, "Running multithreaded\n"); */
-        } else {
+    /* The mutex is statically initialized, so we just lock it. */
+    if (XML_IS_THREADED() != 0)
+        pthread_mutex_lock(&global_init_lock);
+
+#elif defined HAVE_WIN32_THREADS
+
+    LPCRITICAL_SECTION cs;
+
+    /* Create a new critical section */
+    if (global_init_lock == NULL) {
+        cs = malloc(sizeof(CRITICAL_SECTION));
+        if (cs == NULL) {
+            fprintf(stderr, "libxml2: xmlInitParser: out of memory\n");
+            abort();
+        }
+        InitializeCriticalSection(cs);
 
-/* fprintf(stderr, "Running without multithread\n"); */
-            libxml_is_threaded = 0;
+        /* Swap it into the global_init_lock */
+#ifdef InterlockedCompareExchangePointer
+        InterlockedCompareExchangePointer((void **) &global_init_lock,
+                                          cs, NULL);
+#else /* Use older void* version */
+        InterlockedCompareExchange((void **) &global_init_lock,
+                                   (void *) cs, NULL);
+#endif /* InterlockedCompareExchangePointer */
+
+        /* If another thread successfully recorded its critical
+         * section in the global_init_lock then discard the one
+         * allocated by this thread. */
+        if (global_init_lock != cs) {
+            DeleteCriticalSection(cs);
+            free(cs);
         }
     }
-#endif /* XML_PTHREAD_WEAK */
+
+    /* Lock the chosen critical section */
+    EnterCriticalSection(global_init_lock);
+
+#endif
+}
+
+static void
+xmlGlobalInitMutexUnlock(void) {
+#ifdef HAVE_POSIX_THREADS
+    if (XML_IS_THREADED() != 0)
+        pthread_mutex_unlock(&global_init_lock);
+#elif defined HAVE_WIN32_THREADS
+    if (global_init_lock != NULL)
+	LeaveCriticalSection(global_init_lock);
 #endif
 }
 
 /**
- * xmlCleanupThreads:
- *
- * DEPRECATED: This function will be made private. Call xmlCleanupParser
- * to free global state but see the warnings there. xmlCleanupParser
- * should be only called once at program exit. In most cases, you don't
- * have call cleanup functions at all.
- *
- * xmlCleanupThreads() is used to to cleanup all the thread related
- * data of the libxml2 library once processing has ended.
+ * xmlGlobalInitMutexDestroy
  *
- * WARNING: if your application is multithreaded or has plugin support
- *          calling this may crash the application if another thread or
- *          a plugin is still using libxml2. It's sometimes very hard to
- *          guess if libxml2 is in use in the application, some libraries
- *          or plugins may use it without notice. In case of doubt abstain
- *          from calling this function or do it just before calling exit()
- *          to avoid leak reports from valgrind !
+ * Makes sure that the global initialization mutex is destroyed before
+ * application termination.
  */
-void
-xmlCleanupThreads(void)
-{
-#ifdef DEBUG_THREADS
-    xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n");
-#endif
-#ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded != 0)
-        pthread_key_delete(globalkey);
-    once_control = once_control_init;
-#elif defined(HAVE_WIN32_THREADS)
-#if !defined(HAVE_COMPILER_TLS)
-    if (globalkey != TLS_OUT_OF_INDEXES) {
-#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
-        xmlGlobalStateCleanupHelperParams *p;
-
-        EnterCriticalSection(&cleanup_helpers_cs);
-        p = cleanup_helpers_head;
-        while (p != NULL) {
-            xmlGlobalStateCleanupHelperParams *temp = p;
-
-            p = p->next;
-            xmlFreeGlobalState(temp->memory);
-            free(temp);
-        }
-        cleanup_helpers_head = 0;
-        LeaveCriticalSection(&cleanup_helpers_cs);
-#endif
-        TlsFree(globalkey);
-        globalkey = TLS_OUT_OF_INDEXES;
+static void
+xmlGlobalInitMutexDestroy(void) {
+#ifdef HAVE_POSIX_THREADS
+#elif defined HAVE_WIN32_THREADS
+    if (global_init_lock != NULL) {
+        DeleteCriticalSection(global_init_lock);
+        free(global_init_lock);
+        global_init_lock = NULL;
     }
-#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
-    DeleteCriticalSection(&cleanup_helpers_cs);
-#endif
-#endif
-    run_once.done = 0;
-    run_once.control = 0;
 #endif
 }
 
-#ifdef LIBXML_THREAD_ENABLED
-
 /**
- * xmlOnceInit
+ * xmlInitParser:
  *
- * xmlOnceInit() is used to initialize the value of mainthread for use
- * in other routines. This function should only be called using
- * pthread_once() in association with the once_control variable to ensure
- * that the function is only called once. See man pthread_once for more
- * details.
+ * Initialization function for the XML parser.
+ *
+ * Call once from the main thread before using the library in
+ * multithreaded programs.
  */
-static void
-xmlOnceInit(void)
-{
-#ifdef HAVE_PTHREAD_H
-    (void) pthread_key_create(&globalkey, xmlFreeGlobalState);
-    mainthread = pthread_self();
-    __xmlInitializeDict();
-#elif defined(HAVE_WIN32_THREADS)
-    if (!run_once.done) {
-        if (InterlockedIncrement(&run_once.control) == 1) {
-#if !defined(HAVE_COMPILER_TLS)
-#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
-            InitializeCriticalSection(&cleanup_helpers_cs);
+void
+xmlInitParser(void) {
+    /*
+     * Note that the initialization code must not make memory allocations.
+     */
+    if (xmlParserInitialized != 0)
+        return;
+
+    xmlGlobalInitMutexLock();
+
+    if (xmlParserInnerInitialized == 0) {
+#if defined(_WIN32) && \
+    !defined(LIBXML_THREAD_ALLOC_ENABLED) && \
+    (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+        if (xmlFree == free)
+            atexit(xmlCleanupParser);
 #endif
-            globalkey = TlsAlloc();
+
+        xmlInitRandom(); /* Required by xmlInitGlobalsInternal */
+        xmlInitMemoryInternal();
+        xmlInitGlobalsInternal();
+        xmlInitDictInternal();
+        xmlInitEncodingInternal();
+#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
+        xmlInitXPathInternal();
 #endif
-            mainthread = GetCurrentThreadId();
-	    __xmlInitializeDict();
-            run_once.done = 1;
-        } else {
-            /* Another thread is working; give up our slice and
-             * wait until they're done. */
-            while (!run_once.done)
-                Sleep(0);
-        }
+        xmlInitIOCallbacks();
+
+        xmlParserInnerInitialized = 1;
     }
-#elif defined HAVE_BEOS_THREADS
-    if (atomic_add(&run_once_init, 1) == 0) {
-        globalkey = tls_allocate();
-        tls_set(globalkey, NULL);
-        mainthread = find_thread(NULL);
-	__xmlInitializeDict();
-    } else
-        atomic_add(&run_once_init, -1);
-#endif
+
+    xmlGlobalInitMutexUnlock();
+
+    xmlParserInitialized = 1;
 }
-#endif
 
 /**
- * DllMain:
- * @hinstDLL: handle to DLL instance
- * @fdwReason: Reason code for entry
- * @lpvReserved: generic pointer (depends upon reason code)
+ * xmlCleanupParser:
+ *
+ * This function name is somewhat misleading. It does not clean up
+ * parser state, it cleans up memory allocated by the library itself.
+ * It is a cleanup function for the XML library. It tries to reclaim all
+ * related global memory allocated for the library processing.
+ * It doesn't deallocate any document related memory. One should
+ * call xmlCleanupParser() only when the process has finished using
+ * the library and all XML/HTML documents built with it.
+ * See also xmlInitParser() which has the opposite function of preparing
+ * the library for operations.
  *
- * Entry point for Windows library. It is being used to free thread-specific
- * storage.
- *
- * Returns TRUE always
+ * WARNING: if your application is multithreaded or has plugin support
+ *          calling this may crash the application if another thread or
+ *          a plugin is still using libxml2. It's sometimes very hard to
+ *          guess if libxml2 is in use in the application, some libraries
+ *          or plugins may use it without notice. In case of doubt abstain
+ *          from calling this function or do it just before calling exit()
+ *          to avoid leak reports from valgrind !
  */
-#ifdef HAVE_PTHREAD_H
-#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
-#if defined(LIBXML_STATIC_FOR_DLL)
-int XMLCALL
-xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
-           ATTRIBUTE_UNUSED void *lpvReserved)
-#else
-/* declare to avoid "no previous prototype for 'DllMain'" warning */
-/* Note that we do NOT want to include this function declaration in
-   a public header because it's meant to be called by Windows itself,
-   not a program that uses this library.  This also has to be exported. */
-
-XMLPUBFUN BOOL WINAPI
-DllMain (HINSTANCE hinstDLL,
-         DWORD     fdwReason,
-         LPVOID    lpvReserved);
-
-BOOL WINAPI
-DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
-        ATTRIBUTE_UNUSED LPVOID lpvReserved)
+void
+xmlCleanupParser(void) {
+    if (!xmlParserInitialized)
+        return;
+
+    /* These functions can call xmlFree. */
+
+    xmlCleanupCharEncodingHandlers();
+#ifdef LIBXML_CATALOG_ENABLED
+    xmlCatalogCleanup();
 #endif
-{
-    switch (fdwReason) {
-        case DLL_THREAD_DETACH:
-            if (globalkey != TLS_OUT_OF_INDEXES) {
-                xmlGlobalState *globalval = NULL;
-                xmlGlobalStateCleanupHelperParams *p =
-                    (xmlGlobalStateCleanupHelperParams *)
-                    TlsGetValue(globalkey);
-                globalval = (xmlGlobalState *) (p ? p->memory : NULL);
-                if (globalval) {
-                    xmlFreeGlobalState(globalval);
-                    TlsSetValue(globalkey, NULL);
-                }
-                if (p) {
-                    EnterCriticalSection(&cleanup_helpers_cs);
-                    if (p == cleanup_helpers_head)
-                        cleanup_helpers_head = p->next;
-                    else
-                        p->prev->next = p->next;
-                    if (p->next != NULL)
-                        p->next->prev = p->prev;
-                    LeaveCriticalSection(&cleanup_helpers_cs);
-                    free(p);
-                }
-            }
-            break;
-    }
-    return TRUE;
+#ifdef LIBXML_SCHEMAS_ENABLED
+    xmlSchemaCleanupTypes();
+    xmlRelaxNGCleanupTypes();
+#endif
+
+    /* These functions should never call xmlFree. */
+
+    xmlCleanupDictInternal();
+    xmlCleanupRandom();
+    xmlCleanupGlobalsInternal();
+    /*
+     * Must come last. On Windows, xmlCleanupGlobalsInternal can call
+     * xmlFree which uses xmlMemMutex in debug mode.
+     */
+    xmlCleanupMemoryInternal();
+
+    xmlGlobalInitMutexDestroy();
+
+    xmlParserInitialized = 0;
+    xmlParserInnerInitialized = 0;
+}
+
+#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && \
+    !defined(LIBXML_THREAD_ALLOC_ENABLED) && \
+    !defined(LIBXML_STATIC) && \
+    !defined(_WIN32)
+static void
+ATTRIBUTE_DESTRUCTOR
+xmlDestructor(void) {
+    /*
+     * Calling custom deallocation functions in a destructor can cause
+     * problems, for example with Nokogiri.
+     */
+    if (xmlFree == free)
+        xmlCleanupParser();
 }
 #endif
+
diff --git a/tree.c b/tree.c
index df27aa11abab5d7d6ffcb421147c0e8ee9cd8ff6..53eae8e3b46078a5052e2c8b9f9f89708f6508f0 100644
--- a/tree.c
+++ b/tree.c
@@ -28,15 +28,13 @@
 #include <vtk_zlib.h>
 #endif
 
-#include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/uri.h>
 #include <libxml/entities.h>
-#include <libxml/valid.h>
 #include <libxml/xmlerror.h>
 #include <libxml/parserInternals.h>
-#include <libxml/globals.h>
 #ifdef LIBXML_HTML_ENABLED
 #include <libxml/HTMLtree.h>
 #endif
@@ -44,8 +42,10 @@
 #include <libxml/debugXML.h>
 #endif
 
-#include "buf.h"
-#include "save.h"
+#include "private/buf.h"
+#include "private/entities.h"
+#include "private/error.h"
+#include "private/tree.h"
 
 int __xmlRegisterCallbacks = 0;
 
@@ -55,58 +55,23 @@ int __xmlRegisterCallbacks = 0;
  *									*
  ************************************************************************/
 
+static xmlNodePtr
+xmlNewEntityRef(xmlDocPtr doc, xmlChar *name);
+
 static xmlNsPtr
-xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns);
+xmlNewReconciledNs(xmlNodePtr tree, xmlNsPtr ns);
+
+static xmlAttrPtr
+xmlGetPropNodeInternal(const xmlNode *node, const xmlChar *name,
+		       const xmlChar *nsName, int useDTD);
 
 static xmlChar* xmlGetPropNodeValueInternal(const xmlAttr *prop);
 
-/************************************************************************
- *									*
- *		Tree memory error handler				*
- *									*
- ************************************************************************/
-/**
- * xmlTreeErrMemory:
- * @extra:  extra information
- *
- * Handle an out of memory condition
- */
 static void
-xmlTreeErrMemory(const char *extra)
-{
-    __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra);
-}
+xmlBufGetChildContent(xmlBufPtr buf, const xmlNode *tree);
 
-/**
- * xmlTreeErr:
- * @code:  the error number
- * @extra:  extra information
- *
- * Handle an out of memory condition
- */
 static void
-xmlTreeErr(int code, xmlNodePtr node, const char *extra)
-{
-    const char *msg = NULL;
-
-    switch(code) {
-        case XML_TREE_INVALID_HEX:
-	    msg = "invalid hexadecimal character value\n";
-	    break;
-	case XML_TREE_INVALID_DEC:
-	    msg = "invalid decimal character value\n";
-	    break;
-	case XML_TREE_UNTERMINATED_ENTITY:
-	    msg = "unterminated entity reference %15s\n";
-	    break;
-	case XML_TREE_NOT_UTF8:
-	    msg = "string is not in UTF-8\n";
-	    break;
-	default:
-	    msg = "unexpected error number\n";
-    }
-    __xmlSimpleError(XML_FROM_TREE, code, node, msg, extra);
-}
+xmlUnlinkNodeInternal(xmlNodePtr cur);
 
 /************************************************************************
  *									*
@@ -122,27 +87,10 @@ const xmlChar xmlStringTextNoenc[] =
 const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
 
 static int xmlCompressMode = 0;
-static int xmlCheckDTD = 1;
-
-#define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) {		\
-    xmlNodePtr ulccur = (n)->children;					\
-    if (ulccur == NULL) {						\
-        (n)->last = NULL;						\
-    } else {								\
-        while (ulccur->next != NULL) {					\
-		ulccur->parent = (n);					\
-		ulccur = ulccur->next;					\
-	}								\
-	ulccur->parent = (n);						\
-	(n)->last = ulccur;						\
-}}
 
 #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
   (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
 
-/* #define DEBUG_BUFFER */
-/* #define DEBUG_TREE */
-
 /************************************************************************
  *									*
  *		Functions to move to entities.c once the		*
@@ -225,15 +173,19 @@ xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix,
     if (ncname == NULL) return(NULL);
     if (prefix == NULL) return((xmlChar *) ncname);
 
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    /* Make allocation more likely */
+    if (len > 8)
+        len = 8;
+#endif
+
     lenn = strlen((char *) ncname);
     lenp = strlen((char *) prefix);
 
     if ((memory == NULL) || (len < lenn + lenp + 2)) {
 	ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
-	if (ret == NULL) {
-	    xmlTreeErrMemory("building QName");
+	if (ret == NULL)
 	    return(NULL);
-	}
     } else {
 	ret = memory;
     }
@@ -249,6 +201,8 @@ xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix,
  * @name:  the full QName
  * @prefix:  a xmlChar **
  *
+ * DEPRECATED: This function doesn't report malloc failures.
+ *
  * parse an XML qualified name string
  *
  * [NS 5] QName ::= (Prefix ':')? LocalPart
@@ -270,13 +224,6 @@ xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
     *prefix = NULL;
     if (name == NULL) return(NULL);
 
-#ifndef XML_XML_NAMESPACE
-    /* xml: prefix is not really a namespace */
-    if ((name[0] == 'x') && (name[1] == 'm') &&
-        (name[2] == 'l') && (name[3] == ':'))
-	return(NULL);
-#endif
-
     /* nasty but valid */
     if (name[0] == ':')
 	return(NULL);
@@ -288,17 +235,14 @@ xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
     while ((name[len] != 0) && (name[len] != ':'))
 	len++;
 
-    if (name[len] == 0)
+    if ((name[len] == 0) || (name[len+1] == 0))
 	return(NULL);
 
     *prefix = xmlStrndup(name, len);
-    if (*prefix == NULL) {
-	xmlTreeErrMemory("QName split");
+    if (*prefix == NULL)
 	return(NULL);
-    }
     ret = xmlStrdup(&name[len + 1]);
     if (ret == NULL) {
-	xmlTreeErrMemory("QName split");
 	if (*prefix != NULL) {
 	    xmlFree(*prefix);
 	    *prefix = NULL;
@@ -339,7 +283,7 @@ xmlSplitQName3(const xmlChar *name, int *len) {
     while ((name[l] != 0) && (name[l] != ':'))
 	l++;
 
-    if (name[l] == 0)
+    if ((name[l] == 0) || (name[l+1] == 0))
 	return(NULL);
 
     *len = l;
@@ -347,6 +291,53 @@ xmlSplitQName3(const xmlChar *name, int *len) {
     return(&name[l+1]);
 }
 
+/**
+ * xmlSplitQName4:
+ * @name:  the full QName
+ * @prefixPtr:  pointer to resulting prefix
+ *
+ * Parse a QName. The return value points to the start of the local
+ * name in the input string. If the QName has a prefix, it will be
+ * allocated and stored in @prefixPtr. This string must be freed by
+ * the caller. If there's no prefix, @prefixPtr is set to NULL.
+ *
+ * Returns the local name or NULL if a memory allocation failed.
+ */
+const xmlChar *
+xmlSplitQName4(const xmlChar *name, xmlChar **prefixPtr) {
+    xmlChar *prefix;
+    int l = 0;
+
+    if ((name == NULL) || (prefixPtr == NULL))
+        return(NULL);
+
+    *prefixPtr = NULL;
+
+    /* nasty but valid */
+    if (name[0] == ':')
+	return(name);
+
+    /*
+     * we are not trying to validate but just to cut, and yes it will
+     * work even if this is as set of UTF-8 encoded chars
+     */
+    while ((name[l] != 0) && (name[l] != ':'))
+	l++;
+
+    /*
+     * TODO: What about names with multiple colons?
+     */
+    if ((name[l] == 0) || (name[l+1] == 0))
+	return(name);
+
+    prefix = xmlStrndup(name, l);
+    if (prefix == NULL)
+        return(NULL);
+
+    *prefixPtr = prefix;
+    return(&name[l+1]);
+}
+
 /************************************************************************
  *									*
  *		Check Name, NCName and QName strings			*
@@ -355,7 +346,6 @@ xmlSplitQName3(const xmlChar *name, int *len) {
 
 #define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
 
-#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
 /**
  * xmlValidateNCName:
  * @value: the value to check
@@ -427,7 +417,6 @@ try_complex:
 
     return(0);
 }
-#endif
 
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
 /**
@@ -713,19 +702,21 @@ xmlGetBufferAllocationScheme(void) {
 
 /**
  * xmlNewNs:
- * @node:  the element carrying the namespace
+ * @node:  the element carrying the namespace (optional)
  * @href:  the URI associated
- * @prefix:  the prefix for the namespace
+ * @prefix:  the prefix for the namespace (optional)
  *
- * Creation of a new Namespace. This function will refuse to create
- * a namespace with a similar prefix than an existing one present on this
- * node.
- * Note that for a default namespace, @prefix should be NULL.
+ * Create a new namespace. For a default namespace, @prefix should be
+ * NULL. The namespace URI in @href is not checked. You should make sure
+ * to pass a valid URI.
  *
- * We use href==NULL in the case of an element creation where the namespace
- * was not defined.
+ * If @node is provided, it must be an element node. The namespace will
+ * be appended to the node's namespace declarations. It is an error if
+ * the node already has a definition for the prefix or default
+ * namespace.
  *
- * Returns a new namespace pointer or NULL
+ * Returns a new namespace pointer or NULL if arguments are invalid,
+ * the prefix is already in use or a memory allocation failed.
  */
 xmlNsPtr
 xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
@@ -734,35 +725,25 @@ xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
     if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
 	return(NULL);
 
-    if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
-        /* xml namespace is predefined, no need to add it */
-        if (xmlStrEqual(href, XML_XML_NAMESPACE))
-            return(NULL);
-
-        /*
-         * Problem, this is an attempt to bind xml prefix to a wrong
-         * namespace, which breaks
-         * Namespace constraint: Reserved Prefixes and Namespace Names
-         * from XML namespace. But documents authors may not care in
-         * their context so let's proceed.
-         */
-    }
-
     /*
      * Allocate a new Namespace and fill the fields.
      */
     cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building namespace");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlNs));
     cur->type = XML_LOCAL_NAMESPACE;
 
-    if (href != NULL)
+    if (href != NULL) {
 	cur->href = xmlStrdup(href);
-    if (prefix != NULL)
+        if (cur->href == NULL)
+            goto error;
+    }
+    if (prefix != NULL) {
 	cur->prefix = xmlStrdup(prefix);
+        if (cur->prefix == NULL)
+            goto error;
+    }
 
     /*
      * Add it at the end to preserve parsing order ...
@@ -774,39 +755,36 @@ xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
 	} else {
 	    xmlNsPtr prev = node->nsDef;
 
-	    if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
-		(xmlStrEqual(prev->prefix, cur->prefix))) {
-		xmlFreeNs(cur);
-		return(NULL);
-	    }
+	    if ((xmlStrEqual(prev->prefix, cur->prefix)) &&
+                (prev->href != NULL))
+                goto error;
 	    while (prev->next != NULL) {
 	        prev = prev->next;
-		if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
-		    (xmlStrEqual(prev->prefix, cur->prefix))) {
-		    xmlFreeNs(cur);
-		    return(NULL);
-		}
+		if ((xmlStrEqual(prev->prefix, cur->prefix)) &&
+                    (prev->href != NULL))
+                    goto error;
 	    }
 	    prev->next = cur;
 	}
     }
     return(cur);
+
+error:
+    xmlFreeNs(cur);
+    return(NULL);
 }
 
 /**
  * xmlSetNs:
  * @node:  a node in the document
- * @ns:  a namespace pointer
+ * @ns:  a namespace pointer (optional)
  *
- * Associate a namespace to a node, a posteriori.
+ * Set the namespace of an element or attribute node. Passing a NULL
+ * namespace unsets the namespace.
  */
 void
 xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
     if (node == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlSetNs: node == NULL\n");
-#endif
 	return;
     }
     if ((node->type == XML_ELEMENT_NODE) ||
@@ -818,15 +796,11 @@ xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
  * xmlFreeNs:
  * @cur:  the namespace pointer
  *
- * Free up the structures associated to a namespace
+ * Free an xmlNs object.
  */
 void
 xmlFreeNs(xmlNsPtr cur) {
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlFreeNs : ns == NULL\n");
-#endif
 	return;
     }
     if (cur->href != NULL) xmlFree((char *) cur->href);
@@ -838,16 +812,12 @@ xmlFreeNs(xmlNsPtr cur) {
  * xmlFreeNsList:
  * @cur:  the first namespace pointer
  *
- * Free up all the structures associated to the chained namespaces.
+ * Free a list of xmlNs objects.
  */
 void
 xmlFreeNsList(xmlNsPtr cur) {
     xmlNsPtr next;
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlFreeNsList : ns == NULL\n");
-#endif
 	return;
     }
     while (cur != NULL) {
@@ -859,15 +829,21 @@ xmlFreeNsList(xmlNsPtr cur) {
 
 /**
  * xmlNewDtd:
- * @doc:  the document pointer
- * @name:  the DTD name
- * @ExternalID:  the external ID
- * @SystemID:  the system ID
+ * @doc:  the document pointer (optional)
+ * @name:  the DTD name (optional)
+ * @ExternalID:  the external ID (optional)
+ * @SystemID:  the system ID (optional)
+ *
+ * Create a DTD node.
  *
- * Creation of a new DTD for the external subset. To create an
- * internal subset, use xmlCreateIntSubset().
+ * If a document is provided, it is an error if it already has an
+ * external subset. If the document has no external subset, it
+ * will be set to the created DTD.
  *
- * Returns a pointer to the new DTD structure
+ * To create an internal subset, use xmlCreateIntSubset().
+ *
+ * Returns a pointer to the new DTD object or NULL if arguments are
+ * invalid or a memory allocation failed.
  */
 xmlDtdPtr
 xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
@@ -875,12 +851,6 @@ xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
     xmlDtdPtr cur;
 
     if ((doc != NULL) && (doc->extSubset != NULL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewDtd(%s): document %s already have a DTD %s\n",
-	    /* !!! */ (char *) name, doc->name,
-	    /* !!! */ (char *)doc->extSubset->name);
-#endif
 	return(NULL);
     }
 
@@ -888,19 +858,26 @@ xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
      * Allocate a new DTD and fill the fields.
      */
     cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building DTD");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0 , sizeof(xmlDtd));
     cur->type = XML_DTD_NODE;
 
-    if (name != NULL)
+    if (name != NULL) {
 	cur->name = xmlStrdup(name);
-    if (ExternalID != NULL)
+        if (cur->name == NULL)
+            goto error;
+    }
+    if (ExternalID != NULL) {
 	cur->ExternalID = xmlStrdup(ExternalID);
-    if (SystemID != NULL)
+        if (cur->ExternalID == NULL)
+            goto error;
+    }
+    if (SystemID != NULL) {
 	cur->SystemID = xmlStrdup(SystemID);
+        if (cur->SystemID == NULL)
+            goto error;
+    }
     if (doc != NULL)
 	doc->extSubset = cur;
     cur->doc = doc;
@@ -908,16 +885,20 @@ xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
+
+error:
+    xmlFreeDtd(cur);
+    return(NULL);
 }
 
 /**
  * xmlGetIntSubset:
  * @doc:  the document pointer
  *
- * Get the internal subset of a document
- * Returns a pointer to the DTD structure or NULL if not found
+ * Get the internal subset of a document.
+ *
+ * Returns a pointer to the DTD object or NULL if not found.
  */
-
 xmlDtdPtr
 xmlGetIntSubset(const xmlDoc *doc) {
     xmlNodePtr cur;
@@ -935,69 +916,55 @@ xmlGetIntSubset(const xmlDoc *doc) {
 
 /**
  * xmlCreateIntSubset:
- * @doc:  the document pointer
- * @name:  the DTD name
- * @ExternalID:  the external (PUBLIC) ID
- * @SystemID:  the system ID
+ * @doc:  the document pointer (optional)
+ * @name:  the DTD name (optional)
+ * @ExternalID:  the external (PUBLIC) ID (optional)
+ * @SystemID:  the system ID (optional)
+ *
+ * Create a DTD node.
+ *
+ * If a document is provided and it already has an internal subset,
+ * the existing DTD object is returned without creating a new object.
+ * If the document has no internal subset, it will be set to the
+ * created DTD.
  *
- * Create the internal subset of a document
- * Returns a pointer to the new DTD structure
+ * Returns a pointer to the new or existing DTD object or NULL if
+ * arguments are invalid or a memory allocation failed.
  */
 xmlDtdPtr
 xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
                    const xmlChar *ExternalID, const xmlChar *SystemID) {
     xmlDtdPtr cur;
 
-    if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-
-     "xmlCreateIntSubset(): document %s already have an internal subset\n",
-	    doc->name);
-#endif
-	return(NULL);
+    if (doc != NULL) {
+        cur = xmlGetIntSubset(doc);
+        if (cur != NULL)
+            return(cur);
     }
 
     /*
      * Allocate a new DTD and fill the fields.
      */
     cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building internal subset");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlDtd));
     cur->type = XML_DTD_NODE;
 
     if (name != NULL) {
 	cur->name = xmlStrdup(name);
-	if (cur->name == NULL) {
-	    xmlTreeErrMemory("building internal subset");
-	    xmlFree(cur);
-	    return(NULL);
-	}
+	if (cur->name == NULL)
+            goto error;
     }
     if (ExternalID != NULL) {
 	cur->ExternalID = xmlStrdup(ExternalID);
-	if (cur->ExternalID  == NULL) {
-	    xmlTreeErrMemory("building internal subset");
-	    if (cur->name != NULL)
-	        xmlFree((char *)cur->name);
-	    xmlFree(cur);
-	    return(NULL);
-	}
+	if (cur->ExternalID  == NULL)
+            goto error;
     }
     if (SystemID != NULL) {
 	cur->SystemID = xmlStrdup(SystemID);
-	if (cur->SystemID == NULL) {
-	    xmlTreeErrMemory("building internal subset");
-	    if (cur->name != NULL)
-	        xmlFree((char *)cur->name);
-	    if (cur->ExternalID != NULL)
-	        xmlFree((char *)cur->ExternalID);
-	    xmlFree(cur);
-	    return(NULL);
-	}
+	if (cur->SystemID == NULL)
+            goto error;
     }
     if (doc != NULL) {
 	doc->intSubset = cur;
@@ -1041,6 +1008,10 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
+
+error:
+    xmlFreeDtd(cur);
+    return(NULL);
 }
 
 /**
@@ -1055,42 +1026,6 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
 	    (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))	\
 	    xmlFree((char *)(str));
 
-
-/**
- * DICT_COPY:
- * @str:  a string
- *
- * Copy a string using a "dict" dictionary in the current scope,
- * if available.
- */
-#define DICT_COPY(str, cpy) \
-    if (str) { \
-	if (dict) { \
-	    if (xmlDictOwns(dict, (const xmlChar *)(str))) \
-		cpy = (xmlChar *) (str); \
-	    else \
-		cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
-	} else \
-	    cpy = xmlStrdup((const xmlChar *)(str)); }
-
-/**
- * DICT_CONST_COPY:
- * @str:  a string
- *
- * Copy a string using a "dict" dictionary in the current scope,
- * if available.
- */
-#define DICT_CONST_COPY(str, cpy) \
-    if (str) { \
-	if (dict) { \
-	    if (xmlDictOwns(dict, (const xmlChar *)(str))) \
-		cpy = (const xmlChar *) (str); \
-	    else \
-		cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
-	} else \
-	    cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
-
-
 /**
  * xmlFreeDtd:
  * @cur:  the DTD structure to free up
@@ -1118,11 +1053,10 @@ xmlFreeDtd(xmlDtdPtr cur) {
 	 */
         while (c != NULL) {
 	    next = c->next;
-	    if ((c->type != XML_NOTATION_NODE) &&
-	        (c->type != XML_ELEMENT_DECL) &&
+	    if ((c->type != XML_ELEMENT_DECL) &&
 		(c->type != XML_ATTRIBUTE_DECL) &&
 		(c->type != XML_ENTITY_DECL)) {
-		xmlUnlinkNode(c);
+		xmlUnlinkNodeInternal(c);
 		xmlFreeNode(c);
 	    }
 	    c = next;
@@ -1149,11 +1083,11 @@ xmlFreeDtd(xmlDtdPtr cur) {
 
 /**
  * xmlNewDoc:
- * @version:  xmlChar string giving the version of XML "1.0"
+ * @version:  XML version string like "1.0" (optional)
  *
- * Creates a new XML document
+ * Creates a new XML document. If version is NULL, "1.0" is used.
  *
- * Returns a new document
+ * Returns a new document or NULL if a memory allocation failed.
  */
 xmlDocPtr
 xmlNewDoc(const xmlChar *version) {
@@ -1166,16 +1100,13 @@ xmlNewDoc(const xmlChar *version) {
      * Allocate a new document and fill the fields.
      */
     cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building doc");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlDoc));
     cur->type = XML_DOCUMENT_NODE;
 
     cur->version = xmlStrdup(version);
     if (cur->version == NULL) {
-	xmlTreeErrMemory("building doc");
 	xmlFree(cur);
 	return(NULL);
     }
@@ -1200,7 +1131,7 @@ xmlNewDoc(const xmlChar *version) {
  * xmlFreeDoc:
  * @cur:  pointer to the document
  *
- * Free up all the structures used by a document, tree included.
+ * Free a document including all children and associated DTDs.
  */
 void
 xmlFreeDoc(xmlDocPtr cur) {
@@ -1208,19 +1139,10 @@ xmlFreeDoc(xmlDocPtr cur) {
     xmlDictPtr dict = NULL;
 
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlFreeDoc : document == NULL\n");
-#endif
 	return;
     }
-#ifdef LIBXML_DEBUG_RUNTIME
-#ifdef LIBXML_DEBUG_ENABLED
-    xmlDebugCheckDocument(stderr, cur);
-#endif
-#endif
 
-    if (cur != NULL) dict = cur->dict;
+    dict = cur->dict;
 
     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
 	xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
@@ -1237,12 +1159,12 @@ xmlFreeDoc(xmlDocPtr cur) {
     if (intSubset == extSubset)
 	extSubset = NULL;
     if (extSubset != NULL) {
-	xmlUnlinkNode((xmlNodePtr) cur->extSubset);
+	xmlUnlinkNodeInternal((xmlNodePtr) cur->extSubset);
 	cur->extSubset = NULL;
 	xmlFreeDtd(extSubset);
     }
     if (intSubset != NULL) {
-	xmlUnlinkNode((xmlNodePtr) cur->intSubset);
+	xmlUnlinkNodeInternal((xmlNodePtr) cur->intSubset);
 	cur->intSubset = NULL;
 	xmlFreeDtd(intSubset);
     }
@@ -1259,38 +1181,52 @@ xmlFreeDoc(xmlDocPtr cur) {
 }
 
 /**
- * xmlStringLenGetNodeList:
- * @doc:  the document
- * @value:  the value of the text
- * @len:  the length of the string value
+ * xmlNodeParseContentInternal:
+ * @doc:  a document (optional)
+ * @parent:  an element or attribute (optional)
+ * @value:  an attribute value
+ * @len:  maximum length of the attribute value
+ * @listPtr:  pointer to the resulting node list (optional)
  *
- * Parse the value string and build the node list associated. Should
- * produce a flat tree with only TEXTs and ENTITY_REFs.
- * Returns a pointer to the first child
+ * See xmlNodeParseContent.
+ *
+ * Returns 0 on success, -1 if a memory allocation failed.
  */
-xmlNodePtr
-xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
-    xmlNodePtr ret = NULL, last = NULL;
+static int
+xmlNodeParseContentInternal(const xmlDoc *doc, xmlNodePtr parent,
+                            const xmlChar *value, int len,
+                            xmlNodePtr *listPtr) {
+    xmlNodePtr head = NULL, last = NULL;
     xmlNodePtr node;
-    xmlChar *val;
-    const xmlChar *cur, *end;
+    xmlChar *val = NULL;
+    const xmlChar *cur;
     const xmlChar *q;
     xmlEntityPtr ent;
     xmlBufPtr buf;
+    int remaining;
+
+    if (listPtr != NULL)
+        *listPtr = NULL;
+
+    if (len < 0)
+        remaining = INT_MAX;
+    else
+        remaining = len;
+
+    if ((value == NULL) || (value[0] == 0))
+        goto done;
 
-    if (value == NULL) return(NULL);
     cur = value;
-    end = cur + len;
 
-    buf = xmlBufCreateSize(0);
-    if (buf == NULL) return(NULL);
+    buf = xmlBufCreateSize(64);
+    if (buf == NULL)
+        return(-1);
     xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
 
     q = cur;
-    while ((cur < end) && (*cur != 0)) {
+    while ((remaining > 0) && (*cur != 0)) {
 	if (cur[0] == '&') {
 	    int charval = 0;
-	    xmlChar tmp;
 
 	    /*
 	     * Save the current text.
@@ -1298,25 +1234,15 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
             if (cur != q) {
 		if (xmlBufAdd(buf, q, cur - q))
 		    goto out;
+	        q = cur;
 	    }
-	    q = cur;
-	    if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) {
+
+	    if ((remaining > 2) && (cur[1] == '#') && (cur[2] == 'x')) {
+	        int tmp = 0;
+
 		cur += 3;
-		if (cur < end)
-		    tmp = *cur;
-		else
-		    tmp = 0;
-		while (tmp != ';') { /* Non input consuming loop */
-                    /*
-                     * If you find an integer overflow here when fuzzing,
-                     * the bug is probably elsewhere. This function should
-                     * only receive entities that were already validated by
-                     * the parser, typically by xmlParseAttValueComplex
-                     * calling xmlStringDecodeEntities.
-                     *
-                     * So it's better *not* to check for overflow to
-                     * potentially discover new bugs.
-                     */
+                remaining -= 3;
+		while ((remaining > 0) && ((tmp = *cur) != ';')) {
 		    if ((tmp >= '0') && (tmp <= '9'))
 			charval = charval * 16 + (tmp - '0');
 		    else if ((tmp >= 'a') && (tmp <= 'f'))
@@ -1324,135 +1250,147 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
 		    else if ((tmp >= 'A') && (tmp <= 'F'))
 			charval = charval * 16 + (tmp - 'A') + 10;
 		    else {
-			xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
-			           NULL);
 			charval = 0;
 			break;
 		    }
+                    if (charval > 0x110000)
+                        charval = 0x110000;
 		    cur++;
-		    if (cur < end)
-			tmp = *cur;
-		    else
-			tmp = 0;
+                    remaining--;
 		}
-		if (tmp == ';')
+		if (tmp == ';') {
 		    cur++;
+                    remaining--;
+                }
 		q = cur;
-	    } else if ((cur + 1 < end) && (cur[1] == '#')) {
+	    } else if ((remaining > 1) && (cur[1] == '#')) {
+	        int tmp = 0;
+
 		cur += 2;
-		if (cur < end)
-		    tmp = *cur;
-		else
-		    tmp = 0;
-		while (tmp != ';') { /* Non input consuming loops */
-                    /* Don't check for integer overflow, see above. */
+                remaining -= 2;
+		while ((remaining > 0) && ((tmp = *cur) != ';')) {
 		    if ((tmp >= '0') && (tmp <= '9'))
 			charval = charval * 10 + (tmp - '0');
 		    else {
-			xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
-			           NULL);
 			charval = 0;
 			break;
 		    }
+                    if (charval > 0x110000)
+                        charval = 0x110000;
 		    cur++;
-		    if (cur < end)
-			tmp = *cur;
-		    else
-			tmp = 0;
+                    remaining--;
 		}
-		if (tmp == ';')
+		if (tmp == ';') {
 		    cur++;
+                    remaining--;
+                }
 		q = cur;
 	    } else {
 		/*
 		 * Read the entity string
 		 */
 		cur++;
+                remaining--;
 		q = cur;
-		while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++;
-		if ((cur >= end) || (*cur == 0)) {
-		    xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc,
-		               (const char *) q);
-		    goto out;
-		}
+		while ((remaining > 0) && (*cur != 0) && (*cur != ';')) {
+                    cur++;
+                    remaining--;
+                }
+		if ((remaining <= 0) || (*cur == 0))
+		    break;
 		if (cur != q) {
-		    /*
-		     * Predefined entities don't generate nodes
-		     */
 		    val = xmlStrndup(q, cur - q);
+                    if (val == NULL)
+                        goto out;
 		    ent = xmlGetDocEntity(doc, val);
 		    if ((ent != NULL) &&
 			(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
-
+                        /*
+                         * Predefined entities don't generate nodes
+                         */
 			if (xmlBufCat(buf, ent->content))
 			    goto out;
-
 		    } else {
 			/*
 			 * Flush buffer so far
 			 */
 			if (!xmlBufIsEmpty(buf)) {
 			    node = xmlNewDocText(doc, NULL);
-			    if (node == NULL) {
-				if (val != NULL) xmlFree(val);
+			    if (node == NULL)
 				goto out;
-			    }
 			    node->content = xmlBufDetach(buf);
+                            node->parent = parent;
 
 			    if (last == NULL) {
-				last = ret = node;
+				head = node;
 			    } else {
-				last = xmlAddNextSibling(last, node);
+                                last->next = node;
+                                node->prev = last;
 			    }
+                            last = node;
+			}
+
+			if ((ent != NULL) &&
+                            ((ent->flags & XML_ENT_PARSED) == 0) &&
+                            ((ent->flags & XML_ENT_EXPANDING) == 0) &&
+                            (ent->content != NULL)) {
+                            int res;
+
+                            ent->flags |= XML_ENT_EXPANDING;
+                            res = xmlNodeParseContentInternal(doc,
+                                    (xmlNodePtr) ent, ent->content, -1, NULL);
+                            ent->flags &= ~XML_ENT_EXPANDING;
+                            if (res < 0)
+                                goto out;
+                            ent->flags |= XML_ENT_PARSED;
 			}
 
 			/*
 			 * Create a new REFERENCE_REF node
 			 */
-			node = xmlNewReference(doc, val);
-			if (node == NULL) {
-			    if (val != NULL) xmlFree(val);
+			node = xmlNewEntityRef((xmlDocPtr) doc, val);
+                        val = NULL;
+			if (node == NULL)
 			    goto out;
-			}
-			else if ((ent != NULL) && (ent->children == NULL)) {
-			    xmlNodePtr temp;
-
-                            /* Set to non-NULL value to avoid recursion. */
-			    ent->children = (xmlNodePtr) -1;
-			    ent->children = xmlStringGetNodeList(doc,
-				    (const xmlChar*)node->content);
-			    ent->owner = 1;
-			    temp = ent->children;
-			    while (temp) {
-				temp->parent = (xmlNodePtr)ent;
-				ent->last = temp;
-				temp = temp->next;
-			    }
-			}
+                        node->parent = parent;
+                        node->last = (xmlNodePtr) ent;
+                        if (ent != NULL) {
+                            node->children = (xmlNodePtr) ent;
+                            node->content = ent->content;
+                        }
+
 			if (last == NULL) {
-			    last = ret = node;
+			    head = node;
 			} else {
-			    last = xmlAddNextSibling(last, node);
+                            last->next = node;
+                            node->prev = last;
 			}
+                        last = node;
 		    }
 		    xmlFree(val);
+                    val = NULL;
 		}
 		cur++;
+                remaining--;
 		q = cur;
 	    }
 	    if (charval != 0) {
 		xmlChar buffer[10];
 		int l;
 
+                if (charval >= 0x110000)
+                    charval = 0xFFFD; /* replacement character */
+
 		l = xmlCopyCharMultiByte(buffer, charval);
 		buffer[l] = 0;
 
 		if (xmlBufCat(buf, buffer))
 		    goto out;
-		charval = 0;
 	    }
-	} else
+	} else {
 	    cur++;
+            remaining--;
+        }
     }
 
     if (cur != q) {
@@ -1465,391 +1403,258 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
 
     if (!xmlBufIsEmpty(buf)) {
 	node = xmlNewDocText(doc, NULL);
-	if (node == NULL) goto out;
+	if (node == NULL)
+            goto out;
+        node->parent = parent;
 	node->content = xmlBufDetach(buf);
 
 	if (last == NULL) {
-	    ret = node;
+	    head = node;
 	} else {
-	    xmlAddNextSibling(last, node);
+            last->next = node;
+            node->prev = last;
 	}
-    } else if (ret == NULL) {
-        ret = xmlNewDocText(doc, BAD_CAST "");
+        last = node;
+    } else if (head == NULL) {
+        head = xmlNewDocText(doc, BAD_CAST "");
+        if (head == NULL)
+            goto out;
+        head->parent = parent;
+        last = head;
+    }
+
+    xmlBufFree(buf);
+
+done:
+    if (parent != NULL) {
+        if (parent->children != NULL)
+            xmlFreeNodeList(parent->children);
+        parent->children = head;
+        parent->last = last;
     }
 
+    if (listPtr != NULL)
+        *listPtr = head;
+
+    return(0);
+
 out:
     xmlBufFree(buf);
+    if (val != NULL)
+        xmlFree(val);
+    if (head != NULL)
+        xmlFreeNodeList(head);
+    return(-1);
+}
+
+/**
+ * xmlNodeParseContent:
+ * @node:  an element or attribute
+ * @content:  text content with XML references
+ * @len:  maximum length of content
+ *
+ * Parse content and replace the node's children with the resulting
+ * node list.
+ *
+ * @content is expected to be a valid XML attribute value possibly
+ * containing character and entity references. Syntax errors
+ * and references to undeclared entities are ignored silently.
+ * Only references are handled, nested elements, comments or PIs are
+ * not.
+ *
+ * Returns 0 on success, -1 if a memory allocation failed.
+ */
+int
+xmlNodeParseContent(xmlNodePtr node, const xmlChar *content, int len) {
+    return(xmlNodeParseContentInternal(node->doc, node, content, len, NULL));
+}
+
+/**
+ * xmlStringLenGetNodeList:
+ * @doc:  a document (optional)
+ * @value:  an attribute value
+ * @len:  maximum length of the attribute value
+ *
+ * DEPRECATED: Use xmlNodeSetContentLen.
+ *
+ * See xmlStringGetNodeList.
+ *
+ * Returns a pointer to the first child or NULL if a memory
+ * allocation failed.
+ */
+xmlNodePtr
+xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
+    xmlNodePtr ret;
+
+    xmlNodeParseContentInternal(doc, NULL, value, len, &ret);
     return(ret);
 }
 
 /**
  * xmlStringGetNodeList:
- * @doc:  the document
- * @value:  the value of the attribute
+ * @doc:  a document (optional)
+ * @value:  an attribute value
+ *
+ * DEPRECATED: Use xmlNodeSetContent.
+ *
+ * Parse an attribute value and build a node list containing only
+ * text and entity reference nodes. The resulting nodes will be
+ * associated with the document if provided. The document is also
+ * used to look up entities.
+ *
+ * The input is not validated. Syntax errors or references to
+ * undeclared entities will be ignored silently with unspecified
+ * results.
  *
- * Parse the value string and build the node list associated. Should
- * produce a flat tree with only TEXTs and ENTITY_REFs.
- * Returns a pointer to the first child
+ * Returns a pointer to the first child or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr
 xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
-    xmlNodePtr ret = NULL, last = NULL;
-    xmlNodePtr node;
-    xmlChar *val;
-    const xmlChar *cur = value;
-    const xmlChar *q;
-    xmlEntityPtr ent;
+    xmlNodePtr ret;
+
+    xmlNodeParseContentInternal(doc, NULL, value, -1, &ret);
+    return(ret);
+}
+
+/**
+ * xmlNodeListGetStringInternal:
+ * @doc:  a document (optional)
+ * @node:  a node list
+ * @escMode: escape mode (0 = no, 1 = elem, 2 = attr, 3 = raw)
+ *
+ * Returns a pointer to the string.
+ */
+static xmlChar *
+xmlNodeListGetStringInternal(xmlDocPtr doc, const xmlNode *node, int escMode) {
     xmlBufPtr buf;
+    xmlChar *ret;
 
-    if (value == NULL) return(NULL);
+    if (node == NULL)
+        return(xmlStrdup(BAD_CAST ""));
 
-    buf = xmlBufCreateSize(0);
-    if (buf == NULL) return(NULL);
-    xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
+    if ((escMode == 0) &&
+        ((node->type == XML_TEXT_NODE) ||
+         (node->type == XML_CDATA_SECTION_NODE)) &&
+        (node->next == NULL)) {
+        if (node->content == NULL)
+            return(xmlStrdup(BAD_CAST ""));
+        return(xmlStrdup(node->content));
+    }
 
-    q = cur;
-    while (*cur != 0) {
-	if (cur[0] == '&') {
-	    int charval = 0;
-	    xmlChar tmp;
+    buf = xmlBufCreateSize(64);
+    if (buf == NULL)
+        return(NULL);
 
-	    /*
-	     * Save the current text.
-	     */
-            if (cur != q) {
-		if (xmlBufAdd(buf, q, cur - q))
-		    goto out;
-	    }
-	    q = cur;
-	    if ((cur[1] == '#') && (cur[2] == 'x')) {
-		cur += 3;
-		tmp = *cur;
-		while (tmp != ';') { /* Non input consuming loop */
-                    /* Don't check for integer overflow, see above. */
-		    if ((tmp >= '0') && (tmp <= '9'))
-			charval = charval * 16 + (tmp - '0');
-		    else if ((tmp >= 'a') && (tmp <= 'f'))
-			charval = charval * 16 + (tmp - 'a') + 10;
-		    else if ((tmp >= 'A') && (tmp <= 'F'))
-			charval = charval * 16 + (tmp - 'A') + 10;
-		    else {
-			xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
-			           NULL);
-			charval = 0;
-			break;
-		    }
-		    cur++;
-		    tmp = *cur;
-		}
-		if (tmp == ';')
-		    cur++;
-		q = cur;
-	    } else if  (cur[1] == '#') {
-		cur += 2;
-		tmp = *cur;
-		while (tmp != ';') { /* Non input consuming loops */
-                    /* Don't check for integer overflow, see above. */
-		    if ((tmp >= '0') && (tmp <= '9'))
-			charval = charval * 10 + (tmp - '0');
-		    else {
-			xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
-			           NULL);
-			charval = 0;
-			break;
-		    }
-		    cur++;
-		    tmp = *cur;
-		}
-		if (tmp == ';')
-		    cur++;
-		q = cur;
-	    } else {
-		/*
-		 * Read the entity string
-		 */
-		cur++;
-		q = cur;
-		while ((*cur != 0) && (*cur != ';')) cur++;
-		if (*cur == 0) {
-		    xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY,
-		               (xmlNodePtr) doc, (const char *) q);
-		    goto out;
-		}
-		if (cur != q) {
-		    /*
-		     * Predefined entities don't generate nodes
-		     */
-		    val = xmlStrndup(q, cur - q);
-		    ent = xmlGetDocEntity(doc, val);
-		    if ((ent != NULL) &&
-			(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
-
-			if (xmlBufCat(buf, ent->content))
-			    goto out;
-
-		    } else {
-			/*
-			 * Flush buffer so far
-			 */
-			if (!xmlBufIsEmpty(buf)) {
-			    node = xmlNewDocText(doc, NULL);
-			    if (node == NULL) {
-				if (val != NULL) xmlFree(val);
-				goto out;
-			    }
-			    node->content = xmlBufDetach(buf);
-
-			    if (last == NULL) {
-				last = ret = node;
-			    } else {
-				last = xmlAddNextSibling(last, node);
-			    }
-			}
-
-			/*
-			 * Create a new REFERENCE_REF node
-			 */
-			node = xmlNewReference(doc, val);
-			if (node == NULL) {
-			    if (val != NULL) xmlFree(val);
-			    goto out;
-			}
-			else if ((ent != NULL) && (ent->children == NULL)) {
-			    xmlNodePtr temp;
-
-                            /* Set to non-NULL value to avoid recursion. */
-			    ent->children = (xmlNodePtr) -1;
-			    ent->children = xmlStringGetNodeList(doc,
-				    (const xmlChar*)node->content);
-			    ent->owner = 1;
-			    temp = ent->children;
-			    while (temp) {
-				temp->parent = (xmlNodePtr)ent;
-				ent->last = temp;
-				temp = temp->next;
-			    }
-			}
-			if (last == NULL) {
-			    last = ret = node;
-			} else {
-			    last = xmlAddNextSibling(last, node);
-			}
-		    }
-		    xmlFree(val);
-		}
-		cur++;
-		q = cur;
-	    }
-	    if (charval != 0) {
-		xmlChar buffer[10];
-		int len;
-
-		len = xmlCopyCharMultiByte(buffer, charval);
-		buffer[len] = 0;
-
-		if (xmlBufCat(buf, buffer))
-		    goto out;
-		charval = 0;
-	    }
-	} else
-	    cur++;
-    }
-    if ((cur != q) || (ret == NULL)) {
-        /*
-	 * Handle the last piece of text.
-	 */
-	xmlBufAdd(buf, q, cur - q);
-    }
-
-    if (!xmlBufIsEmpty(buf)) {
-	node = xmlNewDocText(doc, NULL);
-        if (node == NULL) {
-            xmlBufFree(buf);
-            return(NULL);
+    while (node != NULL) {
+        if ((node->type == XML_TEXT_NODE) ||
+            (node->type == XML_CDATA_SECTION_NODE)) {
+            if (node->content != NULL) {
+                if (escMode == 0) {
+                    xmlBufCat(buf, node->content);
+                } else {
+                    xmlChar *encoded;
+
+                    if (escMode == 1)
+                        encoded = xmlEncodeEntitiesReentrant(doc,
+                                                             node->content);
+                    else if (escMode == 2)
+                        encoded = xmlEncodeAttributeEntities(doc,
+                                                             node->content);
+                    else
+                        encoded = xmlEncodeSpecialChars(doc, node->content);
+                    if (encoded == NULL)
+                        goto error;
+                    xmlBufCat(buf, encoded);
+                    xmlFree(encoded);
+                }
+            }
+        } else if (node->type == XML_ENTITY_REF_NODE) {
+            if (escMode == 0) {
+                xmlBufGetNodeContent(buf, node);
+            } else {
+                xmlBufAdd(buf, BAD_CAST "&", 1);
+                xmlBufCat(buf, node->name);
+                xmlBufAdd(buf, BAD_CAST ";", 1);
+            }
         }
-	node->content = xmlBufDetach(buf);
 
-	if (last == NULL) {
-	    ret = node;
-	} else {
-	    xmlAddNextSibling(last, node);
-	}
+        node = node->next;
     }
 
-out:
+    ret = xmlBufDetach(buf);
     xmlBufFree(buf);
     return(ret);
+
+error:
+    xmlBufFree(buf);
+    return(NULL);
 }
 
 /**
  * xmlNodeListGetString:
- * @doc:  the document
- * @list:  a Node list
- * @inLine:  should we replace entity contents or show their external form
+ * @doc:  a document (optional)
+ * @list:  a node list of attribute children
+ * @inLine:  whether entity references are substituted
  *
- * Build the string equivalent to the text contained in the Node list
- * made of TEXTs and ENTITY_REFs
+ * Serializes attribute children (text and entity reference nodes)
+ * into a string.
  *
- * Returns a pointer to the string copy, the caller must free it with xmlFree().
+ * If @inLine is true, entity references will be substituted.
+ * Otherwise, entity references will be kept and special characters
+ * like '&' as well as non-ASCII chars will be escaped. See
+ * xmlNodeListGetRawString for an alternative option.
+ *
+ * Returns a string or NULL if a memory allocation failed.
  */
 xmlChar *
 xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine)
 {
-    const xmlNode *node = list;
-    xmlChar *ret = NULL;
-    xmlEntityPtr ent;
-    int attr;
+    int escMode;
 
+    /* backward compatibility */
     if (list == NULL)
-        return (NULL);
-    if ((list->parent != NULL) && (list->parent->type == XML_ATTRIBUTE_NODE))
-        attr = 1;
-    else
-        attr = 0;
-
-    while (node != NULL) {
-        if ((node->type == XML_TEXT_NODE) ||
-            (node->type == XML_CDATA_SECTION_NODE)) {
-            if (inLine) {
-                ret = xmlStrcat(ret, node->content);
-            } else {
-                xmlChar *buffer;
+        return(NULL);
 
-		if (attr)
-		    buffer = xmlEncodeAttributeEntities(doc, node->content);
-		else
-		    buffer = xmlEncodeEntitiesReentrant(doc, node->content);
-                if (buffer != NULL) {
-                    ret = xmlStrcat(ret, buffer);
-                    xmlFree(buffer);
-                }
-            }
-        } else if (node->type == XML_ENTITY_REF_NODE) {
-            if (inLine) {
-                ent = xmlGetDocEntity(doc, node->name);
-                if (ent != NULL) {
-                    xmlChar *buffer;
-
-                    /* an entity content can be any "well balanced chunk",
-                     * i.e. the result of the content [43] production:
-                     * http://www.w3.org/TR/REC-xml#NT-content.
-                     * So it can contain text, CDATA section or nested
-                     * entity reference nodes (among others).
-                     * -> we recursive  call xmlNodeListGetString()
-                     * which handles these types */
-                    buffer = xmlNodeListGetString(doc, ent->children, 1);
-                    if (buffer != NULL) {
-                        ret = xmlStrcat(ret, buffer);
-                        xmlFree(buffer);
-                    }
-                } else {
-                    ret = xmlStrcat(ret, node->content);
-                }
-            } else {
-                xmlChar buf[2];
-
-                buf[0] = '&';
-                buf[1] = 0;
-                ret = xmlStrncat(ret, buf, 1);
-                ret = xmlStrcat(ret, node->name);
-                buf[0] = ';';
-                buf[1] = 0;
-                ret = xmlStrncat(ret, buf, 1);
-            }
-        }
-#if 0
-        else {
-            xmlGenericError(xmlGenericErrorContext,
-                            "xmlGetNodeListString : invalid node type %d\n",
-                            node->type);
-        }
-#endif
-        node = node->next;
+    if (inLine) {
+        escMode = 0;
+    } else {
+        if ((list->parent != NULL) &&
+            (list->parent->type == XML_ATTRIBUTE_NODE))
+            escMode = 2;
+        else
+            escMode = 1;
     }
-    return (ret);
+
+    return(xmlNodeListGetStringInternal(doc, list, escMode));
 }
 
 #ifdef LIBXML_TREE_ENABLED
 /**
  * xmlNodeListGetRawString:
- * @doc:  the document
- * @list:  a Node list
- * @inLine:  should we replace entity contents or show their external form
+ * @doc:  a document (optional)
+ * @list:  a node list of attribute children
+ * @inLine:  whether entity references are substituted
+ *
+ * Serializes attribute children (text and entity reference nodes)
+ * into a string.
  *
- * Builds the string equivalent to the text contained in the Node list
- * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
- * this function doesn't do any character encoding handling.
+ * If @inLine is true, entity references will be substituted.
+ * Otherwise, entity references will be kept and special characters
+ * like '&' will be escaped.
  *
- * Returns a pointer to the string copy, the caller must free it with xmlFree().
+ * Returns a string or NULL if a memory allocation failed.
  */
 xmlChar *
 xmlNodeListGetRawString(const xmlDoc *doc, const xmlNode *list, int inLine)
 {
-    const xmlNode *node = list;
-    xmlChar *ret = NULL;
-    xmlEntityPtr ent;
+    int escMode = inLine ? 0 : 3;
 
+    /* backward compatibility */
     if (list == NULL)
-        return (NULL);
-
-    while (node != NULL) {
-        if ((node->type == XML_TEXT_NODE) ||
-            (node->type == XML_CDATA_SECTION_NODE)) {
-            if (inLine) {
-                ret = xmlStrcat(ret, node->content);
-            } else {
-                xmlChar *buffer;
+        return(NULL);
 
-                buffer = xmlEncodeSpecialChars(doc, node->content);
-                if (buffer != NULL) {
-                    ret = xmlStrcat(ret, buffer);
-                    xmlFree(buffer);
-                }
-            }
-        } else if (node->type == XML_ENTITY_REF_NODE) {
-            if (inLine) {
-                ent = xmlGetDocEntity(doc, node->name);
-                if (ent != NULL) {
-                    xmlChar *buffer;
-
-                    /* an entity content can be any "well balanced chunk",
-                     * i.e. the result of the content [43] production:
-                     * http://www.w3.org/TR/REC-xml#NT-content.
-                     * So it can contain text, CDATA section or nested
-                     * entity reference nodes (among others).
-                     * -> we recursive  call xmlNodeListGetRawString()
-                     * which handles these types */
-                    buffer =
-                        xmlNodeListGetRawString(doc, ent->children, 1);
-                    if (buffer != NULL) {
-                        ret = xmlStrcat(ret, buffer);
-                        xmlFree(buffer);
-                    }
-                } else {
-                    ret = xmlStrcat(ret, node->content);
-                }
-            } else {
-                xmlChar buf[2];
-
-                buf[0] = '&';
-                buf[1] = 0;
-                ret = xmlStrncat(ret, buf, 1);
-                ret = xmlStrcat(ret, node->name);
-                buf[0] = ';';
-                buf[1] = 0;
-                ret = xmlStrncat(ret, buf, 1);
-            }
-        }
-#if 0
-        else {
-            xmlGenericError(xmlGenericErrorContext,
-                            "xmlGetNodeListString : invalid node type %d\n",
-                            node->type);
-        }
-#endif
-        node = node->next;
-    }
-    return (ret);
+    return(xmlNodeListGetStringInternal((xmlDocPtr) doc, list, escMode));
 }
 #endif /* LIBXML_TREE_ENABLED */
 
@@ -1863,7 +1668,7 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
 
     if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) {
         if ((eatname == 1) &&
-	    ((node->doc == NULL) ||
+	    ((node->doc == NULL) || (node->doc->dict == NULL) ||
 	     (!(xmlDictOwns(node->doc->dict, name)))))
             xmlFree((xmlChar *) name);
         return (NULL);
@@ -1876,9 +1681,9 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
     if (cur == NULL) {
         if ((eatname == 1) &&
 	    ((node == NULL) || (node->doc == NULL) ||
+             (node->doc->dict == NULL) ||
 	     (!(xmlDictOwns(node->doc->dict, name)))))
             xmlFree((xmlChar *) name);
-        xmlTreeErrMemory("building attribute");
         return (NULL);
     }
     memset(cur, 0, sizeof(xmlAttr));
@@ -1896,6 +1701,8 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
             cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
         else
             cur->name = xmlStrdup(name);
+        if (cur->name == NULL)
+            goto error;
     } else
         cur->name = name;
 
@@ -1903,6 +1710,8 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
         xmlNodePtr tmp;
 
         cur->children = xmlNewDocText(doc, value);
+        if (cur->children == NULL)
+            goto error;
         cur->last = NULL;
         tmp = cur->children;
         while (tmp != NULL) {
@@ -1911,6 +1720,15 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
                 cur->last = tmp;
             tmp = tmp->next;
         }
+
+        if (doc != NULL) {
+            int res = xmlIsID(doc, node, cur);
+
+            if (res < 0)
+                goto error;
+            if ((res == 1) && (xmlAddIDSafe(cur, value) < 0))
+                goto error;
+        }
     }
 
     /*
@@ -1929,34 +1747,38 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
         }
     }
 
-    if ((value != NULL) && (node != NULL) &&
-        (xmlIsID(node->doc, node, cur) == 1))
-        xmlAddID(NULL, node->doc, value, cur);
-
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
         xmlRegisterNodeDefaultValue((xmlNodePtr) cur);
     return (cur);
+
+error:
+    xmlFreeProp(cur);
+    return(NULL);
 }
 
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
     defined(LIBXML_SCHEMAS_ENABLED)
 /**
  * xmlNewProp:
- * @node:  the holding node
+ * @node:  the parent node (optional)
  * @name:  the name of the attribute
- * @value:  the value of the attribute
+ * @value:  the value of the attribute (optional)
+ *
+ * Create an attribute node.
+ *
+ * If provided, @value should be a raw, unescaped string.
+ *
+ * If @node is provided, the created attribute will be appended without
+ * checking for duplicate names. It is an error if @node is not an
+ * element.
  *
- * Create a new property carried by a node.
- * Returns a pointer to the attribute
+ * Returns a pointer to the attribute or NULL if arguments are invalid
+ * or a memory allocation failed.
  */
 xmlAttrPtr
 xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewProp : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -1966,23 +1788,27 @@ xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
 
 /**
  * xmlNewNsProp:
- * @node:  the holding node
- * @ns:  the namespace
- * @name:  the name of the attribute
- * @value:  the value of the attribute
+ * @node:  the parent node (optional)
+ * @ns:  the namespace (optional)
+ * @name:  the local name of the attribute
+ * @value:  the value of the attribute (optional)
+ *
+ * Create an attribute object.
+ *
+ * If provided, @value should be a raw, unescaped string.
  *
- * Create a new property tagged with a namespace and carried by a node.
- * Returns a pointer to the attribute
+ * If @node is provided, the created attribute will be appended without
+ * checking for duplicate names. It is an error if @node is not an
+ * element.
+ *
+ * Returns a pointer to the attribute or NULL if arguments are invalid
+ * or a memory allocation failed.
  */
 xmlAttrPtr
 xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
            const xmlChar *value) {
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewNsProp : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -1991,23 +1817,23 @@ xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
 
 /**
  * xmlNewNsPropEatName:
- * @node:  the holding node
- * @ns:  the namespace
- * @name:  the name of the attribute
- * @value:  the value of the attribute
+ * @node:  the parent node (optional)
+ * @ns:  the namespace (optional)
+ * @name:  the local name of the attribute
+ * @value:  the value of the attribute (optional)
+ *
+ * Like xmlNewNsProp, but the @name string will be used directly
+ * without making a copy. Takes ownership of @name which will also
+ * be freed on error.
  *
- * Create a new property tagged with a namespace and carried by a node.
- * Returns a pointer to the attribute
+ * Returns a pointer to the attribute or NULL if arguments are invalid
+ * or a memory allocation failed.
  */
 xmlAttrPtr
 xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
            const xmlChar *value) {
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewNsPropEatName : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -2016,27 +1842,25 @@ xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
 
 /**
  * xmlNewDocProp:
- * @doc:  the document
+ * @doc:  the target document (optional)
  * @name:  the name of the attribute
- * @value:  the value of the attribute
+ * @value:  attribute value with XML references (optional)
  *
- * Create a new property carried by a document.
- * NOTE: @value is supposed to be a piece of XML CDATA, so it allows entity
- *       references, but XML special chars need to be escaped first by using
- *       xmlEncodeEntitiesReentrant(). Use xmlNewProp() if you don't need
- *       entities support.
+ * Create an attribute object.
  *
- * Returns a pointer to the attribute
+ * If provided, @value is expected to be a valid XML attribute value
+ * possibly containing character and entity references. Syntax errors
+ * and references to undeclared entities are ignored silently.
+ * If you want to pass a raw string, see xmlNewProp.
+ *
+ * Returns a pointer to the attribute or NULL if arguments are invalid
+ * or a memory allocation failed.
  */
 xmlAttrPtr
 xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
     xmlAttrPtr cur;
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewDocProp : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -2044,10 +1868,8 @@ xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
      * Allocate a new property and fill the fields.
      */
     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building attribute");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlAttr));
     cur->type = XML_ATTRIBUTE_NODE;
 
@@ -2055,32 +1877,28 @@ xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
 	cur->name = xmlDictLookup(doc->dict, name, -1);
     else
 	cur->name = xmlStrdup(name);
+    if (cur->name == NULL)
+        goto error;
     cur->doc = doc;
     if (value != NULL) {
-	xmlNodePtr tmp;
-
-	cur->children = xmlStringGetNodeList(doc, value);
-	cur->last = NULL;
-
-	tmp = cur->children;
-	while (tmp != NULL) {
-	    tmp->parent = (xmlNodePtr) cur;
-	    if (tmp->next == NULL)
-		cur->last = tmp;
-	    tmp = tmp->next;
-	}
+	if (xmlNodeParseContent((xmlNodePtr) cur, value, -1) < 0)
+            goto error;
     }
 
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
+
+error:
+    xmlFreeProp(cur);
+    return(NULL);
 }
 
 /**
  * xmlFreePropList:
- * @cur:  the first property in the list
+ * @cur:  the first attribute in the list
  *
- * Free a property and all its siblings, all the children are freed too.
+ * Free an attribute list including all children.
  */
 void
 xmlFreePropList(xmlAttrPtr cur) {
@@ -2097,7 +1915,7 @@ xmlFreePropList(xmlAttrPtr cur) {
  * xmlFreeProp:
  * @cur:  an attribute
  *
- * Free one attribute, all the content is freed too
+ * Free an attribute including all children.
  */
 void
 xmlFreeProp(xmlAttrPtr cur) {
@@ -2122,26 +1940,22 @@ xmlFreeProp(xmlAttrPtr cur) {
  * xmlRemoveProp:
  * @cur:  an attribute
  *
- * Unlink and free one attribute, all the content is freed too
- * Note this doesn't work for namespace definition attributes
+ * Unlink and free an attribute including all children.
  *
- * Returns 0 if success and -1 in case of error.
+ * Note this doesn't work for namespace declarations.
+ *
+ * The attribute must have a non-NULL parent pointer.
+ *
+ * Returns 0 on success or -1 if the attribute was not found or
+ * arguments are invalid.
  */
 int
 xmlRemoveProp(xmlAttrPtr cur) {
     xmlAttrPtr tmp;
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlRemoveProp : cur == NULL\n");
-#endif
 	return(-1);
     }
     if (cur->parent == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlRemoveProp : cur->parent == NULL\n");
-#endif
 	return(-1);
     }
     tmp = cur->parent->properties;
@@ -2162,31 +1976,25 @@ xmlRemoveProp(xmlAttrPtr cur) {
 	}
         tmp = tmp->next;
     }
-#ifdef DEBUG_TREE
-    xmlGenericError(xmlGenericErrorContext,
-	    "xmlRemoveProp : attribute not owned by its node\n");
-#endif
     return(-1);
 }
 
 /**
  * xmlNewDocPI:
- * @doc:  the target document
- * @name:  the processing instruction name
- * @content:  the PI content
+ * @doc:  the target document (optional)
+ * @name:  the processing instruction target
+ * @content:  the PI content (optional)
  *
- * Creation of a processing instruction element.
- * Returns a pointer to the new node object.
+ * Create a processing instruction object.
+ *
+ * Returns a pointer to the new node object or NULL if arguments are
+ * invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) {
     xmlNodePtr cur;
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewPI : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -2194,37 +2002,44 @@ xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) {
      * Allocate a new node and fill the fields.
      */
     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building PI");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlNode));
     cur->type = XML_PI_NODE;
+    cur->doc = doc;
 
     if ((doc != NULL) && (doc->dict != NULL))
         cur->name = xmlDictLookup(doc->dict, name, -1);
     else
 	cur->name = xmlStrdup(name);
+    if (cur->name == NULL)
+        goto error;
     if (content != NULL) {
 	cur->content = xmlStrdup(content);
+        if (cur->content == NULL)
+            goto error;
     }
-    cur->doc = doc;
 
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
+
+error:
+    xmlFreeNode(cur);
+    return(NULL);
 }
 
 /**
  * xmlNewPI:
- * @name:  the processing instruction name
- * @content:  the PI content
+ * @name:  the processing instruction target
+ * @content:  the PI content (optional)
  *
- * Creation of a processing instruction element.
+ * Create a processing instruction node.
  *
  * Use of this function is DISCOURAGED in favor of xmlNewDocPI.
  *
- * Returns a pointer to the new node object.
+ * Returns a pointer to the new node object or NULL if arguments are
+ * invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlNewPI(const xmlChar *name, const xmlChar *content) {
@@ -2233,124 +2048,122 @@ xmlNewPI(const xmlChar *name, const xmlChar *content) {
 
 /**
  * xmlNewNode:
- * @ns:  namespace if any
+ * @ns:  namespace (optional)
  * @name:  the node name
  *
- * Creation of a new node element. @ns is optional (NULL).
+ * Create an element node.
  *
  * Use of this function is DISCOURAGED in favor of xmlNewDocNode.
  *
- * Returns a pointer to the new node object. Uses xmlStrdup() to make
- * copy of @name.
+ * Returns a pointer to the new node object or NULL if arguments are
+ * invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
-    xmlNodePtr cur;
-
-    if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewNode : name == NULL\n");
-#endif
-	return(NULL);
-    }
-
-    /*
-     * Allocate a new node and fill the fields.
-     */
-    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building node");
-	return(NULL);
-    }
-    memset(cur, 0, sizeof(xmlNode));
-    cur->type = XML_ELEMENT_NODE;
-
-    cur->name = xmlStrdup(name);
-    cur->ns = ns;
-
-    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
-	xmlRegisterNodeDefaultValue(cur);
-    return(cur);
+    return(xmlNewDocNode(NULL, ns, name, NULL));
 }
 
 /**
  * xmlNewNodeEatName:
- * @ns:  namespace if any
+ * @ns:  namespace (optional)
  * @name:  the node name
  *
- * Creation of a new node element. @ns is optional (NULL).
+ * Create an element node.
  *
  * Use of this function is DISCOURAGED in favor of xmlNewDocNodeEatName.
  *
- * Returns a pointer to the new node object, with pointer @name as
- * new node's name. Use xmlNewNode() if a copy of @name string is
- * is needed as new node's name.
+ * Like xmlNewNode, but the @name string will be used directly
+ * without making a copy. Takes ownership of @name which will also
+ * be freed on error.
+ *
+ * Returns a pointer to the new node object or NULL if arguments are
+ * invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) {
-    xmlNodePtr cur;
+    return(xmlNewDocNodeEatName(NULL, ns, name, NULL));
+}
 
-    if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewNode : name == NULL\n");
-#endif
-	return(NULL);
-    }
+static xmlNodePtr
+xmlNewElem(xmlDocPtr doc, xmlNsPtr ns, const xmlChar *name,
+           const xmlChar *content) {
+    xmlNodePtr cur;
 
-    /*
-     * Allocate a new node and fill the fields.
-     */
     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building node");
-	/* we can't check here that name comes from the doc dictionary */
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlNode));
-    cur->type = XML_ELEMENT_NODE;
 
+    cur->type = XML_ELEMENT_NODE;
+    cur->doc = doc;
     cur->name = name;
     cur->ns = ns;
 
-    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
+    if (content != NULL) {
+        if (xmlNodeParseContent(cur, content, -1) < 0) {
+            /* Don't free name on error */
+            xmlFree(cur);
+            return(NULL);
+        }
+    }
+
+    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
+
     return(cur);
 }
 
 /**
  * xmlNewDocNode:
- * @doc:  the document
- * @ns:  namespace if any
+ * @doc:  the target document
+ * @ns:  namespace (optional)
  * @name:  the node name
- * @content:  the XML text content if any
+ * @content:  text content with XML references (optional)
+ *
+ * Create an element node.
+ *
+ * If provided, @content is expected to be a valid XML attribute value
+ * possibly containing character and entity references. Syntax errors
+ * and references to undeclared entities are ignored silently.
+ * Only references are handled, nested elements, comments or PIs are
+ * not. See xmlNewDocRawNode for an alternative.
+ *
+ * General notes on object creation:
  *
- * Creation of a new node element within a document. @ns and @content
- * are optional (NULL).
- * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
- *       references, but XML special chars need to be escaped first by using
- *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
- *       need entities support.
+ * Each node and all its children are associated with the same
+ * document. The document should be provided when creating nodes to
+ * avoid a performance penalty when adding the node to a document
+ * tree. Note that a document only owns nodes reachable from the root
+ * node. Unlinked subtrees must be freed manually.
  *
- * Returns a pointer to the new node object.
+ * Returns a pointer to the new node object or NULL if arguments are
+ * invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
               const xmlChar *name, const xmlChar *content) {
     xmlNodePtr cur;
+    xmlChar *copy;
 
-    if ((doc != NULL) && (doc->dict != NULL))
-        cur = xmlNewNodeEatName(ns, (xmlChar *)
-	                        xmlDictLookup(doc->dict, name, -1));
-    else
-	cur = xmlNewNode(ns, name);
-    if (cur != NULL) {
-        cur->doc = doc;
-	if (content != NULL) {
-	    cur->children = xmlStringGetNodeList(doc, content);
-	    UPDATE_LAST_CHILD_AND_PARENT(cur)
-	}
+    if (name == NULL)
+        return(NULL);
+
+    if ((doc != NULL) && (doc->dict != NULL)) {
+        const xmlChar *dictName = xmlDictLookup(doc->dict, name, -1);
+
+        if (dictName == NULL)
+            return(NULL);
+        return(xmlNewElem(doc, ns, dictName, content));
+    }
+
+    copy = xmlStrdup(name);
+    if (copy == NULL)
+        return(NULL);
+
+    cur = xmlNewElem(doc, ns, copy, content);
+    if (cur == NULL) {
+        xmlFree(copy);
+        return(NULL);
     }
 
     return(cur);
@@ -2358,53 +2171,55 @@ xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
 
 /**
  * xmlNewDocNodeEatName:
- * @doc:  the document
- * @ns:  namespace if any
+ * @doc:  the target document
+ * @ns:  namespace (optional)
  * @name:  the node name
- * @content:  the XML text content if any
+ * @content:  text content with XML references (optional)
+ *
+ * Create an element node.
  *
- * Creation of a new node element within a document. @ns and @content
- * are optional (NULL).
- * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
- *       references, but XML special chars need to be escaped first by using
- *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
- *       need entities support.
+ * Like xmlNewDocNode, but the @name string will be used directly
+ * without making a copy. Takes ownership of @name which will also
+ * be freed on error.
  *
- * Returns a pointer to the new node object.
+ * Returns a pointer to the new node object or NULL if arguments are
+ * invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns,
-              xmlChar *name, const xmlChar *content) {
+                     xmlChar *name, const xmlChar *content) {
     xmlNodePtr cur;
 
-    cur = xmlNewNodeEatName(ns, name);
-    if (cur != NULL) {
-        cur->doc = doc;
-	if (content != NULL) {
-	    cur->children = xmlStringGetNodeList(doc, content);
-	    UPDATE_LAST_CHILD_AND_PARENT(cur)
-	}
-    } else {
-        /* if name don't come from the doc dictionary free it here */
-        if ((name != NULL) && (doc != NULL) &&
-	    (!(xmlDictOwns(doc->dict, name))))
-	    xmlFree(name);
+    if (name == NULL)
+        return(NULL);
+
+    cur = xmlNewElem(doc, ns, name, content);
+    if (cur == NULL) {
+        /* if name doesn't come from the doc dictionary free it here */
+        if ((doc == NULL) ||
+            (doc->dict == NULL) ||
+            (!xmlDictOwns(doc->dict, name)))
+            xmlFree(name);
+        return(NULL);
     }
+
     return(cur);
 }
 
 #ifdef LIBXML_TREE_ENABLED
 /**
  * xmlNewDocRawNode:
- * @doc:  the document
- * @ns:  namespace if any
+ * @doc:  the target document
+ * @ns:  namespace (optional)
  * @name:  the node name
- * @content:  the text content if any
+ * @content:  raw text content (optional)
+ *
+ * Create an element node.
  *
- * Creation of a new node element within a document. @ns and @content
- * are optional (NULL).
+ * If provided, @value should be a raw, unescaped string.
  *
- * Returns a pointer to the new node object.
+ * Returns a pointer to the new node object or NULL if arguments are
+ * invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
@@ -2415,8 +2230,17 @@ xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
     if (cur != NULL) {
         cur->doc = doc;
 	if (content != NULL) {
-	    cur->children = xmlNewDocText(doc, content);
-	    UPDATE_LAST_CHILD_AND_PARENT(cur)
+            xmlNodePtr text;
+
+	    text = xmlNewDocText(doc, content);
+            if (text == NULL) {
+                xmlFreeNode(cur);
+                return(NULL);
+            }
+
+            cur->children = text;
+            cur->last = text;
+            text->parent = cur;
 	}
     }
     return(cur);
@@ -2424,10 +2248,12 @@ xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
 
 /**
  * xmlNewDocFragment:
- * @doc:  the document owning the fragment
+ * @doc:  the target document (optional)
  *
- * Creation of a new Fragment node.
- * Returns a pointer to the new node object.
+ * Create a document fragment node.
+ *
+ * Returns a pointer to the new node object or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr
 xmlNewDocFragment(xmlDocPtr doc) {
@@ -2437,10 +2263,8 @@ xmlNewDocFragment(xmlDocPtr doc) {
      * Allocate a new DocumentFragment node and fill the fields.
      */
     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building fragment");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlNode));
     cur->type = XML_DOCUMENT_FRAG_NODE;
 
@@ -2454,13 +2278,14 @@ xmlNewDocFragment(xmlDocPtr doc) {
 
 /**
  * xmlNewText:
- * @content:  the text content
+ * @content:  raw text content (optional)
  *
- * Creation of a new text node.
+ * Create a text node.
  *
  * Use of this function is DISCOURAGED in favor of xmlNewDocText.
  *
- * Returns a pointer to the new node object.
+ * Returns a pointer to the new node object or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr
 xmlNewText(const xmlChar *content) {
@@ -2470,91 +2295,77 @@ xmlNewText(const xmlChar *content) {
      * Allocate a new node and fill the fields.
      */
     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building text");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlNode));
     cur->type = XML_TEXT_NODE;
 
     cur->name = xmlStringText;
     if (content != NULL) {
 	cur->content = xmlStrdup(content);
+        if (cur->content == NULL)
+            goto error;
     }
 
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue(cur);
     return(cur);
+
+error:
+    xmlFreeNode(cur);
+    return(NULL);
 }
 
 #ifdef LIBXML_TREE_ENABLED
 /**
  * xmlNewTextChild:
  * @parent:  the parent node
- * @ns:  a namespace if any
+ * @ns:  a namespace (optional)
  * @name:  the name of the child
- * @content:  the text content of the child if any.
+ * @content:  raw text content of the child (optional)
+ *
+ * Create a new child element and append it to a parent element.
  *
- * Creation of a new child element, added at the end of @parent children list.
- * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
- * created element inherits the namespace of @parent. If @content is non NULL,
- * a child TEXT node will be created containing the string @content.
- * NOTE: Use xmlNewChild() if @content will contain entities that need to be
- * preserved. Use this function, xmlNewTextChild(), if you need to ensure that
- * reserved XML chars that might appear in @content, such as the ampersand,
- * greater-than or less-than signs, are automatically replaced by their XML
- * escaped entity representations.
+ * If @ns is NULL, the newly created element inherits the namespace
+ * of the parent.
  *
- * Returns a pointer to the new node object.
+ * If @content is provided, a text node will be added to the child
+ * element, see xmlNewDocRawNode.
+ *
+ * Returns a pointer to the new node object or NULL if arguments
+ * are invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
             const xmlChar *name, const xmlChar *content) {
     xmlNodePtr cur, prev;
 
-    if (parent == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewTextChild : parent == NULL\n");
-#endif
+    if ((parent == NULL) || (name == NULL))
 	return(NULL);
-    }
 
-    if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewTextChild : name == NULL\n");
-#endif
-	return(NULL);
-    }
+    switch (parent->type) {
+        case XML_DOCUMENT_NODE:
+        case XML_HTML_DOCUMENT_NODE:
+        case XML_DOCUMENT_FRAG_NODE:
+            break;
 
-    /*
-     * Allocate a new node
-     */
-    if (parent->type == XML_ELEMENT_NODE) {
-	if (ns == NULL)
-	    cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
-	else
-	    cur = xmlNewDocRawNode(parent->doc, ns, name, content);
-    } else if ((parent->type == XML_DOCUMENT_NODE) ||
-	       (parent->type == XML_HTML_DOCUMENT_NODE)) {
-	if (ns == NULL)
-	    cur = xmlNewDocRawNode((xmlDocPtr) parent, NULL, name, content);
-	else
-	    cur = xmlNewDocRawNode((xmlDocPtr) parent, ns, name, content);
-    } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
-	    cur = xmlNewDocRawNode( parent->doc, ns, name, content);
-    } else {
-	return(NULL);
+        case XML_ELEMENT_NODE:
+            if (ns == NULL)
+                ns = parent->ns;
+            break;
+
+        default:
+            return(NULL);
     }
-    if (cur == NULL) return(NULL);
+
+    cur = xmlNewDocRawNode(parent->doc, ns, name, content);
+    if (cur == NULL)
+        return(NULL);
 
     /*
      * add the new element at the end of the children list.
      */
-    cur->type = XML_ELEMENT_NODE;
     cur->parent = parent;
-    cur->doc = parent->doc;
     if (parent->children == NULL) {
         parent->children = cur;
 	parent->last = cur;
@@ -2570,55 +2381,92 @@ xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
 #endif /* LIBXML_TREE_ENABLED */
 
 /**
- * xmlNewCharRef:
- * @doc: the document
- * @name:  the char ref string, starting with # or "&# ... ;"
+ * xmlNewEntityRef:
+ * @doc: the target document (optional)
+ * @name:  the entity name
+ *
+ * Create an empty entity reference node. This function doesn't attempt
+ * to look up the entity in @doc.
  *
- * Creation of a new character reference node.
- * Returns a pointer to the new node object.
+ * @name is consumed.
+ *
+ * Returns a pointer to the new node object or NULL if arguments are
+ * invalid or a memory allocation failed.
  */
-xmlNodePtr
-xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
+static xmlNodePtr
+xmlNewEntityRef(xmlDocPtr doc, xmlChar *name) {
     xmlNodePtr cur;
 
-    if (name == NULL)
-        return(NULL);
-
     /*
      * Allocate a new node and fill the fields.
      */
     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
     if (cur == NULL) {
-	xmlTreeErrMemory("building character reference");
+        xmlFree(name);
 	return(NULL);
     }
     memset(cur, 0, sizeof(xmlNode));
     cur->type = XML_ENTITY_REF_NODE;
-
     cur->doc = doc;
+    cur->name = name;
+
+    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
+	xmlRegisterNodeDefaultValue(cur);
+
+    return(cur);
+}
+
+/**
+ * xmlNewCharRef:
+ * @doc: the target document (optional)
+ * @name:  the entity name
+ *
+ * This function is MISNAMED. It doesn't create a character reference
+ * but an entity reference.
+ *
+ * Create an empty entity reference node. This function doesn't attempt
+ * to look up the entity in @doc.
+ *
+ * Entity names like '&entity;' are handled as well.
+ *
+ * Returns a pointer to the new node object or NULL if arguments are
+ * invalid or a memory allocation failed.
+ */
+xmlNodePtr
+xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
+    xmlChar *copy;
+
+    if (name == NULL)
+        return(NULL);
+
     if (name[0] == '&') {
         int len;
         name++;
 	len = xmlStrlen(name);
 	if (name[len - 1] == ';')
-	    cur->name = xmlStrndup(name, len - 1);
+	    copy = xmlStrndup(name, len - 1);
 	else
-	    cur->name = xmlStrndup(name, len);
+	    copy = xmlStrndup(name, len);
     } else
-	cur->name = xmlStrdup(name);
+	copy = xmlStrdup(name);
+    if (copy == NULL)
+        return(NULL);
 
-    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
-	xmlRegisterNodeDefaultValue(cur);
-    return(cur);
+    return(xmlNewEntityRef(doc, copy));
 }
 
 /**
  * xmlNewReference:
- * @doc: the document
- * @name:  the reference name, or the reference string with & and ;
+ * @doc: the target document (optional)
+ * @name:  the entity name
  *
- * Creation of a new reference node.
- * Returns a pointer to the new node object.
+ * Create a new entity reference node, linking the result with the
+ * entity in @doc if found.
+ *
+ * Entity names like '&entity;' are handled as well.
+ *
+ * Returns a pointer to the new node object or NULL if arguments are
+ * invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlNewReference(const xmlDoc *doc, const xmlChar *name) {
@@ -2632,10 +2480,8 @@ xmlNewReference(const xmlDoc *doc, const xmlChar *name) {
      * Allocate a new node and fill the fields.
      */
     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building reference");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlNode));
     cur->type = XML_ENTITY_REF_NODE;
 
@@ -2650,6 +2496,8 @@ xmlNewReference(const xmlDoc *doc, const xmlChar *name) {
 	    cur->name = xmlStrndup(name, len);
     } else
 	cur->name = xmlStrdup(name);
+    if (cur->name == NULL)
+        goto error;
 
     ent = xmlGetDocEntity(doc, cur->name);
     if (ent != NULL) {
@@ -2666,15 +2514,21 @@ xmlNewReference(const xmlDoc *doc, const xmlChar *name) {
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue(cur);
     return(cur);
+
+error:
+    xmlFreeNode(cur);
+    return(NULL);
 }
 
 /**
  * xmlNewDocText:
- * @doc: the document
- * @content:  the text content
+ * @doc:  the target document
+ * @content:  raw text content (optional)
  *
- * Creation of a new text node within a document.
- * Returns a pointer to the new node object.
+ * Create a new text node.
+ *
+ * Returns a pointer to the new node object or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr
 xmlNewDocText(const xmlDoc *doc, const xmlChar *content) {
@@ -2687,13 +2541,13 @@ xmlNewDocText(const xmlDoc *doc, const xmlChar *content) {
 
 /**
  * xmlNewTextLen:
- * @content:  the text content
- * @len:  the text len.
+ * @content:  raw text content (optional)
+ * @len:  size of text content
  *
  * Use of this function is DISCOURAGED in favor of xmlNewDocTextLen.
  *
- * Creation of a new text node with an extra parameter for the content's length
- * Returns a pointer to the new node object.
+ * Returns a pointer to the new node object or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr
 xmlNewTextLen(const xmlChar *content, int len) {
@@ -2703,16 +2557,18 @@ xmlNewTextLen(const xmlChar *content, int len) {
      * Allocate a new node and fill the fields.
      */
     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building text");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlNode));
     cur->type = XML_TEXT_NODE;
 
     cur->name = xmlStringText;
     if (content != NULL) {
 	cur->content = xmlStrndup(content, len);
+        if (cur->content == NULL) {
+            xmlFreeNode(cur);
+            return(NULL);
+        }
     }
 
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
@@ -2722,13 +2578,14 @@ xmlNewTextLen(const xmlChar *content, int len) {
 
 /**
  * xmlNewDocTextLen:
- * @doc: the document
- * @content:  the text content
- * @len:  the text len.
+ * @doc:  the target document
+ * @content:  raw text content (optional)
+ * @len:  size of text content
+ *
+ * Create a new text node.
  *
- * Creation of a new text node with an extra content length parameter. The
- * text node pertain to a given document.
- * Returns a pointer to the new node object.
+ * Returns a pointer to the new node object or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr
 xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
@@ -2741,12 +2598,14 @@ xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
 
 /**
  * xmlNewComment:
- * @content:  the comment content
+ * @content:  the comment content (optional)
  *
  * Use of this function is DISCOURAGED in favor of xmlNewDocComment.
  *
- * Creation of a new node containing a comment.
- * Returns a pointer to the new node object.
+ * Create a comment node.
+ *
+ * Returns a pointer to the new node object or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr
 xmlNewComment(const xmlChar *content) {
@@ -2756,31 +2615,37 @@ xmlNewComment(const xmlChar *content) {
      * Allocate a new node and fill the fields.
      */
     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building comment");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlNode));
     cur->type = XML_COMMENT_NODE;
 
     cur->name = xmlStringComment;
     if (content != NULL) {
 	cur->content = xmlStrdup(content);
+        if (cur->content == NULL)
+            goto error;
     }
 
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue(cur);
     return(cur);
+
+error:
+    xmlFreeNode(cur);
+    return(NULL);
 }
 
 /**
  * xmlNewCDataBlock:
- * @doc:  the document
- * @content:  the CDATA block content content
- * @len:  the length of the block
+ * @doc:  the target document (optional)
+ * @content:  raw text content (optional)
+ * @len:  size of text content
  *
- * Creation of a new node containing a CDATA block.
- * Returns a pointer to the new node object.
+ * Create a CDATA section node.
+ *
+ * Returns a pointer to the new node object or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr
 xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
@@ -2790,16 +2655,18 @@ xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
      * Allocate a new node and fill the fields.
      */
     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-    if (cur == NULL) {
-	xmlTreeErrMemory("building CDATA");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlNode));
     cur->type = XML_CDATA_SECTION_NODE;
     cur->doc = doc;
 
     if (content != NULL) {
 	cur->content = xmlStrndup(content, len);
+        if (cur->content == NULL) {
+            xmlFree(cur);
+            return(NULL);
+        }
     }
 
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
@@ -2812,8 +2679,10 @@ xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
  * @doc:  the document
  * @content:  the comment content
  *
- * Creation of a new node containing a comment within a document.
- * Returns a pointer to the new node object.
+ * Create a comment node.
+ *
+ * Returns a pointer to the new node object or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr
 xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
@@ -2824,172 +2693,293 @@ xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
     return(cur);
 }
 
-static const xmlChar *_copyStringForNewDictIfNeeded(xmlDictPtr oldDict, xmlDictPtr newDict, const xmlChar *oldValue) {
-    const xmlChar *newValue = oldValue;
-    if (oldValue) {
-        int oldDictOwnsOldValue = oldDict && (xmlDictOwns(oldDict, oldValue) == 1);
-        if (oldDictOwnsOldValue) {
+static void
+xmlRemoveEntity(xmlEntityPtr ent) {
+    xmlDocPtr doc = ent->doc;
+    xmlDtdPtr intSubset, extSubset;
+
+    if (doc == NULL)
+        return;
+    intSubset = doc->intSubset;
+    extSubset = doc->extSubset;
+
+    if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
+        (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
+        (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY)) {
+        if (intSubset != NULL) {
+            if (xmlHashLookup(intSubset->entities, ent->name) == ent)
+                xmlHashRemoveEntry(intSubset->entities, ent->name, NULL);
+        }
+        if (extSubset != NULL) {
+            if (xmlHashLookup(extSubset->entities, ent->name) == ent)
+                xmlHashRemoveEntry(extSubset->entities, ent->name, NULL);
+        }
+    } else if ((ent->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
+               (ent->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
+        if (intSubset != NULL) {
+            if (xmlHashLookup(intSubset->pentities, ent->name) == ent)
+                xmlHashRemoveEntry(intSubset->entities, ent->name, NULL);
+        }
+        if (extSubset != NULL) {
+            if (xmlHashLookup(extSubset->pentities, ent->name) == ent)
+                xmlHashRemoveEntry(extSubset->entities, ent->name, NULL);
+        }
+    }
+}
+
+static int
+xmlNodeSetDoc(xmlNodePtr node, xmlDocPtr doc) {
+    xmlDocPtr oldDoc;
+    xmlDictPtr oldDict, newDict;
+    int ret = 0;
+
+    /*
+     * Remove name and content from old dictionary
+     */
+
+    oldDoc = node->doc;
+    oldDict = oldDoc ? oldDoc->dict : NULL;
+    newDict = doc ? doc->dict : NULL;
+
+    if ((oldDict != NULL) && (oldDict != newDict)) {
+        if ((node->name != NULL) &&
+            ((node->type == XML_ELEMENT_NODE) ||
+             (node->type == XML_ATTRIBUTE_NODE) ||
+             (node->type == XML_PI_NODE) ||
+             (node->type == XML_ENTITY_REF_NODE)) &&
+            (xmlDictOwns(oldDict, node->name))) {
             if (newDict)
-                newValue = xmlDictLookup(newDict, oldValue, -1);
+                node->name = xmlDictLookup(newDict, node->name, -1);
             else
-                newValue = xmlStrdup(oldValue);
+                node->name = xmlStrdup(node->name);
+            if (node->name == NULL)
+                ret = -1;
         }
+
+        if ((node->content != NULL) &&
+            ((node->type == XML_TEXT_NODE) ||
+             (node->type == XML_CDATA_SECTION_NODE)) &&
+            (xmlDictOwns(oldDict, node->content))) {
+            node->content = xmlStrdup(node->content);
+            if (node->content == NULL)
+                ret = -1;
+        }
+    }
+
+    switch (node->type) {
+        case XML_ATTRIBUTE_NODE: {
+            xmlAttrPtr attr = (xmlAttrPtr) node;
+
+            /*
+             * Handle IDs
+             *
+             * TODO: ID attributes should also be added to the new
+             * document, but it's not clear how to handle clashes.
+             */
+            if (attr->atype == XML_ATTRIBUTE_ID)
+                xmlRemoveID(oldDoc, attr);
+
+            break;
+        }
+
+        case XML_ENTITY_REF_NODE:
+            /*
+             * Handle entity references
+             */
+            node->children = NULL;
+            node->last = NULL;
+            node->content = NULL;
+
+            if ((doc != NULL) &&
+                ((doc->intSubset != NULL) || (doc->extSubset != NULL))) {
+                xmlEntityPtr ent;
+
+                /*
+                * Assign new entity node if available
+                */
+                ent = xmlGetDocEntity(doc, node->name);
+                if (ent != NULL) {
+                    node->children = (xmlNodePtr) ent;
+                    node->last = (xmlNodePtr) ent;
+                    node->content = ent->content;
+                }
+            }
+
+            break;
+
+        case XML_DTD_NODE:
+            if (oldDoc != NULL) {
+                if (oldDoc->intSubset == (xmlDtdPtr) node)
+                    oldDoc->intSubset = NULL;
+                if (oldDoc->extSubset == (xmlDtdPtr) node)
+                    oldDoc->extSubset = NULL;
+            }
+
+            break;
+
+        case XML_ENTITY_DECL:
+            xmlRemoveEntity((xmlEntityPtr) node);
+            break;
+
+        /*
+         * TODO:
+         * - Remove element decls from doc->elements
+         * - Remove attribtue decls form doc->attributes
+         */
+
+        default:
+            break;
     }
-    return newValue;
+
+    /*
+     * Set new document
+     */
+    node->doc = doc;
+
+    return(ret);
 }
 
 /**
  * xmlSetTreeDoc:
- * @tree:  the top element
- * @doc:  the document
+ * @tree:  root of a subtree
+ * @doc:  new document
+ *
+ * This is an internal function which shouldn't be used. It is
+ * invoked by functions like xmlAddChild, xmlAddSibling or
+ * xmlReplaceNode. @tree must be the root node of an unlinked
+ * subtree.
+ *
+ * Associate all nodes in a tree with a new document.
+ *
+ * Also copy strings from the old document's dictionary and
+ * remove ID attributes from the old ID table.
  *
- * update all nodes under the tree to point to the right document
+ * Returns 0 on success. If a memory allocation fails, returns -1.
+ * The whole tree will be updated on failure but some strings
+ * may be lost.
  */
-void
+int
 xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
-    xmlAttrPtr prop;
+    int ret = 0;
 
     if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
-	return;
-    if (tree->doc != doc) {
-        xmlDictPtr oldTreeDict = tree->doc ? tree->doc->dict : NULL;
-        xmlDictPtr newDict = doc ? doc->dict : NULL;
-
-	if(tree->type == XML_ELEMENT_NODE) {
-	    prop = tree->properties;
-	    while (prop != NULL) {
-                if (prop->atype == XML_ATTRIBUTE_ID) {
-                    xmlRemoveID(tree->doc, prop);
-                }
+	return(0);
+    if (tree->doc == doc)
+        return(0);
 
-                if (prop->doc != doc) {
-                    xmlDictPtr oldPropDict = prop->doc ? prop->doc->dict : NULL;
-                    prop->name = _copyStringForNewDictIfNeeded(oldPropDict, newDict, prop->name);
-                    prop->doc = doc;
-                }
-		xmlSetListDoc(prop->children, doc);
+    if (tree->type == XML_ELEMENT_NODE) {
+        xmlAttrPtr prop = tree->properties;
 
-                /*
-                 * TODO: ID attributes should be also added to the new
-                 * document, but this breaks things like xmlReplaceNode.
-                 * The underlying problem is that xmlRemoveID is only called
-                 * if a node is destroyed, not if it's unlinked.
-                 */
-#if 0
-                if (xmlIsID(doc, tree, prop)) {
-                    xmlChar *idVal = xmlNodeListGetString(doc, prop->children,
-                                                          1);
-                    xmlAddID(NULL, doc, idVal, prop);
-                }
-#endif
+        while (prop != NULL) {
+            if (prop->children != NULL) {
+                if (xmlSetListDoc(prop->children, doc) < 0)
+                    ret = -1;
+            }
 
-		prop = prop->next;
-	    }
-	}
-        if (tree->type == XML_ENTITY_REF_NODE) {
-            /*
-             * Clear 'children' which points to the entity declaration
-             * from the original document.
-             */
-            tree->children = NULL;
-        } else if (tree->children != NULL) {
-	    xmlSetListDoc(tree->children, doc);
+            if (xmlNodeSetDoc((xmlNodePtr) prop, doc) < 0)
+                ret = -1;
+
+            prop = prop->next;
         }
+    }
 
-        tree->name = _copyStringForNewDictIfNeeded(oldTreeDict, newDict, tree->name);
-        tree->content = (xmlChar *)_copyStringForNewDictIfNeeded(oldTreeDict, NULL, tree->content);
-        /* FIXME: tree->ns should be updated as in xmlStaticCopyNode(). */
-	tree->doc = doc;
+    if ((tree->children != NULL) &&
+        (tree->type != XML_ENTITY_REF_NODE)) {
+        if (xmlSetListDoc(tree->children, doc) < 0)
+            ret = -1;
     }
+
+    if (xmlNodeSetDoc(tree, doc) < 0)
+        ret = -1;
+
+    return(ret);
 }
 
 /**
  * xmlSetListDoc:
- * @list:  the first element
- * @doc:  the document
+ * @list:  a node list
+ * @doc:  new document
+ *
+ * Associate all subtrees in @list with a new document.
  *
- * update all nodes in the list to point to the right document
+ * Internal function, see xmlSetTreeDoc.
+ *
+ * Returns 0 on success. If a memory allocation fails, returns -1.
+ * All subtrees will be updated on failure but some strings
+ * may be lost.
  */
-void
+int
 xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) {
     xmlNodePtr cur;
+    int ret = 0;
 
     if ((list == NULL) || (list->type == XML_NAMESPACE_DECL))
-	return;
-    cur = list;
+	return(0);
+
+    cur = list;
     while (cur != NULL) {
-	if (cur->doc != doc)
-	    xmlSetTreeDoc(cur, doc);
+	if (cur->doc != doc) {
+	    if (xmlSetTreeDoc(cur, doc) < 0)
+                ret = -1;
+        }
 	cur = cur->next;
     }
+
+    return(ret);
 }
 
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
 /**
  * xmlNewChild:
  * @parent:  the parent node
- * @ns:  a namespace if any
+ * @ns:  a namespace (optional)
  * @name:  the name of the child
- * @content:  the XML content of the child if any.
+ * @content:  text content with XML references (optional)
+ *
+ * Create a new child element and append it to a parent element.
+ *
+ * If @ns is NULL, the newly created element inherits the namespace
+ * of the parent.
  *
- * Creation of a new child element, added at the end of @parent children list.
- * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
- * created element inherits the namespace of @parent. If @content is non NULL,
- * a child list containing the TEXTs and ENTITY_REFs node will be created.
- * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
- *       references. XML special chars must be escaped first by using
- *       xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.
+ * If provided, @content is expected to be a valid XML attribute
+ * value possibly containing character and entity references. Text
+ * and entity reference node will be added to the child element,
+ * see xmlNewDocNode.
  *
- * Returns a pointer to the new node object.
+ * Returns a pointer to the new node object or NULL if arguments
+ * are invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
             const xmlChar *name, const xmlChar *content) {
     xmlNodePtr cur, prev;
 
-    if (parent == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewChild : parent == NULL\n");
-#endif
+    if ((parent == NULL) || (name == NULL))
 	return(NULL);
-    }
 
-    if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewChild : name == NULL\n");
-#endif
-	return(NULL);
-    }
+    switch (parent->type) {
+        case XML_DOCUMENT_NODE:
+        case XML_HTML_DOCUMENT_NODE:
+        case XML_DOCUMENT_FRAG_NODE:
+            break;
 
-    /*
-     * Allocate a new node
-     */
-    if (parent->type == XML_ELEMENT_NODE) {
-	if (ns == NULL)
-	    cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
-	else
-	    cur = xmlNewDocNode(parent->doc, ns, name, content);
-    } else if ((parent->type == XML_DOCUMENT_NODE) ||
-	       (parent->type == XML_HTML_DOCUMENT_NODE)) {
-	if (ns == NULL)
-	    cur = xmlNewDocNode((xmlDocPtr) parent, NULL, name, content);
-	else
-	    cur = xmlNewDocNode((xmlDocPtr) parent, ns, name, content);
-    } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
-	    cur = xmlNewDocNode( parent->doc, ns, name, content);
-    } else {
-	return(NULL);
+        case XML_ELEMENT_NODE:
+            if (ns == NULL)
+                ns = parent->ns;
+            break;
+
+        default:
+            return(NULL);
     }
-    if (cur == NULL) return(NULL);
+
+    cur = xmlNewDocNode(parent->doc, ns, name, content);
+    if (cur == NULL)
+        return(NULL);
 
     /*
      * add the new element at the end of the children list.
      */
-    cur->type = XML_ELEMENT_NODE;
     cur->parent = parent;
-    cur->doc = parent->doc;
     if (parent->children == NULL) {
         parent->children = cur;
 	parent->last = cur;
@@ -3004,297 +2994,274 @@ xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
 }
 #endif /* LIBXML_TREE_ENABLED */
 
-/**
- * xmlAddPropSibling:
- * @prev:  the attribute to which @prop is added after
- * @cur:   the base attribute passed to calling function
- * @prop:  the new attribute
- *
- * Add a new attribute after @prev using @cur as base attribute.
- * When inserting before @cur, @prev is passed as @cur->prev.
- * When inserting after @cur, @prev is passed as @cur.
- * If an existing attribute is found it is destroyed prior to adding @prop.
- *
- * See the note regarding namespaces in xmlAddChild.
- *
- * Returns the attribute being inserted or NULL in case of error.
- */
+static void
+xmlTextSetContent(xmlNodePtr text, xmlChar *content) {
+    if ((text->content != NULL) &&
+        (text->content != (xmlChar *) &text->properties)) {
+        xmlDocPtr doc = text->doc;
+
+        if ((doc == NULL) ||
+            (doc->dict == NULL) ||
+            (!xmlDictOwns(doc->dict, text->content)))
+            xmlFree(text->content);
+    }
+
+    text->content = content;
+    text->properties = NULL;
+}
+
+static int
+xmlTextAddContent(xmlNodePtr text, const xmlChar *content, int len) {
+    xmlChar *merged;
+
+    if (content == NULL)
+        return(0);
+
+    merged = xmlStrncatNew(text->content, content, len);
+    if (merged == NULL)
+        return(-1);
+
+    xmlTextSetContent(text, merged);
+    return(0);
+}
+
 static xmlNodePtr
-xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) {
-	xmlAttrPtr attr;
+xmlInsertProp(xmlDocPtr doc, xmlNodePtr cur, xmlNodePtr parent,
+              xmlNodePtr prev, xmlNodePtr next) {
+    xmlAttrPtr attr;
 
-	if ((cur == NULL) || (cur->type != XML_ATTRIBUTE_NODE) ||
-	    (prop == NULL) || (prop->type != XML_ATTRIBUTE_NODE) ||
-	    ((prev != NULL) && (prev->type != XML_ATTRIBUTE_NODE)))
-		return(NULL);
+    if (((prev != NULL) && (prev->type != XML_ATTRIBUTE_NODE)) ||
+        ((next != NULL) && (next->type != XML_ATTRIBUTE_NODE)))
+        return(NULL);
 
-	/* check if an attribute with the same name exists */
-	if (prop->ns == NULL)
-		attr = xmlHasNsProp(cur->parent, prop->name, NULL);
-	else
-		attr = xmlHasNsProp(cur->parent, prop->name, prop->ns->href);
+    /* check if an attribute with the same name exists */
+    attr = xmlGetPropNodeInternal(parent, cur->name,
+                                  cur->ns ? cur->ns->href : NULL, 0);
 
-	if (prop->doc != cur->doc) {
-		xmlSetTreeDoc(prop, cur->doc);
-	}
-	prop->parent = cur->parent;
-	prop->prev = prev;
-	if (prev != NULL) {
-		prop->next = prev->next;
-		prev->next = prop;
-		if (prop->next)
-			prop->next->prev = prop;
-	} else {
-		prop->next = cur;
-		cur->prev = prop;
+    xmlUnlinkNodeInternal(cur);
+
+    if (cur->doc != doc) {
+        if (xmlSetTreeDoc(cur, doc) < 0)
+            return(NULL);
+    }
+
+    cur->parent = parent;
+    cur->prev = prev;
+    cur->next = next;
+
+    if (prev == NULL) {
+        if (parent != NULL)
+            parent->properties = (xmlAttrPtr) cur;
+    } else {
+        prev->next = cur;
+    }
+    if (next != NULL) {
+        next->prev = cur;
+    }
+
+    if ((attr != NULL) && (attr != (xmlAttrPtr) cur)) {
+        /* different instance, destroy it (attributes must be unique) */
+        xmlRemoveProp((xmlAttrPtr) attr);
+    }
+
+    return cur;
+}
+
+static xmlNodePtr
+xmlInsertNode(xmlDocPtr doc, xmlNodePtr cur, xmlNodePtr parent,
+              xmlNodePtr prev, xmlNodePtr next, int coalesce) {
+    xmlNodePtr oldParent;
+
+    if (cur->type == XML_ATTRIBUTE_NODE)
+	return xmlInsertProp(doc, cur, parent, prev, next);
+
+    /*
+     * Coalesce text nodes
+     */
+    if ((coalesce) && (cur->type == XML_TEXT_NODE)) {
+	if ((prev != NULL) && (prev->type == XML_TEXT_NODE) &&
+            (prev->name == cur->name)) {
+            if (xmlTextAddContent(prev, cur->content, -1) < 0)
+                return(NULL);
+            xmlUnlinkNodeInternal(cur);
+	    xmlFreeNode(cur);
+	    return(prev);
 	}
-	if (prop->prev == NULL && prop->parent != NULL)
-		prop->parent->properties = (xmlAttrPtr) prop;
-	if ((attr != NULL) && (attr->type != XML_ATTRIBUTE_DECL)) {
-		/* different instance, destroy it (attributes must be unique) */
-		xmlRemoveProp((xmlAttrPtr) attr);
+
+	if ((next != NULL) && (next->type == XML_TEXT_NODE) &&
+            (next->name == cur->name)) {
+            if (cur->content != NULL) {
+	        xmlChar *merged;
+
+                merged = xmlStrncatNew(cur->content, next->content, -1);
+                if (merged == NULL)
+                    return(NULL);
+                xmlTextSetContent(next, merged);
+            }
+
+            xmlUnlinkNodeInternal(cur);
+	    xmlFreeNode(cur);
+	    return(next);
 	}
-	return prop;
+    }
+
+    /* Unlink */
+    oldParent = cur->parent;
+    if (oldParent != NULL) {
+        if (oldParent->children == cur)
+            oldParent->children = cur->next;
+        if (oldParent->last == cur)
+            oldParent->last = cur->prev;
+    }
+    if (cur->next != NULL)
+        cur->next->prev = cur->prev;
+    if (cur->prev != NULL)
+        cur->prev->next = cur->next;
+
+    if (cur->doc != doc) {
+	if (xmlSetTreeDoc(cur, doc) < 0) {
+            /*
+             * We shouldn't make any modifications to the inserted
+             * tree if a memory allocation fails, but that's hard to
+             * implement. The tree has been moved to the target
+             * document now but some contents are corrupted.
+             * Unlinking is the best we can do.
+             */
+            cur->parent = NULL;
+            cur->prev = NULL;
+            cur->next = NULL;
+            return(NULL);
+        }
+    }
+
+    cur->parent = parent;
+    cur->prev = prev;
+    cur->next = next;
+
+    if (prev == NULL) {
+        if (parent != NULL)
+            parent->children = cur;
+    } else {
+        prev->next = cur;
+    }
+    if (next == NULL) {
+        if (parent != NULL)
+            parent->last = cur;
+    } else {
+        next->prev = cur;
+    }
+
+    return(cur);
 }
 
 /**
  * xmlAddNextSibling:
- * @cur:  the child node
- * @elem:  the new node
+ * @prev:  the target node
+ * @cur:  the new node
  *
- * Add a new node @elem as the next sibling of @cur
- * If the new node was already inserted in a document it is
- * first unlinked from its existing context.
- * As a result of text merging @elem may be freed.
- * If the new node is ATTRIBUTE, it is added into properties instead of children.
- * If there is an attribute with equal name, it is first destroyed.
+ * Unlinks @cur and inserts it as next sibling after @prev.
  *
- * See the note regarding namespaces in xmlAddChild.
+ * Unlike xmlAddChild this function does not merge text nodes.
  *
- * Returns the new node or NULL in case of error.
+ * If @cur is an attribute node, it is inserted after attribute
+ * @prev. If the attribute list contains an attribute with a name
+ * matching @cur, the old attribute is destroyed.
+ *
+ * See the notes in xmlAddChild.
+ *
+ * Returns @cur or a sibling if @cur was merged. Returns NULL
+ * if arguments are invalid or a memory allocation failed.
  */
 xmlNodePtr
-xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
-    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddNextSibling : cur == NULL\n");
-#endif
-	return(NULL);
-    }
-    if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddNextSibling : elem == NULL\n");
-#endif
-	return(NULL);
-    }
-
-    if (cur == elem) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddNextSibling : cur == elem\n");
-#endif
+xmlAddNextSibling(xmlNodePtr prev, xmlNodePtr cur) {
+    if ((prev == NULL) || (prev->type == XML_NAMESPACE_DECL) ||
+        (cur == NULL) || (cur->type == XML_NAMESPACE_DECL) ||
+        (cur == prev))
 	return(NULL);
-    }
 
-    xmlUnlinkNode(elem);
-
-    if (elem->type == XML_TEXT_NODE) {
-	if (cur->type == XML_TEXT_NODE) {
-	    xmlNodeAddContent(cur, elem->content);
-	    xmlFreeNode(elem);
-	    return(cur);
-	}
-	if ((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE) &&
-            (cur->name == cur->next->name)) {
-	    xmlChar *tmp;
-
-	    tmp = xmlStrdup(elem->content);
-	    tmp = xmlStrcat(tmp, cur->next->content);
-	    xmlNodeSetContent(cur->next, tmp);
-	    xmlFree(tmp);
-	    xmlFreeNode(elem);
-	    return(cur->next);
-	}
-    } else if (elem->type == XML_ATTRIBUTE_NODE) {
-		return xmlAddPropSibling(cur, cur, elem);
-    }
+    if (cur == prev->next)
+        return(cur);
 
-    if (elem->doc != cur->doc) {
-	xmlSetTreeDoc(elem, cur->doc);
-    }
-    elem->parent = cur->parent;
-    elem->prev = cur;
-    elem->next = cur->next;
-    cur->next = elem;
-    if (elem->next != NULL)
-	elem->next->prev = elem;
-    if ((elem->parent != NULL) && (elem->parent->last == cur))
-	elem->parent->last = elem;
-    return(elem);
+    return(xmlInsertNode(prev->doc, cur, prev->parent, prev, prev->next, 0));
 }
 
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
     defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
 /**
  * xmlAddPrevSibling:
- * @cur:  the child node
- * @elem:  the new node
+ * @next:  the target node
+ * @cur:  the new node
+ *
+ * Unlinks @cur and inserts it as previous sibling before @next.
+ *
+ * Unlike xmlAddChild this function does not merge text nodes.
  *
- * Add a new node @elem as the previous sibling of @cur
- * merging adjacent TEXT nodes (@elem may be freed)
- * If the new node was already inserted in a document it is
- * first unlinked from its existing context.
- * If the new node is ATTRIBUTE, it is added into properties instead of children.
- * If there is an attribute with equal name, it is first destroyed.
+ * If @cur is an attribute node, it is inserted before attribute
+ * @next. If the attribute list contains an attribute with a name
+ * matching @cur, the old attribute is destroyed.
  *
- * See the note regarding namespaces in xmlAddChild.
+ * See the notes in xmlAddChild.
  *
- * Returns the new node or NULL in case of error.
+ * Returns @cur or a sibling if @cur was merged. Returns NULL
+ * if arguments are invalid or a memory allocation failed.
  */
 xmlNodePtr
-xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
-    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddPrevSibling : cur == NULL\n");
-#endif
-	return(NULL);
-    }
-    if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddPrevSibling : elem == NULL\n");
-#endif
-	return(NULL);
-    }
-
-    if (cur == elem) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddPrevSibling : cur == elem\n");
-#endif
+xmlAddPrevSibling(xmlNodePtr next, xmlNodePtr cur) {
+    if ((next == NULL) || (next->type == XML_NAMESPACE_DECL) ||
+        (cur == NULL) || (cur->type == XML_NAMESPACE_DECL) ||
+        (cur == next))
 	return(NULL);
-    }
-
-    xmlUnlinkNode(elem);
-
-    if (elem->type == XML_TEXT_NODE) {
-	if (cur->type == XML_TEXT_NODE) {
-	    xmlChar *tmp;
 
-	    tmp = xmlStrdup(elem->content);
-	    tmp = xmlStrcat(tmp, cur->content);
-	    xmlNodeSetContent(cur, tmp);
-	    xmlFree(tmp);
-	    xmlFreeNode(elem);
-	    return(cur);
-	}
-	if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE) &&
-            (cur->name == cur->prev->name)) {
-	    xmlNodeAddContent(cur->prev, elem->content);
-	    xmlFreeNode(elem);
-	    return(cur->prev);
-	}
-    } else if (elem->type == XML_ATTRIBUTE_NODE) {
-		return xmlAddPropSibling(cur->prev, cur, elem);
-    }
+    if (cur == next->prev)
+        return(cur);
 
-    if (elem->doc != cur->doc) {
-	xmlSetTreeDoc(elem, cur->doc);
-    }
-    elem->parent = cur->parent;
-    elem->next = cur;
-    elem->prev = cur->prev;
-    cur->prev = elem;
-    if (elem->prev != NULL)
-	elem->prev->next = elem;
-    if ((elem->parent != NULL) && (elem->parent->children == cur)) {
-		elem->parent->children = elem;
-    }
-    return(elem);
+    return(xmlInsertNode(next->doc, cur, next->parent, next->prev, next, 0));
 }
 #endif /* LIBXML_TREE_ENABLED */
 
 /**
  * xmlAddSibling:
- * @cur:  the child node
- * @elem:  the new node
+ * @node:  the target node
+ * @cur:  the new node
+ *
+ * Unlinks @cur and inserts it as last sibling of @node.
+ *
+ * If @cur is a text node, it may be merged with an adjacent text
+ * node and freed. In this case the text node containing the merged
+ * content is returned.
  *
- * Add a new element @elem to the list of siblings of @cur
- * merging adjacent TEXT nodes (@elem may be freed)
- * If the new element was already inserted in a document it is
- * first unlinked from its existing context.
+ * If @cur is an attribute node, it is appended to the attribute
+ * list containing @node. If the attribute list contains an attribute
+ * with a name matching @cur, the old attribute is destroyed.
  *
- * See the note regarding namespaces in xmlAddChild.
+ * See the notes in xmlAddChild.
  *
- * Returns the new element or NULL in case of error.
+ * Returns @cur or a sibling if @cur was merged. Returns NULL
+ * if arguments are invalid or a memory allocation failed.
  */
 xmlNodePtr
-xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
-    xmlNodePtr parent;
-
-    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddSibling : cur == NULL\n");
-#endif
-	return(NULL);
-    }
-
-    if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddSibling : elem == NULL\n");
-#endif
-	return(NULL);
-    }
-
-    if (cur == elem) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddSibling : cur == elem\n");
-#endif
+xmlAddSibling(xmlNodePtr node, xmlNodePtr cur) {
+    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
+        (cur == NULL) || (cur->type == XML_NAMESPACE_DECL) ||
+        (cur == node))
 	return(NULL);
-    }
 
     /*
      * Constant time is we can rely on the ->parent->last to find
      * the last sibling.
      */
-    if ((cur->type != XML_ATTRIBUTE_NODE) && (cur->parent != NULL) &&
-	(cur->parent->children != NULL) &&
-	(cur->parent->last != NULL) &&
-	(cur->parent->last->next == NULL)) {
-	cur = cur->parent->last;
+    if ((node->type != XML_ATTRIBUTE_NODE) && (node->parent != NULL)) {
+        if (node->parent->last != NULL)
+	    node = node->parent->last;
     } else {
-	while (cur->next != NULL) cur = cur->next;
-    }
-
-    xmlUnlinkNode(elem);
-
-    if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE) &&
-        (cur->name == elem->name)) {
-	xmlNodeAddContent(cur, elem->content);
-	xmlFreeNode(elem);
-	return(cur);
-    } else if (elem->type == XML_ATTRIBUTE_NODE) {
-		return xmlAddPropSibling(cur, cur, elem);
+	while (node->next != NULL)
+            node = node->next;
     }
 
-    if (elem->doc != cur->doc) {
-	xmlSetTreeDoc(elem, cur->doc);
-    }
-    parent = cur->parent;
-    elem->prev = cur;
-    elem->next = NULL;
-    elem->parent = parent;
-    cur->next = elem;
-    if (parent != NULL)
-	parent->last = elem;
+    if (cur == node)
+        return(cur);
 
-    return(elem);
+    return(xmlInsertNode(node->doc, cur, node->parent, node, NULL, 1));
 }
 
 /**
@@ -3302,40 +3269,35 @@ xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
  * @parent:  the parent node
  * @cur:  the first node in the list
  *
- * Add a list of node at the end of the child list of the parent
- * merging adjacent TEXT nodes (@cur may be freed)
+ * Append a node list to another node.
  *
- * See the note regarding namespaces in xmlAddChild.
+ * See xmlAddChild.
  *
  * Returns the last child or NULL in case of error.
  */
 xmlNodePtr
 xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
+    xmlNodePtr iter;
     xmlNodePtr prev;
+    int oom;
 
     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddChildList : parent == NULL\n");
-#endif
 	return(NULL);
     }
 
     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddChildList : child == NULL\n");
-#endif
 	return(NULL);
     }
 
-    if ((cur->doc != NULL) && (parent->doc != NULL) &&
-        (cur->doc != parent->doc)) {
-#ifdef DEBUG_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"Elements moved to a different document\n");
-#endif
+    oom = 0;
+    for (iter = cur; iter != NULL; iter = iter->next) {
+	if (iter->doc != parent->doc) {
+	    if (xmlSetTreeDoc(iter, parent->doc) < 0)
+                oom = 1;
+	}
     }
+    if (oom)
+        return(NULL);
 
     /*
      * add the first element at the end of the children list.
@@ -3344,40 +3306,36 @@ xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
     if (parent->children == NULL) {
         parent->children = cur;
     } else {
+        prev = parent->last;
+
 	/*
 	 * If cur and parent->last both are TEXT nodes, then merge them.
 	 */
 	if ((cur->type == XML_TEXT_NODE) &&
-	    (parent->last->type == XML_TEXT_NODE) &&
-	    (cur->name == parent->last->name)) {
-	    xmlNodeAddContent(parent->last, cur->content);
+	    (prev->type == XML_TEXT_NODE) &&
+	    (cur->name == prev->name)) {
+            xmlNodePtr next;
+
+            if (xmlTextAddContent(prev, cur->content, -1) < 0)
+                return(NULL);
+            next = cur->next;
+	    xmlFreeNode(cur);
 	    /*
 	     * if it's the only child, nothing more to be done.
 	     */
-	    if (cur->next == NULL) {
-		xmlFreeNode(cur);
-		return(parent->last);
-	    }
-	    prev = cur;
-	    cur = cur->next;
-	    xmlFreeNode(prev);
+	    if (next == NULL)
+		return(prev);
+	    cur = next;
 	}
-        prev = parent->last;
+
 	prev->next = cur;
 	cur->prev = prev;
     }
     while (cur->next != NULL) {
 	cur->parent = parent;
-	if (cur->doc != parent->doc) {
-	    xmlSetTreeDoc(cur, parent->doc);
-	}
         cur = cur->next;
     }
     cur->parent = parent;
-    /* the parent may not be linked to a doc ! */
-    if (cur->doc != parent->doc) {
-        xmlSetTreeDoc(cur, parent->doc);
-    }
     parent->last = cur;
 
     return(cur);
@@ -3388,150 +3346,91 @@ xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
  * @parent:  the parent node
  * @cur:  the child node
  *
- * Add a new node to @parent, at the end of the child (or property) list
- * merging adjacent TEXT nodes (in which case @cur is freed)
- * If the new node is ATTRIBUTE, it is added into properties instead of children.
- * If there is an attribute with equal name, it is first destroyed.
+ * Unlink @cur and append it to the children of @parent.
+ *
+ * If @cur is a text node, it may be merged with an adjacent text
+ * node and freed. In this case the text node containing the merged
+ * content is returned.
+ *
+ * If @cur is an attribute node, it is appended to the attributes of
+ * @parent. If the attribute list contains an attribute with a name
+ * matching @elem, the old attribute is destroyed.
+ *
+ * General notes:
+ *
+ * Move operations like xmlAddChild can cause element or attribute
+ * nodes to reference namespaces that aren't declared in one of
+ * their ancestors. This can lead to use-after-free errors if the
+ * elements containing the declarations are freed later, especially
+ * when moving nodes from one document to another. You should
+ * consider calling xmlReconciliateNs after a move operation to
+ * normalize namespaces. Another option is to call
+ * xmlDOMWrapAdoptNode with the target parent before moving a node.
  *
- * All tree manipulation functions can safely move nodes within a document.
- * But when moving nodes from one document to another, references to
- * namespaces in element or attribute nodes are NOT fixed. In this case,
- * you MUST call xmlReconciliateNs after the move operation to avoid
- * memory errors.
+ * For the most part, move operations don't check whether the
+ * resulting tree structure is valid. Users must make sure that
+ * parent nodes only receive children of valid types. Inserted
+ * child nodes must never be an ancestor of the parent node to
+ * avoid cycles in the tree structure. In general, only
+ * document, document fragments, elements and attributes
+ * should be used as parent nodes.
  *
- * Returns the child or NULL in case of error.
+ * When moving a node between documents and a memory allocation
+ * fails, the node's content will be corrupted and it will be
+ * unlinked. In this case, the node must be freed manually.
+ *
+ * Moving DTDs between documents isn't supported.
+ *
+ * Returns @elem or a sibling if @elem was merged. Returns NULL
+ * if arguments are invalid or a memory allocation failed.
  */
 xmlNodePtr
 xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
     xmlNodePtr prev;
 
-    if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddChild : parent == NULL\n");
-#endif
-	return(NULL);
-    }
-
-    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddChild : child == NULL\n");
-#endif
-	return(NULL);
-    }
-
-    if (parent == cur) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddChild : parent == cur\n");
-#endif
-	return(NULL);
-    }
-    /*
-     * If cur is a TEXT node, merge its content with adjacent TEXT nodes
-     * cur is then freed.
-     */
-    if (cur->type == XML_TEXT_NODE) {
-	if ((parent->type == XML_TEXT_NODE) &&
-	    (parent->content != NULL) &&
-	    (parent->name == cur->name)) {
-	    xmlNodeAddContent(parent, cur->content);
-	    xmlFreeNode(cur);
-	    return(parent);
-	}
-	if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) &&
-	    (parent->last->name == cur->name) &&
-	    (parent->last != cur)) {
-	    xmlNodeAddContent(parent->last, cur->content);
-	    xmlFreeNode(cur);
-	    return(parent->last);
-	}
-    }
+    if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL) ||
+        (cur == NULL) || (cur->type == XML_NAMESPACE_DECL) ||
+        (parent == cur))
+        return(NULL);
 
     /*
-     * add the new element at the end of the children list.
+     * If parent is a text node, call xmlTextAddContent. This
+     * undocumented quirk should probably be removed.
      */
-    prev = cur->parent;
-    cur->parent = parent;
-    if (cur->doc != parent->doc) {
-	xmlSetTreeDoc(cur, parent->doc);
+    if (parent->type == XML_TEXT_NODE) {
+        if (xmlTextAddContent(parent, cur->content, -1) < 0)
+            return(NULL);
+        xmlFreeNode(cur);
+        return(parent);
     }
-    /* this check prevents a loop on tree-traversions if a developer
-     * tries to add a node to its parent multiple times
-     */
-    if (prev == parent)
-	return(cur);
 
-    /*
-     * Coalescing
-     */
-    if ((parent->type == XML_TEXT_NODE) &&
-	(parent->content != NULL) &&
-	(parent != cur)) {
-	xmlNodeAddContent(parent, cur->content);
-	xmlFreeNode(cur);
-	return(parent);
-    }
     if (cur->type == XML_ATTRIBUTE_NODE) {
-		if (parent->type != XML_ELEMENT_NODE)
-			return(NULL);
-	if (parent->properties != NULL) {
-	    /* check if an attribute with the same name exists */
-	    xmlAttrPtr lastattr;
-
-	    if (cur->ns == NULL)
-		lastattr = xmlHasNsProp(parent, cur->name, NULL);
-	    else
-		lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href);
-	    if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur) && (lastattr->type != XML_ATTRIBUTE_DECL)) {
-		/* different instance, destroy it (attributes must be unique) */
-			xmlUnlinkNode((xmlNodePtr) lastattr);
-		xmlFreeProp(lastattr);
-	    }
-		if (lastattr == (xmlAttrPtr) cur)
-			return(cur);
-
-	}
-	if (parent->properties == NULL) {
-	    parent->properties = (xmlAttrPtr) cur;
-	} else {
-	    /* find the end */
-	    xmlAttrPtr lastattr = parent->properties;
-	    while (lastattr->next != NULL) {
-		lastattr = lastattr->next;
-	    }
-	    lastattr->next = (xmlAttrPtr) cur;
-	    ((xmlAttrPtr) cur)->prev = lastattr;
-	}
+        prev = (xmlNodePtr) parent->properties;
+        if (prev != NULL) {
+            while (prev->next != NULL)
+                prev = prev->next;
+        }
     } else {
-	if (parent->children == NULL) {
-	    parent->children = cur;
-	    parent->last = cur;
-	} else {
-	    prev = parent->last;
-	    prev->next = cur;
-	    cur->prev = prev;
-	    parent->last = cur;
-	}
+        prev = parent->last;
     }
-    return(cur);
+
+    if (cur == prev)
+        return(cur);
+
+    return(xmlInsertNode(parent->doc, cur, parent, prev, NULL, 1));
 }
 
 /**
  * xmlGetLastChild:
  * @parent:  the parent node
  *
- * Search the last child of a node.
- * Returns the last child or NULL if none.
+ * Find the last child of a node.
+ *
+ * Returns the last child or NULL if parent has no children.
  */
 xmlNodePtr
 xmlGetLastChild(const xmlNode *parent) {
     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlGetLastChild : parent == NULL\n");
-#endif
 	return(NULL);
     }
     return(parent->last);
@@ -3546,13 +3445,12 @@ xmlGetLastChild(const xmlNode *parent) {
  * xmlChildElementCount:
  * @parent: the parent node
  *
- * Finds the current number of child nodes of that element which are
- * element nodes.
- * Note the handling of entities references is different than in
- * the W3C DOM element traversal spec since we don't have back reference
- * from entities content to entities references.
+ * Count the number of child nodes which are elements.
  *
- * Returns the count of element child or 0 if not available
+ * Note that entity references are not expanded.
+ *
+ * Returns the number of element children or 0 if arguments are
+ * invalid.
  */
 unsigned long
 xmlChildElementCount(xmlNodePtr parent) {
@@ -3563,10 +3461,10 @@ xmlChildElementCount(xmlNodePtr parent) {
         return(0);
     switch (parent->type) {
         case XML_ELEMENT_NODE:
-        case XML_ENTITY_NODE:
         case XML_DOCUMENT_NODE:
         case XML_DOCUMENT_FRAG_NODE:
         case XML_HTML_DOCUMENT_NODE:
+        case XML_ENTITY_DECL:
             cur = parent->children;
             break;
         default:
@@ -3584,12 +3482,11 @@ xmlChildElementCount(xmlNodePtr parent) {
  * xmlFirstElementChild:
  * @parent: the parent node
  *
- * Finds the first child node of that element which is a Element node
- * Note the handling of entities references is different than in
- * the W3C DOM element traversal spec since we don't have back reference
- * from entities content to entities references.
+ * Find the first child node which is an element.
  *
- * Returns the first element child or NULL if not available
+ * Note that entity references are not expanded.
+ *
+ * Returns the first element or NULL if parent has no children.
  */
 xmlNodePtr
 xmlFirstElementChild(xmlNodePtr parent) {
@@ -3599,10 +3496,10 @@ xmlFirstElementChild(xmlNodePtr parent) {
         return(NULL);
     switch (parent->type) {
         case XML_ELEMENT_NODE:
-        case XML_ENTITY_NODE:
         case XML_DOCUMENT_NODE:
         case XML_DOCUMENT_FRAG_NODE:
         case XML_HTML_DOCUMENT_NODE:
+        case XML_ENTITY_DECL:
             cur = parent->children;
             break;
         default:
@@ -3620,12 +3517,11 @@ xmlFirstElementChild(xmlNodePtr parent) {
  * xmlLastElementChild:
  * @parent: the parent node
  *
- * Finds the last child node of that element which is a Element node
- * Note the handling of entities references is different than in
- * the W3C DOM element traversal spec since we don't have back reference
- * from entities content to entities references.
+ * Find the last child node which is an element.
  *
- * Returns the last element child or NULL if not available
+ * Note that entity references are not expanded.
+ *
+ * Returns the last element or NULL if parent has no children.
  */
 xmlNodePtr
 xmlLastElementChild(xmlNodePtr parent) {
@@ -3635,10 +3531,10 @@ xmlLastElementChild(xmlNodePtr parent) {
         return(NULL);
     switch (parent->type) {
         case XML_ELEMENT_NODE:
-        case XML_ENTITY_NODE:
         case XML_DOCUMENT_NODE:
         case XML_DOCUMENT_FRAG_NODE:
         case XML_HTML_DOCUMENT_NODE:
+        case XML_ENTITY_DECL:
             cur = parent->last;
             break;
         default:
@@ -3656,13 +3552,11 @@ xmlLastElementChild(xmlNodePtr parent) {
  * xmlPreviousElementSibling:
  * @node: the current node
  *
- * Finds the first closest previous sibling of the node which is an
- * element node.
- * Note the handling of entities references is different than in
- * the W3C DOM element traversal spec since we don't have back reference
- * from entities content to entities references.
+ * Find the closest preceding sibling which is a element.
  *
- * Returns the previous element sibling or NULL if not available
+ * Note that entity references are not expanded.
+ *
+ * Returns the sibling or NULL if no sibling was found.
  */
 xmlNodePtr
 xmlPreviousElementSibling(xmlNodePtr node) {
@@ -3673,7 +3567,6 @@ xmlPreviousElementSibling(xmlNodePtr node) {
         case XML_TEXT_NODE:
         case XML_CDATA_SECTION_NODE:
         case XML_ENTITY_REF_NODE:
-        case XML_ENTITY_NODE:
         case XML_PI_NODE:
         case XML_COMMENT_NODE:
         case XML_XINCLUDE_START:
@@ -3695,13 +3588,11 @@ xmlPreviousElementSibling(xmlNodePtr node) {
  * xmlNextElementSibling:
  * @node: the current node
  *
- * Finds the first closest next sibling of the node which is an
- * element node.
- * Note the handling of entities references is different than in
- * the W3C DOM element traversal spec since we don't have back reference
- * from entities content to entities references.
+ * Find the closest following sibling which is a element.
+ *
+ * Note that entity references are not expanded.
  *
- * Returns the next element sibling or NULL if not available
+ * Returns the sibling or NULL if no sibling was found.
  */
 xmlNodePtr
 xmlNextElementSibling(xmlNodePtr node) {
@@ -3712,7 +3603,6 @@ xmlNextElementSibling(xmlNodePtr node) {
         case XML_TEXT_NODE:
         case XML_CDATA_SECTION_NODE:
         case XML_ENTITY_REF_NODE:
-        case XML_ENTITY_NODE:
         case XML_PI_NODE:
         case XML_COMMENT_NODE:
         case XML_DTD_NODE:
@@ -3737,8 +3627,7 @@ xmlNextElementSibling(xmlNodePtr node) {
  * xmlFreeNodeList:
  * @cur:  the first node in the list
  *
- * Free a node and all its siblings, this is a recursive behaviour, all
- * the children are freed too.
+ * Free a node list including all children.
  */
 void
 xmlFreeNodeList(xmlNodePtr cur) {
@@ -3768,8 +3657,14 @@ xmlFreeNodeList(xmlNodePtr cur) {
 	if ((cur->type == XML_DOCUMENT_NODE) ||
             (cur->type == XML_HTML_DOCUMENT_NODE)) {
             xmlFreeDoc((xmlDocPtr) cur);
-        } else if (cur->type != XML_DTD_NODE) {
-
+        } else if (cur->type == XML_DTD_NODE) {
+            /*
+             * TODO: We should consider freeing the DTD if it isn't
+             * referenced from doc->intSubset or doc->extSubset.
+             */
+            cur->prev = NULL;
+            cur->next = NULL;
+        } else {
 	    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
 		xmlDeregisterNodeDefaultValue(cur);
 
@@ -3820,8 +3715,10 @@ xmlFreeNodeList(xmlNodePtr cur) {
  * xmlFreeNode:
  * @cur:  the node
  *
- * Free a node, this is a recursive behaviour, all the children are freed too.
- * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
+ * Free a node including all the children.
+ *
+ * This doesn't unlink the node from the tree. Call xmlUnlinkNode first
+ * unless @cur is a root node.
  */
 void
 xmlFreeNode(xmlNodePtr cur) {
@@ -3842,17 +3739,16 @@ xmlFreeNode(xmlNodePtr cur) {
 	xmlFreeProp((xmlAttrPtr) cur);
 	return;
     }
+    if (cur->type == XML_ENTITY_DECL) {
+        xmlFreeEntity((xmlEntityPtr) cur);
+        return;
+    }
 
     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
 	xmlDeregisterNodeDefaultValue(cur);
 
     if (cur->doc != NULL) dict = cur->doc->dict;
 
-    if (cur->type == XML_ENTITY_DECL) {
-        xmlEntityPtr ent = (xmlEntityPtr) cur;
-	DICT_FREE(ent->SystemID);
-	DICT_FREE(ent->ExternalID);
-    }
     if ((cur->children != NULL) &&
 	(cur->type != XML_ENTITY_REF_NODE))
 	xmlFreeNodeList(cur->children);
@@ -3884,58 +3780,16 @@ xmlFreeNode(xmlNodePtr cur) {
 }
 
 /**
- * xmlUnlinkNode:
+ * xmlUnlinkNodeInternal:
  * @cur:  the node
  *
- * Unlink a node from it's current context, the node is not freed
- * If one need to free the node, use xmlFreeNode() routine after the
- * unlink to discard it.
- * Note that namespace nodes can't be unlinked as they do not have
- * pointer to their parent.
+ * Unlink a node from its tree.
+ *
+ * This function only unlinks the node from the tree. It doesn't
+ * clear references to DTD nodes.
  */
-void
-xmlUnlinkNode(xmlNodePtr cur) {
-    if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlUnlinkNode : node == NULL\n");
-#endif
-	return;
-    }
-    if (cur->type == XML_NAMESPACE_DECL)
-        return;
-    if (cur->type == XML_DTD_NODE) {
-	xmlDocPtr doc;
-	doc = cur->doc;
-	if (doc != NULL) {
-	    if (doc->intSubset == (xmlDtdPtr) cur)
-		doc->intSubset = NULL;
-	    if (doc->extSubset == (xmlDtdPtr) cur)
-		doc->extSubset = NULL;
-	}
-    }
-    if (cur->type == XML_ENTITY_DECL) {
-        xmlDocPtr doc;
-	doc = cur->doc;
-	if (doc != NULL) {
-	    if (doc->intSubset != NULL) {
-	        if (xmlHashLookup(doc->intSubset->entities, cur->name) == cur)
-		    xmlHashRemoveEntry(doc->intSubset->entities, cur->name,
-		                       NULL);
-	        if (xmlHashLookup(doc->intSubset->pentities, cur->name) == cur)
-		    xmlHashRemoveEntry(doc->intSubset->pentities, cur->name,
-		                       NULL);
-	    }
-	    if (doc->extSubset != NULL) {
-	        if (xmlHashLookup(doc->extSubset->entities, cur->name) == cur)
-		    xmlHashRemoveEntry(doc->extSubset->entities, cur->name,
-		                       NULL);
-	        if (xmlHashLookup(doc->extSubset->pentities, cur->name) == cur)
-		    xmlHashRemoveEntry(doc->extSubset->pentities, cur->name,
-		                       NULL);
-	    }
-	}
-    }
+static void
+xmlUnlinkNodeInternal(xmlNodePtr cur) {
     if (cur->parent != NULL) {
 	xmlNodePtr parent;
 	parent = cur->parent;
@@ -3950,61 +3804,89 @@ xmlUnlinkNode(xmlNodePtr cur) {
 	}
 	cur->parent = NULL;
     }
+
     if (cur->next != NULL)
         cur->next->prev = cur->prev;
     if (cur->prev != NULL)
         cur->prev->next = cur->next;
-    cur->next = cur->prev = NULL;
+    cur->next = NULL;
+    cur->prev = NULL;
+}
+
+/**
+ * xmlUnlinkNode:
+ * @cur:  the node
+ *
+ * Unlink a node from its tree.
+ *
+ * The node is not freed. Unless it is reinserted, it must be managed
+ * manually and freed eventually by calling xmlFreeNode.
+ */
+void
+xmlUnlinkNode(xmlNodePtr cur) {
+    if (cur == NULL)
+	return;
+
+    if (cur->type == XML_NAMESPACE_DECL)
+        return;
+
+    if (cur->type == XML_DTD_NODE) {
+	xmlDocPtr doc = cur->doc;
+
+	if (doc != NULL) {
+	    if (doc->intSubset == (xmlDtdPtr) cur)
+		doc->intSubset = NULL;
+	    if (doc->extSubset == (xmlDtdPtr) cur)
+		doc->extSubset = NULL;
+	}
+    }
+
+    if (cur->type == XML_ENTITY_DECL)
+        xmlRemoveEntity((xmlEntityPtr) cur);
+
+    xmlUnlinkNodeInternal(cur);
 }
 
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
 /**
  * xmlReplaceNode:
  * @old:  the old node
- * @cur:  the node
+ * @cur:  the node (optional)
  *
- * Unlink the old node from its current context, prune the new one
- * at the same place. If @cur was already inserted in a document it is
- * first unlinked from its existing context.
+ * Unlink the old node. If @cur is provided, it is unlinked and
+ * inserted in place of @old.
  *
- * See the note regarding namespaces in xmlAddChild.
+ * It is an error if @old has no parent.
  *
- * Returns the @old node
+ * Unlike xmlAddChild, this function doesn't merge text nodes or
+ * delete duplicate attributes.
+ *
+ * See the notes in xmlAddChild.
+ *
+ * Returns @old or NULL if arguments are invalid or a memory
+ * allocation failed.
  */
 xmlNodePtr
 xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
     if (old == cur) return(NULL);
     if ((old == NULL) || (old->type == XML_NAMESPACE_DECL) ||
         (old->parent == NULL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlReplaceNode : old == NULL or without parent\n");
-#endif
 	return(NULL);
     }
     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
+        /* Don't call xmlUnlinkNodeInternal to handle DTDs. */
 	xmlUnlinkNode(old);
 	return(old);
     }
-    if (cur == old) {
-	return(old);
-    }
     if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlReplaceNode : Trying to replace attribute node with other node type\n");
-#endif
 	return(old);
     }
     if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
-#endif
 	return(old);
     }
-    xmlUnlinkNode(cur);
-    xmlSetTreeDoc(cur, old->doc);
+    xmlUnlinkNodeInternal(cur);
+    if (xmlSetTreeDoc(cur, old->doc) < 0)
+        return(NULL);
     cur->parent = old->parent;
     cur->next = old->next;
     if (cur->next != NULL)
@@ -4039,9 +3921,10 @@ xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
  * xmlCopyNamespace:
  * @cur:  the namespace
  *
- * Do a copy of the namespace.
+ * Copy a namespace.
  *
- * Returns: a new #xmlNsPtr, or NULL in case of error.
+ * Returns the copied namespace or NULL if a memory allocation
+ * failed.
  */
 xmlNsPtr
 xmlCopyNamespace(xmlNsPtr cur) {
@@ -4053,10 +3936,6 @@ xmlCopyNamespace(xmlNsPtr cur) {
 	    ret = xmlNewNs(NULL, cur->href, cur->prefix);
 	    break;
 	default:
-#ifdef DEBUG_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "xmlCopyNamespace: invalid type %d\n", cur->type);
-#endif
 	    return(NULL);
     }
     return(ret);
@@ -4066,9 +3945,10 @@ xmlCopyNamespace(xmlNsPtr cur) {
  * xmlCopyNamespaceList:
  * @cur:  the first namespace
  *
- * Do a copy of an namespace list.
+ * Copy a namespace list.
  *
- * Returns: a new #xmlNsPtr, or NULL in case of error.
+ * Returns the head of the copied list or NULL if a memory
+ * allocation failed.
  */
 xmlNsPtr
 xmlCopyNamespaceList(xmlNsPtr cur) {
@@ -4077,6 +3957,10 @@ xmlCopyNamespaceList(xmlNsPtr cur) {
 
     while (cur != NULL) {
         q = xmlCopyNamespace(cur);
+        if (q == NULL) {
+            xmlFreeNsList(ret);
+            return(NULL);
+        }
 	if (p == NULL) {
 	    ret = p = q;
 	} else {
@@ -4088,12 +3972,9 @@ xmlCopyNamespaceList(xmlNsPtr cur) {
     return(ret);
 }
 
-static xmlNodePtr
-xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
-
 static xmlAttrPtr
 xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
-    xmlAttrPtr ret;
+    xmlAttrPtr ret = NULL;
 
     if (cur == NULL) return(NULL);
     if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
@@ -4113,15 +3994,20 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
 
     if ((cur->ns != NULL) && (target != NULL)) {
       xmlNsPtr ns;
+      int res;
 
-      ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
+      res = xmlSearchNsSafe(target, cur->ns->prefix, &ns);
+      if (res < 0)
+          goto error;
       if (ns == NULL) {
         /*
          * Humm, we are copying an element whose namespace is defined
          * out of the new tree scope. Search it in the original tree
          * and add it at the top of the new tree
          */
-        ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix);
+        res = xmlSearchNsSafe(cur->parent, cur->ns->prefix, &ns);
+        if (res < 0)
+          goto error;
         if (ns != NULL) {
           xmlNodePtr root = target;
           xmlNodePtr pred = NULL;
@@ -4135,6 +4021,8 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
             root = pred;
           }
           ret->ns = xmlNewNs(root, ns->href, ns->prefix);
+          if (ret->ns == NULL)
+              goto error;
         }
       } else {
         /*
@@ -4150,7 +4038,9 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
            * we are in trouble: we need a new reconciled namespace.
            * This is expensive
            */
-          ret->ns = xmlNewReconciledNs(target->doc, target, cur->ns);
+          ret->ns = xmlNewReconciledNs(target, cur->ns);
+          if (ret->ns == NULL)
+              goto error;
         }
       }
 
@@ -4161,6 +4051,8 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
 	xmlNodePtr tmp;
 
 	ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret);
+        if (ret->children == NULL)
+            goto error;
 	ret->last = NULL;
 	tmp = ret->children;
 	while (tmp != NULL) {
@@ -4173,20 +4065,31 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
     /*
      * Try to handle IDs
      */
-    if ((target!= NULL) && (cur!= NULL) &&
+    if ((target != NULL) && (cur != NULL) &&
 	(target->doc != NULL) && (cur->doc != NULL) &&
-	(cur->doc->ids != NULL) && (cur->parent != NULL)) {
-	if (xmlIsID(cur->doc, cur->parent, cur)) {
+        (cur->parent != NULL) &&
+        (cur->children != NULL)) {
+        int res = xmlIsID(cur->doc, cur->parent, cur);
+
+        if (res < 0)
+            goto error;
+	if (res != 0) {
 	    xmlChar *id;
 
-	    id = xmlNodeListGetString(cur->doc, cur->children, 1);
-	    if (id != NULL) {
-		xmlAddID(NULL, target->doc, id, ret);
-		xmlFree(id);
-	    }
+	    id = xmlNodeGetContent((xmlNodePtr) cur);
+	    if (id == NULL)
+                goto error;
+            res = xmlAddIDSafe(ret, id);
+	    xmlFree(id);
+            if (res < 0)
+                goto error;
 	}
     }
     return(ret);
+
+error:
+    xmlFreeProp(ret);
+    return(NULL);
 }
 
 /**
@@ -4194,9 +4097,14 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
  * @target:  the element where the attribute will be grafted
  * @cur:  the attribute
  *
- * Do a copy of the attribute.
+ * Create a copy of the attribute. This function sets the parent
+ * pointer of the copy to @target but doesn't set the attribute on
+ * the target element. Users should consider to set the attribute
+ * by calling xmlAddChild afterwards or reset the parent pointer to
+ * NULL.
  *
- * Returns: a new #xmlAttrPtr, or NULL in case of error.
+ * Returns the copied attribute or NULL if a memory allocation
+ * failed.
  */
 xmlAttrPtr
 xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
@@ -4208,9 +4116,12 @@ xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
  * @target:  the element where the attributes will be grafted
  * @cur:  the first attribute
  *
- * Do a copy of an attribute list.
+ * Create a copy of an attribute list. This function sets the
+ * parent pointers of the copied attributes to @target but doesn't
+ * set the attributes on the target element.
  *
- * Returns: a new #xmlAttrPtr, or NULL in case of error.
+ * Returns the head of the copied list or NULL if a memory
+ * allocation failed.
  */
 xmlAttrPtr
 xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
@@ -4221,8 +4132,10 @@ xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
         return(NULL);
     while (cur != NULL) {
         q = xmlCopyProp(target, cur);
-	if (q == NULL)
+	if (q == NULL) {
+            xmlFreePropList(ret);
 	    return(NULL);
+        }
 	if (p == NULL) {
 	    ret = p = q;
 	} else {
@@ -4254,7 +4167,18 @@ xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
  * namespace info, but don't recurse on children.
  */
 
-static xmlNodePtr
+/**
+ * xmlStaticCopyNode:
+ * @node:  source node
+ * @doc:  target document
+ * @parent:  target parent
+ * @extended:  flags
+ *
+ * Copy a node.
+ *
+ * Returns the copy or NULL if a memory allocation failed.
+ */
+xmlNodePtr
 xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
                   int extended) {
     xmlNodePtr ret;
@@ -4266,7 +4190,6 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
         case XML_ELEMENT_NODE:
         case XML_DOCUMENT_FRAG_NODE:
         case XML_ENTITY_REF_NODE:
-        case XML_ENTITY_NODE:
         case XML_PI_NODE:
         case XML_COMMENT_NODE:
         case XML_XINCLUDE_START:
@@ -4282,12 +4205,7 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
 #ifdef LIBXML_TREE_ENABLED
 	    return((xmlNodePtr) xmlCopyDoc((xmlDocPtr) node, extended));
 #endif /* LIBXML_TREE_ENABLED */
-        case XML_DOCUMENT_TYPE_NODE:
-        case XML_NOTATION_NODE:
-        case XML_DTD_NODE:
-        case XML_ELEMENT_DECL:
-        case XML_ATTRIBUTE_DECL:
-        case XML_ENTITY_DECL:
+        default:
             return(NULL);
     }
 
@@ -4295,10 +4213,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
      * Allocate a new node and fill the fields.
      */
     ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-    if (ret == NULL) {
-	xmlTreeErrMemory("copying node");
+    if (ret == NULL)
 	return(NULL);
-    }
     memset(ret, 0, sizeof(xmlNode));
     ret->type = node->type;
 
@@ -4315,6 +4231,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
 	    ret->name = xmlDictLookup(doc->dict, node->name, -1);
 	else
 	    ret->name = xmlStrdup(node->name);
+        if (ret->name == NULL)
+            goto error;
     }
     if ((node->type != XML_ELEMENT_NODE) &&
 	(node->content != NULL) &&
@@ -4322,60 +4240,51 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
 	(node->type != XML_XINCLUDE_END) &&
 	(node->type != XML_XINCLUDE_START)) {
 	ret->content = xmlStrdup(node->content);
+        if (ret->content == NULL)
+            goto error;
     }else{
       if (node->type == XML_ELEMENT_NODE)
         ret->line = node->line;
     }
-    if (parent != NULL) {
-	xmlNodePtr tmp;
-
-	/*
-	 * this is a tricky part for the node register thing:
-	 * in case ret does get coalesced in xmlAddChild
-	 * the deregister-node callback is called; so we register ret now already
-	 */
-	if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
-	    xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
-
-        /*
-         * Note that since ret->parent is already set, xmlAddChild will
-         * return early and not actually insert the node. It will only
-         * coalesce text nodes and unnecessarily call xmlSetTreeDoc.
-         * Assuming that the subtree to be copied always has its text
-         * nodes coalesced, the somewhat confusing call to xmlAddChild
-         * could be removed.
-         */
-        tmp = xmlAddChild(parent, ret);
-	/* node could have coalesced */
-	if (tmp != ret)
-	    return(tmp);
-    }
 
     if (!extended)
 	goto out;
     if (((node->type == XML_ELEMENT_NODE) ||
-         (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL))
+         (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL)) {
         ret->nsDef = xmlCopyNamespaceList(node->nsDef);
+        if (ret->nsDef == NULL)
+            goto error;
+    }
 
-    if (node->ns != NULL) {
-        xmlNsPtr ns;
+    if ((node->type == XML_ELEMENT_NODE) && (node->ns != NULL)) {
+        xmlNsPtr ns = NULL;
+        int res;
 
-	ns = xmlSearchNs(doc, ret, node->ns->prefix);
+	res = xmlSearchNsSafe(ret, node->ns->prefix, &ns);
+        if (res < 0)
+            goto error;
 	if (ns == NULL) {
 	    /*
 	     * Humm, we are copying an element whose namespace is defined
 	     * out of the new tree scope. Search it in the original tree
-	     * and add it at the top of the new tree
+	     * and add it at the top of the new tree.
+             *
+             * TODO: Searching the original tree seems unnecessary. We
+             * already have a namespace URI.
 	     */
-	    ns = xmlSearchNs(node->doc, node, node->ns->prefix);
+	    res = xmlSearchNsSafe(node, node->ns->prefix, &ns);
+            if (res < 0)
+                goto error;
 	    if (ns != NULL) {
 	        xmlNodePtr root = ret;
 
 		while (root->parent != NULL) root = root->parent;
 		ret->ns = xmlNewNs(root, ns->href, ns->prefix);
-		} else {
-			ret->ns = xmlNewReconciledNs(doc, ret, node->ns);
+            } else {
+                ret->ns = xmlNewReconciledNs(ret, node->ns);
 	    }
+            if (ret->ns == NULL)
+                goto error;
 	} else {
 	    /*
 	     * reference the existing namespace definition in our own tree.
@@ -4383,9 +4292,11 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
 	    ret->ns = ns;
 	}
     }
-    if (((node->type == XML_ELEMENT_NODE) ||
-         (node->type == XML_XINCLUDE_START)) && (node->properties != NULL))
+    if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL)) {
         ret->properties = xmlCopyPropList(ret, node->properties);
+        if (ret->properties == NULL)
+            goto error;
+    }
     if (node->type == XML_ENTITY_REF_NODE) {
 	if ((doc == NULL) || (node->doc != doc)) {
 	    /*
@@ -4406,10 +4317,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
         insert = ret;
         while (cur != NULL) {
             xmlNodePtr copy = xmlStaticCopyNode(cur, doc, insert, 2);
-            if (copy == NULL) {
-                xmlFreeNode(ret);
-                return(NULL);
-            }
+            if (copy == NULL)
+                goto error;
 
             /* Check for coalesced text nodes */
             if (insert->last != copy) {
@@ -4446,40 +4355,78 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
     }
 
 out:
-    /* if parent != NULL we already registered the node above */
-    if ((parent == NULL) &&
-        ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)))
+    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
     return(ret);
+
+error:
+    xmlFreeNode(ret);
+    return(NULL);
 }
 
-static xmlNodePtr
+/**
+ * xmlStaticCopyNodeList:
+ * @node:  node to copy
+ * @doc:  target document
+ * @parent:  target node (optional)
+ *
+ * Copy a node list. If @parent is provided, sets the parent pointer
+ * of the copied nodes, but doesn't update the children and last
+ * pointer of @parent.
+ *
+ * Returns a the copy or NULL in case of error.
+ */
+xmlNodePtr
 xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
     xmlNodePtr ret = NULL;
     xmlNodePtr p = NULL,q;
+    xmlDtdPtr newSubset = NULL;
+    int linkedSubset = 0;
 
     while (node != NULL) {
+        xmlNodePtr next = node->next;
+
 #ifdef LIBXML_TREE_ENABLED
 	if (node->type == XML_DTD_NODE ) {
 	    if (doc == NULL) {
-		node = node->next;
+		node = next;
 		continue;
 	    }
-	    if (doc->intSubset == NULL) {
+	    if ((doc->intSubset == NULL) && (newSubset == NULL)) {
 		q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
-		if (q == NULL) return(NULL);
-		q->doc = doc;
+		if (q == NULL) goto error;
+                /* Can't fail on DTD */
+		xmlSetTreeDoc(q, doc);
 		q->parent = parent;
-		doc->intSubset = (xmlDtdPtr) q;
-		xmlAddChild(parent, q);
+		newSubset = (xmlDtdPtr) q;
 	    } else {
+                /*
+                 * We don't allow multiple internal subsets in a document,
+                 * so we move the DTD instead of creating a copy.
+                 */
+                linkedSubset = 1;
 		q = (xmlNodePtr) doc->intSubset;
-		xmlAddChild(parent, q);
+                /* Unlink */
+                if (q->prev == NULL) {
+                    if (q->parent != NULL)
+                        q->parent->children = q->next;
+                } else {
+                    q->prev->next = q->next;
+                }
+                if (q->next == NULL) {
+                    if (q->parent != NULL)
+                        q->parent->last = q->prev;
+                } else {
+                    q->next->prev = q->prev;
+                }
+                q->parent = parent;
+                q->next = NULL;
+                q->prev = NULL;
 	    }
 	} else
 #endif /* LIBXML_TREE_ENABLED */
 	    q = xmlStaticCopyNode(node, doc, parent, 1);
-	if (q == NULL) return(NULL);
+	if (q == NULL) goto error;
 	if (ret == NULL) {
 	    q->prev = NULL;
 	    ret = p = q;
@@ -4489,9 +4436,20 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
 	    q->prev = p;
 	    p = q;
 	}
-	node = node->next;
+	node = next;
     }
+    if ((doc != NULL) && (newSubset != NULL))
+        doc->intSubset = newSubset;
     return(ret);
+error:
+    xmlFreeNodeList(ret);
+    if (newSubset != NULL)
+        xmlFreeDtd(newSubset);
+    if (linkedSubset != 0) {
+        doc->intSubset->next = NULL;
+        doc->intSubset->prev = NULL;
+    }
+    return(NULL);
 }
 
 /**
@@ -4501,9 +4459,11 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
  *			when applicable)
  *		if 2 copy properties and namespaces (when applicable)
  *
- * Do a copy of the node.
+ * Copy a node.
+ *
+ * Use of this function is DISCOURAGED in favor of xmlDocCopyNode.
  *
- * Returns: a new #xmlNodePtr, or NULL in case of error.
+ * Returns the copied node or NULL if a memory allocation failed.
  */
 xmlNodePtr
 xmlCopyNode(xmlNodePtr node, int extended) {
@@ -4521,9 +4481,9 @@ xmlCopyNode(xmlNodePtr node, int extended) {
  *			when applicable)
  *		if 2 copy properties and namespaces (when applicable)
  *
- * Do a copy of the node to a given document.
+ * Copy a node into another document.
  *
- * Returns: a new #xmlNodePtr, or NULL in case of error.
+ * Returns the copied node or NULL if a memory allocation failed.
  */
 xmlNodePtr
 xmlDocCopyNode(xmlNodePtr node, xmlDocPtr doc, int extended) {
@@ -4538,9 +4498,10 @@ xmlDocCopyNode(xmlNodePtr node, xmlDocPtr doc, int extended) {
  * @doc: the target document
  * @node:  the first node in the list.
  *
- * Do a recursive copy of the node list.
+ * Copy a node list and all children into a new document.
  *
- * Returns: a new #xmlNodePtr, or NULL in case of error.
+ * Returns the head of the copied list or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, xmlNodePtr node) {
     xmlNodePtr ret = xmlStaticCopyNodeList(node, doc, NULL);
@@ -4551,10 +4512,12 @@ xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, xmlNodePtr node) {
  * xmlCopyNodeList:
  * @node:  the first node in the list.
  *
- * Do a recursive copy of the node list.
- * Use xmlDocCopyNodeList() if possible to ensure string interning.
+ * Copy a node list and all children.
  *
- * Returns: a new #xmlNodePtr, or NULL in case of error.
+ * Use of this function is DISCOURAGED in favor of xmlDocCopyNodeList.
+ *
+ * Returns the head of the copied list or NULL if a memory
+ * allocation failed.
  */
 xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
     xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
@@ -4564,11 +4527,11 @@ xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
 #if defined(LIBXML_TREE_ENABLED)
 /**
  * xmlCopyDtd:
- * @dtd:  the dtd
+ * @dtd:  the DTD
  *
- * Do a copy of the dtd.
+ * Copy a DTD.
  *
- * Returns: a new #xmlDtdPtr, or NULL in case of error.
+ * Returns the copied DTD or NULL if a memory allocation failed.
  */
 xmlDtdPtr
 xmlCopyDtd(xmlDtdPtr dtd) {
@@ -4578,21 +4541,36 @@ xmlCopyDtd(xmlDtdPtr dtd) {
     if (dtd == NULL) return(NULL);
     ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
     if (ret == NULL) return(NULL);
-    if (dtd->entities != NULL)
+    if (dtd->entities != NULL) {
         ret->entities = (void *) xmlCopyEntitiesTable(
 	                    (xmlEntitiesTablePtr) dtd->entities);
-    if (dtd->notations != NULL)
+        if (ret->entities == NULL)
+            goto error;
+    }
+    if (dtd->notations != NULL) {
         ret->notations = (void *) xmlCopyNotationTable(
 	                    (xmlNotationTablePtr) dtd->notations);
-    if (dtd->elements != NULL)
+        if (ret->notations == NULL)
+            goto error;
+    }
+    if (dtd->elements != NULL) {
         ret->elements = (void *) xmlCopyElementTable(
 	                    (xmlElementTablePtr) dtd->elements);
-    if (dtd->attributes != NULL)
+        if (ret->elements == NULL)
+            goto error;
+    }
+    if (dtd->attributes != NULL) {
         ret->attributes = (void *) xmlCopyAttributeTable(
 	                    (xmlAttributeTablePtr) dtd->attributes);
-    if (dtd->pentities != NULL)
+        if (ret->attributes == NULL)
+            goto error;
+    }
+    if (dtd->pentities != NULL) {
 	ret->pentities = (void *) xmlCopyEntitiesTable(
 			    (xmlEntitiesTablePtr) dtd->pentities);
+        if (ret->pentities == NULL)
+            goto error;
+    }
 
     cur = dtd->children;
     while (cur != NULL) {
@@ -4624,6 +4602,8 @@ xmlCopyDtd(xmlDtdPtr dtd) {
 		xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix);
 	} else if (cur->type == XML_COMMENT_NODE) {
 	    q = xmlCopyNode(cur, 0);
+            if (q == NULL)
+                goto error;
 	}
 
 	if (q == NULL) {
@@ -4645,6 +4625,10 @@ xmlCopyDtd(xmlDtdPtr dtd) {
     }
 
     return(ret);
+
+error:
+    xmlFreeDtd(ret);
+    return(NULL);
 }
 #endif
 
@@ -4654,10 +4638,11 @@ xmlCopyDtd(xmlDtdPtr dtd) {
  * @doc:  the document
  * @recursive:  if not zero do a recursive copy.
  *
- * Do a copy of the document info. If recursive, the content tree will
+ * Copy a document. If recursive, the content tree will
  * be copied too as well as DTD, namespaces and entities.
  *
- * Returns: a new #xmlDocPtr, or NULL in case of error.
+ * Returns the copied document or NULL if a memory allocation
+ * failed.
  */
 xmlDocPtr
 xmlCopyDoc(xmlDocPtr doc, int recursive) {
@@ -4667,12 +4652,21 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) {
     ret = xmlNewDoc(doc->version);
     if (ret == NULL) return(NULL);
     ret->type = doc->type;
-    if (doc->name != NULL)
+    if (doc->name != NULL) {
         ret->name = xmlMemStrdup(doc->name);
-    if (doc->encoding != NULL)
+        if (ret->name == NULL)
+            goto error;
+    }
+    if (doc->encoding != NULL) {
         ret->encoding = xmlStrdup(doc->encoding);
-    if (doc->URL != NULL)
+        if (ret->encoding == NULL)
+            goto error;
+    }
+    if (doc->URL != NULL) {
         ret->URL = xmlStrdup(doc->URL);
+        if (ret->URL == NULL)
+            goto error;
+    }
     ret->charset = doc->charset;
     ret->compression = doc->compression;
     ret->standalone = doc->standalone;
@@ -4683,21 +4677,24 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) {
 #ifdef LIBXML_TREE_ENABLED
     if (doc->intSubset != NULL) {
         ret->intSubset = xmlCopyDtd(doc->intSubset);
-	if (ret->intSubset == NULL) {
-	    xmlFreeDoc(ret);
-	    return(NULL);
-	}
+	if (ret->intSubset == NULL)
+            goto error;
+        /* Can't fail on DTD */
 	xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret);
-	ret->intSubset->parent = ret;
     }
 #endif
-    if (doc->oldNs != NULL)
+    if (doc->oldNs != NULL) {
         ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
+        if (ret->oldNs == NULL)
+            goto error;
+    }
     if (doc->children != NULL) {
 	xmlNodePtr tmp;
 
 	ret->children = xmlStaticCopyNodeList(doc->children, ret,
 		                               (xmlNodePtr)ret);
+        if (ret->children == NULL)
+            goto error;
 	ret->last = NULL;
 	tmp = ret->children;
 	while (tmp != NULL) {
@@ -4707,6 +4704,10 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) {
 	}
     }
     return(ret);
+
+error:
+    xmlFreeDoc(ret);
+    return(NULL);
 }
 #endif /* LIBXML_TREE_ENABLED */
 
@@ -4808,14 +4809,11 @@ xmlGetNodePath(const xmlNode *node)
         return (NULL);
 
     buf_len = 500;
-    buffer = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar));
-    if (buffer == NULL) {
-	xmlTreeErrMemory("getting node path");
+    buffer = (xmlChar *) xmlMallocAtomic(buf_len);
+    if (buffer == NULL)
         return (NULL);
-    }
-    buf = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar));
+    buf = (xmlChar *) xmlMallocAtomic(buf_len);
     if (buf == NULL) {
-	xmlTreeErrMemory("getting node path");
         xmlFree(buffer);
         return (NULL);
     }
@@ -5002,7 +5000,6 @@ xmlGetNodePath(const xmlNode *node)
                 2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20;
             temp = (xmlChar *) xmlRealloc(buffer, buf_len);
             if (temp == NULL) {
-		xmlTreeErrMemory("getting node path");
                 xmlFree(buf);
                 xmlFree(buffer);
                 return (NULL);
@@ -5010,7 +5007,6 @@ xmlGetNodePath(const xmlNode *node)
             buffer = temp;
             temp = (xmlChar *) xmlRealloc(buf, buf_len);
             if (temp == NULL) {
-		xmlTreeErrMemory("getting node path");
                 xmlFree(buf);
                 xmlFree(buffer);
                 return (NULL);
@@ -5038,7 +5034,7 @@ xmlGetNodePath(const xmlNode *node)
  * Get the root element of the document (doc->children is a list
  * containing possibly comments, PIs, etc ...).
  *
- * Returns the #xmlNodePtr for the root or NULL
+ * Returns the root element or NULL if no element was found.
  */
 xmlNodePtr
 xmlDocGetRootElement(const xmlDoc *doc) {
@@ -5064,7 +5060,10 @@ xmlDocGetRootElement(const xmlDoc *doc) {
  * Set the root element of the document (doc->children is a list
  * containing possibly comments, PIs, etc ...).
  *
- * Returns the old root element if any was found, NULL if root was NULL
+ * @root must be an element node. It is unlinked before insertion.
+ *
+ * Returns the unlinked old root element or NULL if the document
+ * didn't have a root element or a memory allocation failed.
  */
 xmlNodePtr
 xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
@@ -5073,15 +5072,18 @@ xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
     if (doc == NULL) return(NULL);
     if ((root == NULL) || (root->type == XML_NAMESPACE_DECL))
 	return(NULL);
-    xmlUnlinkNode(root);
-    xmlSetTreeDoc(root, doc);
-    root->parent = (xmlNodePtr) doc;
     old = doc->children;
     while (old != NULL) {
 	if (old->type == XML_ELEMENT_NODE)
 	    break;
         old = old->next;
     }
+    if (old == root)
+        return(old);
+    xmlUnlinkNodeInternal(root);
+    if (xmlSetTreeDoc(root, doc) < 0)
+        return(NULL);
+    root->parent = (xmlNodePtr) doc;
     if (old == NULL) {
 	if (doc->children == NULL) {
 	    doc->children = root;
@@ -5104,40 +5106,27 @@ xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
  *
  * Set the language of a node, i.e. the values of the xml:lang
  * attribute.
+ *
+ * Return 0 on success, 1 if arguments are invalid, -1 if a
+ * memory allocation failed.
  */
-void
+int
 xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
     xmlNsPtr ns;
+    xmlAttrPtr attr;
+    int res;
 
-    if (cur == NULL) return;
-    switch(cur->type) {
-        case XML_TEXT_NODE:
-        case XML_CDATA_SECTION_NODE:
-        case XML_COMMENT_NODE:
-        case XML_DOCUMENT_NODE:
-        case XML_DOCUMENT_TYPE_NODE:
-        case XML_DOCUMENT_FRAG_NODE:
-        case XML_NOTATION_NODE:
-        case XML_HTML_DOCUMENT_NODE:
-        case XML_DTD_NODE:
-        case XML_ELEMENT_DECL:
-        case XML_ATTRIBUTE_DECL:
-        case XML_ENTITY_DECL:
-        case XML_PI_NODE:
-        case XML_ENTITY_REF_NODE:
-        case XML_ENTITY_NODE:
-	case XML_NAMESPACE_DECL:
-	case XML_XINCLUDE_START:
-	case XML_XINCLUDE_END:
-	    return;
-        case XML_ELEMENT_NODE:
-        case XML_ATTRIBUTE_NODE:
-	    break;
-    }
-    ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
-    if (ns == NULL)
-	return;
-    xmlSetNsProp(cur, ns, BAD_CAST "lang", lang);
+    if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
+        return(1);
+
+    res = xmlSearchNsByHrefSafe(cur, XML_XML_NAMESPACE, &ns);
+    if (res != 0)
+        return(res);
+    attr = xmlSetNsProp(cur, ns, BAD_CAST "lang", lang);
+    if (attr == NULL)
+        return(-1);
+
+    return(0);
 }
 #endif /* LIBXML_TREE_ENABLED */
 
@@ -5154,15 +5143,22 @@ xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
 xmlChar *
 xmlNodeGetLang(const xmlNode *cur) {
     xmlChar *lang;
+    int res;
 
     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
         return(NULL);
+
     while (cur != NULL) {
-        lang = xmlGetNsProp(cur, BAD_CAST "lang", XML_XML_NAMESPACE);
+        res = xmlNodeGetAttrValue(cur, BAD_CAST "lang", XML_XML_NAMESPACE,
+                                  &lang);
+        if (res < 0)
+            return(NULL);
 	if (lang != NULL)
 	    return(lang);
+
 	cur = cur->parent;
     }
+
     return(NULL);
 }
 
@@ -5175,47 +5171,34 @@ xmlNodeGetLang(const xmlNode *cur) {
  *
  * Set (or reset) the space preserving behaviour of a node, i.e. the
  * value of the xml:space attribute.
+ *
+ * Return 0 on success, 1 if arguments are invalid, -1 if a
+ * memory allocation failed.
  */
-void
+int
 xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) {
     xmlNsPtr ns;
+    xmlAttrPtr attr;
+    const char *string;
+    int res;
 
-    if (cur == NULL) return;
-    switch(cur->type) {
-        case XML_TEXT_NODE:
-        case XML_CDATA_SECTION_NODE:
-        case XML_COMMENT_NODE:
-        case XML_DOCUMENT_NODE:
-        case XML_DOCUMENT_TYPE_NODE:
-        case XML_DOCUMENT_FRAG_NODE:
-        case XML_NOTATION_NODE:
-        case XML_HTML_DOCUMENT_NODE:
-        case XML_DTD_NODE:
-        case XML_ELEMENT_DECL:
-        case XML_ATTRIBUTE_DECL:
-        case XML_ENTITY_DECL:
-        case XML_PI_NODE:
-        case XML_ENTITY_REF_NODE:
-        case XML_ENTITY_NODE:
-	case XML_NAMESPACE_DECL:
-	case XML_XINCLUDE_START:
-	case XML_XINCLUDE_END:
-	    return;
-        case XML_ELEMENT_NODE:
-        case XML_ATTRIBUTE_NODE:
-	    break;
-    }
-    ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
-    if (ns == NULL)
-	return;
-    switch (val) {
-    case 0:
-	xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "default");
-	break;
-    case 1:
-	xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "preserve");
-	break;
-    }
+    if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
+        return(1);
+
+    res = xmlSearchNsByHrefSafe(cur, XML_XML_NAMESPACE, &ns);
+    if (res != 0)
+	return(res);
+
+    if (val == 0)
+        string = "default";
+    else
+        string = "preserve";
+
+    attr = xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST string);
+    if (attr == NULL)
+        return(-1);
+
+    return(0);
 }
 #endif /* LIBXML_TREE_ENABLED */
 
@@ -5232,11 +5215,16 @@ xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) {
 int
 xmlNodeGetSpacePreserve(const xmlNode *cur) {
     xmlChar *space;
+        int res;
 
     if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
         return(-1);
+
     while (cur != NULL) {
-	space = xmlGetNsProp(cur, BAD_CAST "space", XML_XML_NAMESPACE);
+	res = xmlNodeGetAttrValue(cur, BAD_CAST "space", XML_XML_NAMESPACE,
+                                  &space);
+        if (res < 0)
+            return(-1);
 	if (space != NULL) {
 	    if (xmlStrEqual(space, BAD_CAST "preserve")) {
 		xmlFree(space);
@@ -5248,8 +5236,10 @@ xmlNodeGetSpacePreserve(const xmlNode *cur) {
 	    }
 	    xmlFree(space);
 	}
+
 	cur = cur->parent;
     }
+
     return(-1);
 }
 
@@ -5265,51 +5255,39 @@ void
 xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
     xmlDocPtr doc;
     xmlDictPtr dict;
-    const xmlChar *freeme = NULL;
+    const xmlChar *copy;
+    const xmlChar *oldName;
 
     if (cur == NULL) return;
     if (name == NULL) return;
     switch(cur->type) {
-        case XML_TEXT_NODE:
-        case XML_CDATA_SECTION_NODE:
-        case XML_COMMENT_NODE:
-        case XML_DOCUMENT_TYPE_NODE:
-        case XML_DOCUMENT_FRAG_NODE:
-        case XML_NOTATION_NODE:
-        case XML_HTML_DOCUMENT_NODE:
-	case XML_NAMESPACE_DECL:
-	case XML_XINCLUDE_START:
-	case XML_XINCLUDE_END:
-	    return;
         case XML_ELEMENT_NODE:
         case XML_ATTRIBUTE_NODE:
         case XML_PI_NODE:
         case XML_ENTITY_REF_NODE:
-        case XML_ENTITY_NODE:
-        case XML_DTD_NODE:
-        case XML_DOCUMENT_NODE:
-        case XML_ELEMENT_DECL:
-        case XML_ATTRIBUTE_DECL:
-        case XML_ENTITY_DECL:
 	    break;
+        default:
+            return;
     }
+
     doc = cur->doc;
     if (doc != NULL)
 	dict = doc->dict;
     else
         dict = NULL;
-    if (dict != NULL) {
-        if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))
-	    freeme = cur->name;
-	cur->name = xmlDictLookup(dict, name, -1);
-    } else {
-	if (cur->name != NULL)
-	    freeme = cur->name;
-	cur->name = xmlStrdup(name);
-    }
 
-    if (freeme)
-        xmlFree((xmlChar *) freeme);
+    if (dict != NULL)
+        copy = xmlDictLookup(dict, name, -1);
+    else
+        copy = xmlStrdup(name);
+    if (copy == NULL)
+        return;
+
+    oldName = cur->name;
+    cur->name = copy;
+    if ((oldName != NULL) &&
+        ((dict == NULL) || (!xmlDictOwns(dict, oldName))))
+        xmlFree((xmlChar *) oldName);
 }
 #endif
 
@@ -5321,31 +5299,17 @@ xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
  *
  * Set (or reset) the base URI of a node, i.e. the value of the
  * xml:base attribute.
+ *
+ * Returns 0 on success, -1 on error.
  */
-void
+int
 xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) {
     xmlNsPtr ns;
     xmlChar* fixed;
 
-    if (cur == NULL) return;
+    if (cur == NULL)
+        return(-1);
     switch(cur->type) {
-        case XML_TEXT_NODE:
-        case XML_CDATA_SECTION_NODE:
-        case XML_COMMENT_NODE:
-        case XML_DOCUMENT_TYPE_NODE:
-        case XML_DOCUMENT_FRAG_NODE:
-        case XML_NOTATION_NODE:
-        case XML_DTD_NODE:
-        case XML_ELEMENT_DECL:
-        case XML_ATTRIBUTE_DECL:
-        case XML_ENTITY_DECL:
-        case XML_PI_NODE:
-        case XML_ENTITY_REF_NODE:
-        case XML_ENTITY_NODE:
-	case XML_NAMESPACE_DECL:
-	case XML_XINCLUDE_START:
-	case XML_XINCLUDE_END:
-	    return;
         case XML_ELEMENT_NODE:
         case XML_ATTRIBUTE_NODE:
 	    break;
@@ -5355,31 +5319,40 @@ xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) {
 
 	    if (doc->URL != NULL)
 		xmlFree((xmlChar *) doc->URL);
-	    if (uri == NULL)
+	    if (uri == NULL) {
 		doc->URL = NULL;
-	    else
+            } else {
 		doc->URL = xmlPathToURI(uri);
-	    return;
+                if (doc->URL == NULL)
+                    return(-1);
+            }
+	    return(0);
 	}
+        default:
+	    return(-1);
     }
 
-    ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
+    xmlSearchNsByHrefSafe(cur, XML_XML_NAMESPACE, &ns);
     if (ns == NULL)
-	return;
+	return(-1);
     fixed = xmlPathToURI(uri);
-    if (fixed != NULL) {
-	xmlSetNsProp(cur, ns, BAD_CAST "base", fixed);
-	xmlFree(fixed);
-    } else {
-	xmlSetNsProp(cur, ns, BAD_CAST "base", uri);
+    if (fixed == NULL)
+        return(-1);
+    if (xmlSetNsProp(cur, ns, BAD_CAST "base", fixed) == NULL) {
+        xmlFree(fixed);
+        return(-1);
     }
+    xmlFree(fixed);
+
+    return(0);
 }
 #endif /* LIBXML_TREE_ENABLED */
 
 /**
- * xmlNodeGetBase:
+ * xmlNodeGetBaseSafe:
  * @doc:  the document the node pertains to
  * @cur:  the node being checked
+ * @baseOut:  pointer to base
  *
  * Searches for the BASE URL. The code should work on both XML
  * and HTML document even if base mechanisms are completely different.
@@ -5390,19 +5363,27 @@ xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) {
  * However it does not return the document base (5.1.3), use
  * doc->URL in this case
  *
- * Returns a pointer to the base URL, or NULL if not found
- *     It's up to the caller to free the memory with xmlFree().
+ * Available since 2.13.0.
+ *
+ * Return 0 in case of success, 1 if a URI or argument is invalid, -1 if a
+ * memory allocation failed.
  */
-xmlChar *
-xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) {
-    xmlChar *oldbase = NULL;
+int
+xmlNodeGetBaseSafe(const xmlDoc *doc, const xmlNode *cur, xmlChar **baseOut) {
+    xmlChar *ret = NULL;
     xmlChar *base, *newbase;
+    int res;
 
+    if (baseOut == NULL)
+        return(1);
+    *baseOut = NULL;
     if ((cur == NULL) && (doc == NULL))
-        return(NULL);
+        return(1);
     if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
-        return(NULL);
-    if (doc == NULL) doc = cur->doc;
+        return(1);
+    if (doc == NULL)
+        doc = cur->doc;
+
     if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
         cur = doc->children;
 	while ((cur != NULL) && (cur->name != NULL)) {
@@ -5419,50 +5400,91 @@ xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) {
 		continue;
 	    }
 	    if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) {
-                return(xmlGetProp(cur, BAD_CAST "href"));
+                if (xmlNodeGetAttrValue(cur, BAD_CAST "href", NULL, &ret) < 0)
+                    return(-1);
+                if (ret == NULL)
+                    return(1);
+                goto found;
 	    }
 	    cur = cur->next;
 	}
-	return(NULL);
+	return(0);
     }
+
     while (cur != NULL) {
 	if (cur->type == XML_ENTITY_DECL) {
 	    xmlEntityPtr ent = (xmlEntityPtr) cur;
-	    return(xmlStrdup(ent->URI));
+
+            if (ent->URI == NULL)
+                break;
+            xmlFree(ret);
+	    ret = xmlStrdup(ent->URI);
+            if (ret == NULL)
+                return(-1);
+            goto found;
 	}
 	if (cur->type == XML_ELEMENT_NODE) {
-	    base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
+	    if (xmlNodeGetAttrValue(cur, BAD_CAST "base", XML_XML_NAMESPACE,
+                                    &base) < 0) {
+                xmlFree(ret);
+                return(-1);
+            }
 	    if (base != NULL) {
-		if (oldbase != NULL) {
-		    newbase = xmlBuildURI(oldbase, base);
-		    if (newbase != NULL) {
-			xmlFree(oldbase);
-			xmlFree(base);
-			oldbase = newbase;
-		    } else {
-			xmlFree(oldbase);
-			xmlFree(base);
-			return(NULL);
-		    }
+		if (ret != NULL) {
+		    res = xmlBuildURISafe(ret, base, &newbase);
+                    xmlFree(ret);
+                    xmlFree(base);
+                    if (res != 0)
+                        return(res);
+		    ret = newbase;
 		} else {
-		    oldbase = base;
+		    ret = base;
 		}
-		if ((!xmlStrncmp(oldbase, BAD_CAST "http://", 7)) ||
-		    (!xmlStrncmp(oldbase, BAD_CAST "ftp://", 6)) ||
-		    (!xmlStrncmp(oldbase, BAD_CAST "urn:", 4)))
-		    return(oldbase);
+		if ((!xmlStrncmp(ret, BAD_CAST "http://", 7)) ||
+		    (!xmlStrncmp(ret, BAD_CAST "ftp://", 6)) ||
+		    (!xmlStrncmp(ret, BAD_CAST "urn:", 4)))
+                    goto found;
 	    }
 	}
 	cur = cur->parent;
     }
+
     if ((doc != NULL) && (doc->URL != NULL)) {
-	if (oldbase == NULL)
-	    return(xmlStrdup(doc->URL));
-	newbase = xmlBuildURI(oldbase, doc->URL);
-	xmlFree(oldbase);
-	return(newbase);
+	if (ret == NULL) {
+	    ret = xmlStrdup(doc->URL);
+            if (ret == NULL)
+                return(-1);
+        } else {
+            res = xmlBuildURISafe(ret, doc->URL, &newbase);
+            xmlFree(ret);
+            if (res != 0)
+                return(res);
+            ret = newbase;
+        }
     }
-    return(oldbase);
+
+found:
+    *baseOut = ret;
+    return(0);
+}
+
+/**
+ * xmlNodeGetBase:
+ * @doc:  the document the node pertains to
+ * @cur:  the node being checked
+ *
+ * See xmlNodeGetBaseSafe. This function doesn't allow to distinguish
+ * memory allocation failures from a non-existing base.
+ *
+ * Returns a pointer to the base URL, or NULL if not found
+ *     It's up to the caller to free the memory with xmlFree().
+ */
+xmlChar *
+xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) {
+    xmlChar *base;
+
+    xmlNodeGetBaseSafe(doc, cur, &base);
+    return(base);
 }
 
 /**
@@ -5493,6 +5515,69 @@ xmlNodeBufGetContent(xmlBufferPtr buffer, const xmlNode *cur)
     return(0);
 }
 
+static void
+xmlBufGetEntityRefContent(xmlBufPtr buf, const xmlNode *ref) {
+    xmlEntityPtr ent;
+
+    if (ref->children != NULL) {
+        ent = (xmlEntityPtr) ref->children;
+    } else {
+        /* lookup entity declaration */
+        ent = xmlGetDocEntity(ref->doc, ref->name);
+        if (ent == NULL)
+            return;
+    }
+
+    /*
+     * The parser should always expand predefined entities but it's
+     * possible to create references to predefined entities using
+     * the tree API.
+     */
+    if (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY) {
+        xmlBufCat(buf, ent->content);
+        return;
+    }
+
+    if (ent->flags & XML_ENT_EXPANDING)
+        return;
+
+    ent->flags |= XML_ENT_EXPANDING;
+    xmlBufGetChildContent(buf, (xmlNodePtr) ent);
+    ent->flags &= ~XML_ENT_EXPANDING;
+}
+
+static void
+xmlBufGetChildContent(xmlBufPtr buf, const xmlNode *tree) {
+    const xmlNode *cur = tree->children;
+
+    while (cur != NULL) {
+        switch (cur->type) {
+            case XML_TEXT_NODE:
+            case XML_CDATA_SECTION_NODE:
+                xmlBufCat(buf, cur->content);
+                break;
+
+            case XML_ENTITY_REF_NODE:
+                xmlBufGetEntityRefContent(buf, cur);
+                break;
+
+            default:
+                if (cur->children != NULL) {
+                    cur = cur->children;
+                    continue;
+                }
+                break;
+        }
+
+        while (cur->next == NULL) {
+            cur = cur->parent;
+            if (cur == tree)
+                return;
+        }
+        cur = cur->next;
+    }
+}
+
 /**
  * xmlBufGetNodeContent:
  * @buf:  a buffer xmlBufPtr
@@ -5509,127 +5594,38 @@ xmlNodeBufGetContent(xmlBufferPtr buffer, const xmlNode *cur)
 int
 xmlBufGetNodeContent(xmlBufPtr buf, const xmlNode *cur)
 {
-    if ((cur == NULL) || (buf == NULL)) return(-1);
+    if ((cur == NULL) || (buf == NULL))
+        return(-1);
+
     switch (cur->type) {
-        case XML_CDATA_SECTION_NODE:
-        case XML_TEXT_NODE:
-	    xmlBufCat(buf, cur->content);
-            break;
+        case XML_DOCUMENT_NODE:
+        case XML_HTML_DOCUMENT_NODE:
         case XML_DOCUMENT_FRAG_NODE:
-        case XML_ELEMENT_NODE:{
-                const xmlNode *tmp = cur;
-
-                while (tmp != NULL) {
-                    switch (tmp->type) {
-                        case XML_CDATA_SECTION_NODE:
-                        case XML_TEXT_NODE:
-                            if (tmp->content != NULL)
-                                xmlBufCat(buf, tmp->content);
-                            break;
-                        case XML_ENTITY_REF_NODE:
-                            xmlBufGetNodeContent(buf, tmp);
-                            break;
-                        default:
-                            break;
-                    }
-                    /*
-                     * Skip to next node
-                     */
-                    if (tmp->children != NULL) {
-                        if (tmp->children->type != XML_ENTITY_DECL) {
-                            tmp = tmp->children;
-                            continue;
-                        }
-                    }
-                    if (tmp == cur)
-                        break;
-
-                    if (tmp->next != NULL) {
-                        tmp = tmp->next;
-                        continue;
-                    }
-
-                    do {
-                        tmp = tmp->parent;
-                        if (tmp == NULL)
-                            break;
-                        if (tmp == cur) {
-                            tmp = NULL;
-                            break;
-                        }
-                        if (tmp->next != NULL) {
-                            tmp = tmp->next;
-                            break;
-                        }
-                    } while (tmp != NULL);
-                }
-		break;
-            }
-        case XML_ATTRIBUTE_NODE:{
-                xmlAttrPtr attr = (xmlAttrPtr) cur;
-		xmlNodePtr tmp = attr->children;
+        case XML_ELEMENT_NODE:
+        case XML_ATTRIBUTE_NODE:
+        case XML_ENTITY_DECL:
+            xmlBufGetChildContent(buf, cur);
+            break;
 
-		while (tmp != NULL) {
-		    if (tmp->type == XML_TEXT_NODE)
-		        xmlBufCat(buf, tmp->content);
-		    else
-		        xmlBufGetNodeContent(buf, tmp);
-		    tmp = tmp->next;
-		}
-                break;
-            }
+        case XML_CDATA_SECTION_NODE:
+        case XML_TEXT_NODE:
         case XML_COMMENT_NODE:
         case XML_PI_NODE:
 	    xmlBufCat(buf, cur->content);
             break;
-        case XML_ENTITY_REF_NODE:{
-                xmlEntityPtr ent;
-                xmlNodePtr tmp;
 
-                /* lookup entity declaration */
-                ent = xmlGetDocEntity(cur->doc, cur->name);
-                if (ent == NULL)
-                    return(-1);
-
-                /* an entity content can be any "well balanced chunk",
-                 * i.e. the result of the content [43] production:
-                 * http://www.w3.org/TR/REC-xml#NT-content
-                 * -> we iterate through child nodes and recursive call
-                 * xmlNodeGetContent() which handles all possible node types */
-                tmp = ent->children;
-                while (tmp) {
-		    xmlBufGetNodeContent(buf, tmp);
-                    tmp = tmp->next;
-                }
-		break;
-            }
-        case XML_ENTITY_NODE:
-        case XML_DOCUMENT_TYPE_NODE:
-        case XML_NOTATION_NODE:
-        case XML_DTD_NODE:
-        case XML_XINCLUDE_START:
-        case XML_XINCLUDE_END:
+        case XML_ENTITY_REF_NODE:
+            xmlBufGetEntityRefContent(buf, cur);
             break;
-        case XML_DOCUMENT_NODE:
-        case XML_HTML_DOCUMENT_NODE:
-	    cur = cur->children;
-	    while (cur!= NULL) {
-		if ((cur->type == XML_ELEMENT_NODE) ||
-		    (cur->type == XML_TEXT_NODE) ||
-		    (cur->type == XML_CDATA_SECTION_NODE)) {
-		    xmlBufGetNodeContent(buf, cur);
-		}
-		cur = cur->next;
-	    }
-	    break;
+
         case XML_NAMESPACE_DECL:
 	    xmlBufCat(buf, ((xmlNsPtr) cur)->href);
 	    break;
-        case XML_ELEMENT_DECL:
-        case XML_ATTRIBUTE_DECL:
-        case XML_ENTITY_DECL:
+
+        default:
             break;
     }
+
     return(0);
 }
 
@@ -5647,167 +5643,131 @@ xmlBufGetNodeContent(xmlBufPtr buf, const xmlNode *cur)
 xmlChar *
 xmlNodeGetContent(const xmlNode *cur)
 {
+    xmlBufPtr buf;
+    xmlChar *ret;
+
     if (cur == NULL)
         return (NULL);
+
     switch (cur->type) {
+        case XML_DOCUMENT_NODE:
+        case XML_HTML_DOCUMENT_NODE:
+        case XML_ENTITY_REF_NODE:
+            break;
+
         case XML_DOCUMENT_FRAG_NODE:
-        case XML_ELEMENT_NODE:{
-                xmlBufPtr buf;
-                xmlChar *ret;
-
-                buf = xmlBufCreateSize(64);
-                if (buf == NULL)
-                    return (NULL);
-                xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
-		xmlBufGetNodeContent(buf, cur);
-                ret = xmlBufDetach(buf);
-                xmlBufFree(buf);
-                return (ret);
-            }
+        case XML_ELEMENT_NODE:
         case XML_ATTRIBUTE_NODE:
-	    return(xmlGetPropNodeValueInternal((xmlAttrPtr) cur));
-        case XML_COMMENT_NODE:
-        case XML_PI_NODE:
-            if (cur->content != NULL)
-                return (xmlStrdup(cur->content));
-            return (NULL);
-        case XML_ENTITY_REF_NODE:{
-                xmlEntityPtr ent;
-                xmlBufPtr buf;
-                xmlChar *ret;
-
-                /* lookup entity declaration */
-                ent = xmlGetDocEntity(cur->doc, cur->name);
-                if (ent == NULL)
-                    return (NULL);
-
-                buf = xmlBufCreate();
-                if (buf == NULL)
-                    return (NULL);
-                xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
-
-                xmlBufGetNodeContent(buf, cur);
-
-                ret = xmlBufDetach(buf);
-                xmlBufFree(buf);
-                return (ret);
+        case XML_ENTITY_DECL: {
+            xmlNodePtr children = cur->children;
+
+            if (children == NULL)
+                return(xmlStrdup(BAD_CAST ""));
+
+            /* Optimization for single text children */
+            if (((children->type == XML_TEXT_NODE) ||
+                 (children->type == XML_CDATA_SECTION_NODE)) &&
+                (children->next == NULL)) {
+                if (children->content == NULL)
+                    return(xmlStrdup(BAD_CAST ""));
+                return(xmlStrdup(children->content));
             }
-        case XML_ENTITY_NODE:
-        case XML_DOCUMENT_TYPE_NODE:
-        case XML_NOTATION_NODE:
-        case XML_DTD_NODE:
-        case XML_XINCLUDE_START:
-        case XML_XINCLUDE_END:
-            return (NULL);
-        case XML_DOCUMENT_NODE:
-        case XML_HTML_DOCUMENT_NODE: {
-	    xmlBufPtr buf;
-	    xmlChar *ret;
 
-	    buf = xmlBufCreate();
-	    if (buf == NULL)
-		return (NULL);
-            xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
-
-	    xmlBufGetNodeContent(buf, (xmlNodePtr) cur);
-
-	    ret = xmlBufDetach(buf);
-	    xmlBufFree(buf);
-	    return (ret);
-	}
-        case XML_NAMESPACE_DECL: {
-	    xmlChar *tmp;
+            break;
+        }
 
-	    tmp = xmlStrdup(((xmlNsPtr) cur)->href);
-            return (tmp);
-	}
-        case XML_ELEMENT_DECL:
-            /* TODO !!! */
-            return (NULL);
-        case XML_ATTRIBUTE_DECL:
-            /* TODO !!! */
-            return (NULL);
-        case XML_ENTITY_DECL:
-            /* TODO !!! */
-            return (NULL);
         case XML_CDATA_SECTION_NODE:
         case XML_TEXT_NODE:
+        case XML_COMMENT_NODE:
+        case XML_PI_NODE:
             if (cur->content != NULL)
-                return (xmlStrdup(cur->content));
-            return (NULL);
+                return(xmlStrdup(cur->content));
+            else
+                return(xmlStrdup(BAD_CAST ""));
+
+        case XML_NAMESPACE_DECL:
+	    return(xmlStrdup(((xmlNsPtr) cur)->href));
+
+        default:
+            return(NULL);
     }
-    return (NULL);
+
+    buf = xmlBufCreateSize(64);
+    if (buf == NULL)
+        return (NULL);
+    xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
+    xmlBufGetNodeContent(buf, cur);
+    ret = xmlBufDetach(buf);
+    xmlBufFree(buf);
+
+    return(ret);
 }
 
-/**
- * xmlNodeSetContent:
- * @cur:  the node being modified
- * @content:  the new value of the content
- *
- * Replace the content of a node.
- * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
- *       references, but XML special chars need to be escaped first by using
- *       xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
- */
-void
-xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
+static int
+xmlNodeSetContentInternal(xmlNodePtr cur, const xmlChar *content, int len) {
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNodeSetContent : node == NULL\n");
-#endif
-	return;
+	return(1);
     }
     switch (cur->type) {
         case XML_DOCUMENT_FRAG_NODE:
         case XML_ELEMENT_NODE:
         case XML_ATTRIBUTE_NODE:
-	    if (cur->children != NULL) xmlFreeNodeList(cur->children);
-	    cur->children = xmlStringGetNodeList(cur->doc, content);
-	    UPDATE_LAST_CHILD_AND_PARENT(cur)
+            if (xmlNodeParseContent(cur, content, len) < 0)
+                return(-1);
 	    break;
+
         case XML_TEXT_NODE:
         case XML_CDATA_SECTION_NODE:
-        case XML_ENTITY_REF_NODE:
-        case XML_ENTITY_NODE:
         case XML_PI_NODE:
-        case XML_COMMENT_NODE:
-	    if ((cur->content != NULL) &&
-	        (cur->content != (xmlChar *) &(cur->properties))) {
-	        if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
-		    (xmlDictOwns(cur->doc->dict, cur->content))))
-		    xmlFree(cur->content);
-	    }
-	    if (cur->children != NULL) xmlFreeNodeList(cur->children);
-	    cur->last = cur->children = NULL;
+        case XML_COMMENT_NODE: {
+            xmlChar *copy = NULL;
+
 	    if (content != NULL) {
-		cur->content = xmlStrdup(content);
-	    } else
-		cur->content = NULL;
-	    cur->properties = NULL;
-	    break;
-        case XML_DOCUMENT_NODE:
-        case XML_HTML_DOCUMENT_NODE:
-        case XML_DOCUMENT_TYPE_NODE:
-	case XML_XINCLUDE_START:
-	case XML_XINCLUDE_END:
-	    break;
-        case XML_NOTATION_NODE:
-	    break;
-        case XML_DTD_NODE:
-	    break;
-	case XML_NAMESPACE_DECL:
-	    break;
-        case XML_ELEMENT_DECL:
-	    /* TODO !!! */
-	    break;
-        case XML_ATTRIBUTE_DECL:
-	    /* TODO !!! */
-	    break;
-        case XML_ENTITY_DECL:
-	    /* TODO !!! */
+                if (len < 0)
+                    copy = xmlStrdup(content);
+                else
+		    copy = xmlStrndup(content, len);
+                if (copy == NULL)
+                    return(-1);
+	    }
+
+            xmlTextSetContent(cur, copy);
 	    break;
+        }
+
+        default:
+            break;
     }
+
+    return(0);
+}
+
+/**
+ * xmlNodeSetContent:
+ * @cur:  the node being modified
+ * @content:  the new value of the content
+ *
+ * Replace the text content of a node.
+ *
+ * Sets the raw text content of text, CDATA, comment or PI nodes.
+ *
+ * For element and attribute nodes, removes all children and
+ * replaces them by parsing @content which is expected to be a
+ * valid XML attribute value possibly containing character and
+ * entity references. Syntax errors and references to undeclared
+ * entities are ignored silently. Unfortunately, there isn't an
+ * API to pass raw content directly. An inefficient work-around
+ * is to escape the content with xmlEncodeSpecialChars before
+ * passing it. A better trick is clearing the old content
+ * with xmlNodeSetContent(node, NULL) first and then calling
+ * xmlNodeAddContent(node, content). Unlike this function,
+ * xmlNodeAddContent accepts raw text.
+ *
+ * Returns 0 on success, 1 on error, -1 if a memory allocation failed.
+ */
+int
+xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
+    return(xmlNodeSetContentInternal(cur, content, -1));
 }
 
 #ifdef LIBXML_TREE_ENABLED
@@ -5817,67 +5777,13 @@ xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
  * @content:  the new value of the content
  * @len:  the size of @content
  *
- * Replace the content of a node.
- * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
- *       references, but XML special chars need to be escaped first by using
- *       xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
+ * See xmlNodeSetContent.
+ *
+ * Returns 0 on success, 1 on error, -1 if a memory allocation failed.
  */
-void
+int
 xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
-    if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNodeSetContentLen : node == NULL\n");
-#endif
-	return;
-    }
-    switch (cur->type) {
-        case XML_DOCUMENT_FRAG_NODE:
-        case XML_ELEMENT_NODE:
-        case XML_ATTRIBUTE_NODE:
-	    if (cur->children != NULL) xmlFreeNodeList(cur->children);
-	    cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
-	    UPDATE_LAST_CHILD_AND_PARENT(cur)
-	    break;
-        case XML_TEXT_NODE:
-        case XML_CDATA_SECTION_NODE:
-        case XML_ENTITY_REF_NODE:
-        case XML_ENTITY_NODE:
-        case XML_PI_NODE:
-        case XML_COMMENT_NODE:
-        case XML_NOTATION_NODE:
-	    if ((cur->content != NULL) &&
-	        (cur->content != (xmlChar *) &(cur->properties))) {
-	        if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
-		    (xmlDictOwns(cur->doc->dict, cur->content))))
-		    xmlFree(cur->content);
-	    }
-	    if (cur->children != NULL) xmlFreeNodeList(cur->children);
-	    cur->children = cur->last = NULL;
-	    if (content != NULL) {
-		cur->content = xmlStrndup(content, len);
-	    } else
-		cur->content = NULL;
-	    cur->properties = NULL;
-	    break;
-        case XML_DOCUMENT_NODE:
-        case XML_DTD_NODE:
-        case XML_HTML_DOCUMENT_NODE:
-        case XML_DOCUMENT_TYPE_NODE:
-	case XML_NAMESPACE_DECL:
-	case XML_XINCLUDE_START:
-	case XML_XINCLUDE_END:
-	    break;
-        case XML_ELEMENT_DECL:
-	    /* TODO !!! */
-	    break;
-        case XML_ATTRIBUTE_DECL:
-	    /* TODO !!! */
-	    break;
-        case XML_ENTITY_DECL:
-	    /* TODO !!! */
-	    break;
-    }
+    return(xmlNodeSetContentInternal(cur, content, len));
 }
 #endif /* LIBXML_TREE_ENABLED */
 
@@ -5891,67 +5797,43 @@ xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
  * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be
  *       raw text, so unescaped XML special chars are allowed, entity
  *       references are not supported.
+ *
+ * Returns 0 on success, 1 on error, -1 if a memory allocation failed.
  */
-void
+int
 xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
-    if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNodeAddContentLen : node == NULL\n");
-#endif
-	return;
-    }
-    if (len <= 0) return;
+    if (cur == NULL)
+	return(1);
+    if ((content == NULL) || (len <= 0))
+        return(0);
+
     switch (cur->type) {
         case XML_DOCUMENT_FRAG_NODE:
         case XML_ELEMENT_NODE: {
-	    xmlNodePtr last, newNode, tmp;
+	    xmlNodePtr newNode, tmp;
 
-	    last = cur->last;
 	    newNode = xmlNewDocTextLen(cur->doc, content, len);
-	    if (newNode != NULL) {
-		tmp = xmlAddChild(cur, newNode);
-		if (tmp != newNode)
-		    return;
-	        if ((last != NULL) && (last->next == newNode)) {
-		    xmlTextMerge(last, newNode);
-		}
-	    }
+	    if (newNode == NULL)
+                return(-1);
+            tmp = xmlAddChild(cur, newNode);
+            if (tmp == NULL) {
+                xmlFreeNode(newNode);
+                return(-1);
+            }
 	    break;
 	}
         case XML_ATTRIBUTE_NODE:
 	    break;
         case XML_TEXT_NODE:
         case XML_CDATA_SECTION_NODE:
-        case XML_ENTITY_REF_NODE:
-        case XML_ENTITY_NODE:
         case XML_PI_NODE:
         case XML_COMMENT_NODE:
-        case XML_NOTATION_NODE:
-	    if (content != NULL) {
-	        if ((cur->content == (xmlChar *) &(cur->properties)) ||
-		    ((cur->doc != NULL) && (cur->doc->dict != NULL) &&
-			    xmlDictOwns(cur->doc->dict, cur->content))) {
-		    cur->content = xmlStrncatNew(cur->content, content, len);
-		    cur->properties = NULL;
-		} else {
-		    cur->content = xmlStrncat(cur->content, content, len);
-                }
-            }
-	    break;
-        case XML_DOCUMENT_NODE:
-        case XML_DTD_NODE:
-        case XML_HTML_DOCUMENT_NODE:
-        case XML_DOCUMENT_TYPE_NODE:
-	case XML_NAMESPACE_DECL:
-	case XML_XINCLUDE_START:
-	case XML_XINCLUDE_END:
-	    break;
-        case XML_ELEMENT_DECL:
-        case XML_ATTRIBUTE_DECL:
-        case XML_ENTITY_DECL:
-	    break;
+            return(xmlTextAddContent(cur, content, len));
+        default:
+            break;
     }
+
+    return(0);
 }
 
 /**
@@ -5963,21 +5845,12 @@ xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
  * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be
  *       raw text, so unescaped XML special chars are allowed, entity
  *       references are not supported.
+ *
+ * Returns 0 on success, 1 on error, -1 if a memory allocation failed.
  */
-void
+int
 xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
-    int len;
-
-    if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNodeAddContent : node == NULL\n");
-#endif
-	return;
-    }
-    if (content == NULL) return;
-    len = xmlStrlen(content);
-    xmlNodeAddContentLen(cur, content, len);
+    return(xmlNodeAddContentLen(cur, content, xmlStrlen(content)));
 }
 
 /**
@@ -5985,120 +5858,246 @@ xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
  * @first:  the first text node
  * @second:  the second text node being merged
  *
- * Merge two text nodes into one
- * Returns the first text node augmented
+ * Merge the second text node into the first. The second node is
+ * unlinked and freed.
+ *
+ * Returns the first text node augmented or NULL in case of error.
  */
 xmlNodePtr
 xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
-    if (first == NULL) return(second);
-    if (second == NULL) return(first);
-    if (first->type != XML_TEXT_NODE) return(first);
-    if (second->type != XML_TEXT_NODE) return(first);
-    if (second->name != first->name)
-	return(first);
-    xmlNodeAddContent(first, second->content);
-    xmlUnlinkNode(second);
+    if ((first == NULL) || (first->type != XML_TEXT_NODE) ||
+        (second == NULL) || (second->type != XML_TEXT_NODE) ||
+        (first == second) ||
+        (first->name != second->name))
+	return(NULL);
+
+    if (xmlTextAddContent(first, second->content, -1) < 0)
+        return(NULL);
+
+    xmlUnlinkNodeInternal(second);
     xmlFreeNode(second);
     return(first);
 }
 
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
 /**
- * xmlGetNsList:
+ * xmlGetNsListSafe:
  * @doc:  the document
  * @node:  the current node
+ * @out:  the returned namespace array
+ *
+ * Find all in-scope namespaces of a node. @out returns a NULL
+ * terminated array of namespace pointers that must be freed by
+ * the caller.
  *
- * Search all the namespace applying to a given element.
- * Returns an NULL terminated array of all the #xmlNsPtr found
- *         that need to be freed by the caller or NULL if no
- *         namespace if defined
+ * Available since 2.13.0.
+ *
+ * Returns 0 on success, 1 if no namespaces were found, -1 if a
+ * memory allocation failed.
  */
-xmlNsPtr *
-xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node)
+int
+xmlGetNsListSafe(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node,
+                 xmlNsPtr **out)
 {
     xmlNsPtr cur;
-    xmlNsPtr *ret = NULL;
+    xmlNsPtr *namespaces = NULL;
     int nbns = 0;
-    int maxns = 10;
+    int maxns = 0;
     int i;
 
+    if (out == NULL)
+        return(1);
+    *out = NULL;
     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
-        return(NULL);
+        return(1);
 
     while (node != NULL) {
         if (node->type == XML_ELEMENT_NODE) {
             cur = node->nsDef;
             while (cur != NULL) {
-                if (ret == NULL) {
-                    ret =
-                        (xmlNsPtr *) xmlMalloc((maxns + 1) *
-                                               sizeof(xmlNsPtr));
-                    if (ret == NULL) {
-			xmlTreeErrMemory("getting namespace list");
-                        return (NULL);
-                    }
-                    ret[nbns] = NULL;
-                }
                 for (i = 0; i < nbns; i++) {
-                    if ((cur->prefix == ret[i]->prefix) ||
-                        (xmlStrEqual(cur->prefix, ret[i]->prefix)))
+                    if ((cur->prefix == namespaces[i]->prefix) ||
+                        (xmlStrEqual(cur->prefix, namespaces[i]->prefix)))
                         break;
                 }
                 if (i >= nbns) {
                     if (nbns >= maxns) {
-                        maxns *= 2;
-                        ret = (xmlNsPtr *) xmlRealloc(ret,
-                                                      (maxns +
-                                                       1) *
+                        xmlNsPtr *tmp;
+
+                        maxns = maxns ? maxns * 2 : 10;
+                        tmp = (xmlNsPtr *) xmlRealloc(namespaces,
+                                                      (maxns + 1) *
                                                       sizeof(xmlNsPtr));
-                        if (ret == NULL) {
-			    xmlTreeErrMemory("getting namespace list");
-                            return (NULL);
+                        if (tmp == NULL) {
+                            xmlFree(namespaces);
+                            return(-1);
                         }
+                        namespaces = tmp;
                     }
-                    ret[nbns++] = cur;
-                    ret[nbns] = NULL;
+                    namespaces[nbns++] = cur;
+                    namespaces[nbns] = NULL;
                 }
 
-                cur = cur->next;
+                cur = cur->next;
+            }
+        }
+        node = node->parent;
+    }
+
+    *out = namespaces;
+    return((namespaces == NULL) ? 1 : 0);
+}
+
+/**
+ * xmlGetNsList:
+ * @doc:  the document
+ * @node:  the current node
+ *
+ * Find all in-scope namespaces of a node.
+ *
+ * Use xmlGetNsListSafe for better error reporting.
+ *
+ * Returns a NULL terminated array of namespace pointers that must
+ * be freed by the caller or NULL if no namespaces were found or
+ * a memory allocation failed.
+ */
+xmlNsPtr *
+xmlGetNsList(const xmlDoc *doc, const xmlNode *node)
+{
+    xmlNsPtr *ret;
+
+    xmlGetNsListSafe(doc, node, &ret);
+    return(ret);
+}
+#endif /* LIBXML_TREE_ENABLED */
+
+static xmlNsPtr
+xmlNewXmlNs(void) {
+    xmlNsPtr ns;
+
+    ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
+    if (ns == NULL)
+        return(NULL);
+    memset(ns, 0, sizeof(xmlNs));
+    ns->type = XML_LOCAL_NAMESPACE;
+    ns->href = xmlStrdup(XML_XML_NAMESPACE);
+    if (ns->href == NULL) {
+        xmlFreeNs(ns);
+        return(NULL);
+    }
+    ns->prefix = xmlStrdup(BAD_CAST "xml");
+    if (ns->prefix == NULL) {
+        xmlFreeNs(ns);
+        return(NULL);
+    }
+
+    return(ns);
+}
+
+/*
+* xmlTreeEnsureXMLDecl:
+* @doc: the doc
+*
+* Ensures that there is an XML namespace declaration on the doc.
+*
+* Returns the XML ns-struct or NULL if a memory allocation failed.
+*/
+static xmlNsPtr
+xmlTreeEnsureXMLDecl(xmlDocPtr doc)
+{
+    xmlNsPtr ns;
+
+    ns = doc->oldNs;
+    if (ns != NULL)
+	return (ns);
+
+    ns = xmlNewXmlNs();
+    doc->oldNs = ns;
+
+    return(ns);
+}
+
+/**
+ * xmlSearchNsSafe:
+ * @node:  a node
+ * @prefix:  a namespace prefix
+ * @out:  pointer to resulting namespace
+ *
+ * Search a namespace with @prefix in scope of @node.
+ *
+ * Returns 0 on success, -1 if a memory allocation failed, 1 on
+ * other errors.
+ */
+int
+xmlSearchNsSafe(xmlNodePtr node, const xmlChar *prefix,
+                xmlNsPtr *out) {
+    xmlNsPtr cur;
+    xmlDocPtr doc;
+    xmlNodePtr orig = node;
+    xmlNodePtr parent;
+
+    if (out == NULL)
+        return(1);
+    *out = NULL;
+    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
+        return(1);
+
+    doc = node->doc;
+
+    if ((doc != NULL) && (IS_STR_XML(prefix))) {
+        cur = xmlTreeEnsureXMLDecl(doc);
+        if (cur == NULL)
+            return(-1);
+        *out = cur;
+        return(0);
+    }
+
+    while (node->type != XML_ELEMENT_NODE) {
+        node = node->parent;
+        if (node == NULL)
+            return(0);
+    }
+
+    parent = node;
+
+    while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) {
+        cur = node->nsDef;
+        while (cur != NULL) {
+            if ((xmlStrEqual(cur->prefix, prefix)) &&
+                (cur->href != NULL)) {
+                *out = cur;
+                return(0);
             }
+            cur = cur->next;
         }
-        node = node->parent;
+        if (orig != node) {
+            cur = node->ns;
+            if ((cur != NULL) &&
+                (xmlStrEqual(cur->prefix, prefix)) &&
+                (cur->href != NULL)) {
+                *out = cur;
+                return(0);
+            }
+        }
+
+	node = node->parent;
     }
-    return (ret);
-}
-#endif /* LIBXML_TREE_ENABLED */
 
-/*
-* xmlTreeEnsureXMLDecl:
-* @doc: the doc
-*
-* Ensures that there is an XML namespace declaration on the doc.
-*
-* Returns the XML ns-struct or NULL on API and internal errors.
-*/
-static xmlNsPtr
-xmlTreeEnsureXMLDecl(xmlDocPtr doc)
-{
-    if (doc == NULL)
-	return (NULL);
-    if (doc->oldNs != NULL)
-	return (doc->oldNs);
-    {
-	xmlNsPtr ns;
-	ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
-	if (ns == NULL) {
-	    xmlTreeErrMemory(
-		"allocating the XML namespace");
-	    return (NULL);
-	}
-	memset(ns, 0, sizeof(xmlNs));
-	ns->type = XML_LOCAL_NAMESPACE;
-	ns->href = xmlStrdup(XML_XML_NAMESPACE);
-	ns->prefix = xmlStrdup((const xmlChar *)"xml");
-	doc->oldNs = ns;
-	return (ns);
+    /*
+     * The XML-1.0 namespace is normally held on the document
+     * element. In this case exceptionally create it on the
+     * node element.
+     */
+    if ((doc == NULL) && (IS_STR_XML(prefix))) {
+        cur = xmlNewXmlNs();
+        if (cur == NULL)
+            return(-1);
+        cur->next = parent->nsDef;
+        parent->nsDef = cur;
+        *out = cur;
     }
+
+    return(0);
 }
 
 /**
@@ -6115,82 +6114,17 @@ xmlTreeEnsureXMLDecl(xmlDocPtr doc)
  * the namespace within those you will be in troubles !!! A warning
  * is generated to cover this case.
  *
- * Returns the namespace pointer or NULL.
+ * Returns the namespace pointer or NULL if no namespace was found or
+ * a memory allocation failed. Allocations can only fail if the "xml"
+ * namespace is queried.
  */
 xmlNsPtr
-xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
-
+xmlSearchNs(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node,
+            const xmlChar *nameSpace) {
     xmlNsPtr cur;
-    const xmlNode *orig = node;
 
-    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) return(NULL);
-    if ((nameSpace != NULL) &&
-	(xmlStrEqual(nameSpace, (const xmlChar *)"xml"))) {
-	if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
-	    /*
-	     * The XML-1.0 namespace is normally held on the root
-	     * element. In this case exceptionally create it on the
-	     * node element.
-	     */
-	    cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
-	    if (cur == NULL) {
-		xmlTreeErrMemory("searching namespace");
-		return(NULL);
-	    }
-	    memset(cur, 0, sizeof(xmlNs));
-	    cur->type = XML_LOCAL_NAMESPACE;
-	    cur->href = xmlStrdup(XML_XML_NAMESPACE);
-	    cur->prefix = xmlStrdup((const xmlChar *)"xml");
-	    cur->next = node->nsDef;
-	    node->nsDef = cur;
-	    return(cur);
-	}
-	if (doc == NULL) {
-	    doc = node->doc;
-	    if (doc == NULL)
-		return(NULL);
-	}
-	/*
-	* Return the XML namespace declaration held by the doc.
-	*/
-	if (doc->oldNs == NULL)
-	    return(xmlTreeEnsureXMLDecl(doc));
-	else
-	    return(doc->oldNs);
-    }
-    while (node != NULL) {
-	if ((node->type == XML_ENTITY_REF_NODE) ||
-	    (node->type == XML_ENTITY_NODE) ||
-	    (node->type == XML_ENTITY_DECL))
-	    return(NULL);
-	if (node->type == XML_ELEMENT_NODE) {
-	    cur = node->nsDef;
-	    while (cur != NULL) {
-		if ((cur->prefix == NULL) && (nameSpace == NULL) &&
-		    (cur->href != NULL))
-		    return(cur);
-		if ((cur->prefix != NULL) && (nameSpace != NULL) &&
-		    (cur->href != NULL) &&
-		    (xmlStrEqual(cur->prefix, nameSpace)))
-		    return(cur);
-		cur = cur->next;
-	    }
-	    if (orig != node) {
-	        cur = node->ns;
-	        if (cur != NULL) {
-		    if ((cur->prefix == NULL) && (nameSpace == NULL) &&
-		        (cur->href != NULL))
-		        return(cur);
-		    if ((cur->prefix != NULL) && (nameSpace != NULL) &&
-		        (cur->href != NULL) &&
-		        (xmlStrEqual(cur->prefix, nameSpace)))
-		        return(cur);
-	        }
-	    }
-	}
-	node = node->parent;
-    }
-    return(NULL);
+    xmlSearchNsSafe(node, nameSpace, &cur);
+    return(cur);
 }
 
 /**
@@ -6213,7 +6147,6 @@ xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node,
 
     while ((node != NULL) && (node != ancestor)) {
         if ((node->type == XML_ENTITY_REF_NODE) ||
-            (node->type == XML_ENTITY_NODE) ||
             (node->type == XML_ENTITY_DECL))
             return (-1);
         if (node->type == XML_ELEMENT_NODE) {
@@ -6237,92 +6170,117 @@ xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node,
 }
 
 /**
- * xmlSearchNsByHref:
- * @doc:  the document
- * @node:  the current node
- * @href:  the namespace value
+ * xmlSearchNsByHrefSafe:
+ * @node:  a node
+ * @href:  a namespace URI
+ * @out:  pointer to resulting namespace
  *
- * Search a Ns aliasing a given URI. Recurse on the parents until it finds
- * the defined namespace or return NULL otherwise.
- * Returns the namespace pointer or NULL.
+ * Search a namespace matching @URI in scope of @node.
+ *
+ * Returns 0 on success, -1 if a memory allocation failed, 1 on
+ * other errors.
  */
-xmlNsPtr
-xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
-{
+int
+xmlSearchNsByHrefSafe(xmlNodePtr node, const xmlChar *href,
+                      xmlNsPtr *out) {
     xmlNsPtr cur;
+    xmlDocPtr doc;
     xmlNodePtr orig = node;
+    xmlNodePtr parent;
     int is_attr;
 
-    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) || (href == NULL))
-        return (NULL);
-    if (xmlStrEqual(href, XML_XML_NAMESPACE)) {
-        /*
-         * Only the document can hold the XML spec namespace.
-         */
-        if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
-            /*
-             * The XML-1.0 namespace is normally held on the root
-             * element. In this case exceptionally create it on the
-             * node element.
-             */
-            cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
-            if (cur == NULL) {
-		xmlTreeErrMemory("searching namespace");
-                return (NULL);
-            }
-            memset(cur, 0, sizeof(xmlNs));
-            cur->type = XML_LOCAL_NAMESPACE;
-            cur->href = xmlStrdup(XML_XML_NAMESPACE);
-            cur->prefix = xmlStrdup((const xmlChar *) "xml");
-            cur->next = node->nsDef;
-            node->nsDef = cur;
-            return (cur);
-        }
-	if (doc == NULL) {
-	    doc = node->doc;
-	    if (doc == NULL)
-		return(NULL);
-	}
-	/*
-	* Return the XML namespace declaration held by the doc.
-	*/
-	if (doc->oldNs == NULL)
-	    return(xmlTreeEnsureXMLDecl(doc));
-	else
-	    return(doc->oldNs);
+    if (out == NULL)
+        return(1);
+    *out = NULL;
+    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
+        return(1);
+
+    doc = node->doc;
+
+    if ((doc != NULL) && (xmlStrEqual(href, XML_XML_NAMESPACE))) {
+        cur = xmlTreeEnsureXMLDecl(doc);
+        if (cur == NULL)
+            return(-1);
+        *out = cur;
+        return(0);
     }
+
     is_attr = (node->type == XML_ATTRIBUTE_NODE);
-    while (node != NULL) {
-        if ((node->type == XML_ENTITY_REF_NODE) ||
-            (node->type == XML_ENTITY_NODE) ||
-            (node->type == XML_ENTITY_DECL))
-            return (NULL);
-        if (node->type == XML_ELEMENT_NODE) {
-            cur = node->nsDef;
-            while (cur != NULL) {
-                if ((cur->href != NULL) && (href != NULL) &&
-                    (xmlStrEqual(cur->href, href))) {
-		    if (((!is_attr) || (cur->prefix != NULL)) &&
-		        (xmlNsInScope(doc, orig, node, cur->prefix) == 1))
-			return (cur);
+
+    while (node->type != XML_ELEMENT_NODE) {
+        node = node->parent;
+        if (node == NULL)
+            return(0);
+    }
+
+    parent = node;
+
+    while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) {
+        cur = node->nsDef;
+        while (cur != NULL) {
+            if (xmlStrEqual(cur->href, href)) {
+                if (((!is_attr) || (cur->prefix != NULL)) &&
+                    (xmlNsInScope(doc, orig, node, cur->prefix) == 1)) {
+                    *out = cur;
+                    return(0);
                 }
-                cur = cur->next;
             }
-            if (orig != node) {
-                cur = node->ns;
-                if (cur != NULL) {
-                    if ((cur->href != NULL) && (href != NULL) &&
-                        (xmlStrEqual(cur->href, href))) {
-			if (((!is_attr) || (cur->prefix != NULL)) &&
-		            (xmlNsInScope(doc, orig, node, cur->prefix) == 1))
-			    return (cur);
+            cur = cur->next;
+        }
+        if (orig != node) {
+            cur = node->ns;
+            if (cur != NULL) {
+                if (xmlStrEqual(cur->href, href)) {
+                    if (((!is_attr) || (cur->prefix != NULL)) &&
+                        (xmlNsInScope(doc, orig, node,
+                                      cur->prefix) == 1)) {
+                        *out = cur;
+                        return(0);
                     }
                 }
             }
         }
+
         node = node->parent;
     }
-    return (NULL);
+
+    /*
+     * The XML-1.0 namespace is normally held on the document
+     * element. In this case exceptionally create it on the
+     * node element.
+     */
+    if ((doc == NULL) && (xmlStrEqual(href, XML_XML_NAMESPACE))) {
+        cur = xmlNewXmlNs();
+        if (cur == NULL)
+            return(-1);
+        cur->next = parent->nsDef;
+        parent->nsDef = cur;
+        *out = cur;
+    }
+
+    return(0);
+}
+
+/**
+ * xmlSearchNsByHref:
+ * @doc:  the document
+ * @node:  the current node
+ * @href:  the namespace value
+ *
+ * Search a Ns aliasing a given URI. Recurse on the parents until it finds
+ * the defined namespace or return NULL otherwise.
+ *
+ * Returns the namespace pointer or NULL if no namespace was found or
+ * a memory allocation failed. Allocations can only fail if the "xml"
+ * namespace is queried.
+ */
+xmlNsPtr
+xmlSearchNsByHref(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node,
+                  const xmlChar * href) {
+    xmlNsPtr cur;
+
+    xmlSearchNsByHrefSafe(node, href, &cur);
+    return(cur);
 }
 
 /**
@@ -6339,29 +6297,24 @@ xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
  * Returns the (new) namespace definition or NULL in case of error
  */
 static xmlNsPtr
-xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
+xmlNewReconciledNs(xmlNodePtr tree, xmlNsPtr ns) {
     xmlNsPtr def;
     xmlChar prefix[50];
     int counter = 1;
+    int res;
 
     if ((tree == NULL) || (tree->type != XML_ELEMENT_NODE)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewReconciledNs : tree == NULL\n");
-#endif
 	return(NULL);
     }
     if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewReconciledNs : ns == NULL\n");
-#endif
 	return(NULL);
     }
     /*
      * Search an existing namespace definition inherited.
      */
-    def = xmlSearchNsByHref(doc, tree, ns->href);
+    res = xmlSearchNsByHrefSafe(tree, ns->href, &def);
+    if (res < 0)
+        return(NULL);
     if (def != NULL)
         return(def);
 
@@ -6374,7 +6327,9 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
     else
 	snprintf((char *) prefix, sizeof(prefix), "%.20s", (char *)ns->prefix);
 
-    def = xmlSearchNs(doc, tree, prefix);
+    res = xmlSearchNsSafe(tree, prefix, &def);
+    if (res < 0)
+        return(NULL);
     while (def != NULL) {
         if (counter > 1000) return(NULL);
 	if (ns->prefix == NULL)
@@ -6382,7 +6337,9 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
 	else
 	    snprintf((char *) prefix, sizeof(prefix), "%.20s%d",
 		(char *)ns->prefix, counter++);
-	def = xmlSearchNs(doc, tree, prefix);
+	res = xmlSearchNsSafe(tree, prefix, &def);
+        if (res < 0)
+            return(NULL);
     }
 
     /*
@@ -6393,6 +6350,12 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
 }
 
 #ifdef LIBXML_TREE_ENABLED
+
+typedef struct {
+    xmlNsPtr oldNs;
+    xmlNsPtr newNs;
+} xmlNsCache;
+
 /**
  * xmlReconciliateNs:
  * @doc:  the document
@@ -6405,12 +6368,12 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
  * as possible the function try to reuse the existing namespaces found in
  * the new environment. If not possible the new namespaces are redeclared
  * on @tree at the top of the given subtree.
- * Returns the number of namespace declarations created or -1 in case of error.
+ *
+ * Returns 0 on success or -1 in case of error.
  */
 int
 xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
-    xmlNsPtr *oldNs = NULL;
-    xmlNsPtr *newNs = NULL;
+    xmlNsCache *cache = NULL;
     int sizeCache = 0;
     int nbCache = 0;
 
@@ -6420,35 +6383,15 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
     int ret = 0, i;
 
     if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) return(-1);
-    if ((doc == NULL) || (doc->type != XML_DOCUMENT_NODE)) return(-1);
     if (node->doc != doc) return(-1);
     while (node != NULL) {
         /*
 	 * Reconciliate the node namespace
 	 */
 	if (node->ns != NULL) {
-	    /*
-	     * initialize the cache if needed
-	     */
-	    if (sizeCache == 0) {
-		sizeCache = 10;
-		oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
-					       sizeof(xmlNsPtr));
-		if (oldNs == NULL) {
-		    xmlTreeErrMemory("fixing namespaces");
-		    return(-1);
-		}
-		newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
-					       sizeof(xmlNsPtr));
-		if (newNs == NULL) {
-		    xmlTreeErrMemory("fixing namespaces");
-		    xmlFree(oldNs);
-		    return(-1);
-		}
-	    }
-	    for (i = 0;i < nbCache;i++) {
-	        if (oldNs[i] == node->ns) {
-		    node->ns = newNs[i];
+	    for (i = 0; i < nbCache; i++) {
+	        if (cache[i].oldNs == node->ns) {
+		    node->ns = cache[i].newNs;
 		    break;
 		}
 	    }
@@ -6456,32 +6399,31 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
 	        /*
 		 * OK we need to recreate a new namespace definition
 		 */
-		n = xmlNewReconciledNs(doc, tree, node->ns);
-		if (n != NULL) { /* :-( what if else ??? */
+		n = xmlNewReconciledNs(tree, node->ns);
+		if (n == NULL) {
+                    ret = -1;
+                } else {
 		    /*
 		     * check if we need to grow the cache buffers.
 		     */
 		    if (sizeCache <= nbCache) {
-		        sizeCache *= 2;
-			oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
-			                               sizeof(xmlNsPtr));
-		        if (oldNs == NULL) {
-			    xmlTreeErrMemory("fixing namespaces");
-			    xmlFree(newNs);
-			    return(-1);
-			}
-			newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
-			                               sizeof(xmlNsPtr));
-		        if (newNs == NULL) {
-			    xmlTreeErrMemory("fixing namespaces");
-			    xmlFree(oldNs);
-			    return(-1);
-			}
+                        xmlNsCache *tmp;
+                        size_t newSize = sizeCache ? sizeCache * 2 : 10;
+
+			tmp = xmlRealloc(cache, newSize * sizeof(tmp[0]));
+		        if (tmp == NULL) {
+                            ret = -1;
+			} else {
+                            cache = tmp;
+                            sizeCache = newSize;
+                        }
 		    }
-		    newNs[nbCache] = n;
-		    oldNs[nbCache++] = node->ns;
-		    node->ns = n;
+		    if (nbCache < sizeCache) {
+                        cache[nbCache].newNs = n;
+                        cache[nbCache++].oldNs = node->ns;
+                    }
                 }
+		node->ns = n;
 	    }
 	}
 	/*
@@ -6491,28 +6433,9 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
 	    attr = node->properties;
 	    while (attr != NULL) {
 		if (attr->ns != NULL) {
-		    /*
-		     * initialize the cache if needed
-		     */
-		    if (sizeCache == 0) {
-			sizeCache = 10;
-			oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
-						       sizeof(xmlNsPtr));
-			if (oldNs == NULL) {
-			    xmlTreeErrMemory("fixing namespaces");
-			    return(-1);
-			}
-			newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
-						       sizeof(xmlNsPtr));
-			if (newNs == NULL) {
-			    xmlTreeErrMemory("fixing namespaces");
-			    xmlFree(oldNs);
-			    return(-1);
-			}
-		    }
-		    for (i = 0;i < nbCache;i++) {
-			if (oldNs[i] == attr->ns) {
-			    attr->ns = newNs[i];
+		    for (i = 0; i < nbCache; i++) {
+			if (cache[i].oldNs == attr->ns) {
+			    attr->ns = cache[i].newNs;
 			    break;
 			}
 		    }
@@ -6520,32 +6443,33 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
 			/*
 			 * OK we need to recreate a new namespace definition
 			 */
-			n = xmlNewReconciledNs(doc, tree, attr->ns);
-			if (n != NULL) { /* :-( what if else ??? */
+			n = xmlNewReconciledNs(tree, attr->ns);
+			if (n == NULL) {
+                            ret = -1;
+                        } else {
 			    /*
 			     * check if we need to grow the cache buffers.
 			     */
 			    if (sizeCache <= nbCache) {
-				sizeCache *= 2;
-				oldNs = (xmlNsPtr *) xmlRealloc(oldNs,
-				           sizeCache * sizeof(xmlNsPtr));
-				if (oldNs == NULL) {
-				    xmlTreeErrMemory("fixing namespaces");
-				    xmlFree(newNs);
-				    return(-1);
-				}
-				newNs = (xmlNsPtr *) xmlRealloc(newNs,
-				           sizeCache * sizeof(xmlNsPtr));
-				if (newNs == NULL) {
-				    xmlTreeErrMemory("fixing namespaces");
-				    xmlFree(oldNs);
-				    return(-1);
-				}
+                                xmlNsCache *tmp;
+                                size_t newSize = sizeCache ?
+                                        sizeCache * 2 : 10;
+
+                                tmp = xmlRealloc(cache,
+                                        newSize * sizeof(tmp[0]));
+                                if (tmp == NULL) {
+                                    ret = -1;
+                                } else {
+                                    cache = tmp;
+                                    sizeCache = newSize;
+                                }
+			    }
+			    if (nbCache < sizeCache) {
+                                cache[nbCache].newNs = n;
+                                cache[nbCache++].oldNs = attr->ns;
 			    }
-			    newNs[nbCache] = n;
-			    oldNs[nbCache++] = attr->ns;
-			    attr->ns = n;
 			}
+			attr->ns = n;
 		    }
 		}
 		attr = attr->next;
@@ -6581,10 +6505,8 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
 	} else
 	    break;
     }
-    if (oldNs != NULL)
-	xmlFree(oldNs);
-    if (newNs != NULL)
-	xmlFree(newNs);
+    if (cache != NULL)
+	xmlFree(cache);
     return(ret);
 }
 #endif /* LIBXML_TREE_ENABLED */
@@ -6646,7 +6568,11 @@ xmlGetPropNodeInternal(const xmlNode *node, const xmlChar *name,
 	*/
 	if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
 	    tmpstr = xmlStrdup(node->ns->prefix);
+	    if (tmpstr == NULL)
+		return(NULL);
 	    tmpstr = xmlStrcat(tmpstr, BAD_CAST ":");
+	    if (tmpstr == NULL)
+		return(NULL);
 	    tmpstr = xmlStrcat(tmpstr, node->name);
 	    if (tmpstr == NULL)
 		return(NULL);
@@ -6722,28 +6648,7 @@ xmlGetPropNodeValueInternal(const xmlAttr *prop)
     if (prop == NULL)
 	return(NULL);
     if (prop->type == XML_ATTRIBUTE_NODE) {
-	/*
-	* Note that we return at least the empty string.
-	*   TODO: Do we really always want that?
-	*/
-	if (prop->children != NULL) {
-	    if ((prop->children->next == NULL) &&
-		((prop->children->type == XML_TEXT_NODE) ||
-		(prop->children->type == XML_CDATA_SECTION_NODE)))
-	    {
-		/*
-		* Optimization for the common case: only 1 text node.
-		*/
-		return(xmlStrdup(prop->children->content));
-	    } else {
-		xmlChar *ret;
-
-		ret = xmlNodeListGetString(prop->doc, prop->children, 1);
-		if (ret != NULL)
-		    return(ret);
-	    }
-	}
-	return(xmlStrdup((xmlChar *)""));
+	return(xmlNodeGetContent((xmlNodePtr) prop));
     } else if (prop->type == XML_ATTRIBUTE_DECL) {
 	return(xmlStrdup(((xmlAttributePtr)prop)->defaultValue));
     }
@@ -6757,10 +6662,11 @@ xmlGetPropNodeValueInternal(const xmlAttr *prop)
  *
  * Search an attribute associated to a node
  * This function also looks in DTD attribute declaration for #FIXED or
- * default declaration values unless DTD use has been turned off.
+ * default declaration values.
  *
  * Returns the attribute or the attribute declaration or NULL if
- *         neither was found.
+ * neither was found. Also returns NULL if a memory allocation failed
+ * making this function unreliable.
  */
 xmlAttrPtr
 xmlHasProp(const xmlNode *node, const xmlChar *name) {
@@ -6779,7 +6685,6 @@ xmlHasProp(const xmlNode *node, const xmlChar *name) {
         }
 	prop = prop->next;
     }
-    if (!xmlCheckDTD) return(NULL);
 
     /*
      * Check if there is a default declaration in the internal
@@ -6811,16 +6716,53 @@ xmlHasProp(const xmlNode *node, const xmlChar *name) {
  * This attribute has to be anchored in the namespace specified.
  * This does the entity substitution.
  * This function looks in DTD attribute declaration for #FIXED or
- * default declaration values unless DTD use has been turned off.
+ * default declaration values.
  * Note that a namespace of NULL indicates to use the default namespace.
  *
- * Returns the attribute or the attribute declaration or NULL
- *     if neither was found.
+ * Returns the attribute or the attribute declaration or NULL if
+ * neither was found. Also returns NULL if a memory allocation failed
+ * making this function unreliable.
  */
 xmlAttrPtr
 xmlHasNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) {
 
-    return(xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD));
+    return(xmlGetPropNodeInternal(node, name, nameSpace, 1));
+}
+
+/**
+ * xmlNodeGetAttrValue:
+ * @node:  the node
+ * @name:  the attribute name
+ * @nsUri:  the URI of the namespace
+ * @out:  the returned string
+ *
+ * Search and get the value of an attribute associated to a node
+ * This attribute has to be anchored in the namespace specified.
+ * This does the entity substitution. The returned value must be
+ * freed by the caller.
+ *
+ * Available since 2.13.0.
+ *
+ * Returns 0 on success, 1 if no attribute was found, -1 if a
+ * memory allocation failed.
+ */
+int
+xmlNodeGetAttrValue(const xmlNode *node, const xmlChar *name,
+                    const xmlChar *nsUri, xmlChar **out) {
+    xmlAttrPtr prop;
+
+    if (out == NULL)
+        return(1);
+    *out = NULL;
+
+    prop = xmlGetPropNodeInternal(node, name, nsUri, 0);
+    if (prop == NULL)
+	return(1);
+
+    *out = xmlGetPropNodeValueInternal(prop);
+    if (*out == NULL)
+        return(-1);
+    return(0);
 }
 
 /**
@@ -6831,13 +6773,17 @@ xmlHasNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace)
  * Search and get the value of an attribute associated to a node
  * This does the entity substitution.
  * This function looks in DTD attribute declaration for #FIXED or
- * default declaration values unless DTD use has been turned off.
- * NOTE: this function acts independently of namespaces associated
+ * default declaration values.
+ *
+ * NOTE: This function acts independently of namespaces associated
  *       to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp()
  *       for namespace aware processing.
  *
- * Returns the attribute value or NULL if not found.
- *     It's up to the caller to free the memory with xmlFree().
+ * NOTE: This function doesn't allow to distinguish malloc failures from
+ *       missing attributes. It's more robust to use xmlNodeGetAttrValue.
+ *
+ * Returns the attribute value or NULL if not found or a memory allocation
+ * failed. It's up to the caller to free the memory with xmlFree().
  */
 xmlChar *
 xmlGetProp(const xmlNode *node, const xmlChar *name) {
@@ -6857,18 +6803,21 @@ xmlGetProp(const xmlNode *node, const xmlChar *name) {
  * Search and get the value of an attribute associated to a node
  * This does the entity substitution.
  * This function looks in DTD attribute declaration for #FIXED or
- * default declaration values unless DTD use has been turned off.
+ * default declaration values.
  * This function is similar to xmlGetProp except it will accept only
  * an attribute in no namespace.
  *
- * Returns the attribute value or NULL if not found.
- *     It's up to the caller to free the memory with xmlFree().
+ * NOTE: This function doesn't allow to distinguish malloc failures from
+ *       missing attributes. It's more robust to use xmlNodeGetAttrValue.
+ *
+ * Returns the attribute value or NULL if not found or a memory allocation
+ * failed. It's up to the caller to free the memory with xmlFree().
  */
 xmlChar *
 xmlGetNoNsProp(const xmlNode *node, const xmlChar *name) {
     xmlAttrPtr prop;
 
-    prop = xmlGetPropNodeInternal(node, name, NULL, xmlCheckDTD);
+    prop = xmlGetPropNodeInternal(node, name, NULL, 1);
     if (prop == NULL)
 	return(NULL);
     return(xmlGetPropNodeValueInternal(prop));
@@ -6884,16 +6833,19 @@ xmlGetNoNsProp(const xmlNode *node, const xmlChar *name) {
  * This attribute has to be anchored in the namespace specified.
  * This does the entity substitution.
  * This function looks in DTD attribute declaration for #FIXED or
- * default declaration values unless DTD use has been turned off.
+ * default declaration values.
  *
- * Returns the attribute value or NULL if not found.
- *     It's up to the caller to free the memory with xmlFree().
+ * NOTE: This function doesn't allow to distinguish malloc failures from
+ *       missing attributes. It's more robust to use xmlNodeGetAttrValue.
+ *
+ * Returns the attribute value or NULL if not found or a memory allocation
+ * failed. It's up to the caller to free the memory with xmlFree().
  */
 xmlChar *
 xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) {
     xmlAttrPtr prop;
 
-    prop = xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD);
+    prop = xmlGetPropNodeInternal(node, name, nameSpace, 1);
     if (prop == NULL)
 	return(NULL);
     return(xmlGetPropNodeValueInternal(prop));
@@ -6916,7 +6868,7 @@ xmlUnsetProp(xmlNodePtr node, const xmlChar *name) {
     prop = xmlGetPropNodeInternal(node, name, NULL, 0);
     if (prop == NULL)
 	return(-1);
-    xmlUnlinkNode((xmlNodePtr) prop);
+    xmlUnlinkNodeInternal((xmlNodePtr) prop);
     xmlFreeProp(prop);
     return(0);
 }
@@ -6934,10 +6886,11 @@ int
 xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) {
     xmlAttrPtr prop;
 
-    prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
+    prop = xmlGetPropNodeInternal(node, name,
+                                  (ns != NULL) ? ns->href : NULL, 0);
     if (prop == NULL)
 	return(-1);
-    xmlUnlinkNode((xmlNodePtr) prop);
+    xmlUnlinkNodeInternal((xmlNodePtr) prop);
     xmlFreeProp(prop);
     return(0);
 }
@@ -6960,8 +6913,10 @@ xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) {
  */
 xmlAttrPtr
 xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
-    int len;
-    const xmlChar *nqname;
+    xmlNsPtr ns = NULL;
+    const xmlChar *localname;
+    xmlChar *prefix;
+    int res;
 
     if ((node == NULL) || (name == NULL) || (node->type != XML_ELEMENT_NODE))
 	return(NULL);
@@ -6969,16 +6924,19 @@ xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
     /*
      * handle QNames
      */
-    nqname = xmlSplitQName3(name, &len);
-    if (nqname != NULL) {
-        xmlNsPtr ns;
-	xmlChar *prefix = xmlStrndup(name, len);
-	ns = xmlSearchNs(node->doc, node, prefix);
-	if (prefix != NULL)
-	    xmlFree(prefix);
-	if (ns != NULL)
-	    return(xmlSetNsProp(node, ns, nqname, value));
+    localname = xmlSplitQName4(name, &prefix);
+    if (localname == NULL)
+        return(NULL);
+
+    if (prefix != NULL) {
+	res = xmlSearchNsSafe(node, prefix, &ns);
+	xmlFree(prefix);
+        if (res < 0)
+            return(NULL);
+        if (ns != NULL)
+            return(xmlSetNsProp(node, ns, localname, value));
     }
+
     return(xmlSetNsProp(node, NULL, name, value));
 }
 
@@ -7002,11 +6960,22 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
 
     if (ns && (ns->href == NULL))
 	return(NULL);
-    prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
+    if (name == NULL)
+        return(NULL);
+    prop = xmlGetPropNodeInternal(node, name,
+                                  (ns != NULL) ? ns->href : NULL, 0);
     if (prop != NULL) {
+        xmlNodePtr children = NULL;
+
 	/*
 	* Modify the attribute's value.
 	*/
+        if (value != NULL) {
+	    children = xmlNewDocText(node->doc, value);
+            if (children == NULL)
+                return(NULL);
+        }
+
 	if (prop->atype == XML_ATTRIBUTE_ID) {
 	    xmlRemoveID(node->doc, prop);
 	    prop->atype = XML_ATTRIBUTE_ID;
@@ -7019,7 +6988,7 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
 	if (value != NULL) {
 	    xmlNodePtr tmp;
 
-	    prop->children = xmlNewDocText(node->doc, value);
+	    prop->children = children;
 	    prop->last = NULL;
 	    tmp = prop->children;
 	    while (tmp != NULL) {
@@ -7029,8 +6998,10 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
 		tmp = tmp->next;
 	    }
 	}
-	if (prop->atype == XML_ATTRIBUTE_ID)
-	    xmlAddID(NULL, node->doc, value, prop);
+	if ((prop->atype == XML_ATTRIBUTE_ID) &&
+	    (xmlAddIDSafe(prop, value) < 0)) {
+            return(NULL);
+        }
 	return(prop);
     }
     /*
@@ -7089,37 +7060,25 @@ xmlIsBlankNode(const xmlNode *node) {
  * @content:  the content
  * @len:  @content length
  *
- * Concat the given string at the end of the existing node content
+ * Concat the given string at the end of the existing node content.
+ *
+ * If @len is -1, the string length will be calculated.
  *
  * Returns -1 in case of error, 0 otherwise
  */
 
 int
 xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
-    if (node == NULL) return(-1);
+    if (node == NULL)
+        return(-1);
 
     if ((node->type != XML_TEXT_NODE) &&
         (node->type != XML_CDATA_SECTION_NODE) &&
 	(node->type != XML_COMMENT_NODE) &&
-	(node->type != XML_PI_NODE)) {
-#ifdef DEBUG_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlTextConcat: node is not text nor CDATA\n");
-#endif
-        return(-1);
-    }
-    /* need to check if content is currently in the dictionary */
-    if ((node->content == (xmlChar *) &(node->properties)) ||
-        ((node->doc != NULL) && (node->doc->dict != NULL) &&
-		xmlDictOwns(node->doc->dict, node->content))) {
-	node->content = xmlStrncatNew(node->content, content, len);
-    } else {
-        node->content = xmlStrncat(node->content, content, len);
-    }
-    node->properties = NULL;
-    if (node->content == NULL)
+	(node->type != XML_PI_NODE))
         return(-1);
-    return(0);
+
+    return(xmlTextAddContent(node, content, len));
 }
 
 /************************************************************************
@@ -7139,16 +7098,13 @@ xmlBufferCreate(void) {
     xmlBufferPtr ret;
 
     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
-    if (ret == NULL) {
-	xmlTreeErrMemory("creating buffer");
+    if (ret == NULL)
         return(NULL);
-    }
     ret->use = 0;
     ret->size = xmlDefaultBufferSize;
     ret->alloc = xmlBufferAllocScheme;
-    ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
+    ret->content = (xmlChar *) xmlMallocAtomic(ret->size);
     if (ret->content == NULL) {
-	xmlTreeErrMemory("creating buffer");
 	xmlFree(ret);
         return(NULL);
     }
@@ -7171,17 +7127,14 @@ xmlBufferCreateSize(size_t size) {
     if (size >= UINT_MAX)
         return(NULL);
     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
-    if (ret == NULL) {
-	xmlTreeErrMemory("creating buffer");
+    if (ret == NULL)
         return(NULL);
-    }
     ret->use = 0;
     ret->alloc = xmlBufferAllocScheme;
     ret->size = (size ? size + 1 : 0);         /* +1 for ending null */
     if (ret->size){
-        ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
+        ret->content = (xmlChar *) xmlMallocAtomic(ret->size);
         if (ret->content == NULL) {
-	    xmlTreeErrMemory("creating buffer");
             xmlFree(ret);
             return(NULL);
         }
@@ -7208,8 +7161,6 @@ xmlBufferDetach(xmlBufferPtr buf) {
 
     if (buf == NULL)
         return(NULL);
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
-        return(NULL);
 
     ret = buf->content;
     buf->content = NULL;
@@ -7225,31 +7176,14 @@ xmlBufferDetach(xmlBufferPtr buf) {
  * @mem: the memory area
  * @size:  the size in byte
  *
- * routine to create an XML buffer from an immutable memory area.
- * The area won't be modified nor copied, and is expected to be
- * present until the end of the buffer lifetime.
- *
- * returns the new structure.
+ * Returns an XML buffer initialized with bytes.
  */
 xmlBufferPtr
 xmlBufferCreateStatic(void *mem, size_t size) {
-    xmlBufferPtr ret;
+    xmlBufferPtr buf = xmlBufferCreateSize(size);
 
-    if ((mem == NULL) || (size == 0))
-        return(NULL);
-    if (size > UINT_MAX)
-        return(NULL);
-
-    ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
-    if (ret == NULL) {
-	xmlTreeErrMemory("creating buffer");
-        return(NULL);
-    }
-    ret->use = size;
-    ret->size = size;
-    ret->alloc = XML_BUFFER_ALLOC_IMMUTABLE;
-    ret->content = (xmlChar *) mem;
-    return(ret);
+    xmlBufferAdd(buf, mem, size);
+    return(buf);
 }
 
 /**
@@ -7263,18 +7197,12 @@ void
 xmlBufferSetAllocationScheme(xmlBufferPtr buf,
                              xmlBufferAllocationScheme scheme) {
     if (buf == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferSetAllocationScheme: buf == NULL\n");
-#endif
         return;
     }
-    if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
-        (buf->alloc == XML_BUFFER_ALLOC_IO)) return;
+    if (buf->alloc == XML_BUFFER_ALLOC_IO) return;
     if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
         (scheme == XML_BUFFER_ALLOC_EXACT) ||
-        (scheme == XML_BUFFER_ALLOC_HYBRID) ||
-        (scheme == XML_BUFFER_ALLOC_IMMUTABLE))
+        (scheme == XML_BUFFER_ALLOC_HYBRID))
 	buf->alloc = scheme;
 }
 
@@ -7288,18 +7216,13 @@ xmlBufferSetAllocationScheme(xmlBufferPtr buf,
 void
 xmlBufferFree(xmlBufferPtr buf) {
     if (buf == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferFree: buf == NULL\n");
-#endif
 	return;
     }
 
     if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
         (buf->contentIO != NULL)) {
         xmlFree(buf->contentIO);
-    } else if ((buf->content != NULL) &&
-        (buf->alloc != XML_BUFFER_ALLOC_IMMUTABLE)) {
+    } else if (buf->content != NULL) {
         xmlFree(buf->content);
     }
     xmlFree(buf);
@@ -7316,10 +7239,7 @@ xmlBufferEmpty(xmlBufferPtr buf) {
     if (buf == NULL) return;
     if (buf->content == NULL) return;
     buf->use = 0;
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) {
-        buf->content = BAD_CAST "";
-    } else if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
-               (buf->contentIO != NULL)) {
+    if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
         size_t start_buf = buf->content - buf->contentIO;
 
 	buf->size += start_buf;
@@ -7346,8 +7266,7 @@ xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
     if (len > buf->use) return(-1);
 
     buf->use -= len;
-    if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
-        ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL))) {
+    if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
 	/*
 	 * we just move the content pointer, but also make sure
 	 * the perceived buffer size has shrunk accordingly
@@ -7391,13 +7310,10 @@ xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
 
     if (buf == NULL) return(-1);
 
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
     if (len < buf->size - buf->use)
         return(0);
-    if (len >= UINT_MAX - buf->use) {
-        xmlTreeErrMemory("growing buffer past UINT_MAX");
+    if (len >= UINT_MAX - buf->use)
         return(-1);
-    }
 
     if (buf->size > (size_t) len) {
         size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2;
@@ -7410,18 +7326,14 @@ xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
         size_t start_buf = buf->content - buf->contentIO;
 
 	newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);
-	if (newbuf == NULL) {
-	    xmlTreeErrMemory("growing buffer");
+	if (newbuf == NULL)
 	    return(-1);
-	}
 	buf->contentIO = newbuf;
 	buf->content = newbuf + start_buf;
     } else {
 	newbuf = (xmlChar *) xmlRealloc(buf->content, size);
-	if (newbuf == NULL) {
-	    xmlTreeErrMemory("growing buffer");
+	if (newbuf == NULL)
 	    return(-1);
-	}
 	buf->content = newbuf;
     }
     buf->size = size;
@@ -7441,23 +7353,15 @@ xmlBufferDump(FILE *file, xmlBufferPtr buf) {
     size_t ret;
 
     if (buf == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferDump: buf == NULL\n");
-#endif
 	return(0);
     }
     if (buf->content == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferDump: buf->content == NULL\n");
-#endif
 	return(0);
     }
     if (file == NULL)
 	file = stdout;
-    ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
-    return(ret > INT_MAX ? INT_MAX : (int)ret);
+    ret = fwrite(buf->content, 1, buf->use, file);
+    return(ret > INT_MAX ? INT_MAX : ret);
 }
 
 /**
@@ -7515,16 +7419,12 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
     if (buf == NULL)
         return(0);
 
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
-
     /* Don't resize if we don't have to */
     if (size < buf->size)
         return 1;
 
-    if (size > UINT_MAX - 10) {
-        xmlTreeErrMemory("growing buffer past UINT_MAX");
+    if (size > UINT_MAX - 10)
         return 0;
-    }
 
     /* figure out new size */
     switch (buf->alloc){
@@ -7532,19 +7432,17 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
 	case XML_BUFFER_ALLOC_DOUBLEIT:
 	    /*take care of empty case*/
             if (buf->size == 0)
-                newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);
+                newSize = size + 10;
             else
                 newSize = buf->size;
 	    while (size > newSize) {
-	        if (newSize > UINT_MAX / 2) {
-	            xmlTreeErrMemory("growing buffer");
+	        if (newSize > UINT_MAX / 2)
 	            return 0;
-	        }
 	        newSize *= 2;
 	    }
 	    break;
 	case XML_BUFFER_ALLOC_EXACT:
-	    newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);
+	    newSize = size + 10;
 	    break;
         case XML_BUFFER_ALLOC_HYBRID:
             if (buf->use < BASE_BUFFER_SIZE)
@@ -7552,17 +7450,15 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
             else {
                 newSize = buf->size;
                 while (size > newSize) {
-                    if (newSize > UINT_MAX / 2) {
-                        xmlTreeErrMemory("growing buffer");
+                    if (newSize > UINT_MAX / 2)
                         return 0;
-                    }
                     newSize *= 2;
                 }
             }
             break;
 
 	default:
-	    newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);
+	    newSize = size + 10;
 	    break;
     }
 
@@ -7577,10 +7473,8 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
 	    buf->size += start_buf;
 	} else {
 	    rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);
-	    if (rebuf == NULL) {
-		xmlTreeErrMemory("growing buffer");
+	    if (rebuf == NULL)
 		return 0;
-	    }
 	    buf->contentIO = rebuf;
 	    buf->content = rebuf + start_buf;
 	}
@@ -7604,10 +7498,8 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
 		rebuf[buf->use] = 0;
 	    }
 	}
-	if (rebuf == NULL) {
-	    xmlTreeErrMemory("growing buffer");
+	if (rebuf == NULL)
 	    return 0;
-	}
 	buf->content = rebuf;
     }
     buf->size = newSize;
@@ -7634,12 +7526,7 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
     if ((str == NULL) || (buf == NULL)) {
 	return -1;
     }
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
     if (len < -1) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferAdd: len < 0\n");
-#endif
 	return -1;
     }
     if (len == 0) return 0;
@@ -7652,18 +7539,14 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
 
     /* Note that both buf->size and buf->use can be zero here. */
     if ((unsigned) len >= buf->size - buf->use) {
-        if ((unsigned) len >= UINT_MAX - buf->use) {
-            xmlTreeErrMemory("growing buffer past UINT_MAX");
+        if ((unsigned) len >= UINT_MAX - buf->use)
             return XML_ERR_NO_MEMORY;
-        }
         needSize = buf->use + len + 1;
-        if (!xmlBufferResize(buf, needSize)){
-	    xmlTreeErrMemory("growing buffer");
+        if (!xmlBufferResize(buf, needSize))
             return XML_ERR_NO_MEMORY;
-        }
     }
 
-    memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
+    memmove(&buf->content[buf->use], str, len);
     buf->use += len;
     buf->content[buf->use] = 0;
     return 0;
@@ -7687,19 +7570,10 @@ xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
 
     if (buf == NULL)
         return(-1);
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
     if (str == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferAddHead: str == NULL\n");
-#endif
 	return -1;
     }
     if (len < -1) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferAddHead: len < 0\n");
-#endif
 	return -1;
     }
     if (len == 0) return 0;
@@ -7726,15 +7600,11 @@ xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
     }
     /* Note that both buf->size and buf->use can be zero here. */
     if ((unsigned) len >= buf->size - buf->use) {
-        if ((unsigned) len >= UINT_MAX - buf->use) {
-            xmlTreeErrMemory("growing buffer past UINT_MAX");
+        if ((unsigned) len >= UINT_MAX - buf->use)
             return(-1);
-        }
         needSize = buf->use + len + 1;
-        if (!xmlBufferResize(buf, needSize)){
-	    xmlTreeErrMemory("growing buffer");
-            return XML_ERR_NO_MEMORY;
-        }
+        if (!xmlBufferResize(buf, needSize))
+            return(-1);
     }
 
     memmove(&buf->content[len], &buf->content[0], buf->use);
@@ -7758,7 +7628,6 @@ int
 xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
     if (buf == NULL)
         return(-1);
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
     if (str == NULL) return -1;
     return xmlBufferAdd(buf, str, -1);
 }
@@ -7790,7 +7659,6 @@ void
 xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
     if (buf == NULL)
         return;
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
     xmlBufferCat(buf, string);
 }
 
@@ -7806,7 +7674,6 @@ void
 xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
     if (buf == NULL)
         return;
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
     xmlBufferCCat(buf, string);
 }
 
@@ -7825,13 +7692,8 @@ xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
     const xmlChar *cur, *base;
     if (buf == NULL)
         return;
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
     if (xmlStrchr(string, '\"')) {
         if (xmlStrchr(string, '\'')) {
-#ifdef DEBUG_BUFFER
-	    xmlGenericError(xmlGenericErrorContext,
- "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
-#endif
 	    xmlBufferCCat(buf, "\"");
             base = cur = string;
             while(*cur != 0){
@@ -7895,6 +7757,8 @@ xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
 /**
  * xmlGetCompressMode:
  *
+ * DEPRECATED: Use xmlGetDocCompressMode
+ *
  * get the default compression mode used, ZLIB based.
  * Returns 0 (uncompressed) to 9 (max compression)
  */
@@ -7908,6 +7772,8 @@ xmlGetCompressMode(void)
  * xmlSetCompressMode:
  * @mode:  the compression ratio
  *
+ * DEPRECATED: Use xmlSetDocCompressMode
+ *
  * set the default compression mode used, ZLIB based
  * Correct values: 0 (uncompressed) to 9 (max compression)
  */
@@ -8015,10 +7881,8 @@ xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position,
 	* Create the ns-map.
 	*/
 	map = (xmlNsMapPtr) xmlMalloc(sizeof(struct xmlNsMap));
-	if (map == NULL) {
-	    xmlTreeErrMemory("allocating namespace map");
-	    return (NULL);
-	}
+	if (map == NULL)
+	    return(NULL);
 	memset(map, 0, sizeof(struct xmlNsMap));
 	*nsmap = map;
     }
@@ -8035,10 +7899,8 @@ xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position,
 	* Create a new item.
 	*/
 	ret = (xmlNsMapItemPtr) xmlMalloc(sizeof(struct xmlNsMapItem));
-	if (ret == NULL) {
-	    xmlTreeErrMemory("allocating namespace map item");
-	    return (NULL);
-	}
+	if (ret == NULL)
+	    return(NULL);
 	memset(ret, 0, sizeof(struct xmlNsMapItem));
     }
 
@@ -8130,10 +7992,8 @@ xmlDOMWrapNewCtxt(void)
     xmlDOMWrapCtxtPtr ret;
 
     ret = xmlMalloc(sizeof(xmlDOMWrapCtxt));
-    if (ret == NULL) {
-	xmlTreeErrMemory("allocating DOM-wrapper context");
+    if (ret == NULL)
 	return (NULL);
-    }
     memset(ret, 0, sizeof(xmlDOMWrapCtxt));
     return (ret);
 }
@@ -8249,39 +8109,6 @@ xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr *map,
     return (0);
 }
 
-/*
-* XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict;
-* otherwise copy it, when it was in the source-dict.
-*/
-#define XML_TREE_ADOPT_STR(str) \
-    if (adoptStr && (str != NULL)) { \
-	if (destDoc->dict) { \
-	    const xmlChar *old = str;	\
-	    str = xmlDictLookup(destDoc->dict, str, -1); \
-	    if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \
-	        (!xmlDictOwns(sourceDoc->dict, old))) \
-		xmlFree((char *)old); \
-	} else if ((sourceDoc) && (sourceDoc->dict) && \
-	    xmlDictOwns(sourceDoc->dict, str)) { \
-	    str = BAD_CAST xmlStrdup(str); \
-	} \
-    }
-
-/*
-* XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then
-* put it in dest-dict or copy it.
-*/
-#define XML_TREE_ADOPT_STR_2(str) \
-    if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \
-	(sourceDoc->dict != NULL) && \
-	xmlDictOwns(sourceDoc->dict, cur->content)) { \
-	if (destDoc->dict) \
-	    cur->content = (xmlChar *) \
-		xmlDictLookup(destDoc->dict, cur->content, -1); \
-	else \
-	    cur->content = xmlStrdup(BAD_CAST cur->content); \
-    }
-
 /*
 * xmlDOMWrapNSNormAddNsMapItem2:
 *
@@ -8293,23 +8120,18 @@ static int
 xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number,
 			xmlNsPtr oldNs, xmlNsPtr newNs)
 {
-    if (*list == NULL) {
-	*list = (xmlNsPtr *) xmlMalloc(6 * sizeof(xmlNsPtr));
-	if (*list == NULL) {
-	    xmlTreeErrMemory("alloc ns map item");
-	    return(-1);
-	}
-	*size = 3;
-	*number = 0;
-    } else if ((*number) >= (*size)) {
-	*size *= 2;
-	*list = (xmlNsPtr *) xmlRealloc(*list,
-	    (*size) * 2 * sizeof(xmlNsPtr));
-	if (*list == NULL) {
-	    xmlTreeErrMemory("realloc ns map item");
-	    return(-1);
-	}
+    if (*number >= *size) {
+        xmlNsPtr *tmp;
+        size_t newSize;
+
+        newSize = *size ? *size * 2 : 3;
+        tmp = xmlRealloc(*list, newSize * 2 * sizeof(tmp[0]));
+        if (tmp == NULL)
+            return(-1);
+        *list = tmp;
+        *size = newSize;
     }
+
     (*list)[2 * (*number)] = oldNs;
     (*list)[2 * (*number) +1] = newNs;
     (*number)++;
@@ -8338,7 +8160,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc,
 		     xmlNodePtr node, int options ATTRIBUTE_UNUSED)
 {
     xmlNsPtr *list = NULL;
-    int sizeList, nbList, i, j;
+    int sizeList = 0, nbList = 0, ret = 0, i, j;
     xmlNsPtr ns;
 
     if ((node == NULL) || (doc == NULL) || (node->doc != doc))
@@ -8354,7 +8176,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc,
 	case XML_ENTITY_REF_NODE:
 	case XML_PI_NODE:
 	case XML_COMMENT_NODE:
-	    xmlUnlinkNode(node);
+	    xmlUnlinkNodeInternal(node);
 	    return (0);
 	case XML_ELEMENT_NODE:
 	case XML_ATTRIBUTE_NODE:
@@ -8362,7 +8184,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc,
 	default:
 	    return (1);
     }
-    xmlUnlinkNode(node);
+    xmlUnlinkNodeInternal(node);
     /*
     * Save out-of-scope ns-references in doc->oldNs.
     */
@@ -8374,7 +8196,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc,
 		    do {
 			if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,
 			    &nbList, ns, ns) == -1)
-			    goto internal_error;
+			    ret = -1;
 			ns = ns->next;
 		    } while (ns != NULL);
 		}
@@ -8404,7 +8226,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc,
 			ns = xmlDOMWrapStoreNs(doc, node->ns->href,
 			    node->ns->prefix);
 			if (ns == NULL)
-			    goto internal_error;
+			    ret = -1;
 		    }
 		    if (ns != NULL) {
 			/*
@@ -8412,7 +8234,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc,
 			*/
 			if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,
 			    &nbList, node->ns, ns) == -1)
-			    goto internal_error;
+			    ret = -1;
 		    }
 		    node->ns = ns;
 		}
@@ -8437,19 +8259,22 @@ next_sibling:
 	if (node->next != NULL)
 	    node = node->next;
 	else {
+            int type = node->type;
+
 	    node = node->parent;
-	    goto next_sibling;
+            if ((type == XML_ATTRIBUTE_NODE) &&
+                (node != NULL) &&
+                (node->children != NULL)) {
+                node = node->children;
+            } else {
+	        goto next_sibling;
+            }
 	}
     } while (node != NULL);
 
     if (list != NULL)
 	xmlFree(list);
-    return (0);
-
-internal_error:
-    if (list != NULL)
-	xmlFree(list);
-    return (-1);
+    return (ret);
 }
 
 /*
@@ -8547,8 +8372,7 @@ xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node,
 		out = prev;
 		prev = cur;
 	    }
-	} else if ((cur->type == XML_ENTITY_NODE) ||
-            (cur->type == XML_ENTITY_DECL))
+	} else if (cur->type == XML_ENTITY_DECL)
 	    return (0);
 	cur = cur->parent;
     } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
@@ -8610,8 +8434,7 @@ xmlSearchNsByPrefixStrict(xmlDocPtr doc, xmlNodePtr node,
 		    ns = ns->next;
 		} while (ns != NULL);
 	    }
-	} else if ((cur->type == XML_ENTITY_NODE) ||
-            (cur->type == XML_ENTITY_DECL))
+	} else if (cur->type == XML_ENTITY_DECL)
 	    return (0);
 	cur = cur->parent;
     } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
@@ -8795,7 +8618,6 @@ xmlDOMWrapNSNormAcquireNormalizedNs(xmlDocPtr doc,
 	*/
 	if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns,
 		tmpns, XML_TREE_NSMAP_DOC) == NULL) {
-	    xmlFreeNs(tmpns);
 	    return (-1);
 	}
 	*retNs = tmpns;
@@ -8825,7 +8647,6 @@ xmlDOMWrapNSNormAcquireNormalizedNs(xmlDocPtr doc,
 	    }
 	}
 	if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, tmpns, depth) == NULL) {
-	    xmlFreeNs(tmpns);
 	    return (-1);
 	}
 	*retNs = tmpns;
@@ -8870,7 +8691,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
     int optRemoveRedundantNS =
 	((xmlDOMReconcileNSOptions) options & XML_DOM_RECONNS_REMOVEREDUND) ? 1 : 0;
     xmlNsPtr *listRedund = NULL;
-    int sizeRedund = 0, nbRedund = 0, ret, i, j;
+    int sizeRedund = 0, nbRedund = 0, ret = 0, i, j;
 
     if ((elem == NULL) || (elem->doc == NULL) ||
 	(elem->type != XML_ELEMENT_NODE))
@@ -8899,7 +8720,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
 				*/
 				if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
 				    elem->parent) == -1)
-				    goto internal_error;
+				    ret = -1;
 			    }
 			    parnsdone = 1;
 			}
@@ -8921,16 +8742,18 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
 				    * Add it to the list of redundant ns-decls.
 				    */
 				    if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund,
-					&sizeRedund, &nbRedund, ns, mi->newNs) == -1)
-					goto internal_error;
-				    /*
-				    * Remove the ns-decl from the element-node.
-				    */
-				    if (prevns)
-					prevns->next = ns->next;
-				    else
-					cur->nsDef = ns->next;
-				    goto next_ns_decl;
+					&sizeRedund, &nbRedund, ns, mi->newNs) == -1) {
+					ret = -1;
+                                    } else {
+                                        /*
+                                        * Remove the ns-decl from the element-node.
+                                        */
+                                        if (prevns)
+                                            prevns->next = ns->next;
+                                        else
+                                            cur->nsDef = ns->next;
+                                        goto next_ns_decl;
+                                    }
 				}
 			    }
 			}
@@ -8960,7 +8783,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
 			*/
 			if (xmlDOMWrapNsMapAddItem(&nsMap, -1, ns, ns,
 			    depth) == NULL)
-			    goto internal_error;
+			    ret = -1;
 
 			prevns = ns;
 next_ns_decl:
@@ -8980,7 +8803,7 @@ next_ns_decl:
 			((xmlNodePtr) elem->parent->doc != elem->parent)) {
 			if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
 				elem->parent) == -1)
-			    goto internal_error;
+			    ret = -1;
 		    }
 		    parnsdone = 1;
 		}
@@ -9019,7 +8842,7 @@ next_ns_decl:
 			&nsMap, depth,
 			ancestorsOnly,
 			(cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
-		    goto internal_error;
+		    ret = -1;
 		cur->ns = ns;
 
 ns_end:
@@ -9079,11 +8902,6 @@ next_sibling:
 	}
     } while (cur != NULL);
 
-    ret = 0;
-    goto exit;
-internal_error:
-    ret = -1;
-exit:
     if (listRedund) {
 	for (i = 0, j = 0; i < nbRedund; i++, j += 2) {
 	    xmlFreeNs(listRedund[j]);
@@ -9119,7 +8937,7 @@ exit:
 */
 static int
 xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
-		      xmlDocPtr sourceDoc,
+		      xmlDocPtr sourceDoc ATTRIBUTE_UNUSED,
 		      xmlNodePtr node,
 		      xmlDocPtr destDoc,
 		      xmlNodePtr destParent,
@@ -9130,21 +8948,12 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
     xmlNsMapPtr nsMap = NULL;
     xmlNsMapItemPtr mi;
     xmlNsPtr ns = NULL;
-    int depth = -1, adoptStr = 1;
+    int depth = -1;
     /* gather @parent's ns-decls. */
     int parnsdone;
     /* @ancestorsOnly should be set per option. */
     int ancestorsOnly = 0;
 
-    /*
-    * Optimize string adoption for equal or none dicts.
-    */
-    if ((sourceDoc != NULL) &&
-	(sourceDoc->dict == destDoc->dict))
-	adoptStr = 0;
-    else
-	adoptStr = 1;
-
     /*
     * Get the ns-map from the context if available.
     */
@@ -9164,40 +8973,21 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
 	parnsdone = 0;
 
     cur = node;
-    if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
-	goto internal_error;
 
     while (cur != NULL) {
-	/*
-	* Paranoid source-doc sanity check.
-	*/
-	if (cur->doc != sourceDoc) {
-	    /*
-	    * We'll assume XIncluded nodes if the doc differs.
-	    * TODO: Do we need to reconciliate XIncluded nodes?
-	    * This here skips XIncluded nodes and tries to handle
-	    * broken sequences.
-	    */
-	    if (cur->next == NULL)
-		goto leave_node;
-	    do {
-		cur = cur->next;
-		if ((cur->type == XML_XINCLUDE_END) ||
-		    (cur->doc == node->doc))
-		    break;
-	    } while (cur->next != NULL);
+        if (cur->doc != destDoc) {
+            if (xmlNodeSetDoc(cur, destDoc) < 0)
+                ret = -1;
+        }
 
-	    if (cur->doc != node->doc)
-		goto leave_node;
-	}
-	cur->doc = destDoc;
 	switch (cur->type) {
 	    case XML_XINCLUDE_START:
 	    case XML_XINCLUDE_END:
 		/*
 		* TODO
 		*/
-		return (-1);
+		ret = -1;
+                goto leave_node;
 	    case XML_ELEMENT_NODE:
 		curElem = cur;
 		depth++;
@@ -9218,14 +9008,12 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
 			*/
 			if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
 			    destParent) == -1)
-			    goto internal_error;
+			    ret = -1;
 			parnsdone = 1;
 		    }
 		    for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
 			/*
 			* NOTE: ns->prefix and ns->href are never in the dict.
-			* XML_TREE_ADOPT_STR(ns->prefix)
-			* XML_TREE_ADOPT_STR(ns->href)
 			*/
 			/*
 			* Does it shadow any ns-decl?
@@ -9247,7 +9035,7 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
 			*/
 			if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
 			    ns, ns, depth) == NULL)
-			    goto internal_error;
+			    ret = -1;
 		    }
 		}
                 /* Falls through. */
@@ -9259,7 +9047,7 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
 		if (! parnsdone) {
 		    if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
 			destParent) == -1)
-			goto internal_error;
+			ret = -1;
 		    parnsdone = 1;
 		}
 		/*
@@ -9293,7 +9081,7 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
 		    */
 		    if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
 			    cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
-			goto internal_error;
+			ret = -1;
 		    cur->ns = ns;
 		} else {
 		    /*
@@ -9307,15 +9095,11 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
 			ancestorsOnly,
 			/* ns-decls must be prefixed for attributes. */
 			(cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
-			goto internal_error;
+			ret = -1;
 		    cur->ns = ns;
 		}
+
 ns_end:
-		/*
-		* Further node properties.
-		* TODO: Is this all?
-		*/
-		XML_TREE_ADOPT_STR(cur->name)
 		if (cur->type == XML_ELEMENT_NODE) {
 		    cur->psvi = NULL;
 		    cur->line = 0;
@@ -9330,55 +9114,16 @@ ns_end:
 			cur = (xmlNodePtr) cur->properties;
 			continue;
 		    }
-		} else {
-		    /*
-		    * Attributes.
-		    */
-		    if ((sourceDoc != NULL) &&
-			(((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID))
-		    {
-			xmlRemoveID(sourceDoc, (xmlAttrPtr) cur);
-		    }
-		    ((xmlAttrPtr) cur)->atype = 0;
-		    ((xmlAttrPtr) cur)->psvi = NULL;
 		}
 		break;
 	    case XML_TEXT_NODE:
 	    case XML_CDATA_SECTION_NODE:
-		/*
-		* This puts the content in the dest dict, only if
-		* it was previously in the source dict.
-		*/
-		XML_TREE_ADOPT_STR_2(cur->content)
-		goto leave_node;
-	    case XML_ENTITY_REF_NODE:
-		/*
-		* Remove reference to the entity-node.
-		*/
-		cur->content = NULL;
-		cur->children = NULL;
-		cur->last = NULL;
-		if ((destDoc->intSubset) || (destDoc->extSubset)) {
-		    xmlEntityPtr ent;
-		    /*
-		    * Assign new entity-node if available.
-		    */
-		    ent = xmlGetDocEntity(destDoc, cur->name);
-		    if (ent != NULL) {
-			cur->content = ent->content;
-			cur->children = (xmlNodePtr) ent;
-			cur->last = (xmlNodePtr) ent;
-		    }
-		}
-		goto leave_node;
 	    case XML_PI_NODE:
-		XML_TREE_ADOPT_STR(cur->name)
-		XML_TREE_ADOPT_STR_2(cur->content)
-		break;
 	    case XML_COMMENT_NODE:
-		break;
+	    case XML_ENTITY_REF_NODE:
+		goto leave_node;
 	    default:
-		goto internal_error;
+		ret = -1;
 	}
 	/*
 	* Walk the tree.
@@ -9429,12 +9174,6 @@ leave_node:
 	}
     }
 
-    goto exit;
-
-internal_error:
-    ret = -1;
-
-exit:
     /*
     * Cleanup.
     */
@@ -9496,7 +9235,7 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
 		      int options ATTRIBUTE_UNUSED)
 {
     int ret = 0;
-    xmlNodePtr cur, curElem = NULL;
+    xmlNodePtr cur, cloneElem = NULL;
     xmlNsMapPtr nsMap = NULL;
     xmlNsMapItemPtr mi;
     xmlNsPtr ns;
@@ -9514,7 +9253,8 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
     xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL;
     xmlDictPtr dict; /* The destination dict */
 
-    if ((node == NULL) || (resNode == NULL) || (destDoc == NULL))
+    if ((node == NULL) || (resNode == NULL) || (destDoc == NULL) ||
+	((destParent != NULL) && (destParent->doc != destDoc)))
 	return(-1);
     /*
     * TODO: Initially we support only element-nodes.
@@ -9546,9 +9286,6 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
     *resNode = NULL;
 
     cur = node;
-    if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
-        return(-1);
-
     while (cur != NULL) {
 	if (cur->doc != sourceDoc) {
 	    /*
@@ -9576,15 +9313,12 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
 	    case XML_PI_NODE:
 	    case XML_DOCUMENT_FRAG_NODE:
 	    case XML_ENTITY_REF_NODE:
-	    case XML_ENTITY_NODE:
 		/*
 		* Nodes of xmlNode structure.
 		*/
 		clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
-		if (clone == NULL) {
-		    xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node");
+		if (clone == NULL)
 		    goto internal_error;
-		}
 		memset(clone, 0, sizeof(xmlNode));
 		/*
 		* Set hierarchical links.
@@ -9596,6 +9330,7 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
 			clone->prev = prevClone;
 		    } else
 			parentClone->children = clone;
+                    parentClone->last = clone;
 		} else
 		    resultClone = clone;
 
@@ -9604,11 +9339,10 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
 		/*
 		* Attributes (xmlAttr).
 		*/
-		clone = (xmlNodePtr) xmlMalloc(sizeof(xmlAttr));
-		if (clone == NULL) {
-		    xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node");
+                /* Use xmlRealloc to avoid -Warray-bounds warning */
+		clone = (xmlNodePtr) xmlRealloc(NULL, sizeof(xmlAttr));
+		if (clone == NULL)
 		    goto internal_error;
-		}
 		memset(clone, 0, sizeof(xmlAttr));
 		/*
 		* Set hierarchical links.
@@ -9649,7 +9383,12 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
 	else if (cur->name == xmlStringComment)
 	    clone->name = xmlStringComment;
 	else if (cur->name != NULL) {
-	    DICT_CONST_COPY(cur->name, clone->name);
+            if (dict != NULL)
+                clone->name = xmlDictLookup(dict, cur->name, -1);
+            else
+                clone->name = xmlStrdup(cur->name);
+            if (clone->name == NULL)
+                goto internal_error;
 	}
 
 	switch (cur->type) {
@@ -9660,7 +9399,7 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
 		*/
 		return (-1);
 	    case XML_ELEMENT_NODE:
-		curElem = cur;
+		cloneElem = clone;
 		depth++;
 		/*
 		* Namespace declarations.
@@ -9686,18 +9425,25 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
 			* Create a new xmlNs.
 			*/
 			cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
-			if (cloneNs == NULL) {
-			    xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
-				"allocating namespace");
-			    return(-1);
-			}
+			if (cloneNs == NULL)
+			    goto internal_error;
 			memset(cloneNs, 0, sizeof(xmlNs));
 			cloneNs->type = XML_LOCAL_NAMESPACE;
 
-			if (ns->href != NULL)
+			if (ns->href != NULL) {
 			    cloneNs->href = xmlStrdup(ns->href);
-			if (ns->prefix != NULL)
+                            if (cloneNs->href == NULL) {
+                                xmlFreeNs(cloneNs);
+                                goto internal_error;
+                            }
+                        }
+			if (ns->prefix != NULL) {
 			    cloneNs->prefix = xmlStrdup(ns->prefix);
+                            if (cloneNs->prefix == NULL) {
+                                xmlFreeNs(cloneNs);
+                                goto internal_error;
+                            }
+                        }
 
 			*cloneNsDefSlot = cloneNs;
 			cloneNsDefSlot = &(cloneNs->next);
@@ -9743,15 +9489,18 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
 		/* IDs will be processed further down. */
 		/* cur->ns will be processed further down. */
 		break;
+	    case XML_PI_NODE:
+	    case XML_COMMENT_NODE:
 	    case XML_TEXT_NODE:
 	    case XML_CDATA_SECTION_NODE:
 		/*
 		* Note that this will also cover the values of attributes.
 		*/
-		DICT_COPY(cur->content, clone->content);
-		goto leave_node;
-	    case XML_ENTITY_NODE:
-		/* TODO: What to do here? */
+                if (cur->content != NULL) {
+                    clone->content = xmlStrdup(cur->content);
+                    if (clone->content == NULL)
+                        goto internal_error;
+                }
 		goto leave_node;
 	    case XML_ENTITY_REF_NODE:
 		if (sourceDoc != destDoc) {
@@ -9777,12 +9526,6 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
 		    clone->last = cur->last;
 		}
 		goto leave_node;
-	    case XML_PI_NODE:
-		DICT_COPY(cur->content, clone->content);
-		goto leave_node;
-	    case XML_COMMENT_NODE:
-		DICT_COPY(cur->content, clone->content);
-		goto leave_node;
 	    default:
 		goto internal_error;
 	}
@@ -9842,8 +9585,8 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
 	    * Acquire a normalized ns-decl and add it to the map.
 	    */
 	    if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc,
-		/* ns-decls on curElem or on destDoc->oldNs */
-		destParent ? curElem : NULL,
+		/* ns-decls on cloneElem or on destDoc->oldNs */
+		destParent ? cloneElem : NULL,
 		cur->ns, &ns,
 		&nsMap, depth,
 		/* if we need to search only in the ancestor-axis */
@@ -9864,19 +9607,22 @@ end_ns_reference:
 	if ((clone->type == XML_ATTRIBUTE_NODE) &&
 	    (clone->parent != NULL))
 	{
-	    if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) {
+            int res;
 
+	    res = xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone);
+            if (res < 0)
+                goto internal_error;
+            if (res == 1) {
 		xmlChar *idVal;
 
-		idVal = xmlNodeListGetString(cur->doc, cur->children, 1);
-		if (idVal != NULL) {
-		    if (xmlAddID(NULL, destDoc, idVal, (xmlAttrPtr) cur) == NULL) {
-			/* TODO: error message. */
-			xmlFree(idVal);
-			goto internal_error;
-		    }
-		    xmlFree(idVal);
-		}
+		idVal = xmlNodeGetContent(cur);
+                if (idVal == NULL)
+                    goto internal_error;
+                if (xmlAddIDSafe((xmlAttrPtr) cur, idVal) < 0) {
+                    xmlFree(idVal);
+                    goto internal_error;
+                }
+                xmlFree(idVal);
 	    }
 	}
 	/*
@@ -9941,11 +9687,6 @@ leave_node:
 	    prevClone = clone;
 	    cur = cur->next;
 	} else if (cur->type != XML_ATTRIBUTE_NODE) {
-	    /*
-	    * Set clone->last.
-	    */
-	    if (clone->parent != NULL)
-		clone->parent->last = clone;
 	    clone = clone->parent;
 	    if (clone != NULL)
 		parentClone = clone->parent;
@@ -10014,19 +9755,22 @@ exit:
 */
 static int
 xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt,
-		    xmlDocPtr sourceDoc,
+		    xmlDocPtr sourceDoc ATTRIBUTE_UNUSED,
 		    xmlAttrPtr attr,
 		    xmlDocPtr destDoc,
 		    xmlNodePtr destParent,
 		    int options ATTRIBUTE_UNUSED)
 {
-    xmlNodePtr cur;
-    int adoptStr = 1;
+    int ret = 0;
 
     if ((attr == NULL) || (destDoc == NULL))
 	return (-1);
 
-    attr->doc = destDoc;
+    if (attr->doc != destDoc) {
+        if (xmlSetTreeDoc((xmlNodePtr) attr, destDoc) < 0)
+            ret = -1;
+    }
+
     if (attr->ns != NULL) {
 	xmlNsPtr ns = NULL;
 
@@ -10047,75 +9791,18 @@ xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt,
 	    */
 	    if (xmlSearchNsByNamespaceStrict(destDoc, destParent, attr->ns->href,
 		&ns, 1) == -1)
-		goto internal_error;
+		ret = -1;
 	    if (ns == NULL) {
 		ns = xmlDOMWrapNSNormDeclareNsForced(destDoc, destParent,
 		    attr->ns->href, attr->ns->prefix, 1);
 	    }
 	}
 	if (ns == NULL)
-	    goto internal_error;
+	    ret = -1;
 	attr->ns = ns;
     }
 
-    XML_TREE_ADOPT_STR(attr->name);
-    attr->atype = 0;
-    attr->psvi = NULL;
-    /*
-    * Walk content.
-    */
-    if (attr->children == NULL)
-	return (0);
-    cur = attr->children;
-    if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
-        goto internal_error;
-    while (cur != NULL) {
-	cur->doc = destDoc;
-	switch (cur->type) {
-	    case XML_TEXT_NODE:
-	    case XML_CDATA_SECTION_NODE:
-		XML_TREE_ADOPT_STR_2(cur->content)
-		break;
-	    case XML_ENTITY_REF_NODE:
-		/*
-		* Remove reference to the entity-node.
-		*/
-		cur->content = NULL;
-		cur->children = NULL;
-		cur->last = NULL;
-		if ((destDoc->intSubset) || (destDoc->extSubset)) {
-		    xmlEntityPtr ent;
-		    /*
-		    * Assign new entity-node if available.
-		    */
-		    ent = xmlGetDocEntity(destDoc, cur->name);
-		    if (ent != NULL) {
-			cur->content = ent->content;
-			cur->children = (xmlNodePtr) ent;
-			cur->last = (xmlNodePtr) ent;
-		    }
-		}
-		break;
-	    default:
-		break;
-	}
-	if (cur->children != NULL) {
-	    cur = cur->children;
-	    continue;
-	}
-next_sibling:
-	if (cur == (xmlNodePtr) attr)
-	    break;
-	if (cur->next != NULL)
-	    cur = cur->next;
-	else {
-	    cur = cur->parent;
-	    goto next_sibling;
-	}
-    }
-    return (0);
-internal_error:
-    return (-1);
+    return (ret);
 }
 
 /*
@@ -10153,6 +9840,8 @@ xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt,
 		    xmlNodePtr destParent,
 		    int options)
 {
+    int ret = 0;
+
     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
         (destDoc == NULL) ||
 	((destParent != NULL) && (destParent->doc != destDoc)))
@@ -10160,17 +9849,18 @@ xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt,
     /*
     * Check node->doc sanity.
     */
-    if ((node->doc != NULL) && (sourceDoc != NULL) &&
-	(node->doc != sourceDoc)) {
-	/*
-	* Might be an XIncluded node.
-	*/
+    if (sourceDoc == NULL) {
+        sourceDoc = node->doc;
+    } else if (node->doc != sourceDoc) {
 	return (-1);
     }
-    if (sourceDoc == NULL)
-	sourceDoc = node->doc;
+
+    /*
+     * TODO: Shouldn't this be allowed?
+     */
     if (sourceDoc == destDoc)
 	return (-1);
+
     switch (node->type) {
 	case XML_ELEMENT_NODE:
 	case XML_ATTRIBUTE_NODE:
@@ -10190,7 +9880,7 @@ xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt,
     * Unlink only if @node was not already added to @destParent.
     */
     if ((node->parent != NULL) && (destParent != node->parent))
-	xmlUnlinkNode(node);
+	xmlUnlinkNodeInternal(node);
 
     if (node->type == XML_ELEMENT_NODE) {
 	    return (xmlDOMWrapAdoptBranch(ctxt, sourceDoc, node,
@@ -10199,51 +9889,102 @@ xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt,
 	    return (xmlDOMWrapAdoptAttr(ctxt, sourceDoc,
 		(xmlAttrPtr) node, destDoc, destParent, options));
     } else {
-	xmlNodePtr cur = node;
-	int adoptStr = 1;
+        if (node->doc != destDoc) {
+            if (xmlNodeSetDoc(node, destDoc) < 0)
+                ret = -1;
+        }
+    }
+    return (ret);
+}
 
-	cur->doc = destDoc;
-	/*
-	* Optimize string adoption.
-	*/
-	if ((sourceDoc != NULL) &&
-	    (sourceDoc->dict == destDoc->dict))
-		adoptStr = 0;
-	switch (node->type) {
-	    case XML_TEXT_NODE:
-	    case XML_CDATA_SECTION_NODE:
-		XML_TREE_ADOPT_STR_2(node->content)
-		    break;
-	    case XML_ENTITY_REF_NODE:
-		/*
-		* Remove reference to the entity-node.
-		*/
-		node->content = NULL;
-		node->children = NULL;
-		node->last = NULL;
-		if ((destDoc->intSubset) || (destDoc->extSubset)) {
-		    xmlEntityPtr ent;
-		    /*
-		    * Assign new entity-node if available.
-		    */
-		    ent = xmlGetDocEntity(destDoc, node->name);
-		    if (ent != NULL) {
-			node->content = ent->content;
-			node->children = (xmlNodePtr) ent;
-			node->last = (xmlNodePtr) ent;
-		    }
-		}
-		XML_TREE_ADOPT_STR(node->name)
-		break;
-	    case XML_PI_NODE: {
-		XML_TREE_ADOPT_STR(node->name)
-		XML_TREE_ADOPT_STR_2(node->content)
-		break;
-	    }
-	    default:
-		break;
-	}
+/************************************************************************
+ *									*
+ *			XHTML detection					*
+ *									*
+ ************************************************************************/
+
+#define XHTML_STRICT_PUBLIC_ID BAD_CAST \
+   "-//W3C//DTD XHTML 1.0 Strict//EN"
+#define XHTML_STRICT_SYSTEM_ID BAD_CAST \
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+#define XHTML_FRAME_PUBLIC_ID BAD_CAST \
+   "-//W3C//DTD XHTML 1.0 Frameset//EN"
+#define XHTML_FRAME_SYSTEM_ID BAD_CAST \
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
+#define XHTML_TRANS_PUBLIC_ID BAD_CAST \
+   "-//W3C//DTD XHTML 1.0 Transitional//EN"
+#define XHTML_TRANS_SYSTEM_ID BAD_CAST \
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+
+/**
+ * xmlIsXHTML:
+ * @systemID:  the system identifier
+ * @publicID:  the public identifier
+ *
+ * Try to find if the document correspond to an XHTML DTD
+ *
+ * Returns 1 if true, 0 if not and -1 in case of error
+ */
+int
+xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) {
+    if ((systemID == NULL) && (publicID == NULL))
+	return(-1);
+    if (publicID != NULL) {
+	if (xmlStrEqual(publicID, XHTML_STRICT_PUBLIC_ID)) return(1);
+	if (xmlStrEqual(publicID, XHTML_FRAME_PUBLIC_ID)) return(1);
+	if (xmlStrEqual(publicID, XHTML_TRANS_PUBLIC_ID)) return(1);
     }
-    return (0);
+    if (systemID != NULL) {
+	if (xmlStrEqual(systemID, XHTML_STRICT_SYSTEM_ID)) return(1);
+	if (xmlStrEqual(systemID, XHTML_FRAME_SYSTEM_ID)) return(1);
+	if (xmlStrEqual(systemID, XHTML_TRANS_SYSTEM_ID)) return(1);
+    }
+    return(0);
+}
+
+/************************************************************************
+ *									*
+ *			Node callbacks					*
+ *									*
+ ************************************************************************/
+
+/**
+ * xmlRegisterNodeDefault:
+ * @func: function pointer to the new RegisterNodeFunc
+ *
+ * DEPRECATED: don't use
+ *
+ * Registers a callback for node creation
+ *
+ * Returns the old value of the registration function
+ */
+xmlRegisterNodeFunc
+xmlRegisterNodeDefault(xmlRegisterNodeFunc func)
+{
+    xmlRegisterNodeFunc old = xmlRegisterNodeDefaultValue;
+
+    __xmlRegisterCallbacks = 1;
+    xmlRegisterNodeDefaultValue = func;
+    return(old);
+}
+
+/**
+ * xmlDeregisterNodeDefault:
+ * @func: function pointer to the new DeregisterNodeFunc
+ *
+ * DEPRECATED: don't use
+ *
+ * Registers a callback for node destruction
+ *
+ * Returns the previous value of the deregistration function
+ */
+xmlDeregisterNodeFunc
+xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func)
+{
+    xmlDeregisterNodeFunc old = xmlDeregisterNodeDefaultValue;
+
+    __xmlRegisterCallbacks = 1;
+    xmlDeregisterNodeDefaultValue = func;
+    return(old);
 }
 
diff --git a/triodef.h b/triodef.h
deleted file mode 100644
index e101f6df5607686d8c992a92c5b817a34e39b4bd..0000000000000000000000000000000000000000
--- a/triodef.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*************************************************************************
- *
- * $Id$
- *
- * Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
- * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
- *
- ************************************************************************/
-
-#ifndef TRIO_TRIODEF_H
-#define TRIO_TRIODEF_H
-
-/*************************************************************************
- * Platform and compiler support detection
- */
-#if defined(__GNUC__)
-# define TRIO_COMPILER_GCC
-#elif defined(__SUNPRO_C)
-# define TRIO_COMPILER_SUNPRO
-#elif defined(__SUNPRO_CC)
-# define TRIO_COMPILER_SUNPRO
-# define __SUNPRO_C __SUNPRO_CC
-#elif defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__)
-# define TRIO_COMPILER_XLC
-#elif defined(_AIX) && !defined(__GNUC__)
-# define TRIO_COMPILER_XLC /* Workaround for old xlc */
-#elif defined(__DECC) || defined(__DECCXX)
-# define TRIO_COMPILER_DECC
-#elif defined(__osf__) && defined(__LANGUAGE_C__)
-# define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */
-#elif defined(_MSC_VER)
-# define TRIO_COMPILER_MSVC
-#elif defined(__BORLANDC__)
-# define TRIO_COMPILER_BCB
-#endif
-
-#if defined(VMS) || defined(__VMS)
-/*
- * VMS is placed first to avoid identifying the platform as Unix
- * based on the DECC compiler later on.
- */
-# define TRIO_PLATFORM_VMS
-#elif defined(__OS400__)
-# define TRIO_PLATFORM_OS400
-#elif defined(unix) || defined(__unix) || defined(__unix__)
-# define TRIO_PLATFORM_UNIX
-#elif defined(TRIO_COMPILER_XLC) || defined(_AIX)
-# define TRIO_PLATFORM_UNIX
-#elif defined(TRIO_COMPILER_DECC) || defined(__osf___)
-# define TRIO_PLATFORM_UNIX
-#elif defined(__NetBSD__)
-# define TRIO_PLATFORM_UNIX
-#elif defined(__Lynx__)
-# define TRIO_PLATFORM_UNIX
-#elif defined(__QNX__)
-# define TRIO_PLATFORM_UNIX
-# define TRIO_PLATFORM_QNX
-#elif defined(__CYGWIN__)
-# define TRIO_PLATFORM_UNIX
-#elif defined(AMIGA) && defined(TRIO_COMPILER_GCC)
-# define TRIO_PLATFORM_UNIX
-#elif defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32)
-# define TRIO_PLATFORM_WIN32
-#elif defined(mpeix) || defined(__mpexl)
-# define TRIO_PLATFORM_MPEIX
-#endif
-
-#if defined(_AIX)
-# define TRIO_PLATFORM_AIX
-#elif defined(__hpux)
-# define TRIO_PLATFORM_HPUX
-#elif defined(sun) || defined(__sun__)
-# if defined(__SVR4) || defined(__svr4__)
-#  define TRIO_PLATFORM_SOLARIS
-# else
-#  define TRIO_PLATFORM_SUNOS
-# endif
-#endif
-
-#if defined(__STDC__) || defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
-# define TRIO_COMPILER_SUPPORTS_C89
-# if defined(__STDC_VERSION__)
-#  define TRIO_COMPILER_SUPPORTS_C90
-#  if (__STDC_VERSION__ >= 199409L)
-#   define TRIO_COMPILER_SUPPORTS_C94
-#  endif
-#  if (__STDC_VERSION__ >= 199901L)
-#   define TRIO_COMPILER_SUPPORTS_C99
-#  endif
-# elif defined(TRIO_COMPILER_SUNPRO)
-#  if (__SUNPRO_C >= 0x420)
-#   define TRIO_COMPILER_SUPPORTS_C94
-#  endif
-# endif
-#elif defined(TRIO_COMPILER_XLC) && defined(__EXTENDED__)
-# define TRIO_COMPILER_SUPPORTS_C89
-# define TRIO_COMPILER_SUPPORTS_C90
-# define TRIO_COMPILER_SUPPORTS_C94
-#endif
-
-#if defined(_XOPEN_SOURCE)
-# if defined(_XOPEN_SOURCE_EXTENDED)
-#  define TRIO_COMPILER_SUPPORTS_UNIX95
-# endif
-# if (_XOPEN_VERSION >= 500)
-#  define TRIO_COMPILER_SUPPORTS_UNIX98
-# endif
-# if (_XOPEN_VERSION >= 600)
-#  define TRIO_COMPILER_SUPPORTS_UNIX01
-# endif
-#endif
-
-/*************************************************************************
- * Generic defines
- */
-
-#if !defined(TRIO_PUBLIC)
-# define TRIO_PUBLIC
-#endif
-#if !defined(TRIO_PRIVATE)
-# define TRIO_PRIVATE static
-#endif
-
-#if !(defined(TRIO_COMPILER_SUPPORTS_C89) || defined(__cplusplus))
-# define TRIO_COMPILER_ANCIENT
-#endif
-
-#if defined(TRIO_COMPILER_ANCIENT)
-# define TRIO_CONST
-# define TRIO_VOLATILE
-# define TRIO_SIGNED
-typedef double trio_long_double_t;
-typedef char * trio_pointer_t;
-# define TRIO_SUFFIX_LONG(x) x
-# define TRIO_PROTO(x) ()
-# define TRIO_NOARGS
-# define TRIO_ARGS1(list,a1) list a1;
-# define TRIO_ARGS2(list,a1,a2) list a1; a2;
-# define TRIO_ARGS3(list,a1,a2,a3) list a1; a2; a3;
-# define TRIO_ARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4;
-# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5;
-# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) list a1; a2; a3; a4; a5; a6;
-# define TRIO_VARGS2(list,a1,a2) list a1; a2
-# define TRIO_VARGS3(list,a1,a2,a3) list a1; a2; a3
-# define TRIO_VARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4
-# define TRIO_VARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5
-# define TRIO_VA_DECL va_dcl
-# define TRIO_VA_START(x,y) va_start(x)
-# define TRIO_VA_END(x) va_end(x)
-#else /* ANSI C */
-# define TRIO_CONST const
-# define TRIO_VOLATILE volatile
-# define TRIO_SIGNED signed
-typedef long double trio_long_double_t;
-typedef void * trio_pointer_t;
-# define TRIO_SUFFIX_LONG(x) x ## L
-# define TRIO_PROTO(x) x
-# define TRIO_NOARGS void
-# define TRIO_ARGS1(list,a1) (a1)
-# define TRIO_ARGS2(list,a1,a2) (a1,a2)
-# define TRIO_ARGS3(list,a1,a2,a3) (a1,a2,a3)
-# define TRIO_ARGS4(list,a1,a2,a3,a4) (a1,a2,a3,a4)
-# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) (a1,a2,a3,a4,a5)
-# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) (a1,a2,a3,a4,a5,a6)
-# define TRIO_VARGS2 TRIO_ARGS2
-# define TRIO_VARGS3 TRIO_ARGS3
-# define TRIO_VARGS4 TRIO_ARGS4
-# define TRIO_VARGS5 TRIO_ARGS5
-# define TRIO_VA_DECL ...
-# define TRIO_VA_START(x,y) va_start(x,y)
-# define TRIO_VA_END(x) va_end(x)
-#endif
-
-#if defined(TRIO_COMPILER_SUPPORTS_C99) || defined(__cplusplus)
-# define TRIO_INLINE inline
-#elif defined(TRIO_COMPILER_GCC)
-# define TRIO_INLINE __inline__
-#elif defined(TRIO_COMPILER_MSVC)
-# define TRIO_INLINE _inline
-#elif defined(TRIO_COMPILER_BCB)
-# define TRIO_INLINE __inline
-#else
-# define TRIO_INLINE
-#endif
-
-/*************************************************************************
- * Workarounds
- */
-
-#if defined(TRIO_PLATFORM_VMS)
-/*
- * Computations done with constants at compile time can trigger these
- * even when compiling with IEEE enabled.
- */
-# pragma message disable (UNDERFLOW, FLOATOVERFL)
-
-# if (__CRTL_VER < 80000000)
-/*
- * Although the compiler supports C99 language constructs, the C
- * run-time library does not contain all C99 functions.
- *
- * This was the case for 70300022. Update the 80000000 value when
- * it has been accurately determined what version of the library
- * supports C99.
- */
-#  if defined(TRIO_COMPILER_SUPPORTS_C99)
-#   undef TRIO_COMPILER_SUPPORTS_C99
-#  endif
-# endif
-#endif
-
-/*
- * Not all preprocessors supports the LL token.
- */
-#if defined(TRIO_COMPILER_BCB)
-#else
-# define TRIO_COMPILER_SUPPORTS_LL
-#endif
-
-#endif /* TRIO_TRIODEF_H */
diff --git a/trionan.c b/trionan.c
deleted file mode 100644
index 8767a9fe6485b03a8a86c807acfcd186fe4812e2..0000000000000000000000000000000000000000
--- a/trionan.c
+++ /dev/null
@@ -1,914 +0,0 @@
-/*************************************************************************
- *
- * $Id$
- *
- * Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
- * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
- *
- ************************************************************************
- *
- * Functions to handle special quantities in floating-point numbers
- * (that is, NaNs and infinity). They provide the capability to detect
- * and fabricate special quantities.
- *
- * Although written to be as portable as possible, it can never be
- * guaranteed to work on all platforms, as not all hardware supports
- * special quantities.
- *
- * The approach used here (approximately) is to:
- *
- *   1. Use C99 functionality when available.
- *   2. Use IEEE 754 bit-patterns if possible.
- *   3. Use platform-specific techniques.
- *
- ************************************************************************/
-
-/*
- * TODO:
- *  o Put all the magic into trio_fpclassify_and_signbit(), and use this from
- *    trio_isnan() etc.
- */
-
-/*************************************************************************
- * Include files
- */
-#include "triodef.h"
-#include "trionan.h"
-
-#include <math.h>
-#include <string.h>
-#include <limits.h>
-#include <float.h>
-#if defined(TRIO_PLATFORM_UNIX)
-# include <signal.h>
-#endif
-#if defined(TRIO_COMPILER_DECC)
-#  if defined(__linux__)
-#   include <cpml.h>
-#  else
-#   include <fp_class.h>
-#  endif
-#endif
-#include <assert.h>
-
-#if defined(TRIO_DOCUMENTATION)
-# include "doc/doc_nan.h"
-#endif
-/** @addtogroup SpecialQuantities
-    @{
-*/
-
-/*************************************************************************
- * Definitions
- */
-
-#define TRIO_TRUE (1 == 1)
-#define TRIO_FALSE (0 == 1)
-
-/*
- * We must enable IEEE floating-point on Alpha
- */
-#if defined(__alpha) && !defined(_IEEE_FP)
-# if defined(TRIO_COMPILER_DECC)
-#  if defined(TRIO_PLATFORM_VMS)
-#   error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE"
-#  else
-#   if !defined(_CFE)
-#    error "Must be compiled with option -ieee"
-#   endif
-#  endif
-# elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__))
-#  error "Must be compiled with option -mieee"
-# endif
-#endif /* __alpha && ! _IEEE_FP */
-
-/*
- * In ANSI/IEEE 754-1985 64-bits double format numbers have the
- * following properties (amongst others)
- *
- *   o FLT_RADIX == 2: binary encoding
- *   o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used
- *     to indicate special numbers (e.g. NaN and Infinity), so the
- *     maximum exponent is 10 bits wide (2^10 == 1024).
- *   o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because
- *     numbers are normalized the initial binary 1 is represented
- *     implicitly (the so-called "hidden bit"), which leaves us with
- *     the ability to represent 53 bits wide mantissa.
- */
-#if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53)
-# define USE_IEEE_754
-#endif
-
-
-/*************************************************************************
- * Constants
- */
-
-static TRIO_CONST char rcsid[] = "@(#)$Id$";
-
-#if defined(USE_IEEE_754)
-
-/*
- * Endian-agnostic indexing macro.
- *
- * The value of internalEndianMagic, when converted into a 64-bit
- * integer, becomes 0x0706050403020100 (we could have used a 64-bit
- * integer value instead of a double, but not all platforms supports
- * that type). The value is automatically encoded with the correct
- * endianness by the compiler, which means that we can support any
- * kind of endianness. The individual bytes are then used as an index
- * for the IEEE 754 bit-patterns and masks.
- */
-#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])
-
-#if (defined(__BORLANDC__) && __BORLANDC__ >= 0x0590)
-static TRIO_CONST double internalEndianMagic = 7.949928895127362e-275;
-#else
-static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275;
-#endif
-
-/* Mask for the exponent */
-static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {
-  0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/* Mask for the mantissa */
-static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = {
-  0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-
-/* Mask for the sign bit */
-static TRIO_CONST unsigned char ieee_754_sign_mask[] = {
-  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/* Bit-pattern for negative zero */
-static TRIO_CONST unsigned char ieee_754_negzero_array[] = {
-  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/* Bit-pattern for infinity */
-static TRIO_CONST unsigned char ieee_754_infinity_array[] = {
-  0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/* Bit-pattern for quiet NaN */
-static TRIO_CONST unsigned char ieee_754_qnan_array[] = {
-  0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-
-/*************************************************************************
- * Functions
- */
-
-/*
- * trio_make_double
- */
-TRIO_PRIVATE double
-trio_make_double
-TRIO_ARGS1((values),
-	   TRIO_CONST unsigned char *values)
-{
-  TRIO_VOLATILE double result;
-  int i;
-
-  for (i = 0; i < (int)sizeof(double); i++) {
-    ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i];
-  }
-  return result;
-}
-
-/*
- * trio_is_special_quantity
- */
-TRIO_PRIVATE int
-trio_is_special_quantity
-TRIO_ARGS2((number, has_mantissa),
-	   double number,
-	   int *has_mantissa)
-{
-  unsigned int i;
-  unsigned char current;
-  int is_special_quantity = TRIO_TRUE;
-
-  *has_mantissa = 0;
-
-  for (i = 0; i < (unsigned int)sizeof(double); i++) {
-    current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
-    is_special_quantity
-      &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]);
-    *has_mantissa |= (current & ieee_754_mantissa_mask[i]);
-  }
-  return is_special_quantity;
-}
-
-/*
- * trio_is_negative
- */
-TRIO_PRIVATE int
-trio_is_negative
-TRIO_ARGS1((number),
-	   double number)
-{
-  unsigned int i;
-  int is_negative = TRIO_FALSE;
-
-  for (i = 0; i < (unsigned int)sizeof(double); i++) {
-    is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]
-		    & ieee_754_sign_mask[i]);
-  }
-  return is_negative;
-}
-
-#endif /* USE_IEEE_754 */
-
-
-/**
-   Generate negative zero.
-
-   @return Floating-point representation of negative zero.
-*/
-TRIO_PUBLIC double
-trio_nzero(TRIO_NOARGS)
-{
-#if defined(USE_IEEE_754)
-  return trio_make_double(ieee_754_negzero_array);
-#else
-  TRIO_VOLATILE double zero = 0.0;
-
-  return -zero;
-#endif
-}
-
-/**
-   Generate positive infinity.
-
-   @return Floating-point representation of positive infinity.
-*/
-TRIO_PUBLIC double
-trio_pinf(TRIO_NOARGS)
-{
-  /* Cache the result */
-  static double result = 0.0;
-
-  if (result == 0.0) {
-
-#if defined(INFINITY) && defined(__STDC_IEC_559__)
-    result = (double)INFINITY;
-
-#elif defined(USE_IEEE_754)
-    result = trio_make_double(ieee_754_infinity_array);
-
-#else
-    /*
-     * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used
-     * as infinity. Otherwise we have to resort to an overflow
-     * operation to generate infinity.
-     */
-# if defined(TRIO_PLATFORM_UNIX)
-    void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
-# endif
-
-    result = HUGE_VAL;
-    if (HUGE_VAL == DBL_MAX) {
-      /* Force overflow */
-      result += HUGE_VAL;
-    }
-
-# if defined(TRIO_PLATFORM_UNIX)
-    signal(SIGFPE, signal_handler);
-# endif
-
-#endif
-  }
-  return result;
-}
-
-/**
-   Generate negative infinity.
-
-   @return Floating-point value of negative infinity.
-*/
-TRIO_PUBLIC double
-trio_ninf(TRIO_NOARGS)
-{
-  static double result = 0.0;
-
-  if (result == 0.0) {
-    /*
-     * Negative infinity is calculated by negating positive infinity,
-     * which can be done because it is legal to do calculations on
-     * infinity (for example,  1 / infinity == 0).
-     */
-    result = -trio_pinf();
-  }
-  return result;
-}
-
-/**
-   Generate NaN.
-
-   @return Floating-point representation of NaN.
-*/
-TRIO_PUBLIC double
-trio_nan(TRIO_NOARGS)
-{
-  /* Cache the result */
-  static double result = 0.0;
-
-  if (result == 0.0) {
-
-#if defined(TRIO_COMPILER_SUPPORTS_C99)
-    result = nan("");
-
-#elif defined(NAN) && defined(__STDC_IEC_559__)
-    result = (double)NAN;
-
-#elif defined(USE_IEEE_754)
-    result = trio_make_double(ieee_754_qnan_array);
-
-#else
-    /*
-     * There are several ways to generate NaN. The one used here is
-     * to divide infinity by infinity. I would have preferred to add
-     * negative infinity to positive infinity, but that yields wrong
-     * result (infinity) on FreeBSD.
-     *
-     * This may fail if the hardware does not support NaN, or if
-     * the Invalid Operation floating-point exception is unmasked.
-     */
-# if defined(TRIO_PLATFORM_UNIX)
-    void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
-# endif
-
-    result = trio_pinf() / trio_pinf();
-
-# if defined(TRIO_PLATFORM_UNIX)
-    signal(SIGFPE, signal_handler);
-# endif
-
-#endif
-  }
-  return result;
-}
-
-/**
-   Check for NaN.
-
-   @param number An arbitrary floating-point number.
-   @return Boolean value indicating whether or not the number is a NaN.
-*/
-TRIO_PUBLIC int
-trio_isnan
-TRIO_ARGS1((number),
-	   double number)
-{
-#if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \
- || defined(TRIO_COMPILER_SUPPORTS_UNIX95)
-  /*
-   * C99 defines isnan() as a macro. UNIX95 defines isnan() as a
-   * function. This function was already present in XPG4, but this
-   * is a bit tricky to detect with compiler defines, so we choose
-   * the conservative approach and only use it for UNIX95.
-   */
-  return isnan(number);
-
-#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
-  /*
-   * Microsoft Visual C++ and Borland C++ Builder have an _isnan()
-   * function.
-   */
-  return _isnan(number) ? TRIO_TRUE : TRIO_FALSE;
-
-#elif defined(USE_IEEE_754)
-  /*
-   * Examine IEEE 754 bit-pattern. A NaN must have a special exponent
-   * pattern, and a non-empty mantissa.
-   */
-  int has_mantissa;
-  int is_special_quantity;
-
-  is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
-
-  return (is_special_quantity && has_mantissa);
-
-#else
-  /*
-   * Fallback solution
-   */
-  int status;
-  double integral, fraction;
-
-# if defined(TRIO_PLATFORM_UNIX)
-  void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
-# endif
-
-  status = (/*
-	     * NaN is the only number which does not compare to itself
-	     */
-	    ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) ||
-	    /*
-	     * Fallback solution if NaN compares to NaN
-	     */
-	    ((number != 0.0) &&
-	     (fraction = modf(number, &integral),
-	      integral == fraction)));
-
-# if defined(TRIO_PLATFORM_UNIX)
-  signal(SIGFPE, signal_handler);
-# endif
-
-  return status;
-
-#endif
-}
-
-/**
-   Check for infinity.
-
-   @param number An arbitrary floating-point number.
-   @return 1 if positive infinity, -1 if negative infinity, 0 otherwise.
-*/
-TRIO_PUBLIC int
-trio_isinf
-TRIO_ARGS1((number),
-	   double number)
-{
-#if defined(TRIO_COMPILER_DECC) && !defined(__linux__)
-  /*
-   * DECC has an isinf() macro, but it works differently than that
-   * of C99, so we use the fp_class() function instead.
-   */
-  return ((fp_class(number) == FP_POS_INF)
-	  ? 1
-	  : ((fp_class(number) == FP_NEG_INF) ? -1 : 0));
-
-#elif defined(isinf)
-  /*
-   * C99 defines isinf() as a macro.
-   */
-  return isinf(number)
-    ? ((number > 0.0) ? 1 : -1)
-    : 0;
-
-#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
-  /*
-   * Microsoft Visual C++ and Borland C++ Builder have an _fpclass()
-   * function that can be used to detect infinity.
-   */
-  return ((_fpclass(number) == _FPCLASS_PINF)
-	  ? 1
-	  : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0));
-
-#elif defined(USE_IEEE_754)
-  /*
-   * Examine IEEE 754 bit-pattern. Infinity must have a special exponent
-   * pattern, and an empty mantissa.
-   */
-  int has_mantissa;
-  int is_special_quantity;
-
-  is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
-
-  return (is_special_quantity && !has_mantissa)
-    ? ((number < 0.0) ? -1 : 1)
-    : 0;
-
-#else
-  /*
-   * Fallback solution.
-   */
-  int status;
-
-# if defined(TRIO_PLATFORM_UNIX)
-  void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
-# endif
-
-  double infinity = trio_pinf();
-
-  status = ((number == infinity)
-	    ? 1
-	    : ((number == -infinity) ? -1 : 0));
-
-# if defined(TRIO_PLATFORM_UNIX)
-  signal(SIGFPE, signal_handler);
-# endif
-
-  return status;
-
-#endif
-}
-
-#if 0
-	/* Temporary fix - this routine is not used anywhere */
-/**
-   Check for finity.
-
-   @param number An arbitrary floating-point number.
-   @return Boolean value indicating whether or not the number is a finite.
-*/
-TRIO_PUBLIC int
-trio_isfinite
-TRIO_ARGS1((number),
-	   double number)
-{
-#if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite)
-  /*
-   * C99 defines isfinite() as a macro.
-   */
-  return isfinite(number);
-
-#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
-  /*
-   * Microsoft Visual C++ and Borland C++ Builder use _finite().
-   */
-  return _finite(number);
-
-#elif defined(USE_IEEE_754)
-  /*
-   * Examine IEEE 754 bit-pattern. For finity we do not care about the
-   * mantissa.
-   */
-  int dummy;
-
-  return (! trio_is_special_quantity(number, &dummy));
-
-#else
-  /*
-   * Fallback solution.
-   */
-  return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0));
-
-#endif
-}
-
-#endif
-
-/*
- * The sign of NaN is always false
- */
-TRIO_PUBLIC int
-trio_fpclassify_and_signbit
-TRIO_ARGS2((number, is_negative),
-	   double number,
-	   int *is_negative)
-{
-#if defined(fpclassify) && defined(signbit)
-  /*
-   * C99 defines fpclassify() and signbit() as a macros
-   */
-  *is_negative = signbit(number);
-  switch (fpclassify(number)) {
-  case FP_NAN:
-    return TRIO_FP_NAN;
-  case FP_INFINITE:
-    return TRIO_FP_INFINITE;
-  case FP_SUBNORMAL:
-    return TRIO_FP_SUBNORMAL;
-  case FP_ZERO:
-    return TRIO_FP_ZERO;
-  default:
-    return TRIO_FP_NORMAL;
-  }
-
-#else
-# if defined(TRIO_COMPILER_DECC)
-  /*
-   * DECC has an fp_class() function.
-   */
-#  define TRIO_FPCLASSIFY(n) fp_class(n)
-#  define TRIO_QUIET_NAN FP_QNAN
-#  define TRIO_SIGNALLING_NAN FP_SNAN
-#  define TRIO_POSITIVE_INFINITY FP_POS_INF
-#  define TRIO_NEGATIVE_INFINITY FP_NEG_INF
-#  define TRIO_POSITIVE_SUBNORMAL FP_POS_DENORM
-#  define TRIO_NEGATIVE_SUBNORMAL FP_NEG_DENORM
-#  define TRIO_POSITIVE_ZERO FP_POS_ZERO
-#  define TRIO_NEGATIVE_ZERO FP_NEG_ZERO
-#  define TRIO_POSITIVE_NORMAL FP_POS_NORM
-#  define TRIO_NEGATIVE_NORMAL FP_NEG_NORM
-
-# elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
-  /*
-   * Microsoft Visual C++ and Borland C++ Builder have an _fpclass()
-   * function.
-   */
-#  define TRIO_FPCLASSIFY(n) _fpclass(n)
-#  define TRIO_QUIET_NAN _FPCLASS_QNAN
-#  define TRIO_SIGNALLING_NAN _FPCLASS_SNAN
-#  define TRIO_POSITIVE_INFINITY _FPCLASS_PINF
-#  define TRIO_NEGATIVE_INFINITY _FPCLASS_NINF
-#  define TRIO_POSITIVE_SUBNORMAL _FPCLASS_PD
-#  define TRIO_NEGATIVE_SUBNORMAL _FPCLASS_ND
-#  define TRIO_POSITIVE_ZERO _FPCLASS_PZ
-#  define TRIO_NEGATIVE_ZERO _FPCLASS_NZ
-#  define TRIO_POSITIVE_NORMAL _FPCLASS_PN
-#  define TRIO_NEGATIVE_NORMAL _FPCLASS_NN
-
-# elif defined(FP_PLUS_NORM)
-  /*
-   * HP-UX 9.x and 10.x have an fpclassify() function, that is different
-   * from the C99 fpclassify() macro supported on HP-UX 11.x.
-   *
-   * AIX has class() for C, and _class() for C++, which returns the
-   * same values as the HP-UX fpclassify() function.
-   */
-#  if defined(TRIO_PLATFORM_AIX)
-#   if defined(__cplusplus)
-#    define TRIO_FPCLASSIFY(n) _class(n)
-#   else
-#    define TRIO_FPCLASSIFY(n) class(n)
-#   endif
-#  else
-#   define TRIO_FPCLASSIFY(n) fpclassify(n)
-#  endif
-#  define TRIO_QUIET_NAN FP_QNAN
-#  define TRIO_SIGNALLING_NAN FP_SNAN
-#  define TRIO_POSITIVE_INFINITY FP_PLUS_INF
-#  define TRIO_NEGATIVE_INFINITY FP_MINUS_INF
-#  define TRIO_POSITIVE_SUBNORMAL FP_PLUS_DENORM
-#  define TRIO_NEGATIVE_SUBNORMAL FP_MINUS_DENORM
-#  define TRIO_POSITIVE_ZERO FP_PLUS_ZERO
-#  define TRIO_NEGATIVE_ZERO FP_MINUS_ZERO
-#  define TRIO_POSITIVE_NORMAL FP_PLUS_NORM
-#  define TRIO_NEGATIVE_NORMAL FP_MINUS_NORM
-# endif
-
-# if defined(TRIO_FPCLASSIFY)
-  switch (TRIO_FPCLASSIFY(number)) {
-  case TRIO_QUIET_NAN:
-  case TRIO_SIGNALLING_NAN:
-    *is_negative = TRIO_FALSE; /* NaN has no sign */
-    return TRIO_FP_NAN;
-  case TRIO_POSITIVE_INFINITY:
-    *is_negative = TRIO_FALSE;
-    return TRIO_FP_INFINITE;
-  case TRIO_NEGATIVE_INFINITY:
-    *is_negative = TRIO_TRUE;
-    return TRIO_FP_INFINITE;
-  case TRIO_POSITIVE_SUBNORMAL:
-    *is_negative = TRIO_FALSE;
-    return TRIO_FP_SUBNORMAL;
-  case TRIO_NEGATIVE_SUBNORMAL:
-    *is_negative = TRIO_TRUE;
-    return TRIO_FP_SUBNORMAL;
-  case TRIO_POSITIVE_ZERO:
-    *is_negative = TRIO_FALSE;
-    return TRIO_FP_ZERO;
-  case TRIO_NEGATIVE_ZERO:
-    *is_negative = TRIO_TRUE;
-    return TRIO_FP_ZERO;
-  case TRIO_POSITIVE_NORMAL:
-    *is_negative = TRIO_FALSE;
-    return TRIO_FP_NORMAL;
-  case TRIO_NEGATIVE_NORMAL:
-    *is_negative = TRIO_TRUE;
-    return TRIO_FP_NORMAL;
-  default:
-    /* Just in case... */
-    *is_negative = (number < 0.0);
-    return TRIO_FP_NORMAL;
-  }
-
-# else
-  /*
-   * Fallback solution.
-   */
-  int rc;
-
-  if (number == 0.0) {
-    /*
-     * In IEEE 754 the sign of zero is ignored in comparisons, so we
-     * have to handle this as a special case by examining the sign bit
-     * directly.
-     */
-#  if defined(USE_IEEE_754)
-    *is_negative = trio_is_negative(number);
-#  else
-    *is_negative = TRIO_FALSE; /* FIXME */
-#  endif
-    return TRIO_FP_ZERO;
-  }
-  if (trio_isnan(number)) {
-    *is_negative = TRIO_FALSE;
-    return TRIO_FP_NAN;
-  }
-  if ((rc = trio_isinf(number))) {
-    *is_negative = (rc == -1);
-    return TRIO_FP_INFINITE;
-  }
-  if ((number > 0.0) && (number < DBL_MIN)) {
-    *is_negative = TRIO_FALSE;
-    return TRIO_FP_SUBNORMAL;
-  }
-  if ((number < 0.0) && (number > -DBL_MIN)) {
-    *is_negative = TRIO_TRUE;
-    return TRIO_FP_SUBNORMAL;
-  }
-  *is_negative = (number < 0.0);
-  return TRIO_FP_NORMAL;
-
-# endif
-#endif
-}
-
-/**
-   Examine the sign of a number.
-
-   @param number An arbitrary floating-point number.
-   @return Boolean value indicating whether or not the number has the
-   sign bit set (i.e. is negative).
-*/
-TRIO_PUBLIC int
-trio_signbit
-TRIO_ARGS1((number),
-	   double number)
-{
-  int is_negative;
-
-  (void)trio_fpclassify_and_signbit(number, &is_negative);
-  return is_negative;
-}
-
-#if 0
-	/* Temporary fix - this routine is not used in libxml */
-/**
-   Examine the class of a number.
-
-   @param number An arbitrary floating-point number.
-   @return Enumerable value indicating the class of @p number
-*/
-TRIO_PUBLIC int
-trio_fpclassify
-TRIO_ARGS1((number),
-	   double number)
-{
-  int dummy;
-
-  return trio_fpclassify_and_signbit(number, &dummy);
-}
-
-#endif
-
-/** @} SpecialQuantities */
-
-/*************************************************************************
- * For test purposes.
- *
- * Add the following compiler option to include this test code.
- *
- *  Unix : -DSTANDALONE
- *  VMS  : /DEFINE=(STANDALONE)
- */
-#if defined(STANDALONE)
-# include <stdio.h>
-
-static TRIO_CONST char *
-getClassification
-TRIO_ARGS1((type),
-	   int type)
-{
-  switch (type) {
-  case TRIO_FP_INFINITE:
-    return "FP_INFINITE";
-  case TRIO_FP_NAN:
-    return "FP_NAN";
-  case TRIO_FP_NORMAL:
-    return "FP_NORMAL";
-  case TRIO_FP_SUBNORMAL:
-    return "FP_SUBNORMAL";
-  case TRIO_FP_ZERO:
-    return "FP_ZERO";
-  default:
-    return "FP_UNKNOWN";
-  }
-}
-
-static void
-print_class
-TRIO_ARGS2((prefix, number),
-	   TRIO_CONST char *prefix,
-	   double number)
-{
-  printf("%-6s: %s %-15s %g\n",
-	 prefix,
-	 trio_signbit(number) ? "-" : "+",
-	 getClassification(TRIO_FPCLASSIFY(number)),
-	 number);
-}
-
-int main(TRIO_NOARGS)
-{
-  double my_nan;
-  double my_pinf;
-  double my_ninf;
-# if defined(TRIO_PLATFORM_UNIX)
-  void (*signal_handler) TRIO_PROTO((int));
-# endif
-
-  my_nan = trio_nan();
-  my_pinf = trio_pinf();
-  my_ninf = trio_ninf();
-
-  print_class("Nan", my_nan);
-  print_class("PInf", my_pinf);
-  print_class("NInf", my_ninf);
-  print_class("PZero", 0.0);
-  print_class("NZero", -0.0);
-  print_class("PNorm", 1.0);
-  print_class("NNorm", -1.0);
-  print_class("PSub", 1.01e-307 - 1.00e-307);
-  print_class("NSub", 1.00e-307 - 1.01e-307);
-
-  printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
-	 my_nan,
-	 ((unsigned char *)&my_nan)[0],
-	 ((unsigned char *)&my_nan)[1],
-	 ((unsigned char *)&my_nan)[2],
-	 ((unsigned char *)&my_nan)[3],
-	 ((unsigned char *)&my_nan)[4],
-	 ((unsigned char *)&my_nan)[5],
-	 ((unsigned char *)&my_nan)[6],
-	 ((unsigned char *)&my_nan)[7],
-	 trio_isnan(my_nan), trio_isinf(my_nan));
-  printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
-	 my_pinf,
-	 ((unsigned char *)&my_pinf)[0],
-	 ((unsigned char *)&my_pinf)[1],
-	 ((unsigned char *)&my_pinf)[2],
-	 ((unsigned char *)&my_pinf)[3],
-	 ((unsigned char *)&my_pinf)[4],
-	 ((unsigned char *)&my_pinf)[5],
-	 ((unsigned char *)&my_pinf)[6],
-	 ((unsigned char *)&my_pinf)[7],
-	 trio_isnan(my_pinf), trio_isinf(my_pinf));
-  printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
-	 my_ninf,
-	 ((unsigned char *)&my_ninf)[0],
-	 ((unsigned char *)&my_ninf)[1],
-	 ((unsigned char *)&my_ninf)[2],
-	 ((unsigned char *)&my_ninf)[3],
-	 ((unsigned char *)&my_ninf)[4],
-	 ((unsigned char *)&my_ninf)[5],
-	 ((unsigned char *)&my_ninf)[6],
-	 ((unsigned char *)&my_ninf)[7],
-	 trio_isnan(my_ninf), trio_isinf(my_ninf));
-
-# if defined(TRIO_PLATFORM_UNIX)
-  signal_handler = signal(SIGFPE, SIG_IGN);
-# endif
-
-  my_pinf = DBL_MAX + DBL_MAX;
-  my_ninf = -my_pinf;
-  my_nan = my_pinf / my_pinf;
-
-# if defined(TRIO_PLATFORM_UNIX)
-  signal(SIGFPE, signal_handler);
-# endif
-
-  printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
-	 my_nan,
-	 ((unsigned char *)&my_nan)[0],
-	 ((unsigned char *)&my_nan)[1],
-	 ((unsigned char *)&my_nan)[2],
-	 ((unsigned char *)&my_nan)[3],
-	 ((unsigned char *)&my_nan)[4],
-	 ((unsigned char *)&my_nan)[5],
-	 ((unsigned char *)&my_nan)[6],
-	 ((unsigned char *)&my_nan)[7],
-	 trio_isnan(my_nan), trio_isinf(my_nan));
-  printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
-	 my_pinf,
-	 ((unsigned char *)&my_pinf)[0],
-	 ((unsigned char *)&my_pinf)[1],
-	 ((unsigned char *)&my_pinf)[2],
-	 ((unsigned char *)&my_pinf)[3],
-	 ((unsigned char *)&my_pinf)[4],
-	 ((unsigned char *)&my_pinf)[5],
-	 ((unsigned char *)&my_pinf)[6],
-	 ((unsigned char *)&my_pinf)[7],
-	 trio_isnan(my_pinf), trio_isinf(my_pinf));
-  printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
-	 my_ninf,
-	 ((unsigned char *)&my_ninf)[0],
-	 ((unsigned char *)&my_ninf)[1],
-	 ((unsigned char *)&my_ninf)[2],
-	 ((unsigned char *)&my_ninf)[3],
-	 ((unsigned char *)&my_ninf)[4],
-	 ((unsigned char *)&my_ninf)[5],
-	 ((unsigned char *)&my_ninf)[6],
-	 ((unsigned char *)&my_ninf)[7],
-	 trio_isnan(my_ninf), trio_isinf(my_ninf));
-
-  return 0;
-}
-#endif
diff --git a/trionan.h b/trionan.h
deleted file mode 100644
index eac0e6f168628d8bc31779ebf855391a5b1aaac1..0000000000000000000000000000000000000000
--- a/trionan.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*************************************************************************
- *
- * $Id$
- *
- * Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
- * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
- *
- ************************************************************************/
-
-#ifndef TRIO_NAN_H
-#define TRIO_NAN_H
-
-#include "triodef.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum {
-  TRIO_FP_INFINITE,
-  TRIO_FP_NAN,
-  TRIO_FP_NORMAL,
-  TRIO_FP_SUBNORMAL,
-  TRIO_FP_ZERO
-};
-
-/*
- * Return NaN (Not-a-Number).
- */
-TRIO_PUBLIC double trio_nan TRIO_PROTO((void));
-
-/*
- * Return positive infinity.
- */
-TRIO_PUBLIC double trio_pinf TRIO_PROTO((void));
-
-/*
- * Return negative infinity.
- */
-TRIO_PUBLIC double trio_ninf TRIO_PROTO((void));
-
-/*
- * Return negative zero.
- */
-TRIO_PUBLIC double trio_nzero TRIO_PROTO((TRIO_NOARGS));
-
-/*
- * If number is a NaN return non-zero, otherwise return zero.
- */
-TRIO_PUBLIC int trio_isnan TRIO_PROTO((double number));
-
-/*
- * If number is positive infinity return 1, if number is negative
- * infinity return -1, otherwise return 0.
- */
-TRIO_PUBLIC int trio_isinf TRIO_PROTO((double number));
-
-/*
- * If number is finite return non-zero, otherwise return zero.
- */
-#if 0
-	/* Temporary fix - these 2 routines not used in libxml */
-TRIO_PUBLIC int trio_isfinite TRIO_PROTO((double number));
-
-TRIO_PUBLIC int trio_fpclassify TRIO_PROTO((double number));
-#endif
-
-TRIO_PUBLIC int trio_signbit TRIO_PROTO((double number));
-
-TRIO_PUBLIC int trio_fpclassify_and_signbit TRIO_PROTO((double number, int *is_negative));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TRIO_NAN_H */
diff --git a/uri.c b/uri.c
index e5c790ebd91cbc5505a42ccd29c47b7e4f05163f..3b986532aeceba33f1e88525c0a1550f8e8b0468 100644
--- a/uri.c
+++ b/uri.c
@@ -16,9 +16,10 @@
 
 #include <libxml/xmlmemory.h>
 #include <libxml/uri.h>
-#include <libxml/globals.h>
 #include <libxml/xmlerror.h>
 
+#include "private/error.h"
+
 /**
  * MAX_URI_LENGTH:
  *
@@ -33,22 +34,8 @@
  */
 #define MAX_URI_LENGTH 1024 * 1024
 
-static void
-xmlURIErrMemory(const char *extra)
-{
-    if (extra)
-        __xmlRaiseError(NULL, NULL, NULL,
-                        NULL, NULL, XML_FROM_URI,
-                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
-                        extra, NULL, NULL, 0, 0,
-                        "Memory allocation failed : %s\n", extra);
-    else
-        __xmlRaiseError(NULL, NULL, NULL,
-                        NULL, NULL, XML_FROM_URI,
-                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
-                        NULL, NULL, NULL, 0, 0,
-                        "Memory allocation failed\n");
-}
+#define PORT_EMPTY           0
+#define PORT_EMPTY_SERVER   -1
 
 static void xmlCleanURI(xmlURIPtr uri);
 
@@ -64,7 +51,6 @@ static void xmlCleanURI(xmlURIPtr uri);
  *            "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" |
  *            "u" | "v" | "w" | "x" | "y" | "z"
  */
-
 #define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z'))
 
 /*
@@ -85,7 +71,6 @@ static void xmlCleanURI(xmlURIPtr uri);
 /*
  * alphanum = alpha | digit
  */
-
 #define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x))
 
 /*
@@ -99,16 +84,15 @@ static void xmlCleanURI(xmlURIPtr uri);
 /*
  * unwise = "{" | "}" | "|" | "\" | "^" | "`"
  */
-
 #define IS_UNWISE(p)                                                    \
       (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) ||         \
        ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) ||        \
        ((*(p) == ']')) || ((*(p) == '`')))
+
 /*
  * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," |
  *            "[" | "]"
  */
-
 #define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \
         ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \
         ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \
@@ -117,13 +101,11 @@ static void xmlCleanURI(xmlURIPtr uri);
 /*
  * unreserved = alphanum | mark
  */
-
 #define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x))
 
 /*
  * Skip to next pointer char, handle escaped sequences
  */
-
 #define NEXT(p) ((*p == '%')? p += 3 : p++)
 
 /*
@@ -135,7 +117,6 @@ static void xmlCleanURI(xmlURIPtr uri);
  *
  * path          = [ abs_path | opaque_part ]
  */
-
 #define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n))
 
 /************************************************************************
@@ -177,7 +158,7 @@ static void xmlCleanURI(xmlURIPtr uri);
 /*
  *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
  */
-#define ISA_UNRESERVED(p)						\
+#define ISA_STRICTLY_UNRESERVED(p)					\
       ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) ||		\
        ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~')))
 
@@ -190,10 +171,47 @@ static void xmlCleanURI(xmlURIPtr uri);
 /*
  *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
  */
-#define ISA_PCHAR(p)							\
-     (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) ||	\
+#define ISA_PCHAR(u, p)							\
+     (ISA_UNRESERVED(u, p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) ||	\
       ((*(p) == ':')) || ((*(p) == '@')))
 
+/*
+ * From https://www.w3.org/TR/leiri/
+ *
+ * " " / "<" / ">" / '"' / "{" / "}" / "|"
+ * / "\" / "^" / "`" / %x0-1F / %x7F-D7FF
+ * / %xE000-FFFD / %x10000-10FFFF
+ */
+#define ISA_UCSCHAR(p) \
+    ((*(p) <= 0x20) || (*(p) >= 0x7F) || (*(p) == '<') || (*(p) == '>') || \
+     (*(p) == '"')  || (*(p) == '{')  || (*(p) == '}') || (*(p) == '|') || \
+     (*(p) == '\\') || (*(p) == '^')  || (*(p) == '`'))
+
+#define ISA_UNRESERVED(u, p) (xmlIsUnreserved(u, p))
+
+#define XML_URI_ALLOW_UNWISE    1
+#define XML_URI_NO_UNESCAPE     2
+#define XML_URI_ALLOW_UCSCHAR   4
+
+static int
+xmlIsUnreserved(xmlURIPtr uri, const char *cur) {
+    if (uri == NULL)
+        return(0);
+
+    if (ISA_STRICTLY_UNRESERVED(cur))
+        return(1);
+
+    if (uri->cleanup & XML_URI_ALLOW_UNWISE) {
+        if (IS_UNWISE(cur))
+            return(1);
+    } else if (uri->cleanup & XML_URI_ALLOW_UCSCHAR) {
+        if (ISA_UCSCHAR(cur))
+            return(1);
+    }
+
+    return(0);
+}
+
 /**
  * xmlParse3986Scheme:
  * @uri:  pointer to an URI structure
@@ -209,18 +227,17 @@ static int
 xmlParse3986Scheme(xmlURIPtr uri, const char **str) {
     const char *cur;
 
-    if (str == NULL)
-	return(-1);
-
     cur = *str;
     if (!ISA_ALPHA(cur))
-	return(2);
+	return(1);
     cur++;
     while (ISA_ALPHA(cur) || ISA_DIGIT(cur) ||
            (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++;
     if (uri != NULL) {
 	if (uri->scheme != NULL) xmlFree(uri->scheme);
 	uri->scheme = STRNDUP(*str, cur - *str);
+        if (uri->scheme == NULL)
+            return(-1);
     }
     *str = cur;
     return(0);
@@ -246,22 +263,20 @@ xmlParse3986Fragment(xmlURIPtr uri, const char **str)
 {
     const char *cur;
 
-    if (str == NULL)
-        return (-1);
-
     cur = *str;
 
-    while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
-           (*cur == '[') || (*cur == ']') ||
-           ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))
+    while ((ISA_PCHAR(uri, cur)) || (*cur == '/') || (*cur == '?') ||
+           (*cur == '[') || (*cur == ']'))
         NEXT(cur);
     if (uri != NULL) {
         if (uri->fragment != NULL)
             xmlFree(uri->fragment);
-	if (uri->cleanup & 2)
+	if (uri->cleanup & XML_URI_NO_UNESCAPE)
 	    uri->fragment = STRNDUP(*str, cur - *str);
 	else
 	    uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL);
+        if (uri->fragment == NULL)
+            return (-1);
     }
     *str = cur;
     return (0);
@@ -283,21 +298,19 @@ xmlParse3986Query(xmlURIPtr uri, const char **str)
 {
     const char *cur;
 
-    if (str == NULL)
-        return (-1);
-
     cur = *str;
 
-    while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
-           ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))
+    while ((ISA_PCHAR(uri, cur)) || (*cur == '/') || (*cur == '?'))
         NEXT(cur);
     if (uri != NULL) {
         if (uri->query != NULL)
             xmlFree(uri->query);
-	if (uri->cleanup & 2)
+	if (uri->cleanup & XML_URI_NO_UNESCAPE)
 	    uri->query = STRNDUP(*str, cur - *str);
 	else
 	    uri->query = xmlURIUnescapeString(*str, cur - *str, NULL);
+        if (uri->query == NULL)
+            return (-1);
 
 	/* Save the raw bytes of the query as well.
 	 * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114
@@ -305,6 +318,8 @@ xmlParse3986Query(xmlURIPtr uri, const char **str)
 	if (uri->query_raw != NULL)
 	    xmlFree (uri->query_raw);
 	uri->query_raw = STRNDUP (*str, cur - *str);
+        if (uri->query_raw == NULL)
+            return (-1);
     }
     *str = cur;
     return (0);
@@ -367,16 +382,18 @@ xmlParse3986Userinfo(xmlURIPtr uri, const char **str)
     const char *cur;
 
     cur = *str;
-    while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) ||
+    while (ISA_UNRESERVED(uri, cur) || ISA_PCT_ENCODED(cur) ||
            ISA_SUB_DELIM(cur) || (*cur == ':'))
 	NEXT(cur);
     if (*cur == '@') {
 	if (uri != NULL) {
 	    if (uri->user != NULL) xmlFree(uri->user);
-	    if (uri->cleanup & 2)
+	    if (uri->cleanup & XML_URI_NO_UNESCAPE)
 		uri->user = STRNDUP(*str, cur - *str);
 	    else
 		uri->user = xmlURIUnescapeString(*str, cur - *str, NULL);
+            if (uri->user == NULL)
+                return(-1);
 	}
 	*str = cur;
 	return(0);
@@ -481,7 +498,8 @@ not_ipv4:
     /*
      * then this should be a hostname which can be empty
      */
-    while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur))
+    while (ISA_UNRESERVED(uri, cur) ||
+           ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur))
         NEXT(cur);
 found:
     if (uri != NULL) {
@@ -489,10 +507,12 @@ found:
 	uri->authority = NULL;
 	if (uri->server != NULL) xmlFree(uri->server);
 	if (cur != host) {
-	    if (uri->cleanup & 2)
+	    if (uri->cleanup & XML_URI_NO_UNESCAPE)
 		uri->server = STRNDUP(host, cur - host);
 	    else
 		uri->server = xmlURIUnescapeString(host, cur - host, NULL);
+            if (uri->server == NULL)
+                return(-1);
 	} else
 	    uri->server = NULL;
     }
@@ -523,6 +543,8 @@ xmlParse3986Authority(xmlURIPtr uri, const char **str)
      * try to parse an userinfo and check for the trailing @
      */
     ret = xmlParse3986Userinfo(uri, &cur);
+    if (ret < 0)
+        return(ret);
     if ((ret != 0) || (*cur != '@'))
         cur = *str;
     else
@@ -555,17 +577,17 @@ xmlParse3986Authority(xmlURIPtr uri, const char **str)
  * Returns 0 or the error code
  */
 static int
-xmlParse3986Segment(const char **str, char forbid, int empty)
+xmlParse3986Segment(xmlURIPtr uri, const char **str, char forbid, int empty)
 {
     const char *cur;
 
     cur = *str;
-    if (!ISA_PCHAR(cur)) {
+    if (!ISA_PCHAR(uri, cur)) {
         if (empty)
 	    return(0);
 	return(1);
     }
-    while (ISA_PCHAR(cur) && (*cur != forbid))
+    while (ISA_PCHAR(uri, cur) && (*cur != forbid))
         NEXT(cur);
     *str = cur;
     return (0);
@@ -593,16 +615,18 @@ xmlParse3986PathAbEmpty(xmlURIPtr uri, const char **str)
 
     while (*cur == '/') {
         cur++;
-	ret = xmlParse3986Segment(&cur, 0, 1);
+	ret = xmlParse3986Segment(uri, &cur, 0, 1);
 	if (ret != 0) return(ret);
     }
     if (uri != NULL) {
 	if (uri->path != NULL) xmlFree(uri->path);
         if (*str != cur) {
-            if (uri->cleanup & 2)
+            if (uri->cleanup & XML_URI_NO_UNESCAPE)
                 uri->path = STRNDUP(*str, cur - *str);
             else
                 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
+            if (uri->path == NULL)
+                return (-1);
         } else {
             uri->path = NULL;
         }
@@ -634,21 +658,23 @@ xmlParse3986PathAbsolute(xmlURIPtr uri, const char **str)
     if (*cur != '/')
         return(1);
     cur++;
-    ret = xmlParse3986Segment(&cur, 0, 0);
+    ret = xmlParse3986Segment(uri, &cur, 0, 0);
     if (ret == 0) {
 	while (*cur == '/') {
 	    cur++;
-	    ret = xmlParse3986Segment(&cur, 0, 1);
+	    ret = xmlParse3986Segment(uri, &cur, 0, 1);
 	    if (ret != 0) return(ret);
 	}
     }
     if (uri != NULL) {
 	if (uri->path != NULL) xmlFree(uri->path);
         if (cur != *str) {
-            if (uri->cleanup & 2)
+            if (uri->cleanup & XML_URI_NO_UNESCAPE)
                 uri->path = STRNDUP(*str, cur - *str);
             else
                 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
+            if (uri->path == NULL)
+                return (-1);
         } else {
             uri->path = NULL;
         }
@@ -677,20 +703,22 @@ xmlParse3986PathRootless(xmlURIPtr uri, const char **str)
 
     cur = *str;
 
-    ret = xmlParse3986Segment(&cur, 0, 0);
+    ret = xmlParse3986Segment(uri, &cur, 0, 0);
     if (ret != 0) return(ret);
     while (*cur == '/') {
         cur++;
-	ret = xmlParse3986Segment(&cur, 0, 1);
+	ret = xmlParse3986Segment(uri, &cur, 0, 1);
 	if (ret != 0) return(ret);
     }
     if (uri != NULL) {
 	if (uri->path != NULL) xmlFree(uri->path);
         if (cur != *str) {
-            if (uri->cleanup & 2)
+            if (uri->cleanup & XML_URI_NO_UNESCAPE)
                 uri->path = STRNDUP(*str, cur - *str);
             else
                 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
+            if (uri->path == NULL)
+                return (-1);
         } else {
             uri->path = NULL;
         }
@@ -719,20 +747,22 @@ xmlParse3986PathNoScheme(xmlURIPtr uri, const char **str)
 
     cur = *str;
 
-    ret = xmlParse3986Segment(&cur, ':', 0);
+    ret = xmlParse3986Segment(uri, &cur, ':', 0);
     if (ret != 0) return(ret);
     while (*cur == '/') {
         cur++;
-	ret = xmlParse3986Segment(&cur, 0, 1);
+	ret = xmlParse3986Segment(uri, &cur, 0, 1);
 	if (ret != 0) return(ret);
     }
     if (uri != NULL) {
 	if (uri->path != NULL) xmlFree(uri->path);
         if (cur != *str) {
-            if (uri->cleanup & 2)
+            if (uri->cleanup & XML_URI_NO_UNESCAPE)
                 uri->path = STRNDUP(*str, cur - *str);
             else
                 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
+            if (uri->path == NULL)
+                return (-1);
         } else {
             uri->path = NULL;
         }
@@ -768,8 +798,11 @@ xmlParse3986HierPart(xmlURIPtr uri, const char **str)
         cur += 2;
 	ret = xmlParse3986Authority(uri, &cur);
 	if (ret != 0) return(ret);
-	if (uri->server == NULL)
-	    uri->port = -1;
+        /*
+         * An empty server is marked with a special URI value.
+         */
+	if ((uri->server == NULL) && (uri->port == PORT_EMPTY))
+	    uri->port = PORT_EMPTY_SERVER;
 	ret = xmlParse3986PathAbEmpty(uri, &cur);
 	if (ret != 0) return(ret);
 	*str = cur;
@@ -777,7 +810,7 @@ xmlParse3986HierPart(xmlURIPtr uri, const char **str)
     } else if (*cur == '/') {
         ret = xmlParse3986PathAbsolute(uri, &cur);
 	if (ret != 0) return(ret);
-    } else if (ISA_PCHAR(cur)) {
+    } else if (ISA_PCHAR(uri, cur)) {
         ret = xmlParse3986PathRootless(uri, &cur);
 	if (ret != 0) return(ret);
     } else {
@@ -820,7 +853,7 @@ xmlParse3986RelativeRef(xmlURIPtr uri, const char *str) {
     } else if (*str == '/') {
 	ret = xmlParse3986PathAbsolute(uri, &str);
 	if (ret != 0) return(ret);
-    } else if (ISA_PCHAR(str)) {
+    } else if (ISA_PCHAR(uri, str)) {
         ret = xmlParse3986PathNoScheme(uri, &str);
 	if (ret != 0) return(ret);
     } else {
@@ -915,6 +948,8 @@ xmlParse3986URIReference(xmlURIPtr uri, const char *str) {
      * it fails.
      */
     ret = xmlParse3986URI(uri, str);
+    if (ret < 0)
+        return(ret);
     if (ret != 0) {
 	xmlCleanURI(uri);
         ret = xmlParse3986RelativeRef(uri, str);
@@ -927,30 +962,58 @@ xmlParse3986URIReference(xmlURIPtr uri, const char *str) {
 }
 
 /**
- * xmlParseURI:
+ * xmlParseURISafe:
  * @str:  the URI string to analyze
+ * @uriOut:  optional pointer to parsed URI
  *
  * Parse an URI based on RFC 3986
  *
  * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
  *
- * Returns a newly built xmlURIPtr or NULL in case of error
+ * Available since 2.13.0.
+ *
+ * Returns 0 on success, an error code (typically 1) if the URI is invalid
+ * or -1 if a memory allocation failed.
  */
-xmlURIPtr
-xmlParseURI(const char *str) {
+int
+xmlParseURISafe(const char *str, xmlURIPtr *uriOut) {
     xmlURIPtr uri;
     int ret;
 
+    if (uriOut == NULL)
+        return(1);
+    *uriOut = NULL;
     if (str == NULL)
-	return(NULL);
+	return(1);
+
     uri = xmlCreateURI();
-    if (uri != NULL) {
-	ret = xmlParse3986URIReference(uri, str);
-        if (ret) {
-	    xmlFreeURI(uri);
-	    return(NULL);
-	}
+    if (uri == NULL)
+        return(-1);
+
+    ret = xmlParse3986URIReference(uri, str);
+    if (ret) {
+        xmlFreeURI(uri);
+        return(ret);
     }
+
+    *uriOut = uri;
+    return(0);
+}
+
+/**
+ * xmlParseURI:
+ * @str:  the URI string to analyze
+ *
+ * Parse an URI based on RFC 3986
+ *
+ * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+ *
+ * Returns a newly built xmlURIPtr or NULL in case of error
+ */
+xmlURIPtr
+xmlParseURI(const char *str) {
+    xmlURIPtr uri;
+    xmlParseURISafe(str, &uri);
     return(uri);
 }
 
@@ -992,7 +1055,7 @@ xmlParseURIRaw(const char *str, int raw) {
     uri = xmlCreateURI();
     if (uri != NULL) {
         if (raw) {
-	    uri->cleanup |= 2;
+	    uri->cleanup |= XML_URI_NO_UNESCAPE;
 	}
 	ret = xmlParseURIReference(uri, str);
         if (ret) {
@@ -1021,11 +1084,10 @@ xmlCreateURI(void) {
     xmlURIPtr ret;
 
     ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI));
-    if (ret == NULL) {
-        xmlURIErrMemory("creating URI structure\n");
+    if (ret == NULL)
 	return(NULL);
-    }
     memset(ret, 0, sizeof(xmlURI));
+    ret->port = PORT_EMPTY;
     return(ret);
 }
 
@@ -1040,16 +1102,12 @@ xmlSaveUriRealloc(xmlChar *ret, int *max) {
     xmlChar *temp;
     int tmp;
 
-    if (*max > MAX_URI_LENGTH) {
-        xmlURIErrMemory("reaching arbitrary MAX_URI_LENGTH limit\n");
+    if (*max > MAX_URI_LENGTH)
         return(NULL);
-    }
     tmp = *max * 2;
     temp = (xmlChar *) xmlRealloc(ret, (tmp + 1));
-    if (temp == NULL) {
-        xmlURIErrMemory("saving URI\n");
+    if (temp == NULL)
         return(NULL);
-    }
     *max = tmp;
     return(temp);
 }
@@ -1074,11 +1132,9 @@ xmlSaveUri(xmlURIPtr uri) {
 
 
     max = 80;
-    ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar));
-    if (ret == NULL) {
-        xmlURIErrMemory("saving URI\n");
+    ret = (xmlChar *) xmlMallocAtomic(max + 1);
+    if (ret == NULL)
 	return(NULL);
-    }
     len = 0;
 
     if (uri->scheme != NULL) {
@@ -1117,7 +1173,7 @@ xmlSaveUri(xmlURIPtr uri) {
 	    }
 	}
     } else {
-	if ((uri->server != NULL) || (uri->port == -1)) {
+	if ((uri->server != NULL) || (uri->port != PORT_EMPTY)) {
 	    if (len + 3 >= max) {
                 temp = xmlSaveUriRealloc(ret, &max);
                 if (temp == NULL) goto mem_error;
@@ -1162,17 +1218,18 @@ xmlSaveUri(xmlURIPtr uri) {
 			if (temp == NULL) goto mem_error;
 			ret = temp;
 		    }
-		    ret[len++] = *p++;
-		}
-		if (uri->port > 0) {
-		    if (len + 10 >= max) {
-			temp = xmlSaveUriRealloc(ret, &max);
-			if (temp == NULL) goto mem_error;
-			ret = temp;
-		    }
-		    len += snprintf((char *) &ret[len], max - len, ":%d", uri->port);
+                    /* TODO: escaping? */
+		    ret[len++] = (xmlChar) *p++;
 		}
 	    }
+            if (uri->port > 0) {
+                if (len + 10 >= max) {
+                    temp = xmlSaveUriRealloc(ret, &max);
+                    if (temp == NULL) goto mem_error;
+                    ret = temp;
+                }
+                len += snprintf((char *) &ret[len], max - len, ":%d", uri->port);
+            }
 	} else if (uri->authority != NULL) {
 	    if (len + 3 >= max) {
                 temp = xmlSaveUriRealloc(ret, &max);
@@ -1405,195 +1462,136 @@ xmlFreeURI(xmlURIPtr uri) {
  *									*
  ************************************************************************/
 
+static int
+xmlIsPathSeparator(int c, int isFile) {
+    (void) isFile;
+
+    if (c == '/')
+        return(1);
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+    if (isFile && (c == '\\'))
+        return(1);
+#endif
+
+    return(0);
+}
+
 /**
- * xmlNormalizeURIPath:
+ * xmlNormalizePath:
  * @path:  pointer to the path string
+ * @isFile:  true for filesystem paths, false for URIs
  *
- * Applies the 5 normalization steps to a path string--that is, RFC 2396
- * Section 5.2, steps 6.c through 6.g.
- *
- * Normalization occurs directly on the string, no new allocation is done
+ * Normalize a filesystem path or URI.
  *
  * Returns 0 or an error code
  */
-int
-xmlNormalizeURIPath(char *path) {
+static int
+xmlNormalizePath(char *path, int isFile) {
     char *cur, *out;
+    int numSeg = 0;
 
     if (path == NULL)
 	return(-1);
 
-    /* Skip all initial "/" chars.  We want to get to the beginning of the
-     * first non-empty segment.
-     */
     cur = path;
-    while (cur[0] == '/')
-      ++cur;
-    if (cur[0] == '\0')
-      return(0);
+    out = path;
 
-    /* Keep everything we've seen so far.  */
-    out = cur;
+    if (*cur == 0)
+        return(0);
 
-    /*
-     * Analyze each segment in sequence for cases (c) and (d).
-     */
-    while (cur[0] != '\0') {
-	/*
-	 * c) All occurrences of "./", where "." is a complete path segment,
-	 *    are removed from the buffer string.
-	 */
-	if ((cur[0] == '.') && (cur[1] == '/')) {
-	    cur += 2;
-	    /* '//' normalization should be done at this point too */
-	    while (cur[0] == '/')
-		cur++;
-	    continue;
-	}
-
-	/*
-	 * d) If the buffer string ends with "." as a complete path segment,
-	 *    that "." is removed.
-	 */
-	if ((cur[0] == '.') && (cur[1] == '\0'))
-	    break;
-
-	/* Otherwise keep the segment.  */
-	while (cur[0] != '/') {
-            if (cur[0] == '\0')
-              goto done_cd;
-	    (out++)[0] = (cur++)[0];
-	}
-	/* normalize // */
-	while ((cur[0] == '/') && (cur[1] == '/'))
-	    cur++;
-
-        (out++)[0] = (cur++)[0];
+    if (xmlIsPathSeparator(*cur, isFile)) {
+        cur++;
+        *out++ = '/';
     }
- done_cd:
-    out[0] = '\0';
-
-    /* Reset to the beginning of the first segment for the next sequence.  */
-    cur = path;
-    while (cur[0] == '/')
-      ++cur;
-    if (cur[0] == '\0')
-	return(0);
-
-    /*
-     * Analyze each segment in sequence for cases (e) and (f).
-     *
-     * e) All occurrences of "<segment>/../", where <segment> is a
-     *    complete path segment not equal to "..", are removed from the
-     *    buffer string.  Removal of these path segments is performed
-     *    iteratively, removing the leftmost matching pattern on each
-     *    iteration, until no matching pattern remains.
-     *
-     * f) If the buffer string ends with "<segment>/..", where <segment>
-     *    is a complete path segment not equal to "..", that
-     *    "<segment>/.." is removed.
-     *
-     * To satisfy the "iterative" clause in (e), we need to collapse the
-     * string every time we find something that needs to be removed.  Thus,
-     * we don't need to keep two pointers into the string: we only need a
-     * "current position" pointer.
-     */
-    while (1) {
-        char *segp, *tmp;
-
-        /* At the beginning of each iteration of this loop, "cur" points to
-         * the first character of the segment we want to examine.
-         */
-
-        /* Find the end of the current segment.  */
-        segp = cur;
-        while ((segp[0] != '/') && (segp[0] != '\0'))
-          ++segp;
-
-        /* If this is the last segment, we're done (we need at least two
-         * segments to meet the criteria for the (e) and (f) cases).
-         */
-        if (segp[0] == '\0')
-          break;
 
-        /* If the first segment is "..", or if the next segment _isn't_ "..",
-         * keep this segment and try the next one.
+    while (*cur != 0) {
+        /*
+         * At this point, out is either empty or ends with a separator.
+         * Collapse multiple separators first.
          */
-        ++segp;
-        if (((cur[0] == '.') && (cur[1] == '.') && (segp == cur+3))
-            || ((segp[0] != '.') || (segp[1] != '.')
-                || ((segp[2] != '/') && (segp[2] != '\0')))) {
-          cur = segp;
-          continue;
+        while (xmlIsPathSeparator(*cur, isFile)) {
+#if defined(_WIN32) || defined(__CYGWIN__)
+            /* Allow two separators at start of path */
+            if ((isFile) && (out == path + 1))
+                *out++ = '/';
+#endif
+            cur++;
         }
 
-        /* If we get here, remove this segment and the next one and back up
-         * to the previous segment (if there is one), to implement the
-         * "iteratively" clause.  It's pretty much impossible to back up
-         * while maintaining two pointers into the buffer, so just compact
-         * the whole buffer now.
-         */
+        if (*cur == '.') {
+            if (cur[1] == 0) {
+                /* Ignore "." at end of path */
+                break;
+            } else if (xmlIsPathSeparator(cur[1], isFile)) {
+                /* Skip "./" */
+                cur += 2;
+                continue;
+            } else if ((cur[1] == '.') &&
+                       ((cur[2] == 0) || xmlIsPathSeparator(cur[2], isFile))) {
+                if (numSeg > 0) {
+                    /* Handle ".." by removing last segment */
+                    do {
+                        out--;
+                    } while ((out > path) &&
+                             !xmlIsPathSeparator(out[-1], isFile));
+                    numSeg--;
+
+                    if (cur[2] == 0)
+                        break;
+                    cur += 3;
+                    continue;
+                } else if (out[0] == '/') {
+                    /* Ignore extraneous ".." in absolute paths */
+                    if (cur[2] == 0)
+                        break;
+                    cur += 3;
+                    continue;
+                } else {
+                    /* Keep "../" at start of relative path */
+                    numSeg--;
+                }
+            }
+        }
 
-        /* If this is the end of the buffer, we're done.  */
-        if (segp[2] == '\0') {
-          cur[0] = '\0';
-          break;
+        /* Copy segment */
+        while ((*cur != 0) && !xmlIsPathSeparator(*cur, isFile)) {
+            *out++ = *cur++;
         }
-        /* Valgrind complained, strcpy(cur, segp + 3); */
-        /* string will overlap, do not use strcpy */
-        tmp = cur;
-        segp += 3;
-        while ((*tmp++ = *segp++) != 0)
-          ;
-
-        /* If there are no previous segments, then keep going from here.  */
-        segp = cur;
-        while ((segp > path) && ((--segp)[0] == '/'))
-          ;
-        if (segp == path)
-          continue;
-
-        /* "segp" is pointing to the end of a previous segment; find it's
-         * start.  We need to back up to the previous segment and start
-         * over with that to handle things like "foo/bar/../..".  If we
-         * don't do this, then on the first pass we'll remove the "bar/..",
-         * but be pointing at the second ".." so we won't realize we can also
-         * remove the "foo/..".
-         */
-        cur = segp;
-        while ((cur > path) && (cur[-1] != '/'))
-          --cur;
-    }
-    out[0] = '\0';
 
-    /*
-     * g) If the resulting buffer string still begins with one or more
-     *    complete path segments of "..", then the reference is
-     *    considered to be in error. Implementations may handle this
-     *    error by retaining these components in the resolved path (i.e.,
-     *    treating them as part of the final URI), by removing them from
-     *    the resolved path (i.e., discarding relative levels above the
-     *    root), or by avoiding traversal of the reference.
-     *
-     * We discard them from the final path.
-     */
-    if (path[0] == '/') {
-      cur = path;
-      while ((cur[0] == '/') && (cur[1] == '.') && (cur[2] == '.')
-             && ((cur[3] == '/') || (cur[3] == '\0')))
-	cur += 3;
+        /* Copy separator */
+        if (*cur != 0) {
+            cur++;
+            *out++ = '/';
+        }
 
-      if (cur != path) {
-	out = path;
-	while (cur[0] != '\0')
-          (out++)[0] = (cur++)[0];
-	out[0] = 0;
-      }
+        numSeg++;
     }
 
+    /* Keep "." if output is empty and it's a file */
+    if ((isFile) && (out <= path))
+        *out++ = '.';
+    *out = 0;
+
     return(0);
 }
 
+/**
+ * xmlNormalizeURIPath:
+ * @path:  pointer to the path string
+ *
+ * Applies the 5 normalization steps to a path string--that is, RFC 2396
+ * Section 5.2, steps 6.c through 6.g.
+ *
+ * Normalization occurs directly on the string, no new allocation is done
+ *
+ * Returns 0 or an error code
+ */
+int
+xmlNormalizeURIPath(char *path) {
+    return(xmlNormalizePath(path, 0));
+}
+
 static int is_hex(char c) {
     if (((c >= '0') && (c <= '9')) ||
         ((c >= 'a') && (c <= 'f')) ||
@@ -1628,10 +1626,8 @@ xmlURIUnescapeString(const char *str, int len, char *target) {
 
     if (target == NULL) {
 	ret = (char *) xmlMallocAtomic(len + 1);
-	if (ret == NULL) {
-            xmlURIErrMemory("unescaping URI value\n");
+	if (ret == NULL)
 	    return(NULL);
-	}
     } else
 	ret = target;
     in = str;
@@ -1655,6 +1651,7 @@ xmlURIUnescapeString(const char *str, int len, char *target) {
 	        c = c * 16 + (*in - 'A') + 10;
 	    in++;
 	    len -= 3;
+            /* Explicit sign change */
 	    *out++ = (char) c;
 	} else {
 	    *out++ = *in++;
@@ -1670,8 +1667,9 @@ xmlURIUnescapeString(const char *str, int len, char *target) {
  * @str:  string to escape
  * @list: exception list string of chars not to escape
  *
- * This routine escapes a string to hex, ignoring reserved characters (a-z)
- * and the characters in the exception list.
+ * This routine escapes a string to hex, ignoring unreserved characters
+ * a-z, A-Z, 0-9, "-._~", a few sub-delims "!*'()", the gen-delim "@"
+ * (why?) and the characters in the exception list.
  *
  * Returns a new escaped string or NULL in case of error.
  */
@@ -1687,25 +1685,24 @@ xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) {
     if (str[0] == 0)
 	return(xmlStrdup(str));
     len = xmlStrlen(str);
-    if (!(len > 0)) return(NULL);
 
     len += 20;
     ret = (xmlChar *) xmlMallocAtomic(len);
-    if (ret == NULL) {
-        xmlURIErrMemory("escaping URI value\n");
+    if (ret == NULL)
 	return(NULL);
-    }
     in = (const xmlChar *) str;
     out = 0;
     while(*in != 0) {
 	if (len - out <= 3) {
-            temp = xmlSaveUriRealloc(ret, &len);
+            if (len > INT_MAX / 2)
+                return(NULL);
+            temp = xmlRealloc(ret, len * 2);
 	    if (temp == NULL) {
-                xmlURIErrMemory("escaping URI value\n");
 		xmlFree(ret);
 		return(NULL);
 	    }
 	    ret = temp;
+            len *= 2;
 	}
 
 	ch = *in;
@@ -1763,7 +1760,7 @@ xmlURIEscape(const xmlChar * str)
 	/*
 	 * Allow escaping errors in the unescaped form
 	 */
-        uri->cleanup = 1;
+        uri->cleanup = XML_URI_ALLOW_UNWISE;
         ret2 = xmlParseURIReference(uri, (const char *)str);
         if (ret2) {
             xmlFreeURI(uri);
@@ -1777,7 +1774,6 @@ xmlURIEscape(const xmlChar * str)
     ret = NULL;
 
 #define NULLCHK(p) if(!p) { \
-         xmlURIErrMemory("escaping URI value\n"); \
          xmlFreeURI(uri); \
          xmlFree(ret); \
          return NULL; } \
@@ -1817,10 +1813,10 @@ xmlURIEscape(const xmlChar * str)
         xmlFree(segment);
     }
 
-    if (uri->port) {
-        xmlChar port[10];
+    if (uri->port > 0) {
+        xmlChar port[11];
 
-        snprintf((char *) port, 10, "%d", uri->port);
+        snprintf((char *) port, 11, "%d", uri->port);
         ret = xmlStrcat(ret, BAD_CAST ":");
         ret = xmlStrcat(ret, port);
     }
@@ -1873,10 +1869,132 @@ xmlURIEscape(const xmlChar * str)
  *									*
  ************************************************************************/
 
+static int
+xmlIsAbsolutePath(const xmlChar *path) {
+    int c = path[0];
+
+    if (xmlIsPathSeparator(c, 1))
+        return(1);
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+    if ((((c >= 'A') && (c <= 'Z')) ||
+         ((c >= 'a') && (c <= 'z'))) &&
+        (path[1] == ':'))
+        return(1);
+#endif
+
+    return(0);
+}
+
 /**
- * xmlBuildURI:
+ * xmlResolvePath:
+ * @ref:  the filesystem path
+ * @base:  the base value
+ * @out:  pointer to result URI
+ *
+ * Resolves a filesystem path from a base path.
+ *
+ * Returns 0 on success, -1 if a memory allocation failed or an error
+ * code if URI or base are invalid.
+ */
+static int
+xmlResolvePath(const xmlChar *escRef, const xmlChar *base, xmlChar **out) {
+    const xmlChar *fragment;
+    xmlChar *tmp = NULL;
+    xmlChar *ref = NULL;
+    xmlChar *result = NULL;
+    int ret = -1;
+    int i;
+
+    if (out == NULL)
+        return(1);
+    *out = NULL;
+
+    if ((escRef == NULL) || (escRef[0] == 0)) {
+        if ((base == NULL) || (base[0] == 0))
+            return(1);
+        ref = xmlStrdup(base);
+        if (ref == NULL)
+            goto err_memory;
+        *out = ref;
+        return(0);
+    }
+
+    /*
+     * If a URI is resolved, we can assume it is a valid URI and not
+     * a filesystem path. This means we have to unescape the part
+     * before the fragment.
+     */
+    fragment = xmlStrchr(escRef, '#');
+    if (fragment != NULL) {
+        tmp = xmlStrndup(escRef, fragment - escRef);
+        if (tmp == NULL)
+            goto err_memory;
+        escRef = tmp;
+    }
+
+    ref = (xmlChar *) xmlURIUnescapeString((char *) escRef, -1, NULL);
+    if (ref == NULL)
+        goto err_memory;
+
+    if ((base == NULL) || (base[0] == 0))
+        goto done;
+
+    if (xmlIsAbsolutePath(ref))
+        goto done;
+
+    /*
+     * Remove last segment from base
+     */
+    i = xmlStrlen(base);
+    while ((i > 0) && !xmlIsPathSeparator(base[i-1], 1))
+        i--;
+
+    /*
+     * Concatenate base and ref
+     */
+    if (i > 0) {
+        int refLen = xmlStrlen(ref);
+
+        result = xmlMalloc(i + refLen + 1);
+        if (result == NULL)
+            goto err_memory;
+
+        memcpy(result, base, i);
+        memcpy(result + i, ref, refLen + 1);
+    }
+
+    /*
+     * Normalize
+     */
+    xmlNormalizePath((char *) result, 1);
+
+done:
+    if (result == NULL) {
+        result = ref;
+        ref = NULL;
+    }
+
+    if (fragment != NULL) {
+        result = xmlStrcat(result, fragment);
+        if (result == NULL)
+            goto err_memory;
+    }
+
+    *out = result;
+    ret = 0;
+
+err_memory:
+    xmlFree(tmp);
+    xmlFree(ref);
+    return(ret);
+}
+
+/**
+ * xmlBuildURISafe:
  * @URI:  the URI instance found in the document
  * @base:  the base value
+ * @valPtr:  pointer to result URI
  *
  * Computes he final URI of the reference done by checking that
  * the given URI is valid, and building the final URI using the
@@ -1885,17 +2003,34 @@ xmlURIEscape(const xmlChar * str)
  *
  * 5.2. Resolving Relative References to Absolute Form
  *
- * Returns a new URI string (to be freed by the caller) or NULL in case
- *         of error.
+ * Available since 2.13.0.
+ *
+ * Returns 0 on success, -1 if a memory allocation failed or an error
+ * code if URI or base are invalid.
  */
-xmlChar *
-xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
+int
+xmlBuildURISafe(const xmlChar *URI, const xmlChar *base, xmlChar **valPtr) {
     xmlChar *val = NULL;
     int ret, len, indx, cur, out;
     xmlURIPtr ref = NULL;
     xmlURIPtr bas = NULL;
     xmlURIPtr res = NULL;
 
+    if (valPtr == NULL)
+        return(1);
+    *valPtr = NULL;
+
+    if (URI == NULL)
+        return(1);
+
+    if (base == NULL) {
+        val = xmlStrdup(URI);
+        if (val == NULL)
+            return(-1);
+        *valPtr = val;
+        return(0);
+    }
+
     /*
      * 1) The URI reference is parsed into the potential four components and
      *    fragment identifier, as described in Section 4.3.
@@ -1904,18 +2039,10 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
      *    as a reference to "." rather than as a synonym for the current
      *    URI.  Should we do that here?
      */
-    if (URI == NULL)
-	ret = -1;
-    else {
-	if (*URI) {
-	    ref = xmlCreateURI();
-	    if (ref == NULL)
-		goto done;
-	    ret = xmlParseURIReference(ref, (const char *) URI);
-	}
-	else
-	    ret = 0;
-    }
+    if (URI[0] != 0)
+        ret = xmlParseURISafe((const char *) URI, &ref);
+    else
+        ret = 0;
     if (ret != 0)
 	goto done;
     if ((ref != NULL) && (ref->scheme != NULL)) {
@@ -1923,19 +2050,30 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
 	 * The URI is absolute don't modify.
 	 */
 	val = xmlStrdup(URI);
+        if (val == NULL)
+            ret = -1;
 	goto done;
     }
-    if (base == NULL)
-	ret = -1;
-    else {
-	bas = xmlCreateURI();
-	if (bas == NULL)
-	    goto done;
-	ret = xmlParseURIReference(bas, (const char *) base);
+
+    /*
+     * If base has no scheme or authority, it is assumed to be a
+     * filesystem path.
+     */
+    if (xmlStrstr(base, BAD_CAST "://") == NULL) {
+        xmlFreeURI(ref);
+        return(xmlResolvePath(URI, base, valPtr));
     }
+
+    ret = xmlParseURISafe((const char *) base, &bas);
+    if (ret < 0)
+        goto done;
     if (ret != 0) {
-	if (ref)
+	if (ref) {
+            ret = 0;
 	    val = xmlSaveUri(ref);
+            if (val == NULL)
+                ret = -1;
+        }
 	goto done;
     }
     if (ref == NULL) {
@@ -1947,6 +2085,8 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
 	    bas->fragment = NULL;
 	}
 	val = xmlSaveUri(bas);
+        if (val == NULL)
+            ret = -1;
 	goto done;
     }
 
@@ -1962,34 +2102,62 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
      *    defined while still treating this as a reference to the current
      *    document.
      */
+    ret = -1;
     res = xmlCreateURI();
     if (res == NULL)
 	goto done;
     if ((ref->scheme == NULL) && (ref->path == NULL) &&
-	((ref->authority == NULL) && (ref->server == NULL))) {
-	if (bas->scheme != NULL)
+	((ref->authority == NULL) && (ref->server == NULL) &&
+         (ref->port == PORT_EMPTY))) {
+	if (bas->scheme != NULL) {
 	    res->scheme = xmlMemStrdup(bas->scheme);
-	if (bas->authority != NULL)
+            if (res->scheme == NULL)
+                goto done;
+        }
+	if (bas->authority != NULL) {
 	    res->authority = xmlMemStrdup(bas->authority);
-	else if ((bas->server != NULL) || (bas->port == -1)) {
-	    if (bas->server != NULL)
+            if (res->authority == NULL)
+                goto done;
+        } else {
+	    if (bas->server != NULL) {
 		res->server = xmlMemStrdup(bas->server);
-	    if (bas->user != NULL)
+                if (res->server == NULL)
+                    goto done;
+            }
+	    if (bas->user != NULL) {
 		res->user = xmlMemStrdup(bas->user);
+                if (res->user == NULL)
+                    goto done;
+            }
 	    res->port = bas->port;
 	}
-	if (bas->path != NULL)
+	if (bas->path != NULL) {
 	    res->path = xmlMemStrdup(bas->path);
-	if (ref->query_raw != NULL)
+            if (res->path == NULL)
+                goto done;
+        }
+	if (ref->query_raw != NULL) {
 	    res->query_raw = xmlMemStrdup (ref->query_raw);
-	else if (ref->query != NULL)
+            if (res->query_raw == NULL)
+                goto done;
+        } else if (ref->query != NULL) {
 	    res->query = xmlMemStrdup(ref->query);
-	else if (bas->query_raw != NULL)
+            if (res->query == NULL)
+                goto done;
+        } else if (bas->query_raw != NULL) {
 	    res->query_raw = xmlMemStrdup(bas->query_raw);
-	else if (bas->query != NULL)
+            if (res->query_raw == NULL)
+                goto done;
+        } else if (bas->query != NULL) {
 	    res->query = xmlMemStrdup(bas->query);
-	if (ref->fragment != NULL)
+            if (res->query == NULL)
+                goto done;
+        }
+	if (ref->fragment != NULL) {
 	    res->fragment = xmlMemStrdup(ref->fragment);
+            if (res->fragment == NULL)
+                goto done;
+        }
 	goto step_7;
     }
 
@@ -2001,17 +2169,30 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
      */
     if (ref->scheme != NULL) {
 	val = xmlSaveUri(ref);
+        if (val != NULL)
+            ret = 0;
 	goto done;
     }
-    if (bas->scheme != NULL)
+    if (bas->scheme != NULL) {
 	res->scheme = xmlMemStrdup(bas->scheme);
+        if (res->scheme == NULL)
+            goto done;
+    }
 
-    if (ref->query_raw != NULL)
+    if (ref->query_raw != NULL) {
 	res->query_raw = xmlMemStrdup(ref->query_raw);
-    else if (ref->query != NULL)
+        if (res->query_raw == NULL)
+            goto done;
+    } else if (ref->query != NULL) {
 	res->query = xmlMemStrdup(ref->query);
-    if (ref->fragment != NULL)
+        if (res->query == NULL)
+            goto done;
+    }
+    if (ref->fragment != NULL) {
 	res->fragment = xmlMemStrdup(ref->fragment);
+        if (res->fragment == NULL)
+            goto done;
+    }
 
     /*
      * 4) If the authority component is defined, then the reference is a
@@ -2020,26 +2201,47 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
      *    component, which will also be undefined if the URI scheme does not
      *    use an authority component.
      */
-    if ((ref->authority != NULL) || (ref->server != NULL)) {
-	if (ref->authority != NULL)
+    if ((ref->authority != NULL) || (ref->server != NULL) ||
+         (ref->port != PORT_EMPTY)) {
+	if (ref->authority != NULL) {
 	    res->authority = xmlMemStrdup(ref->authority);
-	else {
-	    res->server = xmlMemStrdup(ref->server);
-	    if (ref->user != NULL)
+            if (res->authority == NULL)
+                goto done;
+        } else {
+            if (ref->server != NULL) {
+                res->server = xmlMemStrdup(ref->server);
+                if (res->server == NULL)
+                    goto done;
+            }
+	    if (ref->user != NULL) {
 		res->user = xmlMemStrdup(ref->user);
+                if (res->user == NULL)
+                    goto done;
+            }
             res->port = ref->port;
 	}
-	if (ref->path != NULL)
+	if (ref->path != NULL) {
 	    res->path = xmlMemStrdup(ref->path);
+            if (res->path == NULL)
+                goto done;
+        }
 	goto step_7;
     }
-    if (bas->authority != NULL)
+    if (bas->authority != NULL) {
 	res->authority = xmlMemStrdup(bas->authority);
-    else if ((bas->server != NULL) || (bas->port == -1)) {
-	if (bas->server != NULL)
+        if (res->authority == NULL)
+            goto done;
+    } else if ((bas->server != NULL) || (bas->port != PORT_EMPTY)) {
+	if (bas->server != NULL) {
 	    res->server = xmlMemStrdup(bas->server);
-	if (bas->user != NULL)
+            if (res->server == NULL)
+                goto done;
+        }
+	if (bas->user != NULL) {
 	    res->user = xmlMemStrdup(bas->user);
+            if (res->user == NULL)
+                goto done;
+        }
 	res->port = bas->port;
     }
 
@@ -2049,6 +2251,8 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
      */
     if ((ref->path != NULL) && (ref->path[0] == '/')) {
 	res->path = xmlMemStrdup(ref->path);
+        if (res->path == NULL)
+            goto done;
 	goto step_7;
     }
 
@@ -2067,10 +2271,8 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
     if (bas->path != NULL)
 	len += strlen(bas->path);
     res->path = (char *) xmlMallocAtomic(len);
-    if (res->path == NULL) {
-        xmlURIErrMemory("resolving URI against base\n");
+    if (res->path == NULL)
 	goto done;
-    }
     res->path[0] = 0;
 
     /*
@@ -2105,7 +2307,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
 	/*
 	 * Ensure the path includes a '/'
 	 */
-	if ((out == 0) && (bas->server != NULL))
+	if ((out == 0) && ((bas->server != NULL) || bas->port != PORT_EMPTY))
 	    res->path[out++] = '/';
 	while (ref->path[indx] != 0) {
 	    res->path[out++] = ref->path[indx++];
@@ -2126,6 +2328,8 @@ step_7:
      *    reference.
      */
     val = xmlSaveUri(res);
+    if (val != NULL)
+        ret = 0;
 
 done:
     if (ref != NULL)
@@ -2134,13 +2338,161 @@ done:
 	xmlFreeURI(bas);
     if (res != NULL)
 	xmlFreeURI(res);
-    return(val);
+    *valPtr = val;
+    return(ret);
 }
 
 /**
- * xmlBuildRelativeURI:
+ * xmlBuildURI:
+ * @URI:  the URI instance found in the document
+ * @base:  the base value
+ *
+ * Computes he final URI of the reference done by checking that
+ * the given URI is valid, and building the final URI using the
+ * base URI. This is processed according to section 5.2 of the
+ * RFC 2396
+ *
+ * 5.2. Resolving Relative References to Absolute Form
+ *
+ * Returns a new URI string (to be freed by the caller) or NULL in case
+ *         of error.
+ */
+xmlChar *
+xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
+    xmlChar *out;
+
+    xmlBuildURISafe(URI, base, &out);
+    return(out);
+}
+
+static int
+xmlParseUriOrPath(const char *str, xmlURIPtr *out, int *drive) {
+    xmlURIPtr uri;
+    char *buf = NULL;
+    int ret;
+
+    *out = NULL;
+    *drive = 0;
+
+    uri = xmlCreateURI();
+    if (uri == NULL) {
+        ret = -1;
+	goto done;
+    }
+
+    if (xmlStrstr(BAD_CAST str, BAD_CAST "://") == NULL) {
+        const char *path;
+        size_t pathSize;
+        int prependSlash = 0;
+
+        buf = xmlMemStrdup(str);
+        if (buf == NULL) {
+            ret = -1;
+            goto done;
+        }
+        xmlNormalizePath(buf, /* isFile */ 1);
+
+        path = buf;
+
+        if (xmlIsAbsolutePath(BAD_CAST buf)) {
+#if defined(_WIN32) || defined(__CYGWIN__)
+            const char *server = NULL;
+            int isFileScheme = 0;
+#endif
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+            if (strncmp(buf, "//?/UNC/", 8) == 0) {
+                server = buf + 8;
+                isFileScheme = 1;
+            } else if (strncmp(buf, "//?/", 4) == 0) {
+                path = buf + 3;
+                isFileScheme = 1;
+            } else if (strncmp(buf, "//", 2) == 0) {
+                server = buf + 2;
+                isFileScheme = 1;
+            }
+
+            if (server != NULL) {
+                const char *end = strchr(server, '/');
+
+                if (end == NULL) {
+                    uri->server = xmlMemStrdup(server);
+                    path = "/";
+                } else {
+                    uri->server = (char *) xmlStrndup(BAD_CAST server,
+                                                      end - server);
+                    path = end;
+                }
+                if (uri->server == NULL) {
+                    ret = -1;
+                    goto done;
+                }
+            }
+
+            if ((((path[0] >= 'A') && (path[0] <= 'Z')) ||
+                 ((path[0] >= 'a') && (path[0] <= 'z'))) &&
+                (path[1] == ':')) {
+                prependSlash = 1;
+                isFileScheme = 1;
+            }
+
+            if (isFileScheme) {
+                uri->scheme = xmlMemStrdup("file");
+                if (uri->scheme == NULL) {
+                    ret = -1;
+                    goto done;
+                }
+
+                if (uri->server == NULL)
+                    uri->port = PORT_EMPTY_SERVER;
+            }
+#endif
+        }
+
+        pathSize = strlen(path);
+        uri->path = xmlMalloc(pathSize + prependSlash + 1);
+        if (uri->path == NULL) {
+            ret = -1;
+            goto done;
+        }
+        if (prependSlash) {
+            uri->path[0] = '/';
+            memcpy(uri->path + 1, path, pathSize + 1);
+        } else {
+            memcpy(uri->path, path, pathSize + 1);
+        }
+    } else {
+	ret = xmlParseURIReference(uri, str);
+	if (ret != 0)
+	    goto done;
+
+        xmlNormalizePath(uri->path, /* isFile */ 0);
+    }
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+    if ((uri->path[0] == '/') &&
+        (((uri->path[1] >= 'A') && (uri->path[1] <= 'Z')) ||
+         ((uri->path[1] >= 'a') && (uri->path[1] <= 'z'))) &&
+        (uri->path[2] == ':'))
+        *drive = uri->path[1];
+#endif
+
+    *out = uri;
+    uri = NULL;
+    ret = 0;
+
+done:
+    xmlFreeURI(uri);
+    xmlFree(buf);
+
+    return(ret);
+}
+
+/**
+ * xmlBuildRelativeURISafe:
  * @URI:  the URI reference under consideration
  * @base:  the base value
+ * @valPtr:  pointer to result URI
  *
  * Expresses the URI of the reference in terms relative to the
  * base.  Some examples of this operation include:
@@ -2166,105 +2518,112 @@ done:
  *       since this routine (for reasonable efficiency) assumes URI has
  *       already been through some validation.
  *
- * Returns a new URI string (to be freed by the caller) or NULL in case
- * error.
+ * Available since 2.13.0.
+ *
+ * Returns 0 on success, -1 if a memory allocation failed or an error
+ * code if URI or base are invalid.
  */
-xmlChar *
-xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
+int
+xmlBuildRelativeURISafe(const xmlChar * URI, const xmlChar * base,
+                        xmlChar **valPtr)
 {
     xmlChar *val = NULL;
-    int ret;
+    int ret = 0;
     int ix;
     int nbslash = 0;
     int len;
     xmlURIPtr ref = NULL;
     xmlURIPtr bas = NULL;
-    xmlChar *bptr, *uptr, *vptr;
+    const xmlChar *bptr, *uptr, *rptr;
+    xmlChar *vptr;
     int remove_path = 0;
+    int refDrive, baseDrive;
 
+    if (valPtr == NULL)
+        return(1);
+    *valPtr = NULL;
     if ((URI == NULL) || (*URI == 0))
-	return NULL;
+	return(1);
 
-    /*
-     * First parse URI into a standard form
-     */
-    ref = xmlCreateURI ();
-    if (ref == NULL)
-	return NULL;
-    /* If URI not already in "relative" form */
-    if (URI[0] != '.') {
-	ret = xmlParseURIReference (ref, (const char *) URI);
-	if (ret != 0)
-	    goto done;		/* Error in URI, return NULL */
-    } else
-	ref->path = (char *)xmlStrdup(URI);
+    ret = xmlParseUriOrPath((char *) URI, &ref, &refDrive);
+    if (ret < 0)
+        goto done;
+    if (ret != 0) {
+        /* Return URI if URI is invalid */
+        ret = 0;
+        val = xmlStrdup(URI);
+        if (val == NULL)
+            ret = -1;
+        goto done;
+    }
 
-    /*
-     * Next parse base into the same standard form
-     */
-    if ((base == NULL) || (*base == 0)) {
-	val = xmlStrdup (URI);
-	goto done;
+    /* Return URI if base is empty */
+    if ((base == NULL) || (*base == 0))
+        goto done;
+
+    ret = xmlParseUriOrPath((char *) base, &bas, &baseDrive);
+    if (ret < 0)
+        goto done;
+    if (ret != 0) {
+        /* Return URI if base is invalid */
+        ret = 0;
+        goto done;
     }
-    bas = xmlCreateURI ();
-    if (bas == NULL)
-	goto done;
-    if (base[0] != '.') {
-	ret = xmlParseURIReference (bas, (const char *) base);
-	if (ret != 0)
-	    goto done;		/* Error in base, return NULL */
-    } else
-	bas->path = (char *)xmlStrdup(base);
 
     /*
      * If the scheme / server on the URI differs from the base,
      * just return the URI
      */
-    if ((ref->scheme != NULL) &&
-	((bas->scheme == NULL) ||
-	 (xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme)) ||
-	 (xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)))) {
-	val = xmlStrdup (URI);
+    if ((xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme)) ||
+	(xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)) ||
+        (bas->port != ref->port) ||
+        (baseDrive != refDrive)) {
 	goto done;
     }
     if (xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path)) {
 	val = xmlStrdup(BAD_CAST "");
+        if (val == NULL)
+            ret = -1;
 	goto done;
     }
     if (bas->path == NULL) {
 	val = xmlStrdup((xmlChar *)ref->path);
-	goto done;
+        if (val == NULL) {
+            ret = -1;
+            goto done;
+        }
+	goto escape;
     }
     if (ref->path == NULL) {
         ref->path = (char *) "/";
 	remove_path = 1;
     }
 
+    bptr = (xmlChar *) bas->path;
+    rptr = (xmlChar *) ref->path;
+
     /*
-     * At this point (at last!) we can compare the two paths
-     *
-     * First we take care of the special case where either of the
-     * two path components may be missing (bug 316224)
+     * Return URI if URI and base aren't both absolute or relative.
+     */
+    if ((bptr[0] == '/') != (rptr[0] == '/'))
+        goto done;
+
+    /*
+     * At this point we can compare the two paths
      */
-    bptr = (xmlChar *)bas->path;
     {
-        xmlChar *rptr = (xmlChar *) ref->path;
         int pos = 0;
 
         /*
          * Next we compare the two strings and find where they first differ
          */
-	if ((*rptr == '.') && (rptr[1] == '/'))
-            rptr += 2;
-	if ((*bptr == '.') && (bptr[1] == '/'))
-            bptr += 2;
-	else if ((*bptr == '/') && (*rptr != '/'))
-	    bptr++;
 	while ((bptr[pos] == rptr[pos]) && (bptr[pos] != 0))
 	    pos++;
 
 	if (bptr[pos] == rptr[pos]) {
 	    val = xmlStrdup(BAD_CAST "");
+            if (val == NULL)
+                ret = -1;
 	    goto done;		/* (I can't imagine why anyone would do this) */
 	}
 
@@ -2292,6 +2651,8 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
 	 */
 	if (nbslash == 0 && !uptr[0]) {
 	    val = xmlStrdup(BAD_CAST "./");
+            if (val == NULL)
+                ret = -1;
 	    goto done;
 	}
 
@@ -2299,9 +2660,12 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
     }
 
     if (nbslash == 0) {
-	if (uptr != NULL)
+	if (uptr != NULL) {
 	    /* exception characters from xmlSaveUri */
 	    val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,");
+            if (val == NULL)
+                ret = -1;
+        }
 	goto done;
     }
 
@@ -2312,7 +2676,7 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
      */
     val = (xmlChar *) xmlMalloc (len + 3 * nbslash);
     if (val == NULL) {
-        xmlURIErrMemory("building relative URI\n");
+        ret = -1;
 	goto done;
     }
     vptr = val;
@@ -2340,13 +2704,24 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
 	vptr[len - 1] = 0;
     }
 
+escape:
     /* escape the freshly-built path */
     vptr = val;
-	/* exception characters from xmlSaveUri */
+    /* exception characters from xmlSaveUri */
     val = xmlURIEscapeStr(vptr, BAD_CAST "/;&=+$,");
+    if (val == NULL)
+        ret = -1;
+    else
+        ret = 0;
     xmlFree(vptr);
 
 done:
+    if ((ret == 0) && (val == NULL)) {
+        val = xmlSaveUri(ref);
+        if (val == NULL)
+            ret = -1;
+    }
+
     /*
      * Free the working variables
      */
@@ -2356,153 +2731,75 @@ done:
 	xmlFreeURI (ref);
     if (bas != NULL)
 	xmlFreeURI (bas);
+    if (ret != 0) {
+        xmlFree(val);
+        val = NULL;
+    }
+
+    *valPtr = val;
+    return(ret);
+}
+
+/*
+ * xmlBuildRelativeURI:
+ * @URI:  the URI reference under consideration
+ * @base:  the base value
+ *
+ * See xmlBuildRelativeURISafe.
+ *
+ * Returns a new URI string (to be freed by the caller) or NULL in case
+ * error.
+ */
+xmlChar *
+xmlBuildRelativeURI(const xmlChar * URI, const xmlChar * base)
+{
+    xmlChar *val;
 
-    return val;
+    xmlBuildRelativeURISafe(URI, base, &val);
+    return(val);
 }
 
 /**
  * xmlCanonicPath:
  * @path:  the resource locator in a filesystem notation
  *
- * Constructs a canonic path from the specified path.
+ * Prepares a path.
+ *
+ * If the path contains the substring "://", it is considered a
+ * Legacy Extended IRI. Characters which aren't allowed in URIs are
+ * escaped.
  *
- * Returns a new canonic path, or a duplicate of the path parameter if the
- * construction fails. The caller is responsible for freeing the memory occupied
+ * Otherwise, the path is considered a filesystem path which is
+ * copied without modification.
+ *
+ * The caller is responsible for freeing the memory occupied
  * by the returned string. If there is insufficient memory available, or the
  * argument is NULL, the function returns NULL.
+ *
+ * Returns the escaped path.
  */
-#define IS_WINDOWS_PATH(p)					\
-	((p != NULL) &&						\
-	 (((p[0] >= 'a') && (p[0] <= 'z')) ||			\
-	  ((p[0] >= 'A') && (p[0] <= 'Z'))) &&			\
-	 (p[1] == ':') && ((p[2] == '/') || (p[2] == '\\')))
 xmlChar *
 xmlCanonicPath(const xmlChar *path)
 {
-/*
- * For Windows implementations, additional work needs to be done to
- * replace backslashes in pathnames with "forward slashes"
- */
-#if defined(_WIN32)
-    int len = 0;
-    char *p = NULL;
-#endif
-    xmlURIPtr uri;
     xmlChar *ret;
-    const xmlChar *absuri;
 
     if (path == NULL)
 	return(NULL);
 
-#if defined(_WIN32)
-    /*
-     * We must not change the backslashes to slashes if the the path
-     * starts with \\?\
-     * Those paths can be up to 32k characters long.
-     * Was added specifically for OpenOffice, those paths can't be converted
-     * to URIs anyway.
-     */
-    if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
-        (path[3] == '\\') )
-	return xmlStrdup((const xmlChar *) path);
-#endif
-
-	/* sanitize filename starting with // so it can be used as URI */
-    if ((path[0] == '/') && (path[1] == '/') && (path[2] != '/'))
-        path++;
-
-    if ((uri = xmlParseURI((const char *) path)) != NULL) {
-	xmlFreeURI(uri);
-	return xmlStrdup(path);
-    }
-
     /* Check if this is an "absolute uri" */
-    absuri = xmlStrstr(path, BAD_CAST "://");
-    if (absuri != NULL) {
-        int l, j;
-	unsigned char c;
-	xmlChar *escURI;
-
-        /*
-	 * this looks like an URI where some parts have not been
-	 * escaped leading to a parsing problem.  Check that the first
-	 * part matches a protocol.
-	 */
-	l = absuri - path;
-	/* Bypass if first part (part before the '://') is > 20 chars */
-	if ((l <= 0) || (l > 20))
-	    goto path_processing;
-	/* Bypass if any non-alpha characters are present in first part */
-	for (j = 0;j < l;j++) {
-	    c = path[j];
-	    if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))))
-	        goto path_processing;
-	}
-
-	/* Escape all except the characters specified in the supplied path */
-        escURI = xmlURIEscapeStr(path, BAD_CAST ":/?_.#&;=");
-	if (escURI != NULL) {
-	    /* Try parsing the escaped path */
-	    uri = xmlParseURI((const char *) escURI);
-	    /* If successful, return the escaped string */
-	    if (uri != NULL) {
-	        xmlFreeURI(uri);
-		return escURI;
-	    }
-            xmlFree(escURI);
-	}
-    }
-
-path_processing:
-/* For Windows implementations, replace backslashes with 'forward slashes' */
-#if defined(_WIN32)
-    /*
-     * Create a URI structure
-     */
-    uri = xmlCreateURI();
-    if (uri == NULL) {		/* Guard against 'out of memory' */
-        return(NULL);
-    }
-
-    len = xmlStrlen(path);
-    if ((len > 2) && IS_WINDOWS_PATH(path)) {
-        /* make the scheme 'file' */
-	uri->scheme = (char *) xmlStrdup(BAD_CAST "file");
-	/* allocate space for leading '/' + path + string terminator */
-	uri->path = xmlMallocAtomic(len + 2);
-	if (uri->path == NULL) {
-	    xmlFreeURI(uri);	/* Guard against 'out of memory' */
-	    return(NULL);
-	}
-	/* Put in leading '/' plus path */
-	uri->path[0] = '/';
-	p = uri->path + 1;
-	strncpy(p, (char *) path, len + 1);
-    } else {
-	uri->path = (char *) xmlStrdup(path);
-	if (uri->path == NULL) {
-	    xmlFreeURI(uri);
-	    return(NULL);
-	}
-	p = uri->path;
-    }
-    /* Now change all occurrences of '\' to '/' */
-    while (*p != '\0') {
-	if (*p == '\\')
-	    *p = '/';
-	p++;
-    }
-
-    if (uri->scheme == NULL) {
-	ret = xmlStrdup((const xmlChar *) uri->path);
+    if (xmlStrstr(path, BAD_CAST "://") != NULL) {
+	/*
+         * Escape all characters except reserved, unreserved and the
+         * percent sign.
+         *
+         * xmlURIEscapeStr already keeps unreserved characters, so we
+         * pass gen-delims, sub-delims and "%" to ignore.
+         */
+        ret = xmlURIEscapeStr(path, BAD_CAST ":/?#[]@!$&()*+,;='%");
     } else {
-	ret = xmlSaveUri(uri);
+        ret = xmlStrdup((const xmlChar *) path);
     }
 
-    xmlFreeURI(uri);
-#else
-    ret = xmlStrdup((const xmlChar *) path);
-#endif
     return(ret);
 }
 
@@ -2520,41 +2817,5 @@ path_processing:
 xmlChar *
 xmlPathToURI(const xmlChar *path)
 {
-    xmlURIPtr uri;
-    xmlURI temp;
-    xmlChar *ret, *cal;
-
-    if (path == NULL)
-        return(NULL);
-
-    if ((uri = xmlParseURI((const char *) path)) != NULL) {
-	xmlFreeURI(uri);
-	return xmlStrdup(path);
-    }
-    cal = xmlCanonicPath(path);
-    if (cal == NULL)
-        return(NULL);
-#if defined(_WIN32)
-    /* xmlCanonicPath can return an URI on Windows (is that the intended behaviour?)
-       If 'cal' is a valid URI already then we are done here, as continuing would make
-       it invalid. */
-    if ((uri = xmlParseURI((const char *) cal)) != NULL) {
-	xmlFreeURI(uri);
-	return cal;
-    }
-    /* 'cal' can contain a relative path with backslashes. If that is processed
-       by xmlSaveURI, they will be escaped and the external entity loader machinery
-       will fail. So convert them to slashes. Misuse 'ret' for walking. */
-    ret = cal;
-    while (*ret != '\0') {
-	if (*ret == '\\')
-	    *ret = '/';
-	ret++;
-    }
-#endif
-    memset(&temp, 0, sizeof(temp));
-    temp.path = (char *) cal;
-    ret = xmlSaveUri(&temp);
-    xmlFree(cal);
-    return(ret);
+    return(xmlCanonicPath(path));
 }
diff --git a/valid.c b/valid.c
index 1da812ea8c339561365d20dc8498e24a0ed06baa..0e4a9c299471c6348e3dcc9467b12d11e1a5bc69 100644
--- a/valid.c
+++ b/valid.c
@@ -21,17 +21,16 @@
 #include <libxml/parserInternals.h>
 #include <libxml/xmlerror.h>
 #include <libxml/list.h>
-#include <libxml/globals.h>
+#include <libxml/xmlsave.h>
 
-static xmlElementPtr xmlGetDtdElementDesc2(xmlDtdPtr dtd, const xmlChar *name,
-	                           int create);
-/* #define DEBUG_VALID_ALGO */
-/* #define DEBUG_REGEXP_ALGO */
+#include "private/error.h"
+#include "private/parser.h"
+#include "private/regexp.h"
+#include "private/save.h"
+#include "private/tree.h"
 
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
+static xmlElementPtr
+xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name);
 
 #ifdef LIBXML_VALID_ENABLED
 static int
@@ -52,33 +51,56 @@ xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
  * Handle an out of memory error
  */
 static void
-xmlVErrMemory(xmlValidCtxtPtr ctxt, const char *extra)
+xmlVErrMemory(xmlValidCtxtPtr ctxt)
 {
-    xmlGenericErrorFunc channel = NULL;
+    if (ctxt != NULL) {
+        if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
+            xmlCtxtErrMemory(ctxt->userData);
+        } else {
+            xmlRaiseMemoryError(NULL, ctxt->error, ctxt->userData,
+                                XML_FROM_VALID, NULL);
+        }
+    } else {
+        xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_VALID, NULL);
+    }
+}
+
+static void
+xmlDoErrValid(xmlValidCtxtPtr ctxt, xmlNodePtr node,
+              xmlParserErrors code, int level,
+              const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
+              int int1,
+              const char *msg, ...) {
     xmlParserCtxtPtr pctxt = NULL;
-    void *data = NULL;
+    va_list ap;
 
-    if (ctxt != NULL) {
-        channel = ctxt->error;
-        data = ctxt->userData;
-	/* Look up flag to detect if it is part of a parsing
-	   context */
-	if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
-	    long delta = (char *) ctxt - (char *) ctxt->userData;
-	    if ((delta > 0) && (delta < 250))
-		pctxt = ctxt->userData;
-	}
+    if (ctxt == NULL)
+        return;
+    if (ctxt->flags & XML_VCTXT_USE_PCTXT)
+        pctxt = ctxt->userData;
+
+    va_start(ap, msg);
+    if (pctxt != NULL) {
+        xmlCtxtVErr(pctxt, node, XML_FROM_VALID, code, level,
+                    str1, str2, str3, int1, msg, ap);
+    } else {
+        xmlGenericErrorFunc channel = NULL;
+        void *data = NULL;
+        int res;
+
+        if (ctxt != NULL) {
+            channel = ctxt->error;
+            data = ctxt->userData;
+        }
+        res = xmlVRaiseError(NULL, channel, data, NULL, node,
+                             XML_FROM_VALID, code, level, NULL, 0,
+                             (const char *) str1, (const char *) str2,
+                             (const char *) str2, int1, 0,
+                             msg, ap);
+        if (res < 0)
+            xmlVErrMemory(ctxt);
     }
-    if (extra)
-        __xmlRaiseError(NULL, channel, data,
-                        pctxt, NULL, XML_FROM_VALID, XML_ERR_NO_MEMORY,
-                        XML_ERR_FATAL, NULL, 0, extra, NULL, NULL, 0, 0,
-                        "Memory allocation failed : %s\n", extra);
-    else
-        __xmlRaiseError(NULL, channel, data,
-                        pctxt, NULL, XML_FROM_VALID, XML_ERR_NO_MEMORY,
-                        XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0,
-                        "Memory allocation failed\n");
+    va_end(ap);
 }
 
 /**
@@ -93,31 +115,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
 xmlErrValid(xmlValidCtxtPtr ctxt, xmlParserErrors error,
             const char *msg, const char *extra)
 {
-    xmlGenericErrorFunc channel = NULL;
-    xmlParserCtxtPtr pctxt = NULL;
-    void *data = NULL;
-
-    if (ctxt != NULL) {
-        channel = ctxt->error;
-        data = ctxt->userData;
-	/* Look up flag to detect if it is part of a parsing
-	   context */
-	if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
-	    long delta = (char *) ctxt - (char *) ctxt->userData;
-	    if ((delta > 0) && (delta < 250))
-		pctxt = ctxt->userData;
-	}
-    }
-    if (extra)
-        __xmlRaiseError(NULL, channel, data,
-                        pctxt, NULL, XML_FROM_VALID, error,
-                        XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0,
-                        msg, extra);
-    else
-        __xmlRaiseError(NULL, channel, data,
-                        pctxt, NULL, XML_FROM_VALID, error,
-                        XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
-                        "%s", msg);
+    xmlDoErrValid(ctxt, NULL, error, XML_ERR_ERROR, (const xmlChar *) extra,
+                  NULL, NULL, 0, msg, extra);
 }
 
 #if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
@@ -138,27 +137,8 @@ xmlErrValidNode(xmlValidCtxtPtr ctxt,
                 const char *msg, const xmlChar * str1,
                 const xmlChar * str2, const xmlChar * str3)
 {
-    xmlStructuredErrorFunc schannel = NULL;
-    xmlGenericErrorFunc channel = NULL;
-    xmlParserCtxtPtr pctxt = NULL;
-    void *data = NULL;
-
-    if (ctxt != NULL) {
-        channel = ctxt->error;
-        data = ctxt->userData;
-	/* Look up flag to detect if it is part of a parsing
-	   context */
-	if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
-	    long delta = (char *) ctxt - (char *) ctxt->userData;
-	    if ((delta > 0) && (delta < 250))
-		pctxt = ctxt->userData;
-	}
-    }
-    __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
-                    XML_ERR_ERROR, NULL, 0,
-                    (const char *) str1,
-                    (const char *) str2,
-                    (const char *) str3, 0, 0, msg, str1, str2, str3);
+    xmlDoErrValid(ctxt, node, error, XML_ERR_ERROR, str1, str2, str3, 0,
+                  msg, str1, str2, str3);
 }
 #endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
 
@@ -180,27 +160,8 @@ xmlErrValidNodeNr(xmlValidCtxtPtr ctxt,
                 const char *msg, const xmlChar * str1,
                 int int2, const xmlChar * str3)
 {
-    xmlStructuredErrorFunc schannel = NULL;
-    xmlGenericErrorFunc channel = NULL;
-    xmlParserCtxtPtr pctxt = NULL;
-    void *data = NULL;
-
-    if (ctxt != NULL) {
-        channel = ctxt->error;
-        data = ctxt->userData;
-	/* Look up flag to detect if it is part of a parsing
-	   context */
-	if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
-	    long delta = (char *) ctxt - (char *) ctxt->userData;
-	    if ((delta > 0) && (delta < 250))
-		pctxt = ctxt->userData;
-	}
-    }
-    __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
-                    XML_ERR_ERROR, NULL, 0,
-                    (const char *) str1,
-                    (const char *) str3,
-                    NULL, int2, 0, msg, str1, int2, str3);
+    xmlDoErrValid(ctxt, node, error, XML_ERR_ERROR, str1, str3, NULL, int2,
+                  msg, str1, int2, str3);
 }
 
 /**
@@ -220,27 +181,8 @@ xmlErrValidWarning(xmlValidCtxtPtr ctxt,
                 const char *msg, const xmlChar * str1,
                 const xmlChar * str2, const xmlChar * str3)
 {
-    xmlStructuredErrorFunc schannel = NULL;
-    xmlGenericErrorFunc channel = NULL;
-    xmlParserCtxtPtr pctxt = NULL;
-    void *data = NULL;
-
-    if (ctxt != NULL) {
-        channel = ctxt->warning;
-        data = ctxt->userData;
-	/* Look up flag to detect if it is part of a parsing
-	   context */
-	if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
-	    long delta = (char *) ctxt - (char *) ctxt->userData;
-	    if ((delta > 0) && (delta < 250))
-		pctxt = ctxt->userData;
-	}
-    }
-    __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
-                    XML_ERR_WARNING, NULL, 0,
-                    (const char *) str1,
-                    (const char *) str2,
-                    (const char *) str3, 0, 0, msg, str1, str2, str3);
+    xmlDoErrValid(ctxt, node, error, XML_ERR_WARNING, str1, str2, str3, 0,
+                  msg, str1, str2, str3);
 }
 
 
@@ -269,7 +211,7 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
 	ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax *
 		              sizeof(ctxt->vstateTab[0]));
         if (ctxt->vstateTab == NULL) {
-	    xmlVErrMemory(ctxt, "malloc failed");
+	    xmlVErrMemory(ctxt);
 	    return(-1);
 	}
     }
@@ -280,7 +222,7 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
 	tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
 	             2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
         if (tmp == NULL) {
-	    xmlVErrMemory(ctxt, "realloc failed");
+	    xmlVErrMemory(ctxt);
 	    return(-1);
 	}
 	ctxt->vstateMax *= 2;
@@ -295,6 +237,10 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
 	if (elemDecl->contModel != NULL) {
 	    ctxt->vstateTab[ctxt->vstateNr].exec =
 		xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
+            if (ctxt->vstateTab[ctxt->vstateNr].exec == NULL) {
+                xmlVErrMemory(ctxt);
+                return(-1);
+            }
 	} else {
 	    ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
 	    xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
@@ -376,7 +322,7 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont,
 	ctxt->vstateTab = (xmlValidState *) xmlMalloc(
 		     ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
 	if (ctxt->vstateTab == NULL) {
-	    xmlVErrMemory(ctxt, "malloc failed");
+	    xmlVErrMemory(ctxt);
 	    return(-1);
 	}
     }
@@ -386,7 +332,7 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont,
         tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
 	             2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
         if (tmp == NULL) {
-	    xmlVErrMemory(ctxt, "malloc failed");
+	    xmlVErrMemory(ctxt);
 	    return(-1);
 	}
 	ctxt->vstateMax *= 2;
@@ -434,7 +380,7 @@ nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value)
             (xmlNodePtr *) xmlMalloc(ctxt->nodeMax *
                                      sizeof(ctxt->nodeTab[0]));
         if (ctxt->nodeTab == NULL) {
-	    xmlVErrMemory(ctxt, "malloc failed");
+	    xmlVErrMemory(ctxt);
             ctxt->nodeMax = 0;
             return (0);
         }
@@ -444,7 +390,7 @@ nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value)
         tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
 			      ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0]));
         if (tmp == NULL) {
-	    xmlVErrMemory(ctxt, "realloc failed");
+	    xmlVErrMemory(ctxt);
             return (0);
         }
         ctxt->nodeMax *= 2;
@@ -471,151 +417,6 @@ nodeVPop(xmlValidCtxtPtr ctxt)
     return (ret);
 }
 
-#ifdef DEBUG_VALID_ALGO
-static void
-xmlValidPrintNode(xmlNodePtr cur) {
-    if (cur == NULL) {
-	xmlGenericError(xmlGenericErrorContext, "null");
-	return;
-    }
-    switch (cur->type) {
-	case XML_ELEMENT_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "%s ", cur->name);
-	    break;
-	case XML_TEXT_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "text ");
-	    break;
-	case XML_CDATA_SECTION_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "cdata ");
-	    break;
-	case XML_ENTITY_REF_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "&%s; ", cur->name);
-	    break;
-	case XML_PI_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "pi(%s) ", cur->name);
-	    break;
-	case XML_COMMENT_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "comment ");
-	    break;
-	case XML_ATTRIBUTE_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?attr? ");
-	    break;
-	case XML_ENTITY_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?ent? ");
-	    break;
-	case XML_DOCUMENT_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?doc? ");
-	    break;
-	case XML_DOCUMENT_TYPE_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?doctype? ");
-	    break;
-	case XML_DOCUMENT_FRAG_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?frag? ");
-	    break;
-	case XML_NOTATION_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?nota? ");
-	    break;
-	case XML_HTML_DOCUMENT_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?html? ");
-	    break;
-	case XML_DTD_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?dtd? ");
-	    break;
-	case XML_ELEMENT_DECL:
-	    xmlGenericError(xmlGenericErrorContext, "?edecl? ");
-	    break;
-	case XML_ATTRIBUTE_DECL:
-	    xmlGenericError(xmlGenericErrorContext, "?adecl? ");
-	    break;
-	case XML_ENTITY_DECL:
-	    xmlGenericError(xmlGenericErrorContext, "?entdecl? ");
-	    break;
-	case XML_NAMESPACE_DECL:
-	    xmlGenericError(xmlGenericErrorContext, "?nsdecl? ");
-	    break;
-	case XML_XINCLUDE_START:
-	    xmlGenericError(xmlGenericErrorContext, "incstart ");
-	    break;
-	case XML_XINCLUDE_END:
-	    xmlGenericError(xmlGenericErrorContext, "incend ");
-	    break;
-    }
-}
-
-static void
-xmlValidPrintNodeList(xmlNodePtr cur) {
-    if (cur == NULL)
-	xmlGenericError(xmlGenericErrorContext, "null ");
-    while (cur != NULL) {
-	xmlValidPrintNode(cur);
-	cur = cur->next;
-    }
-}
-
-static void
-xmlValidDebug(xmlNodePtr cur, xmlElementContentPtr cont) {
-    char expr[5000];
-
-    expr[0] = 0;
-    xmlGenericError(xmlGenericErrorContext, "valid: ");
-    xmlValidPrintNodeList(cur);
-    xmlGenericError(xmlGenericErrorContext, "against ");
-    xmlSnprintfElementContent(expr, 5000, cont, 1);
-    xmlGenericError(xmlGenericErrorContext, "%s\n", expr);
-}
-
-static void
-xmlValidDebugState(xmlValidStatePtr state) {
-    xmlGenericError(xmlGenericErrorContext, "(");
-    if (state->cont == NULL)
-	xmlGenericError(xmlGenericErrorContext, "null,");
-    else
-	switch (state->cont->type) {
-            case XML_ELEMENT_CONTENT_PCDATA:
-		xmlGenericError(xmlGenericErrorContext, "pcdata,");
-		break;
-            case XML_ELEMENT_CONTENT_ELEMENT:
-		xmlGenericError(xmlGenericErrorContext, "%s,",
-			        state->cont->name);
-		break;
-            case XML_ELEMENT_CONTENT_SEQ:
-		xmlGenericError(xmlGenericErrorContext, "seq,");
-		break;
-            case XML_ELEMENT_CONTENT_OR:
-		xmlGenericError(xmlGenericErrorContext, "or,");
-		break;
-	}
-    xmlValidPrintNode(state->node);
-    xmlGenericError(xmlGenericErrorContext, ",%d,%X,%d)",
-	    state->depth, state->occurs, state->state);
-}
-
-static void
-xmlValidStateDebug(xmlValidCtxtPtr ctxt) {
-    int i, j;
-
-    xmlGenericError(xmlGenericErrorContext, "state: ");
-    xmlValidDebugState(ctxt->vstate);
-    xmlGenericError(xmlGenericErrorContext, " stack: %d ",
-	    ctxt->vstateNr - 1);
-    for (i = 0, j = ctxt->vstateNr - 1;(i < 3) && (j > 0);i++,j--)
-	xmlValidDebugState(&ctxt->vstateTab[j]);
-    xmlGenericError(xmlGenericErrorContext, "\n");
-}
-
-/*****
-#define DEBUG_VALID_STATE(n,c) xmlValidDebug(n,c);
- *****/
-
-#define DEBUG_VALID_STATE(n,c) xmlValidStateDebug(ctxt);
-#define DEBUG_VALID_MSG(m)					\
-    xmlGenericError(xmlGenericErrorContext, "%s\n", m);
-
-#else
-#define DEBUG_VALID_STATE(n,c)
-#define DEBUG_VALID_MSG(m)
-#endif
-
 /* TODO: use hash table for accesses to elem and attribute definitions */
 
 
@@ -666,7 +467,7 @@ xmlValidBuildAContentModel(xmlElementContentPtr content,
 
 	    fullname = xmlBuildQName(content->name, content->prefix, fn, 50);
 	    if (fullname == NULL) {
-	        xmlVErrMemory(ctxt, "Building content model");
+	        xmlVErrMemory(ctxt);
 		return(0);
 	    }
 
@@ -711,11 +512,13 @@ xmlValidBuildAContentModel(xmlElementContentPtr content,
 		oldstate = ctxt->state;
 	    }
 	    do {
-		xmlValidBuildAContentModel(content->c1, ctxt, name);
+		if (xmlValidBuildAContentModel(content->c1, ctxt, name) == 0)
+                    return(0);
 		content = content->c2;
 	    } while ((content->type == XML_ELEMENT_CONTENT_SEQ) &&
 		     (content->ocur == XML_ELEMENT_CONTENT_ONCE));
-	    xmlValidBuildAContentModel(content, ctxt, name);
+	    if (xmlValidBuildAContentModel(content, ctxt, name) == 0)
+                return(0);
 	    oldend = ctxt->state;
 	    ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
 	    switch (ocur) {
@@ -753,13 +556,15 @@ xmlValidBuildAContentModel(xmlElementContentPtr content,
 	     */
 	    do {
 		ctxt->state = oldstate;
-		xmlValidBuildAContentModel(content->c1, ctxt, name);
+		if (xmlValidBuildAContentModel(content->c1, ctxt, name) == 0)
+                    return(0);
 		xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
 		content = content->c2;
 	    } while ((content->type == XML_ELEMENT_CONTENT_OR) &&
 		     (content->ocur == XML_ELEMENT_CONTENT_ONCE));
 	    ctxt->state = oldstate;
-	    xmlValidBuildAContentModel(content, ctxt, name);
+	    if (xmlValidBuildAContentModel(content, ctxt, name) == 0)
+                return(0);
 	    xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
 	    ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
 	    switch (ocur) {
@@ -791,6 +596,8 @@ xmlValidBuildAContentModel(xmlElementContentPtr content,
  * @ctxt:  a validation context
  * @elem:  an element declaration node
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * (Re)Build the automata associated to the content model of this
  * element
  *
@@ -798,6 +605,7 @@ xmlValidBuildAContentModel(xmlElementContentPtr content,
  */
 int
 xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
+    int ret = 0;
 
     if ((ctxt == NULL) || (elem == NULL))
 	return(0);
@@ -816,37 +624,37 @@ xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
 
     ctxt->am = xmlNewAutomata();
     if (ctxt->am == NULL) {
-	xmlErrValidNode(ctxt, (xmlNodePtr) elem,
-	                XML_ERR_INTERNAL_ERROR,
-	                "Cannot create automata for element %s\n",
-		        elem->name, NULL, NULL);
+        xmlVErrMemory(ctxt);
 	return(0);
     }
     ctxt->state = xmlAutomataGetInitState(ctxt->am);
-    xmlValidBuildAContentModel(elem->content, ctxt, elem->name);
+    if (xmlValidBuildAContentModel(elem->content, ctxt, elem->name) == 0)
+        goto done;
     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
     elem->contModel = xmlAutomataCompile(ctxt->am);
+    if (elem->contModel == NULL) {
+        xmlVErrMemory(ctxt);
+        goto done;
+    }
     if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
 	char expr[5000];
 	expr[0] = 0;
 	xmlSnprintfElementContent(expr, 5000, elem->content, 1);
 	xmlErrValidNode(ctxt, (xmlNodePtr) elem,
 	                XML_DTD_CONTENT_NOT_DETERMINIST,
-	       "Content model of %s is not determinist: %s\n",
+	       "Content model of %s is not deterministic: %s\n",
 	       elem->name, BAD_CAST expr, NULL);
-#ifdef DEBUG_REGEXP_ALGO
-        xmlRegexpPrint(stderr, elem->contModel);
-#endif
         ctxt->valid = 0;
-	ctxt->state = NULL;
-	xmlFreeAutomata(ctxt->am);
-	ctxt->am = NULL;
-	return(0);
+	goto done;
     }
+
+    ret = 1;
+
+done:
     ctxt->state = NULL;
     xmlFreeAutomata(ctxt->am);
     ctxt->am = NULL;
-    return(1);
+    return(ret);
 }
 
 #endif /* LIBXML_REGEXP_ENABLED */
@@ -867,10 +675,8 @@ xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
 xmlValidCtxtPtr xmlNewValidCtxt(void) {
     xmlValidCtxtPtr ret;
 
-    if ((ret = xmlMalloc(sizeof (xmlValidCtxt))) == NULL) {
-	xmlVErrMemory(NULL, "malloc failed");
+    if ((ret = xmlMalloc(sizeof (xmlValidCtxt))) == NULL)
 	return (NULL);
-    }
 
     (void) memset(ret, 0, sizeof (xmlValidCtxt));
 
@@ -885,6 +691,8 @@ xmlValidCtxtPtr xmlNewValidCtxt(void) {
  */
 void
 xmlFreeValidCtxt(xmlValidCtxtPtr cur) {
+    if (cur == NULL)
+        return;
     if (cur->vstateTab != NULL)
         xmlFree(cur->vstateTab);
     if (cur->nodeTab != NULL)
@@ -937,10 +745,8 @@ xmlNewDocElementContent(xmlDocPtr doc, const xmlChar *name,
 	    return(NULL);
     }
     ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
-    if (ret == NULL) {
-	xmlVErrMemory(NULL, "malloc failed");
+    if (ret == NULL)
 	return(NULL);
-    }
     memset(ret, 0, sizeof(xmlElementContent));
     ret->type = type;
     ret->ocur = XML_ELEMENT_CONTENT_ONCE;
@@ -962,9 +768,17 @@ xmlNewDocElementContent(xmlDocPtr doc, const xmlChar *name,
 	        ret->prefix = xmlDictLookup(dict, name, l);
 		ret->name = xmlDictLookup(dict, tmp, -1);
 	    }
+            if (ret->prefix == NULL)
+                goto error;
 	}
+        if (ret->name == NULL)
+            goto error;
     }
     return(ret);
+
+error:
+    xmlFreeDocElementContent(doc, ret);
+    return(NULL);
 }
 
 /**
@@ -1002,10 +816,8 @@ xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
         dict = doc->dict;
 
     ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
-    if (ret == NULL) {
-	xmlVErrMemory(NULL, "malloc failed");
+    if (ret == NULL)
 	return(NULL);
-    }
     memset(ret, 0, sizeof(xmlElementContent));
     ret->type = cur->type;
     ret->ocur = cur->ocur;
@@ -1014,6 +826,8 @@ xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
 	    ret->name = xmlDictLookup(dict, cur->name, -1);
 	else
 	    ret->name = xmlStrdup(cur->name);
+        if (ret->name == NULL)
+            goto error;
     }
 
     if (cur->prefix != NULL) {
@@ -1021,20 +835,22 @@ xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
 	    ret->prefix = xmlDictLookup(dict, cur->prefix, -1);
 	else
 	    ret->prefix = xmlStrdup(cur->prefix);
+        if (ret->prefix == NULL)
+            goto error;
     }
-    if (cur->c1 != NULL)
+    if (cur->c1 != NULL) {
         ret->c1 = xmlCopyDocElementContent(doc, cur->c1);
-    if (ret->c1 != NULL)
+        if (ret->c1 == NULL)
+            goto error;
 	ret->c1->parent = ret;
+    }
     if (cur->c2 != NULL) {
         prev = ret;
 	cur = cur->c2;
 	while (cur != NULL) {
 	    tmp = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
-	    if (tmp == NULL) {
-		xmlVErrMemory(NULL, "malloc failed");
-		return(ret);
-	    }
+	    if (tmp == NULL)
+                goto error;
 	    memset(tmp, 0, sizeof(xmlElementContent));
 	    tmp->type = cur->type;
 	    tmp->ocur = cur->ocur;
@@ -1045,6 +861,8 @@ xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
 		    tmp->name = xmlDictLookup(dict, cur->name, -1);
 		else
 		    tmp->name = xmlStrdup(cur->name);
+                if (tmp->name == NULL)
+                    goto error;
 	    }
 
 	    if (cur->prefix != NULL) {
@@ -1052,16 +870,24 @@ xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
 		    tmp->prefix = xmlDictLookup(dict, cur->prefix, -1);
 		else
 		    tmp->prefix = xmlStrdup(cur->prefix);
+                if (tmp->prefix == NULL)
+                    goto error;
 	    }
-	    if (cur->c1 != NULL)
+	    if (cur->c1 != NULL) {
 	        tmp->c1 = xmlCopyDocElementContent(doc,cur->c1);
-	    if (tmp->c1 != NULL)
-		tmp->c1->parent = ret;
+	        if (tmp->c1 == NULL)
+                    goto error;
+		tmp->c1->parent = tmp;
+            }
 	    prev = tmp;
 	    cur = cur->c2;
 	}
     }
     return(ret);
+
+error:
+    xmlFreeElementContent(ret);
+    return(NULL);
 }
 
 /**
@@ -1157,105 +983,6 @@ xmlFreeElementContent(xmlElementContentPtr cur) {
 }
 
 #ifdef LIBXML_OUTPUT_ENABLED
-/**
- * xmlDumpElementOccur:
- * @buf:  An XML buffer
- * @cur:  An element table
- *
- * Dump the occurrence operator of an element.
- */
-static void
-xmlDumpElementOccur(xmlBufferPtr buf, xmlElementContentPtr cur) {
-    switch (cur->ocur) {
-        case XML_ELEMENT_CONTENT_ONCE:
-            break;
-        case XML_ELEMENT_CONTENT_OPT:
-            xmlBufferWriteChar(buf, "?");
-            break;
-        case XML_ELEMENT_CONTENT_MULT:
-            xmlBufferWriteChar(buf, "*");
-            break;
-        case XML_ELEMENT_CONTENT_PLUS:
-            xmlBufferWriteChar(buf, "+");
-            break;
-    }
-}
-
-/**
- * xmlDumpElementContent:
- * @buf:  An XML buffer
- * @content:  An element table
- *
- * This will dump the content of the element table as an XML DTD definition
- */
-static void
-xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content) {
-    xmlElementContentPtr cur;
-
-    if (content == NULL) return;
-
-    xmlBufferWriteChar(buf, "(");
-    cur = content;
-
-    do {
-        if (cur == NULL) return;
-
-        switch (cur->type) {
-            case XML_ELEMENT_CONTENT_PCDATA:
-                xmlBufferWriteChar(buf, "#PCDATA");
-                break;
-            case XML_ELEMENT_CONTENT_ELEMENT:
-                if (cur->prefix != NULL) {
-                    xmlBufferWriteCHAR(buf, cur->prefix);
-                    xmlBufferWriteChar(buf, ":");
-                }
-                xmlBufferWriteCHAR(buf, cur->name);
-                break;
-            case XML_ELEMENT_CONTENT_SEQ:
-            case XML_ELEMENT_CONTENT_OR:
-                if ((cur != content) &&
-                    (cur->parent != NULL) &&
-                    ((cur->type != cur->parent->type) ||
-                     (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
-                    xmlBufferWriteChar(buf, "(");
-                cur = cur->c1;
-                continue;
-            default:
-                xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
-                        "Internal: ELEMENT cur corrupted invalid type\n",
-                        NULL);
-        }
-
-        while (cur != content) {
-            xmlElementContentPtr parent = cur->parent;
-
-            if (parent == NULL) return;
-
-            if (((cur->type == XML_ELEMENT_CONTENT_OR) ||
-                 (cur->type == XML_ELEMENT_CONTENT_SEQ)) &&
-                ((cur->type != parent->type) ||
-                 (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
-                xmlBufferWriteChar(buf, ")");
-            xmlDumpElementOccur(buf, cur);
-
-            if (cur == parent->c1) {
-                if (parent->type == XML_ELEMENT_CONTENT_SEQ)
-                    xmlBufferWriteChar(buf, " , ");
-                else if (parent->type == XML_ELEMENT_CONTENT_OR)
-                    xmlBufferWriteChar(buf, " | ");
-
-                cur = parent->c2;
-                break;
-            }
-
-            cur = parent;
-        }
-    } while (cur != content);
-
-    xmlBufferWriteChar(buf, ")");
-    xmlDumpElementOccur(buf, content);
-}
-
 /**
  * xmlSprintfElementContent:
  * @buf:  an output buffer
@@ -1422,7 +1149,8 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt,
     xmlElementPtr ret;
     xmlElementTablePtr table;
     xmlAttributePtr oldAttributes = NULL;
-    xmlChar *ns, *uqname;
+    const xmlChar *localName;
+    xmlChar *prefix = NULL;
 
     if (dtd == NULL) {
 	return(NULL);
@@ -1434,7 +1162,7 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt,
     switch (type) {
         case XML_ELEMENT_TYPE_EMPTY:
 	    if (content != NULL) {
-		xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
+		xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
 		        "xmlAddElementDecl: content != NULL for EMPTY\n",
 			NULL);
 		return(NULL);
@@ -1442,7 +1170,7 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt,
 	    break;
 	case XML_ELEMENT_TYPE_ANY:
 	    if (content != NULL) {
-		xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
+		xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
 		        "xmlAddElementDecl: content != NULL for ANY\n",
 			NULL);
 		return(NULL);
@@ -1450,7 +1178,7 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt,
 	    break;
 	case XML_ELEMENT_TYPE_MIXED:
 	    if (content == NULL) {
-		xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
+		xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
 		        "xmlAddElementDecl: content == NULL for MIXED\n",
 			NULL);
 		return(NULL);
@@ -1458,25 +1186,24 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt,
 	    break;
 	case XML_ELEMENT_TYPE_ELEMENT:
 	    if (content == NULL) {
-		xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
+		xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
 		        "xmlAddElementDecl: content == NULL for ELEMENT\n",
 			NULL);
 		return(NULL);
 	    }
 	    break;
 	default:
-	    xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
-		    "Internal: ELEMENT decl corrupted invalid type\n",
-		    NULL);
+	    xmlErrValid(ctxt, XML_ERR_ARGUMENT,
+		    "xmlAddElementDecl: invalid type\n", NULL);
 	    return(NULL);
     }
 
     /*
      * check if name is a QName
      */
-    uqname = xmlSplitQName2(name, &ns);
-    if (uqname != NULL)
-	name = uqname;
+    localName = xmlSplitQName4(name, &prefix);
+    if (localName == NULL)
+        goto mem_error;
 
     /*
      * Create the Element table if needed.
@@ -1488,28 +1215,22 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt,
 	if (dtd->doc != NULL)
 	    dict = dtd->doc->dict;
         table = xmlHashCreateDict(0, dict);
+        if (table == NULL)
+            goto mem_error;
 	dtd->elements = (void *) table;
     }
-    if (table == NULL) {
-	xmlVErrMemory(ctxt,
-            "xmlAddElementDecl: Table creation failed!\n");
-	if (uqname != NULL)
-	    xmlFree(uqname);
-	if (ns != NULL)
-	    xmlFree(ns);
-        return(NULL);
-    }
 
     /*
      * lookup old attributes inserted on an undefined element in the
      * internal subset.
      */
     if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) {
-	ret = xmlHashLookup2(dtd->doc->intSubset->elements, name, ns);
+	ret = xmlHashLookup2(dtd->doc->intSubset->elements, localName, prefix);
 	if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) {
 	    oldAttributes = ret->attributes;
 	    ret->attributes = NULL;
-	    xmlHashRemoveEntry2(dtd->doc->intSubset->elements, name, ns, NULL);
+	    xmlHashRemoveEntry2(dtd->doc->intSubset->elements, localName, prefix,
+                                NULL);
 	    xmlFreeElement(ret);
 	}
     }
@@ -1518,7 +1239,7 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt,
      * The element may already be present if one of its attribute
      * was registered first
      */
-    ret = xmlHashLookup2(table, name, ns);
+    ret = xmlHashLookup2(table, localName, prefix);
     if (ret != NULL) {
 	if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) {
 #ifdef LIBXML_VALID_ENABLED
@@ -1529,61 +1250,42 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt,
 	                    "Redefinition of element %s\n",
 			    name, NULL, NULL);
 #endif /* LIBXML_VALID_ENABLED */
-	    if (uqname != NULL)
-		xmlFree(uqname);
-            if (ns != NULL)
-	        xmlFree(ns);
+            if (prefix != NULL)
+	        xmlFree(prefix);
 	    return(NULL);
 	}
-	if (ns != NULL) {
-	    xmlFree(ns);
-	    ns = NULL;
+	if (prefix != NULL) {
+	    xmlFree(prefix);
+	    prefix = NULL;
 	}
     } else {
+        int res;
+
 	ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
-	if (ret == NULL) {
-	    xmlVErrMemory(ctxt, "malloc failed");
-	    if (uqname != NULL)
-		xmlFree(uqname);
-            if (ns != NULL)
-	        xmlFree(ns);
-	    return(NULL);
-	}
+	if (ret == NULL)
+            goto mem_error;
 	memset(ret, 0, sizeof(xmlElement));
 	ret->type = XML_ELEMENT_DECL;
 
 	/*
 	 * fill the structure.
 	 */
-	ret->name = xmlStrdup(name);
+	ret->name = xmlStrdup(localName);
 	if (ret->name == NULL) {
-	    xmlVErrMemory(ctxt, "malloc failed");
-	    if (uqname != NULL)
-		xmlFree(uqname);
-            if (ns != NULL)
-	        xmlFree(ns);
 	    xmlFree(ret);
-	    return(NULL);
+	    goto mem_error;
 	}
-	ret->prefix = ns;
+	ret->prefix = prefix;
+        prefix = NULL;
 
 	/*
 	 * Validity Check:
 	 * Insertion must not fail
 	 */
-	if (xmlHashAddEntry2(table, name, ns, ret)) {
-#ifdef LIBXML_VALID_ENABLED
-	    /*
-	     * The element is already defined in this DTD.
-	     */
-	    xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
-	                    "Redefinition of element %s\n",
-			    name, NULL, NULL);
-#endif /* LIBXML_VALID_ENABLED */
+        res = xmlHashAdd2(table, localName, ret->prefix, ret);
+        if (res <= 0) {
 	    xmlFreeElement(ret);
-	    if (uqname != NULL)
-		xmlFree(uqname);
-	    return(NULL);
+            goto mem_error;
 	}
 	/*
 	 * For new element, may have attributes from earlier
@@ -1601,12 +1303,15 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt,
      * and flag it by setting a special parent value
      * so the parser doesn't unallocate it.
      */
-    if ((ctxt != NULL) && (ctxt->flags & XML_VCTXT_USE_PCTXT)) {
-	ret->content = content;
-	if (content != NULL)
-	    content->parent = (xmlElementContentPtr) 1;
-    } else {
-	ret->content = xmlCopyDocElementContent(dtd->doc, content);
+    if (content != NULL) {
+        if ((ctxt != NULL) && (ctxt->flags & XML_VCTXT_USE_PCTXT)) {
+            ret->content = content;
+            content->parent = (xmlElementContentPtr) 1;
+        } else if (content != NULL){
+            ret->content = xmlCopyDocElementContent(dtd->doc, content);
+            if (ret->content == NULL)
+                goto mem_error;
+        }
     }
 
     /*
@@ -1621,9 +1326,15 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt,
 	ret->prev = dtd->last;
 	dtd->last = (xmlNodePtr) ret;
     }
-    if (uqname != NULL)
-	xmlFree(uqname);
+    if (prefix != NULL)
+	xmlFree(prefix);
     return(ret);
+
+mem_error:
+    xmlVErrMemory(ctxt);
+    if (prefix != NULL)
+        xmlFree(prefix);
+    return(NULL);
 }
 
 static void
@@ -1657,25 +1368,33 @@ xmlCopyElement(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
     xmlElementPtr cur;
 
     cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
-    if (cur == NULL) {
-	xmlVErrMemory(NULL, "malloc failed");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlElement));
     cur->type = XML_ELEMENT_DECL;
     cur->etype = elem->etype;
-    if (elem->name != NULL)
+    if (elem->name != NULL) {
 	cur->name = xmlStrdup(elem->name);
-    else
-	cur->name = NULL;
-    if (elem->prefix != NULL)
+        if (cur->name == NULL)
+            goto error;
+    }
+    if (elem->prefix != NULL) {
 	cur->prefix = xmlStrdup(elem->prefix);
-    else
-	cur->prefix = NULL;
-    cur->content = xmlCopyElementContent(elem->content);
+        if (cur->prefix == NULL)
+            goto error;
+    }
+    if (elem->content != NULL) {
+        cur->content = xmlCopyElementContent(elem->content);
+        if (cur->content == NULL)
+            goto error;
+    }
     /* TODO : rebuild the attribute list on the copy */
     cur->attributes = NULL;
     return(cur);
+
+error:
+    xmlFreeElement(cur);
+    return(NULL);
 }
 
 /**
@@ -1688,7 +1407,7 @@ xmlCopyElement(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
  */
 xmlElementTablePtr
 xmlCopyElementTable(xmlElementTablePtr table) {
-    return((xmlElementTablePtr) xmlHashCopy(table, xmlCopyElement));
+    return(xmlHashCopySafe(table, xmlCopyElement, xmlFreeElementTableEntry));
 }
 #endif /* LIBXML_TREE_ENABLED */
 
@@ -1698,59 +1417,22 @@ xmlCopyElementTable(xmlElementTablePtr table) {
  * @buf:  the XML buffer output
  * @elem:  An element table
  *
+ * DEPRECATED: Use xmlSaveTree.
+ *
  * This will dump the content of the element declaration as an XML
  * DTD definition
  */
 void
 xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
+    xmlSaveCtxtPtr save;
+
     if ((buf == NULL) || (elem == NULL))
         return;
-    switch (elem->etype) {
-	case XML_ELEMENT_TYPE_EMPTY:
-	    xmlBufferWriteChar(buf, "<!ELEMENT ");
-	    if (elem->prefix != NULL) {
-		xmlBufferWriteCHAR(buf, elem->prefix);
-		xmlBufferWriteChar(buf, ":");
-	    }
-	    xmlBufferWriteCHAR(buf, elem->name);
-	    xmlBufferWriteChar(buf, " EMPTY>\n");
-	    break;
-	case XML_ELEMENT_TYPE_ANY:
-	    xmlBufferWriteChar(buf, "<!ELEMENT ");
-	    if (elem->prefix != NULL) {
-		xmlBufferWriteCHAR(buf, elem->prefix);
-		xmlBufferWriteChar(buf, ":");
-	    }
-	    xmlBufferWriteCHAR(buf, elem->name);
-	    xmlBufferWriteChar(buf, " ANY>\n");
-	    break;
-	case XML_ELEMENT_TYPE_MIXED:
-	    xmlBufferWriteChar(buf, "<!ELEMENT ");
-	    if (elem->prefix != NULL) {
-		xmlBufferWriteCHAR(buf, elem->prefix);
-		xmlBufferWriteChar(buf, ":");
-	    }
-	    xmlBufferWriteCHAR(buf, elem->name);
-	    xmlBufferWriteChar(buf, " ");
-	    xmlDumpElementContent(buf, elem->content);
-	    xmlBufferWriteChar(buf, ">\n");
-	    break;
-	case XML_ELEMENT_TYPE_ELEMENT:
-	    xmlBufferWriteChar(buf, "<!ELEMENT ");
-	    if (elem->prefix != NULL) {
-		xmlBufferWriteCHAR(buf, elem->prefix);
-		xmlBufferWriteChar(buf, ":");
-	    }
-	    xmlBufferWriteCHAR(buf, elem->name);
-	    xmlBufferWriteChar(buf, " ");
-	    xmlDumpElementContent(buf, elem->content);
-	    xmlBufferWriteChar(buf, ">\n");
-	    break;
-	default:
-	    xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
-		    "Internal: ELEMENT struct corrupted invalid type\n",
-		    NULL);
-    }
+
+    save = xmlSaveToBuffer(buf, NULL, 0);
+    xmlSaveTree(save, (xmlNodePtr) elem);
+    if (xmlSaveFinish(save) != XML_ERR_OK)
+        xmlFree(xmlBufferDetach(buf));
 }
 
 /**
@@ -1762,9 +1444,9 @@ xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
  * the arguments.
  */
 static void
-xmlDumpElementDeclScan(void *elem, void *buf,
+xmlDumpElementDeclScan(void *elem, void *save,
                        const xmlChar *name ATTRIBUTE_UNUSED) {
-    xmlDumpElementDecl((xmlBufferPtr) buf, (xmlElementPtr) elem);
+    xmlSaveTree(save, elem);
 }
 
 /**
@@ -1772,13 +1454,21 @@ xmlDumpElementDeclScan(void *elem, void *buf,
  * @buf:  the XML buffer output
  * @table:  An element table
  *
+ * DEPRECATED: Don't use.
+ *
  * This will dump the content of the element table as an XML DTD definition
  */
 void
 xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
+    xmlSaveCtxtPtr save;
+
     if ((buf == NULL) || (table == NULL))
         return;
-    xmlHashScan(table, xmlDumpElementDeclScan, buf);
+
+    save = xmlSaveToBuffer(buf, NULL, 0);
+    xmlHashScan(table, xmlDumpElementDeclScan, save);
+    if (xmlSaveFinish(save) != XML_ERR_OK)
+        xmlFree(xmlBufferDetach(buf));
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
 
@@ -1796,14 +1486,18 @@ xmlCreateEnumeration(const xmlChar *name) {
     xmlEnumerationPtr ret;
 
     ret = (xmlEnumerationPtr) xmlMalloc(sizeof(xmlEnumeration));
-    if (ret == NULL) {
-	xmlVErrMemory(NULL, "malloc failed");
+    if (ret == NULL)
         return(NULL);
-    }
     memset(ret, 0, sizeof(xmlEnumeration));
 
-    if (name != NULL)
+    if (name != NULL) {
         ret->name = xmlStrdup(name);
+        if (ret->name == NULL) {
+            xmlFree(ret);
+            return(NULL);
+        }
+    }
+
     return(ret);
 }
 
@@ -1815,12 +1509,14 @@ xmlCreateEnumeration(const xmlChar *name) {
  */
 void
 xmlFreeEnumeration(xmlEnumerationPtr cur) {
-    if (cur == NULL) return;
+    while (cur != NULL) {
+        xmlEnumerationPtr next = cur->next;
 
-    if (cur->next != NULL) xmlFreeEnumeration(cur->next);
+        xmlFree((xmlChar *) cur->name);
+        xmlFree(cur);
 
-    if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
-    xmlFree(cur);
+        cur = next;
+    }
 }
 
 #ifdef LIBXML_TREE_ENABLED
@@ -1835,41 +1531,30 @@ xmlFreeEnumeration(xmlEnumerationPtr cur) {
  */
 xmlEnumerationPtr
 xmlCopyEnumeration(xmlEnumerationPtr cur) {
-    xmlEnumerationPtr ret;
-
-    if (cur == NULL) return(NULL);
-    ret = xmlCreateEnumeration((xmlChar *) cur->name);
-    if (ret == NULL) return(NULL);
+    xmlEnumerationPtr ret = NULL;
+    xmlEnumerationPtr last = NULL;
 
-    if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next);
-    else ret->next = NULL;
+    while (cur != NULL) {
+        xmlEnumerationPtr copy = xmlCreateEnumeration(cur->name);
 
-    return(ret);
-}
-#endif /* LIBXML_TREE_ENABLED */
+        if (copy == NULL) {
+            xmlFreeEnumeration(ret);
+            return(NULL);
+        }
 
-#ifdef LIBXML_OUTPUT_ENABLED
-/**
- * xmlDumpEnumeration:
- * @buf:  the XML buffer output
- * @enum:  An enumeration
- *
- * This will dump the content of the enumeration
- */
-static void
-xmlDumpEnumeration(xmlBufferPtr buf, xmlEnumerationPtr cur) {
-    if ((buf == NULL) || (cur == NULL))
-        return;
+        if (ret == NULL) {
+            ret = last = copy;
+        } else {
+            last->next = copy;
+            last = copy;
+        }
 
-    xmlBufferWriteCHAR(buf, cur->name);
-    if (cur->next == NULL)
-	xmlBufferWriteChar(buf, ")");
-    else {
-	xmlBufferWriteChar(buf, " | ");
-	xmlDumpEnumeration(buf, cur->next);
+        cur = cur->next;
     }
+
+    return(ret);
 }
-#endif /* LIBXML_OUTPUT_ENABLED */
+#endif /* LIBXML_TREE_ENABLED */
 
 #ifdef LIBXML_VALID_ENABLED
 /**
@@ -1969,10 +1654,11 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,
                     const xmlChar *name, const xmlChar *ns,
 		    xmlAttributeType type, xmlAttributeDefault def,
 		    const xmlChar *defaultValue, xmlEnumerationPtr tree) {
-    xmlAttributePtr ret;
+    xmlAttributePtr ret = NULL;
     xmlAttributeTablePtr table;
     xmlElementPtr elemDef;
     xmlDictPtr dict = NULL;
+    int res;
 
     if (dtd == NULL) {
 	xmlFreeEnumeration(tree);
@@ -2015,9 +1701,8 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,
         case XML_ATTRIBUTE_NOTATION:
 	    break;
 	default:
-	    xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
-		    "Internal: ATTRIBUTE struct corrupted invalid type\n",
-		    NULL);
+	    xmlErrValid(ctxt, XML_ERR_ARGUMENT,
+		    "xmlAddAttributeDecl: invalid type\n", NULL);
 	    xmlFreeEnumeration(tree);
 	    return(NULL);
     }
@@ -2054,20 +1739,12 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,
         table = xmlHashCreateDict(0, dict);
 	dtd->attributes = (void *) table;
     }
-    if (table == NULL) {
-	xmlVErrMemory(ctxt,
-            "xmlAddAttributeDecl: Table creation failed!\n");
-	xmlFreeEnumeration(tree);
-        return(NULL);
-    }
-
+    if (table == NULL)
+        goto mem_error;
 
     ret = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
-    if (ret == NULL) {
-	xmlVErrMemory(ctxt, "malloc failed");
-	xmlFreeEnumeration(tree);
-	return(NULL);
-    }
+    if (ret == NULL)
+        goto mem_error;
     memset(ret, 0, sizeof(xmlAttribute));
     ret->type = XML_ATTRIBUTE_DECL;
 
@@ -2083,34 +1760,53 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,
     ret->doc = dtd->doc;
     if (dict) {
 	ret->name = xmlDictLookup(dict, name, -1);
-	ret->prefix = xmlDictLookup(dict, ns, -1);
 	ret->elem = xmlDictLookup(dict, elem, -1);
     } else {
 	ret->name = xmlStrdup(name);
-	ret->prefix = xmlStrdup(ns);
 	ret->elem = xmlStrdup(elem);
     }
+    if ((ret->name == NULL) || (ret->elem == NULL))
+        goto mem_error;
+    if (ns != NULL) {
+        if (dict)
+            ret->prefix = xmlDictLookup(dict, ns, -1);
+        else
+            ret->prefix = xmlStrdup(ns);
+        if (ret->prefix == NULL)
+            goto mem_error;
+    }
     ret->def = def;
     ret->tree = tree;
+    tree = NULL;
     if (defaultValue != NULL) {
         if (dict)
 	    ret->defaultValue = xmlDictLookup(dict, defaultValue, -1);
 	else
 	    ret->defaultValue = xmlStrdup(defaultValue);
+        if (ret->defaultValue == NULL)
+            goto mem_error;
     }
 
+    elemDef = xmlGetDtdElementDesc2(ctxt, dtd, elem);
+    if (elemDef == NULL)
+        goto mem_error;
+
     /*
      * Validity Check:
      * Search the DTD for previous declarations of the ATTLIST
      */
-    if (xmlHashAddEntry3(table, ret->name, ret->prefix, ret->elem, ret) < 0) {
+    res = xmlHashAdd3(table, ret->name, ret->prefix, ret->elem, ret);
+    if (res <= 0) {
+        if (res < 0)
+            goto mem_error;
 #ifdef LIBXML_VALID_ENABLED
-	/*
-	 * The attribute is already defined in this DTD.
-	 */
-	xmlErrValidWarning(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_REDEFINED,
-		 "Attribute %s of element %s: already defined\n",
-		 name, elem, NULL);
+        /*
+         * The attribute is already defined in this DTD.
+         */
+        xmlErrValidWarning(ctxt, (xmlNodePtr) dtd,
+                XML_DTD_ATTRIBUTE_REDEFINED,
+                "Attribute %s of element %s: already defined\n",
+                name, elem, NULL);
 #endif /* LIBXML_VALID_ENABLED */
 	xmlFreeAttribute(ret);
 	return(NULL);
@@ -2120,48 +1816,44 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,
      * Validity Check:
      * Multiple ID per element
      */
-    elemDef = xmlGetDtdElementDesc2(dtd, elem, 1);
-    if (elemDef != NULL) {
-
 #ifdef LIBXML_VALID_ENABLED
-        if ((type == XML_ATTRIBUTE_ID) &&
-	    (xmlScanIDAttributeDecl(NULL, elemDef, 1) != 0)) {
-	    xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_MULTIPLE_ID,
-	   "Element %s has too may ID attributes defined : %s\n",
-		   elem, name, NULL);
-	    if (ctxt != NULL)
-		ctxt->valid = 0;
-	}
+    if ((type == XML_ATTRIBUTE_ID) &&
+        (xmlScanIDAttributeDecl(ctxt, elemDef, 1) != 0)) {
+        xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_MULTIPLE_ID,
+       "Element %s has too may ID attributes defined : %s\n",
+               elem, name, NULL);
+        if (ctxt != NULL)
+            ctxt->valid = 0;
+    }
 #endif /* LIBXML_VALID_ENABLED */
 
-	/*
-	 * Insert namespace default def first they need to be
-	 * processed first.
-	 */
-	if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) ||
-	    ((ret->prefix != NULL &&
-	     (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) {
-	    ret->nexth = elemDef->attributes;
-	    elemDef->attributes = ret;
-	} else {
-	    xmlAttributePtr tmp = elemDef->attributes;
+    /*
+     * Insert namespace default def first they need to be
+     * processed first.
+     */
+    if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) ||
+        ((ret->prefix != NULL &&
+         (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) {
+        ret->nexth = elemDef->attributes;
+        elemDef->attributes = ret;
+    } else {
+        xmlAttributePtr tmp = elemDef->attributes;
 
-	    while ((tmp != NULL) &&
-		   ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) ||
-		    ((ret->prefix != NULL &&
-		     (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) {
-		if (tmp->nexth == NULL)
-		    break;
-		tmp = tmp->nexth;
-	    }
-	    if (tmp != NULL) {
-		ret->nexth = tmp->nexth;
-	        tmp->nexth = ret;
-	    } else {
-		ret->nexth = elemDef->attributes;
-		elemDef->attributes = ret;
-	    }
-	}
+        while ((tmp != NULL) &&
+               ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) ||
+                ((ret->prefix != NULL &&
+                 (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) {
+            if (tmp->nexth == NULL)
+                break;
+            tmp = tmp->nexth;
+        }
+        if (tmp != NULL) {
+            ret->nexth = tmp->nexth;
+            tmp->nexth = ret;
+        } else {
+            ret->nexth = elemDef->attributes;
+            elemDef->attributes = ret;
+        }
     }
 
     /*
@@ -2176,6 +1868,12 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,
 	dtd->last = (xmlNodePtr) ret;
     }
     return(ret);
+
+mem_error:
+    xmlVErrMemory(ctxt);
+    xmlFreeEnumeration(tree);
+    xmlFreeAttribute(ret);
+    return(NULL);
 }
 
 static void
@@ -2209,24 +1907,42 @@ xmlCopyAttribute(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
     xmlAttributePtr cur;
 
     cur = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
-    if (cur == NULL) {
-	xmlVErrMemory(NULL, "malloc failed");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlAttribute));
     cur->type = XML_ATTRIBUTE_DECL;
     cur->atype = attr->atype;
     cur->def = attr->def;
-    cur->tree = xmlCopyEnumeration(attr->tree);
-    if (attr->elem != NULL)
+    if (attr->tree != NULL) {
+        cur->tree = xmlCopyEnumeration(attr->tree);
+        if (cur->tree == NULL)
+            goto error;
+    }
+    if (attr->elem != NULL) {
 	cur->elem = xmlStrdup(attr->elem);
-    if (attr->name != NULL)
+        if (cur->elem == NULL)
+            goto error;
+    }
+    if (attr->name != NULL) {
 	cur->name = xmlStrdup(attr->name);
-    if (attr->prefix != NULL)
+        if (cur->name == NULL)
+            goto error;
+    }
+    if (attr->prefix != NULL) {
 	cur->prefix = xmlStrdup(attr->prefix);
-    if (attr->defaultValue != NULL)
+        if (cur->prefix == NULL)
+            goto error;
+    }
+    if (attr->defaultValue != NULL) {
 	cur->defaultValue = xmlStrdup(attr->defaultValue);
+        if (cur->defaultValue == NULL)
+            goto error;
+    }
     return(cur);
+
+error:
+    xmlFreeAttribute(cur);
+    return(NULL);
 }
 
 /**
@@ -2239,7 +1955,8 @@ xmlCopyAttribute(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
  */
 xmlAttributeTablePtr
 xmlCopyAttributeTable(xmlAttributeTablePtr table) {
-    return((xmlAttributeTablePtr) xmlHashCopy(table, xmlCopyAttribute));
+    return(xmlHashCopySafe(table, xmlCopyAttribute,
+                           xmlFreeAttributeTableEntry));
 }
 #endif /* LIBXML_TREE_ENABLED */
 
@@ -2249,81 +1966,22 @@ xmlCopyAttributeTable(xmlAttributeTablePtr table) {
  * @buf:  the XML buffer output
  * @attr:  An attribute declaration
  *
+ * DEPRECATED: Use xmlSaveTree.
+ *
  * This will dump the content of the attribute declaration as an XML
  * DTD definition
  */
 void
 xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
+    xmlSaveCtxtPtr save;
+
     if ((buf == NULL) || (attr == NULL))
         return;
-    xmlBufferWriteChar(buf, "<!ATTLIST ");
-    xmlBufferWriteCHAR(buf, attr->elem);
-    xmlBufferWriteChar(buf, " ");
-    if (attr->prefix != NULL) {
-	xmlBufferWriteCHAR(buf, attr->prefix);
-	xmlBufferWriteChar(buf, ":");
-    }
-    xmlBufferWriteCHAR(buf, attr->name);
-    switch (attr->atype) {
-	case XML_ATTRIBUTE_CDATA:
-	    xmlBufferWriteChar(buf, " CDATA");
-	    break;
-	case XML_ATTRIBUTE_ID:
-	    xmlBufferWriteChar(buf, " ID");
-	    break;
-	case XML_ATTRIBUTE_IDREF:
-	    xmlBufferWriteChar(buf, " IDREF");
-	    break;
-	case XML_ATTRIBUTE_IDREFS:
-	    xmlBufferWriteChar(buf, " IDREFS");
-	    break;
-	case XML_ATTRIBUTE_ENTITY:
-	    xmlBufferWriteChar(buf, " ENTITY");
-	    break;
-	case XML_ATTRIBUTE_ENTITIES:
-	    xmlBufferWriteChar(buf, " ENTITIES");
-	    break;
-	case XML_ATTRIBUTE_NMTOKEN:
-	    xmlBufferWriteChar(buf, " NMTOKEN");
-	    break;
-	case XML_ATTRIBUTE_NMTOKENS:
-	    xmlBufferWriteChar(buf, " NMTOKENS");
-	    break;
-	case XML_ATTRIBUTE_ENUMERATION:
-	    xmlBufferWriteChar(buf, " (");
-	    xmlDumpEnumeration(buf, attr->tree);
-	    break;
-	case XML_ATTRIBUTE_NOTATION:
-	    xmlBufferWriteChar(buf, " NOTATION (");
-	    xmlDumpEnumeration(buf, attr->tree);
-	    break;
-	default:
-	    xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
-		    "Internal: ATTRIBUTE struct corrupted invalid type\n",
-		    NULL);
-    }
-    switch (attr->def) {
-	case XML_ATTRIBUTE_NONE:
-	    break;
-	case XML_ATTRIBUTE_REQUIRED:
-	    xmlBufferWriteChar(buf, " #REQUIRED");
-	    break;
-	case XML_ATTRIBUTE_IMPLIED:
-	    xmlBufferWriteChar(buf, " #IMPLIED");
-	    break;
-	case XML_ATTRIBUTE_FIXED:
-	    xmlBufferWriteChar(buf, " #FIXED");
-	    break;
-	default:
-	    xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
-		    "Internal: ATTRIBUTE struct corrupted invalid def\n",
-		    NULL);
-    }
-    if (attr->defaultValue != NULL) {
-	xmlBufferWriteChar(buf, " ");
-	xmlBufferWriteQuotedString(buf, attr->defaultValue);
-    }
-    xmlBufferWriteChar(buf, ">\n");
+
+    save = xmlSaveToBuffer(buf, NULL, 0);
+    xmlSaveTree(save, (xmlNodePtr) attr);
+    if (xmlSaveFinish(save) != XML_ERR_OK)
+        xmlFree(xmlBufferDetach(buf));
 }
 
 /**
@@ -2334,9 +1992,9 @@ xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
  * This is used with the hash scan function - just reverses arguments
  */
 static void
-xmlDumpAttributeDeclScan(void *attr, void *buf,
+xmlDumpAttributeDeclScan(void *attr, void *save,
                          const xmlChar *name ATTRIBUTE_UNUSED) {
-    xmlDumpAttributeDecl((xmlBufferPtr) buf, (xmlAttributePtr) attr);
+    xmlSaveTree(save, attr);
 }
 
 /**
@@ -2344,13 +2002,21 @@ xmlDumpAttributeDeclScan(void *attr, void *buf,
  * @buf:  the XML buffer output
  * @table:  An attribute table
  *
+ * DEPRECATED: Don't use.
+ *
  * This will dump the content of the attribute table as an XML DTD definition
  */
 void
 xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
+    xmlSaveCtxtPtr save;
+
     if ((buf == NULL) || (table == NULL))
         return;
-    xmlHashScan(table, xmlDumpAttributeDeclScan, buf);
+
+    save = xmlSaveToBuffer(buf, NULL, 0);
+    xmlHashScan(table, xmlDumpAttributeDeclScan, save);
+    if (xmlSaveFinish(save) != XML_ERR_OK)
+        xmlFree(xmlBufferDetach(buf));
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
 
@@ -2394,8 +2060,9 @@ xmlNotationPtr
 xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd,
 	           const xmlChar *name,
                    const xmlChar *PublicID, const xmlChar *SystemID) {
-    xmlNotationPtr ret;
+    xmlNotationPtr ret = NULL;
     xmlNotationTablePtr table;
+    int res;
 
     if (dtd == NULL) {
 	return(NULL);
@@ -2417,43 +2084,54 @@ xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd,
 	    dict = dtd->doc->dict;
 
         dtd->notations = table = xmlHashCreateDict(0, dict);
-    }
-    if (table == NULL) {
-	xmlVErrMemory(ctxt,
-		"xmlAddNotationDecl: Table creation failed!\n");
-        return(NULL);
+        if (table == NULL)
+            goto mem_error;
     }
 
     ret = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
-    if (ret == NULL) {
-	xmlVErrMemory(ctxt, "malloc failed");
-	return(NULL);
-    }
+    if (ret == NULL)
+        goto mem_error;
     memset(ret, 0, sizeof(xmlNotation));
 
     /*
      * fill the structure.
      */
     ret->name = xmlStrdup(name);
-    if (SystemID != NULL)
+    if (ret->name == NULL)
+        goto mem_error;
+    if (SystemID != NULL) {
         ret->SystemID = xmlStrdup(SystemID);
-    if (PublicID != NULL)
+        if (ret->SystemID == NULL)
+            goto mem_error;
+    }
+    if (PublicID != NULL) {
         ret->PublicID = xmlStrdup(PublicID);
+        if (ret->PublicID == NULL)
+            goto mem_error;
+    }
 
     /*
      * Validity Check:
      * Check the DTD for previous declarations of the ATTLIST
      */
-    if (xmlHashAddEntry(table, name, ret)) {
+    res = xmlHashAdd(table, name, ret);
+    if (res <= 0) {
+        if (res < 0)
+            goto mem_error;
 #ifdef LIBXML_VALID_ENABLED
-	xmlErrValid(NULL, XML_DTD_NOTATION_REDEFINED,
-		    "xmlAddNotationDecl: %s already defined\n",
-		    (const char *) name);
+        xmlErrValid(ctxt, XML_DTD_NOTATION_REDEFINED,
+                    "xmlAddNotationDecl: %s already defined\n",
+                    (const char *) name);
 #endif /* LIBXML_VALID_ENABLED */
 	xmlFreeNotation(ret);
 	return(NULL);
     }
     return(ret);
+
+mem_error:
+    xmlVErrMemory(ctxt);
+    xmlFreeNotation(ret);
+    return(NULL);
 }
 
 static void
@@ -2487,23 +2165,29 @@ xmlCopyNotation(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
     xmlNotationPtr cur;
 
     cur = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
-    if (cur == NULL) {
-	xmlVErrMemory(NULL, "malloc failed");
+    if (cur == NULL)
 	return(NULL);
-    }
-    if (nota->name != NULL)
+    memset(cur, 0, sizeof(*cur));
+    if (nota->name != NULL) {
 	cur->name = xmlStrdup(nota->name);
-    else
-	cur->name = NULL;
-    if (nota->PublicID != NULL)
+        if (cur->name == NULL)
+            goto error;
+    }
+    if (nota->PublicID != NULL) {
 	cur->PublicID = xmlStrdup(nota->PublicID);
-    else
-	cur->PublicID = NULL;
-    if (nota->SystemID != NULL)
+        if (cur->PublicID == NULL)
+            goto error;
+    }
+    if (nota->SystemID != NULL) {
 	cur->SystemID = xmlStrdup(nota->SystemID);
-    else
-	cur->SystemID = NULL;
+        if (cur->SystemID == NULL)
+            goto error;
+    }
     return(cur);
+
+error:
+    xmlFreeNotation(cur);
+    return(NULL);
 }
 
 /**
@@ -2516,7 +2200,7 @@ xmlCopyNotation(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
  */
 xmlNotationTablePtr
 xmlCopyNotationTable(xmlNotationTablePtr table) {
-    return((xmlNotationTablePtr) xmlHashCopy(table, xmlCopyNotation));
+    return(xmlHashCopySafe(table, xmlCopyNotation, xmlFreeNotationTableEntry));
 }
 #endif /* LIBXML_TREE_ENABLED */
 
@@ -2526,39 +2210,21 @@ xmlCopyNotationTable(xmlNotationTablePtr table) {
  * @buf:  the XML buffer output
  * @nota:  A notation declaration
  *
+ * DEPRECATED: Don't use.
+ *
  * This will dump the content the notation declaration as an XML DTD definition
  */
 void
 xmlDumpNotationDecl(xmlBufferPtr buf, xmlNotationPtr nota) {
+    xmlSaveCtxtPtr save;
+
     if ((buf == NULL) || (nota == NULL))
         return;
-    xmlBufferWriteChar(buf, "<!NOTATION ");
-    xmlBufferWriteCHAR(buf, nota->name);
-    if (nota->PublicID != NULL) {
-	xmlBufferWriteChar(buf, " PUBLIC ");
-	xmlBufferWriteQuotedString(buf, nota->PublicID);
-	if (nota->SystemID != NULL) {
-	    xmlBufferWriteChar(buf, " ");
-	    xmlBufferWriteQuotedString(buf, nota->SystemID);
-	}
-    } else {
-	xmlBufferWriteChar(buf, " SYSTEM ");
-	xmlBufferWriteQuotedString(buf, nota->SystemID);
-    }
-    xmlBufferWriteChar(buf, " >\n");
-}
 
-/**
- * xmlDumpNotationDeclScan:
- * @nota:  A notation declaration
- * @buf:  the XML buffer output
- *
- * This is called with the hash scan function, and just reverses args
- */
-static void
-xmlDumpNotationDeclScan(void *nota, void *buf,
-                        const xmlChar *name ATTRIBUTE_UNUSED) {
-    xmlDumpNotationDecl((xmlBufferPtr) buf, (xmlNotationPtr) nota);
+    save = xmlSaveToBuffer(buf, NULL, 0);
+    xmlSaveNotationDecl(save, nota);
+    if (xmlSaveFinish(save) != XML_ERR_OK)
+        xmlFree(xmlBufferDetach(buf));
 }
 
 /**
@@ -2566,13 +2232,21 @@ xmlDumpNotationDeclScan(void *nota, void *buf,
  * @buf:  the XML buffer output
  * @table:  A notation table
  *
+ * DEPRECATED: Don't use.
+ *
  * This will dump the content of the notation table as an XML DTD definition
  */
 void
 xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
+    xmlSaveCtxtPtr save;
+
     if ((buf == NULL) || (table == NULL))
         return;
-    xmlHashScan(table, xmlDumpNotationDeclScan, buf);
+
+    save = xmlSaveToBuffer(buf, NULL, 0);
+    xmlSaveNotationTable(save, table);
+    if (xmlSaveFinish(save) != XML_ERR_OK)
+        xmlFree(xmlBufferDetach(buf));
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
 
@@ -2593,35 +2267,6 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
 	    (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))	\
 	    xmlFree((char *)(str));
 
-/**
- * xmlValidNormalizeString:
- * @str: a string
- *
- * Normalize a string in-place.
- */
-static void
-xmlValidNormalizeString(xmlChar *str) {
-    xmlChar *dst;
-    const xmlChar *src;
-
-    if (str == NULL)
-        return;
-    src = str;
-    dst = str;
-
-    while (*src == 0x20) src++;
-    while (*src != 0) {
-	if (*src == 0x20) {
-	    while (*src == 0x20) src++;
-	    if (*src != 0)
-		*dst++ = 0x20;
-	} else {
-	    *dst++ = *src++;
-	}
-    }
-    *dst = 0;
-}
-
 static int
 xmlIsStreaming(xmlValidCtxtPtr ctxt) {
     xmlParserCtxtPtr pctxt;
@@ -2653,36 +2298,43 @@ xmlFreeID(xmlIDPtr id) {
 	DICT_FREE(id->value)
     if (id->name != NULL)
 	DICT_FREE(id->name)
+    if (id->attr != NULL) {
+        id->attr->id = NULL;
+        id->attr->atype = 0;
+    }
+
     xmlFree(id);
 }
 
 
 /**
- * xmlAddID:
- * @ctxt:  the validation context
- * @doc:  pointer to the document
- * @value:  the value name
+ * xmlAddIDInternal:
  * @attr:  the attribute holding the ID
+ * @value:  the attribute (ID) value
+ * @idPtr:  pointer to resulting ID
  *
  * Register a new id declaration
  *
- * Returns NULL if not, otherwise the new xmlIDPtr
+ * Returns 1 on success, 0 if the ID already exists, -1 if a memory
+ * allocation fails.
  */
-xmlIDPtr
-xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
-         xmlAttrPtr attr) {
-    xmlIDPtr ret;
+static int
+xmlAddIDInternal(xmlAttrPtr attr, const xmlChar *value, xmlIDPtr *idPtr) {
+    xmlDocPtr doc;
+    xmlIDPtr id;
     xmlIDTablePtr table;
+    int ret;
 
-    if (doc == NULL) {
-	return(NULL);
-    }
-    if ((value == NULL) || (value[0] == 0)) {
-	return(NULL);
-    }
-    if (attr == NULL) {
-	return(NULL);
-    }
+    if (idPtr != NULL)
+        *idPtr = NULL;
+    if ((value == NULL) || (value[0] == 0))
+	return(0);
+    if (attr == NULL)
+	return(0);
+
+    doc = attr->doc;
+    if (doc == NULL)
+        return(0);
 
     /*
      * Create the ID table if needed.
@@ -2690,57 +2342,105 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
     table = (xmlIDTablePtr) doc->ids;
     if (table == NULL)  {
         doc->ids = table = xmlHashCreateDict(0, doc->dict);
-    }
-    if (table == NULL) {
-	xmlVErrMemory(ctxt,
-		"xmlAddID: Table creation failed!\n");
-        return(NULL);
+        if (table == NULL)
+            return(-1);
+    } else {
+        id = xmlHashLookup(table, value);
+        if (id != NULL)
+            return(0);
     }
 
-    ret = (xmlIDPtr) xmlMalloc(sizeof(xmlID));
-    if (ret == NULL) {
-	xmlVErrMemory(ctxt, "malloc failed");
-	return(NULL);
-    }
+    id = (xmlIDPtr) xmlMalloc(sizeof(xmlID));
+    if (id == NULL)
+	return(-1);
+    memset(id, 0, sizeof(*id));
 
     /*
      * fill the structure.
      */
-    ret->value = xmlStrdup(value);
-    ret->doc = doc;
-    if (xmlIsStreaming(ctxt)) {
-	/*
-	 * Operating in streaming mode, attr is gonna disappear
-	 */
-	if (doc->dict != NULL)
-	    ret->name = xmlDictLookup(doc->dict, attr->name, -1);
-	else
-	    ret->name = xmlStrdup(attr->name);
-	ret->attr = NULL;
-    } else {
-	ret->attr = attr;
-	ret->name = NULL;
+    id->doc = doc;
+    id->value = xmlStrdup(value);
+    if (id->value == NULL) {
+        xmlFreeID(id);
+        return(-1);
     }
-    ret->lineno = xmlGetLineNo(attr->parent);
 
-    if (xmlHashAddEntry(table, value, ret) < 0) {
-#ifdef LIBXML_VALID_ENABLED
-	/*
-	 * The id is already defined in this DTD.
-	 */
-	if (ctxt != NULL) {
-	    xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED,
-			    "ID %s already defined\n", value, NULL, NULL);
-	}
-#endif /* LIBXML_VALID_ENABLED */
-	xmlFreeID(ret);
-	return(NULL);
+    if (attr->id != NULL)
+        xmlRemoveID(doc, attr);
+
+    if (xmlHashAddEntry(table, value, id) < 0) {
+	xmlFreeID(id);
+	return(-1);
     }
-    if (attr != NULL)
-	attr->atype = XML_ATTRIBUTE_ID;
+
+    ret = 1;
+    if (idPtr != NULL)
+        *idPtr = id;
+
+    id->attr = attr;
+    id->lineno = xmlGetLineNo(attr->parent);
+    attr->atype = XML_ATTRIBUTE_ID;
+    attr->id = id;
+
     return(ret);
 }
 
+/**
+ * xmlAddIDSafe:
+ * @attr:  the attribute holding the ID
+ * @value:  the attribute (ID) value
+ *
+ * Register a new id declaration
+ *
+ * Available since 2.13.0.
+ *
+ * Returns 1 on success, 0 if the ID already exists, -1 if a memory
+ * allocation fails.
+ */
+int
+xmlAddIDSafe(xmlAttrPtr attr, const xmlChar *value) {
+    return(xmlAddIDInternal(attr, value, NULL));
+}
+
+/**
+ * xmlAddID:
+ * @ctxt:  the validation context
+ * @doc:  pointer to the document
+ * @value:  the value name
+ * @attr:  the attribute holding the ID
+ *
+ * Register a new id declaration
+ *
+ * Returns NULL if not, otherwise the new xmlIDPtr
+ */
+xmlIDPtr
+xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
+         xmlAttrPtr attr) {
+    xmlIDPtr id;
+    int res;
+
+    if ((attr == NULL) || (doc != attr->doc))
+        return(NULL);
+
+    res = xmlAddIDInternal(attr, value, &id);
+    if (res < 0) {
+        xmlVErrMemory(ctxt);
+    }
+#ifdef LIBXML_VALID_ENABLED
+    else if (res == 0) {
+        if (ctxt != NULL) {
+            /*
+             * The id is already defined in this DTD.
+             */
+            xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED,
+                            "ID %s already defined\n", value, NULL, NULL);
+        }
+    }
+#endif /* LIBXML_VALID_ENABLED */
+
+    return(id);
+}
+
 static void
 xmlFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
     xmlFreeID((xmlIDPtr) id);
@@ -2768,57 +2468,67 @@ xmlFreeIDTable(xmlIDTablePtr table) {
  * of HTML documents parsed with the HTML parser, then ID detection is
  * done systematically.
  *
- * Returns 0 or 1 depending on the lookup result
+ * Returns 0 or 1 depending on the lookup result or -1 if a memory allocation
+ * failed.
  */
 int
 xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
-    if ((attr == NULL) || (attr->name == NULL)) return(0);
-    if ((attr->ns != NULL) && (attr->ns->prefix != NULL) &&
-        (!strcmp((char *) attr->name, "id")) &&
-        (!strcmp((char *) attr->ns->prefix, "xml")))
-	return(1);
-    if (doc == NULL) return(0);
-    if ((doc->intSubset == NULL) && (doc->extSubset == NULL) &&
-        (doc->type != XML_HTML_DOCUMENT_NODE)) {
-	return(0);
-    } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
-        if ((xmlStrEqual(BAD_CAST "id", attr->name)) ||
-	    ((xmlStrEqual(BAD_CAST "name", attr->name)) &&
-	    ((elem == NULL) || (xmlStrEqual(elem->name, BAD_CAST "a")))))
+    if ((attr == NULL) || (attr->name == NULL))
+        return(0);
+
+    if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
+        if (xmlStrEqual(BAD_CAST "id", attr->name))
+            return(1);
+
+        if ((elem == NULL) || (elem->type != XML_ELEMENT_NODE))
+            return(0);
+
+        if ((xmlStrEqual(BAD_CAST "name", attr->name)) &&
+	    (xmlStrEqual(elem->name, BAD_CAST "a")))
 	    return(1);
-	return(0);
-    } else if (elem == NULL) {
-	return(0);
     } else {
 	xmlAttributePtr attrDecl = NULL;
+	xmlChar felem[50];
+	xmlChar *fullelemname;
+        const xmlChar *aprefix;
+
+        if ((attr->ns != NULL) && (attr->ns->prefix != NULL) &&
+            (!strcmp((char *) attr->name, "id")) &&
+            (!strcmp((char *) attr->ns->prefix, "xml")))
+            return(1);
+
+        if ((doc == NULL) ||
+            ((doc->intSubset == NULL) && (doc->extSubset == NULL)))
+            return(0);
 
-	xmlChar felem[50], fattr[50];
-	xmlChar *fullelemname, *fullattrname;
+        if ((elem == NULL) ||
+            (elem->type != XML_ELEMENT_NODE) ||
+            (elem->name == NULL))
+            return(0);
 
 	fullelemname = (elem->ns != NULL && elem->ns->prefix != NULL) ?
 	    xmlBuildQName(elem->name, elem->ns->prefix, felem, 50) :
 	    (xmlChar *)elem->name;
+        if (fullelemname == NULL)
+            return(-1);
 
-	fullattrname = (attr->ns != NULL && attr->ns->prefix != NULL) ?
-	    xmlBuildQName(attr->name, attr->ns->prefix, fattr, 50) :
-	    (xmlChar *)attr->name;
+        aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL;
 
-	if (fullelemname != NULL && fullattrname != NULL) {
-	    attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullelemname,
-		                         fullattrname);
+	if (fullelemname != NULL) {
+	    attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullelemname,
+		                          attr->name, aprefix);
 	    if ((attrDecl == NULL) && (doc->extSubset != NULL))
-		attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullelemname,
-					     fullattrname);
+		attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullelemname,
+					      attr->name, aprefix);
 	}
 
-	if ((fullattrname != fattr) && (fullattrname != attr->name))
-	    xmlFree(fullattrname);
 	if ((fullelemname != felem) && (fullelemname != elem->name))
 	    xmlFree(fullelemname);
 
         if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID))
 	    return(1);
     }
+
     return(0);
 }
 
@@ -2834,30 +2544,17 @@ xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
 int
 xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
     xmlIDTablePtr table;
-    xmlIDPtr id;
-    xmlChar *ID;
 
     if (doc == NULL) return(-1);
-    if (attr == NULL) return(-1);
+    if ((attr == NULL) || (attr->id == NULL)) return(-1);
 
     table = (xmlIDTablePtr) doc->ids;
     if (table == NULL)
         return(-1);
 
-    ID = xmlNodeListGetString(doc, attr->children, 1);
-    if (ID == NULL)
+    if (xmlHashRemoveEntry(table, attr->id->value, xmlFreeIDTableEntry) < 0)
         return(-1);
-    xmlValidNormalizeString(ID);
 
-    id = xmlHashLookup(table, ID);
-    if (id == NULL || id->attr != attr) {
-        xmlFree(ID);
-        return(-1);
-    }
-
-    xmlHashRemoveEntry(table, ID, xmlFreeIDTableEntry);
-    xmlFree(ID);
-    attr->atype = 0;
     return(0);
 }
 
@@ -3002,7 +2699,7 @@ xmlDummyCompare(const void *data0 ATTRIBUTE_UNUSED,
 xmlRefPtr
 xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
     xmlAttrPtr attr) {
-    xmlRefPtr ret;
+    xmlRefPtr ret = NULL;
     xmlRefTablePtr table;
     xmlListPtr ref_list;
 
@@ -3022,28 +2719,28 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
     table = (xmlRefTablePtr) doc->refs;
     if (table == NULL) {
         doc->refs = table = xmlHashCreateDict(0, doc->dict);
-    }
-    if (table == NULL) {
-	xmlVErrMemory(ctxt,
-            "xmlAddRef: Table creation failed!\n");
-        return(NULL);
+        if (table == NULL)
+            goto failed;
     }
 
     ret = (xmlRefPtr) xmlMalloc(sizeof(xmlRef));
-    if (ret == NULL) {
-	xmlVErrMemory(ctxt, "malloc failed");
-        return(NULL);
-    }
+    if (ret == NULL)
+        goto failed;
+    memset(ret, 0, sizeof(*ret));
 
     /*
      * fill the structure.
      */
     ret->value = xmlStrdup(value);
+    if (ret->value == NULL)
+        goto failed;
     if (xmlIsStreaming(ctxt)) {
 	/*
 	 * Operating in streaming mode, attr is gonna disappear
 	 */
 	ret->name = xmlStrdup(attr->name);
+        if (ret->name == NULL)
+            goto failed;
 	ret->attr = NULL;
     } else {
 	ret->name = NULL;
@@ -3059,28 +2756,22 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
      */
 
     if (NULL == (ref_list = xmlHashLookup(table, value))) {
-        if (NULL == (ref_list = xmlListCreate(xmlFreeRef, xmlDummyCompare))) {
-	    xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
-		    "xmlAddRef: Reference list creation failed!\n",
-		    NULL);
+        int res;
+
+        if (NULL == (ref_list = xmlListCreate(xmlFreeRef, xmlDummyCompare)))
 	    goto failed;
-        }
-        if (xmlHashAddEntry(table, value, ref_list) < 0) {
+        res = xmlHashAdd(table, value, ref_list);
+        if (res <= 0) {
             xmlListDelete(ref_list);
-	    xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
-		    "xmlAddRef: Reference list insertion failed!\n",
-		    NULL);
 	    goto failed;
         }
     }
-    if (xmlListAppend(ref_list, ret) != 0) {
-	xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
-		    "xmlAddRef: Reference list insertion failed!\n",
-		    NULL);
+    if (xmlListAppend(ref_list, ret) != 0)
         goto failed;
-    }
     return(ret);
+
 failed:
+    xmlVErrMemory(ctxt);
     if (ret != NULL) {
         if (ret->value != NULL)
 	    xmlFree((char *)ret->value);
@@ -3134,12 +2825,15 @@ xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
         return(0);
     } else {
         xmlAttributePtr attrDecl;
+        const xmlChar *aprefix;
 
         if (elem == NULL) return(0);
-        attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name);
+        aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL;
+        attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name, attr->name,
+                                      aprefix);
         if ((attrDecl == NULL) && (doc->extSubset != NULL))
-            attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
-		                         elem->name, attr->name);
+            attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name, attr->name,
+                                          aprefix);
 
 	if ((attrDecl != NULL) &&
 	    (attrDecl->atype == XML_ATTRIBUTE_IDREF ||
@@ -3202,7 +2896,7 @@ xmlRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
 
     /*If the list is empty then remove the list entry in the hash */
     if (xmlListEmpty(ref_list))
-        xmlHashUpdateEntry(table, ID, NULL, xmlFreeRefTableEntry);
+        xmlHashRemoveEntry(table, ID, xmlFreeRefTableEntry);
     xmlFree(ID);
     return(0);
 }
@@ -3250,6 +2944,8 @@ xmlGetRefs(xmlDocPtr doc, const xmlChar *ID) {
  *
  * Search the DTD for the description of this element
  *
+ * NOTE: A NULL return value can also mean that a memory allocation failed.
+ *
  * returns the xmlElementPtr if found or NULL
  */
 
@@ -3257,21 +2953,26 @@ xmlElementPtr
 xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) {
     xmlElementTablePtr table;
     xmlElementPtr cur;
-    xmlChar *uqname = NULL, *prefix = NULL;
+    const xmlChar *localname;
+    xmlChar *prefix;
+
+    if ((dtd == NULL) || (dtd->elements == NULL) ||
+        (name == NULL))
+        return(NULL);
 
-    if ((dtd == NULL) || (name == NULL)) return(NULL);
-    if (dtd->elements == NULL)
-	return(NULL);
     table = (xmlElementTablePtr) dtd->elements;
+    if (table == NULL)
+	return(NULL);
 
-    uqname = xmlSplitQName2(name, &prefix);
-    if (uqname != NULL)
-        name = uqname;
-    cur = xmlHashLookup2(table, name, prefix);
-    if (prefix != NULL) xmlFree(prefix);
-    if (uqname != NULL) xmlFree(uqname);
+    localname = xmlSplitQName4(name, &prefix);
+    if (localname == NULL)
+        return(NULL);
+    cur = xmlHashLookup2(table, localname, prefix);
+    if (prefix != NULL)
+        xmlFree(prefix);
     return(cur);
 }
+
 /**
  * xmlGetDtdElementDesc2:
  * @dtd:  a pointer to the DtD to search
@@ -3284,60 +2985,64 @@ xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) {
  */
 
 static xmlElementPtr
-xmlGetDtdElementDesc2(xmlDtdPtr dtd, const xmlChar *name, int create) {
+xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name) {
     xmlElementTablePtr table;
-    xmlElementPtr cur;
-    xmlChar *uqname = NULL, *prefix = NULL;
+    xmlElementPtr cur = NULL;
+    const xmlChar *localName;
+    xmlChar *prefix = NULL;
 
     if (dtd == NULL) return(NULL);
+
+    /*
+     * Create the Element table if needed.
+     */
     if (dtd->elements == NULL) {
 	xmlDictPtr dict = NULL;
 
 	if (dtd->doc != NULL)
 	    dict = dtd->doc->dict;
 
-	if (!create)
-	    return(NULL);
-	/*
-	 * Create the Element table if needed.
-	 */
-	table = (xmlElementTablePtr) dtd->elements;
-	if (table == NULL) {
-	    table = xmlHashCreateDict(0, dict);
-	    dtd->elements = (void *) table;
-	}
-	if (table == NULL) {
-	    xmlVErrMemory(NULL, "element table allocation failed");
-	    return(NULL);
-	}
+	dtd->elements = xmlHashCreateDict(0, dict);
+	if (dtd->elements == NULL)
+            goto mem_error;
     }
     table = (xmlElementTablePtr) dtd->elements;
 
-    uqname = xmlSplitQName2(name, &prefix);
-    if (uqname != NULL)
-        name = uqname;
-    cur = xmlHashLookup2(table, name, prefix);
-    if ((cur == NULL) && (create)) {
+    localName = xmlSplitQName4(name, &prefix);
+    if (localName == NULL)
+        goto mem_error;
+    cur = xmlHashLookup2(table, localName, prefix);
+    if (cur == NULL) {
 	cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
-	if (cur == NULL) {
-	    xmlVErrMemory(NULL, "malloc failed");
-	    return(NULL);
-	}
+	if (cur == NULL)
+            goto mem_error;
 	memset(cur, 0, sizeof(xmlElement));
 	cur->type = XML_ELEMENT_DECL;
+        cur->doc = dtd->doc;
 
 	/*
 	 * fill the structure.
 	 */
-	cur->name = xmlStrdup(name);
-	cur->prefix = xmlStrdup(prefix);
+	cur->name = xmlStrdup(localName);
+        if (cur->name == NULL)
+            goto mem_error;
+	cur->prefix = prefix;
+        prefix = NULL;
 	cur->etype = XML_ELEMENT_TYPE_UNDEFINED;
 
-	xmlHashAddEntry2(table, name, prefix, cur);
+	if (xmlHashAdd2(table, localName, cur->prefix, cur) <= 0)
+            goto mem_error;
     }
-    if (prefix != NULL) xmlFree(prefix);
-    if (uqname != NULL) xmlFree(uqname);
+
+    if (prefix != NULL)
+        xmlFree(prefix);
     return(cur);
+
+mem_error:
+    xmlVErrMemory(ctxt);
+    xmlFree(prefix);
+    xmlFreeElement(cur);
+    return(NULL);
 }
 
 /**
@@ -3379,23 +3084,23 @@ xmlAttributePtr
 xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name) {
     xmlAttributeTablePtr table;
     xmlAttributePtr cur;
-    xmlChar *uqname = NULL, *prefix = NULL;
+    const xmlChar *localname;
+    xmlChar *prefix = NULL;
 
-    if (dtd == NULL) return(NULL);
-    if (dtd->attributes == NULL) return(NULL);
+    if ((dtd == NULL) || (dtd->attributes == NULL) ||
+        (elem == NULL) || (name == NULL))
+        return(NULL);
 
     table = (xmlAttributeTablePtr) dtd->attributes;
     if (table == NULL)
 	return(NULL);
 
-    uqname = xmlSplitQName2(name, &prefix);
-
-    if (uqname != NULL) {
-	cur = xmlHashLookup3(table, uqname, prefix, elem);
-	if (prefix != NULL) xmlFree(prefix);
-	if (uqname != NULL) xmlFree(uqname);
-    } else
-	cur = xmlHashLookup3(table, name, NULL, elem);
+    localname = xmlSplitQName4(name, &prefix);
+    if (localname == NULL)
+        return(NULL);
+    cur = xmlHashLookup3(table, localname, prefix, elem);
+    if (prefix != NULL)
+        xmlFree(prefix);
     return(cur);
 }
 
@@ -3452,6 +3157,8 @@ xmlGetDtdNotationDesc(xmlDtdPtr dtd, const xmlChar *name) {
  * @doc:  the document
  * @notationName:  the notation name to check
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Validate that the given name match a notation declaration.
  * - [ VC: Notation Declared ]
  *
@@ -3519,6 +3226,35 @@ xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name) {
 
 #ifdef LIBXML_VALID_ENABLED
 
+/**
+ * xmlValidNormalizeString:
+ * @str: a string
+ *
+ * Normalize a string in-place.
+ */
+static void
+xmlValidNormalizeString(xmlChar *str) {
+    xmlChar *dst;
+    const xmlChar *src;
+
+    if (str == NULL)
+        return;
+    src = str;
+    dst = str;
+
+    while (*src == 0x20) src++;
+    while (*src != 0) {
+	if (*src == 0x20) {
+	    while (*src == 0x20) src++;
+	    if (*src != 0)
+		*dst++ = 0x20;
+	} else {
+	    *dst++ = *src++;
+	}
+    }
+    *dst = 0;
+}
+
 static int
 xmlIsDocNameStartChar(xmlDocPtr doc, int c) {
     if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
@@ -3838,6 +3574,8 @@ xmlValidateNmtokensValue(const xmlChar *value) {
  * @doc:  a document instance
  * @nota:  a notation definition
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Try to validate a single notation definition
  * basically it does the following checks as described by the
  * XML-1.0 recommendation:
@@ -3894,6 +3632,8 @@ xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
  * @type:  an attribute type
  * @value:  an attribute value
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Validate that the given attribute value match  the proper production
  *
  * [ VC: ID ]
@@ -3989,8 +3729,10 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
 	    xmlEntityPtr ent;
 
 	    dup = xmlStrdup(value);
-	    if (dup == NULL)
+	    if (dup == NULL) {
+                xmlVErrMemory(ctxt);
 		return(0);
+            }
 	    cur = dup;
 	    while (*cur != 0) {
 		nam = cur;
@@ -4048,6 +3790,8 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  * @value:  the attribute value
  * @ctxt:  the validation context or NULL
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Does the validation related extra step of the normalization of attribute
  * values:
  *
@@ -4068,6 +3812,8 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
 	     xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
     xmlChar *ret;
     xmlAttributePtr attrDecl = NULL;
+    const xmlChar *localName;
+    xmlChar *prefix = NULL;
     int extsubset = 0;
 
     if (doc == NULL) return(NULL);
@@ -4075,38 +3821,47 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
     if (name == NULL) return(NULL);
     if (value == NULL) return(NULL);
 
-    if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
-	xmlChar fn[50];
-	xmlChar *fullname;
+    localName = xmlSplitQName4(name, &prefix);
+    if (localName == NULL)
+        goto mem_error;
 
-	fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
-	if (fullname == NULL)
-	    return(NULL);
-	attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, name);
+    if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
+	xmlChar buf[50];
+	xmlChar *elemname;
+
+	elemname = xmlBuildQName(elem->name, elem->ns->prefix, buf, 50);
+	if (elemname == NULL)
+	    goto mem_error;
+        if (doc->intSubset != NULL)
+            attrDecl = xmlHashLookup3(doc->intSubset->attributes, localName,
+                                      prefix, elemname);
 	if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
-	    attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, name);
+	    attrDecl = xmlHashLookup3(doc->extSubset->attributes, localName,
+                                      prefix, elemname);
 	    if (attrDecl != NULL)
 		extsubset = 1;
 	}
-	if ((fullname != fn) && (fullname != elem->name))
-	    xmlFree(fullname);
+	if ((elemname != buf) && (elemname != elem->name))
+	    xmlFree(elemname);
     }
     if ((attrDecl == NULL) && (doc->intSubset != NULL))
-	attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
+	attrDecl = xmlHashLookup3(doc->intSubset->attributes, localName,
+                                  prefix, elem->name);
     if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
-	attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
+	attrDecl = xmlHashLookup3(doc->extSubset->attributes, localName,
+                                  prefix, elem->name);
 	if (attrDecl != NULL)
 	    extsubset = 1;
     }
 
     if (attrDecl == NULL)
-	return(NULL);
+	goto done;
     if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
-	return(NULL);
+	goto done;
 
     ret = xmlStrdup(value);
     if (ret == NULL)
-	return(NULL);
+	goto mem_error;
     xmlValidNormalizeString(ret);
     if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
 	xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
@@ -4114,7 +3869,16 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
 	       name, elem->name, NULL);
 	ctxt->valid = 0;
     }
+
+    xmlFree(prefix);
     return(ret);
+
+mem_error:
+    xmlVErrMemory(ctxt);
+
+done:
+    xmlFree(prefix);
+    return(NULL);
 }
 
 /**
@@ -4124,6 +3888,8 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  * @name:  the attribute name
  * @value:  the attribute value
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Does the validation related extra step of the normalization of attribute
  * values:
  *
@@ -4187,6 +3953,8 @@ xmlValidateAttributeIdCallback(void *payload, void *data,
  * @doc:  a document instance
  * @attr:  an attribute definition
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Try to validate a single attribute definition
  * basically it does the following checks as described by the
  * XML-1.0 recommendation:
@@ -4232,13 +4000,23 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
 
     /* One ID per Element Type */
     if (attr->atype == XML_ATTRIBUTE_ID) {
+        xmlElementPtr elem = NULL;
+        const xmlChar *elemLocalName;
+        xmlChar *elemPrefix;
         int nbId;
 
+        elemLocalName = xmlSplitQName4(attr->elem, &elemPrefix);
+        if (elemLocalName == NULL) {
+            xmlVErrMemory(ctxt);
+            return(0);
+        }
+
 	/* the trick is that we parse DtD as their own internal subset */
-        xmlElementPtr elem = xmlGetDtdElementDesc(doc->intSubset,
-	                                          attr->elem);
+        if (doc->intSubset != NULL)
+            elem = xmlHashLookup2(doc->intSubset->elements,
+                                  elemLocalName, elemPrefix);
 	if (elem != NULL) {
-	    nbId = xmlScanIDAttributeDecl(NULL, elem, 0);
+	    nbId = xmlScanIDAttributeDecl(ctxt, elem, 0);
 	} else {
 	    xmlAttributeTablePtr table;
 
@@ -4258,22 +4036,28 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
 	    xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
        "Element %s has %d ID attribute defined in the internal subset : %s\n",
 		   attr->elem, nbId, attr->name);
+            ret = 0;
 	} else if (doc->extSubset != NULL) {
 	    int extId = 0;
-	    elem = xmlGetDtdElementDesc(doc->extSubset, attr->elem);
+	    elem = xmlHashLookup2(doc->extSubset->elements,
+                                  elemLocalName, elemPrefix);
 	    if (elem != NULL) {
-		extId = xmlScanIDAttributeDecl(NULL, elem, 0);
+		extId = xmlScanIDAttributeDecl(ctxt, elem, 0);
 	    }
 	    if (extId > 1) {
 		xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
        "Element %s has %d ID attribute defined in the external subset : %s\n",
 		       attr->elem, extId, attr->name);
+                ret = 0;
 	    } else if (extId + nbId > 1) {
 		xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
 "Element %s has ID attributes defined in the internal and external subset : %s\n",
 		       attr->elem, attr->name, NULL);
+                ret = 0;
 	    }
 	}
+
+        xmlFree(elemPrefix);
     }
 
     /* Validity Constraint: Enumeration */
@@ -4300,6 +4084,8 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  * @doc:  a document instance
  * @elem:  an element definition
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Try to validate a single element definition
  * basically it does the following checks as described by the
  * XML-1.0 recommendation:
@@ -4315,6 +4101,8 @@ xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
                        xmlElementPtr elem) {
     int ret = 1;
     xmlElementPtr tst;
+    const xmlChar *localName;
+    xmlChar *prefix;
 
     CHECK_DTD;
 
@@ -4378,32 +4166,47 @@ xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
 	}
     }
 
+    localName = xmlSplitQName4(elem->name, &prefix);
+    if (localName == NULL) {
+        xmlVErrMemory(ctxt);
+        return(0);
+    }
+
     /* VC: Unique Element Type Declaration */
-    tst = xmlGetDtdElementDesc(doc->intSubset, elem->name);
-    if ((tst != NULL ) && (tst != elem) &&
-	((tst->prefix == elem->prefix) ||
-	 (xmlStrEqual(tst->prefix, elem->prefix))) &&
-	(tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
-	xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
-	                "Redefinition of element %s\n",
-		       elem->name, NULL, NULL);
-	ret = 0;
+    if (doc->intSubset != NULL) {
+        tst = xmlHashLookup2(doc->intSubset->elements, localName, prefix);
+
+        if ((tst != NULL ) && (tst != elem) &&
+            ((tst->prefix == elem->prefix) ||
+             (xmlStrEqual(tst->prefix, elem->prefix))) &&
+            (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
+            xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
+                            "Redefinition of element %s\n",
+                           elem->name, NULL, NULL);
+            ret = 0;
+        }
     }
-    tst = xmlGetDtdElementDesc(doc->extSubset, elem->name);
-    if ((tst != NULL ) && (tst != elem) &&
-	((tst->prefix == elem->prefix) ||
-	 (xmlStrEqual(tst->prefix, elem->prefix))) &&
-	(tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
-	xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
-	                "Redefinition of element %s\n",
-		       elem->name, NULL, NULL);
-	ret = 0;
+    if (doc->extSubset != NULL) {
+        tst = xmlHashLookup2(doc->extSubset->elements, localName, prefix);
+
+        if ((tst != NULL ) && (tst != elem) &&
+            ((tst->prefix == elem->prefix) ||
+             (xmlStrEqual(tst->prefix, elem->prefix))) &&
+            (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
+            xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
+                            "Redefinition of element %s\n",
+                           elem->name, NULL, NULL);
+            ret = 0;
+        }
     }
+
     /* One ID per Element Type
      * already done when registering the attribute
     if (xmlScanIDAttributeDecl(ctxt, elem) > 1) {
 	ret = 0;
     } */
+
+    xmlFree(prefix);
     return(ret);
 }
 
@@ -4415,6 +4218,8 @@ xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  * @attr:  an attribute instance
  * @value:  the attribute value (without entities processing)
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Try to validate a single attribute for an element
  * basically it does the following checks as described by the
  * XML-1.0 recommendation:
@@ -4437,6 +4242,7 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
                         xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value)
 {
     xmlAttributePtr attrDecl =  NULL;
+    const xmlChar *aprefix;
     int val;
     int ret = 1;
 
@@ -4444,42 +4250,31 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
     if ((elem == NULL) || (elem->name == NULL)) return(0);
     if ((attr == NULL) || (attr->name == NULL)) return(0);
 
+    aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL;
+
     if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
 	xmlChar fn[50];
 	xmlChar *fullname;
 
 	fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
-	if (fullname == NULL)
+	if (fullname == NULL) {
+            xmlVErrMemory(ctxt);
 	    return(0);
-	if (attr->ns != NULL) {
-	    attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
-		                          attr->name, attr->ns->prefix);
-	    if ((attrDecl == NULL) && (doc->extSubset != NULL))
-		attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
-					      attr->name, attr->ns->prefix);
-	} else {
-	    attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, attr->name);
-	    if ((attrDecl == NULL) && (doc->extSubset != NULL))
-		attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
-					     fullname, attr->name);
-	}
+        }
+        attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
+                                      attr->name, aprefix);
+        if ((attrDecl == NULL) && (doc->extSubset != NULL))
+            attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
+                                          attr->name, aprefix);
 	if ((fullname != fn) && (fullname != elem->name))
 	    xmlFree(fullname);
     }
     if (attrDecl == NULL) {
-	if (attr->ns != NULL) {
-	    attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
-		                          attr->name, attr->ns->prefix);
-	    if ((attrDecl == NULL) && (doc->extSubset != NULL))
-		attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
-					      attr->name, attr->ns->prefix);
-	} else {
-	    attrDecl = xmlGetDtdAttrDesc(doc->intSubset,
-		                         elem->name, attr->name);
-	    if ((attrDecl == NULL) && (doc->extSubset != NULL))
-		attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
-					     elem->name, attr->name);
-	}
+        attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
+                                      attr->name, aprefix);
+        if ((attrDecl == NULL) && (doc->extSubset != NULL))
+            attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
+                                          attr->name, aprefix);
     }
 
 
@@ -4490,6 +4285,8 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
 	       attr->name, elem->name, NULL);
 	return(0);
     }
+    if (attr->atype == XML_ATTRIBUTE_ID)
+        xmlRemoveID(doc, attr);
     attr->atype = attrDecl->atype;
 
     val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
@@ -4592,6 +4389,8 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  * @ns:  an namespace declaration instance
  * @value:  the attribute value (without entities processing)
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Try to validate a single namespace declaration for an element
  * basically it does the following checks as described by the
  * XML-1.0 recommendation:
@@ -4627,7 +4426,7 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
 
 	fullname = xmlBuildQName(elem->name, prefix, fn, 50);
 	if (fullname == NULL) {
-	    xmlVErrMemory(ctxt, "Validating namespace");
+	    xmlVErrMemory(ctxt);
 	    return(0);
 	}
 	if (ns->prefix != NULL) {
@@ -4637,11 +4436,11 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
 		attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
 					  ns->prefix, BAD_CAST "xmlns");
 	} else {
-	    attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname,
-		                         BAD_CAST "xmlns");
+	    attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
+                                          BAD_CAST "xmlns", NULL);
 	    if ((attrDecl == NULL) && (doc->extSubset != NULL))
-		attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname,
-			                 BAD_CAST "xmlns");
+		attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
+                                              BAD_CAST "xmlns", NULL);
 	}
 	if ((fullname != fn) && (fullname != elem->name))
 	    xmlFree(fullname);
@@ -4654,11 +4453,11 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
 		attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
 					      ns->prefix, BAD_CAST "xmlns");
 	} else {
-	    attrDecl = xmlGetDtdAttrDesc(doc->intSubset,
-		                         elem->name, BAD_CAST "xmlns");
+	    attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
+                                          BAD_CAST "xmlns", NULL);
 	    if ((attrDecl == NULL) && (doc->extSubset != NULL))
-		attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
-					     elem->name, BAD_CAST "xmlns");
+		attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
+                                              BAD_CAST "xmlns", NULL);
 	}
     }
 
@@ -4890,24 +4689,21 @@ cont:
      * epsilon transition, go directly to the analysis phase
      */
     if (STATE == ROLLBACK_PARENT) {
-	DEBUG_VALID_MSG("restored parent branch");
-	DEBUG_VALID_STATE(NODE, CONT)
 	ret = 1;
 	goto analyze;
     }
 
-    DEBUG_VALID_STATE(NODE, CONT)
     /*
      * we may have to save a backup state here. This is the equivalent
      * of handling epsilon transition in NFAs.
      */
     if ((CONT != NULL) &&
 	((CONT->parent == NULL) ||
+	 (CONT->parent == (xmlElementContentPtr) 1) ||
 	 (CONT->parent->type != XML_ELEMENT_CONTENT_OR)) &&
 	((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
 	 (CONT->ocur == XML_ELEMENT_CONTENT_OPT) ||
 	 ((CONT->ocur == XML_ELEMENT_CONTENT_PLUS) && (OCCURRENCE)))) {
-	DEBUG_VALID_MSG("saving parent branch");
 	if (vstateVPush(ctxt, CONT, NODE, DEPTH, OCCURS, ROLLBACK_PARENT) < 0)
 	    return(0);
     }
@@ -4919,12 +4715,10 @@ cont:
     switch (CONT->type) {
 	case XML_ELEMENT_CONTENT_PCDATA:
 	    if (NODE == NULL) {
-		DEBUG_VALID_MSG("pcdata failed no node");
 		ret = 0;
 		break;
 	    }
 	    if (NODE->type == XML_TEXT_NODE) {
-		DEBUG_VALID_MSG("pcdata found, skip to next");
 		/*
 		 * go to next element in the content model
 		 * skipping ignorable elems
@@ -4942,14 +4736,12 @@ cont:
                 ret = 1;
 		break;
 	    } else {
-		DEBUG_VALID_MSG("pcdata failed");
 		ret = 0;
 		break;
 	    }
 	    break;
 	case XML_ELEMENT_CONTENT_ELEMENT:
 	    if (NODE == NULL) {
-		DEBUG_VALID_MSG("element failed no node");
 		ret = 0;
 		break;
 	    }
@@ -4965,7 +4757,6 @@ cont:
 		}
 	    }
 	    if (ret == 1) {
-		DEBUG_VALID_MSG("element found, skip to next");
 		/*
 		 * go to next element in the content model
 		 * skipping ignorable elems
@@ -4981,7 +4772,6 @@ cont:
 			  (NODE->type != XML_TEXT_NODE) &&
 			  (NODE->type != XML_CDATA_SECTION_NODE)));
 	    } else {
-		DEBUG_VALID_MSG("element failed");
 		ret = 0;
 		break;
 	    }
@@ -5014,8 +4804,7 @@ cont:
 	    /*
 	     * save the second branch 'or' branch
 	     */
-	    DEBUG_VALID_MSG("saving 'or' branch");
-	    if (vstateVPush(ctxt, CONT->c2, NODE, (unsigned char)(DEPTH + 1),
+	    if (vstateVPush(ctxt, CONT->c2, NODE, DEPTH + 1,
 			    OCCURS, ROLLBACK_OR) < 0)
 		return(-1);
 	    DEPTH++;
@@ -5056,7 +4845,6 @@ cont:
      * At this point handle going up in the tree
      */
     if (ret == -1) {
-	DEBUG_VALID_MSG("error found returning");
 	return(ret);
     }
 analyze:
@@ -5071,9 +4859,7 @@ analyze:
 
 		case XML_ELEMENT_CONTENT_ONCE:
 		    cur = ctxt->vstate->node;
-		    DEBUG_VALID_MSG("Once branch failed, rollback");
 		    if (vstateVPop(ctxt) < 0 ) {
-			DEBUG_VALID_MSG("exhaustion, failed");
 			return(0);
 		    }
 		    if (cur != ctxt->vstate->node)
@@ -5082,69 +4868,50 @@ analyze:
 		case XML_ELEMENT_CONTENT_PLUS:
 		    if (OCCURRENCE == 0) {
 			cur = ctxt->vstate->node;
-			DEBUG_VALID_MSG("Plus branch failed, rollback");
 			if (vstateVPop(ctxt) < 0 ) {
-			    DEBUG_VALID_MSG("exhaustion, failed");
 			    return(0);
 			}
 			if (cur != ctxt->vstate->node)
 			    determinist = -3;
 			goto cont;
 		    }
-		    DEBUG_VALID_MSG("Plus branch found");
 		    ret = 1;
 		    break;
 		case XML_ELEMENT_CONTENT_MULT:
-#ifdef DEBUG_VALID_ALGO
-		    if (OCCURRENCE == 0) {
-			DEBUG_VALID_MSG("Mult branch failed");
-		    } else {
-			DEBUG_VALID_MSG("Mult branch found");
-		    }
-#endif
 		    ret = 1;
 		    break;
 		case XML_ELEMENT_CONTENT_OPT:
-		    DEBUG_VALID_MSG("Option branch failed");
 		    ret = 1;
 		    break;
 	    }
 	} else {
 	    switch (CONT->ocur) {
 		case XML_ELEMENT_CONTENT_OPT:
-		    DEBUG_VALID_MSG("Option branch succeeded");
 		    ret = 1;
 		    break;
 		case XML_ELEMENT_CONTENT_ONCE:
-		    DEBUG_VALID_MSG("Once branch succeeded");
 		    ret = 1;
 		    break;
 		case XML_ELEMENT_CONTENT_PLUS:
 		    if (STATE == ROLLBACK_PARENT) {
-			DEBUG_VALID_MSG("Plus branch rollback");
 			ret = 1;
 			break;
 		    }
 		    if (NODE == NULL) {
-			DEBUG_VALID_MSG("Plus branch exhausted");
 			ret = 1;
 			break;
 		    }
-		    DEBUG_VALID_MSG("Plus branch succeeded, continuing");
 		    SET_OCCURRENCE;
 		    goto cont;
 		case XML_ELEMENT_CONTENT_MULT:
 		    if (STATE == ROLLBACK_PARENT) {
-			DEBUG_VALID_MSG("Mult branch rollback");
 			ret = 1;
 			break;
 		    }
 		    if (NODE == NULL) {
-			DEBUG_VALID_MSG("Mult branch exhausted");
 			ret = 1;
 			break;
 		    }
-		    DEBUG_VALID_MSG("Mult branch succeeded, continuing");
 		    /* SET_OCCURRENCE; */
 		    goto cont;
 	    }
@@ -5155,38 +4922,32 @@ analyze:
 	 * Then act accordingly at the parent level
 	 */
 	RESET_OCCURRENCE;
-	if (CONT->parent == NULL)
+	if ((CONT->parent == NULL) ||
+            (CONT->parent == (xmlElementContentPtr) 1))
 	    break;
 
 	switch (CONT->parent->type) {
 	    case XML_ELEMENT_CONTENT_PCDATA:
-		DEBUG_VALID_MSG("Error: parent pcdata");
 		return(-1);
 	    case XML_ELEMENT_CONTENT_ELEMENT:
-		DEBUG_VALID_MSG("Error: parent element");
 		return(-1);
 	    case XML_ELEMENT_CONTENT_OR:
 		if (ret == 1) {
-		    DEBUG_VALID_MSG("Or succeeded");
 		    CONT = CONT->parent;
 		    DEPTH--;
 		} else {
-		    DEBUG_VALID_MSG("Or failed");
 		    CONT = CONT->parent;
 		    DEPTH--;
 		}
 		break;
 	    case XML_ELEMENT_CONTENT_SEQ:
 		if (ret == 0) {
-		    DEBUG_VALID_MSG("Sequence failed");
 		    CONT = CONT->parent;
 		    DEPTH--;
 		} else if (CONT == CONT->parent->c1) {
-		    DEBUG_VALID_MSG("Sequence testing 2nd branch");
 		    CONT = CONT->parent->c2;
 		    goto cont;
 		} else {
-		    DEBUG_VALID_MSG("Sequence succeeded");
 		    CONT = CONT->parent;
 		    DEPTH--;
 		}
@@ -5196,9 +4957,7 @@ analyze:
 	xmlNodePtr cur;
 
 	cur = ctxt->vstate->node;
-	DEBUG_VALID_MSG("Failed, remaining input, rollback");
 	if (vstateVPop(ctxt) < 0 ) {
-	    DEBUG_VALID_MSG("exhaustion, failed");
 	    return(0);
 	}
 	if (cur != ctxt->vstate->node)
@@ -5209,9 +4968,7 @@ analyze:
 	xmlNodePtr cur;
 
 	cur = ctxt->vstate->node;
-	DEBUG_VALID_MSG("Failure, rollback");
 	if (vstateVPop(ctxt) < 0 ) {
-	    DEBUG_VALID_MSG("exhaustion, failed");
 	    return(0);
 	}
 	if (cur != ctxt->vstate->node)
@@ -5263,7 +5020,8 @@ xmlSnprintfElements(char *buf, int size, xmlNodePtr node, int glob) {
 			strcat(buf, " ...");
 		    return;
 		}
-	        strcat(buf, (char *) cur->name);
+                if (cur->name != NULL)
+	            strcat(buf, (char *) cur->name);
 		if (cur->next != NULL)
 		    strcat(buf, " ");
 		break;
@@ -5349,67 +5107,74 @@ xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
 	ctxt->nodeNr = 0;
 	ctxt->nodeTab = NULL;
 	exec = xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
-	if (exec != NULL) {
-	    cur = child;
-	    while (cur != NULL) {
-		switch (cur->type) {
-		    case XML_ENTITY_REF_NODE:
-			/*
-			 * Push the current node to be able to roll back
-			 * and process within the entity
-			 */
-			if ((cur->children != NULL) &&
-			    (cur->children->children != NULL)) {
-			    nodeVPush(ctxt, cur);
-			    cur = cur->children->children;
-			    continue;
-			}
-			break;
-		    case XML_TEXT_NODE:
-			if (xmlIsBlankNode(cur))
-			    break;
-			ret = 0;
-			goto fail;
-		    case XML_CDATA_SECTION_NODE:
-			/* TODO */
-			ret = 0;
-			goto fail;
-		    case XML_ELEMENT_NODE:
-			if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
-			    xmlChar fn[50];
-			    xmlChar *fullname;
-
-			    fullname = xmlBuildQName(cur->name,
-				                     cur->ns->prefix, fn, 50);
-			    if (fullname == NULL) {
-				ret = -1;
-				goto fail;
-			    }
-                            ret = xmlRegExecPushString(exec, fullname, NULL);
-			    if ((fullname != fn) && (fullname != cur->name))
-				xmlFree(fullname);
-			} else {
-			    ret = xmlRegExecPushString(exec, cur->name, NULL);
-			}
-			break;
-		    default:
-			break;
-		}
-		/*
-		 * Switch to next element
-		 */
-		cur = cur->next;
-		while (cur == NULL) {
-		    cur = nodeVPop(ctxt);
-		    if (cur == NULL)
-			break;
-		    cur = cur->next;
-		}
-	    }
-	    ret = xmlRegExecPushString(exec, NULL, NULL);
+	if (exec == NULL) {
+            xmlVErrMemory(ctxt);
+            return(-1);
+        }
+        cur = child;
+        while (cur != NULL) {
+            switch (cur->type) {
+                case XML_ENTITY_REF_NODE:
+                    /*
+                     * Push the current node to be able to roll back
+                     * and process within the entity
+                     */
+                    if ((cur->children != NULL) &&
+                        (cur->children->children != NULL)) {
+                        nodeVPush(ctxt, cur);
+                        cur = cur->children->children;
+                        continue;
+                    }
+                    break;
+                case XML_TEXT_NODE:
+                    if (xmlIsBlankNode(cur))
+                        break;
+                    ret = 0;
+                    goto fail;
+                case XML_CDATA_SECTION_NODE:
+                    /* TODO */
+                    ret = 0;
+                    goto fail;
+                case XML_ELEMENT_NODE:
+                    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+                        xmlChar fn[50];
+                        xmlChar *fullname;
+
+                        fullname = xmlBuildQName(cur->name,
+                                                 cur->ns->prefix, fn, 50);
+                        if (fullname == NULL) {
+                            xmlVErrMemory(ctxt);
+                            ret = -1;
+                            goto fail;
+                        }
+                        ret = xmlRegExecPushString(exec, fullname, NULL);
+                        if ((fullname != fn) && (fullname != cur->name))
+                            xmlFree(fullname);
+                    } else {
+                        ret = xmlRegExecPushString(exec, cur->name, NULL);
+                    }
+                    break;
+                default:
+                    break;
+            }
+            if (ret == XML_REGEXP_OUT_OF_MEMORY)
+                xmlVErrMemory(ctxt);
+            /*
+             * Switch to next element
+             */
+            cur = cur->next;
+            while (cur == NULL) {
+                cur = nodeVPop(ctxt);
+                if (cur == NULL)
+                    break;
+                cur = cur->next;
+            }
+        }
+        ret = xmlRegExecPushString(exec, NULL, NULL);
+        if (ret == XML_REGEXP_OUT_OF_MEMORY)
+            xmlVErrMemory(ctxt);
 fail:
-	    xmlRegFreeExecCtxt(exec);
-	}
+        xmlRegFreeExecCtxt(exec);
     }
 #else  /* LIBXML_REGEXP_ENABLED */
     /*
@@ -5419,7 +5184,7 @@ fail:
     ctxt->vstateTab = (xmlValidState *) xmlMalloc(
 		 ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
     if (ctxt->vstateTab == NULL) {
-	xmlVErrMemory(ctxt, "malloc failed");
+	xmlVErrMemory(ctxt);
 	return(-1);
     }
     /*
@@ -5437,16 +5202,19 @@ fail:
     STATE = 0;
     ret = xmlValidateElementType(ctxt);
     if ((ret == -3) && (warn)) {
-	xmlErrValidWarning(ctxt, child, XML_DTD_CONTENT_NOT_DETERMINIST,
-	       "Content model for Element %s is ambiguous\n",
-	                   name, NULL, NULL);
+	char expr[5000];
+	expr[0] = 0;
+	xmlSnprintfElementContent(expr, 5000, elemDecl->content, 1);
+	xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
+                XML_DTD_CONTENT_NOT_DETERMINIST,
+	        "Content model of %s is not deterministic: %s\n",
+	        name, BAD_CAST expr, NULL);
     } else if (ret == -2) {
 	/*
 	 * An entities reference appeared at this level.
 	 * Build a minimal representation of this node content
 	 * sufficient to run the validation process on it
 	 */
-	DEBUG_VALID_MSG("Found an entity reference, linearizing");
 	cur = child;
 	while (cur != NULL) {
 	    switch (cur->type) {
@@ -5475,7 +5243,7 @@ fail:
 		     */
 		    tmp = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
 		    if (tmp == NULL) {
-			xmlVErrMemory(ctxt, "malloc failed");
+			xmlVErrMemory(ctxt);
 			xmlFreeNodeList(repl);
 			ret = -1;
 			goto done;
@@ -5660,6 +5428,7 @@ done:
     return(ret);
 }
 
+#ifdef LIBXML_REGEXP_ENABLED
 /**
  * xmlValidateCheckMixed:
  * @ctxt:  the validation context
@@ -5725,6 +5494,7 @@ xmlValidateCheckMixed(xmlValidCtxtPtr ctxt,
     }
     return(0);
 }
+#endif /* LIBXML_REGEXP_ENABLED */
 
 /**
  * xmlValidGetElemDecl:
@@ -5773,9 +5543,9 @@ xmlValidGetElemDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
      * full QName but in that case being flexible makes sense.
      */
     if (elemDecl == NULL) {
-	elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name);
+	elemDecl = xmlGetDtdQElementDesc(doc->intSubset, elem->name, NULL);
 	if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
-	    elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name);
+	    elemDecl = xmlGetDtdQElementDesc(doc->extSubset, elem->name, NULL);
 	    if ((elemDecl != NULL) && (extsubset != NULL))
 		*extsubset = 1;
 	}
@@ -5797,6 +5567,8 @@ xmlValidGetElemDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  * @elem:  an element instance
  * @qname:  the qualified name as appearing in the serialization
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Push a new element start on the validation stack.
  *
  * returns 1 if no validation problem was found or 0 otherwise
@@ -5865,6 +5637,10 @@ xmlValidatePushElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
 		     */
 		    if (state->exec != NULL) {
 			ret = xmlRegExecPushString(state->exec, qname, NULL);
+                        if (ret == XML_REGEXP_OUT_OF_MEMORY) {
+                            xmlVErrMemory(ctxt);
+                            return(0);
+                        }
 			if (ret < 0) {
 			    xmlErrValidNode(ctxt, state->node,
 					    XML_DTD_CONTENT_MODEL,
@@ -5890,6 +5666,8 @@ xmlValidatePushElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  * @data:  some character data read
  * @len:  the length of the data
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * check the CData parsed for validation in the current stack
  *
  * returns 1 if no validation problem was found or 0 otherwise
@@ -5963,6 +5741,8 @@ done:
  * @elem:  an element instance
  * @qname:  the qualified name as appearing in the serialization
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Pop the element end from the validation stack.
  *
  * returns 1 if no validation problem was found or 0 otherwise
@@ -5989,11 +5769,15 @@ xmlValidatePopElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc ATTRIBUTE_UNUSED,
 	    if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT) {
 		if (state->exec != NULL) {
 		    ret = xmlRegExecPushString(state->exec, NULL, NULL);
-		    if (ret == 0) {
-			xmlErrValidNode(ctxt, state->node,
-			                XML_DTD_CONTENT_MODEL,
-	   "Element %s content does not follow the DTD, Expecting more child\n",
+		    if (ret <= 0) {
+                        if (ret == XML_REGEXP_OUT_OF_MEMORY)
+                            xmlVErrMemory(ctxt);
+                        else
+			    xmlErrValidNode(ctxt, state->node,
+			                    XML_DTD_CONTENT_MODEL,
+	   "Element %s content does not follow the DTD, Expecting more children\n",
 			       state->node->name, NULL,NULL);
+			ret = 0;
 		    } else {
 			/*
 			 * previous validation errors should not generate
@@ -6016,6 +5800,8 @@ xmlValidatePopElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc ATTRIBUTE_UNUSED,
  * @doc:  a document instance
  * @elem:  an element instance
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Try to validate a single element and it's attributes,
  * basically it does the following checks as described by the
  * XML-1.0 recommendation:
@@ -6043,61 +5829,19 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
 
     if (elem == NULL) return(0);
     switch (elem->type) {
-        case XML_ATTRIBUTE_NODE:
-	    xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		   "Attribute element not expected\n", NULL, NULL ,NULL);
-	    return(0);
         case XML_TEXT_NODE:
-	    if (elem->children != NULL) {
-		xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		                "Text element has children !\n",
-				NULL,NULL,NULL);
-		return(0);
-	    }
-	    if (elem->ns != NULL) {
-		xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		                "Text element has namespace !\n",
-				NULL,NULL,NULL);
-		return(0);
-	    }
-	    if (elem->content == NULL) {
-		xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		                "Text element has no content !\n",
-				NULL,NULL,NULL);
-		return(0);
-	    }
-	    return(1);
-        case XML_XINCLUDE_START:
-        case XML_XINCLUDE_END:
-            return(1);
         case XML_CDATA_SECTION_NODE:
         case XML_ENTITY_REF_NODE:
         case XML_PI_NODE:
         case XML_COMMENT_NODE:
+        case XML_XINCLUDE_START:
+        case XML_XINCLUDE_END:
 	    return(1);
-        case XML_ENTITY_NODE:
-	    xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		   "Entity element not expected\n", NULL, NULL ,NULL);
-	    return(0);
-        case XML_NOTATION_NODE:
-	    xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		   "Notation element not expected\n", NULL, NULL ,NULL);
-	    return(0);
-        case XML_DOCUMENT_NODE:
-        case XML_DOCUMENT_TYPE_NODE:
-        case XML_DOCUMENT_FRAG_NODE:
-	    xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		   "Document element not expected\n", NULL, NULL ,NULL);
-	    return(0);
-        case XML_HTML_DOCUMENT_NODE:
-	    xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		   "HTML Document not expected\n", NULL, NULL ,NULL);
-	    return(0);
         case XML_ELEMENT_NODE:
 	    break;
 	default:
 	    xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		   "unknown element type\n", NULL, NULL ,NULL);
+		   "unexpected element type\n", NULL, NULL ,NULL);
 	    return(0);
     }
 
@@ -6155,8 +5899,10 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
 
 			fullname = xmlBuildQName(child->name, child->ns->prefix,
 				                 fn, 50);
-			if (fullname == NULL)
+			if (fullname == NULL) {
+                            xmlVErrMemory(ctxt);
 			    return(0);
+                        }
 			cont = elemDecl->content;
 			while (cont != NULL) {
 			    if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
@@ -6220,7 +5966,8 @@ child_ok:
 		 */
 		child = elem->children;
 		while (child != NULL) {
-		    if (child->type == XML_TEXT_NODE) {
+		    if ((child->type == XML_TEXT_NODE) &&
+                        (child->content != NULL)) {
 			const xmlChar *content = child->content;
 
 			while (IS_BLANK_CH(*content))
@@ -6241,7 +5988,7 @@ child_ok:
 	    cont = elemDecl->content;
 	    tmp = xmlValidateElementContent(ctxt, child, elemDecl, 1, elem);
 	    if (tmp <= 0)
-		ret = tmp;
+		ret = 0;
 	    break;
     }
     } /* not continuous */
@@ -6383,6 +6130,8 @@ found:
  * @ctxt:  the validation context
  * @doc:  a document instance
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Try to validate a the root element
  * basically it does the following check as described by the
  * XML-1.0 recommendation:
@@ -6422,7 +6171,7 @@ xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
 
 		fullname = xmlBuildQName(root->name, root->ns->prefix, fn, 50);
 		if (fullname == NULL) {
-		    xmlVErrMemory(ctxt, NULL);
+		    xmlVErrMemory(ctxt);
 		    return(0);
 		}
 		ret = xmlStrEqual(doc->intSubset->name, fullname);
@@ -6449,7 +6198,7 @@ name_ok:
  * xmlValidateElement:
  * @ctxt:  the validation context
  * @doc:  a document instance
- * @elem:  an element instance
+ * @root:  an element instance
  *
  * Try to validate the subtree under an element
  *
@@ -6457,60 +6206,67 @@ name_ok:
  */
 
 int
-xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem) {
-    xmlNodePtr child;
+xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr root) {
+    xmlNodePtr elem;
     xmlAttrPtr attr;
     xmlNsPtr ns;
     const xmlChar *value;
     int ret = 1;
 
-    if (elem == NULL) return(0);
-
-    /*
-     * XInclude elements were added after parsing in the infoset,
-     * they don't really mean anything validation wise.
-     */
-    if ((elem->type == XML_XINCLUDE_START) ||
-	(elem->type == XML_XINCLUDE_END) ||
-	(elem->type == XML_NAMESPACE_DECL))
-	return(1);
+    if (root == NULL) return(0);
 
     CHECK_DTD;
 
-    /*
-     * Entities references have to be handled separately
-     */
-    if (elem->type == XML_ENTITY_REF_NODE) {
-	return(1);
-    }
+    elem = root;
+    while (1) {
+        ret &= xmlValidateOneElement(ctxt, doc, elem);
+
+        if (elem->type == XML_ELEMENT_NODE) {
+            attr = elem->properties;
+            while (attr != NULL) {
+                if (attr->children == NULL)
+                    value = xmlStrdup(BAD_CAST "");
+                else
+                    value = xmlNodeListGetString(doc, attr->children, 0);
+                if (value == NULL) {
+                    xmlVErrMemory(ctxt);
+                    ret = 0;
+                } else {
+                    ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
+                    xmlFree((char *)value);
+                }
+                attr= attr->next;
+            }
 
-    ret &= xmlValidateOneElement(ctxt, doc, elem);
-    if (elem->type == XML_ELEMENT_NODE) {
-	attr = elem->properties;
-	while (attr != NULL) {
-	    value = xmlNodeListGetString(doc, attr->children, 0);
-	    ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
-	    if (value != NULL)
-		xmlFree((char *)value);
-	    attr= attr->next;
-	}
-	ns = elem->nsDef;
-	while (ns != NULL) {
-	    if (elem->ns == NULL)
-		ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
-					       ns, ns->href);
-	    else
-		ret &= xmlValidateOneNamespace(ctxt, doc, elem,
-		                               elem->ns->prefix, ns, ns->href);
-	    ns = ns->next;
-	}
-    }
-    child = elem->children;
-    while (child != NULL) {
-        ret &= xmlValidateElement(ctxt, doc, child);
-        child = child->next;
+            ns = elem->nsDef;
+            while (ns != NULL) {
+                if (elem->ns == NULL)
+                    ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
+                                                   ns, ns->href);
+                else
+                    ret &= xmlValidateOneNamespace(ctxt, doc, elem,
+                                                   elem->ns->prefix, ns,
+                                                   ns->href);
+                ns = ns->next;
+            }
+
+            if (elem->children != NULL) {
+                elem = elem->children;
+                continue;
+            }
+        }
+
+        while (1) {
+            if (elem == root)
+                goto done;
+            if (elem->next != NULL)
+                break;
+            elem = elem->parent;
+        }
+        elem = elem->next;
     }
 
+done:
     return(ret);
 }
 
@@ -6537,7 +6293,7 @@ xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
 
 	dup = xmlStrdup(name);
 	if (dup == NULL) {
-	    ctxt->valid = 0;
+            xmlVErrMemory(ctxt);
 	    return;
 	}
 	cur = dup;
@@ -6572,7 +6328,7 @@ xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
 
 	dup = xmlStrdup(name);
 	if (dup == NULL) {
-	    xmlVErrMemory(ctxt, "IDREFS split");
+	    xmlVErrMemory(ctxt);
 	    ctxt->valid = 0;
 	    return;
 	}
@@ -6640,6 +6396,8 @@ xmlValidateCheckRefCallback(void *payload, void *data, const xmlChar *name) {
  * @ctxt:  the validation context
  * @doc:  a document instance
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Does the final step for the document validation once all the
  * incremental validation steps have been completed
  *
@@ -6653,7 +6411,8 @@ xmlValidateCheckRefCallback(void *payload, void *data, const xmlChar *name) {
 int
 xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
     xmlRefTablePtr table;
-    unsigned int save;
+    xmlParserCtxtPtr pctxt = NULL;
+    xmlParserInputPtr oldInput = NULL;
 
     if (ctxt == NULL)
         return(0);
@@ -6663,10 +6422,6 @@ xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
 	return(0);
     }
 
-    /* trick to get correct line id report */
-    save = ctxt->flags;
-    ctxt->flags &= ~XML_VCTXT_USE_PCTXT;
-
     /*
      * Check all the NOTATION/NOTATIONS attributes
      */
@@ -6676,12 +6431,24 @@ xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
     /*
      * Check all the IDREF/IDREFS attributes definition for validity
      */
+
+    /*
+     * Don't print line numbers.
+     */
+    if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
+        pctxt = ctxt->userData;
+        oldInput = pctxt->input;
+        pctxt->input = NULL;
+    }
+
     table = (xmlRefTablePtr) doc->refs;
     ctxt->doc = doc;
     ctxt->valid = 1;
     xmlHashScan(table, xmlValidateCheckRefCallback, ctxt);
 
-    ctxt->flags = save;
+    if (ctxt->flags & XML_VCTXT_USE_PCTXT)
+        pctxt->input = oldInput;
+
     return(ctxt->valid);
 }
 
@@ -6707,31 +6474,42 @@ xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) {
     xmlDtdPtr oldExt, oldInt;
     xmlNodePtr root;
 
-    if (dtd == NULL) return(0);
-    if (doc == NULL) return(0);
+    if (dtd == NULL)
+        return(0);
+    if (doc == NULL)
+        return(0);
+
     oldExt = doc->extSubset;
     oldInt = doc->intSubset;
     doc->extSubset = dtd;
     doc->intSubset = NULL;
-    ret = xmlValidateRoot(ctxt, doc);
-    if (ret == 0) {
-	doc->extSubset = oldExt;
-	doc->intSubset = oldInt;
-	return(ret);
-    }
     if (doc->ids != NULL) {
-          xmlFreeIDTable(doc->ids);
-          doc->ids = NULL;
+        xmlFreeIDTable(doc->ids);
+        doc->ids = NULL;
     }
     if (doc->refs != NULL) {
-          xmlFreeRefTable(doc->refs);
-          doc->refs = NULL;
+        xmlFreeRefTable(doc->refs);
+        doc->refs = NULL;
     }
-    root = xmlDocGetRootElement(doc);
-    ret = xmlValidateElement(ctxt, doc, root);
-    ret &= xmlValidateDocumentFinal(ctxt, doc);
+
+    ret = xmlValidateRoot(ctxt, doc);
+    if (ret != 0) {
+        root = xmlDocGetRootElement(doc);
+        ret = xmlValidateElement(ctxt, doc, root);
+        ret &= xmlValidateDocumentFinal(ctxt, doc);
+    }
+
     doc->extSubset = oldExt;
     doc->intSubset = oldInt;
+    if (doc->ids != NULL) {
+        xmlFreeIDTable(doc->ids);
+        doc->ids = NULL;
+    }
+    if (doc->refs != NULL) {
+        xmlFreeRefTable(doc->refs);
+        doc->refs = NULL;
+    }
+
     return(ret);
 }
 
@@ -6798,6 +6576,9 @@ xmlValidateAttributeCallback(void *payload, void *data,
 	    }
     }
     if (cur->atype == XML_ATTRIBUTE_NOTATION) {
+        const xmlChar *elemLocalName;
+        xmlChar *elemPrefix;
+
 	doc = cur->doc;
 	if (cur->elem == NULL) {
 	    xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
@@ -6806,13 +6587,25 @@ xmlValidateAttributeCallback(void *payload, void *data,
 	    return;
 	}
 
-	if (doc != NULL)
-	    elem = xmlGetDtdElementDesc(doc->intSubset, cur->elem);
-	if ((elem == NULL) && (doc != NULL))
-	    elem = xmlGetDtdElementDesc(doc->extSubset, cur->elem);
+        elemLocalName = xmlSplitQName4(cur->elem, &elemPrefix);
+        if (elemLocalName == NULL) {
+            xmlVErrMemory(ctxt);
+            return;
+        }
+
+	if ((doc != NULL) && (doc->intSubset != NULL))
+	    elem = xmlHashLookup2(doc->intSubset->elements,
+                                  elemLocalName, elemPrefix);
+	if ((elem == NULL) && (doc != NULL) && (doc->extSubset != NULL))
+	    elem = xmlHashLookup2(doc->extSubset->elements,
+                                  elemLocalName, elemPrefix);
 	if ((elem == NULL) && (cur->parent != NULL) &&
 	    (cur->parent->type == XML_DTD_NODE))
-	    elem = xmlGetDtdElementDesc((xmlDtdPtr) cur->parent, cur->elem);
+	    elem = xmlHashLookup2(((xmlDtdPtr) cur->parent)->elements,
+                                  elemLocalName, elemPrefix);
+
+        xmlFree(elemPrefix);
+
 	if (elem == NULL) {
 	    xmlErrValidNode(ctxt, NULL, XML_DTD_UNKNOWN_ELEM,
 		   "attribute %s: could not find decl for element %s\n",
@@ -6833,6 +6626,8 @@ xmlValidateAttributeCallback(void *payload, void *data,
  * @ctxt:  the validation context
  * @doc:  a document instance
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Does the final step for the dtds validation once all the
  * subsets have been parsed
  *
@@ -7007,7 +6802,7 @@ xmlValidGetPotentialChildren(xmlElementContent *ctree,
 /*
  * Dummy function to suppress messages while we try out valid elements
  */
-static void XMLCDECL xmlNoValidityErr(void *ctx ATTRIBUTE_UNUSED,
+static void xmlNoValidityErr(void *ctx ATTRIBUTE_UNUSED,
                                 const char *msg ATTRIBUTE_UNUSED, ...) {
     return;
 }
diff --git a/xinclude.c b/xinclude.c
index 0c6b3f296bf46cbf625e0c1aac9884320355e068..6c1e3ace64f7c838ca819631a91e2fb9e58b1963 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -22,22 +22,17 @@
 #include <libxml/parserInternals.h>
 #include <libxml/xmlerror.h>
 #include <libxml/encoding.h>
-#include <libxml/globals.h>
 
 #ifdef LIBXML_XINCLUDE_ENABLED
 #include <libxml/xinclude.h>
 
-#include "buf.h"
+#include "private/buf.h"
+#include "private/error.h"
+#include "private/tree.h"
+#include "private/xinclude.h"
 
 #define XINCLUDE_MAX_DEPTH 40
 
-/* #define DEBUG_XINCLUDE */
-#ifdef DEBUG_XINCLUDE
-#ifdef LIBXML_DEBUG_ENABLED
-#include <libxml/debugXML.h>
-#endif
-#endif
-
 /************************************************************************
  *									*
  *			XInclude context handling			*
@@ -54,45 +49,72 @@ typedef xmlXIncludeRef *xmlXIncludeRefPtr;
 struct _xmlXIncludeRef {
     xmlChar              *URI; /* the fully resolved resource URL */
     xmlChar         *fragment; /* the fragment in the URI */
-    xmlDocPtr		  doc; /* the parsed document */
-    xmlNodePtr            ref; /* the node making the reference in the source */
+    xmlChar             *base; /* base URI of xi:include element */
+    xmlNodePtr           elem; /* the xi:include element */
     xmlNodePtr            inc; /* the included copy */
     int                   xml; /* xml or txt */
-    int                 count; /* how many refs use that specific doc */
     int	             fallback; /* fallback was loaded */
-    int		      emptyFb; /* flag to show fallback empty */
+    int		    expanding; /* flag to detect inclusion loops */
+    int		      replace; /* should the node be replaced? */
+};
+
+typedef struct _xmlXIncludeDoc xmlXIncludeDoc;
+typedef xmlXIncludeDoc *xmlXIncludeDocPtr;
+struct _xmlXIncludeDoc {
+    xmlDocPtr             doc; /* the parsed document */
+    xmlChar              *url; /* the URL */
+    int             expanding; /* flag to detect inclusion loops */
+};
+
+typedef struct _xmlXIncludeTxt xmlXIncludeTxt;
+typedef xmlXIncludeTxt *xmlXIncludeTxtPtr;
+struct _xmlXIncludeTxt {
+    xmlChar		*text; /* text string */
+    xmlChar              *url; /* the URL */
 };
 
 struct _xmlXIncludeCtxt {
     xmlDocPtr             doc; /* the source document */
-    int               incBase; /* the first include for this document */
     int                 incNr; /* number of includes */
     int                incMax; /* size of includes tab */
     xmlXIncludeRefPtr *incTab; /* array of included references */
 
     int                 txtNr; /* number of unparsed documents */
     int                txtMax; /* size of unparsed documents tab */
-    xmlChar *         *txtTab; /* array of unparsed text strings */
-    xmlURL         *txturlTab; /* array of unparsed text URLs */
+    xmlXIncludeTxt    *txtTab; /* array of unparsed documents */
 
-    xmlChar *             url; /* the current URL processed */
-    int                 urlNr; /* number of URLs stacked */
-    int                urlMax; /* size of URL stack */
-    xmlChar *         *urlTab; /* URL stack */
+    int                 urlNr; /* number of documents stacked */
+    int                urlMax; /* size of document stack */
+    xmlXIncludeDoc    *urlTab; /* document stack */
 
     int              nbErrors; /* the number of errors detected */
+    int              fatalErr; /* abort processing */
+    int                 errNo; /* error code */
     int                legacy; /* using XINCLUDE_OLD_NS */
     int            parseFlags; /* the flags used for parsing XML documents */
-    xmlChar *		 base; /* the current xml:base */
 
     void            *_private; /* application data */
 
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
     unsigned long    incTotal; /* total number of processed inclusions */
+#endif
+    int			depth; /* recursion depth */
+    int		     isStream; /* streaming mode */
+
+    xmlXPathContextPtr xpctxt;
+
+    xmlStructuredErrorFunc errorHandler;
+    void *errorCtxt;
 };
 
+static xmlXIncludeRefPtr
+xmlXIncludeExpandNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node);
+
+static int
+xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref);
+
 static int
-xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
-                     int skipRoot);
+xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree);
 
 
 /************************************************************************
@@ -108,15 +130,14 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
  * Handle an out of memory condition
  */
 static void
-xmlXIncludeErrMemory(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node,
-                     const char *extra)
+xmlXIncludeErrMemory(xmlXIncludeCtxtPtr ctxt)
 {
-    if (ctxt != NULL)
-	ctxt->nbErrors++;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
-                    XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0,
-		    extra, NULL, NULL, 0, 0,
-		    "Memory allocation failed : %s\n", extra);
+    ctxt->errNo = XML_ERR_NO_MEMORY;
+    ctxt->fatalErr = 1;
+    ctxt->nbErrors++;
+
+    xmlRaiseMemoryError(ctxt->errorHandler, NULL, ctxt->errorCtxt,
+                        XML_FROM_XINCLUDE, NULL);
 }
 
 /**
@@ -132,34 +153,34 @@ static void LIBXML_ATTR_FORMAT(4,0)
 xmlXIncludeErr(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
                const char *msg, const xmlChar *extra)
 {
-    if (ctxt != NULL)
-	ctxt->nbErrors++;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
-                    error, XML_ERR_ERROR, NULL, 0,
-		    (const char *) extra, NULL, NULL, 0, 0,
-		    msg, (const char *) extra);
-}
+    xmlStructuredErrorFunc schannel = NULL;
+    xmlGenericErrorFunc channel = NULL;
+    void *data = NULL;
+    int res;
 
-#if 0
-/**
- * xmlXIncludeWarn:
- * @ctxt: the XInclude context
- * @node: the context node
- * @msg:  the error message
- * @extra:  extra information
- *
- * Emit an XInclude warning.
- */
-static void LIBXML_ATTR_FORMAT(4,0)
-xmlXIncludeWarn(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
-               const char *msg, const xmlChar *extra)
-{
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
-                    error, XML_ERR_WARNING, NULL, 0,
-		    (const char *) extra, NULL, NULL, 0, 0,
-		    msg, (const char *) extra);
+    if (ctxt->fatalErr != 0)
+        return;
+    ctxt->nbErrors++;
+
+    schannel = ctxt->errorHandler;
+    data = ctxt->errorCtxt;
+
+    if (schannel == NULL) {
+        channel = xmlGenericError;
+        data = xmlGenericErrorContext;
+    }
+
+    res = __xmlRaiseError(schannel, channel, data, ctxt, node,
+                          XML_FROM_XINCLUDE, error, XML_ERR_ERROR,
+                          NULL, 0, (const char *) extra, NULL, NULL, 0, 0,
+		          msg, (const char *) extra);
+    if (res < 0) {
+        ctxt->errNo = XML_ERR_NO_MEMORY;
+        ctxt->fatalErr = 1;
+    } else {
+        ctxt->errNo = error;
+    }
 }
-#endif
 
 /**
  * xmlXIncludeGetProp:
@@ -176,15 +197,20 @@ xmlXIncludeGetProp(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur,
                    const xmlChar *name) {
     xmlChar *ret;
 
-    ret = xmlGetNsProp(cur, XINCLUDE_NS, name);
+    if (xmlNodeGetAttrValue(cur, name, XINCLUDE_NS, &ret) < 0)
+        xmlXIncludeErrMemory(ctxt);
     if (ret != NULL)
         return(ret);
+
     if (ctxt->legacy != 0) {
-	ret = xmlGetNsProp(cur, XINCLUDE_OLD_NS, name);
-	if (ret != NULL)
-	    return(ret);
+        if (xmlNodeGetAttrValue(cur, name, XINCLUDE_OLD_NS, &ret) < 0)
+            xmlXIncludeErrMemory(ctxt);
+        if (ret != NULL)
+            return(ret);
     }
-    ret = xmlGetProp(cur, name);
+
+    if (xmlNodeGetAttrValue(cur, name, NULL, &ret) < 0)
+        xmlXIncludeErrMemory(ctxt);
     return(ret);
 }
 /**
@@ -197,79 +223,15 @@ static void
 xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) {
     if (ref == NULL)
 	return;
-#ifdef DEBUG_XINCLUDE
-    xmlGenericError(xmlGenericErrorContext, "Freeing ref\n");
-#endif
-    if (ref->doc != NULL) {
-#ifdef DEBUG_XINCLUDE
-	xmlGenericError(xmlGenericErrorContext, "Freeing doc %s\n", ref->URI);
-#endif
-	xmlFreeDoc(ref->doc);
-    }
     if (ref->URI != NULL)
 	xmlFree(ref->URI);
     if (ref->fragment != NULL)
 	xmlFree(ref->fragment);
+    if (ref->base != NULL)
+	xmlFree(ref->base);
     xmlFree(ref);
 }
 
-/**
- * xmlXIncludeNewRef:
- * @ctxt: the XInclude context
- * @URI:  the resource URI
- *
- * Creates a new reference within an XInclude context
- *
- * Returns the new set
- */
-static xmlXIncludeRefPtr
-xmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI,
-	          xmlNodePtr ref) {
-    xmlXIncludeRefPtr ret;
-
-#ifdef DEBUG_XINCLUDE
-    xmlGenericError(xmlGenericErrorContext, "New ref %s\n", URI);
-#endif
-    ret = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef));
-    if (ret == NULL) {
-        xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
-	return(NULL);
-    }
-    memset(ret, 0, sizeof(xmlXIncludeRef));
-    if (URI == NULL)
-	ret->URI = NULL;
-    else
-	ret->URI = xmlStrdup(URI);
-    ret->fragment = NULL;
-    ret->ref = ref;
-    ret->doc = NULL;
-    ret->count = 0;
-    ret->xml = 0;
-    ret->inc = NULL;
-    if (ctxt->incMax == 0) {
-	ctxt->incMax = 4;
-        ctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(ctxt->incMax *
-					      sizeof(ctxt->incTab[0]));
-        if (ctxt->incTab == NULL) {
-	    xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
-	    xmlXIncludeFreeRef(ret);
-	    return(NULL);
-	}
-    }
-    if (ctxt->incNr >= ctxt->incMax) {
-	ctxt->incMax *= 2;
-        ctxt->incTab = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab,
-	             ctxt->incMax * sizeof(ctxt->incTab[0]));
-        if (ctxt->incTab == NULL) {
-	    xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
-	    xmlXIncludeFreeRef(ret);
-	    return(NULL);
-	}
-    }
-    ctxt->incTab[ctxt->incNr++] = ret;
-    return(ret);
-}
-
 /**
  * xmlXIncludeNewContext:
  * @doc:  an XML Document
@@ -282,94 +244,20 @@ xmlXIncludeCtxtPtr
 xmlXIncludeNewContext(xmlDocPtr doc) {
     xmlXIncludeCtxtPtr ret;
 
-#ifdef DEBUG_XINCLUDE
-    xmlGenericError(xmlGenericErrorContext, "New context\n");
-#endif
     if (doc == NULL)
 	return(NULL);
     ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt));
-    if (ret == NULL) {
-	xmlXIncludeErrMemory(NULL, (xmlNodePtr) doc,
-	                     "creating XInclude context");
+    if (ret == NULL)
 	return(NULL);
-    }
     memset(ret, 0, sizeof(xmlXIncludeCtxt));
     ret->doc = doc;
     ret->incNr = 0;
-    ret->incBase = 0;
     ret->incMax = 0;
     ret->incTab = NULL;
     ret->nbErrors = 0;
     return(ret);
 }
 
-/**
- * xmlXIncludeURLPush:
- * @ctxt:  the parser context
- * @value:  the url
- *
- * Pushes a new url on top of the url stack
- *
- * Returns -1 in case of error, the index in the stack otherwise
- */
-static int
-xmlXIncludeURLPush(xmlXIncludeCtxtPtr ctxt,
-	           const xmlChar *value)
-{
-    if (ctxt->urlNr > XINCLUDE_MAX_DEPTH) {
-	xmlXIncludeErr(ctxt, NULL, XML_XINCLUDE_RECURSION,
-	               "detected a recursion in %s\n", value);
-	return(-1);
-    }
-    if (ctxt->urlTab == NULL) {
-	ctxt->urlMax = 4;
-	ctxt->urlNr = 0;
-	ctxt->urlTab = (xmlChar * *) xmlMalloc(
-		        ctxt->urlMax * sizeof(ctxt->urlTab[0]));
-        if (ctxt->urlTab == NULL) {
-	    xmlXIncludeErrMemory(ctxt, NULL, "adding URL");
-            return (-1);
-        }
-    }
-    if (ctxt->urlNr >= ctxt->urlMax) {
-        ctxt->urlMax *= 2;
-        ctxt->urlTab =
-            (xmlChar * *) xmlRealloc(ctxt->urlTab,
-                                      ctxt->urlMax *
-                                      sizeof(ctxt->urlTab[0]));
-        if (ctxt->urlTab == NULL) {
-	    xmlXIncludeErrMemory(ctxt, NULL, "adding URL");
-            return (-1);
-        }
-    }
-    ctxt->url = ctxt->urlTab[ctxt->urlNr] = xmlStrdup(value);
-    return (ctxt->urlNr++);
-}
-
-/**
- * xmlXIncludeURLPop:
- * @ctxt: the parser context
- *
- * Pops the top URL from the URL stack
- */
-static void
-xmlXIncludeURLPop(xmlXIncludeCtxtPtr ctxt)
-{
-    xmlChar * ret;
-
-    if (ctxt->urlNr <= 0)
-        return;
-    ctxt->urlNr--;
-    if (ctxt->urlNr > 0)
-        ctxt->url = ctxt->urlTab[ctxt->urlNr - 1];
-    else
-        ctxt->url = NULL;
-    ret = ctxt->urlTab[ctxt->urlNr];
-    ctxt->urlTab[ctxt->urlNr] = NULL;
-    if (ret != NULL)
-	xmlFree(ret);
-}
-
 /**
  * xmlXIncludeFreeContext:
  * @ctxt: the XInclude context
@@ -380,15 +268,15 @@ void
 xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
     int i;
 
-#ifdef DEBUG_XINCLUDE
-    xmlGenericError(xmlGenericErrorContext, "Freeing context\n");
-#endif
     if (ctxt == NULL)
 	return;
-    while (ctxt->urlNr > 0)
-	xmlXIncludeURLPop(ctxt);
-    if (ctxt->urlTab != NULL)
+    if (ctxt->urlTab != NULL) {
+	for (i = 0; i < ctxt->urlNr; i++) {
+	    xmlFreeDoc(ctxt->urlTab[i].doc);
+	    xmlFree(ctxt->urlTab[i].url);
+	}
 	xmlFree(ctxt->urlTab);
+    }
     for (i = 0;i < ctxt->incNr;i++) {
 	if (ctxt->incTab[i] != NULL)
 	    xmlXIncludeFreeRef(ctxt->incTab[i]);
@@ -397,21 +285,13 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
 	xmlFree(ctxt->incTab);
     if (ctxt->txtTab != NULL) {
 	for (i = 0;i < ctxt->txtNr;i++) {
-	    if (ctxt->txtTab[i] != NULL)
-		xmlFree(ctxt->txtTab[i]);
+	    xmlFree(ctxt->txtTab[i].text);
+	    xmlFree(ctxt->txtTab[i].url);
 	}
 	xmlFree(ctxt->txtTab);
     }
-    if (ctxt->txturlTab != NULL) {
-	for (i = 0;i < ctxt->txtNr;i++) {
-	    if (ctxt->txturlTab[i] != NULL)
-		xmlFree(ctxt->txturlTab[i]);
-	}
-	xmlFree(ctxt->txturlTab);
-    }
-    if (ctxt->base != NULL) {
-        xmlFree(ctxt->base);
-    }
+    if (ctxt->xpctxt != NULL)
+	xmlXPathFreeContext(ctxt->xpctxt);
     xmlFree(ctxt);
 }
 
@@ -424,7 +304,7 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
  */
 static xmlDocPtr
 xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
-    xmlDocPtr ret;
+    xmlDocPtr ret = NULL;
     xmlParserCtxtPtr pctxt;
     xmlParserInputPtr inputStream;
 
@@ -432,9 +312,11 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
 
     pctxt = xmlNewParserCtxt();
     if (pctxt == NULL) {
-	xmlXIncludeErrMemory(ctxt, NULL, "cannot allocate parser context");
+	xmlXIncludeErrMemory(ctxt);
 	return(NULL);
     }
+    if (ctxt->errorHandler != NULL)
+        xmlCtxtSetErrorHandler(pctxt, ctxt->errorHandler, ctxt->errorCtxt);
 
     /*
      * pass in the application data to the parser context.
@@ -452,25 +334,18 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
 	xmlDictReference(pctxt->dict);
     }
 
+    /*
+     * We set DTDLOAD to make sure that ID attributes declared in
+     * external DTDs are detected.
+     */
     xmlCtxtUseOptions(pctxt, ctxt->parseFlags | XML_PARSE_DTDLOAD);
 
-    /* Don't read from stdin. */
-    if ((URL != NULL) && (strcmp(URL, "-") == 0))
-        URL = "./-";
-
     inputStream = xmlLoadExternalEntity(URL, NULL, pctxt);
-    if (inputStream == NULL) {
-	xmlFreeParserCtxt(pctxt);
-	return(NULL);
-    }
+    if (inputStream == NULL)
+        goto error;
 
     inputPush(pctxt, inputStream);
 
-    if (pctxt->directory == NULL)
-        pctxt->directory = xmlParserGetDirectory(URL);
-
-    pctxt->loadsubset |= XML_DETECT_IDS;
-
     xmlParseDocument(pctxt);
 
     if (pctxt->wellFormed) {
@@ -482,6 +357,10 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
 	    xmlFreeDoc(pctxt->myDoc);
         pctxt->myDoc = NULL;
     }
+
+error:
+    if (pctxt->errNo == XML_ERR_NO_MEMORY)
+        xmlXIncludeErrMemory(ctxt);
     xmlFreeParserCtxt(pctxt);
 
     return(ret);
@@ -494,37 +373,46 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
  *
  * Add a new node to process to an XInclude context
  */
-static int
+static xmlXIncludeRefPtr
 xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
-    xmlXIncludeRefPtr ref;
-    xmlURIPtr uri;
-    xmlChar *URL;
+    xmlXIncludeRefPtr ref = NULL;
+    xmlXIncludeRefPtr ret = NULL;
+    xmlURIPtr uri = NULL;
+    xmlChar *href = NULL;
+    xmlChar *parse = NULL;
     xmlChar *fragment = NULL;
-    xmlChar *href;
-    xmlChar *parse;
-    xmlChar *base;
-    xmlChar *URI;
-    int xml = 1, i; /* default Issue 64 */
+    xmlChar *base = NULL;
+    xmlChar *tmp;
+    int xml = 1;
     int local = 0;
-
+    int res;
 
     if (ctxt == NULL)
-	return(-1);
+	return(NULL);
     if (cur == NULL)
-	return(-1);
+	return(NULL);
 
-#ifdef DEBUG_XINCLUDE
-    xmlGenericError(xmlGenericErrorContext, "Add node\n");
-#endif
     /*
      * read the attributes
      */
+
+    fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER);
+
     href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
     if (href == NULL) {
+        if (fragment == NULL) {
+	    xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_NO_HREF,
+	                   "href or xpointer must be present\n", parse);
+	    goto error;
+        }
+
 	href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
-	if (href == NULL)
-	    return(-1);
+	if (href == NULL) {
+            xmlXIncludeErrMemory(ctxt);
+	    goto error;
+        }
     }
+
     parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
     if (parse != NULL) {
 	if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
@@ -534,61 +422,21 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
 	else {
 	    xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE,
 	                   "invalid value %s for 'parse'\n", parse);
-	    if (href != NULL)
-		xmlFree(href);
-	    if (parse != NULL)
-		xmlFree(parse);
-	    return(-1);
+	    goto error;
 	}
     }
 
-    /*
-     * compute the URI
-     */
-    base = xmlNodeGetBase(ctxt->doc, cur);
-    if (base == NULL) {
-	URI = xmlBuildURI(href, ctxt->doc->URL);
-    } else {
-	URI = xmlBuildURI(href, base);
-    }
-    if (URI == NULL) {
-	xmlChar *escbase;
-	xmlChar *eschref;
-	/*
-	 * Some escaping may be needed
-	 */
-	escbase = xmlURIEscape(base);
-	eschref = xmlURIEscape(href);
-	URI = xmlBuildURI(eschref, escbase);
-	if (escbase != NULL)
-	    xmlFree(escbase);
-	if (eschref != NULL)
-	    xmlFree(eschref);
-    }
-    if (parse != NULL)
-	xmlFree(parse);
-    if (href != NULL)
-	xmlFree(href);
-    if (base != NULL)
-	xmlFree(base);
-    if (URI == NULL) {
-	xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
-	               "failed build URL\n", NULL);
-	return(-1);
-    }
-    fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER);
-
     /*
      * Check the URL and remove any fragment identifier
      */
-    uri = xmlParseURI((const char *)URI);
+    res = xmlParseURISafe((const char *)href, &uri);
     if (uri == NULL) {
-	xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
-	               "invalid value URI %s\n", URI);
-	if (fragment != NULL)
-	    xmlFree(fragment);
-	xmlFree(URI);
-	return(-1);
+        if (res < 0)
+            xmlXIncludeErrMemory(ctxt);
+        else
+            xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
+                           "invalid value href %s\n", href);
+        goto error;
     }
 
     if (uri->fragment != NULL) {
@@ -601,28 +449,46 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
 	} else {
 	    xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_FRAGMENT_ID,
        "Invalid fragment identifier in URI %s use the xpointer attribute\n",
-                           URI);
-	    if (fragment != NULL)
-	        xmlFree(fragment);
-	    xmlFreeURI(uri);
-	    xmlFree(URI);
-	    return(-1);
+                           href);
+	    goto error;
 	}
 	uri->fragment = NULL;
     }
-    URL = xmlSaveUri(uri);
-    xmlFreeURI(uri);
-    xmlFree(URI);
-    if (URL == NULL) {
-	xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
-	               "invalid value URI %s\n", URI);
-	if (fragment != NULL)
-	    xmlFree(fragment);
-	return(-1);
+    tmp = xmlSaveUri(uri);
+    if (tmp == NULL) {
+	xmlXIncludeErrMemory(ctxt);
+	goto error;
     }
+    xmlFree(href);
+    href = tmp;
+
+    /*
+     * Resolve URI
+     */
+
+    if (xmlNodeGetBaseSafe(ctxt->doc, cur, &base) < 0) {
+        xmlXIncludeErrMemory(ctxt);
+        goto error;
+    }
+
+    if (href[0] != 0) {
+        if (xmlBuildURISafe(href, base, &tmp) < 0) {
+            xmlXIncludeErrMemory(ctxt);
+            goto error;
+        }
+        if (tmp == NULL) {
+            xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
+                           "failed build URL\n", NULL);
+            goto error;
+        }
+        xmlFree(href);
+        href = tmp;
 
-    if (xmlStrEqual(URL, ctxt->doc->URL))
-	local = 1;
+        if (xmlStrEqual(href, ctxt->doc->URL))
+            local = 1;
+    } else {
+        local = 1;
+    }
 
     /*
      * If local and xml then we need a fragment
@@ -631,182 +497,113 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
         ((fragment == NULL) || (fragment[0] == 0))) {
 	xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
 	               "detected a local recursion with no xpointer in %s\n",
-		       URL);
-        xmlFree(URL);
-        xmlFree(fragment);
-	return(-1);
+		       href);
+	goto error;
     }
 
-    /*
-     * Check the URL against the stack for recursions
-     */
-    if ((!local) && (xml == 1)) {
-	for (i = 0;i < ctxt->urlNr;i++) {
-	    if (xmlStrEqual(URL, ctxt->urlTab[i])) {
-		xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
-		               "detected a recursion in %s\n", URL);
-                xmlFree(URL);
-                xmlFree(fragment);
-		return(-1);
-	    }
-	}
-    }
-
-    ref = xmlXIncludeNewRef(ctxt, URL, cur);
-    xmlFree(URL);
+    ref = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef));
     if (ref == NULL) {
-	return(-1);
+        xmlXIncludeErrMemory(ctxt);
+        goto error;
     }
-    ref->fragment = fragment;
-    ref->doc = NULL;
-    ref->xml = xml;
-    ref->count = 1;
-    return(0);
-}
+    memset(ref, 0, sizeof(xmlXIncludeRef));
 
-/**
- * xmlXIncludeRecurseDoc:
- * @ctxt:  the XInclude context
- * @doc:  the new document
- * @url:  the associated URL
- *
- * The XInclude recursive nature is handled at this point.
- */
-static void
-xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
-	              const xmlURL url ATTRIBUTE_UNUSED) {
-    xmlXIncludeCtxtPtr newctxt;
-    int i;
+    ref->elem = cur;
+    ref->xml = xml;
+    ref->URI = href;
+    href = NULL;
+    ref->fragment = fragment;
+    fragment = NULL;
 
     /*
-     * Avoid recursion in already substituted resources
-    for (i = 0;i < ctxt->urlNr;i++) {
-	if (xmlStrEqual(doc->URL, ctxt->urlTab[i]))
-	    return;
-    }
+     * xml:base fixup
      */
+    if (((ctxt->parseFlags & XML_PARSE_NOBASEFIX) == 0) &&
+        (cur->doc != NULL) &&
+        ((cur->doc->parseFlags & XML_PARSE_NOBASEFIX) == 0)) {
+        if (base != NULL) {
+            ref->base = base;
+            base = NULL;
+        } else {
+            ref->base = xmlStrdup(BAD_CAST "");
+            if (ref->base == NULL) {
+	        xmlXIncludeErrMemory(ctxt);
+                goto error;
+            }
+        }
+    }
 
-#ifdef DEBUG_XINCLUDE
-    xmlGenericError(xmlGenericErrorContext, "Recursing in doc %s\n", doc->URL);
+    if (ctxt->incNr >= ctxt->incMax) {
+        xmlXIncludeRefPtr *table;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+        size_t newSize = ctxt->incMax ? ctxt->incMax * 2 : 1;
+#else
+        size_t newSize = ctxt->incMax ? ctxt->incMax * 2 : 4;
 #endif
-    /*
-     * Handle recursion here.
-     */
-
-    newctxt = xmlXIncludeNewContext(doc);
-    if (newctxt != NULL) {
-	/*
-	 * Copy the private user data
-	 */
-	newctxt->_private = ctxt->_private;
-	/*
-	 * Copy the existing document set
-	 */
-	newctxt->incMax = ctxt->incMax;
-	newctxt->incNr = ctxt->incNr;
-        newctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(newctxt->incMax *
-		                          sizeof(newctxt->incTab[0]));
-        if (newctxt->incTab == NULL) {
-	    xmlXIncludeErrMemory(ctxt, (xmlNodePtr) doc, "processing doc");
-	    xmlFree(newctxt);
-	    return;
-	}
-	/*
-	 * copy the urlTab
-	 */
-	newctxt->urlMax = ctxt->urlMax;
-	newctxt->urlNr = ctxt->urlNr;
-	newctxt->urlTab = ctxt->urlTab;
-
-	/*
-	 * Inherit the existing base
-	 */
-	newctxt->base = xmlStrdup(ctxt->base);
 
-	/*
-	 * Inherit the documents already in use by other includes
-	 */
-	newctxt->incBase = ctxt->incNr;
-	for (i = 0;i < ctxt->incNr;i++) {
-	    newctxt->incTab[i] = ctxt->incTab[i];
-	    newctxt->incTab[i]->count++; /* prevent the recursion from
-					    freeing it */
+        table = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab,
+	             newSize * sizeof(ctxt->incTab[0]));
+        if (table == NULL) {
+	    xmlXIncludeErrMemory(ctxt);
+	    goto error;
 	}
-	/*
-	 * The new context should also inherit the Parse Flags
-	 * (bug 132597)
-	 */
-	newctxt->parseFlags = ctxt->parseFlags;
-        newctxt->incTotal = ctxt->incTotal;
-	xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc), 0);
-        ctxt->incTotal = newctxt->incTotal;
-	for (i = 0;i < ctxt->incNr;i++) {
-	    newctxt->incTab[i]->count--;
-	    newctxt->incTab[i] = NULL;
-	}
-
-	/* urlTab may have been reallocated */
-	ctxt->urlTab = newctxt->urlTab;
-	ctxt->urlMax = newctxt->urlMax;
+        ctxt->incTab = table;
+        ctxt->incMax = newSize;
+    }
+    ctxt->incTab[ctxt->incNr++] = ref;
 
-	newctxt->urlMax = 0;
-	newctxt->urlNr = 0;
-	newctxt->urlTab = NULL;
+    ret = ref;
+    ref = NULL;
 
-	xmlXIncludeFreeContext(newctxt);
-    }
-#ifdef DEBUG_XINCLUDE
-    xmlGenericError(xmlGenericErrorContext, "Done recursing in doc %s\n", url);
-#endif
+error:
+    xmlXIncludeFreeRef(ref);
+    xmlFreeURI(uri);
+    xmlFree(href);
+    xmlFree(parse);
+    xmlFree(fragment);
+    xmlFree(base);
+    return(ret);
 }
 
 /**
- * xmlXIncludeAddTxt:
+ * xmlXIncludeRecurseDoc:
  * @ctxt:  the XInclude context
- * @txt:  the new text node
+ * @doc:  the new document
  * @url:  the associated URL
  *
- * Add a new text node to the list
+ * The XInclude recursive nature is handled at this point.
  */
 static void
-xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *txt,
-                  const xmlURL url) {
-#ifdef DEBUG_XINCLUDE
-    xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
-#endif
-    if (ctxt->txtMax == 0) {
-	ctxt->txtMax = 4;
-        ctxt->txtTab = (xmlChar **) xmlMalloc(ctxt->txtMax *
-		                          sizeof(ctxt->txtTab[0]));
-        if (ctxt->txtTab == NULL) {
-	    xmlXIncludeErrMemory(ctxt, NULL, "processing text");
-	    return;
-	}
-        ctxt->txturlTab = (xmlURL *) xmlMalloc(ctxt->txtMax *
-		                          sizeof(ctxt->txturlTab[0]));
-        if (ctxt->txturlTab == NULL) {
-	    xmlXIncludeErrMemory(ctxt, NULL, "processing text");
-	    return;
-	}
-    }
-    if (ctxt->txtNr >= ctxt->txtMax) {
-	ctxt->txtMax *= 2;
-        ctxt->txtTab = (xmlChar **) xmlRealloc(ctxt->txtTab,
-	             ctxt->txtMax * sizeof(ctxt->txtTab[0]));
-        if (ctxt->txtTab == NULL) {
-	    xmlXIncludeErrMemory(ctxt, NULL, "processing text");
-	    return;
-	}
-        ctxt->txturlTab = (xmlURL *) xmlRealloc(ctxt->txturlTab,
-	             ctxt->txtMax * sizeof(ctxt->txturlTab[0]));
-        if (ctxt->txturlTab == NULL) {
-	    xmlXIncludeErrMemory(ctxt, NULL, "processing text");
-	    return;
-	}
-    }
-    ctxt->txtTab[ctxt->txtNr] = xmlStrdup(txt);
-    ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
-    ctxt->txtNr++;
+xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc) {
+    xmlDocPtr oldDoc;
+    xmlXIncludeRefPtr *oldIncTab;
+    int oldIncMax, oldIncNr, oldIsStream;
+    int i;
+
+    oldDoc = ctxt->doc;
+    oldIncMax = ctxt->incMax;
+    oldIncNr = ctxt->incNr;
+    oldIncTab = ctxt->incTab;
+    oldIsStream = ctxt->isStream;
+    ctxt->doc = doc;
+    ctxt->incMax = 0;
+    ctxt->incNr = 0;
+    ctxt->incTab = NULL;
+    ctxt->isStream = 0;
+
+    xmlXIncludeDoProcess(ctxt, xmlDocGetRootElement(doc));
+
+    if (ctxt->incTab != NULL) {
+        for (i = 0; i < ctxt->incNr; i++)
+            xmlXIncludeFreeRef(ctxt->incTab[i]);
+        xmlFree(ctxt->incTab);
+    }
+
+    ctxt->doc = oldDoc;
+    ctxt->incMax = oldIncMax;
+    ctxt->incNr = oldIncNr;
+    ctxt->incTab = oldIncTab;
+    ctxt->isStream = oldIsStream;
 }
 
 /************************************************************************
@@ -815,70 +612,175 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *txt,
  *									*
  ************************************************************************/
 
-static xmlNodePtr
-xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
-	                xmlDocPtr source, xmlNodePtr elem);
+static void
+xmlXIncludeBaseFixup(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur, xmlNodePtr copy,
+                     const xmlChar *targetBase) {
+    xmlChar *base = NULL;
+    xmlChar *relBase = NULL;
+    xmlNs ns;
+    int res;
+
+    if (cur->type != XML_ELEMENT_NODE)
+        return;
+
+    if (xmlNodeGetBaseSafe(cur->doc, cur, &base) < 0)
+        xmlXIncludeErrMemory(ctxt);
+
+    if ((base != NULL) && !xmlStrEqual(base, targetBase)) {
+        if (xmlBuildRelativeURISafe(base, targetBase, &relBase) < 0) {
+            xmlXIncludeErrMemory(ctxt);
+            goto done;
+        }
+        if (relBase == NULL) {
+            xmlXIncludeErr(ctxt, cur,
+                    XML_XINCLUDE_HREF_URI,
+                    "Building relative URI failed: %s\n",
+                    base);
+            goto done;
+        }
+
+        /*
+         * If the new base doesn't contain a slash, it can be omitted.
+         */
+        if (xmlStrchr(relBase, '/') != NULL) {
+            res = xmlNodeSetBase(copy, relBase);
+            if (res < 0)
+                xmlXIncludeErrMemory(ctxt);
+            goto done;
+        }
+    }
+
+    /*
+     * Delete existing xml:base if bases are equal
+     */
+    memset(&ns, 0, sizeof(ns));
+    ns.href = XML_XML_NAMESPACE;
+    xmlUnsetNsProp(copy, &ns, BAD_CAST "base");
+
+done:
+    xmlFree(base);
+    xmlFree(relBase);
+}
 
 /**
  * xmlXIncludeCopyNode:
  * @ctxt:  the XInclude context
- * @target:  the document target
- * @source:  the document source
  * @elem:  the element
+ * @copyChildren:  copy children instead of node if true
+ *
+ * Make a copy of the node while expanding nested XIncludes.
  *
- * Make a copy of the node while preserving the XInclude semantic
- * of the Infoset copy
+ * Returns a node list, not a single node.
  */
 static xmlNodePtr
-xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
-	            xmlDocPtr source, xmlNodePtr elem) {
+xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem,
+                    int copyChildren, const xmlChar *targetBase) {
     xmlNodePtr result = NULL;
+    xmlNodePtr insertParent = NULL;
+    xmlNodePtr insertLast = NULL;
+    xmlNodePtr cur;
+    xmlNodePtr item;
+    int depth = 0;
 
-    if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
-	(elem == NULL))
-	return(NULL);
-    if (elem->type == XML_DTD_NODE)
-	return(NULL);
-    if (elem->type == XML_DOCUMENT_NODE)
-	result = xmlXIncludeCopyNodeList(ctxt, target, source, elem->children);
-    else
-        result = xmlDocCopyNode(elem, target, 1);
-    return(result);
-}
+    if (copyChildren) {
+        cur = elem->children;
+        if (cur == NULL)
+            return(NULL);
+    } else {
+        cur = elem;
+    }
 
-/**
- * xmlXIncludeCopyNodeList:
- * @ctxt:  the XInclude context
- * @target:  the document target
- * @source:  the document source
- * @elem:  the element list
- *
- * Make a copy of the node list while preserving the XInclude semantic
- * of the Infoset copy
- */
-static xmlNodePtr
-xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
-	                xmlDocPtr source, xmlNodePtr elem) {
-    xmlNodePtr cur, res, result = NULL, last = NULL;
+    while (1) {
+        xmlNodePtr copy = NULL;
+        int recurse = 0;
 
-    if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
-	(elem == NULL))
-	return(NULL);
-    cur = elem;
-    while (cur != NULL) {
-	res = xmlXIncludeCopyNode(ctxt, target, source, cur);
-	if (res != NULL) {
-	    if (result == NULL) {
-		result = last = res;
-	    } else {
-		last->next = res;
-		res->prev = last;
-		last = res;
-	    }
-	}
-	cur = cur->next;
+        if ((cur->type == XML_DOCUMENT_NODE) ||
+            (cur->type == XML_DTD_NODE)) {
+            ;
+        } else if ((cur->type == XML_ELEMENT_NODE) &&
+                   (cur->ns != NULL) &&
+                   (xmlStrEqual(cur->name, XINCLUDE_NODE)) &&
+                   ((xmlStrEqual(cur->ns->href, XINCLUDE_NS)) ||
+                    (xmlStrEqual(cur->ns->href, XINCLUDE_OLD_NS)))) {
+            xmlXIncludeRefPtr ref = xmlXIncludeExpandNode(ctxt, cur);
+
+            if (ref == NULL)
+                goto error;
+            /*
+             * TODO: Insert XML_XINCLUDE_START and XML_XINCLUDE_END nodes
+             */
+            for (item = ref->inc; item != NULL; item = item->next) {
+                copy = xmlStaticCopyNode(item, ctxt->doc, insertParent, 1);
+                if (copy == NULL) {
+                    xmlXIncludeErrMemory(ctxt);
+                    goto error;
+                }
+
+                if (result == NULL)
+                    result = copy;
+                if (insertLast != NULL) {
+                    insertLast->next = copy;
+                    copy->prev = insertLast;
+                } else if (insertParent != NULL) {
+                    insertParent->children = copy;
+                }
+                insertLast = copy;
+
+                if ((depth == 0) && (targetBase != NULL))
+                    xmlXIncludeBaseFixup(ctxt, item, copy, targetBase);
+            }
+        } else {
+            copy = xmlStaticCopyNode(cur, ctxt->doc, insertParent, 2);
+            if (copy == NULL) {
+                xmlXIncludeErrMemory(ctxt);
+                goto error;
+            }
+
+            if (result == NULL)
+                result = copy;
+            if (insertLast != NULL) {
+                insertLast->next = copy;
+                copy->prev = insertLast;
+            } else if (insertParent != NULL) {
+                insertParent->children = copy;
+            }
+            insertLast = copy;
+
+            if ((depth == 0) && (targetBase != NULL))
+                xmlXIncludeBaseFixup(ctxt, cur, copy, targetBase);
+
+            recurse = (cur->type != XML_ENTITY_REF_NODE) &&
+                      (cur->children != NULL);
+        }
+
+        if (recurse) {
+            cur = cur->children;
+            insertParent = insertLast;
+            insertLast = NULL;
+            depth += 1;
+            continue;
+        }
+
+        if (cur == elem)
+            return(result);
+
+        while (cur->next == NULL) {
+            if (insertParent != NULL)
+                insertParent->last = insertLast;
+            cur = cur->parent;
+            if (cur == elem)
+                return(result);
+            insertLast = insertParent;
+            insertParent = insertParent->parent;
+            depth -= 1;
+        }
+
+        cur = cur->next;
     }
-    return(result);
+
+error:
+    xmlFreeNodeList(result);
+    return(NULL);
 }
 
 #ifdef LIBXML_XPTR_LOCS_ENABLED
@@ -913,8 +815,6 @@ xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level); /* in xpointer.c */
 /**
  * xmlXIncludeCopyRange:
  * @ctxt:  the XInclude context
- * @target:  the document target
- * @source:  the document source
  * @obj:  the XPointer result from the evaluation.
  *
  * Build a node list tree copy of the XPointer result.
@@ -923,8 +823,7 @@ xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level); /* in xpointer.c */
  *         The caller has to free the node tree.
  */
 static xmlNodePtr
-xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
-	                xmlDocPtr source, xmlXPathObjectPtr range) {
+xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr range) {
     /* pointers to generated nodes */
     xmlNodePtr list = NULL, last = NULL, listParent = NULL;
     xmlNodePtr tmp, tmp2;
@@ -933,8 +832,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
     int index1, index2;
     int level = 0, lastLevel = 0, endLevel = 0, endFlag = 0;
 
-    if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
-	(range == NULL))
+    if ((ctxt == NULL) || (range == NULL))
 	return(NULL);
     if (range->type != XPATH_RANGE)
 	return(NULL);
@@ -944,7 +842,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 	return(NULL);
     end = range->user2;
     if (end == NULL)
-	return(xmlDocCopyNode(start, target, 1));
+	return(xmlDocCopyNode(start, ctxt->doc, 1));
     if (end->type == XML_NAMESPACE_DECL)
         return(NULL);
 
@@ -966,7 +864,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 	if (level < 0) {
 	    while (level < 0) {
 	        /* copy must include namespaces and properties */
-	        tmp2 = xmlDocCopyNode(listParent, target, 2);
+	        tmp2 = xmlDocCopyNode(listParent, ctxt->doc, 2);
 	        xmlAddChild(tmp2, list);
 	        list = tmp2;
 	        listParent = listParent->parent;
@@ -988,7 +886,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 		int len;
 
 		if (content == NULL) {
-		    tmp = xmlNewDocTextLen(target, NULL, 0);
+		    tmp = xmlNewDocTextLen(ctxt->doc, NULL, 0);
 		} else {
 		    len = index2;
 		    if ((cur == start) && (index1 > 1)) {
@@ -997,7 +895,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 		    } else {
 			len = index2;
 		    }
-		    tmp = xmlNewDocTextLen(target, content, len);
+		    tmp = xmlNewDocTextLen(ctxt->doc, content, len);
 		}
 		/* single sub text node selection */
 		if (list == NULL)
@@ -1012,7 +910,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 	        endLevel = level;	/* remember the level of the end node */
 		endFlag = 1;
 		/* last node - need to take care of properties + namespaces */
-		tmp = xmlDocCopyNode(cur, target, 2);
+		tmp = xmlDocCopyNode(cur, ctxt->doc, 2);
 		if (list == NULL) {
 		    list = tmp;
 		    listParent = cur->parent;
@@ -1048,13 +946,13 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 		const xmlChar *content = cur->content;
 
 		if (content == NULL) {
-		    tmp = xmlNewDocTextLen(target, NULL, 0);
+		    tmp = xmlNewDocTextLen(ctxt->doc, NULL, 0);
 		} else {
 		    if (index1 > 1) {
 			content += (index1 - 1);
 			index1 = 0;
 		    }
-		    tmp = xmlNewDocText(target, content);
+		    tmp = xmlNewDocText(ctxt->doc, content);
 		}
 		last = list = tmp;
 		listParent = cur->parent;
@@ -1063,7 +961,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 		 * start of the range - need to take care of
 		 * properties and namespaces
 		 */
-		tmp = xmlDocCopyNode(cur, target, 2);
+		tmp = xmlDocCopyNode(cur, ctxt->doc, 2);
 		list = last = tmp;
 		listParent = cur->parent;
 		if (index1 > 1) {	/* Do we need to position? */
@@ -1100,7 +998,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 		     * Middle of the range - need to take care of
 		     * properties and namespaces
 		     */
-		    tmp = xmlDocCopyNode(cur, target, 2);
+		    tmp = xmlDocCopyNode(cur, ctxt->doc, 2);
 		    break;
 	    }
 	    if (tmp != NULL) {
@@ -1123,11 +1021,10 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 }
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
 
+#ifdef LIBXML_XPTR_ENABLED
 /**
- * xmlXIncludeBuildNodeList:
+ * xmlXIncludeCopyXPointer:
  * @ctxt:  the XInclude context
- * @target:  the document target
- * @source:  the document source
  * @obj:  the XPointer result from the evaluation.
  *
  * Build a node list tree copy of the XPointer result.
@@ -1137,86 +1034,69 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
  *         the caller has to free the node tree.
  */
 static xmlNodePtr
-xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
-	                xmlDocPtr source, xmlXPathObjectPtr obj) {
-    xmlNodePtr list = NULL, last = NULL;
+xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr obj,
+                        const xmlChar *targetBase) {
+    xmlNodePtr list = NULL, last = NULL, copy;
     int i;
 
-    if (source == NULL)
-	source = ctxt->doc;
-    if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
-	(obj == NULL))
+    if ((ctxt == NULL) || (obj == NULL))
 	return(NULL);
     switch (obj->type) {
         case XPATH_NODESET: {
 	    xmlNodeSetPtr set = obj->nodesetval;
 	    if (set == NULL)
-		return(NULL);
+		break;
 	    for (i = 0;i < set->nodeNr;i++) {
+                xmlNodePtr node;
+
 		if (set->nodeTab[i] == NULL)
 		    continue;
 		switch (set->nodeTab[i]->type) {
-		    case XML_TEXT_NODE:
+		    case XML_DOCUMENT_NODE:
+		    case XML_HTML_DOCUMENT_NODE:
+                        node = xmlDocGetRootElement(
+                                (xmlDocPtr) set->nodeTab[i]);
+                        if (node == NULL) {
+                            xmlXIncludeErr(ctxt, set->nodeTab[i],
+                                           XML_ERR_INTERNAL_ERROR,
+                                          "document without root\n", NULL);
+                            continue;
+                        }
+                        break;
+                    case XML_TEXT_NODE:
 		    case XML_CDATA_SECTION_NODE:
 		    case XML_ELEMENT_NODE:
-		    case XML_ENTITY_REF_NODE:
-		    case XML_ENTITY_NODE:
 		    case XML_PI_NODE:
 		    case XML_COMMENT_NODE:
-		    case XML_DOCUMENT_NODE:
-		    case XML_HTML_DOCUMENT_NODE:
-		    case XML_XINCLUDE_END:
+                        node = set->nodeTab[i];
 			break;
-		    case XML_XINCLUDE_START: {
-	                xmlNodePtr tmp, cur = set->nodeTab[i];
-
-			cur = cur->next;
-			while (cur != NULL) {
-			    switch(cur->type) {
-				case XML_TEXT_NODE:
-				case XML_CDATA_SECTION_NODE:
-				case XML_ELEMENT_NODE:
-				case XML_ENTITY_REF_NODE:
-				case XML_ENTITY_NODE:
-				case XML_PI_NODE:
-				case XML_COMMENT_NODE:
-				    tmp = xmlXIncludeCopyNode(ctxt, target,
-							      source, cur);
-				    if (last == NULL) {
-					list = last = tmp;
-				    } else {
-					last = xmlAddNextSibling(last, tmp);
-				    }
-				    cur = cur->next;
-				    continue;
-				default:
-				    break;
-			    }
-			    break;
-			}
-			continue;
-		    }
-		    case XML_ATTRIBUTE_NODE:
-		    case XML_NAMESPACE_DECL:
-		    case XML_DOCUMENT_TYPE_NODE:
-		    case XML_DOCUMENT_FRAG_NODE:
-		    case XML_NOTATION_NODE:
-		    case XML_DTD_NODE:
-		    case XML_ELEMENT_DECL:
-		    case XML_ATTRIBUTE_DECL:
-		    case XML_ENTITY_DECL:
+                    default:
+                        xmlXIncludeErr(ctxt, set->nodeTab[i],
+                                       XML_XINCLUDE_XPTR_RESULT,
+                                       "invalid node type in XPtr result\n",
+                                       NULL);
 			continue; /* for */
 		}
-		if (last == NULL)
-		    list = last = xmlXIncludeCopyNode(ctxt, target, source,
-			                              set->nodeTab[i]);
-		else {
-		    xmlAddNextSibling(last,
-			    xmlXIncludeCopyNode(ctxt, target, source,
-				                set->nodeTab[i]));
-		    if (last->next != NULL)
-			last = last->next;
+                /*
+                 * OPTIMIZE TODO: External documents should already be
+                 * expanded, so xmlDocCopyNode should work as well.
+                 * xmlXIncludeCopyNode is only required for the initial
+                 * document.
+                 */
+		copy = xmlXIncludeCopyNode(ctxt, node, 0, targetBase);
+                if (copy == NULL) {
+                    xmlFreeNodeList(list);
+                    return(NULL);
+                }
+		if (last == NULL) {
+                    list = copy;
+                } else {
+                    while (last->next != NULL)
+                        last = last->next;
+                    copy->prev = last;
+                    last->next = copy;
 		}
+                last = copy;
 	    }
 	    break;
 	}
@@ -1227,12 +1107,13 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 		return(NULL);
 	    for (i = 0;i < set->locNr;i++) {
 		if (last == NULL)
-		    list = last = xmlXIncludeCopyXPointer(ctxt, target, source,
-			                                  set->locTab[i]);
+		    list = last = xmlXIncludeCopyXPointer(ctxt,
+			                                  set->locTab[i],
+                                                          targetBase);
 		else
 		    xmlAddNextSibling(last,
-			    xmlXIncludeCopyXPointer(ctxt, target, source,
-				                    set->locTab[i]));
+			    xmlXIncludeCopyXPointer(ctxt, set->locTab[i],
+                                                    targetBase));
 		if (last != NULL) {
 		    while (last->next != NULL)
 			last = last->next;
@@ -1241,7 +1122,7 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 	    break;
 	}
 	case XPATH_RANGE:
-	    return(xmlXIncludeCopyRange(ctxt, target, source, obj));
+	    return(xmlXIncludeCopyRange(ctxt, obj));
 	case XPATH_POINT:
 	    /* points are ignored in XInclude */
 	    break;
@@ -1251,6 +1132,8 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
     }
     return(list);
 }
+#endif
+
 /************************************************************************
  *									*
  *			XInclude I/O handling				*
@@ -1268,7 +1151,7 @@ struct _xmlXIncludeMergeData {
  * xmlXIncludeMergeOneEntity:
  * @ent: the entity
  * @doc:  the including doc
- * @nr: the entity name
+ * @name: the entity name
  *
  * Implements the merge of one entity
  */
@@ -1297,32 +1180,36 @@ xmlXIncludeMergeEntity(void *payload, void *vdata,
         case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
 	    break;
     }
-    ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID,
-			  ent->SystemID, ent->content);
-    if (ret != NULL) {
-	if (ent->URI != NULL)
+    prev = xmlGetDocEntity(doc, ent->name);
+    if (prev == NULL) {
+        ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID,
+                              ent->SystemID, ent->content);
+        if (ret == NULL) {
+            xmlXIncludeErrMemory(ctxt);
+            return;
+        }
+	if (ent->URI != NULL) {
 	    ret->URI = xmlStrdup(ent->URI);
+            if (ret->URI == 0)
+                xmlXIncludeErrMemory(ctxt);
+        }
     } else {
-	prev = xmlGetDocEntity(doc, ent->name);
-	if (prev != NULL) {
-	    if (ent->etype != prev->etype)
-		goto error;
-
-	    if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) {
-		if (!xmlStrEqual(ent->SystemID, prev->SystemID))
-		    goto error;
-	    } else if ((ent->ExternalID != NULL) &&
-		       (prev->ExternalID != NULL)) {
-		if (!xmlStrEqual(ent->ExternalID, prev->ExternalID))
-		    goto error;
-	    } else if ((ent->content != NULL) && (prev->content != NULL)) {
-		if (!xmlStrEqual(ent->content, prev->content))
-		    goto error;
-	    } else {
-		goto error;
-	    }
-
-	}
+        if (ent->etype != prev->etype)
+            goto error;
+
+        if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) {
+            if (!xmlStrEqual(ent->SystemID, prev->SystemID))
+                goto error;
+        } else if ((ent->ExternalID != NULL) &&
+                   (prev->ExternalID != NULL)) {
+            if (!xmlStrEqual(ent->ExternalID, prev->ExternalID))
+                goto error;
+        } else if ((ent->content != NULL) && (prev->content != NULL)) {
+            if (!xmlStrEqual(ent->content, prev->content))
+                goto error;
+        } else {
+            goto error;
+        }
     }
     return;
 error:
@@ -1369,8 +1256,10 @@ xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
 	if (cur == NULL)
 	    return(-1);
         target = xmlCreateIntSubset(doc, cur->name, NULL, NULL);
-	if (target == NULL)
+	if (target == NULL) {
+            xmlXIncludeErrMemory(ctxt);
 	    return(-1);
+        }
     }
 
     source = from->intSubset;
@@ -1406,81 +1295,48 @@ xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
  * xmlXIncludeLoadDoc:
  * @ctxt:  the XInclude context
  * @url:  the associated URL
- * @nr:  the xinclude node number
+ * @ref:  an XMLXincludeRefPtr
  *
  * Load the document, and store the result in the XInclude context
  *
  * Returns 0 in case of success, -1 in case of failure
  */
 static int
-xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
+xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) {
+    xmlXIncludeDocPtr cache;
     xmlDocPtr doc;
-    xmlURIPtr uri;
-    xmlChar *URL;
-    xmlChar *fragment = NULL;
+    const xmlChar *url = ref->URI;
+    const xmlChar *fragment = ref->fragment;
     int i = 0;
+    int ret = -1;
+    int cacheNr;
 #ifdef LIBXML_XPTR_ENABLED
     int saveFlags;
 #endif
 
-#ifdef DEBUG_XINCLUDE
-    xmlGenericError(xmlGenericErrorContext, "Loading doc %s:%d\n", url, nr);
-#endif
-    /*
-     * Check the URL and remove any fragment identifier
-     */
-    uri = xmlParseURI((const char *)url);
-    if (uri == NULL) {
-	xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	               XML_XINCLUDE_HREF_URI,
-		       "invalid value URI %s\n", url);
-	return(-1);
-    }
-    if (uri->fragment != NULL) {
-	fragment = (xmlChar *) uri->fragment;
-	uri->fragment = NULL;
-    }
-    if ((ctxt->incTab != NULL) && (ctxt->incTab[nr] != NULL) &&
-        (ctxt->incTab[nr]->fragment != NULL)) {
-	if (fragment != NULL) xmlFree(fragment);
-	fragment = xmlStrdup(ctxt->incTab[nr]->fragment);
-    }
-    URL = xmlSaveUri(uri);
-    xmlFreeURI(uri);
-    if (URL == NULL) {
-        if (ctxt->incTab != NULL)
-	    xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-			   XML_XINCLUDE_HREF_URI,
-			   "invalid value URI %s\n", url);
-	else
-	    xmlXIncludeErr(ctxt, NULL,
-			   XML_XINCLUDE_HREF_URI,
-			   "invalid value URI %s\n", url);
-	if (fragment != NULL)
-	    xmlFree(fragment);
-	return(-1);
-    }
-
     /*
      * Handling of references to the local document are done
      * directly through ctxt->doc.
      */
-    if ((URL[0] == 0) || (URL[0] == '#') ||
-	((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) {
+    if ((url[0] == 0) || (url[0] == '#') ||
+	((ctxt->doc != NULL) && (xmlStrEqual(url, ctxt->doc->URL)))) {
 	doc = ctxt->doc;
         goto loaded;
     }
 
     /*
-     * Prevent reloading twice the document.
+     * Prevent reloading the document twice.
      */
-    for (i = 0; i < ctxt->incNr; i++) {
-	if ((xmlStrEqual(URL, ctxt->incTab[i]->URI)) &&
-	    (ctxt->incTab[i]->doc != NULL)) {
-	    doc = ctxt->incTab[i]->doc;
-#ifdef DEBUG_XINCLUDE
-	    printf("Already loaded %s\n", URL);
-#endif
+    for (i = 0; i < ctxt->urlNr; i++) {
+	if (xmlStrEqual(url, ctxt->urlTab[i].url)) {
+            if (ctxt->urlTab[i].expanding) {
+                xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_RECURSION,
+                               "inclusion loop detected\n", NULL);
+                goto error;
+            }
+	    doc = ctxt->urlTab[i].doc;
+            if (doc == NULL)
+                goto error;
 	    goto loaded;
 	}
     }
@@ -1488,9 +1344,6 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
     /*
      * Load it.
      */
-#ifdef DEBUG_XINCLUDE
-    printf("loading %s\n", URL);
-#endif
 #ifdef LIBXML_XPTR_ENABLED
     /*
      * If this is an XPointer evaluation, we want to assure that
@@ -1503,36 +1356,50 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
     }
 #endif
 
-    doc = xmlXIncludeParseFile(ctxt, (const char *)URL);
+    doc = xmlXIncludeParseFile(ctxt, (const char *)url);
 #ifdef LIBXML_XPTR_ENABLED
     ctxt->parseFlags = saveFlags;
 #endif
-    if (doc == NULL) {
-	xmlFree(URL);
-	if (fragment != NULL)
-	    xmlFree(fragment);
-	return(-1);
+
+    /* Also cache NULL docs */
+    if (ctxt->urlNr >= ctxt->urlMax) {
+        xmlXIncludeDoc *tmp;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+        size_t newSize = ctxt->urlMax ? ctxt->urlMax * 2 : 1;
+#else
+        size_t newSize = ctxt->urlMax ? ctxt->urlMax * 2 : 8;
+#endif
+
+        tmp = xmlRealloc(ctxt->urlTab, sizeof(xmlXIncludeDoc) * newSize);
+        if (tmp == NULL) {
+            xmlXIncludeErrMemory(ctxt);
+            xmlFreeDoc(doc);
+            goto error;
+        }
+        ctxt->urlMax = newSize;
+        ctxt->urlTab = tmp;
     }
-    ctxt->incTab[nr]->doc = doc;
+    cache = &ctxt->urlTab[ctxt->urlNr];
+    cache->doc = doc;
+    cache->url = xmlStrdup(url);
+    if (cache->url == NULL) {
+        xmlXIncludeErrMemory(ctxt);
+        xmlFreeDoc(doc);
+        goto error;
+    }
+    cache->expanding = 0;
+    cacheNr = ctxt->urlNr++;
+
+    if (doc == NULL)
+        goto error;
     /*
      * It's possible that the requested URL has been mapped to a
      * completely different location (e.g. through a catalog entry).
      * To check for this, we compare the URL with that of the doc
      * and change it if they disagree (bug 146988).
-     */
-   if (!xmlStrEqual(URL, doc->URL)) {
-       xmlFree(URL);
-       URL = xmlStrdup(doc->URL);
-   }
-    for (i = nr + 1; i < ctxt->incNr; i++) {
-	if (xmlStrEqual(URL, ctxt->incTab[i]->URI)) {
-	    ctxt->incTab[nr]->count++;
-#ifdef DEBUG_XINCLUDE
-	    printf("Increasing %s count since reused\n", URL);
-#endif
-            break;
-	}
-    }
+     */
+    if ((doc->URL != NULL) && (!xmlStrEqual(url, doc->URL)))
+        url = doc->URL;
 
     /*
      * Make sure we have all entities fixed up
@@ -1552,15 +1419,31 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
 	doc->extSubset = NULL;
     }
      */
-    xmlXIncludeRecurseDoc(ctxt, doc, URL);
+    cache->expanding = 1;
+    xmlXIncludeRecurseDoc(ctxt, doc);
+    /* urlTab might be reallocated. */
+    cache = &ctxt->urlTab[cacheNr];
+    cache->expanding = 0;
 
 loaded:
     if (fragment == NULL) {
-	/*
-	 * Add the top children list as the replacement copy.
-	 */
-	ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
-		                                        doc, doc->children);
+        xmlNodePtr root;
+
+        root = xmlDocGetRootElement(doc);
+        if (root == NULL) {
+            xmlXIncludeErr(ctxt, ref->elem, XML_ERR_INTERNAL_ERROR,
+                           "document without root\n", NULL);
+            goto error;
+        }
+
+        ref->inc = xmlDocCopyNode(root, ctxt->doc, 1);
+        if (ref->inc == NULL) {
+            xmlXIncludeErrMemory(ctxt);
+            goto error;
+        }
+
+        if (ref->base != NULL)
+            xmlXIncludeBaseFixup(ctxt, root, ref->inc, ref->base);
     }
 #ifdef LIBXML_XPTR_ENABLED
     else {
@@ -1569,29 +1452,42 @@ loaded:
 	 * as the replacement copy.
 	 */
 	xmlXPathObjectPtr xptr;
-	xmlXPathContextPtr xptrctxt;
 	xmlNodeSetPtr set;
 
-	xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
-	if (xptrctxt == NULL) {
-	    xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	                   XML_XINCLUDE_XPTR_FAILED,
-			   "could not create XPointer context\n", NULL);
-	    xmlFree(URL);
-	    xmlFree(fragment);
-	    return(-1);
-	}
-	xptr = xmlXPtrEval(fragment, xptrctxt);
-	if (xptr == NULL) {
-	    xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	                   XML_XINCLUDE_XPTR_FAILED,
-			   "XPointer evaluation failed: #%s\n",
-			   fragment);
-	    xmlXPathFreeContext(xptrctxt);
-	    xmlFree(URL);
-	    xmlFree(fragment);
-	    return(-1);
+        if (ctxt->isStream && doc == ctxt->doc) {
+	    xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_XPTR_FAILED,
+			   "XPointer expressions not allowed in streaming"
+                           " mode\n", NULL);
+            goto error;
+        }
+
+        if (ctxt->xpctxt == NULL) {
+            ctxt->xpctxt = xmlXPtrNewContext(doc, NULL, NULL);
+            if (ctxt->xpctxt == NULL) {
+                xmlXIncludeErrMemory(ctxt);
+                goto error;
+            }
+            if (ctxt->errorHandler != NULL)
+                xmlXPathSetErrorHandler(ctxt->xpctxt, ctxt->errorHandler,
+                                        ctxt->errorCtxt);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+            ctxt->xpctxt->opLimit = 100000;
+#endif
+        } else {
+            ctxt->xpctxt->doc = doc;
+        }
+	xptr = xmlXPtrEval(fragment, ctxt->xpctxt);
+	if (ctxt->xpctxt->lastError.code != XML_ERR_OK) {
+            if (ctxt->xpctxt->lastError.code == XML_ERR_NO_MEMORY)
+                xmlXIncludeErrMemory(ctxt);
+            else
+                xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_XPTR_FAILED,
+                               "XPointer evaluation failed: #%s\n",
+                               fragment);
+            goto error;
 	}
+        if (xptr == NULL)
+            goto done;
 	switch (xptr->type) {
 	    case XPATH_UNDEFINED:
 	    case XPATH_BOOLEAN:
@@ -1602,24 +1498,13 @@ loaded:
 #endif
 	    case XPATH_USERS:
 	    case XPATH_XSLT_TREE:
-		xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-		               XML_XINCLUDE_XPTR_RESULT,
+		xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_XPTR_RESULT,
 			       "XPointer is not a range: #%s\n",
 			       fragment);
                 xmlXPathFreeObject(xptr);
-		xmlXPathFreeContext(xptrctxt);
-		xmlFree(URL);
-		xmlFree(fragment);
-		return(-1);
+                goto error;
 	    case XPATH_NODESET:
-	        if ((xptr->nodesetval == NULL) ||
-		    (xptr->nodesetval->nodeNr <= 0)) {
-                    xmlXPathFreeObject(xptr);
-		    xmlXPathFreeContext(xptrctxt);
-		    xmlFree(URL);
-		    xmlFree(fragment);
-		    return(-1);
-		}
+                break;
 
 #ifdef LIBXML_XPTR_LOCS_ENABLED
 	    case XPATH_RANGE:
@@ -1645,14 +1530,14 @@ loaded:
 			continue;
 
 		    case XML_ATTRIBUTE_NODE:
-			xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
+			xmlXIncludeErr(ctxt, ref->elem,
 			               XML_XINCLUDE_XPTR_RESULT,
 				       "XPointer selects an attribute: #%s\n",
 				       fragment);
 			set->nodeTab[i] = NULL;
 			continue;
 		    case XML_NAMESPACE_DECL:
-			xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
+			xmlXIncludeErr(ctxt, ref->elem,
 			               XML_XINCLUDE_XPTR_RESULT,
 				       "XPointer selects a namespace: #%s\n",
 				       fragment);
@@ -1667,7 +1552,7 @@ loaded:
 		    case XML_ENTITY_DECL:
 		    case XML_XINCLUDE_START:
 		    case XML_XINCLUDE_END:
-			xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
+			xmlXIncludeErr(ctxt, ref->elem,
 			               XML_XINCLUDE_XPTR_RESULT,
 				   "XPointer selects unexpected nodes: #%s\n",
 				       fragment);
@@ -1677,285 +1562,212 @@ loaded:
 		}
 	    }
 	}
-        ctxt->incTab[nr]->inc =
-            xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
+        ref->inc = xmlXIncludeCopyXPointer(ctxt, xptr, ref->base);
         xmlXPathFreeObject(xptr);
-	xmlXPathFreeContext(xptrctxt);
-	xmlFree(fragment);
     }
 #endif
 
-    /*
-     * Do the xml:base fixup if needed
-     */
-    if ((doc != NULL) && (URL != NULL) &&
-        (!(ctxt->parseFlags & XML_PARSE_NOBASEFIX)) &&
-	(!(doc->parseFlags & XML_PARSE_NOBASEFIX))) {
-	xmlNodePtr node;
-	xmlChar *base;
-	xmlChar *curBase;
+done:
+    ret = 0;
 
-	/*
-	 * The base is only adjusted if "necessary", i.e. if the xinclude node
-	 * has a base specified, or the URL is relative
-	 */
-	base = xmlGetNsProp(ctxt->incTab[nr]->ref, BAD_CAST "base",
-			XML_XML_NAMESPACE);
-	if (base == NULL) {
-	    /*
-	     * No xml:base on the xinclude node, so we check whether the
-	     * URI base is different than (relative to) the context base
-	     */
-	    curBase = xmlBuildRelativeURI(URL, ctxt->base);
-	    if (curBase == NULL) {	/* Error return */
-	        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	               XML_XINCLUDE_HREF_URI,
-		       "trying to build relative URI from %s\n", URL);
-	    } else {
-		/* If the URI doesn't contain a slash, it's not relative */
-	        if (!xmlStrchr(curBase, (xmlChar) '/'))
-		    xmlFree(curBase);
-		else
-		    base = curBase;
-	    }
-	}
-	if (base != NULL) {	/* Adjustment may be needed */
-	    node = ctxt->incTab[nr]->inc;
-	    while (node != NULL) {
-		/* Only work on element nodes */
-		if (node->type == XML_ELEMENT_NODE) {
-		    curBase = xmlNodeGetBase(node->doc, node);
-		    /* If no current base, set it */
-		    if (curBase == NULL) {
-			xmlNodeSetBase(node, base);
-		    } else {
-			/*
-			 * If the current base is the same as the
-			 * URL of the document, then reset it to be
-			 * the specified xml:base or the relative URI
-			 */
-			if (xmlStrEqual(curBase, node->doc->URL)) {
-			    xmlNodeSetBase(node, base);
-			} else {
-			    /*
-			     * If the element already has an xml:base
-			     * set, then relativise it if necessary
-			     */
-			    xmlChar *xmlBase;
-			    xmlBase = xmlGetNsProp(node,
-					    BAD_CAST "base",
-					    XML_XML_NAMESPACE);
-			    if (xmlBase != NULL) {
-				xmlChar *relBase;
-				relBase = xmlBuildURI(xmlBase, base);
-				if (relBase == NULL) { /* error */
-				    xmlXIncludeErr(ctxt,
-						ctxt->incTab[nr]->ref,
-						XML_XINCLUDE_HREF_URI,
-					"trying to rebuild base from %s\n",
-						xmlBase);
-				} else {
-				    xmlNodeSetBase(node, relBase);
-				    xmlFree(relBase);
-				}
-				xmlFree(xmlBase);
-			    }
-			}
-			xmlFree(curBase);
-		    }
-		}
-	        node = node->next;
-	    }
-	    xmlFree(base);
-	}
-    }
-    if ((nr < ctxt->incNr) && (ctxt->incTab[nr]->doc != NULL) &&
-	(ctxt->incTab[nr]->count <= 1)) {
-#ifdef DEBUG_XINCLUDE
-        printf("freeing %s\n", ctxt->incTab[nr]->doc->URL);
-#endif
-	xmlFreeDoc(ctxt->incTab[nr]->doc);
-	ctxt->incTab[nr]->doc = NULL;
-    }
-    xmlFree(URL);
-    return(0);
+error:
+    return(ret);
 }
 
 /**
  * xmlXIncludeLoadTxt:
  * @ctxt:  the XInclude context
- * @url:  the associated URL
- * @nr:  the xinclude node number
+ * @ref:  an XMLXincludeRefPtr
  *
  * Load the content, and store the result in the XInclude context
  *
  * Returns 0 in case of success, -1 in case of failure
  */
 static int
-xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
+xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) {
     xmlParserInputBufferPtr buf;
-    xmlNodePtr node;
-    xmlURIPtr uri;
-    xmlChar *URL;
+    xmlNodePtr node = NULL;
+    const xmlChar *url = ref->URI;
     int i;
+    int ret = -1;
     xmlChar *encoding = NULL;
-    xmlCharEncoding enc = (xmlCharEncoding) 0;
-    xmlParserCtxtPtr pctxt;
-    xmlParserInputPtr inputStream;
-    int xinclude_multibyte_fallback_used = 0;
-
-    /* Don't read from stdin. */
-    if (xmlStrcmp(url, BAD_CAST "-") == 0)
-        url = BAD_CAST "./-";
-
-    /*
-     * Check the URL and remove any fragment identifier
-     */
-    uri = xmlParseURI((const char *)url);
-    if (uri == NULL) {
-	xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
-	               "invalid value URI %s\n", url);
-	return(-1);
-    }
-    if (uri->fragment != NULL) {
-	xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_TEXT_FRAGMENT,
-	               "fragment identifier forbidden for text: %s\n",
-		       (const xmlChar *) uri->fragment);
-	xmlFreeURI(uri);
-	return(-1);
-    }
-    URL = xmlSaveUri(uri);
-    xmlFreeURI(uri);
-    if (URL == NULL) {
-	xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
-	               "invalid value URI %s\n", url);
-	return(-1);
-    }
+    xmlCharEncodingHandlerPtr handler = NULL;
+    xmlParserCtxtPtr pctxt = NULL;
+    xmlParserInputPtr inputStream = NULL;
+    int len;
+    int res;
+    const xmlChar *content;
 
     /*
      * Handling of references to the local document are done
      * directly through ctxt->doc.
      */
-    if (URL[0] == 0) {
-	xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	               XML_XINCLUDE_TEXT_DOCUMENT,
+    if (url[0] == 0) {
+	xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_TEXT_DOCUMENT,
 		       "text serialization of document not available\n", NULL);
-	xmlFree(URL);
-	return(-1);
+	goto error;
     }
 
     /*
-     * Prevent reloading twice the document.
+     * Prevent reloading the document twice.
      */
     for (i = 0; i < ctxt->txtNr; i++) {
-	if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
-            node = xmlNewDocText(ctxt->doc, ctxt->txtTab[i]);
+	if (xmlStrEqual(url, ctxt->txtTab[i].url)) {
+            node = xmlNewDocText(ctxt->doc, ctxt->txtTab[i].text);
+            if (node == NULL)
+                xmlXIncludeErrMemory(ctxt);
 	    goto loaded;
 	}
     }
+
     /*
      * Try to get the encoding if available
      */
-    if ((ctxt->incTab[nr] != NULL) && (ctxt->incTab[nr]->ref != NULL)) {
-	encoding = xmlGetProp(ctxt->incTab[nr]->ref, XINCLUDE_PARSE_ENCODING);
+    if (ref->elem != NULL) {
+	encoding = xmlXIncludeGetProp(ctxt, ref->elem, XINCLUDE_PARSE_ENCODING);
     }
     if (encoding != NULL) {
-	/*
-	 * TODO: we should not have to remap to the xmlCharEncoding
-	 *       predefined set, a better interface than
-	 *       xmlParserInputBufferCreateFilename should allow any
-	 *       encoding supported by iconv
-	 */
-        enc = xmlParseCharEncoding((const char *) encoding);
-	if (enc == XML_CHAR_ENCODING_ERROR) {
-	    xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	                   XML_XINCLUDE_UNKNOWN_ENCODING,
-			   "encoding %s not supported\n", encoding);
-	    xmlFree(encoding);
-	    xmlFree(URL);
-	    return(-1);
-	}
-	xmlFree(encoding);
+        res = xmlOpenCharEncodingHandler((const char *) encoding,
+                                         /* output */ 0, &handler);
+
+        if (res != 0) {
+            if (res == XML_ERR_NO_MEMORY) {
+                xmlXIncludeErrMemory(ctxt);
+            } else if (res == XML_ERR_UNSUPPORTED_ENCODING) {
+                xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_UNKNOWN_ENCODING,
+                               "encoding %s not supported\n", encoding);
+                goto error;
+            } else {
+                xmlXIncludeErr(ctxt, ref->elem, res,
+                               "unexpected error from iconv or ICU\n", NULL);
+                goto error;
+            }
+        }
     }
 
     /*
      * Load it.
      */
     pctxt = xmlNewParserCtxt();
-    inputStream = xmlLoadExternalEntity((const char*)URL, NULL, pctxt);
-    if(inputStream == NULL) {
-	xmlFreeParserCtxt(pctxt);
-	xmlFree(URL);
-	return(-1);
+    if (pctxt == NULL) {
+        xmlXIncludeErrMemory(ctxt);
+        goto error;
     }
-    buf = inputStream->buf;
-    if (buf == NULL) {
-	xmlFreeInputStream (inputStream);
-	xmlFreeParserCtxt(pctxt);
-	xmlFree(URL);
-	return(-1);
+    if (ctxt->errorHandler != NULL)
+        xmlCtxtSetErrorHandler(pctxt, ctxt->errorHandler, ctxt->errorCtxt);
+    inputStream = xmlLoadExternalEntity((const char*)url, NULL, pctxt);
+    if (inputStream == NULL) {
+        /*
+         * ENOENT only produces a warning which isn't reflected in errNo.
+         */
+        if (pctxt->errNo == XML_ERR_NO_MEMORY)
+            xmlXIncludeErrMemory(ctxt);
+        else if ((pctxt->errNo != XML_ERR_OK) &&
+                 (pctxt->errNo != XML_IO_ENOENT) &&
+                 (pctxt->errNo != XML_IO_UNKNOWN))
+            xmlXIncludeErr(ctxt, NULL, pctxt->errNo, "load error", NULL);
+	goto error;
     }
+    buf = inputStream->buf;
+    if (buf == NULL)
+	goto error;
     if (buf->encoder)
 	xmlCharEncCloseFunc(buf->encoder);
-    buf->encoder = xmlGetCharEncodingHandler(enc);
+    buf->encoder = handler;
+    handler = NULL;
+
     node = xmlNewDocText(ctxt->doc, NULL);
+    if (node == NULL) {
+        xmlXIncludeErrMemory(ctxt);
+	goto error;
+    }
 
     /*
      * Scan all chars from the resource and add the to the node
      */
-xinclude_multibyte_fallback:
-    while (xmlParserInputBufferRead(buf, 128) > 0) {
-	int len;
-	const xmlChar *content;
-
-	content = xmlBufContent(buf->buffer);
-	len = xmlBufLength(buf->buffer);
-	for (i = 0;i < len;) {
-	    int cur;
-	    int l;
-
-	    cur = xmlStringCurrentChar(NULL, &content[i], &l);
-	    if (!IS_CHAR(cur)) {
-		/* Handle split multibyte char at buffer boundary */
-		if (((len - i) < 4) && (!xinclude_multibyte_fallback_used)) {
-		    xinclude_multibyte_fallback_used = 1;
-		    xmlBufShrink(buf->buffer, i);
-		    goto xinclude_multibyte_fallback;
-		} else {
-		    xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-				   XML_XINCLUDE_INVALID_CHAR,
-				   "%s contains invalid char\n", URL);
-		    xmlFreeParserCtxt(pctxt);
-		    xmlFreeParserInputBuffer(buf);
-		    xmlFree(URL);
-		    return(-1);
-		}
-	    } else {
-		xinclude_multibyte_fallback_used = 0;
-		xmlNodeAddContentLen(node, &content[i], l);
-	    }
-	    i += l;
-	}
-	xmlBufShrink(buf->buffer, len);
+    do {
+        res = xmlParserInputBufferRead(buf, 4096);
+    } while (res > 0);
+    if (res < 0) {
+        if (buf->error == XML_ERR_NO_MEMORY)
+            xmlXIncludeErrMemory(ctxt);
+        else
+            xmlXIncludeErr(ctxt, NULL, buf->error, "read error", NULL);
+        goto error;
+    }
+
+    content = xmlBufContent(buf->buffer);
+    len = xmlBufLength(buf->buffer);
+    for (i = 0; i < len;) {
+        int cur;
+        int l;
+
+        l = len - i;
+        cur = xmlGetUTF8Char(&content[i], &l);
+        if ((cur < 0) || (!IS_CHAR(cur))) {
+            xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_INVALID_CHAR,
+                           "%s contains invalid char\n", url);
+            goto error;
+        }
+
+        i += l;
     }
-    xmlFreeParserCtxt(pctxt);
-    xmlXIncludeAddTxt(ctxt, node->content, URL);
-    xmlFreeInputStream(inputStream);
+
+    if (xmlNodeAddContentLen(node, content, len) < 0)
+        xmlXIncludeErrMemory(ctxt);
+
+    if (ctxt->txtNr >= ctxt->txtMax) {
+        xmlXIncludeTxt *tmp;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+        size_t newSize = ctxt->txtMax ? ctxt->txtMax * 2 : 1;
+#else
+        size_t newSize = ctxt->txtMax ? ctxt->txtMax * 2 : 8;
+#endif
+
+        tmp = xmlRealloc(ctxt->txtTab, sizeof(xmlXIncludeTxt) * newSize);
+        if (tmp == NULL) {
+            xmlXIncludeErrMemory(ctxt);
+	    goto error;
+        }
+        ctxt->txtMax = newSize;
+        ctxt->txtTab = tmp;
+    }
+    ctxt->txtTab[ctxt->txtNr].text = xmlStrdup(node->content);
+    if ((node->content != NULL) &&
+        (ctxt->txtTab[ctxt->txtNr].text == NULL)) {
+        xmlXIncludeErrMemory(ctxt);
+        goto error;
+    }
+    ctxt->txtTab[ctxt->txtNr].url = xmlStrdup(url);
+    if (ctxt->txtTab[ctxt->txtNr].url == NULL) {
+        xmlXIncludeErrMemory(ctxt);
+        xmlFree(ctxt->txtTab[ctxt->txtNr].text);
+        goto error;
+    }
+    ctxt->txtNr++;
 
 loaded:
     /*
      * Add the element as the replacement copy.
      */
-    ctxt->incTab[nr]->inc = node;
-    xmlFree(URL);
-    return(0);
+    ref->inc = node;
+    node = NULL;
+    ret = 0;
+
+error:
+    xmlFreeNode(node);
+    xmlFreeInputStream(inputStream);
+    xmlFreeParserCtxt(pctxt);
+    xmlCharEncCloseFunc(handler);
+    xmlFree(encoding);
+    return(ret);
 }
 
 /**
  * xmlXIncludeLoadFallback:
  * @ctxt:  the XInclude context
  * @fallback:  the fallback node
- * @nr:  the xinclude node number
+ * @ref:  an XMLXincludeRefPtr
  *
  * Load the content of the fallback node, and store the result
  * in the XInclude context
@@ -1963,10 +1775,10 @@ loaded:
  * Returns 0 in case of success, -1 in case of failure
  */
 static int
-xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
-    xmlXIncludeCtxtPtr newctxt;
+xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback,
+                        xmlXIncludeRefPtr ref) {
     int ret = 0;
-    int oldNbErrors = ctxt->nbErrors;
+    int oldNbErrors;
 
     if ((fallback == NULL) || (fallback->type == XML_NAMESPACE_DECL) ||
         (ctxt == NULL))
@@ -1976,29 +1788,14 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
 	 * It's possible that the fallback also has 'includes'
 	 * (Bug 129969), so we re-process the fallback just in case
 	 */
-	newctxt = xmlXIncludeNewContext(ctxt->doc);
-	if (newctxt == NULL)
-	    return (-1);
-	newctxt->_private = ctxt->_private;
-	newctxt->base = xmlStrdup(ctxt->base);	/* Inherit the base from the existing context */
-	xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
-        newctxt->incTotal = ctxt->incTotal;
-        if (xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback, 1) < 0)
-            ret = -1;
-        ctxt->incTotal = newctxt->incTotal;
+        oldNbErrors = ctxt->nbErrors;
+	ref->inc = xmlXIncludeCopyNode(ctxt, fallback, 1, ref->base);
 	if (ctxt->nbErrors > oldNbErrors)
 	    ret = -1;
-	xmlXIncludeFreeContext(newctxt);
-
-	ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
-	                                           fallback->children);
-        if (ctxt->incTab[nr]->inc == NULL)
-            ctxt->incTab[nr]->emptyFb = 1;
     } else {
-        ctxt->incTab[nr]->inc = NULL;
-	ctxt->incTab[nr]->emptyFb = 1;	/* flag empty callback */
+        ref->inc = NULL;
     }
-    ctxt->incTab[nr]->fallback = 1;
+    ref->fallback = 1;
     return(ret);
 }
 
@@ -2009,143 +1806,110 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
  ************************************************************************/
 
 /**
- * xmlXIncludePreProcessNode:
+ * xmlXIncludeExpandNode:
  * @ctxt: an XInclude context
  * @node: an XInclude node
  *
- * Implement the XInclude preprocessing, currently just adding the element
- * for further processing.
+ * If the XInclude node wasn't processed yet, create a new RefPtr,
+ * add it to ctxt->incTab and load the included items.
  *
- * Returns the result list or NULL in case of error
+ * Returns the new or existing xmlXIncludeRefPtr, or NULL in case of error.
  */
-static xmlNodePtr
-xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
-    xmlXIncludeAddNode(ctxt, node);
-    return(NULL);
+static xmlXIncludeRefPtr
+xmlXIncludeExpandNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
+    xmlXIncludeRefPtr ref;
+    int i;
+
+    if (ctxt->fatalErr)
+        return(NULL);
+    if (ctxt->depth >= XINCLUDE_MAX_DEPTH) {
+        xmlXIncludeErr(ctxt, node, XML_XINCLUDE_RECURSION,
+                       "maximum recursion depth exceeded\n", NULL);
+        ctxt->fatalErr = 1;
+        return(NULL);
+    }
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    /*
+     * The XInclude engine offers no protection against exponential
+     * expansion attacks similar to "billion laughs". Avoid timeouts by
+     * limiting the total number of replacements when fuzzing.
+     *
+     * Unfortuately, a single XInclude can already result in quadratic
+     * behavior:
+     *
+     *     <doc xmlns:xi="http://www.w3.org/2001/XInclude">
+     *       <xi:include xpointer="xpointer(//e)"/>
+     *       <e>
+     *         <e>
+     *           <e>
+     *             <!-- more nested elements -->
+     *           </e>
+     *         </e>
+     *       </e>
+     *     </doc>
+     */
+    if (ctxt->incTotal >= 20)
+        return(NULL);
+    ctxt->incTotal++;
+#endif
+
+    for (i = 0; i < ctxt->incNr; i++) {
+        if (ctxt->incTab[i]->elem == node) {
+            if (ctxt->incTab[i]->expanding) {
+                xmlXIncludeErr(ctxt, node, XML_XINCLUDE_RECURSION,
+                               "inclusion loop detected\n", NULL);
+                return(NULL);
+            }
+            return(ctxt->incTab[i]);
+        }
+    }
+
+    ref = xmlXIncludeAddNode(ctxt, node);
+    if (ref == NULL)
+        return(NULL);
+    ref->expanding = 1;
+    ctxt->depth++;
+    xmlXIncludeLoadNode(ctxt, ref);
+    ctxt->depth--;
+    ref->expanding = 0;
+
+    return(ref);
 }
 
 /**
  * xmlXIncludeLoadNode:
  * @ctxt: an XInclude context
- * @nr: the node number
+ * @ref: an xmlXIncludeRefPtr
  *
  * Find and load the infoset replacement for the given node.
  *
  * Returns 0 if substitution succeeded, -1 if some processing failed
  */
 static int
-xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
+xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) {
     xmlNodePtr cur;
-    xmlChar *href;
-    xmlChar *parse;
-    xmlChar *base;
-    xmlChar *oldBase;
-    xmlChar *URI;
-    int xml = 1; /* default Issue 64 */
     int ret;
 
-    if (ctxt == NULL)
+    if ((ctxt == NULL) || (ref == NULL))
 	return(-1);
-    if ((nr < 0) || (nr >= ctxt->incNr))
-	return(-1);
-    cur = ctxt->incTab[nr]->ref;
+    cur = ref->elem;
     if (cur == NULL)
 	return(-1);
 
-    /*
-     * read the attributes
-     */
-    href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
-    if (href == NULL) {
-	href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
-	if (href == NULL)
-	    return(-1);
-    }
-    parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
-    if (parse != NULL) {
-	if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
-	    xml = 1;
-	else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
-	    xml = 0;
-	else {
-	    xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	                   XML_XINCLUDE_PARSE_VALUE,
-			   "invalid value %s for 'parse'\n", parse);
-	    if (href != NULL)
-		xmlFree(href);
-	    if (parse != NULL)
-		xmlFree(parse);
-	    return(-1);
-	}
-    }
-
-    /*
-     * compute the URI
-     */
-    base = xmlNodeGetBase(ctxt->doc, cur);
-    if (base == NULL) {
-	URI = xmlBuildURI(href, ctxt->doc->URL);
-    } else {
-	URI = xmlBuildURI(href, base);
-    }
-    if (URI == NULL) {
-	xmlChar *escbase;
-	xmlChar *eschref;
-	/*
-	 * Some escaping may be needed
-	 */
-	escbase = xmlURIEscape(base);
-	eschref = xmlURIEscape(href);
-	URI = xmlBuildURI(eschref, escbase);
-	if (escbase != NULL)
-	    xmlFree(escbase);
-	if (eschref != NULL)
-	    xmlFree(eschref);
-    }
-    if (URI == NULL) {
-	xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	               XML_XINCLUDE_HREF_URI, "failed build URL\n", NULL);
-	if (parse != NULL)
-	    xmlFree(parse);
-	if (href != NULL)
-	    xmlFree(href);
-	if (base != NULL)
-	    xmlFree(base);
-	return(-1);
-    }
-#ifdef DEBUG_XINCLUDE
-    xmlGenericError(xmlGenericErrorContext, "parse: %s\n",
-	    xml ? "xml": "text");
-    xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);
-#endif
-
-    /*
-     * Save the base for this include (saving the current one)
-     */
-    oldBase = ctxt->base;
-    ctxt->base = base;
-
-    if (xml) {
-	ret = xmlXIncludeLoadDoc(ctxt, URI, nr);
+    if (ref->xml) {
+	ret = xmlXIncludeLoadDoc(ctxt, ref);
 	/* xmlXIncludeGetFragment(ctxt, cur, URI); */
     } else {
-	ret = xmlXIncludeLoadTxt(ctxt, URI, nr);
+	ret = xmlXIncludeLoadTxt(ctxt, ref);
     }
 
-    /*
-     * Restore the original base before checking for fallback
-     */
-    ctxt->base = oldBase;
-
     if (ret < 0) {
 	xmlNodePtr children;
 
 	/*
 	 * Time to try a fallback if available
 	 */
-#ifdef DEBUG_XINCLUDE
-	xmlGenericError(xmlGenericErrorContext, "error looking for fallback\n");
-#endif
 	children = cur->children;
 	while (children != NULL) {
 	    if ((children->type == XML_ELEMENT_NODE) &&
@@ -2153,57 +1917,42 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
 		(xmlStrEqual(children->name, XINCLUDE_FALLBACK)) &&
 		((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
 		 (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
-		ret = xmlXIncludeLoadFallback(ctxt, children, nr);
+		ret = xmlXIncludeLoadFallback(ctxt, children, ref);
 		break;
 	    }
 	    children = children->next;
 	}
     }
     if (ret < 0) {
-	xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	               XML_XINCLUDE_NO_FALLBACK,
+	xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_NO_FALLBACK,
 		       "could not load %s, and no fallback was found\n",
-		       URI);
+		       ref->URI);
     }
 
-    /*
-     * Cleanup
-     */
-    if (URI != NULL)
-	xmlFree(URI);
-    if (parse != NULL)
-	xmlFree(parse);
-    if (href != NULL)
-	xmlFree(href);
-    if (base != NULL)
-	xmlFree(base);
     return(0);
 }
 
 /**
  * xmlXIncludeIncludeNode:
  * @ctxt: an XInclude context
- * @nr: the node number
+ * @ref: an xmlXIncludeRefPtr
  *
  * Implement the infoset replacement for the given node
  *
  * Returns 0 if substitution succeeded, -1 if some processing failed
  */
 static int
-xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
+xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) {
     xmlNodePtr cur, end, list, tmp;
 
-    if (ctxt == NULL)
+    if ((ctxt == NULL) || (ref == NULL))
 	return(-1);
-    if ((nr < 0) || (nr >= ctxt->incNr))
-	return(-1);
-    cur = ctxt->incTab[nr]->ref;
+    cur = ref->elem;
     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
 	return(-1);
 
-    list = ctxt->incTab[nr]->inc;
-    ctxt->incTab[nr]->inc = NULL;
-    ctxt->incTab[nr]->emptyFb = 0;
+    list = ref->inc;
+    ref->inc = NULL;
 
     /*
      * Check against the risk of generating a multi-rooted document
@@ -2219,8 +1968,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
 	    tmp = tmp->next;
 	}
 	if (nb_elem > 1) {
-	    xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	                   XML_XINCLUDE_MULTIPLE_ROOT,
+	    xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_MULTIPLE_ROOT,
 		       "XInclude error: would result in multiple root nodes\n",
 			   NULL);
             xmlFreeNodeList(list);
@@ -2231,16 +1979,19 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
     if (ctxt->parseFlags & XML_PARSE_NOXINCNODE) {
 	/*
 	 * Add the list of nodes
+         *
+         * TODO: Coalesce text nodes unless we are streaming mode.
 	 */
 	while (list != NULL) {
 	    end = list;
 	    list = list->next;
 
-	    xmlAddPrevSibling(cur, end);
+	    if (xmlAddPrevSibling(cur, end) == NULL) {
+                xmlUnlinkNode(end);
+                xmlFreeNode(end);
+                goto err_memory;
+            }
 	}
-        /*
-         * FIXME: xmlUnlinkNode doesn't coalesce text nodes.
-         */
 	xmlUnlinkNode(cur);
 	xmlFreeNode(cur);
     } else {
@@ -2250,7 +2001,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
 	 * Change the current node as an XInclude start one, and add an
 	 * XInclude end one
 	 */
-        if (ctxt->incTab[nr]->fallback)
+        if (ref->fallback)
             xmlUnsetProp(cur, BAD_CAST "href");
 	cur->type = XML_XINCLUDE_START;
         /* Remove fallback children */
@@ -2260,15 +2011,13 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
             xmlFreeNode(child);
         }
 	end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
-	if (end == NULL) {
-	    xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-	                   XML_XINCLUDE_BUILD_FAILED,
-			   "failed to build node\n", NULL);
-            xmlFreeNodeList(list);
-	    return(-1);
-	}
+	if (end == NULL)
+            goto err_memory;
 	end->type = XML_XINCLUDE_END;
-	xmlAddNextSibling(cur, end);
+	if (xmlAddNextSibling(cur, end) == NULL) {
+            xmlFreeNode(end);
+            goto err_memory;
+        }
 
 	/*
 	 * Add the list of nodes
@@ -2277,12 +2026,21 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
 	    cur = list;
 	    list = list->next;
 
-	    xmlAddPrevSibling(end, cur);
+	    if (xmlAddPrevSibling(end, cur) == NULL) {
+                xmlUnlinkNode(cur);
+                xmlFreeNode(cur);
+                goto err_memory;
+            }
 	}
     }
 
 
     return(0);
+
+err_memory:
+    xmlXIncludeErrMemory(ctxt);
+    xmlFreeNodeList(list);
+    return(-1);
 }
 
 /**
@@ -2364,9 +2122,7 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
 /**
  * xmlXIncludeDoProcess:
  * @ctxt: the XInclude processing context
- * @doc: an XML document
  * @tree: the top of the tree to process
- * @skipRoot: don't process the root node of the tree
  *
  * Implement the XInclude substitution on the XML document @doc
  *
@@ -2374,63 +2130,26 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
  *    or the number of substitutions done.
  */
 static int
-xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
-                     int skipRoot) {
+xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree) {
+    xmlXIncludeRefPtr ref;
     xmlNodePtr cur;
     int ret = 0;
     int i, start;
 
-    if ((doc == NULL) || (tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
-	return(-1);
-    if ((skipRoot) && (tree->children == NULL))
-        return(-1);
-    if (ctxt == NULL)
-	return(-1);
-
-    if (doc->URL != NULL) {
-	ret = xmlXIncludeURLPush(ctxt, doc->URL);
-	if (ret < 0)
-	    return(-1);
-    }
-    start = ctxt->incNr;
-
-    /*
-     * TODO: The phases must run separately for recursive inclusions.
-     *
-     * - Phase 1 should start with top-level XInclude nodes, load documents,
-     *   execute XPointer expressions, then process only the result nodes
-     *   (not whole document, see bug #324081) and only for phase 1
-     *   recursively. We will need a backreference from xmlNodes to
-     *   xmlIncludeRefs to detect references that were already visited.
-     *   This can also be used for proper cycle detection, see bug #344240.
-     *
-     * - Phase 2 should visit all top-level XInclude nodes and expand
-     *   possible subreferences in the replacement recursively.
-     *
-     * - Phase 3 should finally replace the top-level XInclude nodes.
-     *   It could also be run together with phase 2.
-     */
-
     /*
      * First phase: lookup the elements in the document
      */
-    if (skipRoot)
-        cur = tree->children;
-    else
-        cur = tree;
+    start = ctxt->incNr;
+    cur = tree;
     do {
 	/* TODO: need to work on entities -> stack */
         if (xmlXIncludeTestNode(ctxt, cur) == 1) {
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+            ref = xmlXIncludeExpandNode(ctxt, cur);
             /*
-             * Avoid superlinear expansion by limiting the total number
-             * of replacements.
+             * Mark direct includes.
              */
-            if (ctxt->incTotal >= 20)
-                return(-1);
-#endif
-            ctxt->incTotal++;
-            xmlXIncludePreProcessNode(ctxt, cur);
+            if (ref != NULL)
+                ref->replace = 1;
         } else if ((cur->children != NULL) &&
                    ((cur->type == XML_DOCUMENT_NODE) ||
                     (cur->type == XML_ELEMENT_NODE))) {
@@ -2449,35 +2168,95 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
     } while ((cur != NULL) && (cur != tree));
 
     /*
-     * Second Phase : collect the infosets fragments
+     * Second phase: extend the original document infoset.
      */
-    for (i = start;i < ctxt->incNr; i++) {
-        xmlXIncludeLoadNode(ctxt, i);
+    for (i = start; i < ctxt->incNr; i++) {
+	if (ctxt->incTab[i]->replace != 0) {
+            xmlXIncludeIncludeNode(ctxt, ctxt->incTab[i]);
+            ctxt->incTab[i]->replace = 0;
+        } else {
+            /*
+             * Ignore includes which were added indirectly, for example
+             * inside xi:fallback elements.
+             */
+            if (ctxt->incTab[i]->inc != NULL) {
+                xmlFreeNodeList(ctxt->incTab[i]->inc);
+                ctxt->incTab[i]->inc = NULL;
+            }
+        }
 	ret++;
     }
 
-    /*
-     * Third phase: extend the original document infoset.
-     *
-     * Originally we bypassed the inclusion if there were any errors
-     * encountered on any of the XIncludes.  A bug was raised (bug
-     * 132588) requesting that we output the XIncludes without error,
-     * so the check for inc!=NULL || xptr!=NULL was put in.  This may
-     * give some other problems in the future, but for now it seems to
-     * work ok.
-     *
-     */
-    for (i = ctxt->incBase;i < ctxt->incNr; i++) {
-	if ((ctxt->incTab[i]->inc != NULL) ||
-	    (ctxt->incTab[i]->emptyFb != 0))	/* (empty fallback) */
-	    xmlXIncludeIncludeNode(ctxt, i);
+    if (ctxt->isStream) {
+        /*
+         * incTab references nodes which will eventually be deleted in
+         * streaming mode. The table is only required for XPointer
+         * expressions which aren't allowed in streaming mode.
+         */
+        for (i = 0;i < ctxt->incNr;i++) {
+            xmlXIncludeFreeRef(ctxt->incTab[i]);
+        }
+        ctxt->incNr = 0;
     }
 
-    if (doc->URL != NULL)
-	xmlXIncludeURLPop(ctxt);
     return(ret);
 }
 
+/**
+ * xmlXIncludeDoProcessRoot:
+ * @ctxt: the XInclude processing context
+ * @tree: the top of the tree to process
+ *
+ * Implement the XInclude substitution on the XML document @doc
+ *
+ * Returns 0 if no substitution were done, -1 if some processing failed
+ *    or the number of substitutions done.
+ */
+static int
+xmlXIncludeDoProcessRoot(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree) {
+    if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
+	return(-1);
+    if (ctxt == NULL)
+	return(-1);
+
+    return(xmlXIncludeDoProcess(ctxt, tree));
+}
+
+/**
+ * xmlXIncludeGetLastError:
+ * @ctxt:  an XInclude processing context
+ *
+ * Available since 2.13.0.
+ *
+ * Returns the last error code.
+ */
+int
+xmlXIncludeGetLastError(xmlXIncludeCtxtPtr ctxt) {
+    if (ctxt == NULL)
+        return(XML_ERR_ARGUMENT);
+    return(ctxt->errNo);
+}
+
+/**
+ * xmlXIncludeSetErrorHandler:
+ * @ctxt:  an XInclude processing context
+ * @handler:  error handler
+ * @data:  user data which will be passed to the handler
+ *
+ * Register a callback function that will be called on errors and
+ * warnings. If handler is NULL, the error handler will be deactivated.
+ *
+ * Available since 2.13.0.
+ */
+void
+xmlXIncludeSetErrorHandler(xmlXIncludeCtxtPtr ctxt,
+                           xmlStructuredErrorFunc handler, void *data) {
+    if (ctxt == NULL)
+        return;
+    ctxt->errorHandler = handler;
+    ctxt->errorCtxt = data;
+}
+
 /**
  * xmlXIncludeSetFlags:
  * @ctxt:  an XInclude processing context
@@ -2495,6 +2274,23 @@ xmlXIncludeSetFlags(xmlXIncludeCtxtPtr ctxt, int flags) {
     return(0);
 }
 
+/**
+ * xmlXIncludeSetStreamingMode:
+ * @ctxt:  an XInclude processing context
+ * @mode:  whether streaming mode should be enabled
+ *
+ * In streaming mode, XPointer expressions aren't allowed.
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+int
+xmlXIncludeSetStreamingMode(xmlXIncludeCtxtPtr ctxt, int mode) {
+    if (ctxt == NULL)
+        return(-1);
+    ctxt->isStream = !!mode;
+    return(0);
+}
+
 /**
  * xmlXIncludeProcessTreeFlagsData:
  * @tree: an XML node
@@ -2521,9 +2317,8 @@ xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
     if (ctxt == NULL)
         return(-1);
     ctxt->_private = data;
-    ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
     xmlXIncludeSetFlags(ctxt, flags);
-    ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree, 0);
+    ret = xmlXIncludeDoProcessRoot(ctxt, tree);
     if ((ret >= 0) && (ctxt->nbErrors > 0))
         ret = -1;
 
@@ -2605,9 +2400,8 @@ xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
     ctxt = xmlXIncludeNewContext(tree->doc);
     if (ctxt == NULL)
 	return(-1);
-    ctxt->base = xmlNodeGetBase(tree->doc, tree);
     xmlXIncludeSetFlags(ctxt, flags);
-    ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree, 0);
+    ret = xmlXIncludeDoProcessRoot(ctxt, tree);
     if ((ret >= 0) && (ctxt->nbErrors > 0))
 	ret = -1;
 
@@ -2647,7 +2441,7 @@ xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
         (node->doc == NULL) || (ctxt == NULL))
 	return(-1);
-    ret = xmlXIncludeDoProcess(ctxt, node->doc, node, 0);
+    ret = xmlXIncludeDoProcessRoot(ctxt, node);
     if ((ret >= 0) && (ctxt->nbErrors > 0))
 	ret = -1;
     return(ret);
diff --git a/xlink.c b/xlink.c
index 65715cb3a8fb6178c3e9a5f662ab506b52bae25e..3a77b1999de53e633a77b2aef23a54bf8329a6ad 100644
--- a/xlink.c
+++ b/xlink.c
@@ -19,9 +19,7 @@
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
 #include <libxml/parser.h>
-#include <libxml/valid.h>
 #include <libxml/xlink.h>
-#include <libxml/globals.h>
 
 #define XLINK_NAMESPACE (BAD_CAST "http://www.w3.org/1999/xlink/namespace/")
 #define XHTML_NAMESPACE (BAD_CAST "http://www.w3.org/1999/xhtml/")
diff --git a/xmlIO.c b/xmlIO.c
index e47e2b15274e05716978e5e9bebecbcee4f75e7b..353771b7f2535111193f0e23072f970711c82d3e 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -4,8 +4,6 @@
  * See Copyright for the status of this software.
  *
  * daniel@veillard.com
- *
- * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char
  */
 
 #define IN_LIBXML
@@ -15,9 +13,6 @@
 #include <stdlib.h>
 #include <errno.h>
 
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
@@ -41,22 +36,8 @@
 #include <direct.h>
 #endif
 
-#ifndef S_ISDIR
-#  ifdef _S_ISDIR
-#    define S_ISDIR(x) _S_ISDIR(x)
-#  elif defined(S_IFDIR)
-#    ifdef S_IFMT
-#      define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#    elif defined(_S_IFMT)
-#      define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
-#    endif
-#  endif
-#endif
-
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-#include <libxml/parserInternals.h>
 #include <libxml/xmlIO.h>
+#include <libxml/xmlmemory.h>
 #include <libxml/uri.h>
 #include <libxml/nanohttp.h>
 #include <libxml/nanoftp.h>
@@ -64,19 +45,31 @@
 #ifdef LIBXML_CATALOG_ENABLED
 #include <libxml/catalog.h>
 #endif
-#include <libxml/globals.h>
 
-#include "buf.h"
-#include "enc.h"
+#include "private/buf.h"
+#include "private/enc.h"
+#include "private/error.h"
+#include "private/io.h"
+#include "private/parser.h"
 
 /* #define VERBOSE_FAILURE */
-/* #define DEBUG_EXTERNAL_ENTITIES */
-/* #define DEBUG_INPUT */
 
-#ifdef DEBUG_INPUT
-#define MINLEN 40
-#else
 #define MINLEN 4000
+
+#ifndef STDOUT_FILENO
+  #define STDOUT_FILENO 1
+#endif
+
+#ifndef S_ISDIR
+#  ifdef _S_ISDIR
+#    define S_ISDIR(x) _S_ISDIR(x)
+#  elif defined(S_IFDIR)
+#    ifdef S_IFMT
+#      define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#    elif defined(_S_IFMT)
+#      define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
+#    endif
+#  endif
 #endif
 
 /*
@@ -89,11 +82,14 @@ typedef struct _xmlInputCallback {
     xmlInputCloseCallback closecallback;
 } xmlInputCallback;
 
-#define MAX_INPUT_CALLBACK 15
+/* This dummy function only marks default IO in the callback table */
+static int
+xmlIODefaultMatch(const char *filename);
+
+#define MAX_INPUT_CALLBACK 10
 
 static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
-static int xmlInputCallbackNr = 0;
-static int xmlInputCallbackInitialized = 0;
+static int xmlInputCallbackNr;
 
 #ifdef LIBXML_OUTPUT_ENABLED
 /*
@@ -106,114 +102,18 @@ typedef struct _xmlOutputCallback {
     xmlOutputCloseCallback closecallback;
 } xmlOutputCallback;
 
-#define MAX_OUTPUT_CALLBACK 15
+#define MAX_OUTPUT_CALLBACK 10
 
 static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
-static int xmlOutputCallbackNr = 0;
-static int xmlOutputCallbackInitialized = 0;
-
-xmlOutputBufferPtr
-xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
+static int xmlOutputCallbackNr;
 #endif /* LIBXML_OUTPUT_ENABLED */
 
 /************************************************************************
  *									*
- *		Tree memory error handler				*
+ *			Error handling					*
  *									*
  ************************************************************************/
 
-static const char* const IOerr[] = {
-    "Unknown IO error",         /* UNKNOWN */
-    "Permission denied",	/* EACCES */
-    "Resource temporarily unavailable",/* EAGAIN */
-    "Bad file descriptor",	/* EBADF */
-    "Bad message",		/* EBADMSG */
-    "Resource busy",		/* EBUSY */
-    "Operation canceled",	/* ECANCELED */
-    "No child processes",	/* ECHILD */
-    "Resource deadlock avoided",/* EDEADLK */
-    "Domain error",		/* EDOM */
-    "File exists",		/* EEXIST */
-    "Bad address",		/* EFAULT */
-    "File too large",		/* EFBIG */
-    "Operation in progress",	/* EINPROGRESS */
-    "Interrupted function call",/* EINTR */
-    "Invalid argument",		/* EINVAL */
-    "Input/output error",	/* EIO */
-    "Is a directory",		/* EISDIR */
-    "Too many open files",	/* EMFILE */
-    "Too many links",		/* EMLINK */
-    "Inappropriate message buffer length",/* EMSGSIZE */
-    "Filename too long",	/* ENAMETOOLONG */
-    "Too many open files in system",/* ENFILE */
-    "No such device",		/* ENODEV */
-    "No such file or directory",/* ENOENT */
-    "Exec format error",	/* ENOEXEC */
-    "No locks available",	/* ENOLCK */
-    "Not enough space",		/* ENOMEM */
-    "No space left on device",	/* ENOSPC */
-    "Function not implemented",	/* ENOSYS */
-    "Not a directory",		/* ENOTDIR */
-    "Directory not empty",	/* ENOTEMPTY */
-    "Not supported",		/* ENOTSUP */
-    "Inappropriate I/O control operation",/* ENOTTY */
-    "No such device or address",/* ENXIO */
-    "Operation not permitted",	/* EPERM */
-    "Broken pipe",		/* EPIPE */
-    "Result too large",		/* ERANGE */
-    "Read-only file system",	/* EROFS */
-    "Invalid seek",		/* ESPIPE */
-    "No such process",		/* ESRCH */
-    "Operation timed out",	/* ETIMEDOUT */
-    "Improper link",		/* EXDEV */
-    "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */
-    "encoder error",		/* XML_IO_ENCODER */
-    "flush error",
-    "write error",
-    "no input",
-    "buffer full",
-    "loading error",
-    "not a socket",		/* ENOTSOCK */
-    "already connected",	/* EISCONN */
-    "connection refused",	/* ECONNREFUSED */
-    "unreachable network",	/* ENETUNREACH */
-    "address in use",		/* EADDRINUSE */
-    "already in use",		/* EALREADY */
-    "unknown address family",	/* EAFNOSUPPORT */
-};
-
-#if defined(_WIN32)
-/**
- * __xmlIOWin32UTF8ToWChar:
- * @u8String:  uft-8 string
- *
- * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
- */
-static wchar_t *
-__xmlIOWin32UTF8ToWChar(const char *u8String)
-{
-    wchar_t *wString = NULL;
-
-    if (u8String) {
-        int wLen =
-            MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
-                                -1, NULL, 0);
-        if (wLen) {
-            wString = xmlMalloc(wLen * sizeof(wchar_t));
-            if (wString) {
-                if (MultiByteToWideChar
-                    (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
-                    xmlFree(wString);
-                    wString = NULL;
-                }
-            }
-        }
-    }
-
-    return wString;
-}
-#endif
-
 /**
  * xmlIOErrMemory:
  * @extra:  extra information
@@ -221,9 +121,9 @@ __xmlIOWin32UTF8ToWChar(const char *u8String)
  * Handle an out of memory condition
  */
 static void
-xmlIOErrMemory(const char *extra)
+xmlIOErrMemory(void)
 {
-    __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra);
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_IO, NULL);
 }
 
 /**
@@ -234,13 +134,17 @@ xmlIOErrMemory(const char *extra)
  *
  * Handle an I/O error
  */
-void
+int
 __xmlIOErr(int domain, int code, const char *extra)
 {
-    unsigned int idx;
+    xmlStructuredErrorFunc schannel = NULL;
+    xmlGenericErrorFunc channel = NULL;
+    void *data = NULL;
+    const char *fmt, *arg1, *arg2;
+    int res;
 
     if (code == 0) {
-	if (errno == 0) code = 0;
+	if (errno == 0) code = XML_IO_UNKNOWN;
 #ifdef EACCES
         else if (errno == EACCES) code = XML_IO_EACCES;
 #endif
@@ -396,189 +300,49 @@ __xmlIOErr(int domain, int code, const char *extra)
 #endif
         else code = XML_IO_UNKNOWN;
     }
-    idx = 0;
-    if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN;
-    if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0;
-
-    __xmlSimpleError(domain, code, NULL, IOerr[idx], extra);
-}
-
-/**
- * xmlIOErr:
- * @code:  the error number
- * @extra:  extra information
- *
- * Handle an I/O error
- */
-static void
-xmlIOErr(int code, const char *extra)
-{
-    __xmlIOErr(XML_FROM_IO, code, extra);
-}
 
-/**
- * __xmlLoaderErr:
- * @ctx: the parser context
- * @extra:  extra information
- *
- * Handle a resource access error
- */
-void
-__xmlLoaderErr(void *ctx, const char *msg, const char *filename)
-{
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlStructuredErrorFunc schannel = NULL;
-    xmlGenericErrorFunc channel = NULL;
-    void *data = NULL;
-    xmlErrorLevel level = XML_ERR_ERROR;
-
-    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
-        (ctxt->instate == XML_PARSER_EOF))
-	return;
-    if ((ctxt != NULL) && (ctxt->sax != NULL)) {
-        if (ctxt->validate) {
-	    channel = ctxt->sax->error;
-	    level = XML_ERR_ERROR;
-	} else {
-	    channel = ctxt->sax->warning;
-	    level = XML_ERR_WARNING;
-	}
-	if (ctxt->sax->initialized == XML_SAX2_MAGIC)
-	    schannel = ctxt->sax->serror;
-	data = ctxt->userData;
+    if (xmlStructuredError) {
+        schannel = xmlStructuredError;
+        data = xmlStructuredErrorContext;
+    } else {
+        channel = xmlGenericError;
+        data = xmlGenericErrorContext;
     }
-    __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO,
-                    XML_IO_LOAD_ERROR, level, NULL, 0,
-		    filename, NULL, NULL, 0, 0,
-		    msg, filename);
-
-}
-
-/************************************************************************
- *									*
- *		Tree memory error handler				*
- *									*
- ************************************************************************/
-/**
- * xmlNormalizeWindowsPath:
- * @path: the input file path
- *
- * This function is obsolete. Please see xmlURIFromPath in uri.c for
- * a better solution.
- *
- * Returns a canonicalized version of the path
- */
-xmlChar *
-xmlNormalizeWindowsPath(const xmlChar *path)
-{
-    return xmlCanonicPath(path);
-}
-
-/**
- * xmlCleanupInputCallbacks:
- *
- * clears the entire input callback table. this includes the
- * compiled-in I/O.
- */
-void
-xmlCleanupInputCallbacks(void)
-{
-    int i;
-
-    if (!xmlInputCallbackInitialized)
-        return;
 
-    for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
-        xmlInputCallbackTable[i].matchcallback = NULL;
-        xmlInputCallbackTable[i].opencallback = NULL;
-        xmlInputCallbackTable[i].readcallback = NULL;
-        xmlInputCallbackTable[i].closecallback = NULL;
+    if (extra != NULL) {
+        fmt = "%s: %s";
+    } else {
+        fmt = "%s";
     }
 
-    xmlInputCallbackNr = 0;
-    xmlInputCallbackInitialized = 0;
-}
-
-/**
- * xmlPopInputCallbacks:
- *
- * Clear the top input callback from the input stack. this includes the
- * compiled-in I/O.
- *
- * Returns the number of input callback registered or -1 in case of error.
- */
-int
-xmlPopInputCallbacks(void)
-{
-    if (!xmlInputCallbackInitialized)
-        return(-1);
-
-    if (xmlInputCallbackNr <= 0)
-        return(-1);
-
-    xmlInputCallbackNr--;
-    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL;
-    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL;
-    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL;
-    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL;
-
-    return(xmlInputCallbackNr);
-}
-
-#ifdef LIBXML_OUTPUT_ENABLED
-/**
- * xmlCleanupOutputCallbacks:
- *
- * clears the entire output callback table. this includes the
- * compiled-in I/O callbacks.
- */
-void
-xmlCleanupOutputCallbacks(void)
-{
-    int i;
-
-    if (!xmlOutputCallbackInitialized)
-        return;
+    arg1 = xmlErrString(code);
+    arg2 = extra;
 
-    for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
-        xmlOutputCallbackTable[i].matchcallback = NULL;
-        xmlOutputCallbackTable[i].opencallback = NULL;
-        xmlOutputCallbackTable[i].writecallback = NULL;
-        xmlOutputCallbackTable[i].closecallback = NULL;
+    res = __xmlRaiseError(schannel, channel, data, NULL, NULL,
+                          domain, code, XML_ERR_ERROR, NULL, 0,
+                          extra, NULL, NULL, 0, 0,
+                          fmt, arg1, arg2);
+    if (res < 0) {
+        xmlIOErrMemory();
+        return(XML_ERR_NO_MEMORY);
     }
 
-    xmlOutputCallbackNr = 0;
-    xmlOutputCallbackInitialized = 0;
+    return(code);
 }
 
 /**
- * xmlPopOutputCallbacks:
- *
- * Remove the top output callbacks from the output stack. This includes the
- * compiled-in I/O.
+ * xmlIOErr:
+ * @code:  the error number
+ * @extra:  extra information
  *
- * Returns the number of output callback registered or -1 in case of error.
+ * Handle an I/O error
  */
-int
-xmlPopOutputCallbacks(void)
+static int
+xmlIOErr(int code, const char *extra)
 {
-    if (!xmlOutputCallbackInitialized)
-        return(-1);
-
-    if (xmlOutputCallbackNr <= 0)
-        return(-1);
-
-    xmlOutputCallbackNr--;
-    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = NULL;
-    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = NULL;
-    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = NULL;
-    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = NULL;
-
-    return(xmlOutputCallbackNr);
+    return(__xmlIOErr(XML_FROM_IO, code, extra));
 }
 
-#endif /* LIBXML_OUTPUT_ENABLED */
-
 /************************************************************************
  *									*
  *		Standard I/O for file accesses				*
@@ -588,92 +352,65 @@ xmlPopOutputCallbacks(void)
 #if defined(_WIN32)
 
 /**
- *  xmlWrapOpenUtf8:
- * @path:  the path in utf-8 encoding
- * @mode:  type of access (0 - read, 1 - write)
- *
- * function opens the file specified by @path
+ * __xmlIOWin32UTF8ToWChar:
+ * @u8String:  uft-8 string
  *
+ * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
  */
-static FILE*
-xmlWrapOpenUtf8(const char *path,int mode)
-{
-    FILE *fd = NULL;
-    wchar_t *wPath;
-
-    wPath = __xmlIOWin32UTF8ToWChar(path);
-    if(wPath)
-    {
-       fd = _wfopen(wPath, mode ? L"wb" : L"rb");
-       xmlFree(wPath);
-    }
-    /* maybe path in native encoding */
-    if(fd == NULL)
-       fd = fopen(path, mode ? "wb" : "rb");
-
-    return fd;
-}
-
-#ifdef LIBXML_ZLIB_ENABLED
-static gzFile
-xmlWrapGzOpenUtf8(const char *path, const char *mode)
+static wchar_t *
+__xmlIOWin32UTF8ToWChar(const char *u8String)
 {
-    gzFile fd;
-    wchar_t *wPath;
+    wchar_t *wString = NULL;
+    int i;
 
-    fd = gzopen (path, mode);
-    if (fd)
-        return fd;
+    if (u8String) {
+        int wLen =
+            MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
+                                -1, NULL, 0);
+        if (wLen) {
+            wString = xmlMalloc(wLen * sizeof(wchar_t));
+            if (wString) {
+                if (MultiByteToWideChar
+                    (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
+                    xmlFree(wString);
+                    wString = NULL;
+                }
+            }
 
-    wPath = __xmlIOWin32UTF8ToWChar(path);
-    if(wPath)
-    {
-	int d, m = (strstr(mode, "r") ? O_RDONLY : O_RDWR);
-#ifdef _O_BINARY
-        m |= (strstr(mode, "b") ? _O_BINARY : 0);
-#endif
-	d = _wopen(wPath, m);
-	if (d >= 0)
-	    fd = gzdopen(d, mode);
-        xmlFree(wPath);
+            /*
+             * Convert to backward slash
+             */
+            for (i = 0; wString[i] != 0; i++) {
+                if (wString[i] == '/')
+                    wString[i] = '\\';
+            }
+        }
     }
 
-    return fd;
+    return wString;
 }
+
 #endif
 
 /**
- *  xmlWrapStatUtf8:
- * @path:  the path in utf-8 encoding
- * @info:  structure that stores results
+ * xmlNormalizeWindowsPath:
+ * @path: the input file path
  *
- * function obtains information about the file or directory
+ * DEPRECATED: This never really worked.
  *
+ * Returns a copy of path.
  */
-static int
-xmlWrapStatUtf8(const char *path, struct _stat *info) {
-    int retval = -1;
-    wchar_t *wPath;
-
-    wPath = __xmlIOWin32UTF8ToWChar(path);
-    if (wPath) {
-       retval = _wstat(wPath, info);
-       xmlFree(wPath);
-    }
-    /* maybe path in native encoding */
-    if(retval < 0)
-       retval = _stat(path, info);
-    return retval;
+xmlChar *
+xmlNormalizeWindowsPath(const xmlChar *path)
+{
+    return xmlStrdup(path);
 }
 
-#endif
-
 /**
  * xmlCheckFilename:
  * @path:  the path to check
  *
- * function checks to see if @path is a valid source
- * (file, socket...) for XML.
+ * DEPRECATED: Internal function, don't use.
  *
  * if stat is not available on the target machine,
  * returns 1.  if stat fails, returns 0 (if calling
@@ -681,9 +418,8 @@ xmlWrapStatUtf8(const char *path, struct _stat *info) {
  * if stat succeeds and the file is a directory,
  * returns 2.  otherwise returns 1.
  */
-
 int
-xmlCheckFilename (const char *path)
+xmlCheckFilename(const char *path)
 {
 #ifdef HAVE_STAT
 #if defined(_WIN32)
@@ -691,46 +427,147 @@ xmlCheckFilename (const char *path)
 #else
     struct stat stat_buffer;
 #endif
+    int res;
 #endif
+
     if (path == NULL)
 	return(0);
 
 #ifdef HAVE_STAT
 #if defined(_WIN32)
-    /*
-     * On Windows stat and wstat do not work with long pathname,
-     * which start with '\\?\'
-     */
-    if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
-	(path[3] == '\\') )
-	    return 1;
+    {
+        wchar_t *wpath;
 
-    if (xmlWrapStatUtf8(path, &stat_buffer) == -1)
-        return 0;
+        /*
+         * On Windows stat and wstat do not work with long pathname,
+         * which start with '\\?\'
+         */
+        if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
+            (path[3] == '\\') )
+                return 1;
+
+        wpath = __xmlIOWin32UTF8ToWChar(path);
+        if (wpath == NULL)
+            return(0);
+        res = _wstat(wpath, &stat_buffer);
+        xmlFree(wpath);
+    }
 #else
-    if (stat(path, &stat_buffer) == -1)
-        return 0;
+    res = stat(path, &stat_buffer);
 #endif
+
+    if (res < 0)
+        return 0;
+
 #ifdef S_ISDIR
     if (S_ISDIR(stat_buffer.st_mode))
         return 2;
 #endif
 #endif /* HAVE_STAT */
+
     return 1;
 }
 
-/**
- * xmlInputReadCallbackNop:
- *
- * No Operation xmlInputReadCallback function, does nothing.
- *
- * Returns zero
- */
-int
-xmlInputReadCallbackNop(void *context ATTRIBUTE_UNUSED,
-                        char *buffer ATTRIBUTE_UNUSED,
-                        int len ATTRIBUTE_UNUSED) {
-    return(0);
+static int
+xmlConvertUriToPath(const char *uri, char **out) {
+    const char *escaped;
+    char *unescaped;
+
+    *out = NULL;
+
+    if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file://localhost/", 17)) {
+	escaped = &uri[16];
+    } else if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file:///", 8)) {
+	escaped = &uri[7];
+    } else if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file:/", 6)) {
+        /* lots of generators seems to lazy to read RFC 1738 */
+	escaped = &uri[5];
+    } else {
+        return(1);
+    }
+
+#ifdef _WIN32
+    /* Ignore slash like in file:///C:/file.txt */
+    escaped += 1;
+#endif
+
+    unescaped = xmlURIUnescapeString(escaped, 0, NULL);
+    if (unescaped == NULL)
+        return(-1);
+
+    *out = unescaped;
+    return(0);
+}
+
+/**
+ * xmlFdOpen:
+ * @filename:  the URI for matching
+ * @out:  pointer to resulting context
+ *
+ * Returns an xmlParserErrors code
+ */
+static int
+xmlFdOpen(const char *filename, int write, int *out) {
+    char *fromUri = NULL;
+    int flags;
+    int fd;
+    int ret;
+
+    *out = -1;
+    if (filename == NULL)
+        return(XML_ERR_ARGUMENT);
+
+    if (xmlConvertUriToPath(filename, &fromUri) < 0)
+        return(XML_ERR_NO_MEMORY);
+
+    if (fromUri != NULL)
+        filename = fromUri;
+
+#if defined(_WIN32)
+    {
+        wchar_t *wpath;
+
+        wpath = __xmlIOWin32UTF8ToWChar(filename);
+        if (wpath == NULL) {
+            xmlFree(fromUri);
+            return(XML_ERR_NO_MEMORY);
+        }
+        if (write)
+            flags = _O_WRONLY | _O_CREAT | _O_TRUNC;
+        else
+            flags = _O_RDONLY;
+	fd = _wopen(wpath, flags | _O_BINARY, 0666);
+        xmlFree(wpath);
+    }
+#else
+    if (write)
+        flags = O_WRONLY | O_CREAT | O_TRUNC;
+    else
+        flags = O_RDONLY;
+    fd = open(filename, flags, 0666);
+#endif /* WIN32 */
+
+    if (fd < 0) {
+        /*
+         * Windows and possibly other platforms return EINVAL
+         * for invalid filenames.
+         */
+        if ((errno == ENOENT) || (errno == EINVAL)) {
+            ret = XML_IO_ENOENT;
+        } else {
+            /*
+             * This error won't be forwarded to the parser context
+             * which will report it a second time.
+             */
+            ret = xmlIOErr(0, filename);
+        }
+    } else {
+        *out = fd;
+        ret = XML_ERR_OK;
+    }
+
+    xmlFree(fromUri);
+    return(ret);
 }
 
 /**
@@ -741,14 +578,32 @@ xmlInputReadCallbackNop(void *context ATTRIBUTE_UNUSED,
  *
  * Read @len bytes to @buffer from the I/O channel.
  *
- * Returns the number of bytes written
+ * Returns the number of bytes read
  */
 static int
-xmlFdRead (void * context, char * buffer, int len) {
-    int ret;
+xmlFdRead(void *context, char *buffer, int len) {
+    int fd = (int) (ptrdiff_t) context;
+    int ret = 0;
+    int bytes;
+
+    while (len > 0) {
+        bytes = read(fd, buffer, len);
+        if (bytes < 0) {
+            /*
+             * If we already got some bytes, return them without
+             * raising an error.
+             */
+            if (ret > 0)
+                break;
+            return(-xmlIOErr(0, "read()"));
+        }
+        if (bytes == 0)
+            break;
+        ret += bytes;
+        buffer += bytes;
+        len -= bytes;
+    }
 
-    ret = read((int) (ptrdiff_t) context, &buffer[0], len);
-    if (ret < 0) xmlIOErr(0, "read()");
     return(ret);
 }
 
@@ -764,13 +619,20 @@ xmlFdRead (void * context, char * buffer, int len) {
  * Returns the number of bytes written
  */
 static int
-xmlFdWrite (void * context, const char * buffer, int len) {
+xmlFdWrite(void *context, const char *buffer, int len) {
+    int fd = (int) (ptrdiff_t) context;
     int ret = 0;
+    int bytes;
 
-    if (len > 0) {
-	ret = write((int) (ptrdiff_t) context, &buffer[0], len);
-	if (ret < 0) xmlIOErr(0, "write()");
+    while (len > 0) {
+	bytes = write(fd, buffer, len);
+	if (bytes < 0)
+            return(-xmlIOErr(0, "write()"));
+        ret += bytes;
+        buffer += bytes;
+        len -= bytes;
     }
+
     return(ret);
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
@@ -786,16 +648,19 @@ xmlFdWrite (void * context, const char * buffer, int len) {
 static int
 xmlFdClose (void * context) {
     int ret;
+
     ret = close((int) (ptrdiff_t) context);
-    if (ret < 0) xmlIOErr(0, "close()");
-    return(ret);
+    if (ret < 0)
+        return(xmlIOErr(0, "close()"));
+
+    return(XML_ERR_OK);
 }
 
 /**
  * xmlFileMatch:
  * @filename:  the URI for matching
  *
- * input from FILE *
+ * DEPRECATED: Internal function, don't use.
  *
  * Returns 1 if matches, 0 otherwise
  */
@@ -805,139 +670,82 @@ xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
 }
 
 /**
- * xmlFileOpen_real:
+ * xmlFileOpenSafe:
  * @filename:  the URI for matching
+ * @out:  pointer to resulting context
  *
- * input from FILE *, supports compressed input
- * if @filename is " " then the standard input is used
+ * input from FILE *
  *
  * Returns an I/O context or NULL in case of error
  */
-static void *
-xmlFileOpen_real (const char *filename) {
-    const char *path = filename;
+static int
+xmlFileOpenSafe(const char *filename, int write, void **out) {
+    char *fromUri = NULL;
     FILE *fd;
+    int ret = XML_ERR_OK;
 
+    *out = NULL;
     if (filename == NULL)
-        return(NULL);
+        return(XML_ERR_ARGUMENT);
 
-    if (!strcmp(filename, "-")) {
-	fd = stdin;
-	return((void *) fd);
-    }
-
-    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
-#if defined (_WIN32)
-	path = &filename[17];
-#else
-	path = &filename[16];
-#endif
-    } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
-#if defined (_WIN32)
-	path = &filename[8];
-#else
-	path = &filename[7];
-#endif
-    } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
-        /* lots of generators seems to lazy to read RFC 1738 */
-#if defined (_WIN32)
-	path = &filename[6];
-#else
-	path = &filename[5];
-#endif
-    }
+    if (xmlConvertUriToPath(filename, &fromUri) < 0)
+        return(XML_ERR_NO_MEMORY);
 
-    /* Do not check DDNAME on zOS ! */
-#if !defined(__MVS__)
-    if (!xmlCheckFilename(path))
-        return(NULL);
-#endif
+    if (fromUri != NULL)
+        filename = fromUri;
 
 #if defined(_WIN32)
-    fd = xmlWrapOpenUtf8(path, 0);
+    {
+        wchar_t *wpath;
+
+        wpath = __xmlIOWin32UTF8ToWChar(filename);
+        if (wpath == NULL) {
+            xmlFree(fromUri);
+            return(XML_ERR_NO_MEMORY);
+        }
+	fd = _wfopen(wpath, write ? L"wb" : L"rb");
+        xmlFree(wpath);
+    }
 #else
-    fd = fopen(path, "rb");
+    fd = fopen(filename, write ? "wb" : "rb");
 #endif /* WIN32 */
-    if (fd == NULL) xmlIOErr(0, path);
-    return((void *) fd);
-}
 
-/**
- * xmlFileOpen:
- * @filename:  the URI for matching
- *
- * Wrapper around xmlFileOpen_real that try it with an unescaped
- * version of @filename, if this fails fallback to @filename
- *
- * Returns a handler or NULL in case or failure
- */
-void *
-xmlFileOpen (const char *filename) {
-    char *unescaped;
-    void *retval;
-
-    retval = xmlFileOpen_real(filename);
-    if (retval == NULL) {
-	unescaped = xmlURIUnescapeString(filename, 0, NULL);
-	if (unescaped != NULL) {
-	    retval = xmlFileOpen_real(unescaped);
-	    xmlFree(unescaped);
-	}
+    if (fd == NULL) {
+        /*
+         * Windows and possibly other platforms return EINVAL
+         * for invalid filenames.
+         */
+        if ((errno == ENOENT) || (errno == EINVAL)) {
+            ret = XML_IO_ENOENT;
+        } else {
+            /*
+             * This error won't be forwarded to the parser context
+             * which will report it a second time.
+             */
+            ret = xmlIOErr(0, filename);
+        }
     }
 
-    return retval;
+    *out = fd;
+    xmlFree(fromUri);
+    return(ret);
 }
 
-#ifdef LIBXML_OUTPUT_ENABLED
 /**
- * xmlFileOpenW:
+ * xmlFileOpen:
  * @filename:  the URI for matching
  *
- * output to from FILE *,
- * if @filename is "-" then the standard output is used
+ * DEPRECATED: Internal function, don't use.
  *
- * Returns an I/O context or NULL in case of error
+ * Returns an IO context or NULL in case or failure
  */
-static void *
-xmlFileOpenW (const char *filename) {
-    const char *path = NULL;
-    FILE *fd;
-
-    if (!strcmp(filename, "-")) {
-	fd = stdout;
-	return((void *) fd);
-    }
-
-    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
-#if defined (_WIN32)
-	path = &filename[17];
-#else
-	path = &filename[16];
-#endif
-    else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
-#if defined (_WIN32)
-	path = &filename[8];
-#else
-	path = &filename[7];
-#endif
-    } else
-	path = filename;
-
-    if (path == NULL)
-	return(NULL);
-
-#if defined(_WIN32)
-    fd = xmlWrapOpenUtf8(path, 1);
-#elif(__MVS__)
-    fd = fopen(path, "w");
-#else
-    fd = fopen(path, "wb");
-#endif /* WIN32 */
+void *
+xmlFileOpen(const char *filename) {
+    void *context;
 
-    if (fd == NULL) xmlIOErr(0, path);
-    return((void *) fd);
+    xmlFileOpenSafe(filename, 0, &context);
+    return(context);
 }
-#endif /* LIBXML_OUTPUT_ENABLED */
 
 /**
  * xmlFileRead:
@@ -945,18 +753,30 @@ xmlFileOpenW (const char *filename) {
  * @buffer:  where to drop data
  * @len:  number of bytes to write
  *
- * Read @len bytes to @buffer from the I/O channel.
+ * DEPRECATED: Internal function, don't use.
  *
- * Returns the number of bytes written or < 0 in case of failure
+ * Returns the number of bytes read or < 0 in case of failure
  */
 int
-xmlFileRead (void * context, char * buffer, int len) {
-    int ret;
+xmlFileRead(void * context, char * buffer, int len) {
+    FILE *file = context;
+    size_t bytes;
+
     if ((context == NULL) || (buffer == NULL))
         return(-1);
-    ret = fread(&buffer[0], 1,  len, (FILE *) context);
-    if (ret < 0) xmlIOErr(0, "fread()");
-    return(ret);
+
+    /*
+     * The C standard doesn't mandate that fread sets errno, only
+     * POSIX does. The Windows documentation isn't really clear.
+     * Set errno to zero which will be reported as unknown error
+     * if fread fails without setting errno.
+     */
+    errno = 0;
+    bytes = fread(buffer, 1, len, file);
+    if ((bytes < (size_t) len) && (ferror(file)))
+        return(-xmlIOErr(0, "fread()"));
+
+    return(bytes);
 }
 
 #ifdef LIBXML_OUTPUT_ENABLED
@@ -971,66 +791,65 @@ xmlFileRead (void * context, char * buffer, int len) {
  * Returns the number of bytes written
  */
 static int
-xmlFileWrite (void * context, const char * buffer, int len) {
-    int items;
+xmlFileWrite(void *context, const char *buffer, int len) {
+    FILE *file = context;
+    size_t bytes;
 
     if ((context == NULL) || (buffer == NULL))
         return(-1);
-    items = fwrite(&buffer[0], len, 1, (FILE *) context);
-    if ((items == 0) && (ferror((FILE *) context))) {
-        xmlIOErr(0, "fwrite()");
-	return(-1);
-    }
-    return(items * len);
+
+    errno = 0;
+    bytes = fwrite(buffer, 1, len, file);
+    if (bytes < (size_t) len)
+        return(-xmlIOErr(0, "fwrite()"));
+
+    return(len);
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
 
 /**
- * xmlFileClose:
+ * xmlFileFlush:
  * @context:  the I/O context
  *
- * Close an I/O channel
- *
- * Returns 0 or -1 in case of error
+ * Flush an I/O channel
  */
-int
-xmlFileClose (void * context) {
-    FILE *fil;
-    int ret;
+static int
+xmlFileFlush (void * context) {
+    FILE *file = context;
 
-    if (context == NULL)
+    if (file == NULL)
         return(-1);
-    fil = (FILE *) context;
-    if ((fil == stdout) || (fil == stderr)) {
-        ret = fflush(fil);
-	if (ret < 0)
-	    xmlIOErr(0, "fflush()");
-	return(0);
-    }
-    if (fil == stdin)
-	return(0);
-    ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0;
-    if (ret < 0)
-        xmlIOErr(0, "fclose()");
-    return(ret);
+
+    if (fflush(file) != 0)
+        return(xmlIOErr(0, "fflush()"));
+
+    return(XML_ERR_OK);
 }
 
 /**
- * xmlFileFlush:
+ * xmlFileClose:
  * @context:  the I/O context
  *
- * Flush an I/O channel
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Returns 0 or -1 an error code case of error
  */
-static int
-xmlFileFlush (void * context) {
-    int ret;
+int
+xmlFileClose (void * context) {
+    FILE *file = context;
 
     if (context == NULL)
         return(-1);
-    ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0;
-    if (ret < 0)
-        xmlIOErr(0, "fflush()");
-    return(ret);
+
+    if (file == stdin)
+        return(0);
+    if ((file == stdout) || (file == stderr))
+        return(xmlFileFlush(file));
+
+    if (fclose(file) != 0)
+        return(xmlIOErr(0, "fclose()"));
+
+    return(0);
 }
 
 #ifdef LIBXML_OUTPUT_ENABLED
@@ -1042,7 +861,8 @@ xmlFileFlush (void * context) {
  *
  * Write @len bytes from @buffer to the xml buffer
  *
- * Returns the number of bytes written
+ * Returns the number of bytes written or a negative xmlParserErrors
+ * value.
  */
 static int
 xmlBufferWrite (void * context, const char * buffer, int len) {
@@ -1050,7 +870,7 @@ xmlBufferWrite (void * context, const char * buffer, int len) {
 
     ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
     if (ret != 0)
-        return(-1);
+        return(-XML_ERR_NO_MEMORY);
     return(len);
 }
 #endif
@@ -1061,148 +881,6 @@ xmlBufferWrite (void * context, const char * buffer, int len) {
  *		I/O for compressed file accesses			*
  *									*
  ************************************************************************/
-/**
- * xmlGzfileMatch:
- * @filename:  the URI for matching
- *
- * input from compressed file test
- *
- * Returns 1 if matches, 0 otherwise
- */
-static int
-xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
-    return(1);
-}
-
-/**
- * xmlGzfileOpen_real:
- * @filename:  the URI for matching
- *
- * input from compressed file open
- * if @filename is " " then the standard input is used
- *
- * Returns an I/O context or NULL in case of error
- */
-static void *
-xmlGzfileOpen_real (const char *filename) {
-    const char *path = NULL;
-    gzFile fd;
-
-    if (!strcmp(filename, "-")) {
-        int duped_fd = dup(fileno(stdin));
-        fd = gzdopen(duped_fd, "rb");
-        if (fd == Z_NULL && duped_fd >= 0) {
-            close(duped_fd);  /* gzdOpen() does not close on failure */
-        }
-
-	return((void *) fd);
-    }
-
-    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
-#if defined (_WIN32)
-	path = &filename[17];
-#else
-	path = &filename[16];
-#endif
-    else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
-#if defined (_WIN32)
-	path = &filename[8];
-#else
-	path = &filename[7];
-#endif
-    } else
-	path = filename;
-
-    if (path == NULL)
-	return(NULL);
-    if (!xmlCheckFilename(path))
-        return(NULL);
-
-#if defined(_WIN32)
-    fd = xmlWrapGzOpenUtf8(path, "rb");
-#else
-    fd = gzopen(path, "rb");
-#endif
-    return((void *) fd);
-}
-
-/**
- * xmlGzfileOpen:
- * @filename:  the URI for matching
- *
- * Wrapper around xmlGzfileOpen_real if the open fails, it will
- * try to unescape @filename
- */
-static void *
-xmlGzfileOpen (const char *filename) {
-    char *unescaped;
-    void *retval;
-
-    retval = xmlGzfileOpen_real(filename);
-    if (retval == NULL) {
-	unescaped = xmlURIUnescapeString(filename, 0, NULL);
-	if (unescaped != NULL) {
-	    retval = xmlGzfileOpen_real(unescaped);
-	}
-	xmlFree(unescaped);
-    }
-    return retval;
-}
-
-#ifdef LIBXML_OUTPUT_ENABLED
-/**
- * xmlGzfileOpenW:
- * @filename:  the URI for matching
- * @compression:  the compression factor (0 - 9 included)
- *
- * input from compressed file open
- * if @filename is " " then the standard input is used
- *
- * Returns an I/O context or NULL in case of error
- */
-static void *
-xmlGzfileOpenW (const char *filename, int compression) {
-    const char *path = NULL;
-    char mode[15];
-    gzFile fd;
-
-    snprintf(mode, sizeof(mode), "wb%d", compression);
-    if (!strcmp(filename, "-")) {
-        int duped_fd = dup(fileno(stdout));
-        fd = gzdopen(duped_fd, "rb");
-        if (fd == Z_NULL && duped_fd >= 0) {
-            close(duped_fd);  /* gzdOpen() does not close on failure */
-        }
-
-	return((void *) fd);
-    }
-
-    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
-#if defined (_WIN32)
-	path = &filename[17];
-#else
-	path = &filename[16];
-#endif
-    else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
-#if defined (_WIN32)
-	path = &filename[8];
-#else
-	path = &filename[7];
-#endif
-    } else
-	path = filename;
-
-    if (path == NULL)
-	return(NULL);
-
-#if defined(_WIN32)
-    fd = xmlWrapGzOpenUtf8(path, mode);
-#else
-    fd = gzopen(path, mode);
-#endif
-    return((void *) fd);
-}
-#endif /* LIBXML_OUTPUT_ENABLED */
 
 /**
  * xmlGzfileRead:
@@ -1260,112 +938,38 @@ xmlGzfileClose (void * context) {
 }
 #endif /* LIBXML_ZLIB_ENABLED */
 
-#ifdef LIBXML_LZMA_ENABLED
 /************************************************************************
  *									*
  *		I/O for compressed file accesses			*
  *									*
  ************************************************************************/
-#include "xzlib.h"
+
+#ifdef LIBXML_LZMA_ENABLED
+
+#include "private/xzlib.h"
+
 /**
- * xmlXzfileMatch:
- * @filename:  the URI for matching
+ * xmlXzfileRead:
+ * @context:  the I/O context
+ * @buffer:  where to drop data
+ * @len:  number of bytes to write
  *
- * input from compressed file test
+ * Read @len bytes to @buffer from the compressed I/O channel.
  *
- * Returns 1 if matches, 0 otherwise
+ * Returns the number of bytes written
  */
 static int
-xmlXzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
-    return(1);
+xmlXzfileRead (void * context, char * buffer, int len) {
+    int ret;
+
+    ret = __libxml2_xzread((xzFile) context, &buffer[0], len);
+    if (ret < 0) xmlIOErr(0, "xzread()");
+    return(ret);
 }
 
 /**
- * xmlXzFileOpen_real:
- * @filename:  the URI for matching
- *
- * input from compressed file open
- * if @filename is " " then the standard input is used
- *
- * Returns an I/O context or NULL in case of error
- */
-static void *
-xmlXzfileOpen_real (const char *filename) {
-    const char *path = NULL;
-    xzFile fd;
-
-    if (!strcmp(filename, "-")) {
-        fd = __libxml2_xzdopen(dup(fileno(stdin)), "rb");
-	return((void *) fd);
-    }
-
-    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
-	path = &filename[16];
-    } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
-	path = &filename[7];
-    } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
-        /* lots of generators seems to lazy to read RFC 1738 */
-	path = &filename[5];
-    } else
-	path = filename;
-
-    if (path == NULL)
-	return(NULL);
-    if (!xmlCheckFilename(path))
-        return(NULL);
-
-    fd = __libxml2_xzopen(path, "rb");
-    return((void *) fd);
-}
-
-/**
- * xmlXzfileOpen:
- * @filename:  the URI for matching
- *
- * Wrapper around xmlXzfileOpen_real that try it with an unescaped
- * version of @filename, if this fails fallback to @filename
- *
- * Returns a handler or NULL in case or failure
- */
-static void *
-xmlXzfileOpen (const char *filename) {
-    char *unescaped;
-    void *retval;
-
-    retval = xmlXzfileOpen_real(filename);
-    if (retval == NULL) {
-	unescaped = xmlURIUnescapeString(filename, 0, NULL);
-	if (unescaped != NULL) {
-	    retval = xmlXzfileOpen_real(unescaped);
-	}
-	xmlFree(unescaped);
-    }
-
-    return retval;
-}
-
-/**
- * xmlXzfileRead:
- * @context:  the I/O context
- * @buffer:  where to drop data
- * @len:  number of bytes to write
- *
- * Read @len bytes to @buffer from the compressed I/O channel.
- *
- * Returns the number of bytes written
- */
-static int
-xmlXzfileRead (void * context, char * buffer, int len) {
-    int ret;
-
-    ret = __libxml2_xzread((xzFile) context, &buffer[0], len);
-    if (ret < 0) xmlIOErr(0, "xzread()");
-    return(ret);
-}
-
-/**
- * xmlXzfileClose:
- * @context:  the I/O context
+ * xmlXzfileClose:
+ * @context:  the I/O context
  *
  * Close a compressed I/O channel
  */
@@ -1379,392 +983,19 @@ xmlXzfileClose (void * context) {
 }
 #endif /* LIBXML_LZMA_ENABLED */
 
-#ifdef LIBXML_HTTP_ENABLED
 /************************************************************************
  *									*
  *			I/O for HTTP file accesses			*
  *									*
  ************************************************************************/
 
-#ifdef LIBXML_OUTPUT_ENABLED
-typedef struct xmlIOHTTPWriteCtxt_
-{
-    int			compression;
-
-    char *		uri;
-
-    void *		doc_buff;
-
-} xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr;
-
-#ifdef LIBXML_ZLIB_ENABLED
-
-#define DFLT_WBITS		( -15 )
-#define DFLT_MEM_LVL		( 8 )
-#define GZ_MAGIC1		( 0x1f )
-#define GZ_MAGIC2		( 0x8b )
-#define LXML_ZLIB_OS_CODE	( 0x03 )
-#define INIT_HTTP_BUFF_SIZE	( 32768 )
-#define DFLT_ZLIB_RATIO		( 5 )
-
-/*
-**  Data structure and functions to work with sending compressed data
-**  via HTTP.
-*/
-
-typedef struct xmlZMemBuff_
-{
-   unsigned long	size;
-   unsigned long	crc;
-
-   unsigned char *	zbuff;
-   z_stream		zctrl;
-
-} xmlZMemBuff, *xmlZMemBuffPtr;
-
-/**
- * append_reverse_ulong
- * @buff:  Compressed memory buffer
- * @data:  Unsigned long to append
- *
- * Append a unsigned long in reverse byte order to the end of the
- * memory buffer.
- */
-static void
-append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) {
-
-    int		idx;
-
-    if ( buff == NULL )
-	return;
-
-    /*
-    **  This is plagiarized from putLong in gzio.c (zlib source) where
-    **  the number "4" is hardcoded.  If zlib is ever patched to
-    **  support 64 bit file sizes, this code would need to be patched
-    **  as well.
-    */
-
-    for ( idx = 0; idx < 4; idx++ ) {
-	*buff->zctrl.next_out = ( data & 0xff );
-	data >>= 8;
-	buff->zctrl.next_out++;
-    }
-
-    return;
-}
-
-/**
- *
- * xmlFreeZMemBuff
- * @buff:  The memory buffer context to clear
- *
- * Release all the resources associated with the compressed memory buffer.
- */
-static void
-xmlFreeZMemBuff( xmlZMemBuffPtr buff ) {
-
-#ifdef DEBUG_HTTP
-    int z_err;
-#endif
-
-    if ( buff == NULL )
-	return;
-
-    xmlFree( buff->zbuff );
-#ifdef DEBUG_HTTP
-    z_err = deflateEnd( &buff->zctrl );
-    if ( z_err != Z_OK )
-	xmlGenericError( xmlGenericErrorContext,
-			"xmlFreeZMemBuff:  Error releasing zlib context:  %d\n",
-			z_err );
-#else
-    deflateEnd( &buff->zctrl );
-#endif
-
-    xmlFree( buff );
-    return;
-}
-
-/**
- * xmlCreateZMemBuff
- *@compression:	Compression value to use
- *
- * Create a memory buffer to hold the compressed XML document.  The
- * compressed document in memory will end up being identical to what
- * would be created if gzopen/gzwrite/gzclose were being used to
- * write the document to disk.  The code for the header/trailer data to
- * the compression is plagiarized from the zlib source files.
- */
-static void *
-xmlCreateZMemBuff( int compression ) {
-
-    int			z_err;
-    int			hdr_lgth;
-    xmlZMemBuffPtr	buff = NULL;
-
-    if ( ( compression < 1 ) || ( compression > 9 ) )
-	return ( NULL );
-
-    /*  Create the control and data areas  */
-
-    buff = xmlMalloc( sizeof( xmlZMemBuff ) );
-    if ( buff == NULL ) {
-	xmlIOErrMemory("creating buffer context");
-	return ( NULL );
-    }
-
-    (void)memset( buff, 0, sizeof( xmlZMemBuff ) );
-    buff->size = INIT_HTTP_BUFF_SIZE;
-    buff->zbuff = xmlMalloc( buff->size );
-    if ( buff->zbuff == NULL ) {
-	xmlFreeZMemBuff( buff );
-	xmlIOErrMemory("creating buffer");
-	return ( NULL );
-    }
-
-    z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED,
-			    DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY );
-    if ( z_err != Z_OK ) {
-	xmlChar msg[500];
-	xmlFreeZMemBuff( buff );
-	buff = NULL;
-	xmlStrPrintf(msg, 500,
-		    "xmlCreateZMemBuff:  %s %d\n",
-		    "Error initializing compression context.  ZLIB error:",
-		    z_err );
-	xmlIOErr(XML_IO_WRITE, (const char *) msg);
-	return ( NULL );
-    }
-
-    /*  Set the header data.  The CRC will be needed for the trailer  */
-    buff->crc = crc32( 0L, NULL, 0 );
-    hdr_lgth = snprintf( (char *)buff->zbuff, buff->size,
-			"%c%c%c%c%c%c%c%c%c%c",
-			GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED,
-			0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE );
-    buff->zctrl.next_out  = buff->zbuff + hdr_lgth;
-    buff->zctrl.avail_out = buff->size - hdr_lgth;
-
-    return ( buff );
-}
-
-/**
- * xmlZMemBuffExtend
- * @buff:  Buffer used to compress and consolidate data.
- * @ext_amt:   Number of bytes to extend the buffer.
- *
- * Extend the internal buffer used to store the compressed data by the
- * specified amount.
- *
- * Returns 0 on success or -1 on failure to extend the buffer.  On failure
- * the original buffer still exists at the original size.
- */
-static int
-xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) {
-
-    int			rc = -1;
-    size_t		new_size;
-    size_t		cur_used;
-
-    unsigned char *	tmp_ptr = NULL;
-
-    if ( buff == NULL )
-	return ( -1 );
-
-    else if ( ext_amt == 0 )
-	return ( 0 );
-
-    cur_used = buff->zctrl.next_out - buff->zbuff;
-    new_size = buff->size + ext_amt;
-
-#ifdef DEBUG_HTTP
-    if ( cur_used > new_size )
-	xmlGenericError( xmlGenericErrorContext,
-			"xmlZMemBuffExtend:  %s\n%s %d bytes.\n",
-			"Buffer overwrite detected during compressed memory",
-			"buffer extension.  Overflowed by",
-			(cur_used - new_size ) );
-#endif
-
-    tmp_ptr = xmlRealloc( buff->zbuff, new_size );
-    if ( tmp_ptr != NULL ) {
-	rc = 0;
-	buff->size  = new_size;
-	buff->zbuff = tmp_ptr;
-	buff->zctrl.next_out  = tmp_ptr + cur_used;
-	buff->zctrl.avail_out = new_size - cur_used;
-    }
-    else {
-	xmlChar msg[500];
-	xmlStrPrintf(msg, 500,
-		    "xmlZMemBuffExtend:  %s %lu bytes.\n",
-		    "Allocation failure extending output buffer to",
-		    (unsigned long) new_size );
-	xmlIOErr(XML_IO_WRITE, (const char *) msg);
-    }
-
-    return ( rc );
-}
-
-/**
- * xmlZMemBuffAppend
- * @buff:  Buffer used to compress and consolidate data
- * @src:   Uncompressed source content to append to buffer
- * @len:   Length of source data to append to buffer
- *
- * Compress and append data to the internal buffer.  The data buffer
- * will be expanded if needed to store the additional data.
- *
- * Returns the number of bytes appended to the buffer or -1 on error.
- */
-static int
-xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) {
-
-    int		z_err;
-    size_t	min_accept;
-
-    if ( ( buff == NULL ) || ( src == NULL ) )
-	return ( -1 );
-
-    buff->zctrl.avail_in = len;
-    buff->zctrl.next_in  = (unsigned char *)src;
-    while ( buff->zctrl.avail_in > 0 ) {
-	/*
-	**  Extend the buffer prior to deflate call if a reasonable amount
-	**  of output buffer space is not available.
-	*/
-	min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO;
-	if ( buff->zctrl.avail_out <= min_accept ) {
-	    if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
-		return ( -1 );
-	}
-
-	z_err = deflate( &buff->zctrl, Z_NO_FLUSH );
-	if ( z_err != Z_OK ) {
-	    xmlChar msg[500];
-	    xmlStrPrintf(msg, 500,
-			"xmlZMemBuffAppend:  %s %d %s - %d",
-			"Compression error while appending",
-			len, "bytes to buffer.  ZLIB error", z_err );
-	    xmlIOErr(XML_IO_WRITE, (const char *) msg);
-	    return ( -1 );
-	}
-    }
-
-    buff->crc = crc32( buff->crc, (unsigned char *)src, len );
-
-    return ( len );
-}
-
-/**
- * xmlZMemBuffGetContent
- * @buff:  Compressed memory content buffer
- * @data_ref:  Pointer reference to point to compressed content
- *
- * Flushes the compression buffers, appends gzip file trailers and
- * returns the compressed content and length of the compressed data.
- * NOTE:  The gzip trailer code here is plagiarized from zlib source.
- *
- * Returns the length of the compressed data or -1 on error.
- */
-static int
-xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) {
-
-    int		zlgth = -1;
-    int		z_err;
-
-    if ( ( buff == NULL ) || ( data_ref == NULL ) )
-	return ( -1 );
-
-    /*  Need to loop until compression output buffers are flushed  */
-
-    do
-    {
-	z_err = deflate( &buff->zctrl, Z_FINISH );
-	if ( z_err == Z_OK ) {
-	    /*  In this case Z_OK means more buffer space needed  */
-
-	    if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
-		return ( -1 );
-	}
-    }
-    while ( z_err == Z_OK );
-
-    /*  If the compression state is not Z_STREAM_END, some error occurred  */
-
-    if ( z_err == Z_STREAM_END ) {
-
-	/*  Need to append the gzip data trailer  */
-
-	if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) {
-	    if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 )
-		return ( -1 );
-	}
-
-	/*
-	**  For whatever reason, the CRC and length data are pushed out
-	**  in reverse byte order.  So a memcpy can't be used here.
-	*/
-
-	append_reverse_ulong( buff, buff->crc );
-	append_reverse_ulong( buff, buff->zctrl.total_in );
-
-	zlgth = buff->zctrl.next_out - buff->zbuff;
-	*data_ref = (char *)buff->zbuff;
-    }
-
-    else {
-	xmlChar msg[500];
-	xmlStrPrintf(msg, 500,
-		    "xmlZMemBuffGetContent:  %s - %d\n",
-		    "Error flushing zlib buffers.  Error code", z_err );
-	xmlIOErr(XML_IO_WRITE, (const char *) msg);
-    }
-
-    return ( zlgth );
-}
-#endif /* LIBXML_OUTPUT_ENABLED */
-#endif  /*  LIBXML_ZLIB_ENABLED  */
-
-#ifdef LIBXML_OUTPUT_ENABLED
-/**
- * xmlFreeHTTPWriteCtxt
- * @ctxt:  Context to cleanup
- *
- * Free allocated memory and reclaim system resources.
- *
- * No return value.
- */
-static void
-xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt )
-{
-    if ( ctxt->uri != NULL )
-	xmlFree( ctxt->uri );
-
-    if ( ctxt->doc_buff != NULL ) {
-
-#ifdef LIBXML_ZLIB_ENABLED
-	if ( ctxt->compression > 0 ) {
-	    xmlFreeZMemBuff( ctxt->doc_buff );
-	}
-	else
-#endif
-	{
-	    xmlOutputBufferClose( ctxt->doc_buff );
-	}
-    }
-
-    xmlFree( ctxt );
-    return;
-}
-#endif /* LIBXML_OUTPUT_ENABLED */
-
-
+#ifdef LIBXML_HTTP_ENABLED
 /**
  * xmlIOHTTPMatch:
  * @filename:  the URI for matching
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * check if the URI matches an HTTP one
  *
  * Returns 1 if matches, 0 otherwise
@@ -1780,6 +1011,8 @@ xmlIOHTTPMatch (const char *filename) {
  * xmlIOHTTPOpen:
  * @filename:  the URI for matching
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * open an HTTP I/O channel
  *
  * Returns an I/O context or NULL in case of error
@@ -1795,78 +1028,15 @@ xmlIOHTTPOpen (const char *filename) {
  * @post_uri:  The destination URI for the document
  * @compression:  The compression desired for the document.
  *
- * Open a temporary buffer to collect the document for a subsequent HTTP POST
- * request.  Non-static as is called from the output buffer creation routine.
+ * DEPRECATED: Support for HTTP POST has been removed.
  *
- * Returns an I/O context or NULL in case of error.
+ * Returns NULL.
  */
-
 void *
-xmlIOHTTPOpenW(const char *post_uri, int compression ATTRIBUTE_UNUSED)
+xmlIOHTTPOpenW(const char *post_uri ATTRIBUTE_UNUSED,
+               int compression ATTRIBUTE_UNUSED)
 {
-
-    xmlIOHTTPWriteCtxtPtr ctxt = NULL;
-
-    if (post_uri == NULL)
-        return (NULL);
-
-    ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt));
-    if (ctxt == NULL) {
-	xmlIOErrMemory("creating HTTP output context");
-        return (NULL);
-    }
-
-    (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt));
-
-    ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri);
-    if (ctxt->uri == NULL) {
-	xmlIOErrMemory("copying URI");
-        xmlFreeHTTPWriteCtxt(ctxt);
-        return (NULL);
-    }
-
-    /*
-     * **  Since the document length is required for an HTTP post,
-     * **  need to put the document into a buffer.  A memory buffer
-     * **  is being used to avoid pushing the data to disk and back.
-     */
-
-#ifdef LIBXML_ZLIB_ENABLED
-    if ((compression > 0) && (compression <= 9)) {
-
-        ctxt->compression = compression;
-        ctxt->doc_buff = xmlCreateZMemBuff(compression);
-    } else
-#endif
-    {
-        /*  Any character conversions should have been done before this  */
-
-        ctxt->doc_buff = xmlAllocOutputBufferInternal(NULL);
-    }
-
-    if (ctxt->doc_buff == NULL) {
-        xmlFreeHTTPWriteCtxt(ctxt);
-        ctxt = NULL;
-    }
-
-    return (ctxt);
-}
-#endif /* LIBXML_OUTPUT_ENABLED */
-
-#ifdef LIBXML_OUTPUT_ENABLED
-/**
- * xmlIOHTTPDfltOpenW
- * @post_uri:  The destination URI for this document.
- *
- * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent
- * HTTP post command.  This function should generally not be used as
- * the open callback is short circuited in xmlOutputBufferCreateFile.
- *
- * Returns a pointer to the new IO context.
- */
-static void *
-xmlIOHTTPDfltOpenW( const char * post_uri ) {
-    return ( xmlIOHTTPOpenW( post_uri, 0 ) );
+    return(NULL);
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
 
@@ -1876,6 +1046,8 @@ xmlIOHTTPDfltOpenW( const char * post_uri ) {
  * @buffer:  where to drop data
  * @len:  number of bytes to write
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Read @len bytes to @buffer from the I/O channel.
  *
  * Returns the number of bytes written
@@ -1886,59 +1058,12 @@ xmlIOHTTPRead(void * context, char * buffer, int len) {
     return(xmlNanoHTTPRead(context, &buffer[0], len));
 }
 
-#ifdef LIBXML_OUTPUT_ENABLED
-/**
- * xmlIOHTTPWrite
- * @context:  previously opened writing context
- * @buffer:   data to output to temporary buffer
- * @len:      bytes to output
- *
- * Collect data from memory buffer into a temporary file for later
- * processing.
- *
- * Returns number of bytes written.
- */
-
-static int
-xmlIOHTTPWrite( void * context, const char * buffer, int len ) {
-
-    xmlIOHTTPWriteCtxtPtr	ctxt = context;
-
-    if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) )
-	return ( -1 );
-
-    if ( len > 0 ) {
-
-	/*  Use gzwrite or fwrite as previously setup in the open call  */
-
-#ifdef LIBXML_ZLIB_ENABLED
-	if ( ctxt->compression > 0 )
-	    len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len );
-
-	else
-#endif
-	    len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer );
-
-	if ( len < 0 ) {
-	    xmlChar msg[500];
-	    xmlStrPrintf(msg, 500,
-			"xmlIOHTTPWrite:  %s\n%s '%s'.\n",
-			"Error appending to internal buffer.",
-			"Error sending document to URI",
-			ctxt->uri );
-	    xmlIOErr(XML_IO_WRITE, (const char *) msg);
-	}
-    }
-
-    return ( len );
-}
-#endif /* LIBXML_OUTPUT_ENABLED */
-
-
 /**
  * xmlIOHTTPClose:
  * @context:  the I/O context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Close an HTTP I/O channel
  *
  * Returns 0
@@ -1948,171 +1073,6 @@ xmlIOHTTPClose (void * context) {
     xmlNanoHTTPClose(context);
     return 0;
 }
-
-#ifdef LIBXML_OUTPUT_ENABLED
-/**
- * xmlIOHTTCloseWrite
- * @context:  The I/O context
- * @http_mthd: The HTTP method to be used when sending the data
- *
- * Close the transmit HTTP I/O channel and actually send the data.
- */
-static int
-xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) {
-
-    int				close_rc = -1;
-    int				http_rtn = 0;
-    int				content_lgth = 0;
-    xmlIOHTTPWriteCtxtPtr	ctxt = context;
-
-    char *			http_content = NULL;
-    char *			content_encoding = NULL;
-    char *			content_type = (char *) "text/xml";
-    void *			http_ctxt = NULL;
-
-    if ( ( ctxt == NULL ) || ( http_mthd == NULL ) )
-	return ( -1 );
-
-    /*  Retrieve the content from the appropriate buffer  */
-
-#ifdef LIBXML_ZLIB_ENABLED
-
-    if ( ctxt->compression > 0 ) {
-	content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content );
-	content_encoding = (char *) "Content-Encoding: gzip";
-    }
-    else
-#endif
-    {
-	/*  Pull the data out of the memory output buffer  */
-
-	xmlOutputBufferPtr	dctxt = ctxt->doc_buff;
-	http_content = (char *) xmlBufContent(dctxt->buffer);
-	content_lgth = xmlBufUse(dctxt->buffer);
-    }
-
-    if ( http_content == NULL ) {
-	xmlChar msg[500];
-	xmlStrPrintf(msg, 500,
-		     "xmlIOHTTPCloseWrite:  %s '%s' %s '%s'.\n",
-		     "Error retrieving content.\nUnable to",
-		     http_mthd, "data to URI", ctxt->uri );
-	xmlIOErr(XML_IO_WRITE, (const char *) msg);
-    }
-
-    else {
-
-	http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content,
-					&content_type, content_encoding,
-					content_lgth );
-
-	if ( http_ctxt != NULL ) {
-#ifdef DEBUG_HTTP
-	    /*  If testing/debugging - dump reply with request content  */
-
-	    FILE *	tst_file = NULL;
-	    char	buffer[ 4096 ];
-	    char *	dump_name = NULL;
-	    int		avail;
-
-	    xmlGenericError( xmlGenericErrorContext,
-			"xmlNanoHTTPCloseWrite:  HTTP %s to\n%s returned %d.\n",
-			http_mthd, ctxt->uri,
-			xmlNanoHTTPReturnCode( http_ctxt ) );
-
-	    /*
-	    **  Since either content or reply may be gzipped,
-	    **  dump them to separate files instead of the
-	    **  standard error context.
-	    */
-
-	    dump_name = tempnam( NULL, "lxml" );
-	    if ( dump_name != NULL ) {
-		(void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name );
-
-		tst_file = fopen( buffer, "wb" );
-		if ( tst_file != NULL ) {
-		    xmlGenericError( xmlGenericErrorContext,
-			"Transmitted content saved in file:  %s\n", buffer );
-
-		    fwrite( http_content, sizeof( char ),
-					content_lgth, tst_file );
-		    fclose( tst_file );
-		}
-
-		(void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name );
-		tst_file = fopen( buffer, "wb" );
-		if ( tst_file != NULL ) {
-		    xmlGenericError( xmlGenericErrorContext,
-			"Reply content saved in file:  %s\n", buffer );
-
-
-		    while ( (avail = xmlNanoHTTPRead( http_ctxt,
-					buffer, sizeof( buffer ) )) > 0 ) {
-
-			fwrite( buffer, sizeof( char ), avail, tst_file );
-		    }
-
-		    fclose( tst_file );
-		}
-
-		free( dump_name );
-	    }
-#endif  /*  DEBUG_HTTP  */
-
-	    http_rtn = xmlNanoHTTPReturnCode( http_ctxt );
-	    if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) )
-		close_rc = 0;
-	    else {
-                xmlChar msg[500];
-                xmlStrPrintf(msg, 500,
-                      "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
-			    http_mthd, content_lgth,
-			    "bytes to URI", ctxt->uri,
-			    "failed.  HTTP return code:", http_rtn );
-		xmlIOErr(XML_IO_WRITE, (const char *) msg);
-            }
-
-	    xmlNanoHTTPClose( http_ctxt );
-	    xmlFree( content_type );
-	}
-    }
-
-    /*  Final cleanups  */
-
-    xmlFreeHTTPWriteCtxt( ctxt );
-
-    return ( close_rc );
-}
-
-/**
- * xmlIOHTTPClosePut
- *
- * @context:  The I/O context
- *
- * Close the transmit HTTP I/O channel and actually send data using a PUT
- * HTTP method.
- */
-static int
-xmlIOHTTPClosePut( void * ctxt ) {
-    return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) );
-}
-
-
-/**
- * xmlIOHTTPClosePost
- *
- * @context:  The I/O context
- *
- * Close the transmit HTTP I/O channel and actually send data using a POST
- * HTTP method.
- */
-static int
-xmlIOHTTPClosePost( void * ctxt ) {
-    return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) );
-}
-#endif /* LIBXML_OUTPUT_ENABLED */
-
 #endif /* LIBXML_HTTP_ENABLED */
 
 #ifdef LIBXML_FTP_ENABLED
@@ -2125,6 +1085,8 @@ xmlIOHTTPClosePost( void * ctxt ) {
  * xmlIOFTPMatch:
  * @filename:  the URI for matching
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * check if the URI matches an FTP one
  *
  * Returns 1 if matches, 0 otherwise
@@ -2140,6 +1102,8 @@ xmlIOFTPMatch (const char *filename) {
  * xmlIOFTPOpen:
  * @filename:  the URI for matching
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * open an FTP I/O channel
  *
  * Returns an I/O context or NULL in case of error
@@ -2155,6 +1119,8 @@ xmlIOFTPOpen (const char *filename) {
  * @buffer:  where to drop data
  * @len:  number of bytes to write
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Read @len bytes to @buffer from the I/O channel.
  *
  * Returns the number of bytes written
@@ -2169,6 +1135,8 @@ xmlIOFTPRead(void * context, char * buffer, int len) {
  * xmlIOFTPClose:
  * @context:  the I/O context
  *
+ * DEPRECATED: Internal function, don't use.
+ *
  * Close an FTP I/O channel
  *
  * Returns 0
@@ -2179,161 +1147,192 @@ xmlIOFTPClose (void * context) {
 }
 #endif /* LIBXML_FTP_ENABLED */
 
+/************************************************************************
+ *									*
+ *			Input/output buffers				*
+ *									*
+ ************************************************************************/
 
-/**
- * xmlRegisterInputCallbacks:
- * @matchFunc:  the xmlInputMatchCallback
- * @openFunc:  the xmlInputOpenCallback
- * @readFunc:  the xmlInputReadCallback
- * @closeFunc:  the xmlInputCloseCallback
- *
- * Register a new set of I/O callback for handling parser input.
- *
- * Returns the registered handler number or -1 in case of error
- */
-int
-xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
-	xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
-	xmlInputCloseCallback closeFunc) {
-    if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
-	return(-1);
-    }
-    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
-    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
-    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
-    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
-    xmlInputCallbackInitialized = 1;
-    return(xmlInputCallbackNr++);
+static int
+xmlIODefaultMatch(const char *filename ATTRIBUTE_UNUSED) {
+    return(1);
 }
 
-#ifdef LIBXML_OUTPUT_ENABLED
 /**
- * xmlRegisterOutputCallbacks:
- * @matchFunc:  the xmlOutputMatchCallback
- * @openFunc:  the xmlOutputOpenCallback
- * @writeFunc:  the xmlOutputWriteCallback
- * @closeFunc:  the xmlOutputCloseCallback
+ * xmlInputDefaultOpen:
+ * @buf:  input buffer to be filled
+ * @filename:  filename or URI
  *
- * Register a new set of I/O callback for handling output.
- *
- * Returns the registered handler number or -1 in case of error
+ * Returns an xmlParserErrors code.
  */
-int
-xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
-	xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
-	xmlOutputCloseCallback closeFunc) {
-    if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
-	return(-1);
+static int
+xmlInputDefaultOpen(xmlParserInputBufferPtr buf, const char *filename) {
+    int ret;
+    int fd;
+
+#ifdef LIBXML_FTP_ENABLED
+    if (xmlIOFTPMatch(filename)) {
+        buf->context = xmlIOFTPOpen(filename);
+
+        if (buf->context != NULL) {
+            buf->readcallback = xmlIOFTPRead;
+            buf->closecallback = xmlIOFTPClose;
+            return(XML_ERR_OK);
+        }
     }
-    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
-    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
-    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
-    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
-    xmlOutputCallbackInitialized = 1;
-    return(xmlOutputCallbackNr++);
-}
-#endif /* LIBXML_OUTPUT_ENABLED */
+#endif /* LIBXML_FTP_ENABLED */
 
-/**
- * xmlRegisterDefaultInputCallbacks:
- *
- * Registers the default compiled-in I/O handlers.
- */
-void
-xmlRegisterDefaultInputCallbacks(void) {
-    if (xmlInputCallbackInitialized)
-	return;
+#ifdef LIBXML_HTTP_ENABLED
+    if (xmlIOHTTPMatch(filename)) {
+        buf->context = xmlIOHTTPOpen(filename);
+
+        if (buf->context != NULL) {
+            buf->readcallback = xmlIOHTTPRead;
+            buf->closecallback = xmlIOHTTPClose;
+            return(XML_ERR_OK);
+        }
+    }
+#endif /* LIBXML_HTTP_ENABLED */
+
+    if (!xmlFileMatch(filename))
+        return(XML_IO_ENOENT);
 
-    xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
-	                      xmlFileRead, xmlFileClose);
-#ifdef LIBXML_ZLIB_ENABLED
-    xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
-	                      xmlGzfileRead, xmlGzfileClose);
-#endif /* LIBXML_ZLIB_ENABLED */
 #ifdef LIBXML_LZMA_ENABLED
-    xmlRegisterInputCallbacks(xmlXzfileMatch, xmlXzfileOpen,
-	                      xmlXzfileRead, xmlXzfileClose);
+    {
+        xzFile xzStream;
+
+        ret = xmlFdOpen(filename, 0, &fd);
+        if (ret != XML_ERR_OK)
+            return(ret);
+
+        xzStream = __libxml2_xzdopen(filename, fd, "rb");
+
+        if (xzStream == NULL) {
+            close(fd);
+        } else {
+            if (__libxml2_xzcompressed(xzStream) > 0) {
+                buf->context = xzStream;
+                buf->readcallback = xmlXzfileRead;
+                buf->closecallback = xmlXzfileClose;
+                buf->compressed = 1;
+
+                return(XML_ERR_OK);
+            }
+
+            xmlXzfileClose(xzStream);
+        }
+    }
 #endif /* LIBXML_LZMA_ENABLED */
 
-#ifdef LIBXML_HTTP_ENABLED
-    xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
-	                      xmlIOHTTPRead, xmlIOHTTPClose);
-#endif /* LIBXML_HTTP_ENABLED */
+#ifdef LIBXML_ZLIB_ENABLED
+    {
+        gzFile gzStream;
 
-#ifdef LIBXML_FTP_ENABLED
-    xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
-	                      xmlIOFTPRead, xmlIOFTPClose);
-#endif /* LIBXML_FTP_ENABLED */
-    xmlInputCallbackInitialized = 1;
+        ret = xmlFdOpen(filename, 0, &fd);
+        if (ret != XML_ERR_OK)
+            return(ret);
+
+        gzStream = gzdopen(fd, "rb");
+
+        if (gzStream == NULL) {
+            close(fd);
+        } else {
+            char buff4[4];
+
+            if ((gzread(gzStream, buff4, 4) > 0) &&
+                (gzdirect(gzStream) == 0)) {
+                gzrewind(gzStream);
+
+                buf->context = gzStream;
+                buf->readcallback = xmlGzfileRead;
+                buf->closecallback = xmlGzfileClose;
+                buf->compressed = 1;
+
+                return(XML_ERR_OK);
+            }
+
+            xmlGzfileClose(gzStream);
+        }
+    }
+#endif /* LIBXML_ZLIB_ENABLED */
+
+    ret = xmlFdOpen(filename, 0, &fd);
+    if (ret != XML_ERR_OK)
+        return(ret);
+
+    buf->context = (void *) (ptrdiff_t) fd;
+    buf->readcallback = xmlFdRead;
+    buf->closecallback = xmlFdClose;
+    return(XML_ERR_OK);
 }
 
 #ifdef LIBXML_OUTPUT_ENABLED
 /**
- * xmlRegisterDefaultOutputCallbacks:
+ * xmlOutputDefaultOpen:
+ * @buf:  input buffer to be filled
+ * @filename:  filename or URI
+ * @compression:  compression level or 0
+ * @is_file_uri:  whether filename is a file URI
  *
- * Registers the default compiled-in I/O handlers.
+ * Returns an xmlParserErrors code.
  */
-void
-xmlRegisterDefaultOutputCallbacks (void) {
-    if (xmlOutputCallbackInitialized)
-	return;
+static int
+xmlOutputDefaultOpen(xmlOutputBufferPtr buf, const char *filename,
+                     int compression) {
+    int fd;
 
-    xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
-	                      xmlFileWrite, xmlFileClose);
+    (void) compression;
 
-#ifdef LIBXML_HTTP_ENABLED
-    xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
-	                       xmlIOHTTPWrite, xmlIOHTTPClosePut);
-#endif
+    if (!strcmp(filename, "-")) {
+        fd = dup(STDOUT_FILENO);
+
+        if (fd < 0)
+            return(xmlIOErr(0, "dup()"));
+    } else {
+        int ret;
 
-/*********************************
- No way a-priori to distinguish between gzipped files from
- uncompressed ones except opening if existing then closing
- and saving with same compression ratio ... a pain.
+        ret = xmlFdOpen(filename, /* write */ 1, &fd);
+        if (ret != XML_ERR_OK)
+            return(ret);
+    }
 
 #ifdef LIBXML_ZLIB_ENABLED
-    xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
-	                       xmlGzfileWrite, xmlGzfileClose);
-#endif
+    if ((compression > 0) && (compression <= 9)) {
+        gzFile gzStream;
+        char mode[15];
 
- Nor FTP PUT ....
-#ifdef LIBXML_FTP_ENABLED
-    xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
-	                       xmlIOFTPWrite, xmlIOFTPClose);
-#endif
- **********************************/
-    xmlOutputCallbackInitialized = 1;
-}
+        snprintf(mode, sizeof(mode), "wb%d", compression);
+        gzStream = gzdopen(fd, mode);
 
-#ifdef LIBXML_HTTP_ENABLED
-/**
- * xmlRegisterHTTPPostCallbacks:
- *
- * By default, libxml submits HTTP output requests using the "PUT" method.
- * Calling this method changes the HTTP output method to use the "POST"
- * method instead.
- *
- */
-void
-xmlRegisterHTTPPostCallbacks( void ) {
+        if (gzStream == NULL) {
+            close(fd);
+            return(xmlIOErr(XML_IO_UNKNOWN, "gzdopen()"));
+        }
 
-    /*  Register defaults if not done previously  */
+        buf->context = gzStream;
+        buf->writecallback = xmlGzfileWrite;
+        buf->closecallback = xmlGzfileClose;
 
-    if ( xmlOutputCallbackInitialized == 0 )
-	xmlRegisterDefaultOutputCallbacks( );
+        return(XML_ERR_OK);
+    }
+#endif /* LIBXML_ZLIB_ENABLED */
 
-    xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
-	                       xmlIOHTTPWrite, xmlIOHTTPClosePost);
-    return;
+    buf->context = (void *) (ptrdiff_t) fd;
+    buf->writecallback = xmlFdWrite;
+    buf->closecallback = xmlFdClose;
+    return(XML_ERR_OK);
 }
 #endif
-#endif /* LIBXML_OUTPUT_ENABLED */
 
 /**
  * xmlAllocParserInputBuffer:
- * @enc:  the charset encoding if known
+ * @enc:  the charset encoding if known (deprecated)
  *
- * Create a buffered parser input for progressive parsing
+ * Create a buffered parser input for progressive parsing.
+ *
+ * The encoding argument is deprecated and should be set to
+ * XML_CHAR_ENCODING_NONE. The encoding can be changed with
+ * xmlSwitchEncoding or xmlSwitchEncodingName later on.
  *
  * Returns the new parser input or NULL
  */
@@ -2343,17 +1342,22 @@ xmlAllocParserInputBuffer(xmlCharEncoding enc) {
 
     ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
     if (ret == NULL) {
-	xmlIOErrMemory("creating input buffer");
 	return(NULL);
     }
-    memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
+    memset(ret, 0, sizeof(xmlParserInputBuffer));
     ret->buffer = xmlBufCreateSize(2 * xmlDefaultBufferSize);
     if (ret->buffer == NULL) {
         xmlFree(ret);
 	return(NULL);
     }
     xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
-    ret->encoder = xmlGetCharEncodingHandler(enc);
+    if (enc != XML_CHAR_ENCODING_NONE) {
+        if (xmlLookupCharEncodingHandler(enc, &ret->encoder) != 0) {
+            /* We can't handle errors properly here. */
+            xmlFreeParserInputBuffer(ret);
+            return(NULL);
+        }
+    }
     if (ret->encoder != NULL)
         ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
     else
@@ -2382,16 +1386,15 @@ xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
 
     ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
     if (ret == NULL) {
-	xmlIOErrMemory("creating output buffer");
 	return(NULL);
     }
-    memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
+    memset(ret, 0, sizeof(xmlOutputBuffer));
     ret->buffer = xmlBufCreate();
     if (ret->buffer == NULL) {
         xmlFree(ret);
 	return(NULL);
     }
-    xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
+    xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_IO);
 
     ret->encoder = encoder;
     if (encoder != NULL) {
@@ -2430,10 +1433,9 @@ xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
 
     ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
     if (ret == NULL) {
-	xmlIOErrMemory("creating output buffer");
 	return(NULL);
     }
-    memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
+    memset(ret, 0, sizeof(xmlOutputBuffer));
     ret->buffer = xmlBufCreate();
     if (ret->buffer == NULL) {
         xmlFree(ret);
@@ -2507,22 +1509,36 @@ xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
  * flushes and close the output I/O channel
  * and free up all the associated resources
  *
- * Returns the number of byte written or -1 in case of error.
+ * Returns the number of byte written or a negative xmlParserErrors
+ * code in case of error.
  */
 int
 xmlOutputBufferClose(xmlOutputBufferPtr out)
 {
-    int written;
-    int err_rc = 0;
+    int ret;
 
     if (out == NULL)
         return (-1);
+
     if (out->writecallback != NULL)
         xmlOutputBufferFlush(out);
+
     if (out->closecallback != NULL) {
-        err_rc = out->closecallback(out->context);
+        int code = out->closecallback(out->context);
+
+        if ((code != XML_ERR_OK) && (out->error == XML_ERR_OK)) {
+            if (code < 0)
+                out->error = XML_IO_UNKNOWN;
+            else
+                out->error = code;
+        }
     }
-    written = out->written;
+
+    if (out->error != XML_ERR_OK)
+        ret = -out->error;
+    else
+        ret = out->written;
+
     if (out->conv) {
         xmlBufFree(out->conv);
         out->conv = NULL;
@@ -2535,81 +1551,79 @@ xmlOutputBufferClose(xmlOutputBufferPtr out)
         out->buffer = NULL;
     }
 
-    if (out->error)
-        err_rc = -1;
     xmlFree(out);
-    return ((err_rc == 0) ? written : err_rc);
+
+    return(ret);
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
 
-xmlParserInputBufferPtr
-__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
-    xmlParserInputBufferPtr ret;
-    int i = 0;
-    void *context = NULL;
+/**
+ * xmlParserInputBufferCreateFilenameInt:
+ * @URI:  the filename or URI
+ * @enc:  encoding enum (deprecated)
+ * @out:  pointer to resulting input buffer
+ *
+ * Returns an xmlParserErrors code.
+ */
+static int
+xmlParserInputBufferCreateFilenameInt(const char *URI, xmlCharEncoding enc,
+                                      xmlParserInputBufferPtr *out) {
+    xmlParserInputBufferPtr buf;
+    int ret;
+    int i;
+
+    xmlInitParser();
 
-    if (xmlInputCallbackInitialized == 0)
-	xmlRegisterDefaultInputCallbacks();
+    *out = NULL;
+    if (URI == NULL)
+        return(XML_ERR_ARGUMENT);
 
-    if (URI == NULL) return(NULL);
+    /*
+     * Allocate the Input buffer front-end.
+     */
+    buf = xmlAllocParserInputBuffer(enc);
+    if (buf == NULL)
+        return(XML_ERR_NO_MEMORY);
 
     /*
      * Try to find one of the input accept method accepting that scheme
      * Go in reverse to give precedence to user defined handlers.
      */
-    if (context == NULL) {
-	for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
-	    if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
-		(xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
-		context = xmlInputCallbackTable[i].opencallback(URI);
-		if (context != NULL) {
-		    break;
-		}
-	    }
-	}
+    ret = XML_IO_ENOENT;
+    for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
+        xmlInputCallback *cb = &xmlInputCallbackTable[i];
+
+        if (cb->matchcallback == xmlIODefaultMatch) {
+            ret = xmlInputDefaultOpen(buf, URI);
+
+            if ((ret == XML_ERR_OK) || (ret != XML_IO_ENOENT))
+                break;
+        } else if ((cb->matchcallback != NULL) &&
+                   (cb->matchcallback(URI) != 0)) {
+            buf->context = cb->opencallback(URI);
+            if (buf->context != NULL) {
+                buf->readcallback = cb->readcallback;
+                buf->closecallback = cb->closecallback;
+                ret = XML_ERR_OK;
+                break;
+            }
+        }
     }
-    if (context == NULL) {
-	return(NULL);
+    if (ret != XML_ERR_OK) {
+        xmlFreeParserInputBuffer(buf);
+        *out = NULL;
+	return(ret);
     }
 
-    /*
-     * Allocate the Input buffer front-end.
-     */
-    ret = xmlAllocParserInputBuffer(enc);
-    if (ret != NULL) {
-	ret->context = context;
-	ret->readcallback = xmlInputCallbackTable[i].readcallback;
-	ret->closecallback = xmlInputCallbackTable[i].closecallback;
-#ifdef LIBXML_ZLIB_ENABLED
-	if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) &&
-		(strcmp(URI, "-") != 0)) {
-#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
-            ret->compressed = !gzdirect(context);
-#else
-	    if (((z_stream *)context)->avail_in > 4) {
-	        char *cptr, buff4[4];
-		cptr = (char *) ((z_stream *)context)->next_in;
-		if (gzread(context, buff4, 4) == 4) {
-		    if (strncmp(buff4, cptr, 4) == 0)
-		        ret->compressed = 0;
-		    else
-		        ret->compressed = 1;
-		    gzrewind(context);
-		}
-	    }
-#endif
-	}
-#endif
-#ifdef LIBXML_LZMA_ENABLED
-	if ((xmlInputCallbackTable[i].opencallback == xmlXzfileOpen) &&
-		(strcmp(URI, "-") != 0)) {
-            ret->compressed = __libxml2_xzcompressed(context);
-	}
-#endif
-    }
-    else
-      xmlInputCallbackTable[i].closecallback (context);
+    *out = buf;
+    return(ret);
+}
+
+xmlParserInputBufferPtr
+__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
+    xmlParserInputBufferPtr ret;
 
+    xmlParserInputBufferCreateFilenameInt(URI, enc, &ret);
     return(ret);
 }
 
@@ -2619,7 +1633,6 @@ __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
  * @enc:  the charset encoding if known
  *
  * Create a buffered parser input for the progressive parsing of a file
- * If filename is "-' then we use stdin as the input.
  * Automatic support for ZLIB/Compress compressed document is provided
  * by default if found at compile-time.
  * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
@@ -2628,135 +1641,106 @@ __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
  */
 xmlParserInputBufferPtr
 xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
-    if ((xmlParserInputBufferCreateFilenameValue)) {
-		return xmlParserInputBufferCreateFilenameValue(URI, enc);
-	}
-	return __xmlParserInputBufferCreateFilename(URI, enc);
+    if (xmlParserInputBufferCreateFilenameValue != NULL)
+        return(xmlParserInputBufferCreateFilenameValue(URI, enc));
+
+    return(__xmlParserInputBufferCreateFilename(URI, enc));
+}
+
+/**
+ * xmlParserInputBufferCreateFilenameSafe:
+ * @URI:  the filename or URI
+ * @enc:  encoding enum (deprecated)
+ * @out:  pointer to resulting input buffer
+ *
+ * Create an input buffer for a filename or URI.
+ *
+ * Returns an xmlParserErrors code.
+ */
+int
+xmlParserInputBufferCreateFilenameSafe(const char *URI, xmlCharEncoding enc,
+                                       xmlParserInputBufferPtr *out) {
+    if (xmlParserInputBufferCreateFilenameValue != NULL) {
+        *out = xmlParserInputBufferCreateFilenameValue(URI, enc);
+
+        if (*out == NULL)
+            return(XML_IO_ENOENT);
+        return(XML_ERR_OK);
+    }
+
+    return(xmlParserInputBufferCreateFilenameInt(URI, enc, out));
 }
 
 #ifdef LIBXML_OUTPUT_ENABLED
 xmlOutputBufferPtr
 __xmlOutputBufferCreateFilename(const char *URI,
                               xmlCharEncodingHandlerPtr encoder,
-                              int compression ATTRIBUTE_UNUSED) {
+                              int compression) {
     xmlOutputBufferPtr ret;
     xmlURIPtr puri;
     int i = 0;
-    void *context = NULL;
     char *unescaped = NULL;
-#ifdef LIBXML_ZLIB_ENABLED
-    int is_file_uri = 1;
-#endif
 
-    if (xmlOutputCallbackInitialized == 0)
-	xmlRegisterDefaultOutputCallbacks();
+    xmlInitParser();
 
-    if (URI == NULL) return(NULL);
+    if (URI == NULL)
+        return(NULL);
 
     puri = xmlParseURI(URI);
     if (puri != NULL) {
-#ifdef LIBXML_ZLIB_ENABLED
-        if ((puri->scheme != NULL) &&
-	    (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
-	    is_file_uri = 0;
-#endif
-	/*
-	 * try to limit the damages of the URI unescaping code.
-	 */
-	if ((puri->scheme == NULL) ||
-	    (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
-	    unescaped = xmlURIUnescapeString(URI, 0, NULL);
-	xmlFreeURI(puri);
+        /*
+         * try to limit the damages of the URI unescaping code.
+         */
+        if (puri->scheme == NULL) {
+            unescaped = xmlURIUnescapeString(URI, 0, NULL);
+             if (unescaped == NULL) {
+                 xmlFreeURI(puri);
+                 return(NULL);
+             }
+             URI = unescaped;
+        }
+        xmlFreeURI(puri);
     }
 
     /*
-     * Try to find one of the output accept method accepting that scheme
-     * Go in reverse to give precedence to user defined handlers.
-     * try with an unescaped version of the URI
+     * Allocate the Output buffer front-end.
      */
-    if (unescaped != NULL) {
-#ifdef LIBXML_ZLIB_ENABLED
-	if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
-	    context = xmlGzfileOpenW(unescaped, compression);
-	    if (context != NULL) {
-		ret = xmlAllocOutputBufferInternal(encoder);
-		if (ret != NULL) {
-		    ret->context = context;
-		    ret->writecallback = xmlGzfileWrite;
-		    ret->closecallback = xmlGzfileClose;
-		}
-		xmlFree(unescaped);
-		return(ret);
-	    }
-	}
-#endif
-	for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
-	    if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
-		(xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) {
-#if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
-		/*  Need to pass compression parameter into HTTP open calls  */
-		if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
-		    context = xmlIOHTTPOpenW(unescaped, compression);
-		else
-#endif
-		    context = xmlOutputCallbackTable[i].opencallback(unescaped);
-		if (context != NULL)
-		    break;
-	    }
-	}
-	xmlFree(unescaped);
+    ret = xmlAllocOutputBufferInternal(encoder);
+    if (ret == NULL) {
+        xmlFree(unescaped);
+        return(NULL);
     }
 
     /*
-     * If this failed try with a non-escaped URI this may be a strange
-     * filename
+     * Try to find one of the output accept method accepting that scheme
+     * Go in reverse to give precedence to user defined handlers.
      */
-    if (context == NULL) {
-#ifdef LIBXML_ZLIB_ENABLED
-	if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
-	    context = xmlGzfileOpenW(URI, compression);
-	    if (context != NULL) {
-		ret = xmlAllocOutputBufferInternal(encoder);
-		if (ret != NULL) {
-		    ret->context = context;
-		    ret->writecallback = xmlGzfileWrite;
-		    ret->closecallback = xmlGzfileClose;
-		}
-		else
-		    xmlGzfileClose(context);
-		return(ret);
-	    }
-	}
-#endif
-	for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
-	    if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
-		(xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
-#if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
-		/*  Need to pass compression parameter into HTTP open calls  */
-		if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
-		    context = xmlIOHTTPOpenW(URI, compression);
-		else
-#endif
-		    context = xmlOutputCallbackTable[i].opencallback(URI);
-		if (context != NULL)
-		    break;
-	    }
-	}
-    }
+    for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
+        xmlOutputCallback *cb = &xmlOutputCallbackTable[i];
+        int code;
 
-    if (context == NULL) {
-	return(NULL);
+        if (cb->matchcallback == xmlIODefaultMatch) {
+            code = xmlOutputDefaultOpen(ret, URI, compression);
+            /* TODO: Handle other errors */
+            if (code == XML_ERR_OK)
+                break;
+        } else if ((cb->matchcallback != NULL) &&
+                   (cb->matchcallback(URI) != 0)) {
+            ret->context = cb->opencallback(URI);
+            if (ret->context != NULL) {
+                ret->writecallback = cb->writecallback;
+                ret->closecallback = cb->closecallback;
+                break;
+            }
+        }
     }
 
-    /*
-     * Allocate the Output buffer front-end.
-     */
-    ret = xmlAllocOutputBufferInternal(encoder);
-    if (ret != NULL) {
-	ret->context = context;
-	ret->writecallback = xmlOutputCallbackTable[i].writecallback;
-	ret->closecallback = xmlOutputCallbackTable[i].closecallback;
+    if (ret->context == NULL) {
+        xmlOutputBufferClose(ret);
+	ret = NULL;
     }
+
+    xmlFree(unescaped);
     return(ret);
 }
 
@@ -2789,27 +1773,28 @@ xmlOutputBufferCreateFilename(const char *URI,
 /**
  * xmlParserInputBufferCreateFile:
  * @file:  a FILE*
- * @enc:  the charset encoding if known
+ * @enc:  the charset encoding if known (deprecated)
  *
  * Create a buffered parser input for the progressive parsing of a FILE *
  * buffered C I/O
  *
+ * The encoding argument is deprecated and should be set to
+ * XML_CHAR_ENCODING_NONE. The encoding can be changed with
+ * xmlSwitchEncoding or xmlSwitchEncodingName later on.
+ *
  * Returns the new parser input or NULL
  */
 xmlParserInputBufferPtr
 xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
     xmlParserInputBufferPtr ret;
 
-    if (xmlInputCallbackInitialized == 0)
-	xmlRegisterDefaultInputCallbacks();
-
     if (file == NULL) return(NULL);
 
     ret = xmlAllocParserInputBuffer(enc);
     if (ret != NULL) {
         ret->context = file;
 	ret->readcallback = xmlFileRead;
-	ret->closecallback = xmlFileFlush;
+	ret->closecallback = NULL;
     }
 
     return(ret);
@@ -2830,9 +1815,6 @@ xmlOutputBufferPtr
 xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
     xmlOutputBufferPtr ret;
 
-    if (xmlOutputCallbackInitialized == 0)
-	xmlRegisterDefaultOutputCallbacks();
-
     if (file == NULL) return(NULL);
 
     ret = xmlAllocOutputBufferInternal(encoder);
@@ -2877,7 +1859,7 @@ xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
  */
 const xmlChar *
 xmlOutputBufferGetContent(xmlOutputBufferPtr out) {
-    if ((out == NULL) || (out->buffer == NULL))
+    if ((out == NULL) || (out->buffer == NULL) || (out->error != 0))
         return(NULL);
 
     return(xmlBufContent(out->buffer));
@@ -2893,7 +1875,7 @@ xmlOutputBufferGetContent(xmlOutputBufferPtr out) {
  */
 size_t
 xmlOutputBufferGetSize(xmlOutputBufferPtr out) {
-    if ((out == NULL) || (out->buffer == NULL))
+    if ((out == NULL) || (out->buffer == NULL) || (out->error != 0))
         return(0);
 
     return(xmlBufUse(out->buffer));
@@ -2905,11 +1887,15 @@ xmlOutputBufferGetSize(xmlOutputBufferPtr out) {
 /**
  * xmlParserInputBufferCreateFd:
  * @fd:  a file descriptor number
- * @enc:  the charset encoding if known
+ * @enc:  the charset encoding if known (deprecated)
  *
  * Create a buffered parser input for the progressive parsing for the input
  * from a file descriptor
  *
+ * The encoding argument is deprecated and should be set to
+ * XML_CHAR_ENCODING_NONE. The encoding can be changed with
+ * xmlSwitchEncoding or xmlSwitchEncodingName later on.
+ *
  * Returns the new parser input or NULL
  */
 xmlParserInputBufferPtr
@@ -2922,87 +1908,207 @@ xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
     if (ret != NULL) {
         ret->context = (void *) (ptrdiff_t) fd;
 	ret->readcallback = xmlFdRead;
-	ret->closecallback = xmlFdClose;
     }
 
     return(ret);
 }
 
+typedef struct {
+    char *mem;
+    const char *cur;
+    size_t size;
+} xmlMemIOCtxt;
+
+static int
+xmlMemRead(void *vctxt, char *buf, int size) {
+    xmlMemIOCtxt *ctxt = vctxt;
+
+    if ((size_t) size > ctxt->size)
+        size = ctxt->size;
+
+    memcpy(buf, ctxt->cur, size);
+    ctxt->cur += size;
+    ctxt->size -= size;
+
+    return size;
+}
+
+static int
+xmlMemClose(void *vctxt) {
+    xmlMemIOCtxt *ctxt = vctxt;
+
+    if (ctxt->mem != NULL)
+        xmlFree(ctxt->mem);
+    xmlFree(ctxt);
+    return(0);
+}
+
 /**
- * xmlParserInputBufferCreateMem:
- * @mem:  the memory input
- * @size:  the length of the memory block
- * @enc:  the charset encoding if known
+ * xmlNewInputBufferMemory:
+ * @mem:  memory buffer
+ * @size:  size of buffer
+ * @flags:  flags
+ * @enc:  the charset encoding if known (deprecated)
  *
- * Create a buffered parser input for the progressive parsing for the input
- * from a memory area.
+ * Create an input buffer for memory.
  *
- * Returns the new parser input or NULL
+ * Returns the new input buffer or NULL.
  */
 xmlParserInputBufferPtr
-xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
+xmlNewInputBufferMemory(const void *mem, size_t size, int flags,
+                        xmlCharEncoding enc) {
     xmlParserInputBufferPtr ret;
-    int errcode;
+    xmlMemIOCtxt *ctxt;
+    char *copy = NULL;
+
+    if ((flags & XML_INPUT_BUF_STATIC) == 0) {
+        if (size + 1 == 0)
+            return(NULL);
+        copy = xmlMalloc(size + 1);
+        if (copy == NULL)
+            return(NULL);
+        memcpy(copy, mem, size);
+        copy[size] = 0;
 
-    if (size < 0) return(NULL);
-    if (mem == NULL) return(NULL);
+        mem = copy;
+    }
 
     ret = xmlAllocParserInputBuffer(enc);
-    if (ret != NULL) {
-        ret->context = (void *) mem;
-	ret->readcallback = xmlInputReadCallbackNop;
-	ret->closecallback = NULL;
-	errcode = xmlBufAdd(ret->buffer, (const xmlChar *) mem, size);
-	if (errcode != 0) {
-	    xmlFree(ret);
-	    return(NULL);
-	}
+    if (ret == NULL) {
+        xmlFree(copy);
+        return(NULL);
+    }
+
+    ctxt = xmlMalloc(sizeof(*ctxt));
+    if (ctxt == NULL) {
+        xmlFreeParserInputBuffer(ret);
+        xmlFree(copy);
+        return(NULL);
     }
 
+    ctxt->mem = copy;
+    ctxt->cur = mem;
+    ctxt->size = size;
+
+    ret->context = ctxt;
+    ret->readcallback = xmlMemRead;
+    ret->closecallback = xmlMemClose;
+
     return(ret);
 }
 
+/**
+ * xmlParserInputBufferCreateMem:
+ * @mem:  the memory input
+ * @size:  the length of the memory block
+ * @enc:  the charset encoding if known (deprecated)
+ *
+ * Create a parser input buffer for parsing from a memory area.
+ *
+ * This function makes a copy of the whole input buffer. If you are sure
+ * that the contents of the buffer will remain valid until the document
+ * was parsed, you can avoid the copy by using
+ * xmlParserInputBufferCreateStatic.
+ *
+ * The encoding argument is deprecated and should be set to
+ * XML_CHAR_ENCODING_NONE. The encoding can be changed with
+ * xmlSwitchEncoding or xmlSwitchEncodingName later on.
+ *
+ * Returns the new parser input or NULL in case of error.
+ */
+xmlParserInputBufferPtr
+xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
+    if ((mem == NULL) || (size < 0))
+        return(NULL);
+
+    return(xmlNewInputBufferMemory(mem, size, 0, enc));
+}
+
 /**
  * xmlParserInputBufferCreateStatic:
  * @mem:  the memory input
  * @size:  the length of the memory block
  * @enc:  the charset encoding if known
  *
- * Create a buffered parser input for the progressive parsing for the input
- * from an immutable memory area. This will not copy the memory area to
- * the buffer, but the memory is expected to be available until the end of
- * the parsing, this is useful for example when using mmap'ed file.
+ * Create a parser input buffer for parsing from a memory area.
  *
- * Returns the new parser input or NULL
+ * This functions assumes that the contents of the input buffer remain
+ * valid until the document was parsed. Use xmlParserInputBufferCreateMem
+ * otherwise.
+ *
+ * The encoding argument is deprecated and should be set to
+ * XML_CHAR_ENCODING_NONE. The encoding can be changed with
+ * xmlSwitchEncoding or xmlSwitchEncodingName later on.
+ *
+ * Returns the new parser input or NULL in case of error.
  */
 xmlParserInputBufferPtr
 xmlParserInputBufferCreateStatic(const char *mem, int size,
                                  xmlCharEncoding enc) {
+    if ((mem == NULL) || (size < 0))
+        return(NULL);
+
+    return(xmlNewInputBufferMemory(mem, size, XML_INPUT_BUF_STATIC, enc));
+}
+
+typedef struct {
+    const char *str;
+} xmlStringIOCtxt;
+
+static int
+xmlStringRead(void *vctxt, char *buf, int size) {
+    xmlStringIOCtxt *ctxt = vctxt;
+    const char *zero;
+    size_t len;
+
+    zero = memchr(ctxt->str, 0, size);
+    len = zero ? zero - ctxt->str : size;
+
+    memcpy(buf, ctxt->str, len);
+    ctxt->str += len;
+
+    return(len);
+}
+
+static int
+xmlStringClose(void *vctxt) {
+    xmlFree(vctxt);
+    return(0);
+}
+
+/**
+ * xmlNewInputBufferString:
+ * @str:  C string
+ * @flags:  flags
+ *
+ * Create an input buffer for a null-teriminated C string.
+ *
+ * Returns the new input buffer or NULL.
+ */
+xmlParserInputBufferPtr
+xmlNewInputBufferString(const char *str, int flags) {
     xmlParserInputBufferPtr ret;
+    xmlStringIOCtxt *ctxt;
 
-    if (size < 0) return(NULL);
-    if (mem == NULL) return(NULL);
+    if ((flags & XML_INPUT_BUF_STATIC) == 0)
+        return(xmlNewInputBufferMemory(str, strlen(str), flags,
+                                       XML_CHAR_ENCODING_NONE));
 
-    ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
-    if (ret == NULL) {
-	xmlIOErrMemory("creating input buffer");
-	return(NULL);
-    }
-    memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
-    ret->buffer = xmlBufCreateStatic((void *)mem, (size_t) size);
-    if (ret->buffer == NULL) {
-        xmlFree(ret);
-	return(NULL);
+    ret = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
+    if (ret == NULL)
+        return(NULL);
+
+    ctxt = xmlMalloc(sizeof(*ctxt));
+    if (ctxt == NULL) {
+        xmlFreeParserInputBuffer(ret);
+        return(NULL);
     }
-    ret->encoder = xmlGetCharEncodingHandler(enc);
-    if (ret->encoder != NULL)
-        ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
-    else
-        ret->raw = NULL;
-    ret->compressed = -1;
-    ret->context = (void *) mem;
-    ret->readcallback = NULL;
-    ret->closecallback = NULL;
+
+    ctxt->str = str;
+
+    ret->context = ctxt;
+    ret->readcallback = xmlStringRead;
+    ret->closecallback = xmlStringClose;
 
     return(ret);
 }
@@ -3040,11 +2146,15 @@ xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
  * @ioread:  an I/O read function
  * @ioclose:  an I/O close function
  * @ioctx:  an I/O handler
- * @enc:  the charset encoding if known
+ * @enc:  the charset encoding if known (deprecated)
  *
  * Create a buffered parser input for the progressive parsing for the input
  * from an I/O handler
  *
+ * The encoding argument is deprecated and should be set to
+ * XML_CHAR_ENCODING_NONE. The encoding can be changed with
+ * xmlSwitchEncoding or xmlSwitchEncodingName later on.
+ *
  * Returns the new parser input or NULL
  */
 xmlParserInputBufferPtr
@@ -3105,13 +2215,17 @@ xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
  * Returns the old value of the registration function
  */
 xmlParserInputBufferCreateFilenameFunc
-xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
+xmlParserInputBufferCreateFilenameDefault(
+        xmlParserInputBufferCreateFilenameFunc func)
 {
-    xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue;
-    if (old == NULL) {
-		old = __xmlParserInputBufferCreateFilename;
-	}
+    xmlParserInputBufferCreateFilenameFunc old;
 
+    old = xmlParserInputBufferCreateFilenameValue;
+    if (old == NULL)
+        old = __xmlParserInputBufferCreateFilename;
+
+    if (func == __xmlParserInputBufferCreateFilename)
+        func = NULL;
     xmlParserInputBufferCreateFilenameValue = func;
     return(old);
 }
@@ -3159,40 +2273,36 @@ xmlParserInputBufferPush(xmlParserInputBufferPtr in,
     if (len < 0) return(0);
     if ((in == NULL) || (in->error)) return(-1);
     if (in->encoder != NULL) {
-        unsigned int use;
-
         /*
 	 * Store the data in the incoming raw buffer
 	 */
         if (in->raw == NULL) {
 	    in->raw = xmlBufCreate();
+            if (in->raw == NULL) {
+                in->error = XML_ERR_NO_MEMORY;
+                return(-1);
+            }
 	}
 	ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
-	if (ret != 0)
+	if (ret != 0) {
+            in->error = XML_ERR_NO_MEMORY;
 	    return(-1);
+        }
 
 	/*
 	 * convert as much as possible to the parser reading buffer.
 	 */
-	use = xmlBufUse(in->raw);
-	nbchars = xmlCharEncInput(in, 1);
-	if (nbchars < 0) {
-	    xmlIOErr(XML_IO_ENCODER, NULL);
-	    in->error = XML_IO_ENCODER;
+	nbchars = xmlCharEncInput(in);
+	if (nbchars < 0)
 	    return(-1);
-	}
-	in->rawconsumed += (use - xmlBufUse(in->raw));
     } else {
 	nbchars = len;
         ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
-	if (ret != 0)
+	if (ret != 0) {
+            in->error = XML_ERR_NO_MEMORY;
 	    return(-1);
+        }
     }
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext,
-	    "I/O: pushed %d chars, buffer %d/%d\n",
-            nbchars, xmlBufUse(in->buffer), xmlBufLength(in->buffer));
-#endif
     return(nbchars);
 }
 
@@ -3226,41 +2336,48 @@ endOfInput (void * context ATTRIBUTE_UNUSED,
  */
 int
 xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
-    char *buffer = NULL;
+    xmlBufPtr buf;
     int res = 0;
-    int nbchars = 0;
 
     if ((in == NULL) || (in->error)) return(-1);
     if ((len <= MINLEN) && (len != 4))
         len = MINLEN;
 
-    if (xmlBufAvail(in->buffer) <= 0) {
-	xmlIOErr(XML_IO_BUFFER_FULL, NULL);
-	in->error = XML_IO_BUFFER_FULL;
-	return(-1);
-    }
-
-    if (xmlBufGrow(in->buffer, len + 1) < 0) {
-        xmlIOErrMemory("growing input buffer");
-        in->error = XML_ERR_NO_MEMORY;
-        return(-1);
+    if (in->encoder == NULL) {
+        if (in->readcallback == NULL)
+            return(0);
+        buf = in->buffer;
+    } else {
+        if (in->raw == NULL) {
+	    in->raw = xmlBufCreate();
+	}
+        buf = in->raw;
     }
-    buffer = (char *)xmlBufEnd(in->buffer);
 
     /*
      * Call the read method for this I/O type.
      */
     if (in->readcallback != NULL) {
-	res = in->readcallback(in->context, &buffer[0], len);
+        if (xmlBufGrow(buf, len + 1) < 0) {
+            in->error = XML_ERR_NO_MEMORY;
+            return(-1);
+        }
+
+	res = in->readcallback(in->context, (char *)xmlBufEnd(buf), len);
 	if (res <= 0)
 	    in->readcallback = endOfInput;
-    } else {
-	xmlIOErr(XML_IO_NO_INPUT, NULL);
-	in->error = XML_IO_NO_INPUT;
-	return(-1);
-    }
-    if (res < 0) {
-	return(-1);
+        if (res < 0) {
+            if (res == -1)
+                in->error = XML_IO_UNKNOWN;
+            else
+                in->error = -res;
+            return(-1);
+        }
+
+        if (xmlBufAddLen(buf, res) < 0) {
+            in->error = XML_ERR_NO_MEMORY;
+            return(-1);
+        }
     }
 
     /*
@@ -3273,41 +2390,12 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
 #endif
     }
 
-    len = res;
     if (in->encoder != NULL) {
-        unsigned int use;
-
-        /*
-	 * Store the data in the incoming raw buffer
-	 */
-        if (in->raw == NULL) {
-	    in->raw = xmlBufCreate();
-	}
-	res = xmlBufAdd(in->raw, (const xmlChar *) buffer, len);
-	if (res != 0)
-	    return(-1);
-
-	/*
-	 * convert as much as possible to the parser reading buffer.
-	 */
-	use = xmlBufUse(in->raw);
-	nbchars = xmlCharEncInput(in, 1);
-	if (nbchars < 0) {
-	    xmlIOErr(XML_IO_ENCODER, NULL);
-	    in->error = XML_IO_ENCODER;
+	res = xmlCharEncInput(in);
+	if (res < 0)
 	    return(-1);
-	}
-	in->rawconsumed += (use - xmlBufUse(in->raw));
-    } else {
-	nbchars = len;
-        xmlBufAddLen(in->buffer, nbchars);
     }
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext,
-	    "I/O: read %d chars, buffer %d\n",
-            nbchars, xmlBufUse(in->buffer));
-#endif
-    return(nbchars);
+    return(res);
 }
 
 /**
@@ -3324,13 +2412,7 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
  */
 int
 xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
-    if ((in == NULL) || (in->error)) return(-1);
-    if (in->readcallback != NULL)
-	return(xmlParserInputBufferGrow(in, len));
-    else if (xmlBufGetAllocationScheme(in->buffer) == XML_BUFFER_ALLOC_IMMUTABLE)
-	return(0);
-    else
-        return(-1);
+    return(xmlParserInputBufferGrow(in, len));
 }
 
 #ifdef LIBXML_OUTPUT_ENABLED
@@ -3373,10 +2455,16 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
 	     */
 	    if (out->conv == NULL) {
 		out->conv = xmlBufCreate();
+                if (out->conv == NULL) {
+                    out->error = XML_ERR_NO_MEMORY;
+                    return(-1);
+                }
 	    }
 	    ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
-	    if (ret != 0)
+	    if (ret != 0) {
+                out->error = XML_ERR_NO_MEMORY;
 	        return(-1);
+            }
 
 	    if ((xmlBufUse(out->buffer) < MINLEN) && (chunk == len))
 		goto done;
@@ -3385,19 +2473,18 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
 	     * convert as much as possible to the parser reading buffer.
 	     */
 	    ret = xmlCharEncOutput(out, 0);
-	    if ((ret < 0) && (ret != -3)) {
-		xmlIOErr(XML_IO_ENCODER, NULL);
-		out->error = XML_IO_ENCODER;
+	    if (ret < 0)
 		return(-1);
-	    }
             if (out->writecallback)
 	        nbchars = xmlBufUse(out->conv);
             else
                 nbchars = ret >= 0 ? ret : 0;
 	} else {
 	    ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
-	    if (ret != 0)
+	    if (ret != 0) {
+                out->error = XML_ERR_NO_MEMORY;
 	        return(-1);
+            }
             if (out->writecallback)
 	        nbchars = xmlBufUse(out->buffer);
             else
@@ -3425,8 +2512,10 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
 		    xmlBufShrink(out->buffer, ret);
 	    }
 	    if (ret < 0) {
-		xmlIOErr(XML_IO_WRITE, NULL);
-		out->error = XML_IO_WRITE;
+                int errNo = (ret == -1) ? XML_IO_WRITE : -ret;
+
+		xmlIOErr(errNo, NULL);
+		out->error = errNo;
 		return(ret);
 	    }
             if (out->written > INT_MAX - ret)
@@ -3438,10 +2527,6 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
     } while (len > 0);
 
 done:
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext,
-	    "I/O: wrote %d chars\n", written);
-#endif
     return(written);
 }
 
@@ -3496,7 +2581,7 @@ xmlEscapeContent(unsigned char* out, int *outlen,
 	    *out++ = '3';
 	    *out++ = ';';
 	} else {
-	    *out++ = (unsigned char) *in;
+	    *out++ = *in;
 	}
 	++in;
     }
@@ -3532,8 +2617,7 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
     int cons;        /* byte from str consumed */
 
     if ((out == NULL) || (out->error) || (str == NULL) ||
-        (out->buffer == NULL) ||
-	(xmlBufGetAllocationScheme(out->buffer) == XML_BUFFER_ALLOC_IMMUTABLE))
+        (out->buffer == NULL))
         return(-1);
     len = strlen((const char *)str);
     if (len < 0) return(0);
@@ -3554,8 +2638,10 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
 	 * not the case force a flush, but make sure we stay in the loop
 	 */
 	if (chunk < 40) {
-	    if (xmlBufGrow(out->buffer, 100) < 0)
+	    if (xmlBufGrow(out->buffer, 100) < 0) {
+                out->error = XML_ERR_NO_MEMORY;
 	        return(-1);
+            }
             oldwritten = -1;
 	    continue;
 	}
@@ -3569,11 +2655,17 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
 	     */
 	    if (out->conv == NULL) {
 		out->conv = xmlBufCreate();
+                if (out->conv == NULL) {
+                    out->error = XML_ERR_NO_MEMORY;
+                    return(-1);
+                }
 	    }
 	    ret = escaping(xmlBufEnd(out->buffer) ,
 	                   &chunk, str, &cons);
-	    if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
-	        return(-1);
+            if (ret < 0) {
+                out->error = XML_ERR_NO_MEMORY;
+                return(-1);
+            }
             xmlBufAddLen(out->buffer, chunk);
 
 	    if ((xmlBufUse(out->buffer) < MINLEN) && (cons == len))
@@ -3583,19 +2675,18 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
 	     * convert as much as possible to the output buffer.
 	     */
 	    ret = xmlCharEncOutput(out, 0);
-	    if ((ret < 0) && (ret != -3)) {
-		xmlIOErr(XML_IO_ENCODER, NULL);
-		out->error = XML_IO_ENCODER;
+	    if (ret < 0)
 		return(-1);
-	    }
             if (out->writecallback)
 	        nbchars = xmlBufUse(out->conv);
             else
                 nbchars = ret >= 0 ? ret : 0;
 	} else {
 	    ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons);
-	    if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
-	        return(-1);
+            if (ret < 0) {
+                out->error = XML_ERR_NO_MEMORY;
+                return(-1);
+            }
             xmlBufAddLen(out->buffer, chunk);
             if (out->writecallback)
 	        nbchars = xmlBufUse(out->buffer);
@@ -3624,25 +2715,25 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
 		    xmlBufShrink(out->buffer, ret);
 	    }
 	    if (ret < 0) {
-		xmlIOErr(XML_IO_WRITE, NULL);
-		out->error = XML_IO_WRITE;
-		return(ret);
+                int errNo = (ret == -1) ? XML_IO_WRITE : -ret;
+		xmlIOErr(errNo, NULL);
+		out->error = errNo;
+		return(-1);
 	    }
             if (out->written > INT_MAX - ret)
                 out->written = INT_MAX;
             else
                 out->written += ret;
 	} else if (xmlBufAvail(out->buffer) < MINLEN) {
-	    xmlBufGrow(out->buffer, MINLEN);
+            if (xmlBufGrow(out->buffer, MINLEN) < 0) {
+                out->error = XML_ERR_NO_MEMORY;
+                return(-1);
+            }
 	}
 	written += nbchars;
     } while ((len > 0) && (oldwritten != written));
 
 done:
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext,
-	    "I/O: wrote %d chars\n", written);
-#endif
     return(written);
 }
 
@@ -3673,6 +2764,56 @@ xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
     return(len);
 }
 
+/**
+ * xmlOutputBufferWriteQuotedString:
+ * @buf:  output buffer
+ * @string:  the string to add
+ *
+ * routine which manage and grows an output buffer. This one writes
+ * a quoted or double quoted #xmlChar string, checking first if it holds
+ * quote or double-quotes internally
+ */
+void
+xmlOutputBufferWriteQuotedString(xmlOutputBufferPtr buf,
+                                 const xmlChar *string) {
+    const xmlChar *cur, *base;
+
+    if ((buf == NULL) || (buf->error))
+        return;
+
+    if (xmlStrchr(string, '\"')) {
+        if (xmlStrchr(string, '\'')) {
+	    xmlOutputBufferWrite(buf, 1, "\"");
+            base = cur = string;
+            while(*cur != 0){
+                if(*cur == '"'){
+                    if (base != cur)
+                        xmlOutputBufferWrite(buf, cur - base,
+                                             (const char *) base);
+                    xmlOutputBufferWrite(buf, 6, "&quot;");
+                    cur++;
+                    base = cur;
+                }
+                else {
+                    cur++;
+                }
+            }
+            if (base != cur)
+                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
+	    xmlOutputBufferWrite(buf, 1, "\"");
+	}
+        else{
+	    xmlOutputBufferWrite(buf, 1, "'");
+            xmlOutputBufferWriteString(buf, (const char *) string);
+	    xmlOutputBufferWrite(buf, 1, "'");
+        }
+    } else {
+        xmlOutputBufferWrite(buf, 1, "\"");
+        xmlOutputBufferWriteString(buf, (const char *) string);
+        xmlOutputBufferWrite(buf, 1, "\"");
+    }
+}
+
 /**
  * xmlOutputBufferFlush:
  * @out:  a buffered output
@@ -3695,11 +2836,8 @@ xmlOutputBufferFlush(xmlOutputBufferPtr out) {
 	 */
 	do {
 	    nbchars = xmlCharEncOutput(out, 0);
-	    if (nbchars < 0) {
-		xmlIOErr(XML_IO_ENCODER, NULL);
-		out->error = XML_IO_ENCODER;
+	    if (nbchars < 0)
 		return(-1);
-	    }
 	} while (nbchars);
     }
 
@@ -3721,8 +2859,10 @@ xmlOutputBufferFlush(xmlOutputBufferPtr out) {
 	    xmlBufShrink(out->buffer, ret);
     }
     if (ret < 0) {
-	xmlIOErr(XML_IO_FLUSH, NULL);
-	out->error = XML_IO_FLUSH;
+        int errNo = (ret == -1) ? XML_IO_WRITE : -ret;
+
+        xmlIOErr(errNo, NULL);
+        out->error = errNo;
 	return(ret);
     }
     if (out->written > INT_MAX - ret)
@@ -3730,10 +2870,6 @@ xmlOutputBufferFlush(xmlOutputBufferPtr out) {
     else
         out->written += ret;
 
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext,
-	    "I/O: flushed %d chars\n", ret);
-#endif
     return(ret);
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
@@ -3752,9 +2888,6 @@ xmlParserGetDirectory(const char *filename) {
     char dir[1024];
     char *cur;
 
-    if (xmlInputCallbackInitialized == 0)
-	xmlRegisterDefaultInputCallbacks();
-
     if (filename == NULL) return(NULL);
 
 #if defined(_WIN32)
@@ -3775,347 +2908,220 @@ xmlParserGetDirectory(const char *filename) {
 	else *cur = 0;
 	ret = xmlMemStrdup(dir);
     } else {
-        if (getcwd(dir, 1024) != NULL) {
-	    dir[1023] = 0;
-	    ret = xmlMemStrdup(dir);
-	}
+        ret = xmlMemStrdup(".");
     }
     return(ret);
 #undef IS_XMLPGD_SEP
 }
 
-/****************************************************************
- *								*
- *		External entities loading			*
- *								*
- ****************************************************************/
-
 /**
- * xmlCheckHTTPInput:
- * @ctxt: an XML parser context
- * @ret: an XML parser input
+ * xmlNoNetExists:
+ * @filename:  the path to check
+ *
+ * DEPRECATED: Internal function, don't use.
  *
- * Check an input in case it was created from an HTTP stream, in that
- * case it will handle encoding and update of the base URL in case of
- * redirection. It also checks for HTTP errors in which case the input
- * is cleanly freed up and an appropriate error is raised in context
+ * Like xmlCheckFilename but handles file URIs.
  *
- * Returns the input or NULL in case of HTTP error.
+ * Returns 0, 1, or 2.
  */
-xmlParserInputPtr
-xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
-    /* Avoid unused variable warning if features are disabled. */
-    (void) ctxt;
+int
+xmlNoNetExists(const char *filename) {
+    char *fromUri;
+    int ret;
 
-#ifdef LIBXML_HTTP_ENABLED
-    if ((ret != NULL) && (ret->buf != NULL) &&
-        (ret->buf->readcallback == xmlIOHTTPRead) &&
-        (ret->buf->context != NULL)) {
-        const char *encoding;
-        const char *redir;
-        const char *mime;
-        int code;
+    if (filename == NULL)
+	return(0);
 
-        code = xmlNanoHTTPReturnCode(ret->buf->context);
-        if (code >= 400) {
-            /* fatal error */
-	    if (ret->filename != NULL)
-		__xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
-                         (const char *) ret->filename);
-	    else
-		__xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
-            xmlFreeInputStream(ret);
-            ret = NULL;
-        } else {
+    if (xmlConvertUriToPath(filename, &fromUri) < 0)
+        return(0);
 
-            mime = xmlNanoHTTPMimeType(ret->buf->context);
-            if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
-                (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
-                encoding = xmlNanoHTTPEncoding(ret->buf->context);
-                if (encoding != NULL) {
-                    xmlCharEncodingHandlerPtr handler;
-
-                    handler = xmlFindCharEncodingHandler(encoding);
-                    if (handler != NULL) {
-                        xmlSwitchInputEncoding(ctxt, ret, handler);
-                    } else {
-                        __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
-                                         "Unknown encoding %s",
-                                         BAD_CAST encoding, NULL);
-                    }
-                    if (ret->encoding == NULL)
-                        ret->encoding = xmlStrdup(BAD_CAST encoding);
-                }
-#if 0
-            } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
-#endif
-            }
-            redir = xmlNanoHTTPRedir(ret->buf->context);
-            if (redir != NULL) {
-                if (ret->filename != NULL)
-                    xmlFree((xmlChar *) ret->filename);
-                if (ret->directory != NULL) {
-                    xmlFree((xmlChar *) ret->directory);
-                    ret->directory = NULL;
-                }
-                ret->filename =
-                    (char *) xmlStrdup((const xmlChar *) redir);
-            }
-        }
-    }
-#endif
+    if (fromUri != NULL)
+        filename = fromUri;
+
+    ret =  xmlCheckFilename(filename);
+
+    xmlFree(fromUri);
     return(ret);
 }
 
-static int xmlNoNetExists(const char *URL) {
-    const char *path;
+/************************************************************************
+ *									*
+ *			Input/output callbacks				*
+ *									*
+ ************************************************************************/
 
-    if (URL == NULL)
-	return(0);
+/**
+ * xmlInitIOCallbacks:
+ *
+ * Initialize callback tables.
+ */
+void
+xmlInitIOCallbacks(void)
+{
+    xmlInputCallbackNr = 1;
+    xmlInputCallbackTable[0].matchcallback = xmlIODefaultMatch;
 
-    if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17))
-#if defined (_WIN32)
-	path = &URL[17];
-#else
-	path = &URL[16];
-#endif
-    else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) {
-#if defined (_WIN32)
-	path = &URL[8];
-#else
-	path = &URL[7];
+#ifdef LIBXML_OUTPUT_ENABLED
+    xmlOutputCallbackNr = 1;
+    xmlOutputCallbackTable[0].matchcallback = xmlIODefaultMatch;
 #endif
-    } else
-	path = URL;
-
-    return xmlCheckFilename(path);
 }
 
-#ifdef LIBXML_CATALOG_ENABLED
-
 /**
- * xmlResolveResourceFromCatalog:
- * @URL:  the URL for the entity to load
- * @ID:  the System ID for the entity to load
- * @ctxt:  the context in which the entity is called or NULL
+ * xmlRegisterInputCallbacks:
+ * @matchFunc:  the xmlInputMatchCallback
+ * @openFunc:  the xmlInputOpenCallback
+ * @readFunc:  the xmlInputReadCallback
+ * @closeFunc:  the xmlInputCloseCallback
  *
- * Resolves the URL and ID against the appropriate catalog.
- * This function is used by xmlDefaultExternalEntityLoader and
- * xmlNoNetExternalEntityLoader.
+ * Register a new set of I/O callback for handling parser input.
  *
- * Returns a new allocated URL, or NULL.
+ * Returns the registered handler number or -1 in case of error
  */
-static xmlChar *
-xmlResolveResourceFromCatalog(const char *URL, const char *ID,
-                              xmlParserCtxtPtr ctxt) {
-    xmlChar *resource = NULL;
-    xmlCatalogAllow pref;
-
-    /*
-     * If the resource doesn't exists as a file,
-     * try to load it from the resource pointed in the catalogs
-     */
-    pref = xmlCatalogGetDefaults();
-
-    if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) {
-	/*
-	 * Do a local lookup
-	 */
-	if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
-	    ((pref == XML_CATA_ALLOW_ALL) ||
-	     (pref == XML_CATA_ALLOW_DOCUMENT))) {
-	    resource = xmlCatalogLocalResolve(ctxt->catalogs,
-					      (const xmlChar *)ID,
-					      (const xmlChar *)URL);
-        }
-	/*
-	 * Try a global lookup
-	 */
-	if ((resource == NULL) &&
-	    ((pref == XML_CATA_ALLOW_ALL) ||
-	     (pref == XML_CATA_ALLOW_GLOBAL))) {
-	    resource = xmlCatalogResolve((const xmlChar *)ID,
-					 (const xmlChar *)URL);
-	}
-	if ((resource == NULL) && (URL != NULL))
-	    resource = xmlStrdup((const xmlChar *) URL);
-
-	/*
-	 * TODO: do an URI lookup on the reference
-	 */
-	if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) {
-	    xmlChar *tmp = NULL;
-
-	    if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
-		((pref == XML_CATA_ALLOW_ALL) ||
-		 (pref == XML_CATA_ALLOW_DOCUMENT))) {
-		tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
-	    }
-	    if ((tmp == NULL) &&
-		((pref == XML_CATA_ALLOW_ALL) ||
-	         (pref == XML_CATA_ALLOW_GLOBAL))) {
-		tmp = xmlCatalogResolveURI(resource);
-	    }
+int
+xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
+	xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
+	xmlInputCloseCallback closeFunc) {
+    xmlInitParser();
 
-	    if (tmp != NULL) {
-		xmlFree(resource);
-		resource = tmp;
-	    }
-	}
+    if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
+	return(-1);
     }
-
-    return resource;
+    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
+    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
+    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
+    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
+    return(xmlInputCallbackNr++);
 }
 
-#endif
+/**
+ * xmlRegisterDefaultInputCallbacks:
+ *
+ * Registers the default compiled-in I/O handlers.
+ */
+void
+xmlRegisterDefaultInputCallbacks(void) {
+    xmlRegisterInputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
+}
 
 /**
- * xmlDefaultExternalEntityLoader:
- * @URL:  the URL for the entity to load
- * @ID:  the System ID for the entity to load
- * @ctxt:  the context in which the entity is called or NULL
+ * xmlPopInputCallbacks:
  *
- * By default we don't load external entities, yet.
+ * Clear the top input callback from the input stack. this includes the
+ * compiled-in I/O.
  *
- * Returns a new allocated xmlParserInputPtr, or NULL.
+ * Returns the number of input callback registered or -1 in case of error.
  */
-static xmlParserInputPtr
-xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
-                               xmlParserCtxtPtr ctxt)
+int
+xmlPopInputCallbacks(void)
 {
-    xmlParserInputPtr ret = NULL;
-    xmlChar *resource = NULL;
-
-#ifdef DEBUG_EXTERNAL_ENTITIES
-    xmlGenericError(xmlGenericErrorContext,
-                    "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
-#endif
-    if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
-        int options = ctxt->options;
+    xmlInitParser();
 
-	ctxt->options -= XML_PARSE_NONET;
-        ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
-	ctxt->options = options;
-	return(ret);
-    }
-#ifdef LIBXML_CATALOG_ENABLED
-    resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
-#endif
+    if (xmlInputCallbackNr <= 0)
+        return(-1);
 
-    if (resource == NULL)
-        resource = (xmlChar *) URL;
+    xmlInputCallbackNr--;
 
-    if (resource == NULL) {
-        if (ID == NULL)
-            ID = "NULL";
-        __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
-        return (NULL);
-    }
-    ret = xmlNewInputFromFile(ctxt, (const char *) resource);
-    if ((resource != NULL) && (resource != (xmlChar *) URL))
-        xmlFree(resource);
-    return (ret);
+    return(xmlInputCallbackNr);
 }
 
-static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
-       xmlDefaultExternalEntityLoader;
-
 /**
- * xmlSetExternalEntityLoader:
- * @f:  the new entity resolver function
+ * xmlCleanupInputCallbacks:
  *
- * Changes the defaultexternal entity resolver function for the application
+ * clears the entire input callback table. this includes the
+ * compiled-in I/O.
  */
 void
-xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
-    xmlCurrentExternalEntityLoader = f;
+xmlCleanupInputCallbacks(void)
+{
+    xmlInitParser();
+
+    xmlInputCallbackNr = 0;
 }
 
+#ifdef LIBXML_OUTPUT_ENABLED
 /**
- * xmlGetExternalEntityLoader:
+ * xmlRegisterOutputCallbacks:
+ * @matchFunc:  the xmlOutputMatchCallback
+ * @openFunc:  the xmlOutputOpenCallback
+ * @writeFunc:  the xmlOutputWriteCallback
+ * @closeFunc:  the xmlOutputCloseCallback
+ *
+ * Register a new set of I/O callback for handling output.
  *
- * Get the default external entity resolver function for the application
+ * Returns the registered handler number or -1 in case of error
+ */
+int
+xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
+	xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
+	xmlOutputCloseCallback closeFunc) {
+    xmlInitParser();
+
+    if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
+	return(-1);
+    }
+    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
+    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
+    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
+    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
+    return(xmlOutputCallbackNr++);
+}
+
+/**
+ * xmlRegisterDefaultOutputCallbacks:
  *
- * Returns the xmlExternalEntityLoader function pointer
+ * Registers the default compiled-in I/O handlers.
  */
-xmlExternalEntityLoader
-xmlGetExternalEntityLoader(void) {
-    return(xmlCurrentExternalEntityLoader);
+void
+xmlRegisterDefaultOutputCallbacks (void) {
+    xmlRegisterOutputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
 }
 
 /**
- * xmlLoadExternalEntity:
- * @URL:  the URL for the entity to load
- * @ID:  the Public ID for the entity to load
- * @ctxt:  the context in which the entity is called or NULL
+ * xmlPopOutputCallbacks:
  *
- * Load an external entity, note that the use of this function for
- * unparsed entities may generate problems
+ * Remove the top output callbacks from the output stack. This includes the
+ * compiled-in I/O.
  *
- * Returns the xmlParserInputPtr or NULL
+ * Returns the number of output callback registered or -1 in case of error.
  */
-xmlParserInputPtr
-xmlLoadExternalEntity(const char *URL, const char *ID,
-                      xmlParserCtxtPtr ctxt) {
-    if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) {
-	char *canonicFilename;
-	xmlParserInputPtr ret;
-
-	canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
-	if (canonicFilename == NULL) {
-            xmlIOErrMemory("building canonical path\n");
-	    return(NULL);
-	}
+int
+xmlPopOutputCallbacks(void)
+{
+    xmlInitParser();
 
-	ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
-	xmlFree(canonicFilename);
-	return(ret);
-    }
-    return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
-}
+    if (xmlOutputCallbackNr <= 0)
+        return(-1);
 
-/************************************************************************
- *									*
- *		Disabling Network access				*
- *									*
- ************************************************************************/
+    xmlOutputCallbackNr--;
+
+    return(xmlOutputCallbackNr);
+}
 
 /**
- * xmlNoNetExternalEntityLoader:
- * @URL:  the URL for the entity to load
- * @ID:  the System ID for the entity to load
- * @ctxt:  the context in which the entity is called or NULL
- *
- * A specific entity loader disabling network accesses, though still
- * allowing local catalog accesses for resolution.
+ * xmlCleanupOutputCallbacks:
  *
- * Returns a new allocated xmlParserInputPtr, or NULL.
+ * clears the entire output callback table. this includes the
+ * compiled-in I/O callbacks.
  */
-xmlParserInputPtr
-xmlNoNetExternalEntityLoader(const char *URL, const char *ID,
-                             xmlParserCtxtPtr ctxt) {
-    xmlParserInputPtr input = NULL;
-    xmlChar *resource = NULL;
-
-#ifdef LIBXML_CATALOG_ENABLED
-    resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
-#endif
+void
+xmlCleanupOutputCallbacks(void)
+{
+    xmlInitParser();
 
-    if (resource == NULL)
-	resource = (xmlChar *) URL;
+    xmlOutputCallbackNr = 0;
+}
 
-    if (resource != NULL) {
-        if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
-            (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
-            xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource);
-	    if (resource != (xmlChar *) URL)
-		xmlFree(resource);
-	    return(NULL);
-	}
-    }
-    input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt);
-    if (resource != (xmlChar *) URL)
-	xmlFree(resource);
-    return(input);
+#ifdef LIBXML_HTTP_ENABLED
+/**
+ * xmlRegisterHTTPPostCallbacks:
+ *
+ * DEPRECATED: Support for HTTP POST has been removed.
+ */
+void
+xmlRegisterHTTPPostCallbacks(void) {
+    xmlRegisterDefaultOutputCallbacks();
 }
+#endif
+#endif /* LIBXML_OUTPUT_ENABLED */
 
diff --git a/xmlcatalog.c b/xmlcatalog.c
new file mode 100644
index 0000000000000000000000000000000000000000..cfc55132f3f05b8e94577cbf8aee5440715e0e95
--- /dev/null
+++ b/xmlcatalog.c
@@ -0,0 +1,614 @@
+/*
+ * xmlcatalog.c : a small utility program to handle XML catalogs
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#include "libxml.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#ifdef HAVE_LIBREADLINE
+#include <readline/readline.h>
+#ifdef HAVE_LIBHISTORY
+#include <readline/history.h>
+#endif
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/uri.h>
+#include <libxml/catalog.h>
+#include <libxml/parser.h>
+
+#if defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
+static int shell = 0;
+static int sgml = 0;
+static int noout = 0;
+static int create = 0;
+static int add = 0;
+static int del = 0;
+static int convert = 0;
+static int no_super_update = 0;
+static int verbose = 0;
+static char *filename = NULL;
+
+
+#ifndef XML_SGML_DEFAULT_CATALOG
+#define XML_SGML_DEFAULT_CATALOG SYSCONFDIR "/sgml/catalog"
+#endif
+
+/************************************************************************
+ *									*
+ *			Shell Interface					*
+ *									*
+ ************************************************************************/
+/**
+ * xmlShellReadline:
+ * @prompt:  the prompt value
+ *
+ * Read a string
+ *
+ * Returns a pointer to it or NULL on EOF the caller is expected to
+ *     free the returned string.
+ */
+static char *
+xmlShellReadline(const char *prompt) {
+#ifdef HAVE_LIBREADLINE
+    char *line_read;
+
+    /* Get a line from the user. */
+    line_read = readline (prompt);
+
+    /* If the line has any text in it, save it on the history. */
+    if (line_read && *line_read)
+	add_history (line_read);
+
+    return (line_read);
+#else
+    char line_read[501];
+    char *ret;
+    int len;
+
+    if (prompt != NULL)
+	fprintf(stdout, "%s", prompt);
+    fflush(stdout);
+    if (!fgets(line_read, 500, stdin))
+        return(NULL);
+    line_read[500] = 0;
+    len = strlen(line_read);
+    ret = (char *) malloc(len + 1);
+    if (ret != NULL) {
+	memcpy (ret, line_read, len + 1);
+    }
+    return(ret);
+#endif
+}
+
+static void usershell(void) {
+    char *cmdline = NULL, *cur;
+    int nbargs;
+    char command[100];
+    char arg[400];
+    char *argv[20];
+    int i, ret;
+    xmlChar *ans;
+
+    while (1) {
+	cmdline = xmlShellReadline("> ");
+	if (cmdline == NULL)
+	    return;
+
+	/*
+	 * Parse the command itself
+	 */
+	cur = cmdline;
+	nbargs = 0;
+	while ((*cur == ' ') || (*cur == '\t')) cur++;
+	i = 0;
+	while ((*cur != ' ') && (*cur != '\t') &&
+	       (*cur != '\n') && (*cur != '\r')) {
+	    if (*cur == 0)
+		break;
+	    command[i++] = *cur++;
+	}
+	command[i] = 0;
+	if (i == 0) {
+	    free(cmdline);
+	    continue;
+	}
+
+	/*
+	 * Parse the argument string
+	 */
+	memset(arg, 0, sizeof(arg));
+	while ((*cur == ' ') || (*cur == '\t')) cur++;
+	i = 0;
+	while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
+	    if (*cur == 0)
+		break;
+	    arg[i++] = *cur++;
+	}
+	arg[i] = 0;
+
+	/*
+	 * Parse the arguments
+	 */
+	i = 0;
+	nbargs = 0;
+	cur = arg;
+	memset(argv, 0, sizeof(argv));
+	while (*cur != 0) {
+	    while ((*cur == ' ') || (*cur == '\t')) cur++;
+	    if (*cur == '\'') {
+		cur++;
+		argv[i] = cur;
+		while ((*cur != 0) && (*cur != '\'')) cur++;
+		if (*cur == '\'') {
+		    *cur = 0;
+		    nbargs++;
+		    i++;
+		    cur++;
+		}
+	    } else if (*cur == '"') {
+		cur++;
+		argv[i] = cur;
+		while ((*cur != 0) && (*cur != '"')) cur++;
+		if (*cur == '"') {
+		    *cur = 0;
+		    nbargs++;
+		    i++;
+		    cur++;
+		}
+	    } else {
+		argv[i] = cur;
+		while ((*cur != 0) && (*cur != ' ') && (*cur != '\t'))
+		    cur++;
+		*cur = 0;
+		nbargs++;
+		i++;
+		cur++;
+	    }
+	}
+
+	/*
+	 * start interpreting the command
+	 */
+	if (!strcmp(command, "exit") ||
+	    !strcmp(command, "quit") ||
+	    !strcmp(command, "bye")) {
+	    free(cmdline);
+	    break;
+	}
+
+	if (!strcmp(command, "public")) {
+	    if (nbargs != 1) {
+		printf("public requires 1 arguments\n");
+	    } else {
+		ans = xmlCatalogResolvePublic((const xmlChar *) argv[0]);
+		if (ans == NULL) {
+		    printf("No entry for PUBLIC %s\n", argv[0]);
+		} else {
+		    printf("%s\n", (char *) ans);
+		    xmlFree(ans);
+		}
+	    }
+	} else if (!strcmp(command, "system")) {
+	    if (nbargs != 1) {
+		printf("system requires 1 arguments\n");
+	    } else {
+		ans = xmlCatalogResolveSystem((const xmlChar *) argv[0]);
+		if (ans == NULL) {
+		    printf("No entry for SYSTEM %s\n", argv[0]);
+		} else {
+		    printf("%s\n", (char *) ans);
+		    xmlFree(ans);
+		}
+	    }
+	} else if (!strcmp(command, "add")) {
+	    if ((nbargs != 3) && (nbargs != 2)) {
+		printf("add requires 2 or 3 arguments\n");
+	    } else {
+		if (argv[2] == NULL)
+		ret = xmlCatalogAdd(BAD_CAST argv[0], NULL,
+				    BAD_CAST argv[1]);
+		else
+		    ret = xmlCatalogAdd(BAD_CAST argv[0], BAD_CAST argv[1],
+					BAD_CAST argv[2]);
+		if (ret != 0)
+		    printf("add command failed\n");
+	    }
+	} else if (!strcmp(command, "del")) {
+	    if (nbargs != 1) {
+		printf("del requires 1\n");
+	    } else {
+		ret = xmlCatalogRemove(BAD_CAST argv[0]);
+		if (ret <= 0)
+		    printf("del command failed\n");
+
+	    }
+	} else if (!strcmp(command, "resolve")) {
+	    if (nbargs != 2) {
+		printf("resolve requires 2 arguments\n");
+	    } else {
+		ans = xmlCatalogResolve(BAD_CAST argv[0],
+			                BAD_CAST argv[1]);
+		if (ans == NULL) {
+		    printf("Resolver failed to find an answer\n");
+		} else {
+		    printf("%s\n", (char *) ans);
+		    xmlFree(ans);
+		}
+	    }
+	} else if (!strcmp(command, "dump")) {
+	    if (nbargs != 0) {
+		printf("dump has no arguments\n");
+	    } else {
+		xmlCatalogDump(stdout);
+	    }
+	} else if (!strcmp(command, "debug")) {
+	    if (nbargs != 0) {
+		printf("debug has no arguments\n");
+	    } else {
+		verbose++;
+		xmlCatalogSetDebug(verbose);
+	    }
+	} else if (!strcmp(command, "quiet")) {
+	    if (nbargs != 0) {
+		printf("quiet has no arguments\n");
+	    } else {
+		if (verbose > 0)
+		    verbose--;
+		xmlCatalogSetDebug(verbose);
+	    }
+	} else {
+	    if (strcmp(command, "help")) {
+		printf("Unrecognized command %s\n", command);
+	    }
+	    printf("Commands available:\n");
+	    printf("\tpublic PublicID: make a PUBLIC identifier lookup\n");
+	    printf("\tsystem SystemID: make a SYSTEM identifier lookup\n");
+	    printf("\tresolve PublicID SystemID: do a full resolver lookup\n");
+	    printf("\tadd 'type' 'orig' 'replace' : add an entry\n");
+	    printf("\tdel 'values' : remove values\n");
+	    printf("\tdump: print the current catalog state\n");
+	    printf("\tdebug: increase the verbosity level\n");
+	    printf("\tquiet: decrease the verbosity level\n");
+	    printf("\texit:  quit the shell\n");
+	}
+	free(cmdline); /* not xmlFree here ! */
+    }
+}
+
+/************************************************************************
+ *									*
+ *			Main						*
+ *									*
+ ************************************************************************/
+static void usage(const char *name) {
+    /* split into 2 printf's to avoid overly long string (gcc warning) */
+    printf("\
+Usage : %s [options] catalogfile entities...\n\
+\tParse the catalog file (void specification possibly expressed as \"\"\n\
+\tappoints the default system one) and query it for the entities\n\
+\t--sgml : handle SGML Super catalogs for --add and --del\n\
+\t--shell : run a shell allowing interactive queries\n\
+\t--create : create a new catalog\n\
+\t--add 'type' 'orig' 'replace' : add an XML entry\n\
+\t--add 'entry' : add an SGML entry\n", name);
+    printf("\
+\t--del 'values' : remove values\n\
+\t--noout: avoid dumping the result on stdout\n\
+\t         used with --add or --del, it saves the catalog changes\n\
+\t         and with --sgml it automatically updates the super catalog\n\
+\t--no-super-update: do not update the SGML super catalog\n\
+\t-v --verbose : provide debug information\n");
+}
+int main(int argc, char **argv) {
+    int i;
+    int ret;
+    int exit_value = 0;
+
+
+    if (argc <= 1) {
+	usage(argv[0]);
+	return(1);
+    }
+
+    LIBXML_TEST_VERSION
+    for (i = 1; i < argc ; i++) {
+	if (!strcmp(argv[i], "-"))
+	    break;
+
+	if (argv[i][0] != '-')
+	    break;
+	if ((!strcmp(argv[i], "-verbose")) ||
+	    (!strcmp(argv[i], "-v")) ||
+	    (!strcmp(argv[i], "--verbose"))) {
+	    verbose++;
+	    xmlCatalogSetDebug(verbose);
+	} else if ((!strcmp(argv[i], "-noout")) ||
+	    (!strcmp(argv[i], "--noout"))) {
+            noout = 1;
+	} else if ((!strcmp(argv[i], "-shell")) ||
+	    (!strcmp(argv[i], "--shell"))) {
+	    shell++;
+            noout = 1;
+	} else if ((!strcmp(argv[i], "-sgml")) ||
+	    (!strcmp(argv[i], "--sgml"))) {
+	    sgml++;
+	} else if ((!strcmp(argv[i], "-create")) ||
+	    (!strcmp(argv[i], "--create"))) {
+	    create++;
+	} else if ((!strcmp(argv[i], "-convert")) ||
+	    (!strcmp(argv[i], "--convert"))) {
+	    convert++;
+	} else if ((!strcmp(argv[i], "-no-super-update")) ||
+	    (!strcmp(argv[i], "--no-super-update"))) {
+	    no_super_update++;
+	} else if ((!strcmp(argv[i], "-add")) ||
+	    (!strcmp(argv[i], "--add"))) {
+	    if (sgml)
+		i += 2;
+	    else
+		i += 3;
+	    add++;
+	} else if ((!strcmp(argv[i], "-del")) ||
+	    (!strcmp(argv[i], "--del"))) {
+	    i += 1;
+	    del++;
+	} else {
+	    fprintf(stderr, "Unknown option %s\n", argv[i]);
+	    usage(argv[0]);
+	    return(1);
+	}
+    }
+
+    for (i = 1; i < argc; i++) {
+	if ((!strcmp(argv[i], "-add")) ||
+	    (!strcmp(argv[i], "--add"))) {
+	    if (sgml)
+		i += 2;
+	    else
+		i += 3;
+	    continue;
+	} else if ((!strcmp(argv[i], "-del")) ||
+	    (!strcmp(argv[i], "--del"))) {
+	    i += 1;
+
+	    /* No catalog entry specified */
+	    if (i == argc || (sgml && i + 1 == argc)) {
+		fprintf(stderr, "No catalog entry specified to remove from\n");
+		usage (argv[0]);
+		return(1);
+	    }
+
+	    continue;
+	} else if (argv[i][0] == '-')
+	    continue;
+
+	if (filename == NULL && argv[i][0] == '\0') {
+	    /* Interpret empty-string catalog specification as
+	       a shortcut for a default system catalog. */
+	    xmlInitializeCatalog();
+	} else {
+	    filename = argv[i];
+	    ret = xmlLoadCatalog(argv[i]);
+	    if ((ret < 0) && (create)) {
+		xmlCatalogAdd(BAD_CAST "catalog", BAD_CAST argv[i], NULL);
+	    }
+
+            /*
+             * Catalogs are loaded lazily. Make sure that dumping works
+             * by the issuing a dummy request that forces the catalog to
+             * be loaded.
+             */
+            xmlCatalogResolvePublic(BAD_CAST "");
+	}
+	break;
+    }
+
+    if (convert)
+        ret = xmlCatalogConvert();
+
+    if ((add) || (del)) {
+	for (i = 1; i < argc ; i++) {
+	    if (!strcmp(argv[i], "-"))
+		break;
+
+	    if (argv[i][0] != '-')
+		continue;
+	    if (strcmp(argv[i], "-add") && strcmp(argv[i], "--add") &&
+		strcmp(argv[i], "-del") && strcmp(argv[i], "--del"))
+		continue;
+
+	    if (sgml) {
+		/*
+		 * Maintenance of SGML catalogs.
+		 */
+		xmlCatalogPtr catal = NULL;
+		xmlCatalogPtr super = NULL;
+
+		catal = xmlLoadSGMLSuperCatalog(argv[i + 1]);
+
+		if ((!strcmp(argv[i], "-add")) ||
+		    (!strcmp(argv[i], "--add"))) {
+		    if (catal == NULL)
+			catal = xmlNewCatalog(1);
+		    xmlACatalogAdd(catal, BAD_CAST "CATALOG",
+					 BAD_CAST argv[i + 2], NULL);
+
+		    if (!no_super_update) {
+			super = xmlLoadSGMLSuperCatalog(XML_SGML_DEFAULT_CATALOG);
+			if (super == NULL)
+			    super = xmlNewCatalog(1);
+
+			xmlACatalogAdd(super, BAD_CAST "CATALOG",
+					     BAD_CAST argv[i + 1], NULL);
+		    }
+		} else {
+		    if (catal != NULL)
+			ret = xmlACatalogRemove(catal, BAD_CAST argv[i + 2]);
+		    else
+			ret = -1;
+		    if (ret < 0) {
+			fprintf(stderr, "Failed to remove entry from %s\n",
+				argv[i + 1]);
+			exit_value = 1;
+		    }
+		    if ((!no_super_update) && (noout) && (catal != NULL) &&
+			(xmlCatalogIsEmpty(catal))) {
+			super = xmlLoadSGMLSuperCatalog(
+				   XML_SGML_DEFAULT_CATALOG);
+			if (super != NULL) {
+			    ret = xmlACatalogRemove(super,
+				    BAD_CAST argv[i + 1]);
+			    if (ret < 0) {
+				fprintf(stderr,
+					"Failed to remove entry from %s\n",
+					XML_SGML_DEFAULT_CATALOG);
+				exit_value = 1;
+			    }
+			}
+		    }
+		}
+		if (noout) {
+		    FILE *out;
+
+		    if (xmlCatalogIsEmpty(catal)) {
+			remove(argv[i + 1]);
+		    } else {
+			out = fopen(argv[i + 1], "w");
+			if (out == NULL) {
+			    fprintf(stderr, "could not open %s for saving\n",
+				    argv[i + 1]);
+			    exit_value = 2;
+			    noout = 0;
+			} else {
+			    xmlACatalogDump(catal, out);
+			    fclose(out);
+			}
+		    }
+		    if (!no_super_update && super != NULL) {
+			if (xmlCatalogIsEmpty(super)) {
+			    remove(XML_SGML_DEFAULT_CATALOG);
+			} else {
+			    out = fopen(XML_SGML_DEFAULT_CATALOG, "w");
+			    if (out == NULL) {
+				fprintf(stderr,
+					"could not open %s for saving\n",
+					XML_SGML_DEFAULT_CATALOG);
+				exit_value = 2;
+				noout = 0;
+			    } else {
+
+				xmlACatalogDump(super, out);
+				fclose(out);
+			    }
+			}
+		    }
+		} else {
+		    xmlACatalogDump(catal, stdout);
+		}
+		i += 2;
+
+                xmlFreeCatalog(catal);
+                xmlFreeCatalog(super);
+	    } else {
+		if ((!strcmp(argv[i], "-add")) ||
+		    (!strcmp(argv[i], "--add"))) {
+			if ((argv[i + 3] == NULL) || (argv[i + 3][0] == 0))
+			    ret = xmlCatalogAdd(BAD_CAST argv[i + 1], NULL,
+						BAD_CAST argv[i + 2]);
+			else
+			    ret = xmlCatalogAdd(BAD_CAST argv[i + 1],
+						BAD_CAST argv[i + 2],
+						BAD_CAST argv[i + 3]);
+			if (ret != 0) {
+			    printf("add command failed\n");
+			    exit_value = 3;
+			}
+			i += 3;
+		} else if ((!strcmp(argv[i], "-del")) ||
+		    (!strcmp(argv[i], "--del"))) {
+		    ret = xmlCatalogRemove(BAD_CAST argv[i + 1]);
+		    if (ret < 0) {
+			fprintf(stderr, "Failed to remove entry %s\n",
+				argv[i + 1]);
+			exit_value = 1;
+		    }
+		    i += 1;
+		}
+	    }
+	}
+
+    } else if (shell) {
+	usershell();
+    } else {
+	for (i++; i < argc; i++) {
+	    xmlURIPtr uri;
+	    xmlChar *ans;
+
+	    uri = xmlParseURI(argv[i]);
+	    if (uri == NULL) {
+		ans = xmlCatalogResolvePublic((const xmlChar *) argv[i]);
+		if (ans == NULL) {
+		    printf("No entry for PUBLIC %s\n", argv[i]);
+		    exit_value = 4;
+		} else {
+		    printf("%s\n", (char *) ans);
+		    xmlFree(ans);
+		}
+	    } else {
+                xmlFreeURI(uri);
+		ans = xmlCatalogResolveSystem((const xmlChar *) argv[i]);
+		if (ans == NULL) {
+		    printf("No entry for SYSTEM %s\n", argv[i]);
+		    ans = xmlCatalogResolveURI ((const xmlChar *) argv[i]);
+		    if (ans == NULL) {
+			printf ("No entry for URI %s\n", argv[i]);
+		        exit_value = 4;
+		    } else {
+		        printf("%s\n", (char *) ans);
+			xmlFree (ans);
+		    }
+		} else {
+		    printf("%s\n", (char *) ans);
+		    xmlFree(ans);
+		}
+	    }
+	}
+    }
+    if ((!sgml) && ((add) || (del) || (create) || (convert))) {
+	if (noout && filename && *filename) {
+	    FILE *out;
+
+	    out = fopen(filename, "w");
+	    if (out == NULL) {
+		fprintf(stderr, "could not open %s for saving\n", filename);
+		exit_value = 2;
+		noout = 0;
+	    } else {
+		xmlCatalogDump(out);
+	    }
+	} else {
+	    xmlCatalogDump(stdout);
+	}
+    }
+
+    /*
+     * Cleanup and check for memory leaks
+     */
+    xmlCleanupParser();
+    return(exit_value);
+}
+#else
+int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    fprintf(stderr, "libxml was not compiled with catalog and output support\n");
+    return(1);
+}
+#endif
diff --git a/xmllint.c b/xmllint.c
new file mode 100644
index 0000000000000000000000000000000000000000..3a7a8a002e96bf65918d14dc813667aaf97ca8dd
--- /dev/null
+++ b/xmllint.c
@@ -0,0 +1,3787 @@
+/*
+ * xmllint.c : a small tester program for XML input.
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#include "libxml.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_TIMEB_H
+#include <sys/timeb.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#elif defined (_WIN32)
+#include <io.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+/* seems needed for Solaris */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+#endif
+#ifdef HAVE_LIBREADLINE
+#include <readline/readline.h>
+#ifdef HAVE_LIBHISTORY
+#include <readline/history.h>
+#endif
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/debugXML.h>
+#include <libxml/xmlerror.h>
+#ifdef LIBXML_XINCLUDE_ENABLED
+#include <libxml/xinclude.h>
+#endif
+#ifdef LIBXML_CATALOG_ENABLED
+#include <libxml/catalog.h>
+#endif
+#include <libxml/xmlreader.h>
+#ifdef LIBXML_SCHEMATRON_ENABLED
+#include <libxml/schematron.h>
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/relaxng.h>
+#include <libxml/xmlschemas.h>
+#endif
+#ifdef LIBXML_PATTERN_ENABLED
+#include <libxml/pattern.h>
+#endif
+#ifdef LIBXML_C14N_ENABLED
+#include <libxml/c14n.h>
+#endif
+#ifdef LIBXML_OUTPUT_ENABLED
+#include <libxml/xmlsave.h>
+#endif
+
+#ifdef XMLLINT_FUZZ
+  #define ERR_STREAM stdout
+#else
+  #define ERR_STREAM stderr
+#endif
+
+#ifndef XML_XML_DEFAULT_CATALOG
+#define XML_XML_DEFAULT_CATALOG "file://" SYSCONFDIR "/xml/catalog"
+#endif
+
+#ifndef STDIN_FILENO
+  #define STDIN_FILENO 0
+#endif
+
+typedef enum {
+    XMLLINT_RETURN_OK = 0,	    /* No error */
+    XMLLINT_ERR_UNCLASS = 1,	    /* Unclassified */
+    XMLLINT_ERR_DTD = 2,	    /* Error in DTD */
+    XMLLINT_ERR_VALID = 3,	    /* Validation error */
+    XMLLINT_ERR_RDFILE = 4,	    /* CtxtReadFile error */
+    XMLLINT_ERR_SCHEMACOMP = 5,	    /* Schema compilation */
+    XMLLINT_ERR_OUT = 6,	    /* Error writing output */
+    XMLLINT_ERR_SCHEMAPAT = 7,	    /* Error in schema pattern */
+    /*XMLLINT_ERR_RDREGIS = 8,*/
+    XMLLINT_ERR_MEM = 9,	    /* Out of memory error */
+    XMLLINT_ERR_XPATH = 10,	    /* XPath evaluation error */
+    XMLLINT_ERR_XPATH_EMPTY = 11    /* XPath result is empty */
+} xmllintReturnCode;
+
+#ifdef LIBXML_DEBUG_ENABLED
+static int shell = 0;
+static int debugent = 0;
+#endif
+static int debug = 0;
+static int maxmem = 0;
+#ifdef LIBXML_TREE_ENABLED
+static int copy = 0;
+#endif /* LIBXML_TREE_ENABLED */
+static int noout = 0;
+#ifdef LIBXML_OUTPUT_ENABLED
+static const char *output = NULL;
+static int format = 0;
+static const char *encoding = NULL;
+static int compress = 0;
+#endif /* LIBXML_OUTPUT_ENABLED */
+#ifdef LIBXML_VALID_ENABLED
+static int postvalid = 0;
+static const char *dtdvalid = NULL;
+static const char *dtdvalidfpi = NULL;
+static int insert = 0;
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+static const char *relaxng = NULL;
+static xmlRelaxNGPtr relaxngschemas = NULL;
+static const char *schema = NULL;
+static xmlSchemaPtr wxschemas = NULL;
+#endif
+#ifdef LIBXML_SCHEMATRON_ENABLED
+static const char *schematron = NULL;
+static xmlSchematronPtr wxschematron = NULL;
+#endif
+static int repeat = 0;
+#if defined(LIBXML_HTML_ENABLED)
+static int html = 0;
+static int xmlout = 0;
+#endif
+static int htmlout = 0;
+#ifdef LIBXML_PUSH_ENABLED
+static int push = 0;
+static int pushsize = 4096;
+#endif /* LIBXML_PUSH_ENABLED */
+#ifdef HAVE_MMAP
+static int memory = 0;
+#endif
+static int testIO = 0;
+#ifdef LIBXML_XINCLUDE_ENABLED
+static int xinclude = 0;
+#endif
+static xmllintReturnCode progresult = XMLLINT_RETURN_OK;
+static int quiet = 0;
+static int timing = 0;
+static int generate = 0;
+static int dropdtd = 0;
+#ifdef LIBXML_C14N_ENABLED
+static int canonical = 0;
+static int canonical_11 = 0;
+static int exc_canonical = 0;
+#endif
+#ifdef LIBXML_READER_ENABLED
+static int walker = 0;
+#ifdef LIBXML_PATTERN_ENABLED
+static const char *pattern = NULL;
+static xmlPatternPtr patternc = NULL;
+static xmlStreamCtxtPtr patstream = NULL;
+#endif
+#endif /* LIBXML_READER_ENABLED */
+#ifdef LIBXML_XPATH_ENABLED
+static const char *xpathquery = NULL;
+#endif
+static int options = XML_PARSE_COMPACT | XML_PARSE_BIG_LINES;
+static unsigned maxAmpl = 0;
+
+/************************************************************************
+ *									*
+ *		 Entity loading control and customization.		*
+ *									*
+ ************************************************************************/
+#define MAX_PATHS 64
+#ifdef _WIN32
+# define PATH_SEPARATOR ';'
+#else
+# define PATH_SEPARATOR ':'
+#endif
+static xmlChar *paths[MAX_PATHS + 1];
+static int nbpaths = 0;
+static int load_trace = 0;
+
+static
+void parsePath(const xmlChar *path) {
+    const xmlChar *cur;
+
+    if (path == NULL)
+	return;
+    while (*path != 0) {
+	if (nbpaths >= MAX_PATHS) {
+	    fprintf(ERR_STREAM, "MAX_PATHS reached: too many paths\n");
+	    return;
+	}
+	cur = path;
+	while ((*cur == ' ') || (*cur == PATH_SEPARATOR))
+	    cur++;
+	path = cur;
+	while ((*cur != 0) && (*cur != ' ') && (*cur != PATH_SEPARATOR))
+	    cur++;
+	if (cur != path) {
+	    paths[nbpaths] = xmlStrndup(path, cur - path);
+	    if (paths[nbpaths] != NULL)
+		nbpaths++;
+	    path = cur;
+	}
+    }
+}
+
+static xmlExternalEntityLoader defaultEntityLoader = NULL;
+
+static xmlParserInputPtr
+xmllintExternalEntityLoader(const char *URL, const char *ID,
+			     xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr ret;
+    warningSAXFunc warning = NULL;
+    errorSAXFunc err = NULL;
+
+    int i;
+    const char *lastsegment = URL;
+    const char *iter = URL;
+
+    if ((nbpaths > 0) && (iter != NULL)) {
+	while (*iter != 0) {
+	    if (*iter == '/')
+		lastsegment = iter + 1;
+	    iter++;
+	}
+    }
+
+    if ((ctxt != NULL) && (ctxt->sax != NULL)) {
+	warning = ctxt->sax->warning;
+	err = ctxt->sax->error;
+	ctxt->sax->warning = NULL;
+	ctxt->sax->error = NULL;
+    }
+
+    if (defaultEntityLoader != NULL) {
+	ret = defaultEntityLoader(URL, ID, ctxt);
+	if (ret != NULL) {
+	    if (warning != NULL)
+		ctxt->sax->warning = warning;
+	    if (err != NULL)
+		ctxt->sax->error = err;
+	    if (load_trace) {
+		fprintf \
+			(ERR_STREAM,
+			 "Loaded URL=\"%s\" ID=\"%s\"\n",
+			 URL ? URL : "(null)",
+			 ID ? ID : "(null)");
+	    }
+	    return(ret);
+	}
+    }
+    for (i = 0;i < nbpaths;i++) {
+	xmlChar *newURL;
+
+	newURL = xmlStrdup((const xmlChar *) paths[i]);
+	newURL = xmlStrcat(newURL, (const xmlChar *) "/");
+	newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
+	if (newURL != NULL) {
+	    ret = defaultEntityLoader((const char *)newURL, ID, ctxt);
+	    if (ret != NULL) {
+		if (warning != NULL)
+		    ctxt->sax->warning = warning;
+		if (err != NULL)
+		    ctxt->sax->error = err;
+		if (load_trace) {
+		    fprintf \
+			(ERR_STREAM,
+			 "Loaded URL=\"%s\" ID=\"%s\"\n",
+			 newURL,
+			 ID ? ID : "(null)");
+		}
+		xmlFree(newURL);
+		return(ret);
+	    }
+	    xmlFree(newURL);
+	}
+    }
+    if (err != NULL)
+        ctxt->sax->error = err;
+    if (warning != NULL) {
+	ctxt->sax->warning = warning;
+	if (URL != NULL)
+	    warning(ctxt, "failed to load external entity \"%s\"\n", URL);
+	else if (ID != NULL)
+	    warning(ctxt, "failed to load external entity \"%s\"\n", ID);
+    }
+    return(NULL);
+}
+
+/************************************************************************
+ *									*
+ * Memory allocation consumption debugging				*
+ *									*
+ ************************************************************************/
+
+static void
+OOM(void)
+{
+    fprintf(ERR_STREAM, "Ran out of memory needs > %d bytes\n", maxmem);
+    progresult = XMLLINT_ERR_MEM;
+}
+
+static void
+myFreeFunc(void *mem)
+{
+    xmlMemFree(mem);
+}
+static void *
+myMallocFunc(size_t size)
+{
+    void *ret;
+
+    ret = xmlMemMalloc(size);
+    if (ret != NULL) {
+        if (xmlMemUsed() > maxmem) {
+            OOM();
+            xmlMemFree(ret);
+            return (NULL);
+        }
+    }
+    return (ret);
+}
+static void *
+myReallocFunc(void *mem, size_t size)
+{
+    size_t oldsize = xmlMemSize(mem);
+
+    if (xmlMemUsed() + size - oldsize > (size_t) maxmem) {
+        OOM();
+        return (NULL);
+    }
+
+    return (xmlMemRealloc(mem, size));
+}
+static char *
+myStrdupFunc(const char *str)
+{
+    char *ret;
+
+    ret = xmlMemoryStrdup(str);
+    if (ret != NULL) {
+        if (xmlMemUsed() > maxmem) {
+            OOM();
+            xmlMemFree(ret);
+            return (NULL);
+        }
+    }
+    return (ret);
+}
+/************************************************************************
+ *									*
+ * Internal timing routines to remove the necessity to have		*
+ * unix-specific function calls.					*
+ *									*
+ ************************************************************************/
+
+#ifndef HAVE_GETTIMEOFDAY
+#ifdef HAVE_SYS_TIMEB_H
+#ifdef HAVE_SYS_TIME_H
+#ifdef HAVE_FTIME
+
+static int
+my_gettimeofday(struct timeval *tvp, void *tzp)
+{
+	struct timeb timebuffer;
+
+	ftime(&timebuffer);
+	if (tvp) {
+		tvp->tv_sec = timebuffer.time;
+		tvp->tv_usec = timebuffer.millitm * 1000L;
+	}
+	return (0);
+}
+#define HAVE_GETTIMEOFDAY 1
+#define gettimeofday my_gettimeofday
+
+#endif /* HAVE_FTIME */
+#endif /* HAVE_SYS_TIME_H */
+#endif /* HAVE_SYS_TIMEB_H */
+#endif /* !HAVE_GETTIMEOFDAY */
+
+#if defined(HAVE_GETTIMEOFDAY)
+static struct timeval begin, end;
+
+/*
+ * startTimer: call where you want to start timing
+ */
+static void
+startTimer(void)
+{
+    gettimeofday(&begin, NULL);
+}
+
+/*
+ * endTimer: call where you want to stop timing and to print out a
+ *           message about the timing performed; format is a printf
+ *           type argument
+ */
+static void LIBXML_ATTR_FORMAT(1,2)
+endTimer(const char *fmt, ...)
+{
+    long msec;
+    va_list ap;
+
+    gettimeofday(&end, NULL);
+    msec = end.tv_sec - begin.tv_sec;
+    msec *= 1000;
+    msec += (end.tv_usec - begin.tv_usec) / 1000;
+
+    va_start(ap, fmt);
+    vfprintf(ERR_STREAM, fmt, ap);
+    va_end(ap);
+
+    fprintf(ERR_STREAM, " took %ld ms\n", msec);
+}
+#else
+/*
+ * No gettimeofday function, so we have to make do with calling clock.
+ * This is obviously less accurate, but there's little we can do about
+ * that.
+ */
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 100
+#endif
+
+static clock_t begin, end;
+static void
+startTimer(void)
+{
+    begin = clock();
+}
+static void LIBXML_ATTR_FORMAT(1,2)
+endTimer(const char *fmt, ...)
+{
+    long msec;
+    va_list ap;
+
+    end = clock();
+    msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
+
+    va_start(ap, fmt);
+    vfprintf(ERR_STREAM, fmt, ap);
+    va_end(ap);
+    fprintf(ERR_STREAM, " took %ld ms\n", msec);
+}
+#endif
+/************************************************************************
+ *									*
+ *			HTML output					*
+ *									*
+ ************************************************************************/
+static char buffer[50000];
+
+static void
+xmlHTMLEncodeSend(void) {
+    char *result;
+
+    /*
+     * xmlEncodeEntitiesReentrant assumes valid UTF-8, but the buffer might
+     * end with a truncated UTF-8 sequence. This is a hack to at least avoid
+     * an out-of-bounds read.
+     */
+    memset(&buffer[sizeof(buffer)-4], 0, 4);
+    result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
+    if (result) {
+	fprintf(ERR_STREAM, "%s", result);
+	xmlFree(result);
+    }
+    buffer[0] = 0;
+}
+
+/**
+ * xmlHTMLPrintFileInfo:
+ * @input:  an xmlParserInputPtr input
+ *
+ * Displays the associated file and line information for the current input
+ */
+
+static void
+xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
+    int len;
+    fprintf(ERR_STREAM, "<p>");
+
+    len = strlen(buffer);
+    if (input != NULL) {
+	if (input->filename) {
+	    snprintf(&buffer[len], sizeof(buffer) - len, "%s:%d: ", input->filename,
+		    input->line);
+	} else {
+	    snprintf(&buffer[len], sizeof(buffer) - len, "Entity: line %d: ", input->line);
+	}
+    }
+    xmlHTMLEncodeSend();
+}
+
+/**
+ * xmlHTMLPrintFileContext:
+ * @input:  an xmlParserInputPtr input
+ *
+ * Displays current context within the input content for error tracking
+ */
+
+static void
+xmlHTMLPrintFileContext(xmlParserInputPtr input) {
+    const xmlChar *cur, *base;
+    int len;
+    int n;
+
+    if (input == NULL) return;
+    fprintf(ERR_STREAM, "<pre>\n");
+    cur = input->cur;
+    base = input->base;
+    while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
+	cur--;
+    }
+    n = 0;
+    while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
+        cur--;
+    if ((*cur == '\n') || (*cur == '\r')) cur++;
+    base = cur;
+    n = 0;
+    while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
+	len = strlen(buffer);
+        snprintf(&buffer[len], sizeof(buffer) - len, "%c",
+		    (unsigned char) *cur++);
+	n++;
+    }
+    len = strlen(buffer);
+    snprintf(&buffer[len], sizeof(buffer) - len, "\n");
+    cur = input->cur;
+    while ((cur > base) && ((*cur == '\n') || (*cur == '\r')))
+	cur--;
+    n = 0;
+    while ((cur != base) && (n++ < 80)) {
+	len = strlen(buffer);
+        snprintf(&buffer[len], sizeof(buffer) - len, " ");
+        base++;
+    }
+    len = strlen(buffer);
+    snprintf(&buffer[len], sizeof(buffer) - len, "^\n");
+    xmlHTMLEncodeSend();
+    fprintf(ERR_STREAM, "</pre>");
+}
+
+/**
+ * xmlHTMLError:
+ * @ctx:  an XML parser context
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ *
+ * Display and format an error messages, gives file, line, position and
+ * extra parameters.
+ */
+static void LIBXML_ATTR_FORMAT(2,3)
+xmlHTMLError(void *ctx, const char *msg, ...)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlParserInputPtr input;
+    va_list args;
+    int len;
+
+    buffer[0] = 0;
+    input = ctxt->input;
+    if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
+        input = ctxt->inputTab[ctxt->inputNr - 2];
+    }
+
+    xmlHTMLPrintFileInfo(input);
+
+    fprintf(ERR_STREAM, "<b>error</b>: ");
+    va_start(args, msg);
+    len = strlen(buffer);
+    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
+    va_end(args);
+    xmlHTMLEncodeSend();
+    fprintf(ERR_STREAM, "</p>\n");
+
+    xmlHTMLPrintFileContext(input);
+    xmlHTMLEncodeSend();
+}
+
+/**
+ * xmlHTMLWarning:
+ * @ctx:  an XML parser context
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ *
+ * Display and format a warning messages, gives file, line, position and
+ * extra parameters.
+ */
+static void LIBXML_ATTR_FORMAT(2,3)
+xmlHTMLWarning(void *ctx, const char *msg, ...)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlParserInputPtr input;
+    va_list args;
+    int len;
+
+    buffer[0] = 0;
+    input = ctxt->input;
+    if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
+        input = ctxt->inputTab[ctxt->inputNr - 2];
+    }
+
+
+    xmlHTMLPrintFileInfo(input);
+
+    fprintf(ERR_STREAM, "<b>warning</b>: ");
+    va_start(args, msg);
+    len = strlen(buffer);
+    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
+    va_end(args);
+    xmlHTMLEncodeSend();
+    fprintf(ERR_STREAM, "</p>\n");
+
+    xmlHTMLPrintFileContext(input);
+    xmlHTMLEncodeSend();
+}
+
+/**
+ * xmlHTMLValidityError:
+ * @ctx:  an XML parser context
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ *
+ * Display and format an validity error messages, gives file,
+ * line, position and extra parameters.
+ */
+static void LIBXML_ATTR_FORMAT(2,3)
+xmlHTMLValidityError(void *ctx, const char *msg, ...)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlParserInputPtr input;
+    va_list args;
+    int len;
+
+    buffer[0] = 0;
+    input = ctxt->input;
+
+    if (input != NULL) {
+        if ((input->filename == NULL) && (ctxt->inputNr > 1))
+            input = ctxt->inputTab[ctxt->inputNr - 2];
+
+        xmlHTMLPrintFileInfo(input);
+    }
+
+    fprintf(ERR_STREAM, "<b>validity error</b>: ");
+    len = strlen(buffer);
+    va_start(args, msg);
+    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
+    va_end(args);
+    xmlHTMLEncodeSend();
+    fprintf(ERR_STREAM, "</p>\n");
+
+    if (input != NULL)
+        xmlHTMLPrintFileContext(input);
+    xmlHTMLEncodeSend();
+    progresult = XMLLINT_ERR_VALID;
+}
+
+/**
+ * xmlHTMLValidityWarning:
+ * @ctx:  an XML parser context
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ *
+ * Display and format a validity warning messages, gives file, line,
+ * position and extra parameters.
+ */
+static void LIBXML_ATTR_FORMAT(2,3)
+xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlParserInputPtr input;
+    va_list args;
+    int len;
+
+    buffer[0] = 0;
+    input = ctxt->input;
+    if ((input->filename == NULL) && (ctxt->inputNr > 1))
+        input = ctxt->inputTab[ctxt->inputNr - 2];
+
+    xmlHTMLPrintFileInfo(input);
+
+    fprintf(ERR_STREAM, "<b>validity warning</b>: ");
+    va_start(args, msg);
+    len = strlen(buffer);
+    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
+    va_end(args);
+    xmlHTMLEncodeSend();
+    fprintf(ERR_STREAM, "</p>\n");
+
+    xmlHTMLPrintFileContext(input);
+    xmlHTMLEncodeSend();
+}
+
+/************************************************************************
+ *									*
+ *			Shell Interface					*
+ *									*
+ ************************************************************************/
+#ifdef LIBXML_DEBUG_ENABLED
+#ifdef LIBXML_XPATH_ENABLED
+/**
+ * xmlShellReadline:
+ * @prompt:  the prompt value
+ *
+ * Read a string
+ *
+ * Returns a pointer to it or NULL on EOF the caller is expected to
+ *     free the returned string.
+ */
+static char *
+xmlShellReadline(char *prompt) {
+#ifdef HAVE_LIBREADLINE
+    char *line_read;
+
+    /* Get a line from the user. */
+    line_read = readline (prompt);
+
+    /* If the line has any text in it, save it on the history. */
+    if (line_read && *line_read)
+	add_history (line_read);
+
+    return (line_read);
+#else
+    char line_read[501];
+    char *ret;
+    int len;
+
+    if (prompt != NULL)
+	fprintf(stdout, "%s", prompt);
+    fflush(stdout);
+    if (!fgets(line_read, 500, stdin))
+        return(NULL);
+    line_read[500] = 0;
+    len = strlen(line_read);
+    ret = (char *) malloc(len + 1);
+    if (ret != NULL) {
+	memcpy (ret, line_read, len + 1);
+    }
+    return(ret);
+#endif
+}
+#endif /* LIBXML_XPATH_ENABLED */
+#endif /* LIBXML_DEBUG_ENABLED */
+
+/************************************************************************
+ *									*
+ *			I/O Interfaces					*
+ *									*
+ ************************************************************************/
+
+static int myRead(void *f, char *buf, int len) {
+    return(fread(buf, 1, len, (FILE *) f));
+}
+static int myClose(void *context) {
+    FILE *f = (FILE *) context;
+    if (f == stdin)
+        return(0);
+    return(fclose(f));
+}
+
+/************************************************************************
+ *									*
+ *			SAX based tests					*
+ *									*
+ ************************************************************************/
+
+/*
+ * empty SAX block
+ */
+static xmlSAXHandler emptySAXHandlerStruct = {
+    NULL, /* internalSubset */
+    NULL, /* isStandalone */
+    NULL, /* hasInternalSubset */
+    NULL, /* hasExternalSubset */
+    NULL, /* resolveEntity */
+    NULL, /* getEntity */
+    NULL, /* entityDecl */
+    NULL, /* notationDecl */
+    NULL, /* attributeDecl */
+    NULL, /* elementDecl */
+    NULL, /* unparsedEntityDecl */
+    NULL, /* setDocumentLocator */
+    NULL, /* startDocument */
+    NULL, /* endDocument */
+    NULL, /* startElement */
+    NULL, /* endElement */
+    NULL, /* reference */
+    NULL, /* characters */
+    NULL, /* ignorableWhitespace */
+    NULL, /* processingInstruction */
+    NULL, /* comment */
+    NULL, /* xmlParserWarning */
+    NULL, /* xmlParserError */
+    NULL, /* xmlParserError */
+    NULL, /* getParameterEntity */
+    NULL, /* cdataBlock; */
+    NULL, /* externalSubset; */
+    XML_SAX2_MAGIC,
+    NULL,
+    NULL, /* startElementNs */
+    NULL, /* endElementNs */
+    NULL  /* xmlStructuredErrorFunc */
+};
+
+static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
+extern xmlSAXHandlerPtr debugSAXHandler;
+static int callbacks;
+
+/**
+ * isStandaloneDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Is this document tagged standalone ?
+ *
+ * Returns 1 if true
+ */
+static int
+isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return(0);
+    fprintf(stdout, "SAX.isStandalone()\n");
+    return(0);
+}
+
+/**
+ * hasInternalSubsetDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an internal subset
+ *
+ * Returns 1 if true
+ */
+static int
+hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return(0);
+    fprintf(stdout, "SAX.hasInternalSubset()\n");
+    return(0);
+}
+
+/**
+ * hasExternalSubsetDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an external subset
+ *
+ * Returns 1 if true
+ */
+static int
+hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return(0);
+    fprintf(stdout, "SAX.hasExternalSubset()\n");
+    return(0);
+}
+
+/**
+ * internalSubsetDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an internal subset
+ */
+static void
+internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+	       const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.internalSubset(%s,", name);
+    if (ExternalID == NULL)
+	fprintf(stdout, " ,");
+    else
+	fprintf(stdout, " %s,", ExternalID);
+    if (SystemID == NULL)
+	fprintf(stdout, " )\n");
+    else
+	fprintf(stdout, " %s)\n", SystemID);
+}
+
+/**
+ * externalSubsetDebug:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an external subset
+ */
+static void
+externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+	       const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.externalSubset(%s,", name);
+    if (ExternalID == NULL)
+	fprintf(stdout, " ,");
+    else
+	fprintf(stdout, " %s,", ExternalID);
+    if (SystemID == NULL)
+	fprintf(stdout, " )\n");
+    else
+	fprintf(stdout, " %s)\n", SystemID);
+}
+
+/**
+ * resolveEntityDebug:
+ * @ctxt:  An XML parser context
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * Special entity resolver, better left to the parser, it has
+ * more context than the application layer.
+ * The default behaviour is to NOT resolve the entities, in that case
+ * the ENTITY_REF nodes are built in the structure (and the parameter
+ * values).
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+static xmlParserInputPtr
+resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
+{
+    callbacks++;
+    if (noout)
+	return(NULL);
+    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
+
+
+    fprintf(stdout, "SAX.resolveEntity(");
+    if (publicId != NULL)
+	fprintf(stdout, "%s", (char *)publicId);
+    else
+	fprintf(stdout, " ");
+    if (systemId != NULL)
+	fprintf(stdout, ", %s)\n", (char *)systemId);
+    else
+	fprintf(stdout, ", )\n");
+    return(NULL);
+}
+
+/**
+ * getEntityDebug:
+ * @ctxt:  An XML parser context
+ * @name: The entity name
+ *
+ * Get an entity by name
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+static xmlEntityPtr
+getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+    callbacks++;
+    if (noout)
+	return(NULL);
+    fprintf(stdout, "SAX.getEntity(%s)\n", name);
+    return(NULL);
+}
+
+/**
+ * getParameterEntityDebug:
+ * @ctxt:  An XML parser context
+ * @name: The entity name
+ *
+ * Get a parameter entity by name
+ *
+ * Returns the xmlParserInputPtr
+ */
+static xmlEntityPtr
+getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+    callbacks++;
+    if (noout)
+	return(NULL);
+    fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
+    return(NULL);
+}
+
+
+/**
+ * entityDeclDebug:
+ * @ctxt:  An XML parser context
+ * @name:  the entity name
+ * @type:  the entity type
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @content: the entity value (without processing).
+ *
+ * An entity definition has been parsed
+ */
+static void
+entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
+          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
+{
+const xmlChar *nullstr = BAD_CAST "(null)";
+    /* not all libraries handle printing null pointers nicely */
+    if (publicId == NULL)
+        publicId = nullstr;
+    if (systemId == NULL)
+        systemId = nullstr;
+    if (content == NULL)
+        content = (xmlChar *)nullstr;
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
+            name, type, publicId, systemId, content);
+}
+
+/**
+ * attributeDeclDebug:
+ * @ctxt:  An XML parser context
+ * @name:  the attribute name
+ * @type:  the attribute type
+ *
+ * An attribute definition has been parsed
+ */
+static void
+attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
+                   const xmlChar * name, int type, int def,
+                   const xmlChar * defaultValue, xmlEnumerationPtr tree)
+{
+    callbacks++;
+    if (noout)
+        return;
+    if (defaultValue == NULL)
+        fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
+                elem, name, type, def);
+    else
+        fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
+                elem, name, type, def, defaultValue);
+    xmlFreeEnumeration(tree);
+}
+
+/**
+ * elementDeclDebug:
+ * @ctxt:  An XML parser context
+ * @name:  the element name
+ * @type:  the element type
+ * @content: the element value (without processing).
+ *
+ * An element definition has been parsed
+ */
+static void
+elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
+	    xmlElementContentPtr content ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
+            name, type);
+}
+
+/**
+ * notationDeclDebug:
+ * @ctxt:  An XML parser context
+ * @name: The name of the notation
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * What to do when a notation declaration has been parsed.
+ */
+static void
+notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+	     const xmlChar *publicId, const xmlChar *systemId)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
+            (char *) name, (char *) publicId, (char *) systemId);
+}
+
+/**
+ * unparsedEntityDeclDebug:
+ * @ctxt:  An XML parser context
+ * @name: The name of the entity
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @notationName: the name of the notation
+ *
+ * What to do when an unparsed entity declaration is parsed
+ */
+static void
+unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+		   const xmlChar *publicId, const xmlChar *systemId,
+		   const xmlChar *notationName)
+{
+const xmlChar *nullstr = BAD_CAST "(null)";
+
+    if (publicId == NULL)
+        publicId = nullstr;
+    if (systemId == NULL)
+        systemId = nullstr;
+    if (notationName == NULL)
+        notationName = nullstr;
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
+            (char *) name, (char *) publicId, (char *) systemId,
+	    (char *) notationName);
+}
+
+/**
+ * setDocumentLocatorDebug:
+ * @ctxt:  An XML parser context
+ * @loc: A SAX Locator
+ *
+ * Receive the document locator at startup, actually xmlDefaultSAXLocator
+ * Everything is available on the context, so this is useless in our case.
+ */
+static void
+setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.setDocumentLocator()\n");
+}
+
+/**
+ * startDocumentDebug:
+ * @ctxt:  An XML parser context
+ *
+ * called when the document start being processed.
+ */
+static void
+startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.startDocument()\n");
+}
+
+/**
+ * endDocumentDebug:
+ * @ctxt:  An XML parser context
+ *
+ * called when the document end has been detected.
+ */
+static void
+endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.endDocument()\n");
+}
+
+/**
+ * startElementDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The element name
+ *
+ * called when an opening tag has been processed.
+ */
+static void
+startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
+{
+    int i;
+
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.startElement(%s", (char *) name);
+    if (atts != NULL) {
+        for (i = 0;(atts[i] != NULL);i++) {
+	    fprintf(stdout, ", %s='", atts[i++]);
+	    if (atts[i] != NULL)
+	        fprintf(stdout, "%s'", atts[i]);
+	}
+    }
+    fprintf(stdout, ")\n");
+}
+
+/**
+ * endElementDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The element name
+ *
+ * called when the end of an element has been detected.
+ */
+static void
+endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
+}
+
+/**
+ * charactersDebug:
+ * @ctxt:  An XML parser context
+ * @ch:  a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some chars from the parser.
+ * Question: how much at a time ???
+ */
+static void
+charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+    char out[40];
+    int i;
+
+    callbacks++;
+    if (noout)
+	return;
+    for (i = 0;(i<len) && (i < 30);i++)
+	out[i] = (char) 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 LIBXML_ATTR_FORMAT(2,3)
+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 LIBXML_ATTR_FORMAT(2,3)
+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 LIBXML_ATTR_FORMAT(2,3)
+fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
+{
+    va_list args;
+
+    callbacks++;
+    if (noout)
+	return;
+    va_start(args, msg);
+    fprintf(stdout, "SAX.fatalError: ");
+    vfprintf(stdout, msg, args);
+    va_end(args);
+}
+
+static xmlSAXHandler debugSAXHandlerStruct = {
+    internalSubsetDebug,
+    isStandaloneDebug,
+    hasInternalSubsetDebug,
+    hasExternalSubsetDebug,
+    resolveEntityDebug,
+    getEntityDebug,
+    entityDeclDebug,
+    notationDeclDebug,
+    attributeDeclDebug,
+    elementDeclDebug,
+    unparsedEntityDeclDebug,
+    setDocumentLocatorDebug,
+    startDocumentDebug,
+    endDocumentDebug,
+    startElementDebug,
+    endElementDebug,
+    referenceDebug,
+    charactersDebug,
+    ignorableWhitespaceDebug,
+    processingInstructionDebug,
+    commentDebug,
+    warningDebug,
+    errorDebug,
+    fatalErrorDebug,
+    getParameterEntityDebug,
+    cdataBlockDebug,
+    externalSubsetDebug,
+    1,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
+
+/*
+ * SAX2 specific callbacks
+ */
+/**
+ * startElementNsDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The element name
+ *
+ * called when an opening tag has been processed.
+ */
+static void
+startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
+                    const xmlChar *localname,
+                    const xmlChar *prefix,
+                    const xmlChar *URI,
+		    int nb_namespaces,
+		    const xmlChar **namespaces,
+		    int nb_attributes,
+		    int nb_defaulted,
+		    const xmlChar **attributes)
+{
+    int i;
+
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.startElementNs(%s", (char *) localname);
+    if (prefix == NULL)
+	fprintf(stdout, ", NULL");
+    else
+	fprintf(stdout, ", %s", (char *) prefix);
+    if (URI == NULL)
+	fprintf(stdout, ", NULL");
+    else
+	fprintf(stdout, ", '%s'", (char *) URI);
+    fprintf(stdout, ", %d", nb_namespaces);
+
+    if (namespaces != NULL) {
+        for (i = 0;i < nb_namespaces * 2;i++) {
+	    fprintf(stdout, ", xmlns");
+	    if (namespaces[i] != NULL)
+	        fprintf(stdout, ":%s", namespaces[i]);
+	    i++;
+	    fprintf(stdout, "='%s'", namespaces[i]);
+	}
+    }
+    fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted);
+    if (attributes != NULL) {
+        for (i = 0;i < nb_attributes * 5;i += 5) {
+	    if (attributes[i + 1] != NULL)
+		fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]);
+	    else
+		fprintf(stdout, ", %s='", attributes[i]);
+	    fprintf(stdout, "%.4s...', %d", attributes[i + 3],
+		    (int)(attributes[i + 4] - attributes[i + 3]));
+	}
+    }
+    fprintf(stdout, ")\n");
+}
+
+/**
+ * endElementDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The element name
+ *
+ * called when the end of an element has been detected.
+ */
+static void
+endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
+                  const xmlChar *localname,
+                  const xmlChar *prefix,
+                  const xmlChar *URI)
+{
+    callbacks++;
+    if (noout)
+	return;
+    fprintf(stdout, "SAX.endElementNs(%s", (char *) localname);
+    if (prefix == NULL)
+	fprintf(stdout, ", NULL");
+    else
+	fprintf(stdout, ", %s", (char *) prefix);
+    if (URI == NULL)
+	fprintf(stdout, ", NULL)\n");
+    else
+	fprintf(stdout, ", '%s')\n", (char *) URI);
+}
+
+static xmlSAXHandler debugSAX2HandlerStruct = {
+    internalSubsetDebug,
+    isStandaloneDebug,
+    hasInternalSubsetDebug,
+    hasExternalSubsetDebug,
+    resolveEntityDebug,
+    getEntityDebug,
+    entityDeclDebug,
+    notationDeclDebug,
+    attributeDeclDebug,
+    elementDeclDebug,
+    unparsedEntityDeclDebug,
+    setDocumentLocatorDebug,
+    startDocumentDebug,
+    endDocumentDebug,
+    NULL,
+    NULL,
+    referenceDebug,
+    charactersDebug,
+    ignorableWhitespaceDebug,
+    processingInstructionDebug,
+    commentDebug,
+    warningDebug,
+    errorDebug,
+    fatalErrorDebug,
+    getParameterEntityDebug,
+    cdataBlockDebug,
+    externalSubsetDebug,
+    XML_SAX2_MAGIC,
+    NULL,
+    startElementNsDebug,
+    endElementNsDebug,
+    NULL
+};
+
+static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
+
+static void
+testSAX(const char *filename) {
+    xmlSAXHandlerPtr handler;
+    const char *user_data = "user_data"; /* mostly for debugging */
+
+    callbacks = 0;
+
+    if (noout) {
+        handler = emptySAXHandler;
+#ifdef LIBXML_SAX1_ENABLED
+    } else if (options & XML_PARSE_SAX1) {
+        handler = debugSAXHandler;
+#endif
+    } else {
+        handler = debugSAX2Handler;
+    }
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+    if (wxschemas != NULL) {
+        int ret;
+	xmlSchemaValidCtxtPtr vctxt;
+        xmlParserInputBufferPtr buf;
+
+        if (strcmp(filename, "-") == 0)
+            buf = xmlParserInputBufferCreateFd(STDIN_FILENO,
+                    XML_CHAR_ENCODING_NONE);
+        else
+            buf = xmlParserInputBufferCreateFilename(filename,
+                    XML_CHAR_ENCODING_NONE);
+        if (buf == NULL)
+            return;
+
+	vctxt = xmlSchemaNewValidCtxt(wxschemas);
+        if (vctxt == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            xmlFreeParserInputBuffer(buf);
+            return;
+        }
+	xmlSchemaValidateSetFilename(vctxt, filename);
+
+	ret = xmlSchemaValidateStream(vctxt, buf, 0, handler,
+	                              (void *)user_data);
+	if (repeat == 0) {
+	    if (ret == 0) {
+	        if (!quiet) {
+	            fprintf(ERR_STREAM, "%s validates\n", filename);
+	        }
+	    } else if (ret > 0) {
+		fprintf(ERR_STREAM, "%s fails to validate\n", filename);
+		progresult = XMLLINT_ERR_VALID;
+	    } else {
+		fprintf(ERR_STREAM, "%s validation generated an internal error\n",
+		       filename);
+		progresult = XMLLINT_ERR_VALID;
+	    }
+	}
+	xmlSchemaFreeValidCtxt(vctxt);
+    } else
+#endif
+    {
+        xmlParserCtxtPtr ctxt = NULL;
+
+	/*
+	 * Create the parser context amd hook the input
+	 */
+	ctxt = xmlNewSAXParserCtxt(handler, (void *) user_data);
+	if (ctxt == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+	    return;
+	}
+        if (maxAmpl > 0)
+            xmlCtxtSetMaxAmplification(ctxt, maxAmpl);
+
+        if (strcmp(filename, "-") == 0)
+            xmlCtxtReadFd(ctxt, STDIN_FILENO, "-", NULL, options);
+        else
+            xmlCtxtReadFile(ctxt, filename, NULL, options);
+
+	if (ctxt->myDoc != NULL) {
+	    fprintf(ERR_STREAM, "SAX generated a doc !\n");
+	    xmlFreeDoc(ctxt->myDoc);
+	    ctxt->myDoc = NULL;
+	}
+        xmlFreeParserCtxt(ctxt);
+    }
+}
+
+/************************************************************************
+ *									*
+ *			Stream Test processing				*
+ *									*
+ ************************************************************************/
+#ifdef LIBXML_READER_ENABLED
+static void processNode(xmlTextReaderPtr reader) {
+    const xmlChar *name, *value;
+    int type, empty;
+
+    type = xmlTextReaderNodeType(reader);
+    empty = xmlTextReaderIsEmptyElement(reader);
+
+    if (debug) {
+	name = xmlTextReaderConstName(reader);
+	if (name == NULL)
+	    name = BAD_CAST "--";
+
+	value = xmlTextReaderConstValue(reader);
+
+
+	printf("%d %d %s %d %d",
+		xmlTextReaderDepth(reader),
+		type,
+		name,
+		empty,
+		xmlTextReaderHasValue(reader));
+	if (value == NULL)
+	    printf("\n");
+	else {
+	    printf(" %s\n", value);
+	}
+    }
+#ifdef LIBXML_PATTERN_ENABLED
+    if (patternc) {
+        xmlChar *path = NULL;
+        int match = -1;
+
+	if (type == XML_READER_TYPE_ELEMENT) {
+	    /* do the check only on element start */
+	    match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
+
+	    if (match) {
+#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
+		path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
+		printf("Node %s matches pattern %s\n", path, pattern);
+#else
+                printf("Node %s matches pattern %s\n",
+                       xmlTextReaderConstName(reader), pattern);
+#endif
+	    }
+	}
+	if (patstream != NULL) {
+	    int ret;
+
+	    if (type == XML_READER_TYPE_ELEMENT) {
+		ret = xmlStreamPush(patstream,
+		                    xmlTextReaderConstLocalName(reader),
+				    xmlTextReaderConstNamespaceUri(reader));
+		if (ret < 0) {
+		    fprintf(ERR_STREAM, "xmlStreamPush() failure\n");
+                    xmlFreeStreamCtxt(patstream);
+		    patstream = NULL;
+		} else if (ret != match) {
+#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
+		    if (path == NULL) {
+		        path = xmlGetNodePath(
+		                       xmlTextReaderCurrentNode(reader));
+		    }
+#endif
+		    fprintf(ERR_STREAM,
+		            "xmlPatternMatch and xmlStreamPush disagree\n");
+                    if (path != NULL)
+                        fprintf(ERR_STREAM, "  pattern %s node %s\n",
+                                pattern, path);
+                    else
+		        fprintf(ERR_STREAM, "  pattern %s node %s\n",
+			    pattern, xmlTextReaderConstName(reader));
+		}
+
+	    }
+	    if ((type == XML_READER_TYPE_END_ELEMENT) ||
+	        ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
+	        ret = xmlStreamPop(patstream);
+		if (ret < 0) {
+		    fprintf(ERR_STREAM, "xmlStreamPop() failure\n");
+                    xmlFreeStreamCtxt(patstream);
+		    patstream = NULL;
+		}
+	    }
+	}
+	if (path != NULL)
+	    xmlFree(path);
+    }
+#endif
+}
+
+static void streamFile(const char *filename) {
+    xmlTextReaderPtr reader;
+    int ret;
+#ifdef HAVE_MMAP
+    int fd = -1;
+    struct stat info;
+    const char *base = NULL;
+
+    if (memory) {
+	if (stat(filename, &info) < 0)
+	    return;
+	if ((fd = open(filename, O_RDONLY)) < 0)
+	    return;
+	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
+	if (base == (void *) MAP_FAILED) {
+	    close(fd);
+	    fprintf(ERR_STREAM, "mmap failure for file %s\n", filename);
+	    progresult = XMLLINT_ERR_RDFILE;
+	    return;
+	}
+
+	reader = xmlReaderForMemory(base, info.st_size, filename,
+	                            NULL, options);
+    } else
+#endif
+    if (strcmp(filename, "-") == 0)
+	reader = xmlReaderForFd(STDIN_FILENO, "-", NULL, options);
+    else
+	reader = xmlReaderForFile(filename, NULL, options);
+#ifdef LIBXML_PATTERN_ENABLED
+    if (patternc != NULL) {
+        patstream = xmlPatternGetStreamCtxt(patternc);
+	if (patstream != NULL) {
+	    ret = xmlStreamPush(patstream, NULL, NULL);
+	    if (ret < 0) {
+		fprintf(ERR_STREAM, "xmlStreamPush() failure\n");
+		xmlFreeStreamCtxt(patstream);
+		patstream = NULL;
+            }
+	}
+    }
+#endif
+
+
+    if (reader != NULL) {
+        if (maxAmpl > 0)
+            xmlTextReaderSetMaxAmplification(reader, maxAmpl);
+#ifdef LIBXML_SCHEMAS_ENABLED
+	if (relaxng != NULL) {
+	    if ((timing) && (!repeat)) {
+		startTimer();
+	    }
+	    ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
+	    if (ret < 0) {
+		fprintf(ERR_STREAM,
+			"Relax-NG schema %s failed to compile\n", relaxng);
+		progresult = XMLLINT_ERR_SCHEMACOMP;
+		relaxng = NULL;
+	    }
+	    if ((timing) && (!repeat)) {
+		endTimer("Compiling the schemas");
+	    }
+	}
+	if (schema != NULL) {
+	    if ((timing) && (!repeat)) {
+		startTimer();
+	    }
+	    ret = xmlTextReaderSchemaValidate(reader, schema);
+	    if (ret < 0) {
+		fprintf(ERR_STREAM,
+			"XSD schema %s failed to compile\n", schema);
+		progresult = XMLLINT_ERR_SCHEMACOMP;
+		schema = NULL;
+	    }
+	    if ((timing) && (!repeat)) {
+		endTimer("Compiling the schemas");
+	    }
+	}
+#endif
+
+	/*
+	 * Process all nodes in sequence
+	 */
+	if ((timing) && (!repeat)) {
+	    startTimer();
+	}
+	ret = xmlTextReaderRead(reader);
+	while (ret == 1) {
+	    if ((debug)
+#ifdef LIBXML_PATTERN_ENABLED
+	        || (patternc)
+#endif
+	       )
+		processNode(reader);
+	    ret = xmlTextReaderRead(reader);
+	}
+	if ((timing) && (!repeat)) {
+#ifdef LIBXML_SCHEMAS_ENABLED
+	    if (relaxng != NULL)
+		endTimer("Parsing and validating");
+	    else
+#endif
+#ifdef LIBXML_VALID_ENABLED
+	    if (options & XML_PARSE_DTDVALID)
+		endTimer("Parsing and validating");
+	    else
+#endif
+	    endTimer("Parsing");
+	}
+
+#ifdef LIBXML_VALID_ENABLED
+	if (options & XML_PARSE_DTDVALID) {
+	    if (xmlTextReaderIsValid(reader) != 1) {
+		fprintf(ERR_STREAM,
+			"Document %s does not validate\n", filename);
+		progresult = XMLLINT_ERR_VALID;
+	    }
+	}
+#endif /* LIBXML_VALID_ENABLED */
+#ifdef LIBXML_SCHEMAS_ENABLED
+	if ((relaxng != NULL) || (schema != NULL)) {
+	    if (xmlTextReaderIsValid(reader) != 1) {
+		fprintf(ERR_STREAM, "%s fails to validate\n", filename);
+		progresult = XMLLINT_ERR_VALID;
+	    } else {
+	        if (!quiet) {
+	            fprintf(ERR_STREAM, "%s validates\n", filename);
+	        }
+	    }
+	}
+#endif
+	/*
+	 * Done, cleanup and status
+	 */
+	xmlFreeTextReader(reader);
+	if (ret != 0) {
+	    fprintf(ERR_STREAM, "%s : failed to parse\n", filename);
+	    progresult = XMLLINT_ERR_UNCLASS;
+	}
+    } else {
+	fprintf(ERR_STREAM, "Unable to open %s\n", filename);
+	progresult = XMLLINT_ERR_UNCLASS;
+    }
+#ifdef LIBXML_PATTERN_ENABLED
+    if (patstream != NULL) {
+	xmlFreeStreamCtxt(patstream);
+	patstream = NULL;
+    }
+#endif
+#ifdef HAVE_MMAP
+    if (memory) {
+	munmap((char *) base, info.st_size);
+	close(fd);
+    }
+#endif
+}
+
+static void walkDoc(xmlDocPtr doc) {
+    xmlTextReaderPtr reader;
+    int ret;
+
+#ifdef LIBXML_PATTERN_ENABLED
+    if (pattern != NULL) {
+        xmlNodePtr root;
+        const xmlChar *namespaces[22];
+        int i;
+        xmlNsPtr ns;
+
+        root = xmlDocGetRootElement(doc);
+        if (root == NULL ) {
+            fprintf(ERR_STREAM,
+                    "Document does not have a root element");
+            progresult = XMLLINT_ERR_UNCLASS;
+            return;
+        }
+        for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) {
+            namespaces[i++] = ns->href;
+            namespaces[i++] = ns->prefix;
+        }
+        namespaces[i++] = NULL;
+        namespaces[i] = NULL;
+
+        ret = xmlPatternCompileSafe((const xmlChar *) pattern, doc->dict,
+                                    0, &namespaces[0], &patternc);
+	if (patternc == NULL) {
+            if (ret < 0) {
+                progresult = XMLLINT_ERR_MEM;
+            } else {
+                fprintf(ERR_STREAM,
+                        "Pattern %s failed to compile\n", pattern);
+                progresult = XMLLINT_ERR_SCHEMAPAT;
+            }
+            goto error;
+	}
+
+        patstream = xmlPatternGetStreamCtxt(patternc);
+        if (patstream == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            goto error;
+        }
+
+        ret = xmlStreamPush(patstream, NULL, NULL);
+        if (ret < 0) {
+            fprintf(ERR_STREAM, "xmlStreamPush() failure\n");
+            progresult = XMLLINT_ERR_MEM;
+            goto error;
+        }
+    }
+#endif /* LIBXML_PATTERN_ENABLED */
+    reader = xmlReaderWalker(doc);
+    if (reader != NULL) {
+	if ((timing) && (!repeat)) {
+	    startTimer();
+	}
+	ret = xmlTextReaderRead(reader);
+	while (ret == 1) {
+	    if ((debug)
+#ifdef LIBXML_PATTERN_ENABLED
+	        || (patternc)
+#endif
+	       )
+		processNode(reader);
+	    ret = xmlTextReaderRead(reader);
+	}
+	if ((timing) && (!repeat)) {
+	    endTimer("walking through the doc");
+	}
+	xmlFreeTextReader(reader);
+	if (ret != 0) {
+	    fprintf(ERR_STREAM, "failed to walk through the doc\n");
+	    progresult = XMLLINT_ERR_UNCLASS;
+	}
+    } else {
+	fprintf(ERR_STREAM, "Failed to crate a reader from the document\n");
+	progresult = XMLLINT_ERR_UNCLASS;
+    }
+
+#ifdef LIBXML_PATTERN_ENABLED
+error:
+    if (patternc != NULL) {
+        xmlFreePattern(patternc);
+        patternc = NULL;
+    }
+    if (patstream != NULL) {
+	xmlFreeStreamCtxt(patstream);
+	patstream = NULL;
+    }
+#endif
+}
+#endif /* LIBXML_READER_ENABLED */
+
+#ifdef LIBXML_XPATH_ENABLED
+/************************************************************************
+ *									*
+ *			XPath Query                                     *
+ *									*
+ ************************************************************************/
+
+static void doXPathDump(xmlXPathObjectPtr cur) {
+    switch(cur->type) {
+        case XPATH_NODESET: {
+#ifdef LIBXML_OUTPUT_ENABLED
+            xmlOutputBufferPtr buf;
+            xmlNodePtr node;
+            int i;
+
+            if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr <= 0)) {
+                progresult = XMLLINT_ERR_XPATH_EMPTY;
+                if (!quiet) {
+                    fprintf(ERR_STREAM, "XPath set is empty\n");
+                }
+                break;
+            }
+            buf = xmlOutputBufferCreateFile(stdout, NULL);
+            if (buf == NULL) {
+                fprintf(ERR_STREAM, "Out of memory for XPath\n");
+                progresult = XMLLINT_ERR_MEM;
+                return;
+            }
+            for (i = 0;i < cur->nodesetval->nodeNr;i++) {
+                node = cur->nodesetval->nodeTab[i];
+                xmlNodeDumpOutput(buf, NULL, node, 0, 0, NULL);
+                xmlOutputBufferWrite(buf, 1, "\n");
+            }
+            xmlOutputBufferClose(buf);
+#else
+            printf("xpath returned %d nodes\n", cur->nodesetval->nodeNr);
+#endif
+	    break;
+        }
+        case XPATH_BOOLEAN:
+	    if (cur->boolval) printf("true\n");
+	    else printf("false\n");
+	    break;
+        case XPATH_NUMBER:
+	    switch (xmlXPathIsInf(cur->floatval)) {
+	    case 1:
+		printf("Infinity\n");
+		break;
+	    case -1:
+		printf("-Infinity\n");
+		break;
+	    default:
+		if (xmlXPathIsNaN(cur->floatval)) {
+		    printf("NaN\n");
+		} else {
+		    printf("%0g\n", cur->floatval);
+		}
+	    }
+	    break;
+        case XPATH_STRING:
+	    printf("%s\n", (const char *) cur->stringval);
+	    break;
+        case XPATH_UNDEFINED:
+	    fprintf(ERR_STREAM, "XPath Object is uninitialized\n");
+            progresult = XMLLINT_ERR_XPATH;
+	    break;
+	default:
+	    fprintf(ERR_STREAM, "XPath object of unexpected type\n");
+            progresult = XMLLINT_ERR_XPATH;
+	    break;
+    }
+}
+
+static void doXPathQuery(xmlDocPtr doc, const char *query) {
+    xmlXPathContextPtr ctxt;
+    xmlXPathObjectPtr res;
+
+    ctxt = xmlXPathNewContext(doc);
+    if (ctxt == NULL) {
+        fprintf(ERR_STREAM, "Out of memory for XPath\n");
+        progresult = XMLLINT_ERR_MEM;
+        return;
+    }
+    ctxt->node = (xmlNodePtr) doc;
+    res = xmlXPathEval(BAD_CAST query, ctxt);
+    xmlXPathFreeContext(ctxt);
+
+    if (res == NULL) {
+        fprintf(ERR_STREAM, "XPath evaluation failure\n");
+        progresult = XMLLINT_ERR_XPATH;
+        return;
+    }
+    doXPathDump(res);
+    xmlXPathFreeObject(res);
+}
+#endif /* LIBXML_XPATH_ENABLED */
+
+/************************************************************************
+ *									*
+ *			Tree Test processing				*
+ *									*
+ ************************************************************************/
+
+static xmlDocPtr
+parseFile(const char *filename, xmlParserCtxtPtr rectxt) {
+    xmlParserCtxtPtr ctxt;
+    xmlDocPtr doc = NULL;
+
+#ifdef LIBXML_TREE_ENABLED
+    if ((generate) && (filename == NULL)) {
+        xmlNodePtr n;
+
+        doc = xmlNewDoc(BAD_CAST "1.0");
+        if (doc == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            return(NULL);
+        }
+        n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL);
+        if (n == NULL) {
+            xmlFreeDoc(doc);
+            progresult = XMLLINT_ERR_MEM;
+            return(NULL);
+        }
+        if (xmlNodeSetContent(n, BAD_CAST "abc") < 0) {
+            xmlFreeNode(n);
+            xmlFreeDoc(doc);
+            progresult = XMLLINT_ERR_MEM;
+            return(NULL);
+        }
+        xmlDocSetRootElement(doc, n);
+
+        return(doc);
+    }
+#endif /* LIBXML_TREE_ENABLED */
+
+#ifdef LIBXML_HTML_ENABLED
+#ifdef LIBXML_PUSH_ENABLED
+    if ((html) && (push)) {
+        FILE *f;
+        int res;
+        char chars[4096];
+
+        if ((filename[0] == '-') && (filename[1] == 0)) {
+            f = stdin;
+        } else {
+	    f = fopen(filename, "rb");
+            if (f == NULL) {
+                fprintf(ERR_STREAM, "Can't open %s\n", filename);
+                progresult = XMLLINT_ERR_RDFILE;
+                return(NULL);
+            }
+        }
+
+        res = fread(chars, 1, 4, f);
+        ctxt = htmlCreatePushParserCtxt(NULL, NULL,
+                    chars, res, filename, XML_CHAR_ENCODING_NONE);
+        if (ctxt == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            if (f != stdin)
+                fclose(f);
+            return(NULL);
+        }
+        htmlCtxtUseOptions(ctxt, options);
+        while ((res = fread(chars, 1, pushsize, f)) > 0) {
+            htmlParseChunk(ctxt, chars, res, 0);
+        }
+        htmlParseChunk(ctxt, chars, 0, 1);
+        doc = ctxt->myDoc;
+        htmlFreeParserCtxt(ctxt);
+        if (f != stdin)
+            fclose(f);
+
+        return(doc);
+    }
+#endif /* LIBXML_PUSH_ENABLED */
+
+#ifdef HAVE_MMAP
+    if ((html) && (memory)) {
+	int fd;
+	struct stat info;
+	const char *base;
+	if (stat(filename, &info) < 0)
+	    return(NULL);
+	if ((fd = open(filename, O_RDONLY)) < 0)
+	    return(NULL);
+	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
+	if (base == (void *) MAP_FAILED) {
+	    close(fd);
+	    fprintf(ERR_STREAM, "mmap failure for file %s\n", filename);
+	    progresult = XMLLINT_ERR_RDFILE;
+	    return(NULL);
+	}
+
+	doc = htmlReadMemory((char *) base, info.st_size, filename,
+	                     NULL, options);
+
+	munmap((char *) base, info.st_size);
+	close(fd);
+
+        return(doc);
+    }
+#endif
+
+    if (html) {
+        if (strcmp(filename, "-") == 0)
+            doc = htmlReadFd(STDIN_FILENO, "-", NULL, options);
+        else
+            doc = htmlReadFile(filename, NULL, options);
+
+        return(doc);
+    }
+#endif /* LIBXML_HTML_ENABLED */
+
+#ifdef LIBXML_PUSH_ENABLED
+    if (push) {
+        FILE *f;
+        int res;
+        char chars[4096];
+
+        if ((filename[0] == '-') && (filename[1] == 0)) {
+            f = stdin;
+        } else {
+            f = fopen(filename, "rb");
+            if (f == NULL) {
+                fprintf(ERR_STREAM, "Can't open %s\n", filename);
+                progresult = XMLLINT_ERR_RDFILE;
+                return(NULL);
+            }
+        }
+
+        res = fread(chars, 1, 4, f);
+        ctxt = xmlCreatePushParserCtxt(NULL, NULL,
+                    chars, res, filename);
+        if (ctxt == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            if (f != stdin)
+                fclose(f);
+            return(NULL);
+        }
+        xmlCtxtUseOptions(ctxt, options);
+
+        if (maxAmpl > 0)
+            xmlCtxtSetMaxAmplification(ctxt, maxAmpl);
+
+        if (htmlout) {
+            ctxt->sax->error = xmlHTMLError;
+            ctxt->sax->warning = xmlHTMLWarning;
+            ctxt->vctxt.error = xmlHTMLValidityError;
+            ctxt->vctxt.warning = xmlHTMLValidityWarning;
+        }
+
+        while ((res = fread(chars, 1, pushsize, f)) > 0) {
+            xmlParseChunk(ctxt, chars, res, 0);
+        }
+        xmlParseChunk(ctxt, chars, 0, 1);
+
+        doc = ctxt->myDoc;
+        if (f != stdin)
+            fclose(f);
+    } else
+#endif /* LIBXML_PUSH_ENABLED */
+    {
+        if (rectxt == NULL) {
+            ctxt = xmlNewParserCtxt();
+            if (ctxt == NULL) {
+                progresult = XMLLINT_ERR_MEM;
+                return(NULL);
+            }
+        } else {
+            ctxt = rectxt;
+        }
+
+        if (maxAmpl > 0)
+            xmlCtxtSetMaxAmplification(ctxt, maxAmpl);
+
+        if (htmlout) {
+            ctxt->sax->error = xmlHTMLError;
+            ctxt->sax->warning = xmlHTMLWarning;
+            ctxt->vctxt.error = xmlHTMLValidityError;
+            ctxt->vctxt.warning = xmlHTMLValidityWarning;
+        }
+
+        if (testIO) {
+            FILE *f;
+
+            if ((filename[0] == '-') && (filename[1] == 0)) {
+                f = stdin;
+            } else {
+                f = fopen(filename, "rb");
+                if (f == NULL) {
+                    fprintf(ERR_STREAM, "Can't open %s\n", filename);
+                    progresult = XMLLINT_ERR_RDFILE;
+                    goto error;
+                }
+            }
+
+            doc = xmlCtxtReadIO(ctxt, myRead, myClose, f, filename, NULL,
+                                options);
+#ifdef HAVE_MMAP
+        } else if (memory) {
+            int fd;
+            struct stat info;
+            const char *base;
+
+            if (stat(filename, &info) < 0)
+                goto error;
+            if ((fd = open(filename, O_RDONLY)) < 0)
+                goto error;
+            base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
+            if (base == (void *) MAP_FAILED) {
+                close(fd);
+                fprintf(ERR_STREAM, "mmap failure for file %s\n", filename);
+                progresult = XMLLINT_ERR_RDFILE;
+                goto error;
+            }
+
+            doc = xmlCtxtReadMemory(ctxt, base, info.st_size, filename, NULL,
+                                    options);
+
+            munmap((char *) base, info.st_size);
+            close(fd);
+#endif
+        } else {
+            if (strcmp(filename, "-") == 0)
+                doc = xmlCtxtReadFd(ctxt, STDIN_FILENO, "-", NULL, options);
+            else
+                doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
+        }
+    }
+
+    if (doc == NULL) {
+        if (ctxt->errNo == XML_ERR_NO_MEMORY)
+            progresult = XMLLINT_ERR_MEM;
+        else
+	    progresult = XMLLINT_ERR_RDFILE;
+    } else {
+#ifdef LIBXML_VALID_ENABLED
+        if ((options & XML_PARSE_DTDVALID) && (ctxt->valid == 0))
+            progresult = XMLLINT_ERR_VALID;
+#endif /* LIBXML_VALID_ENABLED */
+    }
+
+error:
+    if (ctxt != rectxt)
+        xmlFreeParserCtxt(ctxt);
+
+    return(doc);
+}
+
+static void
+parseAndPrintFile(const char *filename, xmlParserCtxtPtr rectxt) {
+    xmlDocPtr doc;
+
+    if ((timing) && (!repeat))
+	startTimer();
+
+    doc = parseFile(filename, rectxt);
+    if (doc == NULL) {
+        if (progresult == XMLLINT_RETURN_OK)
+            progresult = XMLLINT_ERR_UNCLASS;
+	return;
+    }
+
+    if ((timing) && (!repeat)) {
+	endTimer("Parsing");
+    }
+
+    if (dropdtd) {
+	xmlDtdPtr dtd;
+
+	dtd = xmlGetIntSubset(doc);
+	if (dtd != NULL) {
+	    xmlUnlinkNode((xmlNodePtr)dtd);
+            doc->intSubset = dtd;
+	}
+    }
+
+#ifdef LIBXML_XINCLUDE_ENABLED
+    if (xinclude) {
+	if ((timing) && (!repeat)) {
+	    startTimer();
+	}
+	if (xmlXIncludeProcessFlags(doc, options) < 0)
+	    progresult = XMLLINT_ERR_UNCLASS;
+	if ((timing) && (!repeat)) {
+	    endTimer("Xinclude processing");
+	}
+    }
+#endif
+
+#ifdef LIBXML_XPATH_ENABLED
+    if (xpathquery != NULL) {
+        doXPathQuery(doc, xpathquery);
+    }
+#endif
+
+#ifdef LIBXML_DEBUG_ENABLED
+#ifdef LIBXML_XPATH_ENABLED
+    /*
+     * shell interaction
+     */
+    if (shell) {
+        xmlXPathOrderDocElems(doc);
+        xmlShell(doc, filename, xmlShellReadline, stdout);
+    }
+#endif
+#endif
+
+#ifdef LIBXML_TREE_ENABLED
+    /*
+     * test intermediate copy if needed.
+     */
+    if (copy) {
+        xmlDocPtr tmp;
+
+        tmp = doc;
+	if (timing) {
+	    startTimer();
+	}
+	doc = xmlCopyDoc(doc, 1);
+        if (doc == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            xmlFreeDoc(tmp);
+            return;
+        }
+	if (timing) {
+	    endTimer("Copying");
+	}
+	if (timing) {
+	    startTimer();
+	}
+	xmlFreeDoc(tmp);
+	if (timing) {
+	    endTimer("Freeing original");
+	}
+    }
+#endif /* LIBXML_TREE_ENABLED */
+
+#ifdef LIBXML_VALID_ENABLED
+    if ((insert)
+#ifdef LIBXML_HTML_ENABLED
+        && (!html)
+#endif
+    ) {
+        const xmlChar* list[256];
+	int nb, i;
+	xmlNodePtr node;
+
+	if (doc->children != NULL) {
+	    node = doc->children;
+	    while ((node != NULL) &&
+                   ((node->type != XML_ELEMENT_NODE) ||
+                    (node->last == NULL)))
+                node = node->next;
+	    if (node != NULL) {
+		nb = xmlValidGetValidElements(node->last, NULL, list, 256);
+		if (nb < 0) {
+		    fprintf(ERR_STREAM, "could not get valid list of elements\n");
+		} else if (nb == 0) {
+		    fprintf(ERR_STREAM, "No element can be inserted under root\n");
+		} else {
+		    fprintf(ERR_STREAM, "%d element types can be inserted under root:\n",
+		           nb);
+		    for (i = 0;i < nb;i++) {
+			 fprintf(ERR_STREAM, "%s\n", (char *) list[i]);
+		    }
+		}
+	    }
+	}
+    }else
+#endif /* LIBXML_VALID_ENABLED */
+#ifdef LIBXML_READER_ENABLED
+    if (walker) {
+        walkDoc(doc);
+    }
+#endif /* LIBXML_READER_ENABLED */
+#ifdef LIBXML_OUTPUT_ENABLED
+    if (noout == 0) {
+        if (compress)
+            xmlSetDocCompressMode(doc, 9);
+
+	/*
+	 * print it.
+	 */
+#ifdef LIBXML_DEBUG_ENABLED
+	if (!debug) {
+#endif
+	    if ((timing) && (!repeat)) {
+		startTimer();
+	    }
+#ifdef LIBXML_HTML_ENABLED
+            if ((html) && (!xmlout)) {
+		if (compress) {
+		    htmlSaveFile(output ? output : "-", doc);
+		}
+		else if (encoding != NULL) {
+		    if (format == 1) {
+			htmlSaveFileFormat(output ? output : "-", doc, encoding, 1);
+		    }
+		    else {
+			htmlSaveFileFormat(output ? output : "-", doc, encoding, 0);
+		    }
+		}
+		else if (format == 1) {
+		    htmlSaveFileFormat(output ? output : "-", doc, NULL, 1);
+		}
+		else {
+		    FILE *out;
+		    if (output == NULL)
+			out = stdout;
+		    else {
+			out = fopen(output,"wb");
+		    }
+		    if (out != NULL) {
+			if (htmlDocDump(out, doc) < 0)
+			    progresult = XMLLINT_ERR_OUT;
+
+			if (output != NULL)
+			    fclose(out);
+		    } else {
+			fprintf(ERR_STREAM, "failed to open %s\n", output);
+			progresult = XMLLINT_ERR_OUT;
+		    }
+		}
+		if ((timing) && (!repeat)) {
+		    endTimer("Saving");
+		}
+	    } else
+#endif
+#ifdef LIBXML_C14N_ENABLED
+            if (canonical) {
+	        xmlChar *result = NULL;
+		int size;
+
+		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result);
+		if (size >= 0) {
+		    if (write(1, result, size) == -1) {
+		        fprintf(ERR_STREAM, "Can't write data\n");
+		    }
+		    xmlFree(result);
+		} else {
+		    fprintf(ERR_STREAM, "Failed to canonicalize\n");
+		    progresult = XMLLINT_ERR_OUT;
+		}
+	    } else if (canonical_11) {
+	        xmlChar *result = NULL;
+		int size;
+
+		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result);
+		if (size >= 0) {
+		    if (write(1, result, size) == -1) {
+		        fprintf(ERR_STREAM, "Can't write data\n");
+		    }
+		    xmlFree(result);
+		} else {
+		    fprintf(ERR_STREAM, "Failed to canonicalize\n");
+		    progresult = XMLLINT_ERR_OUT;
+		}
+	    } else
+            if (exc_canonical) {
+	        xmlChar *result = NULL;
+		int size;
+
+		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result);
+		if (size >= 0) {
+		    if (write(1, result, size) == -1) {
+		        fprintf(ERR_STREAM, "Can't write data\n");
+		    }
+		    xmlFree(result);
+		} else {
+		    fprintf(ERR_STREAM, "Failed to canonicalize\n");
+		    progresult = XMLLINT_ERR_OUT;
+		}
+	    } else
+#endif
+#ifdef HAVE_MMAP
+	    if (memory) {
+		xmlChar *result;
+		int len;
+
+		if (encoding != NULL) {
+		    if (format == 1) {
+		        xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
+		    } else {
+			xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
+		    }
+		} else {
+		    if (format == 1)
+			xmlDocDumpFormatMemory(doc, &result, &len, 1);
+		    else
+			xmlDocDumpMemory(doc, &result, &len);
+		}
+		if (result == NULL) {
+		    fprintf(ERR_STREAM, "Failed to save\n");
+		    progresult = XMLLINT_ERR_OUT;
+		} else {
+		    if (write(1, result, len) == -1) {
+		        fprintf(ERR_STREAM, "Can't write data\n");
+		    }
+		    xmlFree(result);
+		}
+
+	    } else
+#endif /* HAVE_MMAP */
+	    if (compress) {
+		xmlSaveFile(output ? output : "-", doc);
+	    } else {
+	        xmlSaveCtxtPtr ctxt;
+		int saveOpts = 0;
+
+                if (format == 1)
+		    saveOpts |= XML_SAVE_FORMAT;
+                else if (format == 2)
+                    saveOpts |= XML_SAVE_WSNONSIG;
+
+#if defined(LIBXML_HTML_ENABLED)
+                if (xmlout)
+                    saveOpts |= XML_SAVE_AS_XML;
+#endif
+
+		if (output == NULL)
+		    ctxt = xmlSaveToFd(1, encoding, saveOpts);
+		else
+		    ctxt = xmlSaveToFilename(output, encoding, saveOpts);
+
+		if (ctxt != NULL) {
+		    if (xmlSaveDoc(ctxt, doc) < 0) {
+			fprintf(ERR_STREAM, "failed save to %s\n",
+				output ? output : "-");
+			progresult = XMLLINT_ERR_OUT;
+		    }
+		    xmlSaveClose(ctxt);
+		} else {
+		    progresult = XMLLINT_ERR_OUT;
+		}
+	    }
+	    if ((timing) && (!repeat)) {
+		endTimer("Saving");
+	    }
+#ifdef LIBXML_DEBUG_ENABLED
+	} else {
+	    FILE *out;
+	    if (output == NULL)
+	        out = stdout;
+	    else {
+		out = fopen(output,"wb");
+	    }
+	    if (out != NULL) {
+		xmlDebugDumpDocument(out, doc);
+
+		if (output != NULL)
+		    fclose(out);
+	    } else {
+		fprintf(ERR_STREAM, "failed to open %s\n", output);
+		progresult = XMLLINT_ERR_OUT;
+	    }
+	}
+#endif
+    }
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+#ifdef LIBXML_VALID_ENABLED
+    /*
+     * A posteriori validation test
+     */
+    if ((dtdvalid != NULL) || (dtdvalidfpi != NULL)) {
+	xmlDtdPtr dtd;
+
+	if ((timing) && (!repeat)) {
+	    startTimer();
+	}
+	if (dtdvalid != NULL)
+	    dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
+	else
+	    dtd = xmlParseDTD((const xmlChar *)dtdvalidfpi, NULL);
+	if ((timing) && (!repeat)) {
+	    endTimer("Parsing DTD");
+	}
+	if (dtd == NULL) {
+	    if (dtdvalid != NULL)
+		fprintf(ERR_STREAM,
+			"Could not parse DTD %s\n", dtdvalid);
+	    else
+		fprintf(ERR_STREAM,
+			"Could not parse DTD %s\n", dtdvalidfpi);
+	    progresult = XMLLINT_ERR_DTD;
+	} else {
+	    xmlValidCtxtPtr cvp;
+
+	    if ((cvp = xmlNewValidCtxt()) == NULL) {
+		fprintf(ERR_STREAM,
+			"Couldn't allocate validation context\n");
+                progresult = XMLLINT_ERR_MEM;
+                xmlFreeDtd(dtd);
+                return;
+	    }
+
+	    if ((timing) && (!repeat)) {
+		startTimer();
+	    }
+	    if (!xmlValidateDtd(cvp, doc, dtd)) {
+		if (dtdvalid != NULL)
+		    fprintf(ERR_STREAM,
+			    "Document %s does not validate against %s\n",
+			    filename, dtdvalid);
+		else
+		    fprintf(ERR_STREAM,
+			    "Document %s does not validate against %s\n",
+			    filename, dtdvalidfpi);
+		progresult = XMLLINT_ERR_VALID;
+	    }
+	    if ((timing) && (!repeat)) {
+		endTimer("Validating against DTD");
+	    }
+	    xmlFreeValidCtxt(cvp);
+	    xmlFreeDtd(dtd);
+	}
+    } else if (postvalid) {
+	xmlValidCtxtPtr cvp;
+
+	if ((cvp = xmlNewValidCtxt()) == NULL) {
+	    fprintf(ERR_STREAM,
+		    "Couldn't allocate validation context\n");
+            progresult = XMLLINT_ERR_MEM;
+            xmlFreeDoc(doc);
+            return;
+	}
+
+	if ((timing) && (!repeat)) {
+	    startTimer();
+	}
+	if (!xmlValidateDocument(cvp, doc)) {
+	    fprintf(ERR_STREAM,
+		    "Document %s does not validate\n", filename);
+	    progresult = XMLLINT_ERR_VALID;
+	}
+	if ((timing) && (!repeat)) {
+	    endTimer("Validating");
+	}
+	xmlFreeValidCtxt(cvp);
+    }
+#endif /* LIBXML_VALID_ENABLED */
+#ifdef LIBXML_SCHEMATRON_ENABLED
+    if (wxschematron != NULL) {
+	xmlSchematronValidCtxtPtr ctxt;
+	int ret;
+	int flag;
+
+	if ((timing) && (!repeat)) {
+	    startTimer();
+	}
+
+	if (debug)
+	    flag = XML_SCHEMATRON_OUT_XML;
+	else
+	    flag = XML_SCHEMATRON_OUT_TEXT;
+	if (noout)
+	    flag |= XML_SCHEMATRON_OUT_QUIET;
+	ctxt = xmlSchematronNewValidCtxt(wxschematron, flag);
+        if (ctxt == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            xmlFreeDoc(doc);
+            return;
+        }
+	ret = xmlSchematronValidateDoc(ctxt, doc);
+	if (ret == 0) {
+	    if (!quiet) {
+	        fprintf(ERR_STREAM, "%s validates\n", filename);
+	    }
+	} else if (ret > 0) {
+	    fprintf(ERR_STREAM, "%s fails to validate\n", filename);
+	    progresult = XMLLINT_ERR_VALID;
+	} else {
+	    fprintf(ERR_STREAM, "%s validation generated an internal error\n",
+		   filename);
+	    progresult = XMLLINT_ERR_VALID;
+	}
+	xmlSchematronFreeValidCtxt(ctxt);
+	if ((timing) && (!repeat)) {
+	    endTimer("Validating");
+	}
+    }
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+    if (relaxngschemas != NULL) {
+	xmlRelaxNGValidCtxtPtr ctxt;
+	int ret;
+
+	if ((timing) && (!repeat)) {
+	    startTimer();
+	}
+
+	ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
+        if (ctxt == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            xmlFreeDoc(doc);
+            return;
+        }
+	ret = xmlRelaxNGValidateDoc(ctxt, doc);
+	if (ret == 0) {
+	    if (!quiet) {
+	        fprintf(ERR_STREAM, "%s validates\n", filename);
+	    }
+	} else if (ret > 0) {
+	    fprintf(ERR_STREAM, "%s fails to validate\n", filename);
+	    progresult = XMLLINT_ERR_VALID;
+	} else {
+	    fprintf(ERR_STREAM, "%s validation generated an internal error\n",
+		   filename);
+	    progresult = XMLLINT_ERR_VALID;
+	}
+	xmlRelaxNGFreeValidCtxt(ctxt);
+	if ((timing) && (!repeat)) {
+	    endTimer("Validating");
+	}
+    } else if (wxschemas != NULL) {
+	xmlSchemaValidCtxtPtr ctxt;
+	int ret;
+
+	if ((timing) && (!repeat)) {
+	    startTimer();
+	}
+
+	ctxt = xmlSchemaNewValidCtxt(wxschemas);
+        if (ctxt == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            xmlFreeDoc(doc);
+            return;
+        }
+	ret = xmlSchemaValidateDoc(ctxt, doc);
+	if (ret == 0) {
+	    if (!quiet) {
+	        fprintf(ERR_STREAM, "%s validates\n", filename);
+	    }
+	} else if (ret > 0) {
+	    fprintf(ERR_STREAM, "%s fails to validate\n", filename);
+	    progresult = XMLLINT_ERR_VALID;
+	} else {
+	    fprintf(ERR_STREAM, "%s validation generated an internal error\n",
+		   filename);
+	    progresult = XMLLINT_ERR_VALID;
+	}
+	xmlSchemaFreeValidCtxt(ctxt);
+	if ((timing) && (!repeat)) {
+	    endTimer("Validating");
+	}
+    }
+#endif
+
+#ifdef LIBXML_DEBUG_ENABLED
+    if ((debugent)
+#if defined(LIBXML_HTML_ENABLED)
+        && (!html)
+#endif
+    )
+	xmlDebugDumpEntities(ERR_STREAM, doc);
+#endif
+
+    /*
+     * free it.
+     */
+    if ((timing) && (!repeat)) {
+	startTimer();
+    }
+    xmlFreeDoc(doc);
+    if ((timing) && (!repeat)) {
+	endTimer("Freeing");
+    }
+}
+
+/************************************************************************
+ *									*
+ *			Usage and Main					*
+ *									*
+ ************************************************************************/
+
+static void showVersion(const char *name) {
+    fprintf(ERR_STREAM, "%s: using libxml version %s\n", name, xmlParserVersion);
+    fprintf(ERR_STREAM, "   compiled with: ");
+    if (xmlHasFeature(XML_WITH_THREAD)) fprintf(ERR_STREAM, "Threads ");
+    if (xmlHasFeature(XML_WITH_TREE)) fprintf(ERR_STREAM, "Tree ");
+    if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(ERR_STREAM, "Output ");
+    if (xmlHasFeature(XML_WITH_PUSH)) fprintf(ERR_STREAM, "Push ");
+    if (xmlHasFeature(XML_WITH_READER)) fprintf(ERR_STREAM, "Reader ");
+    if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(ERR_STREAM, "Patterns ");
+    if (xmlHasFeature(XML_WITH_WRITER)) fprintf(ERR_STREAM, "Writer ");
+    if (xmlHasFeature(XML_WITH_SAX1)) fprintf(ERR_STREAM, "SAXv1 ");
+    if (xmlHasFeature(XML_WITH_FTP)) fprintf(ERR_STREAM, "FTP ");
+    if (xmlHasFeature(XML_WITH_HTTP)) fprintf(ERR_STREAM, "HTTP ");
+    if (xmlHasFeature(XML_WITH_VALID)) fprintf(ERR_STREAM, "DTDValid ");
+    if (xmlHasFeature(XML_WITH_HTML)) fprintf(ERR_STREAM, "HTML ");
+    if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(ERR_STREAM, "Legacy ");
+    if (xmlHasFeature(XML_WITH_C14N)) fprintf(ERR_STREAM, "C14N ");
+    if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(ERR_STREAM, "Catalog ");
+    if (xmlHasFeature(XML_WITH_XPATH)) fprintf(ERR_STREAM, "XPath ");
+    if (xmlHasFeature(XML_WITH_XPTR)) fprintf(ERR_STREAM, "XPointer ");
+    if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(ERR_STREAM, "XInclude ");
+    if (xmlHasFeature(XML_WITH_ICONV)) fprintf(ERR_STREAM, "Iconv ");
+    if (xmlHasFeature(XML_WITH_ICU)) fprintf(ERR_STREAM, "ICU ");
+    if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(ERR_STREAM, "ISO8859X ");
+    if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(ERR_STREAM, "Unicode ");
+    if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(ERR_STREAM, "Regexps ");
+    if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(ERR_STREAM, "Automata ");
+    if (xmlHasFeature(XML_WITH_EXPR)) fprintf(ERR_STREAM, "Expr ");
+    if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(ERR_STREAM, "Schemas ");
+    if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(ERR_STREAM, "Schematron ");
+    if (xmlHasFeature(XML_WITH_MODULES)) fprintf(ERR_STREAM, "Modules ");
+    if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(ERR_STREAM, "Debug ");
+    if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(ERR_STREAM, "Zlib ");
+    if (xmlHasFeature(XML_WITH_LZMA)) fprintf(ERR_STREAM, "Lzma ");
+    fprintf(ERR_STREAM, "\n");
+}
+
+static void usage(FILE *f, const char *name) {
+    fprintf(f, "Usage : %s [options] XMLfiles ...\n", name);
+#ifdef LIBXML_OUTPUT_ENABLED
+    fprintf(f, "\tParse the XML files and output the result of the parsing\n");
+#else
+    fprintf(f, "\tParse the XML files\n");
+#endif /* LIBXML_OUTPUT_ENABLED */
+    fprintf(f, "\t--version : display the version of the XML library used\n");
+#ifdef LIBXML_DEBUG_ENABLED
+    fprintf(f, "\t--debug : dump a debug tree of the in-memory document\n");
+    fprintf(f, "\t--shell : run a navigating shell\n");
+    fprintf(f, "\t--debugent : debug the entities defined in the document\n");
+#else
+#ifdef LIBXML_READER_ENABLED
+    fprintf(f, "\t--debug : dump the nodes content when using --stream\n");
+#endif /* LIBXML_READER_ENABLED */
+#endif
+#ifdef LIBXML_TREE_ENABLED
+    fprintf(f, "\t--copy : used to test the internal copy implementation\n");
+#endif /* LIBXML_TREE_ENABLED */
+    fprintf(f, "\t--recover : output what was parsable on broken XML documents\n");
+    fprintf(f, "\t--huge : remove any internal arbitrary parser limits\n");
+    fprintf(f, "\t--noent : substitute entity references by their value\n");
+    fprintf(f, "\t--noenc : ignore any encoding specified inside the document\n");
+    fprintf(f, "\t--noout : don't output the result tree\n");
+    fprintf(f, "\t--path 'paths': provide a set of paths for resources\n");
+    fprintf(f, "\t--load-trace : print trace of all external entities loaded\n");
+    fprintf(f, "\t--nonet : refuse to fetch DTDs or entities over network\n");
+    fprintf(f, "\t--nocompact : do not generate compact text nodes\n");
+    fprintf(f, "\t--htmlout : output results as HTML\n");
+    fprintf(f, "\t--nowrap : do not put HTML doc wrapper\n");
+#ifdef LIBXML_VALID_ENABLED
+    fprintf(f, "\t--valid : validate the document in addition to std well-formed check\n");
+    fprintf(f, "\t--postvalid : do a posteriori validation, i.e after parsing\n");
+    fprintf(f, "\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
+    fprintf(f, "\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n");
+    fprintf(f, "\t--insert : ad-hoc test for valid insertions\n");
+#endif /* LIBXML_VALID_ENABLED */
+    fprintf(f, "\t--quiet : be quiet when succeeded\n");
+    fprintf(f, "\t--timing : print some timings\n");
+    fprintf(f, "\t--repeat : repeat 100 times, for timing or profiling\n");
+    fprintf(f, "\t--dropdtd : remove the DOCTYPE of the input docs\n");
+#ifdef LIBXML_HTML_ENABLED
+    fprintf(f, "\t--html : use the HTML parser\n");
+    fprintf(f, "\t--xmlout : force to use the XML serializer when using --html\n");
+    fprintf(f, "\t--nodefdtd : do not default HTML doctype\n");
+#endif
+#ifdef LIBXML_PUSH_ENABLED
+    fprintf(f, "\t--push : use the push mode of the parser\n");
+    fprintf(f, "\t--pushsmall : use the push mode of the parser using tiny increments\n");
+#endif /* LIBXML_PUSH_ENABLED */
+#ifdef HAVE_MMAP
+    fprintf(f, "\t--memory : parse from memory\n");
+#endif
+    fprintf(f, "\t--maxmem nbbytes : limits memory allocation to nbbytes bytes\n");
+    fprintf(f, "\t--nowarning : do not emit warnings from parser/validator\n");
+    fprintf(f, "\t--noblanks : drop (ignorable?) blanks spaces\n");
+    fprintf(f, "\t--nocdata : replace cdata section with text nodes\n");
+#ifdef LIBXML_OUTPUT_ENABLED
+    fprintf(f, "\t--output file or -o file: save to a given file\n");
+    fprintf(f, "\t--format : reformat/reindent the output\n");
+    fprintf(f, "\t--encode encoding : output in the given encoding\n");
+    fprintf(f, "\t--pretty STYLE : pretty-print in a particular style\n");
+    fprintf(f, "\t                 0 Do not pretty print\n");
+    fprintf(f, "\t                 1 Format the XML content, as --format\n");
+    fprintf(f, "\t                 2 Add whitespace inside tags, preserving content\n");
+#ifdef LIBXML_ZLIB_ENABLED
+    fprintf(f, "\t--compress : turn on gzip compression of output\n");
+#endif
+#endif /* LIBXML_OUTPUT_ENABLED */
+    fprintf(f, "\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
+    fprintf(f, "\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
+    fprintf(f, "\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
+#ifdef LIBXML_C14N_ENABLED
+#endif /* LIBXML_C14N_ENABLED */
+    fprintf(f, "\t--nsclean : remove redundant namespace declarations\n");
+    fprintf(f, "\t--testIO : test user I/O support\n");
+#ifdef LIBXML_CATALOG_ENABLED
+    fprintf(f, "\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
+    fprintf(f, "\t             otherwise XML Catalogs starting from \n");
+    fprintf(f, "\t         %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
+    fprintf(f, "\t--nocatalogs: deactivate all catalogs\n");
+#endif
+    fprintf(f, "\t--auto : generate a small doc on the fly\n");
+#ifdef LIBXML_XINCLUDE_ENABLED
+    fprintf(f, "\t--xinclude : do XInclude processing\n");
+    fprintf(f, "\t--noxincludenode : same but do not generate XInclude nodes\n");
+    fprintf(f, "\t--nofixup-base-uris : do not fixup xml:base uris\n");
+#endif
+    fprintf(f, "\t--loaddtd : fetch external DTD\n");
+    fprintf(f, "\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
+#ifdef LIBXML_READER_ENABLED
+    fprintf(f, "\t--stream : use the streaming interface to process very large files\n");
+    fprintf(f, "\t--walker : create a reader and walk though the resulting doc\n");
+#ifdef LIBXML_PATTERN_ENABLED
+    fprintf(f, "\t--pattern pattern_value : test the pattern support\n");
+#endif
+#endif /* LIBXML_READER_ENABLED */
+#ifdef LIBXML_SCHEMAS_ENABLED
+    fprintf(f, "\t--relaxng schema : do RelaxNG validation against the schema\n");
+    fprintf(f, "\t--schema schema : do validation against the WXS schema\n");
+#endif
+#ifdef LIBXML_SCHEMATRON_ENABLED
+    fprintf(f, "\t--schematron schema : do validation against a schematron\n");
+#endif
+#ifdef LIBXML_SAX1_ENABLED
+    fprintf(f, "\t--sax1: use the old SAX1 interfaces for processing\n");
+#endif
+    fprintf(f, "\t--sax: do not build a tree but work just at the SAX level\n");
+    fprintf(f, "\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
+#ifdef LIBXML_XPATH_ENABLED
+    fprintf(f, "\t--xpath expr: evaluate the XPath expression, imply --noout\n");
+#endif
+    fprintf(f, "\t--max-ampl value: set maximum amplification factor\n");
+
+    fprintf(f, "\nLibxml project home page: https://gitlab.gnome.org/GNOME/libxml2\n");
+}
+
+static unsigned long
+parseInteger(const char *ctxt, const char *str,
+             unsigned long min, unsigned long max) {
+    char *strEnd;
+    unsigned long val;
+
+    errno = 0;
+    val = strtoul(str, &strEnd, 10);
+    if (errno == EINVAL || *strEnd != 0) {
+        fprintf(ERR_STREAM, "%s: invalid integer: %s\n", ctxt, str);
+        exit(XMLLINT_ERR_UNCLASS);
+    }
+    if (errno != 0 || val < min || val > max) {
+        fprintf(ERR_STREAM, "%s: integer out of range: %s\n", ctxt, str);
+        exit(XMLLINT_ERR_UNCLASS);
+    }
+
+    return(val);
+}
+
+static int
+skipArgs(const char *arg) {
+    if ((!strcmp(arg, "-path")) ||
+        (!strcmp(arg, "--path")) ||
+        (!strcmp(arg, "-maxmem")) ||
+        (!strcmp(arg, "--maxmem")) ||
+#ifdef LIBXML_OUTPUT_ENABLED
+        (!strcmp(arg, "-o")) ||
+        (!strcmp(arg, "-output")) ||
+        (!strcmp(arg, "--output")) ||
+        (!strcmp(arg, "-encode")) ||
+        (!strcmp(arg, "--encode")) ||
+        (!strcmp(arg, "-pretty")) ||
+        (!strcmp(arg, "--pretty")) ||
+#endif
+#ifdef LIBXML_VALID_ENABLED
+        (!strcmp(arg, "-dtdvalid")) ||
+        (!strcmp(arg, "--dtdvalid")) ||
+        (!strcmp(arg, "-dtdvalidfpi")) ||
+        (!strcmp(arg, "--dtdvalidfpi")) ||
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+        (!strcmp(arg, "-relaxng")) ||
+        (!strcmp(arg, "--relaxng")) ||
+        (!strcmp(arg, "-schema")) ||
+        (!strcmp(arg, "--schema")) ||
+#endif
+#ifdef LIBXML_SCHEMATRON_ENABLED
+        (!strcmp(arg, "-schematron")) ||
+        (!strcmp(arg, "--schematron")) ||
+#endif
+#if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
+        (!strcmp(arg, "-pattern")) ||
+        (!strcmp(arg, "--pattern")) ||
+#endif
+#ifdef LIBXML_XPATH_ENABLED
+        (!strcmp(arg, "-xpath")) ||
+        (!strcmp(arg, "--xpath")) ||
+#endif
+        (!strcmp(arg, "-max-ampl")) ||
+        (!strcmp(arg, "--max-ampl"))
+    ) {
+        return(1);
+    }
+
+    return(0);
+}
+
+static int
+xmllintMain(int argc, const char **argv) {
+    int i, acount;
+    int files = 0;
+    int version = 0;
+    int nowrap = 0;
+    int sax = 0;
+#ifdef LIBXML_READER_ENABLED
+    int stream = 0;
+#endif
+#ifdef LIBXML_CATALOG_ENABLED
+    int catalogs = 0;
+    int nocatalogs = 0;
+#endif
+
+#ifdef XMLLINT_FUZZ
+#ifdef LIBXML_DEBUG_ENABLED
+    shell = 0;
+    debugent = 0;
+#endif
+    debug = 0;
+    maxmem = 0;
+#ifdef LIBXML_TREE_ENABLED
+    copy = 0;
+#endif /* LIBXML_TREE_ENABLED */
+    noout = 0;
+#ifdef LIBXML_OUTPUT_ENABLED
+    format = 0;
+    output = NULL;
+    compress = 0;
+#endif /* LIBXML_OUTPUT_ENABLED */
+#ifdef LIBXML_VALID_ENABLED
+    postvalid = 0;
+    dtdvalid = NULL;
+    dtdvalidfpi = NULL;
+    insert = 0;
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+    relaxng = NULL;
+    relaxngschemas = NULL;
+    schema = NULL;
+    wxschemas = NULL;
+#endif
+#ifdef LIBXML_SCHEMATRON_ENABLED
+    schematron = NULL;
+    wxschematron = NULL;
+#endif
+    repeat = 0;
+#if defined(LIBXML_HTML_ENABLED)
+    html = 0;
+    xmlout = 0;
+#endif
+    htmlout = 0;
+#ifdef LIBXML_PUSH_ENABLED
+    push = 0;
+    pushsize = 4096;
+#endif /* LIBXML_PUSH_ENABLED */
+#ifdef HAVE_MMAP
+    memory = 0;
+#endif
+    testIO = 0;
+    encoding = NULL;
+#ifdef LIBXML_XINCLUDE_ENABLED
+    xinclude = 0;
+#endif
+    progresult = XMLLINT_RETURN_OK;
+    quiet = 0;
+    timing = 0;
+    generate = 0;
+    dropdtd = 0;
+#ifdef LIBXML_C14N_ENABLED
+    canonical = 0;
+    canonical_11 = 0;
+    exc_canonical = 0;
+#endif
+#ifdef LIBXML_READER_ENABLED
+    walker = 0;
+#ifdef LIBXML_PATTERN_ENABLED
+    pattern = NULL;
+    patternc = NULL;
+    patstream = NULL;
+#endif
+#endif /* LIBXML_READER_ENABLED */
+#ifdef LIBXML_XPATH_ENABLED
+    xpathquery = NULL;
+#endif
+    options = XML_PARSE_COMPACT | XML_PARSE_BIG_LINES;
+    maxAmpl = 0;
+    defaultEntityLoader = NULL;
+#endif /* XMLLINT_FUZZ */
+
+    if (argc <= 1) {
+	usage(ERR_STREAM, argv[0]);
+	return(XMLLINT_ERR_UNCLASS);
+    }
+
+    /* xmlMemSetup must be called before initializing the parser. */
+    for (i = 1; i < argc ; i++) {
+	if ((!strcmp(argv[i], "-maxmem")) ||
+	    (!strcmp(argv[i], "--maxmem"))) {
+            i++;
+            if (i >= argc) {
+                fprintf(ERR_STREAM, "maxmem: missing integer value\n");
+                return(XMLLINT_ERR_UNCLASS);
+            }
+            errno = 0;
+            maxmem = parseInteger("maxmem", argv[i], 0, INT_MAX);
+        } else if (argv[i][0] == '-') {
+            i += skipArgs(argv[i]);
+	}
+    }
+    if (maxmem != 0)
+        xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc, myStrdupFunc);
+
+    LIBXML_TEST_VERSION
+
+    for (i = 1; i < argc ; i++) {
+	if (argv[i][0] != '-' || argv[i][1] == 0)
+	    continue;
+
+	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
+	    debug++;
+	else
+#ifdef LIBXML_DEBUG_ENABLED
+	if ((!strcmp(argv[i], "-shell")) ||
+	         (!strcmp(argv[i], "--shell"))) {
+	    shell++;
+            noout = 1;
+        } else
+#endif
+#ifdef LIBXML_TREE_ENABLED
+	if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
+	    copy++;
+	else
+#endif /* LIBXML_TREE_ENABLED */
+	if ((!strcmp(argv[i], "-recover")) ||
+	         (!strcmp(argv[i], "--recover"))) {
+	    options |= XML_PARSE_RECOVER;
+	} else if ((!strcmp(argv[i], "-huge")) ||
+	         (!strcmp(argv[i], "--huge"))) {
+	    options |= XML_PARSE_HUGE;
+	} else if ((!strcmp(argv[i], "-noent")) ||
+	         (!strcmp(argv[i], "--noent"))) {
+	    options |= XML_PARSE_NOENT;
+	} else if ((!strcmp(argv[i], "-noenc")) ||
+	         (!strcmp(argv[i], "--noenc"))) {
+	    options |= XML_PARSE_IGNORE_ENC;
+	} else if ((!strcmp(argv[i], "-nsclean")) ||
+	         (!strcmp(argv[i], "--nsclean"))) {
+	    options |= XML_PARSE_NSCLEAN;
+	} else if ((!strcmp(argv[i], "-nocdata")) ||
+	         (!strcmp(argv[i], "--nocdata"))) {
+	    options |= XML_PARSE_NOCDATA;
+	} else if ((!strcmp(argv[i], "-nodict")) ||
+	         (!strcmp(argv[i], "--nodict"))) {
+	    options |= XML_PARSE_NODICT;
+	} else if ((!strcmp(argv[i], "-version")) ||
+	         (!strcmp(argv[i], "--version"))) {
+	    showVersion(argv[0]);
+	    version = 1;
+	} else if ((!strcmp(argv[i], "-noout")) ||
+	         (!strcmp(argv[i], "--noout")))
+	    noout++;
+	else if ((!strcmp(argv[i], "-htmlout")) ||
+	         (!strcmp(argv[i], "--htmlout")))
+	    htmlout++;
+	else if ((!strcmp(argv[i], "-nowrap")) ||
+	         (!strcmp(argv[i], "--nowrap")))
+	    nowrap++;
+#ifdef LIBXML_HTML_ENABLED
+	else if ((!strcmp(argv[i], "-html")) ||
+	         (!strcmp(argv[i], "--html"))) {
+	    html++;
+        }
+	else if ((!strcmp(argv[i], "-xmlout")) ||
+	         (!strcmp(argv[i], "--xmlout"))) {
+	    xmlout++;
+	} else if ((!strcmp(argv[i], "-nodefdtd")) ||
+	         (!strcmp(argv[i], "--nodefdtd"))) {
+	    options |= HTML_PARSE_NODEFDTD;
+        }
+#endif /* LIBXML_HTML_ENABLED */
+	else if ((!strcmp(argv[i], "-loaddtd")) ||
+	         (!strcmp(argv[i], "--loaddtd"))) {
+	    options |= XML_PARSE_DTDLOAD;
+	} else if ((!strcmp(argv[i], "-dtdattr")) ||
+	         (!strcmp(argv[i], "--dtdattr"))) {
+	    options |= XML_PARSE_DTDATTR;
+	}
+#ifdef LIBXML_VALID_ENABLED
+	else if ((!strcmp(argv[i], "-valid")) ||
+	         (!strcmp(argv[i], "--valid"))) {
+	    options |= XML_PARSE_DTDVALID;
+	} else if ((!strcmp(argv[i], "-postvalid")) ||
+	         (!strcmp(argv[i], "--postvalid"))) {
+	    postvalid++;
+	    options |= XML_PARSE_DTDLOAD;
+	} else if ((!strcmp(argv[i], "-dtdvalid")) ||
+	         (!strcmp(argv[i], "--dtdvalid"))) {
+	    i++;
+	    dtdvalid = argv[i];
+	    options |= XML_PARSE_DTDLOAD;
+	} else if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
+	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
+	    i++;
+	    dtdvalidfpi = argv[i];
+	    options |= XML_PARSE_DTDLOAD;
+        }
+	else if ((!strcmp(argv[i], "-insert")) ||
+	         (!strcmp(argv[i], "--insert")))
+	    insert++;
+#endif /* LIBXML_VALID_ENABLED */
+	else if ((!strcmp(argv[i], "-dropdtd")) ||
+	         (!strcmp(argv[i], "--dropdtd")))
+	    dropdtd++;
+	else if ((!strcmp(argv[i], "-quiet")) ||
+	         (!strcmp(argv[i], "--quiet")))
+	    quiet++;
+	else if ((!strcmp(argv[i], "-timing")) ||
+	         (!strcmp(argv[i], "--timing")))
+	    timing++;
+	else if ((!strcmp(argv[i], "-auto")) ||
+	         (!strcmp(argv[i], "--auto")))
+	    generate++;
+	else if ((!strcmp(argv[i], "-repeat")) ||
+	         (!strcmp(argv[i], "--repeat"))) {
+	    if (repeat)
+	        repeat *= 10;
+	    else
+	        repeat = 100;
+	}
+#ifdef LIBXML_PUSH_ENABLED
+	else if ((!strcmp(argv[i], "-push")) ||
+	         (!strcmp(argv[i], "--push")))
+	    push++;
+	else if ((!strcmp(argv[i], "-pushsmall")) ||
+	         (!strcmp(argv[i], "--pushsmall"))) {
+	    push++;
+            pushsize = 10;
+        }
+#endif /* LIBXML_PUSH_ENABLED */
+#ifdef HAVE_MMAP
+	else if ((!strcmp(argv[i], "-memory")) ||
+	         (!strcmp(argv[i], "--memory")))
+	    memory++;
+#endif
+	else if ((!strcmp(argv[i], "-testIO")) ||
+	         (!strcmp(argv[i], "--testIO")))
+	    testIO++;
+#ifdef LIBXML_XINCLUDE_ENABLED
+	else if ((!strcmp(argv[i], "-xinclude")) ||
+	         (!strcmp(argv[i], "--xinclude"))) {
+	    xinclude++;
+	    options |= XML_PARSE_XINCLUDE;
+	}
+	else if ((!strcmp(argv[i], "-noxincludenode")) ||
+	         (!strcmp(argv[i], "--noxincludenode"))) {
+	    xinclude++;
+	    options |= XML_PARSE_XINCLUDE;
+	    options |= XML_PARSE_NOXINCNODE;
+	}
+	else if ((!strcmp(argv[i], "-nofixup-base-uris")) ||
+	         (!strcmp(argv[i], "--nofixup-base-uris"))) {
+	    xinclude++;
+	    options |= XML_PARSE_XINCLUDE;
+	    options |= XML_PARSE_NOBASEFIX;
+	}
+#endif
+	else if ((!strcmp(argv[i], "-nowarning")) ||
+	         (!strcmp(argv[i], "--nowarning"))) {
+	    options |= XML_PARSE_NOWARNING;
+            options &= ~XML_PARSE_PEDANTIC;
+        }
+	else if ((!strcmp(argv[i], "-pedantic")) ||
+	         (!strcmp(argv[i], "--pedantic"))) {
+	    options |= XML_PARSE_PEDANTIC;
+            options &= ~XML_PARSE_NOWARNING;
+        }
+#ifdef LIBXML_DEBUG_ENABLED
+	else if ((!strcmp(argv[i], "-debugent")) ||
+		 (!strcmp(argv[i], "--debugent"))) {
+	    debugent++;
+	}
+#endif
+#ifdef LIBXML_C14N_ENABLED
+	else if ((!strcmp(argv[i], "-c14n")) ||
+		 (!strcmp(argv[i], "--c14n"))) {
+	    canonical++;
+	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
+	}
+	else if ((!strcmp(argv[i], "-c14n11")) ||
+		 (!strcmp(argv[i], "--c14n11"))) {
+	    canonical_11++;
+	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
+	}
+	else if ((!strcmp(argv[i], "-exc-c14n")) ||
+		 (!strcmp(argv[i], "--exc-c14n"))) {
+	    exc_canonical++;
+	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
+	}
+#endif
+#ifdef LIBXML_CATALOG_ENABLED
+	else if ((!strcmp(argv[i], "-catalogs")) ||
+		 (!strcmp(argv[i], "--catalogs"))) {
+	    catalogs++;
+	} else if ((!strcmp(argv[i], "-nocatalogs")) ||
+		 (!strcmp(argv[i], "--nocatalogs"))) {
+	    nocatalogs++;
+	}
+#endif
+	else if ((!strcmp(argv[i], "-noblanks")) ||
+	         (!strcmp(argv[i], "--noblanks"))) {
+            options |= XML_PARSE_NOBLANKS;
+        }
+	else if ((!strcmp(argv[i], "-maxmem")) ||
+	         (!strcmp(argv[i], "--maxmem"))) {
+	     i++;
+        }
+#ifdef LIBXML_OUTPUT_ENABLED
+	else if ((!strcmp(argv[i], "-o")) ||
+	         (!strcmp(argv[i], "-output")) ||
+	         (!strcmp(argv[i], "--output"))) {
+	    i++;
+	    output = argv[i];
+	}
+	else if ((!strcmp(argv[i], "-format")) ||
+	         (!strcmp(argv[i], "--format"))) {
+	    format = 1;
+            options |= XML_PARSE_NOBLANKS;
+	}
+	else if ((!strcmp(argv[i], "-encode")) ||
+	         (!strcmp(argv[i], "--encode"))) {
+	    i++;
+	    encoding = argv[i];
+	    /*
+	     * OK it's for testing purposes
+	     */
+	    xmlAddEncodingAlias("UTF-8", "DVEnc");
+        }
+	else if ((!strcmp(argv[i], "-pretty")) ||
+	         (!strcmp(argv[i], "--pretty"))) {
+	    i++;
+            if (argv[i] != NULL)
+	        format = atoi(argv[i]);
+	}
+#ifdef LIBXML_ZLIB_ENABLED
+	else if ((!strcmp(argv[i], "-compress")) ||
+	         (!strcmp(argv[i], "--compress"))) {
+	    compress++;
+        }
+#endif
+#endif /* LIBXML_OUTPUT_ENABLED */
+#ifdef LIBXML_READER_ENABLED
+	else if ((!strcmp(argv[i], "-stream")) ||
+	         (!strcmp(argv[i], "--stream"))) {
+	     stream++;
+	}
+	else if ((!strcmp(argv[i], "-walker")) ||
+	         (!strcmp(argv[i], "--walker"))) {
+	     walker++;
+             noout++;
+        }
+#ifdef LIBXML_PATTERN_ENABLED
+        else if ((!strcmp(argv[i], "-pattern")) ||
+                   (!strcmp(argv[i], "--pattern"))) {
+	    i++;
+	    pattern = argv[i];
+	}
+#endif
+#endif /* LIBXML_READER_ENABLED */
+#ifdef LIBXML_SAX1_ENABLED
+	else if ((!strcmp(argv[i], "-sax1")) ||
+	         (!strcmp(argv[i], "--sax1"))) {
+	    options |= XML_PARSE_SAX1;
+	}
+#endif /* LIBXML_SAX1_ENABLED */
+	else if ((!strcmp(argv[i], "-sax")) ||
+	         (!strcmp(argv[i], "--sax"))) {
+	    sax++;
+        }
+#ifdef LIBXML_SCHEMAS_ENABLED
+	else if ((!strcmp(argv[i], "-relaxng")) ||
+	         (!strcmp(argv[i], "--relaxng"))) {
+	    i++;
+	    relaxng = argv[i];
+	    options |= XML_PARSE_NOENT;
+	} else if ((!strcmp(argv[i], "-schema")) ||
+	         (!strcmp(argv[i], "--schema"))) {
+	    i++;
+	    schema = argv[i];
+	    options |= XML_PARSE_NOENT;
+        }
+#endif
+#ifdef LIBXML_SCHEMATRON_ENABLED
+	else if ((!strcmp(argv[i], "-schematron")) ||
+	         (!strcmp(argv[i], "--schematron"))) {
+	    i++;
+	    schematron = argv[i];
+	    options |= XML_PARSE_NOENT;
+        }
+#endif
+        else if ((!strcmp(argv[i], "-nonet")) ||
+                   (!strcmp(argv[i], "--nonet"))) {
+	    options |= XML_PARSE_NONET;
+#ifndef XMLLINT_FUZZ
+	    xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
+#endif
+        } else if ((!strcmp(argv[i], "-nocompact")) ||
+                   (!strcmp(argv[i], "--nocompact"))) {
+	    options &= ~XML_PARSE_COMPACT;
+	} else if ((!strcmp(argv[i], "-load-trace")) ||
+	           (!strcmp(argv[i], "--load-trace"))) {
+	    load_trace++;
+        } else if ((!strcmp(argv[i], "-path")) ||
+                   (!strcmp(argv[i], "--path"))) {
+	    i++;
+	    parsePath(BAD_CAST argv[i]);
+        }
+#ifdef LIBXML_XPATH_ENABLED
+        else if ((!strcmp(argv[i], "-xpath")) ||
+                   (!strcmp(argv[i], "--xpath"))) {
+	    i++;
+	    noout++;
+	    xpathquery = argv[i];
+        }
+#endif
+	else if ((!strcmp(argv[i], "-oldxml10")) ||
+	           (!strcmp(argv[i], "--oldxml10"))) {
+	    options |= XML_PARSE_OLD10;
+	} else if ((!strcmp(argv[i], "-max-ampl")) ||
+	           (!strcmp(argv[i], "--max-ampl"))) {
+            i++;
+            if (i >= argc) {
+                fprintf(ERR_STREAM, "max-ampl: missing integer value\n");
+                return(XMLLINT_ERR_UNCLASS);
+            }
+            maxAmpl = parseInteger("max-ampl", argv[i], 1, UINT_MAX);
+	} else {
+	    fprintf(ERR_STREAM, "Unknown option %s\n", argv[i]);
+	    usage(ERR_STREAM, argv[0]);
+	    return(XMLLINT_ERR_UNCLASS);
+	}
+    }
+
+#ifdef LIBXML_CATALOG_ENABLED
+    if (nocatalogs == 0) {
+	if (catalogs) {
+	    const char *catal;
+
+	    catal = getenv("SGML_CATALOG_FILES");
+	    if (catal != NULL) {
+		xmlLoadCatalogs(catal);
+	    } else {
+		fprintf(ERR_STREAM, "Variable $SGML_CATALOG_FILES not set\n");
+	    }
+	}
+    }
+#endif
+
+#ifdef LIBXML_OUTPUT_ENABLED
+    {
+        const char *indent = getenv("XMLLINT_INDENT");
+        if (indent != NULL) {
+            xmlTreeIndentString = indent;
+        }
+    }
+#endif
+
+    defaultEntityLoader = xmlGetExternalEntityLoader();
+    xmlSetExternalEntityLoader(xmllintExternalEntityLoader);
+
+    if ((htmlout) && (!nowrap)) {
+	fprintf(ERR_STREAM,
+         "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
+	fprintf(ERR_STREAM,
+		"\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
+	fprintf(ERR_STREAM,
+	 "<html><head><title>%s output</title></head>\n",
+		argv[0]);
+	fprintf(ERR_STREAM,
+	 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
+		argv[0]);
+    }
+
+#ifdef LIBXML_SCHEMATRON_ENABLED
+    if ((schematron != NULL) && (sax == 0)
+#ifdef LIBXML_READER_ENABLED
+        && (stream == 0)
+#endif /* LIBXML_READER_ENABLED */
+	) {
+	xmlSchematronParserCtxtPtr ctxt;
+
+        /* forces loading the DTDs */
+	options |= XML_PARSE_DTDLOAD;
+	if (timing) {
+	    startTimer();
+	}
+	ctxt = xmlSchematronNewParserCtxt(schematron);
+        if (ctxt == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            goto error;
+        }
+	wxschematron = xmlSchematronParse(ctxt);
+	if (wxschematron == NULL) {
+	    fprintf(ERR_STREAM,
+		    "Schematron schema %s failed to compile\n", schematron);
+            progresult = XMLLINT_ERR_SCHEMACOMP;
+	    schematron = NULL;
+	}
+	xmlSchematronFreeParserCtxt(ctxt);
+	if (timing) {
+	    endTimer("Compiling the schemas");
+	}
+    }
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+    if ((relaxng != NULL) && (sax == 0)
+#ifdef LIBXML_READER_ENABLED
+        && (stream == 0)
+#endif /* LIBXML_READER_ENABLED */
+	) {
+	xmlRelaxNGParserCtxtPtr ctxt;
+
+        /* forces loading the DTDs */
+	options |= XML_PARSE_DTDLOAD;
+	if (timing) {
+	    startTimer();
+	}
+	ctxt = xmlRelaxNGNewParserCtxt(relaxng);
+        if (ctxt == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            goto error;
+        }
+	relaxngschemas = xmlRelaxNGParse(ctxt);
+	if (relaxngschemas == NULL) {
+	    fprintf(ERR_STREAM,
+		    "Relax-NG schema %s failed to compile\n", relaxng);
+            progresult = XMLLINT_ERR_SCHEMACOMP;
+	    relaxng = NULL;
+	}
+	xmlRelaxNGFreeParserCtxt(ctxt);
+	if (timing) {
+	    endTimer("Compiling the schemas");
+	}
+    } else if ((schema != NULL)
+#ifdef LIBXML_READER_ENABLED
+		&& (stream == 0)
+#endif
+	) {
+	xmlSchemaParserCtxtPtr ctxt;
+
+	if (timing) {
+	    startTimer();
+	}
+	ctxt = xmlSchemaNewParserCtxt(schema);
+        if (ctxt == NULL) {
+            progresult = XMLLINT_ERR_MEM;
+            goto error;
+        }
+	wxschemas = xmlSchemaParse(ctxt);
+	if (wxschemas == NULL) {
+	    fprintf(ERR_STREAM,
+		    "WXS schema %s failed to compile\n", schema);
+            progresult = XMLLINT_ERR_SCHEMACOMP;
+	    schema = NULL;
+	}
+	xmlSchemaFreeParserCtxt(ctxt);
+	if (timing) {
+	    endTimer("Compiling the schemas");
+	}
+    }
+#endif /* LIBXML_SCHEMAS_ENABLED */
+#if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
+    if ((pattern != NULL) && (walker == 0)) {
+        patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
+	if (patternc == NULL) {
+	    fprintf(ERR_STREAM,
+		    "Pattern %s failed to compile\n", pattern);
+            progresult = XMLLINT_ERR_SCHEMAPAT;
+	    pattern = NULL;
+	}
+    }
+#endif /* LIBXML_READER_ENABLED && LIBXML_PATTERN_ENABLED */
+    for (i = 1; i < argc ; i++) {
+	if ((argv[i][0] == '-') && (strcmp(argv[i], "-") != 0)) {
+            i += skipArgs(argv[i]);
+            continue;
+        }
+	if ((timing) && (repeat))
+	    startTimer();
+        if (repeat) {
+            xmlParserCtxtPtr ctxt;
+
+            ctxt = xmlNewParserCtxt();
+            if (ctxt == NULL) {
+                progresult = XMLLINT_ERR_MEM;
+                goto error;
+            }
+            if (maxAmpl > 0)
+                xmlCtxtSetMaxAmplification(ctxt, maxAmpl);
+
+            for (acount = 0;acount < repeat;acount++) {
+#ifdef LIBXML_READER_ENABLED
+                if (stream != 0) {
+                    streamFile(argv[i]);
+                } else {
+#endif /* LIBXML_READER_ENABLED */
+                    if (sax) {
+                        testSAX(argv[i]);
+                    } else {
+                        parseAndPrintFile(argv[i], ctxt);
+                    }
+#ifdef LIBXML_READER_ENABLED
+                }
+#endif /* LIBXML_READER_ENABLED */
+            }
+
+            xmlFreeParserCtxt(ctxt);
+        } else {
+#ifdef LIBXML_READER_ENABLED
+            if (stream != 0)
+                streamFile(argv[i]);
+            else
+#endif /* LIBXML_READER_ENABLED */
+            if (sax) {
+                testSAX(argv[i]);
+            } else {
+                parseAndPrintFile(argv[i], NULL);
+            }
+        }
+        files ++;
+        if ((timing) && (repeat)) {
+            endTimer("%d iterations", repeat);
+        }
+    }
+    if (generate)
+	parseAndPrintFile(NULL, NULL);
+    if ((htmlout) && (!nowrap)) {
+	fprintf(ERR_STREAM, "</body></html>\n");
+    }
+    if ((files == 0) && (!generate) && (version == 0)) {
+	usage(ERR_STREAM, argv[0]);
+        progresult = XMLLINT_ERR_UNCLASS;
+    }
+#ifdef LIBXML_SCHEMATRON_ENABLED
+    if (wxschematron != NULL)
+	xmlSchematronFree(wxschematron);
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+    if (relaxngschemas != NULL)
+	xmlRelaxNGFree(relaxngschemas);
+    if (wxschemas != NULL)
+	xmlSchemaFree(wxschemas);
+#endif
+#if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
+    if (patternc != NULL)
+        xmlFreePattern(patternc);
+#endif
+
+    /* Avoid unused label warning if features are disabled. */
+    goto error;
+
+error:
+    if (defaultEntityLoader != NULL)
+        xmlSetExternalEntityLoader(defaultEntityLoader);
+    xmlCleanupParser();
+
+    return(progresult);
+}
+
+#ifndef XMLLINT_FUZZ
+int
+main(int argc, char **argv) {
+    return(xmllintMain(argc, (const char **) argv));
+}
+#endif
+
diff --git a/xmlmemory.c b/xmlmemory.c
index 892d50c306dc3b94120107ea4c334ceb7d0672aa..f0628e2a83a7e623a81a91a621c4b671bceb3423 100644
--- a/xmlmemory.c
+++ b/xmlmemory.c
@@ -12,32 +12,17 @@
 #include <ctype.h>
 #include <time.h>
 
-/* #define DEBUG_MEMORY */
-
-/**
- * MEM_LIST:
- *
- * keep track of all allocated blocks for error reporting
- * Always build the memory list !
- */
-#ifdef DEBUG_MEMORY_LOCATION
-#ifndef MEM_LIST
-#define MEM_LIST /* keep a list of all the allocated memory blocks */
-#endif
-#endif
-
-#include <libxml/globals.h>	/* must come before xmlmemory.h */
 #include <libxml/xmlmemory.h>
 #include <libxml/xmlerror.h>
+#include <libxml/parser.h>
 #include <libxml/threads.h>
 
-static int xmlMemInitialized = 0;
+#include "private/memory.h"
+#include "private/threads.h"
+
 static unsigned long  debugMemSize = 0;
 static unsigned long  debugMemBlocks = 0;
-static unsigned long  debugMaxMemSize = 0;
-static xmlMutexPtr xmlMemMutex = NULL;
-
-void xmlMallocBreakpoint(void);
+static xmlMutex xmlMemMutex;
 
 /************************************************************************
  *									*
@@ -45,51 +30,23 @@ void xmlMallocBreakpoint(void);
  *									*
  ************************************************************************/
 
-#if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED)
-#ifdef xmlMalloc
-#undef xmlMalloc
-#endif
-#ifdef xmlRealloc
-#undef xmlRealloc
-#endif
-#ifdef xmlMemStrdup
-#undef xmlMemStrdup
-#endif
-#endif
-
 /*
  * Each of the blocks allocated begin with a header containing information
  */
 
 #define MEMTAG 0x5aa5U
 
-#define MALLOC_TYPE 1
-#define REALLOC_TYPE 2
-#define STRDUP_TYPE 3
-#define MALLOC_ATOMIC_TYPE 4
-#define REALLOC_ATOMIC_TYPE 5
-
 typedef struct memnod {
     unsigned int   mh_tag;
-    unsigned int   mh_type;
-    unsigned long  mh_number;
     size_t         mh_size;
-#ifdef MEM_LIST
-   struct memnod *mh_next;
-   struct memnod *mh_prev;
-#endif
-   const char    *mh_file;
-   unsigned int   mh_line;
-}  MEMHDR;
-
+} MEMHDR;
 
 #ifdef SUN4
 #define ALIGN_SIZE  16
 #else
 #define ALIGN_SIZE  sizeof(double)
 #endif
-#define HDR_SIZE    sizeof(MEMHDR)
-#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
+#define RESERVE_SIZE (((sizeof(MEMHDR) + ALIGN_SIZE - 1) \
 		      / ALIGN_SIZE ) * ALIGN_SIZE)
 
 #define MAX_SIZE_T ((size_t)-1)
@@ -97,113 +54,21 @@ typedef struct memnod {
 #define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE))
 #define HDR_2_CLIENT(a)    ((void *) (((char *) (a)) + RESERVE_SIZE))
 
-
-static unsigned int block=0;
-static unsigned int xmlMemStopAtBlock = 0;
-static void *xmlMemTraceBlockAt = NULL;
-#ifdef MEM_LIST
-static MEMHDR *memlist = NULL;
-#endif
-
-static void debugmem_tag_error(void *addr);
-#ifdef MEM_LIST
-static void  debugmem_list_add(MEMHDR *);
-static void debugmem_list_delete(MEMHDR *);
-#endif
-#define Mem_Tag_Err(a) debugmem_tag_error(a);
-
-#ifndef TEST_POINT
-#define TEST_POINT
-#endif
-
-/**
- * xmlMallocBreakpoint:
- *
- * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
- * number reaches the specified value this function is called. One need to add a breakpoint
- * to it to get the context in which the given block is allocated.
- */
-
-void
-xmlMallocBreakpoint(void) {
-    xmlGenericError(xmlGenericErrorContext,
-	    "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
-}
-
 /**
  * xmlMallocLoc:
  * @size:  an int specifying the size in byte to allocate.
  * @file:  the file name or NULL
  * @line:  the line number
  *
- * a malloc() equivalent, with logging of the allocation info.
+ * DEPRECATED: don't use
  *
  * Returns a pointer to the allocated area or NULL in case of lack of memory.
  */
-
 void *
-xmlMallocLoc(size_t size, const char * file, int line)
+xmlMallocLoc(size_t size, const char *file ATTRIBUTE_UNUSED,
+             int line ATTRIBUTE_UNUSED)
 {
-    MEMHDR *p;
-    void *ret;
-
-    if (!xmlMemInitialized) xmlInitMemory();
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Malloc(%d)\n",size);
-#endif
-
-    TEST_POINT
-
-    if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlMallocLoc : Unsigned overflow\n");
-	xmlMemoryDump();
-	return(NULL);
-    }
-
-    p = (MEMHDR *) malloc(RESERVE_SIZE+size);
-
-    if (!p) {
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlMallocLoc : Out of free space\n");
-	xmlMemoryDump();
-	return(NULL);
-    }
-    p->mh_tag = MEMTAG;
-    p->mh_size = size;
-    p->mh_type = MALLOC_TYPE;
-    p->mh_file = file;
-    p->mh_line = line;
-    xmlMutexLock(xmlMemMutex);
-    p->mh_number = ++block;
-    debugMemSize += size;
-    debugMemBlocks++;
-    if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
-#ifdef MEM_LIST
-    debugmem_list_add(p);
-#endif
-    xmlMutexUnlock(xmlMemMutex);
-
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Malloc(%d) Ok\n",size);
-#endif
-
-    if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
-
-    ret = HDR_2_CLIENT(p);
-
-    if (xmlMemTraceBlockAt == ret) {
-	xmlGenericError(xmlGenericErrorContext,
-			"%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
-			(long unsigned)size);
-	xmlMallocBreakpoint();
-    }
-
-    TEST_POINT
-
-    return(ret);
+    return(xmlMemMalloc(size));
 }
 
 /**
@@ -212,196 +77,119 @@ xmlMallocLoc(size_t size, const char * file, int line)
  * @file:  the file name or NULL
  * @line:  the line number
  *
- * a malloc() equivalent, with logging of the allocation info.
+ * DEPRECATED: don't use
  *
  * Returns a pointer to the allocated area or NULL in case of lack of memory.
  */
+void *
+xmlMallocAtomicLoc(size_t size, const char *file ATTRIBUTE_UNUSED,
+                   int line ATTRIBUTE_UNUSED)
+{
+    return(xmlMemMalloc(size));
+}
 
+/**
+ * xmlMemMalloc:
+ * @size:  an int specifying the size in byte to allocate.
+ *
+ * a malloc() equivalent, with logging of the allocation info.
+ *
+ * Returns a pointer to the allocated area or NULL in case of lack of memory.
+ */
 void *
-xmlMallocAtomicLoc(size_t size, const char * file, int line)
+xmlMemMalloc(size_t size)
 {
     MEMHDR *p;
-    void *ret;
-
-    if (!xmlMemInitialized) xmlInitMemory();
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Malloc(%d)\n",size);
-#endif
 
-    TEST_POINT
+    xmlInitParser();
 
     if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlMallocAtomicLoc : Unsigned overflow\n");
-	xmlMemoryDump();
-	return(NULL);
+        fprintf(stderr, "xmlMemMalloc: Unsigned overflow\n");
+        return(NULL);
     }
 
-    p = (MEMHDR *) malloc(RESERVE_SIZE+size);
-
+    p = (MEMHDR *) malloc(RESERVE_SIZE + size);
     if (!p) {
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlMallocAtomicLoc : Out of free space\n");
-	xmlMemoryDump();
-	return(NULL);
+        fprintf(stderr, "xmlMemMalloc: Out of memory\n");
+        return(NULL);
     }
     p->mh_tag = MEMTAG;
     p->mh_size = size;
-    p->mh_type = MALLOC_ATOMIC_TYPE;
-    p->mh_file = file;
-    p->mh_line = line;
-    xmlMutexLock(xmlMemMutex);
-    p->mh_number = ++block;
+
+    xmlMutexLock(&xmlMemMutex);
     debugMemSize += size;
     debugMemBlocks++;
-    if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
-#ifdef MEM_LIST
-    debugmem_list_add(p);
-#endif
-    xmlMutexUnlock(xmlMemMutex);
-
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Malloc(%d) Ok\n",size);
-#endif
-
-    if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
+    xmlMutexUnlock(&xmlMemMutex);
 
-    ret = HDR_2_CLIENT(p);
-
-    if (xmlMemTraceBlockAt == ret) {
-	xmlGenericError(xmlGenericErrorContext,
-			"%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
-			(long unsigned)size);
-	xmlMallocBreakpoint();
-    }
-
-    TEST_POINT
-
-    return(ret);
+    return(HDR_2_CLIENT(p));
 }
+
 /**
- * xmlMemMalloc:
+ * xmlReallocLoc:
+ * @ptr:  the initial memory block pointer
  * @size:  an int specifying the size in byte to allocate.
+ * @file:  the file name or NULL
+ * @line:  the line number
  *
- * a malloc() equivalent, with logging of the allocation info.
+ * DEPRECATED: don't use
  *
  * Returns a pointer to the allocated area or NULL in case of lack of memory.
  */
-
 void *
-xmlMemMalloc(size_t size)
+xmlReallocLoc(void *ptr, size_t size, const char *file ATTRIBUTE_UNUSED,
+              int line ATTRIBUTE_UNUSED)
 {
-    return(xmlMallocLoc(size, "none", 0));
+    return(xmlMemRealloc(ptr, size));
 }
 
 /**
- * xmlReallocLoc:
+ * xmlMemRealloc:
  * @ptr:  the initial memory block pointer
  * @size:  an int specifying the size in byte to allocate.
- * @file:  the file name or NULL
- * @line:  the line number
  *
  * a realloc() equivalent, with logging of the allocation info.
  *
  * Returns a pointer to the allocated area or NULL in case of lack of memory.
  */
-
 void *
-xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
-{
+xmlMemRealloc(void *ptr, size_t size) {
     MEMHDR *p, *tmp;
-    unsigned long number;
-#ifdef DEBUG_MEMORY
-    size_t oldsize;
-#endif
+    size_t oldSize;
 
     if (ptr == NULL)
-        return(xmlMallocLoc(size, file, line));
+        return(xmlMemMalloc(size));
+
+    xmlInitParser();
 
-    if (!xmlMemInitialized) xmlInitMemory();
-    TEST_POINT
+    if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
+        fprintf(stderr, "xmlMemRealloc: Unsigned overflow\n");
+        return(NULL);
+    }
 
     p = CLIENT_2_HDR(ptr);
-    number = p->mh_number;
-    if (xmlMemStopAtBlock == number) xmlMallocBreakpoint();
     if (p->mh_tag != MEMTAG) {
-       Mem_Tag_Err(p);
-	 goto error;
+        fprintf(stderr, "xmlMemRealloc: Tag error\n");
+        return(NULL);
     }
+    oldSize = p->mh_size;
     p->mh_tag = ~MEMTAG;
-    xmlMutexLock(xmlMemMutex);
-    debugMemSize -= p->mh_size;
-    debugMemBlocks--;
-#ifdef DEBUG_MEMORY
-    oldsize = p->mh_size;
-#endif
-#ifdef MEM_LIST
-    debugmem_list_delete(p);
-#endif
-    xmlMutexUnlock(xmlMemMutex);
-
-    if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlReallocLoc : Unsigned overflow\n");
-	xmlMemoryDump();
-	return(NULL);
-    }
 
-    tmp = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
+    tmp = (MEMHDR *) realloc(p, RESERVE_SIZE + size);
     if (!tmp) {
-	 free(p);
-	 goto error;
+        p->mh_tag = MEMTAG;
+        fprintf(stderr, "xmlMemRealloc: Out of memory\n");
+        return(NULL);
     }
     p = tmp;
-    if (xmlMemTraceBlockAt == ptr) {
-	xmlGenericError(xmlGenericErrorContext,
-			"%p : Realloced(%lu -> %lu) Ok\n",
-			xmlMemTraceBlockAt, (long unsigned)p->mh_size,
-			(long unsigned)size);
-	xmlMallocBreakpoint();
-    }
     p->mh_tag = MEMTAG;
-    p->mh_number = number;
-    p->mh_type = REALLOC_TYPE;
     p->mh_size = size;
-    p->mh_file = file;
-    p->mh_line = line;
-    xmlMutexLock(xmlMemMutex);
-    debugMemSize += size;
-    debugMemBlocks++;
-    if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
-#ifdef MEM_LIST
-    debugmem_list_add(p);
-#endif
-    xmlMutexUnlock(xmlMemMutex);
 
-    TEST_POINT
+    xmlMutexLock(&xmlMemMutex);
+    debugMemSize -= oldSize;
+    debugMemSize += size;
+    xmlMutexUnlock(&xmlMemMutex);
 
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Realloced(%d to %d) Ok\n", oldsize, size);
-#endif
     return(HDR_2_CLIENT(p));
-
-error:
-    return(NULL);
-}
-
-/**
- * xmlMemRealloc:
- * @ptr:  the initial memory block pointer
- * @size:  an int specifying the size in byte to allocate.
- *
- * a realloc() equivalent, with logging of the allocation info.
- *
- * Returns a pointer to the allocated area or NULL in case of lack of memory.
- */
-
-void *
-xmlMemRealloc(void *ptr,size_t size) {
-    return(xmlReallocLoc(ptr, size, "none", 0));
 }
 
 /**
@@ -414,64 +202,30 @@ void
 xmlMemFree(void *ptr)
 {
     MEMHDR *p;
-    char *target;
-#ifdef DEBUG_MEMORY
-    size_t size;
-#endif
 
     if (ptr == NULL)
-	return;
+        return;
 
     if (ptr == (void *) -1) {
-	xmlGenericError(xmlGenericErrorContext,
-	    "trying to free pointer from freed area\n");
-        goto error;
-    }
-
-    if (xmlMemTraceBlockAt == ptr) {
-	xmlGenericError(xmlGenericErrorContext,
-			"%p : Freed()\n", xmlMemTraceBlockAt);
-	xmlMallocBreakpoint();
+        fprintf(stderr, "xmlMemFree: Pointer from freed area\n");
+        return;
     }
 
-    TEST_POINT
-
-    target = (char *) ptr;
-
     p = CLIENT_2_HDR(ptr);
     if (p->mh_tag != MEMTAG) {
-        Mem_Tag_Err(p);
-        goto error;
+        fprintf(stderr, "xmlMemFree: Tag error\n");
+        return;
     }
-    if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
     p->mh_tag = ~MEMTAG;
-    memset(target, -1, p->mh_size);
-    xmlMutexLock(xmlMemMutex);
+    memset(ptr, -1, p->mh_size);
+
+    xmlMutexLock(&xmlMemMutex);
     debugMemSize -= p->mh_size;
     debugMemBlocks--;
-#ifdef DEBUG_MEMORY
-    size = p->mh_size;
-#endif
-#ifdef MEM_LIST
-    debugmem_list_delete(p);
-#endif
-    xmlMutexUnlock(xmlMemMutex);
+    xmlMutexUnlock(&xmlMemMutex);
 
     free(p);
 
-    TEST_POINT
-
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Freed(%d) Ok\n", size);
-#endif
-
-    return;
-
-error:
-    xmlGenericError(xmlGenericErrorContext,
-	    "xmlMemFree(%p) error\n", ptr);
-    xmlMallocBreakpoint();
     return;
 }
 
@@ -481,79 +235,77 @@ error:
  * @file:  the file name or NULL
  * @line:  the line number
  *
- * a strdup() equivalent, with logging of the allocation info.
+ * DEPRECATED: don't use
  *
  * Returns a pointer to the new string or NULL if allocation error occurred.
  */
-
 char *
-xmlMemStrdupLoc(const char *str, const char *file, int line)
+xmlMemStrdupLoc(const char *str, const char *file ATTRIBUTE_UNUSED,
+                int line ATTRIBUTE_UNUSED)
 {
+    return(xmlMemoryStrdup(str));
+}
+
+/**
+ * xmlMemoryStrdup:
+ * @str:  the initial string pointer
+ *
+ * a strdup() equivalent, with logging of the allocation info.
+ *
+ * Returns a pointer to the new string or NULL if allocation error occurred.
+ */
+char *
+xmlMemoryStrdup(const char *str) {
     char *s;
     size_t size = strlen(str) + 1;
     MEMHDR *p;
 
-    if (!xmlMemInitialized) xmlInitMemory();
-    TEST_POINT
+    xmlInitParser();
 
     if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlMemStrdupLoc : Unsigned overflow\n");
-	xmlMemoryDump();
-	return(NULL);
+        fprintf(stderr, "xmlMemoryStrdup: Unsigned overflow\n");
+        return(NULL);
     }
 
-    p = (MEMHDR *) malloc(RESERVE_SIZE+size);
+    p = (MEMHDR *) malloc(RESERVE_SIZE + size);
     if (!p) {
-      goto error;
+        fprintf(stderr, "xmlMemoryStrdup: Out of memory\n");
+        return(NULL);
     }
     p->mh_tag = MEMTAG;
     p->mh_size = size;
-    p->mh_type = STRDUP_TYPE;
-    p->mh_file = file;
-    p->mh_line = line;
-    xmlMutexLock(xmlMemMutex);
-    p->mh_number = ++block;
+
+    xmlMutexLock(&xmlMemMutex);
     debugMemSize += size;
     debugMemBlocks++;
-    if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
-#ifdef MEM_LIST
-    debugmem_list_add(p);
-#endif
-    xmlMutexUnlock(xmlMemMutex);
+    xmlMutexUnlock(&xmlMemMutex);
 
     s = (char *) HDR_2_CLIENT(p);
 
-    if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
-
-    strcpy(s,str);
-
-    TEST_POINT
-
-    if (xmlMemTraceBlockAt == s) {
-	xmlGenericError(xmlGenericErrorContext,
-			"%p : Strdup() Ok\n", xmlMemTraceBlockAt);
-	xmlMallocBreakpoint();
-    }
+    memcpy(s, str, size);
 
     return(s);
-
-error:
-    return(NULL);
 }
 
 /**
- * xmlMemoryStrdup:
- * @str:  the initial string pointer
- *
- * a strdup() equivalent, with logging of the allocation info.
+ * xmlMemSize:
+ * @ptr:  pointer to the memory allocation
  *
- * Returns a pointer to the new string or NULL if allocation error occurred.
+ * Returns the size of a memory allocation.
  */
 
-char *
-xmlMemoryStrdup(const char *str) {
-    return(xmlMemStrdupLoc(str, "none", 0));
+size_t
+xmlMemSize(void *ptr) {
+    MEMHDR *p;
+
+    if (ptr == NULL)
+	return(0);
+
+    p = CLIENT_2_HDR(ptr);
+    if (p->mh_tag != MEMTAG)
+        return(0);
+
+    return(p->mh_size);
 }
 
 /**
@@ -566,12 +318,7 @@ xmlMemoryStrdup(const char *str) {
 
 int
 xmlMemUsed(void) {
-    int res;
-
-    xmlMutexLock(xmlMemMutex);
-    res = debugMemSize;
-    xmlMutexUnlock(xmlMemMutex);
-    return(res);
+    return(debugMemSize);
 }
 
 /**
@@ -586,343 +333,55 @@ int
 xmlMemBlocks(void) {
     int res;
 
-    xmlMutexLock(xmlMemMutex);
+    xmlMutexLock(&xmlMemMutex);
     res = debugMemBlocks;
-    xmlMutexUnlock(xmlMemMutex);
+    xmlMutexUnlock(&xmlMemMutex);
     return(res);
 }
 
-#ifdef MEM_LIST
-/**
- * xmlMemContentShow:
- * @fp:  a FILE descriptor used as the output file
- * @p:  a memory block header
- *
- * tries to show some content from the memory block
- */
-
-static void
-xmlMemContentShow(FILE *fp, MEMHDR *p)
-{
-    int i,j,k,len;
-    const char *buf;
-
-    if (p == NULL) {
-	fprintf(fp, " NULL");
-	return;
-    }
-    len = p->mh_size;
-    buf = (const char *) HDR_2_CLIENT(p);
-
-    for (i = 0;i < len;i++) {
-        if (buf[i] == 0) break;
-	if (!isprint((unsigned char) buf[i])) break;
-    }
-    if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
-        if (len >= 4) {
-	    MEMHDR *q;
-	    void *cur;
-
-            for (j = 0;(j < len -3) && (j < 40);j += 4) {
-		cur = *((void **) &buf[j]);
-		q = CLIENT_2_HDR(cur);
-		p = memlist;
-		k = 0;
-		while (p != NULL) {
-		    if (p == q) break;
-		    p = p->mh_next;
-		    if (k++ > 100) break;
-		}
-		if ((p != NULL) && (p == q)) {
-		    fprintf(fp, " pointer to #%lu at index %d",
-		            p->mh_number, j);
-		    return;
-		}
-	    }
-	}
-    } else if ((i == 0) && (buf[i] == 0)) {
-        fprintf(fp," null");
-    } else {
-        if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
-	else {
-            fprintf(fp," [");
-	    for (j = 0;j < i;j++)
-                fprintf(fp,"%c", buf[j]);
-            fprintf(fp,"]");
-	}
-    }
-}
-#endif
-
 /**
  * xmlMemDisplayLast:
- * @fp:  a FILE descriptor used as the output file, if NULL, the result is
- *       written to the file .memorylist
+ * @fp:  a FILE descriptor
  * @nbBytes: the amount of memory to dump
  *
- * the last nbBytes of memory allocated and not freed, useful for dumping
- * the memory left allocated between two places at runtime.
+ * DEPRECATED: This feature was removed.
  */
-
 void
-xmlMemDisplayLast(FILE *fp, long nbBytes)
+xmlMemDisplayLast(FILE *fp ATTRIBUTE_UNUSED, long nbBytes ATTRIBUTE_UNUSED)
 {
-#ifdef MEM_LIST
-    MEMHDR *p;
-    unsigned idx;
-    int     nb = 0;
-#endif
-    FILE *old_fp = fp;
-
-    if (nbBytes <= 0)
-        return;
-
-    if (fp == NULL) {
-	fp = fopen(".memorylist", "w");
-	if (fp == NULL)
-	    return;
-    }
-
-#ifdef MEM_LIST
-    fprintf(fp,"   Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n",
-            nbBytes, debugMemSize, debugMaxMemSize);
-    fprintf(fp,"BLOCK  NUMBER   SIZE  TYPE\n");
-    idx = 0;
-    xmlMutexLock(xmlMemMutex);
-    p = memlist;
-    while ((p) && (nbBytes > 0)) {
-	  fprintf(fp,"%-5u  %6lu %6lu ",idx++,p->mh_number,
-		  (unsigned long)p->mh_size);
-        switch (p->mh_type) {
-           case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
-           case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
-           case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
-           case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
-           case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
-           default:
-	        fprintf(fp,"Unknown memory block, may be corrupted");
-		xmlMutexUnlock(xmlMemMutex);
-		if (old_fp == NULL)
-		    fclose(fp);
-		return;
-        }
-	if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
-        if (p->mh_tag != MEMTAG)
-	      fprintf(fp,"  INVALID");
-        nb++;
-	if (nb < 100)
-	    xmlMemContentShow(fp, p);
-	else
-	    fprintf(fp," skip");
-
-        fprintf(fp,"\n");
-	nbBytes -= (unsigned long)p->mh_size;
-        p = p->mh_next;
-    }
-    xmlMutexUnlock(xmlMemMutex);
-#else
-    fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
-#endif
-    if (old_fp == NULL)
-	fclose(fp);
 }
 
 /**
  * xmlMemDisplay:
- * @fp:  a FILE descriptor used as the output file, if NULL, the result is
- *       written to the file .memorylist
+ * @fp:  a FILE descriptor
  *
- * show in-extenso the memory blocks allocated
+ * DEPRECATED: This feature was removed.
  */
-
 void
-xmlMemDisplay(FILE *fp)
+xmlMemDisplay(FILE *fp ATTRIBUTE_UNUSED)
 {
-#ifdef MEM_LIST
-    MEMHDR *p;
-    unsigned idx;
-    int     nb = 0;
-    time_t currentTime;
-    char buf[500];
-    struct tm * tstruct;
-#endif
-    FILE *old_fp = fp;
-
-    if (fp == NULL) {
-	fp = fopen(".memorylist", "w");
-	if (fp == NULL)
-	    return;
-    }
-
-#ifdef MEM_LIST
-    currentTime = time(NULL);
-    tstruct = localtime(&currentTime);
-    strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
-    fprintf(fp,"      %s\n\n", buf);
-
-
-    fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lu\n",
-            debugMemSize, debugMaxMemSize);
-    fprintf(fp,"BLOCK  NUMBER   SIZE  TYPE\n");
-    idx = 0;
-    xmlMutexLock(xmlMemMutex);
-    p = memlist;
-    while (p) {
-	  fprintf(fp,"%-5u  %6lu %6lu ",idx++,p->mh_number,
-		  (unsigned long)p->mh_size);
-        switch (p->mh_type) {
-           case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
-           case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
-           case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
-           case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
-           case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
-           default:
-	        fprintf(fp,"Unknown memory block, may be corrupted");
-		xmlMutexUnlock(xmlMemMutex);
-		if (old_fp == NULL)
-		    fclose(fp);
-		return;
-        }
-	if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
-        if (p->mh_tag != MEMTAG)
-	      fprintf(fp,"  INVALID");
-        nb++;
-	if (nb < 100)
-	    xmlMemContentShow(fp, p);
-	else
-	    fprintf(fp," skip");
-
-        fprintf(fp,"\n");
-        p = p->mh_next;
-    }
-    xmlMutexUnlock(xmlMemMutex);
-#else
-    fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
-#endif
-    if (old_fp == NULL)
-	fclose(fp);
-}
-
-#ifdef MEM_LIST
-
-static void debugmem_list_add(MEMHDR *p)
-{
-     p->mh_next = memlist;
-     p->mh_prev = NULL;
-     if (memlist) memlist->mh_prev = p;
-     memlist = p;
-#ifdef MEM_LIST_DEBUG
-     if (stderr)
-     Mem_Display(stderr);
-#endif
-}
-
-static void debugmem_list_delete(MEMHDR *p)
-{
-     if (p->mh_next)
-     p->mh_next->mh_prev = p->mh_prev;
-     if (p->mh_prev)
-     p->mh_prev->mh_next = p->mh_next;
-     else memlist = p->mh_next;
-#ifdef MEM_LIST_DEBUG
-     if (stderr)
-     Mem_Display(stderr);
-#endif
 }
 
-#endif
-
-/*
- * debugmem_tag_error:
- *
- * internal error function.
- */
-
-static void debugmem_tag_error(void *p)
-{
-     xmlGenericError(xmlGenericErrorContext,
-	     "Memory tag error occurs :%p \n\t bye\n", p);
-#ifdef MEM_LIST
-     if (stderr)
-     xmlMemDisplay(stderr);
-#endif
-}
-
-#ifdef MEM_LIST
-static FILE *xmlMemoryDumpFile = NULL;
-#endif
-
 /**
  * xmlMemShow:
- * @fp:  a FILE descriptor used as the output file
+ * @fp:  a FILE descriptor
  * @nr:  number of entries to dump
  *
- * show a show display of the memory allocated, and dump
- * the @nr last allocated areas which were not freed
+ * DEPRECATED: This feature was removed.
  */
-
 void
-xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED)
+xmlMemShow(FILE *fp ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED)
 {
-#ifdef MEM_LIST
-    MEMHDR *p;
-#endif
-
-    if (fp != NULL)
-	fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lu\n",
-		debugMemSize, debugMaxMemSize);
-#ifdef MEM_LIST
-    xmlMutexLock(xmlMemMutex);
-    if (nr > 0) {
-	fprintf(fp,"NUMBER   SIZE  TYPE   WHERE\n");
-	p = memlist;
-	while ((p) && nr > 0) {
-	      fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
-	    switch (p->mh_type) {
-	       case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
-	       case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
-	       case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
-	      case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
-	      case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
-		default:fprintf(fp,"   ???    in ");break;
-	    }
-	    if (p->mh_file != NULL)
-	        fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
-	    if (p->mh_tag != MEMTAG)
-		fprintf(fp,"  INVALID");
-	    xmlMemContentShow(fp, p);
-	    fprintf(fp,"\n");
-	    nr--;
-	    p = p->mh_next;
-	}
-    }
-    xmlMutexUnlock(xmlMemMutex);
-#endif /* MEM_LIST */
 }
 
 /**
  * xmlMemoryDump:
  *
- * Dump in-extenso the memory blocks allocated to the file .memorylist
+ * DEPRECATED: This feature was removed.
  */
-
 void
 xmlMemoryDump(void)
 {
-#ifdef MEM_LIST
-    FILE *dump;
-
-    if (debugMaxMemSize == 0)
-	return;
-    dump = fopen(".memdump", "w");
-    if (dump == NULL)
-	xmlMemoryDumpFile = stderr;
-    else xmlMemoryDumpFile = dump;
-
-    xmlMemDisplay(xmlMemoryDumpFile);
-
-    if (dump != NULL) fclose(dump);
-#endif /* MEM_LIST */
 }
 
 
@@ -935,71 +394,55 @@ xmlMemoryDump(void)
 /**
  * xmlInitMemory:
  *
- * DEPRECATED: This function will be made private. Call xmlInitParser to
- * initialize the library.
+ * DEPRECATED: Alias for xmlInitParser.
  *
- * Initialize the memory layer.
- *
- * Returns 0 on success
+ * Returns 0.
  */
 int
-xmlInitMemory(void)
-{
-     char *breakpoint;
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlInitMemory()\n");
-#endif
-    /*
-     This is really not good code (see Bug 130419).  Suggestions for
-     improvement will be welcome!
-    */
-     if (xmlMemInitialized) return(-1);
-     xmlMemInitialized = 1;
-     xmlMemMutex = xmlNewMutex();
-
-     breakpoint = getenv("XML_MEM_BREAKPOINT");
-     if (breakpoint != NULL) {
-         sscanf(breakpoint, "%ud", &xmlMemStopAtBlock);
-     }
-     breakpoint = getenv("XML_MEM_TRACE");
-     if (breakpoint != NULL) {
-         sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
-     }
-
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlInitMemory() Ok\n");
-#endif
-     return(0);
+xmlInitMemory(void) {
+    xmlInitParser();
+    return(0);
+}
+
+/**
+ * xmlInitMemoryInternal:
+ *
+ * Initialize the memory layer.
+ */
+void
+xmlInitMemoryInternal(void) {
+    xmlInitMutex(&xmlMemMutex);
 }
 
 /**
  * xmlCleanupMemory:
  *
- * DEPRECATED: This function will be made private. Call xmlCleanupParser
+ * DEPRECATED: This function is a no-op. Call xmlCleanupParser
  * to free global state but see the warnings there. xmlCleanupParser
  * should be only called once at program exit. In most cases, you don't
  * have call cleanup functions at all.
+ */
+void
+xmlCleanupMemory(void) {
+}
+
+/**
+ * xmlCleanupMemoryInternal:
  *
  * Free up all the memory allocated by the library for its own
  * use. This should not be called by user level code.
  */
 void
-xmlCleanupMemory(void) {
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlCleanupMemory()\n");
-#endif
-    if (xmlMemInitialized == 0)
-        return;
-
-    xmlFreeMutex(xmlMemMutex);
-    xmlMemMutex = NULL;
-    xmlMemInitialized = 0;
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlCleanupMemory() Ok\n");
+xmlCleanupMemoryInternal(void) {
+    /*
+     * Don't clean up mutex on Windows. Global state destructors can call
+     * malloc functions after xmlCleanupParser was called. If memory
+     * debugging is enabled, xmlMemMutex can be used after cleanup.
+     *
+     * See python/tests/thread2.py
+     */
+#if !defined(LIBXML_THREAD_ENABLED) || !defined(_WIN32)
+    xmlCleanupMutex(&xmlMemMutex);
 #endif
 }
 
@@ -1021,10 +464,6 @@ xmlCleanupMemory(void) {
 int
 xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
             xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlMemSetup()\n");
-#endif
     if (freeFunc == NULL)
 	return(-1);
     if (mallocFunc == NULL)
@@ -1038,10 +477,6 @@ xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
     xmlMallocAtomic = mallocFunc;
     xmlRealloc = reallocFunc;
     xmlMemStrdup = strdupFunc;
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlMemSetup() Ok\n");
-#endif
     return(0);
 }
 
@@ -1088,10 +523,6 @@ int
 xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
               xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
 	      xmlStrdupFunc strdupFunc) {
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlGcMemSetup()\n");
-#endif
     if (freeFunc == NULL)
 	return(-1);
     if (mallocFunc == NULL)
@@ -1107,10 +538,6 @@ xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
     xmlMallocAtomic = mallocAtomicFunc;
     xmlRealloc = reallocFunc;
     xmlMemStrdup = strdupFunc;
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlGcMemSetup() Ok\n");
-#endif
     return(0);
 }
 
diff --git a/xmlmodule.c b/xmlmodule.c
index 44eba066977b527a0b14a0424b375257a9fefd2f..dd2fd7a53932674a846a2f96c83ed9fe0253660f 100644
--- a/xmlmodule.c
+++ b/xmlmodule.c
@@ -17,10 +17,12 @@
 #include "libxml.h"
 
 #include <string.h>
+#include <libxml/xmlmodule.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/xmlerror.h>
-#include <libxml/xmlmodule.h>
-#include <libxml/globals.h>
+#include <libxml/xmlstring.h>
+
+#include "private/error.h"
 
 #ifdef LIBXML_MODULES_ENABLED
 
@@ -39,27 +41,6 @@ static int xmlModulePlatformSymbol(void *handle, const char *name, void **result
  *									*
  ************************************************************************/
 
-/**
- * xmlModuleErrMemory:
- * @extra:  extra information
- *
- * Handle an out of memory condition
- */
-static void
-xmlModuleErrMemory(xmlModulePtr module, const char *extra)
-{
-    const char *name = NULL;
-
-    if (module != NULL) {
-        name = (const char *) module->name;
-    }
-
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
-                    XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
-                    name, NULL, 0, 0,
-                    "Memory allocation failed : %s\n", extra);
-}
-
 /**
  * xmlModuleOpen:
  * @name: the module name
@@ -80,10 +61,8 @@ xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED)
     xmlModulePtr module;
 
     module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
-    if (module == NULL) {
-        xmlModuleErrMemory(NULL, "creating module");
+    if (module == NULL)
         return (NULL);
-    }
 
     memset(module, 0, sizeof(xmlModule));
 
@@ -91,9 +70,6 @@ xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED)
 
     if (module->handle == NULL) {
         xmlFree(module);
-        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
-                        XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
-                        name, NULL, 0, 0, "failed to open %s\n", name);
         return(NULL);
     }
 
@@ -120,23 +96,13 @@ xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol)
 {
     int rc = -1;
 
-    if ((NULL == module) || (symbol == NULL) || (name == NULL)) {
-        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
-                        XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
-                        NULL, NULL, 0, 0, "null parameter\n");
+    if ((NULL == module) || (symbol == NULL) || (name == NULL))
         return rc;
-    }
 
     rc = xmlModulePlatformSymbol(module->handle, name, symbol);
 
-    if (rc == -1) {
-        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
-                        XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
-                        name, NULL, 0, 0,
-                        "failed to find symbol: %s\n",
-			(name == NULL ? "NULL" : name));
+    if (rc == -1)
         return rc;
-    }
 
     return rc;
 }
@@ -156,22 +122,13 @@ xmlModuleClose(xmlModulePtr module)
 {
     int rc;
 
-    if (NULL == module) {
-        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
-                        XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
-                        NULL, NULL, 0, 0, "null module pointer\n");
+    if (NULL == module)
         return -1;
-    }
 
     rc = xmlModulePlatformClose(module->handle);
 
-    if (rc != 0) {
-        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
-                        XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
-                        (const char *) module->name, NULL, 0, 0,
-                        "failed to close: %s\n", module->name);
+    if (rc != 0)
         return -2;
-    }
 
     rc = xmlModuleFree(module);
     return (rc);
@@ -190,12 +147,8 @@ xmlModuleClose(xmlModulePtr module)
 int
 xmlModuleFree(xmlModulePtr module)
 {
-    if (NULL == module) {
-        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
-                        XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL,
-                        NULL, NULL, 0, 0, "null module pointer\n");
+    if (NULL == module)
         return -1;
-    }
 
     xmlFree(module->name);
     xmlFree(module);
@@ -340,7 +293,7 @@ xmlModulePlatformClose(void *handle)
 static int
 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
 {
-XML_IGNORE_PEDANTIC_WARNINGS
+XML_IGNORE_FPTR_CAST_WARNINGS
     *symbol = GetProcAddress(handle, name);
     return (NULL == *symbol) ? -1 : 0;
 XML_POP_WARNINGS
@@ -348,112 +301,4 @@ XML_POP_WARNINGS
 
 #endif /* _WIN32 */
 
-#ifdef HAVE_BEOS
-
-#include <kernel/image.h>
-
-/*
- * xmlModulePlatformOpen:
- * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
- * returns a handle on success, and zero on error.
- */
-
-static void *
-xmlModulePlatformOpen(const char *name)
-{
-    return (void *) load_add_on(name);
-}
-
-/*
- * xmlModulePlatformClose:
- * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
- * returns 0 on success, and non-zero on error.
- */
-
-static int
-xmlModulePlatformClose(void *handle)
-{
-    status_t rc;
-
-    rc = unload_add_on((image_id) handle);
-
-    if (rc == B_OK)
-        return 0;
-    else
-        return -1;
-}
-
-/*
- * xmlModulePlatformSymbol:
- * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
- * returns 0 on success and the loaded symbol in result, and -1 on error.
- */
-
-static int
-xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
-{
-    status_t rc;
-
-    rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol);
-
-    return (rc == B_OK) ? 0 : -1;
-}
-
-#endif /* HAVE_BEOS */
-
-#ifdef HAVE_OS2
-
-#include <os2.h>
-
-/*
- * xmlModulePlatformOpen:
- * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html
- * returns a handle on success, and zero on error.
- */
-
-static void *
-xmlModulePlatformOpen(const char *name)
-{
-    char errbuf[256];
-    void *handle;
-    int rc;
-
-    rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle);
-
-    if (rc)
-        return 0;
-    else
-        return (handle);
-}
-
-/*
- * xmlModulePlatformClose:
- * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html
- * returns 0 on success, and non-zero on error.
- */
-
-static int
-xmlModulePlatformClose(void *handle)
-{
-    return DosFreeModule(handle);
-}
-
-/*
- * xmlModulePlatformSymbol:
- * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html
- * returns 0 on success and the loaded symbol in result, and -1 on error.
- */
-
-static int
-xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
-{
-    int rc;
-
-    rc = DosQueryProcAddr(handle, 0, name, symbol);
-
-    return (rc == NO_ERROR) ? 0 : -1;
-}
-
-#endif /* HAVE_OS2 */
-
 #endif /* LIBXML_MODULES_ENABLED */
diff --git a/xmlreader.c b/xmlreader.c
index b3299cedfccebb74c9a57f3e5a6e093b99376df5..3528d7d8f0c179d401c4a454a43c1a290ddae0c1 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -39,9 +39,13 @@
 #include <libxml/pattern.h>
 #endif
 
-#include "buf.h"
-
-#define MAX_ERR_MSG_SIZE 64000
+#include "private/buf.h"
+#include "private/error.h"
+#include "private/tree.h"
+#include "private/parser.h"
+#ifdef LIBXML_XINCLUDE_ENABLED
+#include "private/xinclude.h"
+#endif
 
 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 /* Keeping free objects can hide memory errors. */
@@ -50,48 +54,14 @@
 #define MAX_FREE_NODES 100
 #endif
 
-/*
- * The following VA_COPY was coded following an example in
- * the Samba project.  It may not be sufficient for some
- * esoteric implementations of va_list but (hopefully) will
- * be sufficient for libxml2.
- */
-#ifndef VA_COPY
-  #ifdef HAVE_VA_COPY
-    #define VA_COPY(dest, src) va_copy(dest, src)
+#ifndef va_copy
+  #ifdef __va_copy
+    #define va_copy(dest, src) __va_copy(dest, src)
   #else
-    #ifdef HAVE___VA_COPY
-      #define VA_COPY(dest,src) __va_copy(dest, src)
-    #else
-      #ifndef VA_LIST_IS_ARRAY
-        #define VA_COPY(dest,src) (dest) = (src)
-      #else
-        #include <string.h>
-        #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
-      #endif
-    #endif
+    #define va_copy(dest, src) memcpy(dest, src, sizeof(va_list))
   #endif
 #endif
 
-/* #define DEBUG_CALLBACKS */
-/* #define DEBUG_READER */
-
-/**
- * TODO:
- *
- * macro to flag unimplemented blocks
- */
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
-
-#ifdef DEBUG_READER
-#define DUMP_READER xmlTextReaderDebug(reader);
-#else
-#define DUMP_READER
-#endif
-
 #define CHUNK_SIZE 512
 /************************************************************************
  *									*
@@ -192,22 +162,9 @@ struct _xmlTextReader {
 #define NODE_IS_PRESERVED	0x2
 #define NODE_IS_SPRESERVED	0x4
 
-/**
- * CONSTSTR:
- *
- * Macro used to return an interned string
- */
-#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
-#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
-
 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
 
-/************************************************************************
- *									*
- *	Our own version of the freeing routines as we recycle nodes	*
- *									*
- ************************************************************************/
 /**
  * DICT_FREE:
  * @str:  a string
@@ -223,6 +180,65 @@ static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
 
+static void
+xmlTextReaderErrMemory(xmlTextReaderPtr reader) {
+    if (reader->ctxt != NULL)
+        xmlCtxtErrMemory(reader->ctxt);
+    else
+        xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_PARSER, NULL);
+    reader->mode = XML_TEXTREADER_MODE_ERROR;
+    reader->state = XML_TEXTREADER_ERROR;
+}
+
+static xmlChar *
+readerStrdup(xmlTextReaderPtr reader, const xmlChar *string) {
+    xmlChar *copy;
+
+    if (string == NULL)
+        return(NULL);
+
+    copy = xmlStrdup(string);
+    if (copy == NULL)
+        xmlTextReaderErrMemory(reader);
+
+    return(copy);
+}
+
+static const xmlChar *
+constString(xmlTextReaderPtr reader, const xmlChar *string) {
+    const xmlChar *dictString;
+
+    if (string == NULL)
+        return(NULL);
+
+    dictString = xmlDictLookup(reader->dict, string, -1);
+    if (dictString == NULL)
+        xmlTextReaderErrMemory(reader);
+
+    return(dictString);
+}
+
+static const xmlChar *
+constQString(xmlTextReaderPtr reader, const xmlChar *prefix,
+             const xmlChar *name) {
+    const xmlChar *dictString;
+
+    if (name == NULL)
+        return(NULL);
+
+    dictString = xmlDictQLookup(reader->dict, prefix, name);
+    if (dictString == NULL)
+        xmlTextReaderErrMemory(reader);
+
+    return(dictString);
+}
+
+/************************************************************************
+ *									*
+ *	Our own version of the freeing routines as we recycle nodes	*
+ *									*
+ ************************************************************************/
+
 /**
  * xmlTextReaderFreeProp:
  * @reader:  the xmlTextReaderPtr used
@@ -246,7 +262,19 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
     if (cur->children != NULL)
         xmlTextReaderFreeNodeList(reader, cur->children);
 
-    DICT_FREE(cur->name);
+    if (cur->id != NULL) {
+        /*
+         * Operating in streaming mode, attr is gonna disappear
+         */
+        cur->id->attr = NULL;
+        if (cur->id->name != NULL)
+            DICT_FREE(cur->id->name);
+        cur->id->name = cur->name;
+        cur->name = NULL;
+    } else {
+        DICT_FREE(cur->name);
+    }
+
     if ((reader != NULL) && (reader->ctxt != NULL) &&
         (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
         cur->next = reader->ctxt->freeAttrs;
@@ -501,33 +529,34 @@ xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
  *			The reader core parser				*
  *									*
  ************************************************************************/
-#ifdef DEBUG_READER
+
 static void
-xmlTextReaderDebug(xmlTextReaderPtr reader) {
-    if ((reader == NULL) || (reader->ctxt == NULL)) {
-	fprintf(stderr, "xmlTextReader NULL\n");
-	return;
-    }
-    fprintf(stderr, "xmlTextReader: state %d depth %d ",
-	    reader->state, reader->depth);
-    if (reader->node == NULL) {
-	fprintf(stderr, "node = NULL\n");
-    } else {
-	fprintf(stderr, "node %s\n", reader->node->name);
-    }
-    fprintf(stderr, "  input: base %d, cur %d, depth %d: ",
-	    reader->base, reader->cur, reader->ctxt->nodeNr);
-    if (reader->input->buffer == NULL) {
-	fprintf(stderr, "buffer is NULL\n");
-    } else {
-#ifdef LIBXML_DEBUG_ENABLED
-	xmlDebugDumpString(stderr,
-		&reader->input->buffer->content[reader->cur]);
-#endif
-	fprintf(stderr, "\n");
+xmlTextReaderStructuredRelay(void *userData, const xmlError *error)
+{
+    xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
+
+    if (reader->sErrorFunc != NULL) {
+        reader->sErrorFunc(reader->errorFuncArg, error);
+    } else if (reader->errorFunc != NULL) {
+        xmlParserSeverities severity;
+
+        if ((error->domain == XML_FROM_VALID) ||
+            (error->domain == XML_FROM_DTD)) {
+            if (error->level == XML_ERR_WARNING)
+                severity = XML_PARSER_SEVERITY_VALIDITY_WARNING;
+            else
+                severity = XML_PARSER_SEVERITY_VALIDITY_ERROR;
+        } else {
+            if (error->level == XML_ERR_WARNING)
+                severity = XML_PARSER_SEVERITY_WARNING;
+            else
+                severity = XML_PARSER_SEVERITY_ERROR;
+        }
+
+        reader->errorFunc(reader->errorFuncArg, error->message, severity,
+                          reader->ctxt);
     }
 }
-#endif
 
 /**
  * xmlTextReaderEntPush:
@@ -536,30 +565,23 @@ xmlTextReaderDebug(xmlTextReaderPtr reader) {
  *
  * Pushes a new entity reference node on top of the entities stack
  *
- * Returns 0 in case of error, the index in the stack otherwise
+ * Returns -1 in case of error, the index in the stack otherwise
  */
 static int
 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
 {
-    if (reader->entMax <= 0) {
-	reader->entMax = 10;
-	reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
-		                                  sizeof(reader->entTab[0]));
-        if (reader->entTab == NULL) {
-            xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
-            return (0);
-        }
-    }
     if (reader->entNr >= reader->entMax) {
-        reader->entMax *= 2;
-        reader->entTab =
-            (xmlNodePtr *) xmlRealloc(reader->entTab,
-                                      reader->entMax *
-                                      sizeof(reader->entTab[0]));
-        if (reader->entTab == NULL) {
-            xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
-            return (0);
+        size_t newSize = reader->entMax == 0 ? 10 : reader->entMax * 2;
+        xmlNodePtr *tmp;
+
+        tmp = (xmlNodePtr *) xmlRealloc(reader->entTab,
+                                        newSize * sizeof(*tmp));
+        if (tmp == NULL) {
+            xmlTextReaderErrMemory(reader);
+            return (-1);
         }
+        reader->entTab = tmp;
+        reader->entMax = newSize;
     }
     reader->entTab[reader->entNr] = value;
     reader->ent = value;
@@ -605,9 +627,6 @@ xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderStartElement(%s)\n", fullname);
-#endif
     if ((reader != NULL) && (reader->startElement != NULL)) {
 	reader->startElement(ctx, fullname, atts);
 	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
@@ -631,9 +650,6 @@ xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderEndElement(%s)\n", fullname);
-#endif
     if ((reader != NULL) && (reader->endElement != NULL)) {
 	reader->endElement(ctx, fullname);
     }
@@ -668,9 +684,6 @@ xmlTextReaderStartElementNs(void *ctx,
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderStartElementNs(%s)\n", localname);
-#endif
     if ((reader != NULL) && (reader->startElementNs != NULL)) {
 	reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
 	                       namespaces, nb_attributes, nb_defaulted,
@@ -702,9 +715,6 @@ xmlTextReaderEndElementNs(void *ctx,
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderEndElementNs(%s)\n", localname);
-#endif
     if ((reader != NULL) && (reader->endElementNs != NULL)) {
 	reader->endElementNs(ctx, localname, prefix, URI);
     }
@@ -725,9 +735,6 @@ xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderCharacters()\n");
-#endif
     if ((reader != NULL) && (reader->characters != NULL)) {
 	reader->characters(ctx, ch, len);
     }
@@ -747,9 +754,6 @@ xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderCDataBlock()\n");
-#endif
     if ((reader != NULL) && (reader->cdataBlock != NULL)) {
 	reader->cdataBlock(ctx, ch, len);
     }
@@ -769,7 +773,6 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
     xmlBufPtr inbuf;
     int val, s;
     xmlTextReaderState oldstate;
-    int alloc;
 
     if ((reader->input == NULL) || (reader->input->buffer == NULL))
 	return(-1);
@@ -777,7 +780,6 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
     oldstate = reader->state;
     reader->state = XML_TEXTREADER_NONE;
     inbuf = reader->input->buffer;
-    alloc = xmlBufGetAllocationScheme(inbuf);
 
     while (reader->state == XML_TEXTREADER_NONE) {
 	if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
@@ -786,22 +788,16 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
 	     */
 	    if (reader->mode != XML_TEXTREADER_MODE_EOF) {
 		val = xmlParserInputBufferRead(reader->input, 4096);
-		if ((val == 0) &&
-		    (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
+		if (val == 0) {
 		    if (xmlBufUse(inbuf) == reader->cur) {
 			reader->mode = XML_TEXTREADER_MODE_EOF;
-			reader->state = oldstate;
+                        break;
 		    }
 		} else if (val < 0) {
-		    reader->mode = XML_TEXTREADER_MODE_EOF;
-		    reader->state = oldstate;
-		    if ((oldstate != XML_TEXTREADER_START) ||
-			(reader->ctxt->myDoc != NULL))
-			return(val);
-		} else if (val == 0) {
-		    /* mark the end of the stream and process the remains */
-		    reader->mode = XML_TEXTREADER_MODE_EOF;
-		    break;
+                    xmlCtxtErrIO(reader->ctxt, reader->input->error, NULL);
+                    reader->mode = XML_TEXTREADER_MODE_ERROR;
+                    reader->state = XML_TEXTREADER_ERROR;
+                    return(-1);
 		}
 
 	    } else
@@ -831,12 +827,13 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
 	    break;
 	}
     }
+    reader->state = oldstate;
 
     /*
      * Discard the consumed input when needed and possible
      */
     if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
-        if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
+        if (reader->input->readcallback != NULL) {
 	    if ((reader->cur >= 4096) &&
 		(xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
 		val = xmlBufShrink(inbuf, reader->cur);
@@ -867,7 +864,6 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
 	    }
 	}
     }
-    reader->state = oldstate;
     if (reader->ctxt->wellFormed == 0) {
 	reader->mode = XML_TEXTREADER_MODE_EOF;
         return(-1);
@@ -883,8 +879,8 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
  *
  * Push the current node for validation
  */
-static void
-xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
+static int
+xmlTextReaderValidatePush(xmlTextReaderPtr reader) {
     xmlNodePtr node = reader->node;
 
 #ifdef LIBXML_VALID_ENABLED
@@ -894,17 +890,24 @@ xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
 	    reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
 				    reader->ctxt->myDoc, node, node->name);
 	} else {
-	    /* TODO use the BuildQName interface */
+            xmlChar buf[50];
 	    xmlChar *qname;
 
-	    qname = xmlStrdup(node->ns->prefix);
-	    qname = xmlStrcat(qname, BAD_CAST ":");
-	    qname = xmlStrcat(qname, node->name);
+	    qname = xmlBuildQName(node->name, node->ns->prefix, buf, 50);
+            if (qname == NULL) {
+                xmlTextReaderErrMemory(reader);
+                return(-1);
+            }
 	    reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
 				    reader->ctxt->myDoc, node, qname);
-	    if (qname != NULL)
-		xmlFree(qname);
+            if (qname != buf)
+	        xmlFree(qname);
 	}
+        /*if (reader->ctxt->errNo == XML_ERR_NO_MEMORY) {
+            reader->mode = XML_TEXTREADER_MODE_ERROR;
+            reader->state = XML_TEXTREADER_ERROR;
+            return(-1);
+        }*/
     }
 #endif /* LIBXML_VALID_ENABLED */
 #ifdef LIBXML_SCHEMAS_ENABLED
@@ -912,7 +915,7 @@ xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
                (reader->rngValidCtxt != NULL)) {
 	int ret;
 
-	if (reader->rngFullNode != NULL) return;
+	if (reader->rngFullNode != NULL) return(0);
 	ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
 	                                    reader->ctxt->myDoc,
 					    node);
@@ -934,6 +937,8 @@ xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
 	    reader->rngValidErrors++;
     }
 #endif
+
+    return(0);
 }
 
 /**
@@ -973,7 +978,7 @@ xmlTextReaderValidateCData(xmlTextReaderPtr reader,
  *
  * Pop the current node from validation
  */
-static void
+static int
 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
     xmlNodePtr node = reader->node;
 
@@ -984,17 +989,24 @@ xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
 	    reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
 				    reader->ctxt->myDoc, node, node->name);
 	} else {
-	    /* TODO use the BuildQName interface */
+            xmlChar buf[50];
 	    xmlChar *qname;
 
-	    qname = xmlStrdup(node->ns->prefix);
-	    qname = xmlStrcat(qname, BAD_CAST ":");
-	    qname = xmlStrcat(qname, node->name);
+	    qname = xmlBuildQName(node->name, node->ns->prefix, buf, 50);
+            if (qname == NULL) {
+                xmlTextReaderErrMemory(reader);
+                return(-1);
+            }
 	    reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
 				    reader->ctxt->myDoc, node, qname);
-	    if (qname != NULL)
-		xmlFree(qname);
+            if (qname != buf)
+	        xmlFree(qname);
 	}
+        /*if (reader->ctxt->errNo == XML_ERR_NO_MEMORY) {
+            reader->mode = XML_TEXTREADER_MODE_ERROR;
+            reader->state = XML_TEXTREADER_ERROR;
+            return(-1);
+        }*/
     }
 #endif /* LIBXML_VALID_ENABLED */
 #ifdef LIBXML_SCHEMAS_ENABLED
@@ -1005,7 +1017,7 @@ xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
 	if (reader->rngFullNode != NULL) {
 	    if (node == reader->rngFullNode)
 	        reader->rngFullNode = NULL;
-	    return;
+	    return(0);
 	}
 	ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
 	                                   reader->ctxt->myDoc,
@@ -1014,6 +1026,8 @@ xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
 	    reader->rngValidErrors++;
     }
 #endif
+
+    return(0);
 }
 
 /**
@@ -1024,7 +1038,7 @@ xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
  * entity substitution is not activated. As a result the parser interface
  * must walk through the entity and do the validation calls
  */
-static void
+static int
 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
     xmlNodePtr oldnode = reader->node;
     xmlNodePtr node = reader->node;
@@ -1034,7 +1048,11 @@ xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
 	    if ((node->children != NULL) &&
 		(node->children->type == XML_ENTITY_DECL) &&
 		(node->children->children != NULL)) {
-		xmlTextReaderEntPush(reader, node);
+		if (xmlTextReaderEntPush(reader, node) < 0) {
+                    if (node == oldnode)
+                        break;
+                    goto skip_children;
+                }
 		node = node->children->children;
 		continue;
 	    } else {
@@ -1048,7 +1066,8 @@ xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
 #ifdef LIBXML_REGEXP_ENABLED
 	} else if (node->type == XML_ELEMENT_NODE) {
 	    reader->node = node;
-	    xmlTextReaderValidatePush(reader);
+	    if (xmlTextReaderValidatePush(reader) < 0)
+                return(-1);
 	} else if ((node->type == XML_TEXT_NODE) ||
 		   (node->type == XML_CDATA_SECTION_NODE)) {
             xmlTextReaderValidateCData(reader, node->content,
@@ -1063,7 +1082,8 @@ xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
 	    node = node->children;
 	    continue;
 	} else if (node->type == XML_ELEMENT_NODE) {
-	    xmlTextReaderValidatePop(reader);
+	    if (xmlTextReaderValidatePop(reader) < 0)
+                return(-1);
 	}
 skip_children:
 	if (node->next != NULL) {
@@ -1084,7 +1104,8 @@ skip_children:
 		    }
 		}
 		reader->node = node;
-		xmlTextReaderValidatePop(reader);
+		if (xmlTextReaderValidatePop(reader) < 0)
+                    return(-1);
 	    }
 	    if ((node->type == XML_ENTITY_DECL) &&
 		(reader->ent != NULL) && (reader->ent->children == node)) {
@@ -1099,6 +1120,8 @@ skip_children:
 	} while ((node != NULL) && (node != oldnode));
     } while ((node != NULL) && (node != oldnode));
     reader->node = oldnode;
+
+    return(0);
 }
 #endif /* LIBXML_REGEXP_ENABLED */
 
@@ -1141,7 +1164,8 @@ xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
     if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
         return(-1);
     do {
-	if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
+	if (PARSER_STOPPED(reader->ctxt))
+            return(1);
 
         if (xmlTextReaderGetSuccessor(reader->node) != NULL)
 	    return(1);
@@ -1152,60 +1176,13 @@ xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
 	val = xmlTextReaderPushData(reader);
 	if (val < 0){
 	    reader->mode = XML_TEXTREADER_MODE_ERROR;
+            reader->state = XML_TEXTREADER_ERROR;
 	    return(-1);
 	}
     } while(reader->mode != XML_TEXTREADER_MODE_EOF);
     return(1);
 }
 
-/**
- * xmlTextReaderCollectSiblings:
- * @node:    the first child
- *
- *  Traverse depth-first through all sibling nodes and their children
- *  nodes and concatenate their content. This is an auxiliary function
- *  to xmlTextReaderReadString.
- *
- *  Returns a string containing the content, or NULL in case of error.
- */
-static xmlChar *
-xmlTextReaderCollectSiblings(xmlNodePtr node)
-{
-    xmlBufferPtr buffer;
-    xmlChar *ret;
-
-    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
-        return(NULL);
-
-    buffer = xmlBufferCreate();
-    if (buffer == NULL)
-       return NULL;
-    xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
-
-    for ( ; node != NULL; node = node->next) {
-       switch (node->type) {
-       case XML_TEXT_NODE:
-       case XML_CDATA_SECTION_NODE:
-           xmlBufferCat(buffer, node->content);
-           break;
-       case XML_ELEMENT_NODE: {
-           xmlChar *tmp;
-
-	   tmp = xmlTextReaderCollectSiblings(node->children);
-           xmlBufferCat(buffer, tmp);
-	   xmlFree(tmp);
-	   break;
-       }
-       default:
-           break;
-       }
-    }
-    ret = buffer->content;
-    buffer->content = NULL;
-    xmlBufferFree(buffer);
-    return(ret);
-}
-
 /**
  * xmlTextReaderRead:
  * @reader:  the xmlTextReaderPtr used
@@ -1222,19 +1199,17 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
     xmlTextReaderState oldstate = XML_TEXTREADER_START;
     xmlNodePtr oldnode = NULL;
 
-
     if (reader == NULL)
 	return(-1);
+    if (reader->state == XML_TEXTREADER_ERROR)
+        return(-1);
+
     reader->curnode = NULL;
     if (reader->doc != NULL)
         return(xmlTextReaderReadTree(reader));
     if (reader->ctxt == NULL)
 	return(-1);
 
-#ifdef DEBUG_READER
-    fprintf(stderr, "\nREAD ");
-    DUMP_READER
-#endif
     if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
 	reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
 	/*
@@ -1242,11 +1217,11 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
 	 */
 	do {
 	    val = xmlTextReaderPushData(reader);
-		if (val < 0){
-			reader->mode = XML_TEXTREADER_MODE_ERROR;
-			reader->state = XML_TEXTREADER_ERROR;
-		return(-1);
-		}
+            if (val < 0) {
+                reader->mode = XML_TEXTREADER_MODE_ERROR;
+                reader->state = XML_TEXTREADER_ERROR;
+                return(-1);
+            }
 	} while ((reader->ctxt->node == NULL) &&
 		 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
 		  (reader->state != XML_TEXTREADER_DONE)));
@@ -1254,11 +1229,11 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
 	    if (reader->ctxt->myDoc != NULL) {
 		reader->node = reader->ctxt->myDoc->children;
 	    }
-	    if (reader->node == NULL){
-			reader->mode = XML_TEXTREADER_MODE_ERROR;
-			reader->state = XML_TEXTREADER_ERROR;
+	    if (reader->node == NULL) {
+                reader->mode = XML_TEXTREADER_MODE_ERROR;
+                reader->state = XML_TEXTREADER_ERROR;
 		return(-1);
-		}
+	    }
 	    reader->state = XML_TEXTREADER_ELEMENT;
 	} else {
 	    if (reader->ctxt->myDoc != NULL) {
@@ -1278,10 +1253,13 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
 
 get_next_node:
     if (reader->node == NULL) {
-	if (reader->mode == XML_TEXTREADER_MODE_EOF)
+	if (reader->mode == XML_TEXTREADER_MODE_EOF) {
 	    return(0);
-	else
+        } else {
+            reader->mode = XML_TEXTREADER_MODE_ERROR;
+            reader->state = XML_TEXTREADER_ERROR;
 	    return(-1);
+        }
     }
 
     /*
@@ -1303,13 +1281,14 @@ get_next_node:
 	   ((reader->ctxt->node == NULL) ||
 	    (reader->ctxt->node == reader->node) ||
 	    (reader->ctxt->node == reader->node->parent)) &&
-	   (reader->ctxt->instate != XML_PARSER_EOF)) {
+	   (reader->ctxt->instate != XML_PARSER_EOF) &&
+	   (PARSER_STOPPED(reader->ctxt) == 0)) {
 	val = xmlTextReaderPushData(reader);
-	if (val < 0){
-		reader->mode = XML_TEXTREADER_MODE_ERROR;
-		reader->state = XML_TEXTREADER_ERROR;
+	if (val < 0) {
+            reader->mode = XML_TEXTREADER_MODE_ERROR;
+            reader->state = XML_TEXTREADER_ERROR;
 	    return(-1);
-	}
+        }
 	if (reader->node == NULL)
 	    goto node_end;
     }
@@ -1339,7 +1318,8 @@ get_next_node:
 #ifdef LIBXML_REGEXP_ENABLED
 	if ((reader->validate) &&
 	    (reader->node->type == XML_ELEMENT_NODE))
-	    xmlTextReaderValidatePop(reader);
+	    if (xmlTextReaderValidatePop(reader) < 0)
+                return(-1);
 #endif /* LIBXML_REGEXP_ENABLED */
         if ((reader->preserves > 0) &&
 	    (reader->node->extra & NODE_IS_SPRESERVED))
@@ -1376,8 +1356,11 @@ get_next_node:
 	goto node_found;
     }
 #ifdef LIBXML_REGEXP_ENABLED
-    if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
-	xmlTextReaderValidatePop(reader);
+    if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) &&
+        (reader->node->type == XML_ELEMENT_NODE)) {
+        if (xmlTextReaderValidatePop(reader) < 0)
+            return(-1);
+    }
 #endif /* LIBXML_REGEXP_ENABLED */
     if ((reader->preserves > 0) &&
 	(reader->node->extra & NODE_IS_SPRESERVED))
@@ -1389,8 +1372,11 @@ get_next_node:
 	if (reader->mode != XML_TEXTREADER_MODE_EOF) {
 	    val = xmlParseChunk(reader->ctxt, "", 0, 1);
 	    reader->state = XML_TEXTREADER_DONE;
-	    if (val != 0)
+	    if (val != 0) {
+                reader->mode = XML_TEXTREADER_MODE_ERROR;
+                reader->state = XML_TEXTREADER_ERROR;
 	        return(-1);
+            }
 	}
 	reader->node = NULL;
 	reader->depth = -1;
@@ -1426,8 +1412,6 @@ get_next_node:
     reader->state = XML_TEXTREADER_BACKTRACK;
 
 node_found:
-    DUMP_READER
-
     /*
      * If we are in the middle of a piece of CDATA make sure it's finished
      */
@@ -1444,6 +1428,7 @@ node_found:
      * Handle XInclude if asked for
      */
     if ((reader->xinclude) && (reader->in_xinclude == 0) &&
+        (reader->state != XML_TEXTREADER_BACKTRACK) &&
         (reader->node != NULL) &&
 	(reader->node->type == XML_ELEMENT_NODE) &&
 	(reader->node->ns != NULL) &&
@@ -1451,15 +1436,29 @@ node_found:
 	 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
 	if (reader->xincctxt == NULL) {
 	    reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
+            if (reader->xincctxt == NULL) {
+                xmlTextReaderErrMemory(reader);
+                return(-1);
+            }
 	    xmlXIncludeSetFlags(reader->xincctxt,
 	                        reader->parserFlags & (~XML_PARSE_NOXINCNODE));
+            xmlXIncludeSetStreamingMode(reader->xincctxt, 1);
+            if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
+                xmlXIncludeSetErrorHandler(reader->xincctxt,
+                        xmlTextReaderStructuredRelay, reader);
 	}
 	/*
 	 * expand that node and process it
 	 */
 	if (xmlTextReaderExpand(reader) == NULL)
-	    return -1;
-	xmlXIncludeProcessNode(reader->xincctxt, reader->node);
+	    return(-1);
+        if (xmlXIncludeProcessNode(reader->xincctxt, reader->node) < 0) {
+            int err = xmlXIncludeGetLastError(reader->xincctxt);
+
+            if (err == XML_ERR_NO_MEMORY)
+                xmlTextReaderErrMemory(reader);
+            return(-1);
+        }
     }
     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
         reader->in_xinclude++;
@@ -1479,14 +1478,16 @@ node_found:
 	if ((reader->node->children != NULL) &&
 	    (reader->node->children->type == XML_ENTITY_DECL) &&
 	    (reader->node->children->children != NULL)) {
-	    xmlTextReaderEntPush(reader, reader->node);
+	    if (xmlTextReaderEntPush(reader, reader->node) < 0)
+                goto get_next_node;
 	    reader->node = reader->node->children->children;
 	}
 #ifdef LIBXML_REGEXP_ENABLED
     } else if ((reader->node != NULL) &&
 	       (reader->node->type == XML_ENTITY_REF_NODE) &&
 	       (reader->ctxt != NULL) && (reader->validate)) {
-	xmlTextReaderValidateEntity(reader);
+	if (xmlTextReaderValidateEntity(reader) < 0)
+            return(-1);
 #endif /* LIBXML_REGEXP_ENABLED */
     }
     if ((reader->node != NULL) &&
@@ -1503,7 +1504,8 @@ node_found:
 	if ((node->type == XML_ELEMENT_NODE) &&
             ((reader->state != XML_TEXTREADER_END) &&
 	     (reader->state != XML_TEXTREADER_BACKTRACK))) {
-	    xmlTextReaderValidatePush(reader);
+	    if (xmlTextReaderValidatePush(reader) < 0)
+                return(-1);
 	} else if ((node->type == XML_TEXT_NODE) ||
 		   (node->type == XML_CDATA_SECTION_NODE)) {
             xmlTextReaderValidateCData(reader, node->content,
@@ -1609,6 +1611,37 @@ xmlTextReaderNext(xmlTextReaderPtr reader) {
 }
 
 #ifdef LIBXML_WRITER_ENABLED
+static void
+xmlTextReaderDumpCopy(xmlTextReaderPtr reader, xmlOutputBufferPtr output,
+                      xmlNodePtr node) {
+    if ((node->type == XML_DTD_NODE) ||
+        (node->type == XML_ELEMENT_DECL) ||
+        (node->type == XML_ATTRIBUTE_DECL) ||
+        (node->type == XML_ENTITY_DECL))
+        return;
+
+    if ((node->type == XML_DOCUMENT_NODE) ||
+        (node->type == XML_HTML_DOCUMENT_NODE)) {
+        xmlNodeDumpOutput(output, node->doc, node, 0, 0, NULL);
+    } else {
+        xmlNodePtr copy;
+
+        /*
+         * Create a copy to make sure that namespace declarations from
+         * ancestors are added.
+         */
+        copy = xmlDocCopyNode(node, node->doc, 1);
+        if (copy == NULL) {
+            xmlTextReaderErrMemory(reader);
+            return;
+        }
+
+        xmlNodeDumpOutput(output, copy->doc, copy, 0, 0, NULL);
+
+        xmlFreeNode(copy);
+    }
+}
+
 /**
  * xmlTextReaderReadInnerXml:
  * @reader:  the xmlTextReaderPtr used
@@ -1620,47 +1653,36 @@ xmlTextReaderNext(xmlTextReaderPtr reader) {
  *         string must be deallocated by the caller.
  */
 xmlChar *
-xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
+xmlTextReaderReadInnerXml(xmlTextReaderPtr reader)
 {
-    xmlChar *resbuf;
-    xmlNodePtr node, cur_node;
-    xmlBufferPtr buff, buff2;
-    xmlDocPtr doc;
+    xmlOutputBufferPtr output;
+    xmlNodePtr cur;
+    xmlChar *ret;
 
-    if (xmlTextReaderExpand(reader) == NULL) {
-        return NULL;
-    }
-    doc = reader->node->doc;
-    buff = xmlBufferCreate();
-    if (buff == NULL)
-        return NULL;
-    xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT);
-    for (cur_node = reader->node->children; cur_node != NULL;
-         cur_node = cur_node->next) {
-        /* XXX: Why is the node copied? */
-        node = xmlDocCopyNode(cur_node, doc, 1);
-        /* XXX: Why do we need a second buffer? */
-        buff2 = xmlBufferCreate();
-        xmlBufferSetAllocationScheme(buff2, XML_BUFFER_ALLOC_DOUBLEIT);
-        if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
-            xmlFreeNode(node);
-            xmlBufferFree(buff2);
-            xmlBufferFree(buff);
-            return NULL;
-        }
-        xmlBufferCat(buff, buff2->content);
-        xmlFreeNode(node);
-        xmlBufferFree(buff2);
+    if (xmlTextReaderExpand(reader) == NULL)
+        return(NULL);
+
+    if (reader->node == NULL)
+        return(NULL);
+
+    output = xmlAllocOutputBuffer(NULL);
+    if (output == NULL) {
+        xmlTextReaderErrMemory(reader);
+        return(NULL);
     }
-    resbuf = buff->content;
-    buff->content = NULL;
 
-    xmlBufferFree(buff);
-    return resbuf;
+    for (cur = reader->node->children; cur != NULL; cur = cur->next)
+        xmlTextReaderDumpCopy(reader, output, cur);
+
+    if (output->error)
+        xmlCtxtErrIO(reader->ctxt, output->error, NULL);
+
+    ret = xmlBufDetach(output->buffer);
+    xmlOutputBufferClose(output);
+
+    return(ret);
 }
-#endif
 
-#ifdef LIBXML_WRITER_ENABLED
 /**
  * xmlTextReaderReadOuterXml:
  * @reader:  the xmlTextReaderPtr used
@@ -1672,38 +1694,33 @@ xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
  *         by the caller.
  */
 xmlChar *
-xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
+xmlTextReaderReadOuterXml(xmlTextReaderPtr reader)
 {
-    xmlChar *resbuf;
+    xmlOutputBufferPtr output;
     xmlNodePtr node;
-    xmlBufferPtr buff;
-    xmlDocPtr doc;
+    xmlChar *ret;
+
+    if (xmlTextReaderExpand(reader) == NULL)
+        return(NULL);
 
-    if (xmlTextReaderExpand(reader) == NULL) {
-        return NULL;
-    }
     node = reader->node;
-    doc = node->doc;
-    /* XXX: Why is the node copied? */
-	if (node->type == XML_DTD_NODE) {
-		node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
-	} else {
-		node = xmlDocCopyNode(node, doc, 1);
-	}
-    buff = xmlBufferCreate();
-    xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT);
-    if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
-        xmlFreeNode(node);
-        xmlBufferFree(buff);
-        return NULL;
+    if (node == NULL)
+        return(NULL);
+
+    output = xmlAllocOutputBuffer(NULL);
+    if (output == NULL) {
+        xmlTextReaderErrMemory(reader);
+        return(NULL);
     }
 
-    resbuf = buff->content;
-    buff->content = NULL;
+    xmlTextReaderDumpCopy(reader, output, node);
+    if (output->error)
+        xmlCtxtErrIO(reader->ctxt, output->error, NULL);
 
-    xmlFreeNode(node);
-    xmlBufferFree(buff);
-    return resbuf;
+    ret = xmlBufDetach(output->buffer);
+    xmlOutputBufferClose(output);
+
+    return(ret);
 }
 #endif
 
@@ -1720,29 +1737,73 @@ xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
 xmlChar *
 xmlTextReaderReadString(xmlTextReaderPtr reader)
 {
-    xmlNodePtr node;
+    xmlNodePtr node, cur;
+    xmlBufPtr buf;
+    xmlChar *ret;
 
     if ((reader == NULL) || (reader->node == NULL))
        return(NULL);
 
     node = (reader->curnode != NULL) ? reader->curnode : reader->node;
     switch (node->type) {
-    case XML_TEXT_NODE:
-       if (node->content != NULL)
-           return(xmlStrdup(node->content));
-       break;
-    case XML_ELEMENT_NODE:
-	if (xmlTextReaderDoExpand(reader) != -1) {
-	    return xmlTextReaderCollectSiblings(node->children);
-	}
-	break;
-    case XML_ATTRIBUTE_NODE:
-	TODO
-	break;
-    default:
-       break;
+        case XML_TEXT_NODE:
+        case XML_CDATA_SECTION_NODE:
+            break;
+        case XML_ELEMENT_NODE:
+            if (xmlTextReaderDoExpand(reader) == -1)
+                return(NULL);
+            break;
+        case XML_ATTRIBUTE_NODE:
+            /* TODO */
+            break;
+        default:
+            break;
     }
-    return(NULL);
+
+    buf = xmlBufCreateSize(30);
+    if (buf == NULL) {
+        xmlTextReaderErrMemory(reader);
+        return(NULL);
+    }
+    xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
+
+    cur = node;
+    while (cur != NULL) {
+        switch (cur->type) {
+            case XML_TEXT_NODE:
+            case XML_CDATA_SECTION_NODE:
+                xmlBufCat(buf, cur->content);
+                break;
+
+            case XML_ELEMENT_NODE:
+                if (cur->children != NULL) {
+                    cur = cur->children;
+                    continue;
+                }
+                break;
+
+            default:
+                break;
+        }
+
+        if (cur == node)
+            goto done;
+
+        while (cur->next == NULL) {
+            cur = cur->parent;
+            if (cur == node)
+                goto done;
+        }
+        cur = cur->next;
+    }
+
+done:
+    ret = xmlBufDetach(buf);
+    if (ret == NULL)
+        xmlTextReaderErrMemory(reader);
+
+    xmlBufFree(buf);
+    return(ret);
 }
 
 #if 0
@@ -1772,7 +1833,6 @@ xmlTextReaderReadBase64(xmlTextReaderPtr reader,
 
     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
 	return(0);
-    TODO
     return(0);
 }
 
@@ -1802,7 +1862,6 @@ xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
 
     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
 	return(0);
-    TODO
     return(0);
 }
 #endif
@@ -2002,11 +2061,8 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
     if (input == NULL)
 	return(NULL);
     ret = xmlMalloc(sizeof(xmlTextReader));
-    if (ret == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewTextReader : malloc failed\n");
+    if (ret == NULL)
 	return(NULL);
-    }
     memset(ret, 0, sizeof(xmlTextReader));
     ret->doc = NULL;
     ret->entTab = NULL;
@@ -2016,8 +2072,6 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
     ret->buffer = xmlBufCreateSize(100);
     if (ret->buffer == NULL) {
         xmlFree(ret);
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewTextReader : malloc failed\n");
 	return(NULL);
     }
     /* no operation on a reader should require a huge buffer */
@@ -2027,8 +2081,6 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
     if (ret->sax == NULL) {
 	xmlBufFree(ret->buffer);
 	xmlFree(ret);
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewTextReader : malloc failed\n");
 	return(NULL);
     }
     xmlSAXVersion(ret->sax, 2);
@@ -2074,8 +2126,6 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
     }
 
     if (ret->ctxt == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewTextReader : malloc failed\n");
 	xmlBufFree(ret->buffer);
 	xmlFree(ret->sax);
 	xmlFree(ret);
@@ -2089,7 +2139,6 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
     /*
      * use the parser dictionary to allocate all elements and attributes names
      */
-    ret->ctxt->docdict = 1;
     ret->dict = ret->ctxt->dict;
 #ifdef LIBXML_XINCLUDE_ENABLED
     ret->xinclude = 0;
@@ -2113,7 +2162,6 @@ xmlTextReaderPtr
 xmlNewTextReaderFilename(const char *URI) {
     xmlParserInputBufferPtr input;
     xmlTextReaderPtr ret;
-    char *directory = NULL;
 
     input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
     if (input == NULL)
@@ -2124,12 +2172,6 @@ xmlNewTextReaderFilename(const char *URI) {
 	return(NULL);
     }
     ret->allocs |= XML_TEXTREADER_INPUT;
-    if (ret->ctxt->directory == NULL)
-        directory = xmlParserGetDirectory(URI);
-    if ((ret->ctxt->directory == NULL) && (directory != NULL))
-        ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
-    if (directory != NULL)
-	xmlFree(directory);
     return(ret);
 }
 
@@ -2205,6 +2247,7 @@ xmlFreeTextReader(xmlTextReaderPtr reader) {
  *			Methods for XmlTextReader			*
  *									*
  ************************************************************************/
+
 /**
  * xmlTextReaderClose:
  * @reader:  the xmlTextReaderPtr used
@@ -2285,7 +2328,7 @@ xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
 	ns = ns->next;
     }
     if (ns != NULL)
-	return(xmlStrdup(ns->href));
+	return(readerStrdup(reader, ns->href));
 
     cur = reader->node->properties;
     if (cur == NULL)
@@ -2297,8 +2340,11 @@ xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
     }
     /* TODO walk the DTD if present */
 
+    if (cur->children == NULL)
+        return(NULL);
     ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
-    if (ret == NULL) return(xmlStrdup((xmlChar *)""));
+    if (ret == NULL)
+        xmlTextReaderErrMemory(reader);
     return(ret);
 }
 
@@ -2315,9 +2361,10 @@ xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
 xmlChar *
 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
     xmlChar *prefix = NULL;
-    xmlChar *localname;
+    const xmlChar *localname;
     xmlNsPtr ns;
     xmlChar *ret = NULL;
+    int result;
 
     if ((reader == NULL) || (name == NULL))
 	return(NULL);
@@ -2330,43 +2377,56 @@ xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
     if (reader->node->type != XML_ELEMENT_NODE)
 	return(NULL);
 
-    localname = xmlSplitQName2(name, &prefix);
+    localname = xmlSplitQName4(name, &prefix);
     if (localname == NULL) {
-		/*
-		 * Namespace default decl
-		 */
-		if (xmlStrEqual(name, BAD_CAST "xmlns")) {
-			ns = reader->node->nsDef;
-			while (ns != NULL) {
-				if (ns->prefix == NULL) {
-					return(xmlStrdup(ns->href));
-				}
-				ns = ns->next;
-			}
-			return NULL;
-		}
-		return(xmlGetNoNsProp(reader->node, name));
-	}
+        xmlTextReaderErrMemory(reader);
+        return(NULL);
+    }
+    if (prefix == NULL) {
+        /*
+         * Namespace default decl
+         */
+        if (xmlStrEqual(name, BAD_CAST "xmlns")) {
+            ns = reader->node->nsDef;
+            while (ns != NULL) {
+                if (ns->prefix == NULL) {
+                    return(readerStrdup(reader, ns->href));
+                }
+                ns = ns->next;
+            }
+            return NULL;
+        }
+
+        result = xmlNodeGetAttrValue(reader->node, name, NULL, &ret);
+        if (result < 0)
+            xmlTextReaderErrMemory(reader);
+        return(ret);
+    }
 
     /*
      * Namespace default decl
      */
     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
-		ns = reader->node->nsDef;
-		while (ns != NULL) {
-			if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
-				ret = xmlStrdup(ns->href);
-				break;
-			}
-			ns = ns->next;
-		}
+        ns = reader->node->nsDef;
+        while (ns != NULL) {
+            if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
+                ret = readerStrdup(reader, ns->href);
+                break;
+            }
+            ns = ns->next;
+        }
     } else {
-		ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
-		if (ns != NULL)
-			ret = xmlGetNsProp(reader->node, localname, ns->href);
-	}
+        result = xmlSearchNsSafe(reader->node, prefix, &ns);
+        if (result < 0)
+            xmlTextReaderErrMemory(reader);
+        if (ns != NULL) {
+            result = xmlNodeGetAttrValue(reader->node, localname, ns->href,
+                                         &ret);
+            if (result < 0)
+                xmlTextReaderErrMemory(reader);
+        }
+    }
 
-    xmlFree(localname);
     if (prefix != NULL)
         xmlFree(prefix);
     return(ret);
@@ -2387,8 +2447,10 @@ xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
 xmlChar *
 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
 			    const xmlChar *namespaceURI) {
+    xmlChar *ret = NULL;
     xmlChar *prefix = NULL;
     xmlNsPtr ns;
+    int result;
 
     if ((reader == NULL) || (localName == NULL))
 	return(NULL);
@@ -2402,21 +2464,25 @@ xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
 	return(NULL);
 
     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
-		if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
-			prefix = BAD_CAST localName;
-		}
-		ns = reader->node->nsDef;
-		while (ns != NULL) {
-			if ((prefix == NULL && ns->prefix == NULL) ||
-				((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
-				return xmlStrdup(ns->href);
-			}
-			ns = ns->next;
-		}
-		return NULL;
+        if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
+            prefix = BAD_CAST localName;
+        }
+        ns = reader->node->nsDef;
+        while (ns != NULL) {
+            if ((prefix == NULL && ns->prefix == NULL) ||
+                ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
+                return readerStrdup(reader, ns->href);
+            }
+            ns = ns->next;
+        }
+        return NULL;
     }
 
-    return(xmlGetNsProp(reader->node, localName, namespaceURI));
+    result = xmlNodeGetAttrValue(reader->node, localName, namespaceURI, &ret);
+    if (result < 0)
+        xmlTextReaderErrMemory(reader);
+
+    return(ret);
 }
 
 /**
@@ -2465,7 +2531,6 @@ xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
 	 *   - by the layer which allocated it.
 	 *   - by the layer to which would have been returned to.
 	 */
-	TODO
 	return(NULL);
     }
     return(ret);
@@ -2485,16 +2550,21 @@ xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
 xmlChar *
 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
     xmlNsPtr ns;
+    int result;
 
     if (reader == NULL)
 	return(NULL);
     if (reader->node == NULL)
 	return(NULL);
 
-    ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
+    result = xmlSearchNsSafe(reader->node, prefix, &ns);
+    if (result < 0) {
+        xmlTextReaderErrMemory(reader);
+        return(NULL);
+    }
     if (ns == NULL)
 	return(NULL);
-    return(xmlStrdup(ns->href));
+    return(readerStrdup(reader, ns->href));
 }
 
 /**
@@ -2560,7 +2630,7 @@ xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
 int
 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
     xmlChar *prefix = NULL;
-    xmlChar *localname;
+    const xmlChar *localname;
     xmlNsPtr ns;
     xmlAttrPtr prop;
 
@@ -2573,8 +2643,12 @@ xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
     if (reader->node->type != XML_ELEMENT_NODE)
 	return(0);
 
-    localname = xmlSplitQName2(name, &prefix);
+    localname = xmlSplitQName4(name, &prefix);
     if (localname == NULL) {
+        xmlTextReaderErrMemory(reader);
+        return(-1);
+    }
+    if (prefix == NULL) {
 	/*
 	 * Namespace default decl
 	 */
@@ -2636,15 +2710,11 @@ xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
 	prop = prop->next;
     }
 not_found:
-    if (localname != NULL)
-        xmlFree(localname);
     if (prefix != NULL)
         xmlFree(prefix);
     return(0);
 
 found:
-    if (localname != NULL)
-        xmlFree(localname);
     if (prefix != NULL)
         xmlFree(prefix);
     return(1);
@@ -2831,12 +2901,24 @@ xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
 	if (reader->faketext == NULL) {
 	    reader->faketext = xmlNewDocText(reader->node->doc,
 		                             ns->href);
+            if (reader->faketext == NULL) {
+                xmlTextReaderErrMemory(reader);
+                return(-1);
+            }
 	} else {
             if ((reader->faketext->content != NULL) &&
 	        (reader->faketext->content !=
 		 (xmlChar *) &(reader->faketext->properties)))
 		xmlFree(reader->faketext->content);
-	    reader->faketext->content = xmlStrdup(ns->href);
+            if (ns->href == NULL) {
+                reader->faketext->content = NULL;
+            } else {
+                reader->faketext->content = xmlStrdup(ns->href);
+                if (reader->faketext->content == NULL) {
+                    xmlTextReaderErrMemory(reader);
+                    return(-1);
+                }
+            }
 	}
 	reader->curnode = reader->faketext;
     } else {
@@ -2858,20 +2940,17 @@ xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
  */
 const xmlChar *
 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
-    xmlDocPtr doc = NULL;
+    const xmlChar *encoding = NULL;
+
     if (reader == NULL)
-	return(NULL);
-    if (reader->doc != NULL)
-        doc = reader->doc;
-    else if (reader->ctxt != NULL)
-	doc = reader->ctxt->myDoc;
-    if (doc == NULL)
-	return(NULL);
+        return(NULL);
 
-    if (doc->encoding == NULL)
-	return(NULL);
-    else
-      return(CONSTSTR(doc->encoding));
+    if (reader->ctxt != NULL)
+        encoding = xmlGetActualEncoding(reader->ctxt);
+    else if (reader->doc != NULL)
+        encoding = reader->doc->encoding;
+
+    return(constString(reader, encoding));
 }
 
 
@@ -3045,14 +3124,14 @@ xmlTextReaderLocalName(xmlTextReaderPtr reader) {
     if (node->type == XML_NAMESPACE_DECL) {
 	xmlNsPtr ns = (xmlNsPtr) node;
 	if (ns->prefix == NULL)
-	    return(xmlStrdup(BAD_CAST "xmlns"));
+	    return(readerStrdup(reader, BAD_CAST "xmlns"));
 	else
-	    return(xmlStrdup(ns->prefix));
+	    return(readerStrdup(reader, ns->prefix));
     }
     if ((node->type != XML_ELEMENT_NODE) &&
 	(node->type != XML_ATTRIBUTE_NODE))
 	return(xmlTextReaderName(reader));
-    return(xmlStrdup(node->name));
+    return(readerStrdup(reader, node->name));
 }
 
 /**
@@ -3076,7 +3155,7 @@ xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
     if (node->type == XML_NAMESPACE_DECL) {
 	xmlNsPtr ns = (xmlNsPtr) node;
 	if (ns->prefix == NULL)
-	    return(CONSTSTR(BAD_CAST "xmlns"));
+	    return(constString(reader, BAD_CAST "xmlns"));
 	else
 	    return(ns->prefix);
     }
@@ -3111,41 +3190,41 @@ xmlTextReaderName(xmlTextReaderPtr reader) {
         case XML_ATTRIBUTE_NODE:
 	    if ((node->ns == NULL) ||
 		(node->ns->prefix == NULL))
-		return(xmlStrdup(node->name));
+		return(readerStrdup(reader, node->name));
 
-	    ret = xmlStrdup(node->ns->prefix);
-	    ret = xmlStrcat(ret, BAD_CAST ":");
-	    ret = xmlStrcat(ret, node->name);
+            ret = xmlBuildQName(node->name, node->ns->prefix, NULL, 0);
+            if (ret == NULL)
+                xmlTextReaderErrMemory(reader);
 	    return(ret);
         case XML_TEXT_NODE:
-	    return(xmlStrdup(BAD_CAST "#text"));
+	    return(readerStrdup(reader, BAD_CAST "#text"));
         case XML_CDATA_SECTION_NODE:
-	    return(xmlStrdup(BAD_CAST "#cdata-section"));
+	    return(readerStrdup(reader, BAD_CAST "#cdata-section"));
         case XML_ENTITY_NODE:
         case XML_ENTITY_REF_NODE:
-	    return(xmlStrdup(node->name));
+	    return(readerStrdup(reader, node->name));
         case XML_PI_NODE:
-	    return(xmlStrdup(node->name));
+	    return(readerStrdup(reader, node->name));
         case XML_COMMENT_NODE:
-	    return(xmlStrdup(BAD_CAST "#comment"));
+	    return(readerStrdup(reader, BAD_CAST "#comment"));
         case XML_DOCUMENT_NODE:
         case XML_HTML_DOCUMENT_NODE:
-	    return(xmlStrdup(BAD_CAST "#document"));
+	    return(readerStrdup(reader, BAD_CAST "#document"));
         case XML_DOCUMENT_FRAG_NODE:
-	    return(xmlStrdup(BAD_CAST "#document-fragment"));
+	    return(readerStrdup(reader, BAD_CAST "#document-fragment"));
         case XML_NOTATION_NODE:
-	    return(xmlStrdup(node->name));
+	    return(readerStrdup(reader, node->name));
         case XML_DOCUMENT_TYPE_NODE:
         case XML_DTD_NODE:
-	    return(xmlStrdup(node->name));
+	    return(readerStrdup(reader, node->name));
         case XML_NAMESPACE_DECL: {
 	    xmlNsPtr ns = (xmlNsPtr) node;
 
-	    ret = xmlStrdup(BAD_CAST "xmlns");
 	    if (ns->prefix == NULL)
-		return(ret);
-	    ret = xmlStrcat(ret, BAD_CAST ":");
-	    ret = xmlStrcat(ret, ns->prefix);
+		return(readerStrdup(reader, BAD_CAST "xmlns"));
+            ret = xmlBuildQName(ns->prefix, BAD_CAST "xmlns", NULL, 0);
+            if (ret == NULL)
+                xmlTextReaderErrMemory(reader);
 	    return(ret);
 	}
 
@@ -3184,34 +3263,34 @@ xmlTextReaderConstName(xmlTextReaderPtr reader) {
 	    if ((node->ns == NULL) ||
 		(node->ns->prefix == NULL))
 		return(node->name);
-	    return(CONSTQSTR(node->ns->prefix, node->name));
+	    return(constQString(reader, node->ns->prefix, node->name));
         case XML_TEXT_NODE:
-	    return(CONSTSTR(BAD_CAST "#text"));
+	    return(constString(reader, BAD_CAST "#text"));
         case XML_CDATA_SECTION_NODE:
-	    return(CONSTSTR(BAD_CAST "#cdata-section"));
+	    return(constString(reader, BAD_CAST "#cdata-section"));
         case XML_ENTITY_NODE:
         case XML_ENTITY_REF_NODE:
-	    return(CONSTSTR(node->name));
+	    return(constString(reader, node->name));
         case XML_PI_NODE:
-	    return(CONSTSTR(node->name));
+	    return(constString(reader, node->name));
         case XML_COMMENT_NODE:
-	    return(CONSTSTR(BAD_CAST "#comment"));
+	    return(constString(reader, BAD_CAST "#comment"));
         case XML_DOCUMENT_NODE:
         case XML_HTML_DOCUMENT_NODE:
-	    return(CONSTSTR(BAD_CAST "#document"));
+	    return(constString(reader, BAD_CAST "#document"));
         case XML_DOCUMENT_FRAG_NODE:
-	    return(CONSTSTR(BAD_CAST "#document-fragment"));
+	    return(constString(reader, BAD_CAST "#document-fragment"));
         case XML_NOTATION_NODE:
-	    return(CONSTSTR(node->name));
+	    return(constString(reader, node->name));
         case XML_DOCUMENT_TYPE_NODE:
         case XML_DTD_NODE:
-	    return(CONSTSTR(node->name));
+	    return(constString(reader, node->name));
         case XML_NAMESPACE_DECL: {
 	    xmlNsPtr ns = (xmlNsPtr) node;
 
 	    if (ns->prefix == NULL)
-		return(CONSTSTR(BAD_CAST "xmlns"));
-	    return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
+		return(constString(reader, BAD_CAST "xmlns"));
+	    return(constQString(reader, BAD_CAST "xmlns", ns->prefix));
 	}
 
         case XML_ELEMENT_DECL:
@@ -3246,13 +3325,13 @@ xmlTextReaderPrefix(xmlTextReaderPtr reader) {
 	xmlNsPtr ns = (xmlNsPtr) node;
 	if (ns->prefix == NULL)
 	    return(NULL);
-	return(xmlStrdup(BAD_CAST "xmlns"));
+	return(readerStrdup(reader, BAD_CAST "xmlns"));
     }
     if ((node->type != XML_ELEMENT_NODE) &&
 	(node->type != XML_ATTRIBUTE_NODE))
 	return(NULL);
     if ((node->ns != NULL) && (node->ns->prefix != NULL))
-	return(xmlStrdup(node->ns->prefix));
+	return(readerStrdup(reader, node->ns->prefix));
     return(NULL);
 }
 
@@ -3278,13 +3357,13 @@ xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
 	xmlNsPtr ns = (xmlNsPtr) node;
 	if (ns->prefix == NULL)
 	    return(NULL);
-	return(CONSTSTR(BAD_CAST "xmlns"));
+	return(constString(reader, BAD_CAST "xmlns"));
     }
     if ((node->type != XML_ELEMENT_NODE) &&
 	(node->type != XML_ATTRIBUTE_NODE))
 	return(NULL);
     if ((node->ns != NULL) && (node->ns->prefix != NULL))
-	return(CONSTSTR(node->ns->prefix));
+	return(constString(reader, node->ns->prefix));
     return(NULL);
 }
 
@@ -3307,12 +3386,12 @@ xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
     else
 	node = reader->node;
     if (node->type == XML_NAMESPACE_DECL)
-	return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
+	return(readerStrdup(reader, BAD_CAST "http://www.w3.org/2000/xmlns/"));
     if ((node->type != XML_ELEMENT_NODE) &&
 	(node->type != XML_ATTRIBUTE_NODE))
 	return(NULL);
     if (node->ns != NULL)
-	return(xmlStrdup(node->ns->href));
+	return(readerStrdup(reader, node->ns->href));
     return(NULL);
 }
 
@@ -3335,12 +3414,12 @@ xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
     else
 	node = reader->node;
     if (node->type == XML_NAMESPACE_DECL)
-	return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
+	return(constString(reader, BAD_CAST "http://www.w3.org/2000/xmlns/"));
     if ((node->type != XML_ELEMENT_NODE) &&
 	(node->type != XML_ATTRIBUTE_NODE))
 	return(NULL);
     if (node->ns != NULL)
-	return(CONSTSTR(node->ns->href));
+	return(constString(reader, node->ns->href));
     return(NULL);
 }
 
@@ -3355,9 +3434,16 @@ xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
  */
 xmlChar *
 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
+    xmlChar *ret = NULL;
+    int result;
+
     if ((reader == NULL) || (reader->node == NULL))
 	return(NULL);
-    return(xmlNodeGetBase(NULL, reader->node));
+    result = xmlNodeGetBaseSafe(NULL, reader->node, &ret);
+    if (result < 0)
+        xmlTextReaderErrMemory(reader);
+
+    return(ret);
 }
 
 /**
@@ -3373,13 +3459,16 @@ const xmlChar *
 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
     xmlChar *tmp;
     const xmlChar *ret;
+    int result;
 
     if ((reader == NULL) || (reader->node == NULL))
 	return(NULL);
-    tmp = xmlNodeGetBase(NULL, reader->node);
+    result = xmlNodeGetBaseSafe(NULL, reader->node, &tmp);
+    if (result < 0)
+        xmlTextReaderErrMemory(reader);
     if (tmp == NULL)
         return(NULL);
-    ret = CONSTSTR(tmp);
+    ret = constString(reader, tmp);
     xmlFree(tmp);
     return(ret);
 }
@@ -3492,23 +3581,26 @@ xmlTextReaderValue(xmlTextReaderPtr reader) {
 
     switch (node->type) {
         case XML_NAMESPACE_DECL:
-	    return(xmlStrdup(((xmlNsPtr) node)->href));
+	    return(readerStrdup(reader, ((xmlNsPtr) node)->href));
         case XML_ATTRIBUTE_NODE:{
 	    xmlAttrPtr attr = (xmlAttrPtr) node;
+            xmlDocPtr doc = NULL;
+            xmlChar *ret;
 
+            if (attr->children == NULL)
+                return(NULL);
 	    if (attr->parent != NULL)
-		return (xmlNodeListGetString
-			(attr->parent->doc, attr->children, 1));
-	    else
-		return (xmlNodeListGetString(NULL, attr->children, 1));
-	    break;
+                doc = attr->parent->doc;
+	    ret = xmlNodeListGetString(doc, attr->children, 1);
+            if (ret == NULL)
+                xmlTextReaderErrMemory(reader);
+	    return(ret);
 	}
         case XML_TEXT_NODE:
         case XML_CDATA_SECTION_NODE:
         case XML_PI_NODE:
         case XML_COMMENT_NODE:
-            if (node->content != NULL)
-                return (xmlStrdup(node->content));
+            return(readerStrdup(reader, node->content));
 	default:
 	    break;
     }
@@ -3550,11 +3642,8 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) {
 	    else {
 		if (reader->buffer == NULL) {
 		    reader->buffer = xmlBufCreateSize(100);
-                    if (reader->buffer == NULL) {
-                        xmlGenericError(xmlGenericErrorContext,
-                                        "xmlTextReaderSetup : malloc failed\n");
+                    if (reader->buffer == NULL)
                         return (NULL);
-                    }
 		    xmlBufSetAllocationScheme(reader->buffer,
 		                              XML_BUFFER_ALLOC_DOUBLEIT);
                 } else
@@ -3562,12 +3651,12 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) {
 	        xmlBufGetNodeContent(reader->buffer, node);
 		ret = xmlBufContent(reader->buffer);
 		if (ret == NULL) {
+                    xmlTextReaderErrMemory(reader);
 		    /* error on the buffer best to reallocate */
 		    xmlBufFree(reader->buffer);
 		    reader->buffer = xmlBufCreateSize(100);
 		    xmlBufSetAllocationScheme(reader->buffer,
 		                              XML_BUFFER_ALLOC_DOUBLEIT);
-		    ret = BAD_CAST "";
 		}
 		return(ret);
 	    }
@@ -3613,7 +3702,7 @@ xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
     if (reader == NULL)
 	return(-1);
     /* TODO maybe lookup the attribute value for " first */
-    return((int) '"');
+    return('"');
 }
 
 /**
@@ -3654,7 +3743,7 @@ xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
     tmp = xmlNodeGetLang(reader->node);
     if (tmp == NULL)
         return(NULL);
-    ret = CONSTSTR(tmp);
+    ret = constString(reader, tmp);
     xmlFree(tmp);
     return(ret);
 }
@@ -3674,7 +3763,7 @@ const xmlChar *
 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
     if (reader == NULL)
 	return(NULL);
-    return(CONSTSTR(str));
+    return(constString(reader, str));
 }
 
 /**
@@ -3729,18 +3818,21 @@ xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
 		if (ctxt->loadsubset == 0) {
 		    if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
 			return(-1);
-		    ctxt->loadsubset = XML_DETECT_IDS;
+                    ctxt->options |= XML_PARSE_DTDLOAD;
+		    ctxt->loadsubset |= XML_DETECT_IDS;
 		}
 	    } else {
-		ctxt->loadsubset = 0;
+                ctxt->options &= ~XML_PARSE_DTDLOAD;
+		ctxt->loadsubset &= ~XML_DETECT_IDS;
 	    }
 	    return(0);
         case XML_PARSER_DEFAULTATTRS:
 	    if (value != 0) {
+                ctxt->options |= XML_PARSE_DTDATTR;
 		ctxt->loadsubset |= XML_COMPLETE_ATTRS;
 	    } else {
-		if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
-		    ctxt->loadsubset -= XML_COMPLETE_ATTRS;
+                ctxt->options &= ~XML_PARSE_DTDATTR;
+		ctxt->loadsubset &= ~XML_COMPLETE_ATTRS;
 	    }
 	    return(0);
         case XML_PARSER_VALIDATE:
@@ -3875,10 +3967,7 @@ xmlTextReaderPreserve(xmlTextReaderPtr reader) {
     if (reader == NULL)
 	return(NULL);
 
-    if (reader->curnode != NULL)
-        cur = reader->curnode;
-    else
-        cur = reader->node;
+    cur = reader->node;
     if (cur == NULL)
         return(NULL);
 
@@ -3928,7 +4017,7 @@ xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
 	reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
 					      sizeof(reader->patternTab[0]));
         if (reader->patternTab == NULL) {
-            xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
+            xmlTextReaderErrMemory(reader);
             return (-1);
         }
     }
@@ -3939,7 +4028,7 @@ xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
                                       reader->patternMax *
                                       sizeof(reader->patternTab[0]));
         if (tmp == NULL) {
-            xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
+            xmlTextReaderErrMemory(reader);
 	    reader->patternMax /= 2;
             return (-1);
         }
@@ -3976,80 +4065,6 @@ xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
 }
 
 #ifdef LIBXML_SCHEMAS_ENABLED
-static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
-
-static void XMLCDECL
-xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
-
-static void XMLCDECL
-xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
-
-static void XMLCDECL
-xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
-
-static void XMLCDECL
-xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
-
-static void XMLCDECL
-xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
-{
-    xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
-
-    char *str;
-
-    va_list ap;
-
-    va_start(ap, msg);
-    str = xmlTextReaderBuildMessage(msg, ap);
-    if (!reader->errorFunc) {
-        xmlTextReaderValidityError(ctx, "%s", str);
-    } else {
-        reader->errorFunc(reader->errorFuncArg, str,
-                          XML_PARSER_SEVERITY_VALIDITY_ERROR,
-                          NULL /* locator */ );
-    }
-    if (str != NULL)
-        xmlFree(str);
-    va_end(ap);
-}
-
-static void XMLCDECL
-xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
-{
-    xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
-
-    char *str;
-
-    va_list ap;
-
-    va_start(ap, msg);
-    str = xmlTextReaderBuildMessage(msg, ap);
-    if (!reader->errorFunc) {
-        xmlTextReaderValidityWarning(ctx, "%s", str);
-    } else {
-        reader->errorFunc(reader->errorFuncArg, str,
-                          XML_PARSER_SEVERITY_VALIDITY_WARNING,
-                          NULL /* locator */ );
-    }
-    if (str != NULL)
-        xmlFree(str);
-    va_end(ap);
-}
-
-static void
-  xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
-
-static void
-xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
-{
-    xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
-
-    if (reader->sErrorFunc) {
-        reader->sErrorFunc(reader->errorFuncArg, error);
-    } else {
-        xmlTextReaderStructuredError(reader, error);
-    }
-}
 /**
  * xmlTextReaderRelaxNGSetSchema:
  * @reader:  the xmlTextReaderPtr used
@@ -4096,17 +4111,9 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
     if (reader->rngValidCtxt == NULL)
         return(-1);
-    if (reader->errorFunc != NULL) {
-	xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
-			xmlTextReaderValidityErrorRelay,
-			xmlTextReaderValidityWarningRelay,
-			reader);
-    }
-	if (reader->sErrorFunc != NULL) {
-		xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
-			xmlTextReaderValidityStructuredRelay,
-			reader);
-    }
+    if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
+	xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
+			xmlTextReaderStructuredRelay, reader);
     reader->rngValidErrors = 0;
     reader->rngFullNode = NULL;
     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
@@ -4238,17 +4245,9 @@ xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
                                 xmlTextReaderLocator,
 				(void *) reader);
 
-    if (reader->errorFunc != NULL) {
-	xmlSchemaSetValidErrors(reader->xsdValidCtxt,
-			xmlTextReaderValidityErrorRelay,
-			xmlTextReaderValidityWarningRelay,
-			reader);
-    }
-	if (reader->sErrorFunc != NULL) {
-		xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
-			xmlTextReaderValidityStructuredRelay,
-			reader);
-    }
+    if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
+	xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
+			xmlTextReaderStructuredRelay, reader);
     reader->xsdValidErrors = 0;
     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
     return(0);
@@ -4308,21 +4307,14 @@ xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
 	/* Parse the schema and create validation environment. */
 
 	pctxt = xmlRelaxNGNewParserCtxt(rng);
-	if (reader->errorFunc != NULL) {
-	    xmlRelaxNGSetParserErrors(pctxt,
-		xmlTextReaderValidityErrorRelay,
-		xmlTextReaderValidityWarningRelay,
-		reader);
-	}
-	if (reader->sErrorFunc != NULL) {
-	    xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
-		xmlTextReaderValidityStructuredRelay,
-		reader);
-	}
+	if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
+	    xmlRelaxNGSetParserStructuredErrors(pctxt,
+                    xmlTextReaderStructuredRelay, reader);
 	reader->rngSchemas = xmlRelaxNGParse(pctxt);
 	xmlRelaxNGFreeParserCtxt(pctxt);
 	if (reader->rngSchemas == NULL)
 	    return(-1);
+
 	reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
 	if (reader->rngValidCtxt == NULL) {
 	    xmlRelaxNGFree(reader->rngSchemas);
@@ -4340,17 +4332,9 @@ xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
     * TODO: In case the user provides the validation context we
     *	could make this redirection optional.
     */
-    if (reader->errorFunc != NULL) {
-	xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
-			 xmlTextReaderValidityErrorRelay,
-			 xmlTextReaderValidityWarningRelay,
-			 reader);
-    }
-	if (reader->sErrorFunc != NULL) {
-		xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
-			xmlTextReaderValidityStructuredRelay,
-			reader);
-    }
+    if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
+        xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
+                xmlTextReaderStructuredRelay, reader);
     reader->rngValidErrors = 0;
     reader->rngFullNode = NULL;
     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
@@ -4413,12 +4397,9 @@ xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
 	xmlSchemaParserCtxtPtr pctxt;
 	/* Parse the schema and create validation environment. */
 	pctxt = xmlSchemaNewParserCtxt(xsd);
-	if (reader->errorFunc != NULL) {
-	    xmlSchemaSetParserErrors(pctxt,
-		xmlTextReaderValidityErrorRelay,
-		xmlTextReaderValidityWarningRelay,
-		reader);
-	}
+	if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
+	    xmlSchemaSetParserStructuredErrors(pctxt,
+                    xmlTextReaderStructuredRelay, reader);
 	reader->xsdSchemas = xmlSchemaParse(pctxt);
 	xmlSchemaFreeParserCtxt(pctxt);
 	if (reader->xsdSchemas == NULL)
@@ -4461,17 +4442,9 @@ xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
     * TODO: In case the user provides the validation context we
     *   could make this redirection optional.
     */
-    if (reader->errorFunc != NULL) {
-	xmlSchemaSetValidErrors(reader->xsdValidCtxt,
-			 xmlTextReaderValidityErrorRelay,
-			 xmlTextReaderValidityWarningRelay,
-			 reader);
-    }
-	if (reader->sErrorFunc != NULL) {
-		xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
-			xmlTextReaderValidityStructuredRelay,
-			reader);
-    }
+    if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
+	xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
+			xmlTextReaderStructuredRelay, reader);
     reader->xsdValidErrors = 0;
     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
     return(0);
@@ -4610,7 +4583,7 @@ xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
     if (doc->version == NULL)
 	return(NULL);
     else
-      return(CONSTSTR(doc->version));
+      return(constString(reader, doc->version));
 }
 
 /**
@@ -4644,43 +4617,6 @@ xmlTextReaderStandalone(xmlTextReaderPtr reader) {
  *									*
  ************************************************************************/
 
-/* helper to build a xmlMalloc'ed string from a format and va_list */
-static char *
-xmlTextReaderBuildMessage(const char *msg, va_list ap) {
-    int size = 0;
-    int chars;
-    char *larger;
-    char *str = NULL;
-    va_list aq;
-
-    while (1) {
-        VA_COPY(aq, ap);
-        chars = vsnprintf(str, size, msg, aq);
-        va_end(aq);
-        if (chars < 0) {
-	    xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
-	    if (str)
-		xmlFree(str);
-	    return NULL;
-	}
-	if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
-            break;
-        if (chars < MAX_ERR_MSG_SIZE)
-	size = chars + 1;
-	else
-		size = MAX_ERR_MSG_SIZE;
-        if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
-	    xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
-	    if (str)
-                xmlFree(str);
-            return NULL;
-        }
-        str = larger;
-    }
-
-    return str;
-}
-
 /**
  * xmlTextReaderLocatorLineNumber:
  * @locator: the xmlTextReaderLocatorPtr used
@@ -4754,105 +4690,14 @@ xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
     return ret;
 }
 
-static void
-xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
-                          char *str)
-{
-    xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
-
-    xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
-
-    if (str != NULL) {
-        if (reader->errorFunc)
-            reader->errorFunc(reader->errorFuncArg, str, severity,
-                              (xmlTextReaderLocatorPtr) ctx);
-        xmlFree(str);
-    }
-}
-
-static void
-xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
-{
-    xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
-
-    xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
-
-    if (error && reader->sErrorFunc) {
-        reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
-    }
-}
-
-static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
-xmlTextReaderError(void *ctxt, const char *msg, ...)
-{
-    va_list ap;
-
-    va_start(ap, msg);
-    xmlTextReaderGenericError(ctxt,
-                              XML_PARSER_SEVERITY_ERROR,
-                              xmlTextReaderBuildMessage(msg, ap));
-    va_end(ap);
-
-}
-
-static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
-xmlTextReaderWarning(void *ctxt, const char *msg, ...)
-{
-    va_list ap;
-
-    va_start(ap, msg);
-    xmlTextReaderGenericError(ctxt,
-                              XML_PARSER_SEVERITY_WARNING,
-                              xmlTextReaderBuildMessage(msg, ap));
-    va_end(ap);
-}
-
-static void XMLCDECL
-xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
-{
-    va_list ap;
-
-    int len = xmlStrlen((const xmlChar *) msg);
-
-    if ((len > 1) && (msg[len - 2] != ':')) {
-        /*
-         * some callbacks only report locator information:
-         * skip them (mimicking behaviour in error.c)
-         */
-        va_start(ap, msg);
-        xmlTextReaderGenericError(ctxt,
-                                  XML_PARSER_SEVERITY_VALIDITY_ERROR,
-                                  xmlTextReaderBuildMessage(msg, ap));
-        va_end(ap);
-    }
-}
-
-static void XMLCDECL
-xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
-{
-    va_list ap;
-
-    int len = xmlStrlen((const xmlChar *) msg);
-
-    if ((len != 0) && (msg[len - 1] != ':')) {
-        /*
-         * some callbacks only report locator information:
-         * skip them (mimicking behaviour in error.c)
-         */
-        va_start(ap, msg);
-        xmlTextReaderGenericError(ctxt,
-                                  XML_PARSER_SEVERITY_VALIDITY_WARNING,
-                                  xmlTextReaderBuildMessage(msg, ap));
-        va_end(ap);
-    }
-}
-
 /**
  * xmlTextReaderSetErrorHandler:
  * @reader:  the xmlTextReaderPtr used
  * @f:	the callback function to call on error and warnings
  * @arg:    a user argument to pass to the callback function
  *
+ * DEPRECATED: Use xmlTextReaderSetStructuredErrorHandler.
+ *
  * Register a callback function that will be called on error and warnings.
  *
  * If @f is NULL, the default error and warning handlers are restored.
@@ -4862,53 +4707,35 @@ xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
                              xmlTextReaderErrorFunc f, void *arg)
 {
     if (f != NULL) {
-        reader->ctxt->sax->error = xmlTextReaderError;
-        reader->ctxt->sax->serror = NULL;
-        reader->ctxt->vctxt.error = xmlTextReaderValidityError;
-        reader->ctxt->sax->warning = xmlTextReaderWarning;
-        reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
         reader->errorFunc = f;
         reader->sErrorFunc = NULL;
         reader->errorFuncArg = arg;
+        xmlCtxtSetErrorHandler(reader->ctxt,
+                xmlTextReaderStructuredRelay, reader);
 #ifdef LIBXML_SCHEMAS_ENABLED
         if (reader->rngValidCtxt) {
-            xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
-                                     xmlTextReaderValidityErrorRelay,
-                                     xmlTextReaderValidityWarningRelay,
-                                     reader);
-            xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
-                                               reader);
+            xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
+                    xmlTextReaderStructuredRelay, reader);
         }
         if (reader->xsdValidCtxt) {
-            xmlSchemaSetValidErrors(reader->xsdValidCtxt,
-                                    xmlTextReaderValidityErrorRelay,
-                                    xmlTextReaderValidityWarningRelay,
-                                    reader);
-            xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
-                                              reader);
+            xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
+                    xmlTextReaderStructuredRelay, reader);
         }
 #endif
     } else {
         /* restore defaults */
-        reader->ctxt->sax->error = xmlParserError;
-        reader->ctxt->vctxt.error = xmlParserValidityError;
-        reader->ctxt->sax->warning = xmlParserWarning;
-        reader->ctxt->vctxt.warning = xmlParserValidityWarning;
         reader->errorFunc = NULL;
         reader->sErrorFunc = NULL;
         reader->errorFuncArg = NULL;
+        xmlCtxtSetErrorHandler(reader->ctxt, NULL, NULL);
 #ifdef LIBXML_SCHEMAS_ENABLED
         if (reader->rngValidCtxt) {
-            xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
-                                     reader);
             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
-                                               reader);
+                                               NULL);
         }
         if (reader->xsdValidCtxt) {
-            xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
-                                    reader);
             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
-                                              reader);
+                                              NULL);
         }
 #endif
     }
@@ -4929,52 +4756,35 @@ xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
                                        xmlStructuredErrorFunc f, void *arg)
 {
     if (f != NULL) {
-        reader->ctxt->sax->error = NULL;
-        reader->ctxt->sax->serror = xmlTextReaderStructuredError;
-        reader->ctxt->vctxt.error = xmlTextReaderValidityError;
-        reader->ctxt->sax->warning = xmlTextReaderWarning;
-        reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
         reader->sErrorFunc = f;
         reader->errorFunc = NULL;
         reader->errorFuncArg = arg;
+        xmlCtxtSetErrorHandler(reader->ctxt,
+                xmlTextReaderStructuredRelay, reader);
 #ifdef LIBXML_SCHEMAS_ENABLED
         if (reader->rngValidCtxt) {
-            xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
-                                     reader);
             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
-                                        xmlTextReaderValidityStructuredRelay,
-                                               reader);
+                    xmlTextReaderStructuredRelay, reader);
         }
         if (reader->xsdValidCtxt) {
-            xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
-                                    reader);
             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
-                                       xmlTextReaderValidityStructuredRelay,
-                                              reader);
+                    xmlTextReaderStructuredRelay, reader);
         }
 #endif
     } else {
         /* restore defaults */
-        reader->ctxt->sax->error = xmlParserError;
-        reader->ctxt->sax->serror = NULL;
-        reader->ctxt->vctxt.error = xmlParserValidityError;
-        reader->ctxt->sax->warning = xmlParserWarning;
-        reader->ctxt->vctxt.warning = xmlParserValidityWarning;
         reader->errorFunc = NULL;
         reader->sErrorFunc = NULL;
         reader->errorFuncArg = NULL;
+        xmlCtxtSetErrorHandler(reader->ctxt, NULL, NULL);
 #ifdef LIBXML_SCHEMAS_ENABLED
         if (reader->rngValidCtxt) {
-            xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
-                                     reader);
             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
-                                               reader);
+                                               NULL);
         }
         if (reader->xsdValidCtxt) {
-            xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
-                                    reader);
             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
-                                              reader);
+                                              NULL);
         }
 #endif
     }
@@ -5074,8 +4884,6 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
     if (reader->buffer == NULL)
         reader->buffer = xmlBufCreateSize(100);
     if (reader->buffer == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlTextReaderSetup : malloc failed\n");
         return (-1);
     }
     /* no operation on a reader should require a huge buffer */
@@ -5084,8 +4892,6 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
     if (reader->sax == NULL)
 	reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
     if (reader->sax == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlTextReaderSetup : malloc failed\n");
         return (-1);
     }
     xmlSAXVersion(reader->sax, 2);
@@ -5132,13 +4938,15 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
                 reader->base = 0;
                 reader->cur = 0;
             }
+            if (reader->ctxt == NULL) {
+                return (-1);
+            }
         } else {
 	    xmlParserInputPtr inputStream;
 	    xmlParserInputBufferPtr buf;
-	    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
 
 	    xmlCtxtReset(reader->ctxt);
-	    buf = xmlAllocParserInputBuffer(enc);
+	    buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
 	    if (buf == NULL) return(-1);
 	    inputStream = xmlNewInputStream(reader->ctxt);
 	    if (inputStream == NULL) {
@@ -5157,11 +4965,6 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
 	    inputPush(reader->ctxt, inputStream);
 	    reader->cur = 0;
 	}
-        if (reader->ctxt == NULL) {
-            xmlGenericError(xmlGenericErrorContext,
-                            "xmlTextReaderSetup : malloc failed\n");
-            return (-1);
-        }
     }
     if (reader->dict != NULL) {
         if (reader->ctxt->dict != NULL) {
@@ -5183,7 +4986,6 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
     /*
      * use the parser dictionary to allocate all elements and attributes names
      */
-    reader->ctxt->docdict = 1;
     reader->ctxt->parseMode = XML_PARSE_READER;
 
 #ifdef LIBXML_XINCLUDE_ENABLED
@@ -5194,6 +4996,8 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
     if (options & XML_PARSE_XINCLUDE) {
         reader->xinclude = 1;
 	reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
+        if (reader->xinclude_name == NULL)
+            return(-1);
 	options -= XML_PARSE_XINCLUDE;
     } else
         reader->xinclude = 0;
@@ -5217,23 +5021,50 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
         reader->validate = XML_TEXTREADER_VALIDATE_DTD;
 
     xmlCtxtUseOptions(reader->ctxt, options);
-    if (encoding != NULL) {
-        xmlCharEncodingHandlerPtr hdlr;
-
-        hdlr = xmlFindCharEncodingHandler(encoding);
-        if (hdlr != NULL)
-            xmlSwitchToEncoding(reader->ctxt, hdlr);
-    }
+    if (encoding != NULL)
+        xmlSwitchEncodingName(reader->ctxt, encoding);
     if ((URL != NULL) && (reader->ctxt->input != NULL) &&
-        (reader->ctxt->input->filename == NULL))
+        (reader->ctxt->input->filename == NULL)) {
         reader->ctxt->input->filename = (char *)
             xmlStrdup((const xmlChar *) URL);
+        if (reader->ctxt->input->filename == NULL)
+            return(-1);
+    }
 
     reader->doc = NULL;
 
     return (0);
 }
 
+/**
+ * xmlTextReaderSetMaxAmplification:
+ * @reader: an XML reader
+ * @maxAmpl:  maximum amplification factor
+ *
+ * Set the maximum amplification factor. See xmlCtxtSetMaxAmplification.
+ */
+void
+xmlTextReaderSetMaxAmplification(xmlTextReaderPtr reader, unsigned maxAmpl)
+{
+    xmlCtxtSetMaxAmplification(reader->ctxt, maxAmpl);
+}
+
+/**
+ * xmlTextReaderGetLastError:
+ * @reader: an XML reader
+ *
+ * Available since 2.13.0.
+ *
+ * Returns the last error.
+ */
+const xmlError *
+xmlTextReaderGetLastError(xmlTextReaderPtr reader)
+{
+    if (reader == NULL)
+        return(NULL);
+    return(&reader->ctxt->lastError);
+}
+
 /**
  * xmlTextReaderByteConsumed:
  * @reader: an XML reader
@@ -5273,8 +5104,6 @@ xmlReaderWalker(xmlDocPtr doc)
 
     ret = xmlMalloc(sizeof(xmlTextReader));
     if (ret == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewTextReader : malloc failed\n");
 	return(NULL);
     }
     memset(ret, 0, sizeof(xmlTextReader));
@@ -5337,7 +5166,10 @@ xmlReaderForFile(const char *filename, const char *encoding, int options)
     reader = xmlNewTextReaderFilename(filename);
     if (reader == NULL)
         return (NULL);
-    xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
+    if (xmlTextReaderSetup(reader, NULL, NULL, encoding, options) < 0) {
+        xmlFreeTextReader(reader);
+        return (NULL);
+    }
     return (reader);
 }
 
@@ -5361,8 +5193,7 @@ xmlReaderForMemory(const char *buffer, int size, const char *URL,
     xmlTextReaderPtr reader;
     xmlParserInputBufferPtr buf;
 
-    buf = xmlParserInputBufferCreateStatic(buffer, size,
-                                      XML_CHAR_ENCODING_NONE);
+    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
     if (buf == NULL) {
         return (NULL);
     }
@@ -5372,7 +5203,10 @@ xmlReaderForMemory(const char *buffer, int size, const char *URL,
         return (NULL);
     }
     reader->allocs |= XML_TEXTREADER_INPUT;
-    xmlTextReaderSetup(reader, NULL, URL, encoding, options);
+    if (xmlTextReaderSetup(reader, NULL, URL, encoding, options) < 0) {
+        xmlFreeTextReader(reader);
+        return (NULL);
+    }
     return (reader);
 }
 
@@ -5409,7 +5243,10 @@ xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
         return (NULL);
     }
     reader->allocs |= XML_TEXTREADER_INPUT;
-    xmlTextReaderSetup(reader, NULL, URL, encoding, options);
+    if (xmlTextReaderSetup(reader, NULL, URL, encoding, options) < 0) {
+        xmlFreeTextReader(reader);
+        return (NULL);
+    }
     return (reader);
 }
 
@@ -5451,7 +5288,10 @@ xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
         return (NULL);
     }
     reader->allocs |= XML_TEXTREADER_INPUT;
-    xmlTextReaderSetup(reader, NULL, URL, encoding, options);
+    if (xmlTextReaderSetup(reader, NULL, URL, encoding, options) < 0) {
+        xmlFreeTextReader(reader);
+        return (NULL);
+    }
     return (reader);
 }
 
@@ -5588,7 +5428,7 @@ xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
     if (buffer == NULL)
         return (-1);
 
-    input = xmlParserInputBufferCreateStatic(buffer, size,
+    input = xmlParserInputBufferCreateMem(buffer, size,
                                       XML_CHAR_ENCODING_NONE);
     if (input == NULL) {
         return (-1);
diff --git a/xmlregexp.c b/xmlregexp.c
index a2a36c499183064621457d8d6175aa5722214840..31e3d1a6229df16d91b98ad869a3ae63ac561b26 100644
--- a/xmlregexp.c
+++ b/xmlregexp.c
@@ -19,8 +19,6 @@
 
 #ifdef LIBXML_REGEXP_ENABLED
 
-/* #define DEBUG_ERR */
-
 #include <stdio.h>
 #include <string.h>
 #include <limits.h>
@@ -31,15 +29,13 @@
 #include <libxml/xmlautomata.h>
 #include <libxml/xmlunicode.h>
 
+#include "private/error.h"
+#include "private/regexp.h"
+
 #ifndef SIZE_MAX
 #define SIZE_MAX ((size_t) -1)
 #endif
 
-/* #define DEBUG_REGEXP_GRAPH */
-/* #define DEBUG_REGEXP_EXEC */
-/* #define DEBUG_PUSH */
-/* #define DEBUG_COMPACTION */
-
 #define MAX_PUSH 10000000
 
 #ifdef ERROR
@@ -52,7 +48,6 @@
 #define CUR (*(ctxt->cur))
 #define NXT(index) (ctxt->cur[index])
 
-#define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
 #define NEXTL(l) ctxt->cur += l;
 #define XML_REG_STRING_SEPARATOR '|'
 /*
@@ -61,16 +56,6 @@
  */
 #define PREV (ctxt->cur[-1])
 
-/**
- * TODO:
- *
- * macro to flag unimplemented blocks
- */
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
-
 /************************************************************************
  *									*
  *			Datatypes and structures			*
@@ -361,8 +346,6 @@ static int xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint);
 static int xmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint,
                   int neg, int start, int end, const xmlChar *blockName);
 
-void xmlAutomataSetFlags(xmlAutomataPtr am, int flags);
-
 /************************************************************************
  *									*
  *		Regexp memory error handler				*
@@ -375,17 +358,12 @@ void xmlAutomataSetFlags(xmlAutomataPtr am, int flags);
  * Handle an out of memory condition
  */
 static void
-xmlRegexpErrMemory(xmlRegParserCtxtPtr ctxt, const char *extra)
+xmlRegexpErrMemory(xmlRegParserCtxtPtr ctxt)
 {
-    const char *regexp = NULL;
-    if (ctxt != NULL) {
-        regexp = (const char *) ctxt->string;
-	ctxt->error = XML_ERR_NO_MEMORY;
-    }
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP,
-		    XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
-		    regexp, NULL, 0, 0,
-		    "Memory allocation failed : %s\n", extra);
+    if (ctxt != NULL)
+        ctxt->error = XML_ERR_NO_MEMORY;
+
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_REGEXP, NULL);
 }
 
 /**
@@ -399,16 +377,20 @@ xmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt, const char *extra)
 {
     const char *regexp = NULL;
     int idx = 0;
+    int res;
 
     if (ctxt != NULL) {
         regexp = (const char *) ctxt->string;
 	idx = ctxt->cur - ctxt->string;
 	ctxt->error = XML_REGEXP_COMPILE_ERROR;
     }
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP,
-		    XML_REGEXP_COMPILE_ERROR, XML_ERR_FATAL, NULL, 0, extra,
-		    regexp, NULL, idx, 0,
-		    "failed to compile: %s\n", extra);
+
+    res = __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP,
+                          XML_REGEXP_COMPILE_ERROR, XML_ERR_FATAL,
+                          NULL, 0, extra, regexp, NULL, idx, 0,
+                          "failed to compile: %s\n", extra);
+    if (res < 0)
+        xmlRegexpErrMemory(ctxt);
 }
 
 /************************************************************************
@@ -435,7 +417,8 @@ xmlRegCalloc2(size_t dim1, size_t dim2, size_t elemSize) {
     void *ret;
 
     /* Check for overflow */
-    if (dim1 > SIZE_MAX / dim2 / elemSize)
+    if ((dim2 == 0) || (elemSize == 0) ||
+        (dim1 > SIZE_MAX / dim2 / elemSize))
         return (NULL);
     totalSize = dim1 * dim2 * elemSize;
     ret = xmlMalloc(totalSize);
@@ -458,7 +441,7 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
 
     ret = (xmlRegexpPtr) xmlMalloc(sizeof(xmlRegexp));
     if (ret == NULL) {
-	xmlRegexpErrMemory(ctxt, "compiling regexp");
+	xmlRegexpErrMemory(ctxt);
 	return(NULL);
     }
     memset(ret, 0, sizeof(xmlRegexp));
@@ -472,7 +455,11 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
     ret->determinist = ctxt->determinist;
     ret->flags = ctxt->flags;
     if (ret->determinist == -1) {
-        xmlRegexpIsDeterminist(ret);
+        if (xmlRegexpIsDeterminist(ret) < 0) {
+            xmlRegexpErrMemory(ctxt);
+            xmlFree(ret);
+            return(NULL);
+        }
     }
 
     if ((ret->determinist != 0) &&
@@ -499,7 +486,7 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
 
 	stateRemap = xmlMalloc(ret->nbStates * sizeof(int));
 	if (stateRemap == NULL) {
-	    xmlRegexpErrMemory(ctxt, "compiling regexp");
+	    xmlRegexpErrMemory(ctxt);
 	    xmlFree(ret);
 	    return(NULL);
 	}
@@ -511,19 +498,16 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
 		stateRemap[i] = -1;
 	    }
 	}
-#ifdef DEBUG_COMPACTION
-	printf("Final: %d states\n", nbstates);
-#endif
 	stringMap = xmlMalloc(ret->nbAtoms * sizeof(char *));
 	if (stringMap == NULL) {
-	    xmlRegexpErrMemory(ctxt, "compiling regexp");
+	    xmlRegexpErrMemory(ctxt);
 	    xmlFree(stateRemap);
 	    xmlFree(ret);
 	    return(NULL);
 	}
 	stringRemap = xmlMalloc(ret->nbAtoms * sizeof(int));
 	if (stringRemap == NULL) {
-	    xmlRegexpErrMemory(ctxt, "compiling regexp");
+	    xmlRegexpErrMemory(ctxt);
 	    xmlFree(stringMap);
 	    xmlFree(stateRemap);
 	    xmlFree(ret);
@@ -563,9 +547,6 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
 		return(NULL);
 	    }
 	}
-#ifdef DEBUG_COMPACTION
-	printf("Final: %d atoms\n", nbatoms);
-#endif
 	transitions = (int *) xmlRegCalloc2(nbstates + 1, nbatoms + 1,
                                             sizeof(int));
 	if (transitions == NULL) {
@@ -598,14 +579,14 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
 
 	    for (j = 0;j < state->nbTrans;j++) {
 		trans = &(state->trans[j]);
-		if ((trans->to == -1) || (trans->atom == NULL))
+		if ((trans->to < 0) || (trans->atom == NULL))
 		    continue;
                 atomno = stringRemap[trans->atom->no];
 		if ((trans->atom->data != NULL) && (transdata == NULL)) {
 		    transdata = (void **) xmlRegCalloc2(nbstates, nbatoms,
 			                                sizeof(void *));
 		    if (transdata == NULL) {
-			xmlRegexpErrMemory(ctxt, "compiling regexp");
+			xmlRegexpErrMemory(ctxt);
 			break;
 		    }
 		}
@@ -619,11 +600,6 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
 		if (prev != 0) {
 		    if (prev != targetno + 1) {
 			ret->determinist = 0;
-#ifdef DEBUG_COMPACTION
-			printf("Indet: state %d trans %d, atom %d to %d : %d to %d\n",
-			       i, j, trans->atom->no, trans->to, atomno, targetno);
-			printf("       previous to is %d\n", prev);
-#endif
 			if (transdata != NULL)
 			    xmlFree(transdata);
 			xmlFree(transitions);
@@ -648,18 +624,6 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
 	    }
 	}
 	ret->determinist = 1;
-#ifdef DEBUG_COMPACTION
-	/*
-	 * Debug
-	 */
-	for (i = 0;i < nbstates;i++) {
-	    for (j = 0;j < nbatoms + 1;j++) {
-                printf("%02d ", transitions[i * (nbatoms + 1) + j]);
-	    }
-	    printf("\n");
-	}
-	printf("\n");
-#endif
 	/*
 	 * Cleanup of the old data
 	 */
@@ -713,8 +677,13 @@ xmlRegNewParserCtxt(const xmlChar *string) {
     if (ret == NULL)
 	return(NULL);
     memset(ret, 0, sizeof(xmlRegParserCtxt));
-    if (string != NULL)
+    if (string != NULL) {
 	ret->string = xmlStrdup(string);
+        if (ret->string == NULL) {
+            xmlFree(ret);
+            return(NULL);
+        }
+    }
     ret->cur = ret->string;
     ret->neg = 0;
     ret->negs = 0;
@@ -742,7 +711,7 @@ xmlRegNewRange(xmlRegParserCtxtPtr ctxt,
 
     ret = (xmlRegRangePtr) xmlMalloc(sizeof(xmlRegRange));
     if (ret == NULL) {
-	xmlRegexpErrMemory(ctxt, "allocating range");
+	xmlRegexpErrMemory(ctxt);
 	return(NULL);
     }
     ret->neg = neg;
@@ -790,7 +759,7 @@ xmlRegCopyRange(xmlRegParserCtxtPtr ctxt, xmlRegRangePtr range) {
     if (range->blockName != NULL) {
 	ret->blockName = xmlStrdup(range->blockName);
 	if (ret->blockName == NULL) {
-	    xmlRegexpErrMemory(ctxt, "allocating range");
+	    xmlRegexpErrMemory(ctxt);
 	    xmlRegFreeRange(ret);
 	    return(NULL);
 	}
@@ -813,7 +782,7 @@ xmlRegNewAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomType type) {
 
     ret = (xmlRegAtomPtr) xmlMalloc(sizeof(xmlRegAtom));
     if (ret == NULL) {
-	xmlRegexpErrMemory(ctxt, "allocating atom");
+	xmlRegexpErrMemory(ctxt);
 	return(NULL);
     }
     memset(ret, 0, sizeof(xmlRegAtom));
@@ -865,7 +834,7 @@ xmlRegCopyAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
 
     ret = (xmlRegAtomPtr) xmlMalloc(sizeof(xmlRegAtom));
     if (ret == NULL) {
-	xmlRegexpErrMemory(ctxt, "copying atom");
+	xmlRegexpErrMemory(ctxt);
 	return(NULL);
     }
     memset(ret, 0, sizeof(xmlRegAtom));
@@ -879,7 +848,7 @@ xmlRegCopyAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
         ret->ranges = (xmlRegRangePtr *) xmlMalloc(sizeof(xmlRegRangePtr) *
 	                                           atom->nbRanges);
 	if (ret->ranges == NULL) {
-	    xmlRegexpErrMemory(ctxt, "copying atom");
+	    xmlRegexpErrMemory(ctxt);
 	    goto error;
 	}
 	for (i = 0;i < atom->nbRanges;i++) {
@@ -902,7 +871,7 @@ xmlRegNewState(xmlRegParserCtxtPtr ctxt) {
 
     ret = (xmlRegStatePtr) xmlMalloc(sizeof(xmlRegState));
     if (ret == NULL) {
-	xmlRegexpErrMemory(ctxt, "allocating state");
+	xmlRegexpErrMemory(ctxt);
 	return(NULL);
     }
     memset(ret, 0, sizeof(xmlRegState));
@@ -1189,55 +1158,13 @@ xmlRegPrintState(FILE *output, xmlRegStatePtr state) {
     }
 }
 
-#ifdef DEBUG_REGEXP_GRAPH
-static void
-xmlRegPrintCtxt(FILE *output, xmlRegParserCtxtPtr ctxt) {
-    int i;
-
-    fprintf(output, " ctxt: ");
-    if (ctxt == NULL) {
-	fprintf(output, "NULL\n");
-	return;
-    }
-    fprintf(output, "'%s' ", ctxt->string);
-    if (ctxt->error)
-	fprintf(output, "error ");
-    if (ctxt->neg)
-	fprintf(output, "neg ");
-    fprintf(output, "\n");
-    fprintf(output, "%d atoms:\n", ctxt->nbAtoms);
-    for (i = 0;i < ctxt->nbAtoms; i++) {
-	fprintf(output, " %02d ", i);
-	xmlRegPrintAtom(output, ctxt->atoms[i]);
-    }
-    if (ctxt->atom != NULL) {
-	fprintf(output, "current atom:\n");
-	xmlRegPrintAtom(output, ctxt->atom);
-    }
-    fprintf(output, "%d states:", ctxt->nbStates);
-    if (ctxt->start != NULL)
-	fprintf(output, " start: %d", ctxt->start->no);
-    if (ctxt->end != NULL)
-	fprintf(output, " end: %d", ctxt->end->no);
-    fprintf(output, "\n");
-    for (i = 0;i < ctxt->nbStates; i++) {
-	xmlRegPrintState(output, ctxt->states[i]);
-    }
-    fprintf(output, "%d counters:\n", ctxt->nbCounters);
-    for (i = 0;i < ctxt->nbCounters; i++) {
-	fprintf(output, " %d: min %d max %d\n", i, ctxt->counters[i].min,
-		                                ctxt->counters[i].max);
-    }
-}
-#endif
-
 /************************************************************************
  *									*
  *		 Finite Automata structures manipulations		*
  *									*
  ************************************************************************/
 
-static void
+static xmlRegRangePtr
 xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom,
 	           int neg, xmlRegAtomType type, int start, int end,
 		   xmlChar *blockName) {
@@ -1245,20 +1172,20 @@ xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom,
 
     if (atom == NULL) {
 	ERROR("add range: atom is NULL");
-	return;
+	return(NULL);
     }
     if (atom->type != XML_REGEXP_RANGES) {
 	ERROR("add range: atom is not ranges");
-	return;
+	return(NULL);
     }
     if (atom->maxRanges == 0) {
 	atom->maxRanges = 4;
 	atom->ranges = (xmlRegRangePtr *) xmlMalloc(atom->maxRanges *
 		                             sizeof(xmlRegRangePtr));
 	if (atom->ranges == NULL) {
-	    xmlRegexpErrMemory(ctxt, "adding ranges");
+	    xmlRegexpErrMemory(ctxt);
 	    atom->maxRanges = 0;
-	    return;
+	    return(NULL);
 	}
     } else if (atom->nbRanges >= atom->maxRanges) {
 	xmlRegRangePtr *tmp;
@@ -1266,18 +1193,19 @@ xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom,
 	tmp = (xmlRegRangePtr *) xmlRealloc(atom->ranges, atom->maxRanges *
 		                             sizeof(xmlRegRangePtr));
 	if (tmp == NULL) {
-	    xmlRegexpErrMemory(ctxt, "adding ranges");
+	    xmlRegexpErrMemory(ctxt);
 	    atom->maxRanges /= 2;
-	    return;
+	    return(NULL);
 	}
 	atom->ranges = tmp;
     }
     range = xmlRegNewRange(ctxt, neg, type, start, end);
     if (range == NULL)
-	return;
+	return(NULL);
     range->blockName = blockName;
     atom->ranges[atom->nbRanges++] = range;
 
+    return(range);
 }
 
 static int
@@ -1287,7 +1215,7 @@ xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) {
 	ctxt->counters = (xmlRegCounter *) xmlMalloc(ctxt->maxCounters *
 		                             sizeof(xmlRegCounter));
 	if (ctxt->counters == NULL) {
-	    xmlRegexpErrMemory(ctxt, "allocating counter");
+	    xmlRegexpErrMemory(ctxt);
 	    ctxt->maxCounters = 0;
 	    return(-1);
 	}
@@ -1297,7 +1225,7 @@ xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) {
 	tmp = (xmlRegCounter *) xmlRealloc(ctxt->counters, ctxt->maxCounters *
 		                           sizeof(xmlRegCounter));
 	if (tmp == NULL) {
-	    xmlRegexpErrMemory(ctxt, "allocating counter");
+	    xmlRegexpErrMemory(ctxt);
 	    ctxt->maxCounters /= 2;
 	    return(-1);
 	}
@@ -1314,26 +1242,17 @@ xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
 	ERROR("atom push: atom is NULL");
 	return(-1);
     }
-    if (ctxt->maxAtoms == 0) {
-	ctxt->maxAtoms = 4;
-	ctxt->atoms = (xmlRegAtomPtr *) xmlMalloc(ctxt->maxAtoms *
-		                             sizeof(xmlRegAtomPtr));
-	if (ctxt->atoms == NULL) {
-	    xmlRegexpErrMemory(ctxt, "pushing atom");
-	    ctxt->maxAtoms = 0;
-	    return(-1);
-	}
-    } else if (ctxt->nbAtoms >= ctxt->maxAtoms) {
+    if (ctxt->nbAtoms >= ctxt->maxAtoms) {
+        size_t newSize = ctxt->maxAtoms ? ctxt->maxAtoms * 2 : 4;
 	xmlRegAtomPtr *tmp;
-	ctxt->maxAtoms *= 2;
-	tmp = (xmlRegAtomPtr *) xmlRealloc(ctxt->atoms, ctxt->maxAtoms *
-		                             sizeof(xmlRegAtomPtr));
+
+	tmp = xmlRealloc(ctxt->atoms, newSize * sizeof(xmlRegAtomPtr));
 	if (tmp == NULL) {
-	    xmlRegexpErrMemory(ctxt, "allocating counter");
-	    ctxt->maxAtoms /= 2;
+	    xmlRegexpErrMemory(ctxt);
 	    return(-1);
 	}
 	ctxt->atoms = tmp;
+        ctxt->maxAtoms = newSize;
     }
     atom->no = ctxt->nbAtoms;
     ctxt->atoms[ctxt->nbAtoms++] = atom;
@@ -1348,7 +1267,7 @@ xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target,
 	target->transTo = (int *) xmlMalloc(target->maxTransTo *
 		                             sizeof(int));
 	if (target->transTo == NULL) {
-	    xmlRegexpErrMemory(ctxt, "adding transition");
+	    xmlRegexpErrMemory(ctxt);
 	    target->maxTransTo = 0;
 	    return;
 	}
@@ -1358,7 +1277,7 @@ xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target,
 	tmp = (int *) xmlRealloc(target->transTo, target->maxTransTo *
 		                             sizeof(int));
 	if (tmp == NULL) {
-	    xmlRegexpErrMemory(ctxt, "adding transition");
+	    xmlRegexpErrMemory(ctxt);
 	    target->maxTransTo /= 2;
 	    return;
 	}
@@ -1395,10 +1314,6 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
 	    (trans->to == target->no) &&
 	    (trans->counter == counter) &&
 	    (trans->count == count)) {
-#ifdef DEBUG_REGEXP_GRAPH
-	    printf("Ignoring duplicate transition from %d to %d\n",
-		    state->no, target->no);
-#endif
 	    return;
 	}
     }
@@ -1408,7 +1323,7 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
 	state->trans = (xmlRegTrans *) xmlMalloc(state->maxTrans *
 		                             sizeof(xmlRegTrans));
 	if (state->trans == NULL) {
-	    xmlRegexpErrMemory(ctxt, "adding transition");
+	    xmlRegexpErrMemory(ctxt);
 	    state->maxTrans = 0;
 	    return;
 	}
@@ -1418,25 +1333,12 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
 	tmp = (xmlRegTrans *) xmlRealloc(state->trans, state->maxTrans *
 		                             sizeof(xmlRegTrans));
 	if (tmp == NULL) {
-	    xmlRegexpErrMemory(ctxt, "adding transition");
+	    xmlRegexpErrMemory(ctxt);
 	    state->maxTrans /= 2;
 	    return;
 	}
 	state->trans = tmp;
     }
-#ifdef DEBUG_REGEXP_GRAPH
-    printf("Add trans from %d to %d ", state->no, target->no);
-    if (count == REGEXP_ALL_COUNTER)
-	printf("all transition\n");
-    else if (count >= 0)
-	printf("count based %d\n", count);
-    else if (counter >= 0)
-	printf("counted %d\n", counter);
-    else if (atom == NULL)
-	printf("epsilon transition\n");
-    else if (atom != NULL)
-        xmlRegPrintAtom(stdout, atom);
-#endif
 
     state->trans[state->nbTrans].atom = atom;
     state->trans[state->nbTrans].to = target->no;
@@ -1447,33 +1349,31 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
     xmlRegStateAddTransTo(ctxt, target, state->no);
 }
 
-static int
-xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
-    if (state == NULL) return(-1);
-    if (ctxt->maxStates == 0) {
-	ctxt->maxStates = 4;
-	ctxt->states = (xmlRegStatePtr *) xmlMalloc(ctxt->maxStates *
-		                             sizeof(xmlRegStatePtr));
-	if (ctxt->states == NULL) {
-	    xmlRegexpErrMemory(ctxt, "adding state");
-	    ctxt->maxStates = 0;
-	    return(-1);
-	}
-    } else if (ctxt->nbStates >= ctxt->maxStates) {
+static xmlRegStatePtr
+xmlRegStatePush(xmlRegParserCtxtPtr ctxt) {
+    xmlRegStatePtr state;
+
+    if (ctxt->nbStates >= ctxt->maxStates) {
+        size_t newSize = ctxt->maxStates ? ctxt->maxStates * 2 : 4;
 	xmlRegStatePtr *tmp;
-	ctxt->maxStates *= 2;
-	tmp = (xmlRegStatePtr *) xmlRealloc(ctxt->states, ctxt->maxStates *
-		                             sizeof(xmlRegStatePtr));
+
+	tmp = xmlRealloc(ctxt->states, newSize * sizeof(tmp[0]));
 	if (tmp == NULL) {
-	    xmlRegexpErrMemory(ctxt, "adding state");
-	    ctxt->maxStates /= 2;
-	    return(-1);
+	    xmlRegexpErrMemory(ctxt);
+	    return(NULL);
 	}
 	ctxt->states = tmp;
+	ctxt->maxStates = newSize;
     }
+
+    state = xmlRegNewState(ctxt);
+    if (state == NULL)
+        return(NULL);
+
     state->no = ctxt->nbStates;
     ctxt->states[ctxt->nbStates++] = state;
-    return(0);
+
+    return(state);
 }
 
 /**
@@ -1484,19 +1384,21 @@ xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
  * @lax:
  *
  */
-static void
+static int
 xmlFAGenerateAllTransition(xmlRegParserCtxtPtr ctxt,
 			   xmlRegStatePtr from, xmlRegStatePtr to,
 			   int lax) {
     if (to == NULL) {
-	to = xmlRegNewState(ctxt);
-	xmlRegStatePush(ctxt, to);
+	to = xmlRegStatePush(ctxt);
+        if (to == NULL)
+            return(-1);
 	ctxt->state = to;
     }
     if (lax)
 	xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_LAX_COUNTER);
     else
 	xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_COUNTER);
+    return(0);
 }
 
 /**
@@ -1506,15 +1408,17 @@ xmlFAGenerateAllTransition(xmlRegParserCtxtPtr ctxt,
  * @to:  the target state or NULL for building a new one
  *
  */
-static void
+static int
 xmlFAGenerateEpsilonTransition(xmlRegParserCtxtPtr ctxt,
 			       xmlRegStatePtr from, xmlRegStatePtr to) {
     if (to == NULL) {
-	to = xmlRegNewState(ctxt);
-	xmlRegStatePush(ctxt, to);
+	to = xmlRegStatePush(ctxt);
+        if (to == NULL)
+            return(-1);
 	ctxt->state = to;
     }
     xmlRegStateAddTrans(ctxt, from, NULL, to, -1, -1);
+    return(0);
 }
 
 /**
@@ -1525,15 +1429,17 @@ xmlFAGenerateEpsilonTransition(xmlRegParserCtxtPtr ctxt,
  * counter:  the counter for that transition
  *
  */
-static void
+static int
 xmlFAGenerateCountedEpsilonTransition(xmlRegParserCtxtPtr ctxt,
 	    xmlRegStatePtr from, xmlRegStatePtr to, int counter) {
     if (to == NULL) {
-	to = xmlRegNewState(ctxt);
-	xmlRegStatePush(ctxt, to);
+	to = xmlRegStatePush(ctxt);
+        if (to == NULL)
+            return(-1);
 	ctxt->state = to;
     }
     xmlRegStateAddTrans(ctxt, from, NULL, to, counter, -1);
+    return(0);
 }
 
 /**
@@ -1544,15 +1450,17 @@ xmlFAGenerateCountedEpsilonTransition(xmlRegParserCtxtPtr ctxt,
  * counter:  the counter for that transition
  *
  */
-static void
+static int
 xmlFAGenerateCountedTransition(xmlRegParserCtxtPtr ctxt,
 	    xmlRegStatePtr from, xmlRegStatePtr to, int counter) {
     if (to == NULL) {
-	to = xmlRegNewState(ctxt);
-	xmlRegStatePush(ctxt, to);
+	to = xmlRegStatePush(ctxt);
+        if (to == NULL)
+            return(-1);
 	ctxt->state = to;
     }
     xmlRegStateAddTrans(ctxt, from, NULL, to, -1, counter);
+    return(0);
 }
 
 /**
@@ -1579,9 +1487,6 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	 * this is a subexpression handling one should not need to
 	 * create a new node except for XML_REGEXP_QUANT_RANGE.
 	 */
-	if (xmlRegAtomPush(ctxt, atom) < 0) {
-	    return(-1);
-	}
 	if ((to != NULL) && (atom->stop != to) &&
 	    (atom->quant != XML_REGEXP_QUANT_RANGE)) {
 	    /*
@@ -1591,8 +1496,9 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 #ifdef DV
 	} else if ((to == NULL) && (atom->quant != XML_REGEXP_QUANT_RANGE) &&
 		   (atom->quant != XML_REGEXP_QUANT_ONCE)) {
-	    to = xmlRegNewState(ctxt);
-	    xmlRegStatePush(ctxt, to);
+	    to = xmlRegStatePush(ctxt, to);
+            if (to == NULL)
+                return(-1);
 	    ctxt->state = to;
 	    xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to);
 #endif
@@ -1632,8 +1538,9 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 		if (to != NULL) {
 		    newstate = to;
 		} else {
-		    newstate = xmlRegNewState(ctxt);
-		    xmlRegStatePush(ctxt, newstate);
+		    newstate = xmlRegStatePush(ctxt);
+                    if (newstate == NULL)
+                        return(-1);
 		}
 
 		/*
@@ -1661,10 +1568,14 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 		    copy->max = 0;
 
 		    if (xmlFAGenerateTransitions(ctxt, atom->start, NULL, copy)
-		        < 0)
+		        < 0) {
+                        xmlRegFreeAtom(copy);
 			return(-1);
+                    }
 		    inter = ctxt->state;
 		    counter = xmlRegGetCounter(ctxt);
+                    if (counter < 0)
+                        return(-1);
 		    ctxt->counters[counter].min = atom->min - 1;
 		    ctxt->counters[counter].max = atom->max - 1;
 		    /* count the number of times we see it again */
@@ -1683,6 +1594,8 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 		     * epsilon transition.
 		     */
 		    counter = xmlRegGetCounter(ctxt);
+                    if (counter < 0)
+                        return(-1);
 		    ctxt->counters[counter].min = atom->min - 1;
 		    ctxt->counters[counter].max = atom->max - 1;
 		    /* allow a way out based on the count */
@@ -1705,6 +1618,8 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	    default:
 		break;
 	}
+	if (xmlRegAtomPush(ctxt, atom) < 0)
+	    return(-1);
 	return(0);
     }
     if ((atom->min == 0) && (atom->max == 0) &&
@@ -1713,12 +1628,9 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	 * we can discard the atom and generate an epsilon transition instead
 	 */
 	if (to == NULL) {
-	    to = xmlRegNewState(ctxt);
-	    if (to != NULL)
-		xmlRegStatePush(ctxt, to);
-	    else {
+	    to = xmlRegStatePush(ctxt);
+	    if (to == NULL)
 		return(-1);
-	    }
 	}
 	xmlFAGenerateEpsilonTransition(ctxt, from, to);
 	ctxt->state = to;
@@ -1726,12 +1638,9 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	return(0);
     }
     if (to == NULL) {
-	to = xmlRegNewState(ctxt);
-	if (to != NULL)
-	    xmlRegStatePush(ctxt, to);
-	else {
+	to = xmlRegStatePush(ctxt);
+	if (to == NULL)
 	    return(-1);
-	}
     }
     end = to;
     if ((atom->quant == XML_REGEXP_QUANT_MULT) ||
@@ -1743,18 +1652,12 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	 */
         xmlRegStatePtr tmp;
 
-	tmp = xmlRegNewState(ctxt);
-	if (tmp != NULL)
-	    xmlRegStatePush(ctxt, tmp);
-	else {
+	tmp = xmlRegStatePush(ctxt);
+        if (tmp == NULL)
 	    return(-1);
-	}
 	xmlFAGenerateEpsilonTransition(ctxt, tmp, to);
 	to = tmp;
     }
-    if (xmlRegAtomPush(ctxt, atom) < 0) {
-	return(-1);
-    }
     if ((atom->quant == XML_REGEXP_QUANT_RANGE) &&
         (atom->min == 0) && (atom->max > 0)) {
 	nullable = 1;
@@ -1785,6 +1688,8 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	default:
 	    break;
     }
+    if (xmlRegAtomPush(ctxt, atom) < 0)
+	return(-1);
     return(0);
 }
 
@@ -1803,9 +1708,6 @@ xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int fromnr,
     xmlRegStatePtr from;
     xmlRegStatePtr to;
 
-#ifdef DEBUG_REGEXP_GRAPH
-    printf("xmlFAReduceEpsilonTransitions(%d, %d)\n", fromnr, tonr);
-#endif
     from = ctxt->states[fromnr];
     if (from == NULL)
 	return;
@@ -1818,56 +1720,67 @@ xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int fromnr,
 
     to->mark = XML_REGEXP_MARK_VISITED;
     if (to->type == XML_REGEXP_FINAL_STATE) {
-#ifdef DEBUG_REGEXP_GRAPH
-	printf("State %d is final, so %d becomes final\n", tonr, fromnr);
-#endif
 	from->type = XML_REGEXP_FINAL_STATE;
     }
     for (transnr = 0;transnr < to->nbTrans;transnr++) {
-        if (to->trans[transnr].to < 0)
+        xmlRegTransPtr t1 = &to->trans[transnr];
+        int tcounter;
+
+        if (t1->to < 0)
 	    continue;
-	if (to->trans[transnr].atom == NULL) {
+        if (t1->counter >= 0) {
+            /* assert(counter < 0); */
+            tcounter = t1->counter;
+        } else {
+            tcounter = counter;
+        }
+	if (t1->atom == NULL) {
 	    /*
 	     * Don't remove counted transitions
 	     * Don't loop either
 	     */
-	    if (to->trans[transnr].to != fromnr) {
-		if (to->trans[transnr].count >= 0) {
-		    int newto = to->trans[transnr].to;
-
-		    xmlRegStateAddTrans(ctxt, from, NULL,
-					ctxt->states[newto],
-					-1, to->trans[transnr].count);
+	    if (t1->to != fromnr) {
+		if (t1->count >= 0) {
+		    xmlRegStateAddTrans(ctxt, from, NULL, ctxt->states[t1->to],
+					-1, t1->count);
 		} else {
-#ifdef DEBUG_REGEXP_GRAPH
-		    printf("Found epsilon trans %d from %d to %d\n",
-			   transnr, tonr, to->trans[transnr].to);
-#endif
-		    if (to->trans[transnr].counter >= 0) {
-			xmlFAReduceEpsilonTransitions(ctxt, fromnr,
-					      to->trans[transnr].to,
-					      to->trans[transnr].counter);
-		    } else {
-			xmlFAReduceEpsilonTransitions(ctxt, fromnr,
-					      to->trans[transnr].to,
-					      counter);
-		    }
+                    xmlFAReduceEpsilonTransitions(ctxt, fromnr, t1->to,
+                                                  tcounter);
 		}
 	    }
 	} else {
-	    int newto = to->trans[transnr].to;
-
-	    if (to->trans[transnr].counter >= 0) {
-		xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom,
-				    ctxt->states[newto],
-				    to->trans[transnr].counter, -1);
-	    } else {
-		xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom,
-				    ctxt->states[newto], counter, -1);
-	    }
+            xmlRegStateAddTrans(ctxt, from, t1->atom,
+                                ctxt->states[t1->to], tcounter, -1);
 	}
     }
+}
+
+/**
+ * xmlFAFinishReduceEpsilonTransitions:
+ * @ctxt:  a regexp parser context
+ * @fromnr:  the from state
+ * @tonr:  the to state
+ * @counter:  should that transition be associated to a counted
+ *
+ */
+static void
+xmlFAFinishReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int tonr) {
+    int transnr;
+    xmlRegStatePtr to;
+
+    to = ctxt->states[tonr];
+    if (to == NULL)
+	return;
+    if ((to->mark == XML_REGEXP_MARK_START) ||
+	(to->mark == XML_REGEXP_MARK_NORMAL))
+	return;
+
     to->mark = XML_REGEXP_MARK_NORMAL;
+    for (transnr = 0;transnr < to->nbTrans;transnr++) {
+	xmlRegTransPtr t1 = &to->trans[transnr];
+	if ((t1->to >= 0) && (t1->atom == NULL))
+            xmlFAFinishReduceEpsilonTransitions(ctxt, t1->to);
+    }
 }
 
 /**
@@ -1914,23 +1827,11 @@ xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
 	    newto = state->trans[0].to;
 
             if (state->type == XML_REGEXP_START_STATE) {
-#ifdef DEBUG_REGEXP_GRAPH
-		printf("Found simple epsilon trans from start %d to %d\n",
-		       statenr, newto);
-#endif
             } else {
-#ifdef DEBUG_REGEXP_GRAPH
-		printf("Found simple epsilon trans from %d to %d\n",
-		       statenr, newto);
-#endif
 	        for (i = 0;i < state->nbTransTo;i++) {
 		    tmp = ctxt->states[state->transTo[i]];
 		    for (j = 0;j < tmp->nbTrans;j++) {
 			if (tmp->trans[j].to == statenr) {
-#ifdef DEBUG_REGEXP_GRAPH
-			    printf("Changed transition %d on %d to go to %d\n",
-				   j, tmp->no, newto);
-#endif
 			    tmp->trans[j].to = -1;
 			    xmlRegStateAddTrans(ctxt, tmp, tmp->trans[j].atom,
 						ctxt->states[newto],
@@ -1972,9 +1873,6 @@ xmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
     for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
 	state = ctxt->states[statenr];
 	if ((state != NULL) && (state->type == XML_REGEXP_UNREACH_STATE)) {
-#ifdef DEBUG_REGEXP_GRAPH
-	    printf("Removed unreachable state %d\n", statenr);
-#endif
 	    xmlRegFreeState(state);
 	    ctxt->states[statenr] = NULL;
 	}
@@ -2003,28 +1901,16 @@ xmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
 		(state->trans[transnr].to >= 0)) {
 		if (state->trans[transnr].to == statenr) {
 		    state->trans[transnr].to = -1;
-#ifdef DEBUG_REGEXP_GRAPH
-		    printf("Removed loopback epsilon trans %d on %d\n",
-			   transnr, statenr);
-#endif
 		} else if (state->trans[transnr].count < 0) {
 		    int newto = state->trans[transnr].to;
 
-#ifdef DEBUG_REGEXP_GRAPH
-		    printf("Found epsilon trans %d from %d to %d\n",
-			   transnr, statenr, newto);
-#endif
 		    has_epsilon = 1;
 		    state->trans[transnr].to = -2;
 		    state->mark = XML_REGEXP_MARK_START;
 		    xmlFAReduceEpsilonTransitions(ctxt, statenr,
 				      newto, state->trans[transnr].counter);
+		    xmlFAFinishReduceEpsilonTransitions(ctxt, newto);
 		    state->mark = XML_REGEXP_MARK_NORMAL;
-#ifdef DEBUG_REGEXP_GRAPH
-		} else {
-		    printf("Found counted transition %d on %d\n",
-			   transnr, statenr);
-#endif
 	        }
 	    }
 	}
@@ -2098,9 +1984,6 @@ xmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
     for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
 	state = ctxt->states[statenr];
 	if ((state != NULL) && (state->reached == XML_REGEXP_MARK_NORMAL)) {
-#ifdef DEBUG_REGEXP_GRAPH
-	    printf("Removed unreachable state %d\n", statenr);
-#endif
 	    xmlRegFreeState(state);
 	    ctxt->states[statenr] = NULL;
 	}
@@ -2626,7 +2509,7 @@ not_determinist:
  */
 static int
 xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
-	                 int to, xmlRegAtomPtr atom) {
+	                int fromnr, int tonr, xmlRegAtomPtr atom) {
     int ret = 1;
     int res;
     int transnr, nbTrans;
@@ -2651,22 +2534,23 @@ xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
 	/*
 	 * check transitions conflicting with the one looked at
 	 */
+        if ((t1->to < 0) || (t1->to == fromnr))
+            continue;
 	if (t1->atom == NULL) {
-	    if (t1->to < 0)
-		continue;
 	    state->markd = XML_REGEXP_MARK_VISITED;
 	    res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
-		                           to, atom);
+		                          fromnr, tonr, atom);
 	    if (res == 0) {
 	        ret = 0;
 		/* t1->nd = 1; */
 	    }
 	    continue;
 	}
-	if (t1->to != to)
-	    continue;
 	if (xmlFACompareAtoms(t1->atom, atom, deep)) {
-	    ret = 0;
+            /* Treat equal transitions as deterministic. */
+            if ((t1->to != tonr) ||
+                (!xmlFAEqualAtoms(t1->atom, atom, deep)))
+                ret = 0;
 	    /* mark the transition as non-deterministic */
 	    t1->nd = 1;
 	}
@@ -2715,10 +2599,6 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
     int ret = 1;
     int deep = 1;
 
-#ifdef DEBUG_REGEXP_GRAPH
-    printf("xmlFAComputesDeterminism\n");
-    xmlRegPrintCtxt(stdout, ctxt);
-#endif
     if (ctxt->determinist != -1)
 	return(ctxt->determinist);
 
@@ -2744,11 +2624,11 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
 		/* t1->nd = 1; */
 		continue;
 	    }
-	    if (t1->to == -1) /* eliminated */
+	    if (t1->to < 0) /* eliminated */
 		continue;
 	    for (i = 0;i < transnr;i++) {
 		t2 = &(state->trans[i]);
-		if (t2->to == -1) /* eliminated */
+		if (t2->to < 0) /* eliminated */
 		    continue;
 		if (t2->atom != NULL) {
 		    if (t1->to == t2->to) {
@@ -2786,11 +2666,11 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
 	    if (t1->atom == NULL) {
 		continue;
 	    }
-	    if (t1->to == -1) /* eliminated */
+	    if (t1->to < 0) /* eliminated */
 		continue;
 	    for (i = 0;i < transnr;i++) {
 		t2 = &(state->trans[i]);
-		if (t2->to == -1) /* eliminated */
+		if (t2->to < 0) /* eliminated */
 		    continue;
 		if (t2->atom != NULL) {
                     /*
@@ -2798,29 +2678,39 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
                      * find transitions which indicate a conflict
                      */
 		    if (xmlFACompareAtoms(t1->atom, t2->atom, 1)) {
-			ret = 0;
+                        /*
+                         * Treat equal counter transitions that couldn't be
+                         * eliminated as deterministic.
+                         */
+                        if ((t1->to != t2->to) ||
+                            (t1->counter == t2->counter) ||
+                            (!xmlFAEqualAtoms(t1->atom, t2->atom, deep)))
+                            ret = 0;
 			/* mark the transitions as non-deterministic ones */
 			t1->nd = 1;
 			t2->nd = 1;
 			last = t1;
 		    }
-		} else if (t1->to != -1) {
+		} else {
+                    int res;
+
 		    /*
 		     * do the closure in case of remaining specific
 		     * epsilon transitions like choices or all
 		     */
-		    ret = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
-						   t2->to, t2->atom);
-                    xmlFAFinishRecurseDeterminism(ctxt, ctxt->states[t1->to]);
+		    res = xmlFARecurseDeterminism(ctxt, ctxt->states[t2->to],
+						  statenr, t1->to, t1->atom);
+                    xmlFAFinishRecurseDeterminism(ctxt, ctxt->states[t2->to]);
 		    /* don't shortcut the computation so all non deterministic
 		       transition get marked down
 		    if (ret == 0)
 			return(0);
 		     */
-		    if (ret == 0) {
+		    if (res == 0) {
 			t1->nd = 1;
 			/* t2->nd = 1; */
 			last = t1;
+                        ret = 0;
 		    }
 		}
 	    }
@@ -3139,33 +3029,11 @@ xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint) {
  *									*
  ************************************************************************/
 
-#ifdef DEBUG_REGEXP_EXEC
-static void
-xmlFARegDebugExec(xmlRegExecCtxtPtr exec) {
-    printf("state: %d:%d:idx %d", exec->state->no, exec->transno, exec->index);
-    if (exec->inputStack != NULL) {
-	int i;
-	printf(": ");
-	for (i = 0;(i < 3) && (i < exec->inputStackNr);i++)
-	    printf("%s ", (const char *)
-	           exec->inputStack[exec->inputStackNr - (i + 1)].value);
-    } else {
-	printf(": %s", &(exec->inputString[exec->index]));
-    }
-    printf("\n");
-}
-#endif
-
 static void
 xmlFARegExecSave(xmlRegExecCtxtPtr exec) {
-#ifdef DEBUG_REGEXP_EXEC
-    printf("saving ");
-    exec->transno++;
-    xmlFARegDebugExec(exec);
-    exec->transno--;
-#endif
 #ifdef MAX_PUSH
     if (exec->nbPush > MAX_PUSH) {
+        exec->status = XML_REGEXP_INTERNAL_LIMIT;
         return;
     }
     exec->nbPush++;
@@ -3176,8 +3044,8 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) {
 	exec->rollbacks = (xmlRegExecRollback *) xmlMalloc(exec->maxRollbacks *
 		                             sizeof(xmlRegExecRollback));
 	if (exec->rollbacks == NULL) {
-	    xmlRegexpErrMemory(NULL, "saving regexp");
 	    exec->maxRollbacks = 0;
+            exec->status = XML_REGEXP_OUT_OF_MEMORY;
 	    return;
 	}
 	memset(exec->rollbacks, 0,
@@ -3190,8 +3058,8 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) {
 	tmp = (xmlRegExecRollback *) xmlRealloc(exec->rollbacks,
 			exec->maxRollbacks * sizeof(xmlRegExecRollback));
 	if (tmp == NULL) {
-	    xmlRegexpErrMemory(NULL, "saving regexp");
 	    exec->maxRollbacks /= 2;
+            exec->status = XML_REGEXP_OUT_OF_MEMORY;
 	    return;
 	}
 	exec->rollbacks = tmp;
@@ -3206,8 +3074,7 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) {
 	    exec->rollbacks[exec->nbRollbacks].counts = (int *)
 		xmlMalloc(exec->comp->nbCounters * sizeof(int));
 	    if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
-		xmlRegexpErrMemory(NULL, "saving regexp");
-		exec->status = -5;
+		exec->status = XML_REGEXP_OUT_OF_MEMORY;
 		return;
 	    }
 	}
@@ -3219,11 +3086,10 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) {
 
 static void
 xmlFARegExecRollBack(xmlRegExecCtxtPtr exec) {
+    if (exec->status != XML_REGEXP_OK)
+        return;
     if (exec->nbRollbacks <= 0) {
-	exec->status = -1;
-#ifdef DEBUG_REGEXP_EXEC
-	printf("rollback failed on empty stack\n");
-#endif
+	exec->status = XML_REGEXP_NOT_FOUND;
 	return;
     }
     exec->nbRollbacks--;
@@ -3233,7 +3099,7 @@ xmlFARegExecRollBack(xmlRegExecCtxtPtr exec) {
     if (exec->comp->nbCounters > 0) {
 	if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
 	    fprintf(stderr, "exec save: allocation failed");
-	    exec->status = -6;
+	    exec->status = XML_REGEXP_INTERNAL_ERROR;
 	    return;
 	}
 	if (exec->counts) {
@@ -3241,11 +3107,6 @@ xmlFARegExecRollBack(xmlRegExecCtxtPtr exec) {
 	       exec->comp->nbCounters * sizeof(int));
 	}
     }
-
-#ifdef DEBUG_REGEXP_EXEC
-    printf("restored ");
-    xmlFARegDebugExec(exec);
-#endif
 }
 
 /************************************************************************
@@ -3267,7 +3128,7 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
     exec->maxRollbacks = 0;
     exec->nbRollbacks = 0;
     exec->rollbacks = NULL;
-    exec->status = 0;
+    exec->status = XML_REGEXP_OK;
     exec->comp = comp;
     exec->state = comp->states[0];
     exec->transno = 0;
@@ -3277,13 +3138,12 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
     if (comp->nbCounters > 0) {
 	exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int));
 	if (exec->counts == NULL) {
-	    xmlRegexpErrMemory(NULL, "running regexp");
-	    return(-1);
+	    return(XML_REGEXP_OUT_OF_MEMORY);
 	}
         memset(exec->counts, 0, comp->nbCounters * sizeof(int));
     } else
 	exec->counts = NULL;
-    while ((exec->status == 0) && (exec->state != NULL) &&
+    while ((exec->status == XML_REGEXP_OK) && (exec->state != NULL) &&
 	   ((exec->inputString[exec->index] != 0) ||
 	    ((exec->state != NULL) &&
 	     (exec->state->type != XML_REGEXP_FINAL_STATE)))) {
@@ -3327,7 +3187,7 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
 		xmlRegCounterPtr counter;
 
 		if (exec->counts == NULL) {
-		    exec->status = -1;
+		    exec->status = XML_REGEXP_INTERNAL_ERROR;
 		    goto error;
 		}
 		/*
@@ -3336,19 +3196,21 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
 
 		count = exec->counts[trans->count];
 		counter = &exec->comp->counters[trans->count];
-#ifdef DEBUG_REGEXP_EXEC
-		printf("testing count %d: val %d, min %d, max %d\n",
-		       trans->count, count, counter->min,  counter->max);
-#endif
 		ret = ((count >= counter->min) && (count <= counter->max));
 		if ((ret) && (counter->min != counter->max))
 		    deter = 0;
 	    } else if (atom == NULL) {
 		fprintf(stderr, "epsilon transition left at runtime\n");
-		exec->status = -2;
+		exec->status = XML_REGEXP_INTERNAL_ERROR;
 		break;
 	    } else if (exec->inputString[exec->index] != 0) {
-                codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), len);
+                len = 4;
+                codepoint = xmlGetUTF8Char(&exec->inputString[exec->index],
+                                           &len);
+                if (codepoint < 0) {
+                    exec->status = XML_REGEXP_INVALID_UTF8;
+                    goto error;
+                }
 		ret = xmlRegCheckCharacter(atom, codepoint);
 		if ((ret == 1) && (atom->min >= 0) && (atom->max > 0)) {
 		    xmlRegStatePtr to = comp->states[trans->to];
@@ -3365,7 +3227,7 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
 			if ((exec->counts == NULL) ||
 			    (exec->comp == NULL) ||
 			    (exec->comp->counters == NULL)) {
-			    exec->status = -1;
+			    exec->status = XML_REGEXP_INTERNAL_ERROR;
 			    goto error;
 			}
 			counter = &exec->comp->counters[trans->counter];
@@ -3375,11 +3237,10 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
                     /* Save before incrementing */
 		    if (exec->state->nbTrans > exec->transno + 1) {
 			xmlFARegExecSave(exec);
+                        if (exec->status != XML_REGEXP_OK)
+                            goto error;
 		    }
 		    if (trans->counter >= 0) {
-#ifdef DEBUG_REGEXP_EXEC
-			printf("Increasing count %d\n", trans->counter);
-#endif
 			exec->counts[trans->counter]++;
 		    }
 		    exec->transcount = 1;
@@ -3408,11 +3269,18 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
 			    exec->transno = -1; /* trick */
 			    exec->state = to;
 			    xmlFARegExecSave(exec);
+                            if (exec->status != XML_REGEXP_OK)
+                                goto error;
 			    exec->transno = transno;
 			    exec->state = state;
 			}
-			codepoint = CUR_SCHAR(&(exec->inputString[exec->index]),
-				              len);
+                        len = 4;
+                        codepoint = xmlGetUTF8Char(
+                                &exec->inputString[exec->index], &len);
+                        if (codepoint < 0) {
+                            exec->status = XML_REGEXP_INVALID_UTF8;
+                            goto error;
+                        }
 			ret = xmlRegCheckCharacter(atom, codepoint);
 			exec->transcount++;
 		    } while (ret == 1);
@@ -3430,12 +3298,9 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
 		    }
 		    if (trans->counter >= 0) {
 			if (exec->counts == NULL) {
-			    exec->status = -1;
+			    exec->status = XML_REGEXP_INTERNAL_ERROR;
 			    goto error;
 			}
-#ifdef DEBUG_REGEXP_EXEC
-			printf("Decreasing count %d\n", trans->counter);
-#endif
 			exec->counts[trans->counter]--;
 		    }
 		} else if ((ret == 0) && (atom->min == 0) && (atom->max > 0)) {
@@ -3458,15 +3323,9 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
 		if ((trans->nd == 1) ||
 		    ((trans->count >= 0) && (deter == 0) &&
 		     (exec->state->nbTrans > exec->transno + 1))) {
-#ifdef DEBUG_REGEXP_EXEC
-		    if (trans->nd == 1)
-		        printf("Saving on nd transition atom %d for %c at %d\n",
-			       trans->atom->no, codepoint, exec->index);
-		    else
-		        printf("Saving on counted transition count %d for %c at %d\n",
-			       trans->count, codepoint, exec->index);
-#endif
 		    xmlFARegExecSave(exec);
+                    if (exec->status != XML_REGEXP_OK)
+                        goto error;
 		}
 		if (trans->counter >= 0) {
 		    xmlRegCounterPtr counter;
@@ -3475,32 +3334,22 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
 		    if ((exec->counts == NULL) ||
 			(exec->comp == NULL) ||
 			(exec->comp->counters == NULL)) {
-			exec->status = -1;
+			exec->status = XML_REGEXP_INTERNAL_ERROR;
 			goto error;
 		    }
 		    counter = &exec->comp->counters[trans->counter];
 		    if (exec->counts[trans->counter] >= counter->max)
 			continue; /* for loop on transitions */
-#ifdef DEBUG_REGEXP_EXEC
-		    printf("Increasing count %d\n", trans->counter);
-#endif
 		    exec->counts[trans->counter]++;
 		}
 		if ((trans->count >= 0) &&
 		    (trans->count < REGEXP_ALL_COUNTER)) {
 		    if (exec->counts == NULL) {
-		        exec->status = -1;
+		        exec->status = XML_REGEXP_INTERNAL_ERROR;
 			goto error;
 		    }
-#ifdef DEBUG_REGEXP_EXEC
-		    printf("resetting count %d on transition\n",
-		           trans->count);
-#endif
 		    exec->counts[trans->count] = 0;
 		}
-#ifdef DEBUG_REGEXP_EXEC
-		printf("entering state %d\n", trans->to);
-#endif
 		exec->state = comp->states[trans->to];
 		exec->transno = 0;
 		if (trans->atom != NULL) {
@@ -3508,7 +3357,7 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
 		}
 		goto progress;
 	    } else if (ret < 0) {
-		exec->status = -4;
+		exec->status = XML_REGEXP_INTERNAL_ERROR;
 		break;
 	    }
 	}
@@ -3518,10 +3367,6 @@ rollback:
 	     * Failed to find a way out
 	     */
 	    exec->determinist = 0;
-#ifdef DEBUG_REGEXP_EXEC
-	    printf("rollback from state %d on %d:%c\n", exec->state->no,
-	           codepoint,codepoint);
-#endif
 	    xmlFARegExecRollBack(exec);
 	}
 progress:
@@ -3539,16 +3384,13 @@ error:
 	xmlFree(exec->rollbacks);
     }
     if (exec->state == NULL)
-        return(-1);
+        return(XML_REGEXP_INTERNAL_ERROR);
     if (exec->counts != NULL)
 	xmlFree(exec->counts);
-    if (exec->status == 0)
+    if (exec->status == XML_REGEXP_OK)
 	return(1);
-    if (exec->status == -1) {
-	if (exec->nbPush > MAX_PUSH)
-	    return(-1);
+    if (exec->status == XML_REGEXP_NOT_FOUND)
 	return(0);
-    }
     return(exec->status);
 }
 
@@ -3557,9 +3399,6 @@ error:
  *	Progressive interface to the verifier one atom at a time	*
  *									*
  ************************************************************************/
-#ifdef DEBUG_ERR
-static void testerr(xmlRegExecCtxtPtr exec);
-#endif
 
 /**
  * xmlRegNewExecCtxt:
@@ -3581,10 +3420,8 @@ xmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) {
     if ((comp->compact == NULL) && (comp->states == NULL))
         return(NULL);
     exec = (xmlRegExecCtxtPtr) xmlMalloc(sizeof(xmlRegExecCtxt));
-    if (exec == NULL) {
-	xmlRegexpErrMemory(NULL, "creating execution context");
+    if (exec == NULL)
 	return(NULL);
-    }
     memset(exec, 0, sizeof(xmlRegExecCtxt));
     exec->inputString = NULL;
     exec->index = 0;
@@ -3592,7 +3429,7 @@ xmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) {
     exec->maxRollbacks = 0;
     exec->nbRollbacks = 0;
     exec->rollbacks = NULL;
-    exec->status = 0;
+    exec->status = XML_REGEXP_OK;
     exec->comp = comp;
     if (comp->compact == NULL)
 	exec->state = comp->states[0];
@@ -3608,7 +3445,6 @@ xmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) {
 	exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int)
 	                                 * 2);
 	if (exec->counts == NULL) {
-	    xmlRegexpErrMemory(NULL, "creating execution context");
 	    xmlFree(exec);
 	    return(NULL);
 	}
@@ -3664,19 +3500,32 @@ xmlRegFreeExecCtxt(xmlRegExecCtxtPtr exec) {
     xmlFree(exec);
 }
 
+static int
+xmlRegExecSetErrString(xmlRegExecCtxtPtr exec, const xmlChar *value) {
+    if (exec->errString != NULL)
+        xmlFree(exec->errString);
+    if (value == NULL) {
+        exec->errString = NULL;
+    } else {
+        exec->errString = xmlStrdup(value);
+        if (exec->errString == NULL) {
+            exec->status = XML_REGEXP_OUT_OF_MEMORY;
+            return(-1);
+        }
+    }
+    return(0);
+}
+
 static void
 xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value,
 	                    void *data) {
-#ifdef DEBUG_PUSH
-    printf("saving value: %d:%s\n", exec->inputStackNr, value);
-#endif
     if (exec->inputStackMax == 0) {
 	exec->inputStackMax = 4;
 	exec->inputStack = (xmlRegInputTokenPtr)
 	    xmlMalloc(exec->inputStackMax * sizeof(xmlRegInputToken));
 	if (exec->inputStack == NULL) {
-	    xmlRegexpErrMemory(NULL, "pushing input string");
 	    exec->inputStackMax = 0;
+            exec->status = XML_REGEXP_OUT_OF_MEMORY;
 	    return;
 	}
     } else if (exec->inputStackNr + 1 >= exec->inputStackMax) {
@@ -3686,13 +3535,21 @@ xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value,
 	tmp = (xmlRegInputTokenPtr) xmlRealloc(exec->inputStack,
 			exec->inputStackMax * sizeof(xmlRegInputToken));
 	if (tmp == NULL) {
-	    xmlRegexpErrMemory(NULL, "pushing input string");
 	    exec->inputStackMax /= 2;
+            exec->status = XML_REGEXP_OUT_OF_MEMORY;
 	    return;
 	}
 	exec->inputStack = tmp;
     }
-    exec->inputStack[exec->inputStackNr].value = xmlStrdup(value);
+    if (value == NULL) {
+        exec->inputStack[exec->inputStackNr].value = NULL;
+    } else {
+        exec->inputStack[exec->inputStackNr].value = xmlStrdup(value);
+        if (exec->inputStack[exec->inputStackNr].value == NULL) {
+            exec->status = XML_REGEXP_OUT_OF_MEMORY;
+            return;
+        }
+    }
     exec->inputStack[exec->inputStackNr].data = data;
     exec->inputStackNr++;
     exec->inputStack[exec->inputStackNr].value = NULL;
@@ -3782,10 +3639,6 @@ xmlRegCompactPushString(xmlRegExecCtxtPtr exec,
 	return(0);
     }
 
-#ifdef DEBUG_PUSH
-    printf("value pushed: %s\n", value);
-#endif
-
     /*
      * Examine all outside transitions from current state
      */
@@ -3799,9 +3652,6 @@ xmlRegCompactPushString(xmlRegExecCtxtPtr exec,
 		    exec->callback(exec->data, value,
 			  comp->transdata[state * comp->nbstrings + i], data);
 		}
-#ifdef DEBUG_PUSH
-		printf("entering state %d\n", target);
-#endif
 		if (comp->compact[target * (comp->nbstrings + 1)] ==
 		    XML_REGEXP_SINK_STATE)
 		    goto error;
@@ -3817,19 +3667,11 @@ xmlRegCompactPushString(xmlRegExecCtxtPtr exec,
      * Failed to find an exit transition out from current state for the
      * current token
      */
-#ifdef DEBUG_PUSH
-    printf("failed to find a transition for %s on state %d\n", value, state);
-#endif
 error:
-    if (exec->errString != NULL)
-        xmlFree(exec->errString);
-    exec->errString = xmlStrdup(value);
     exec->errStateNo = state;
-    exec->status = -1;
-#ifdef DEBUG_ERR
-    testerr(exec);
-#endif
-    return(-1);
+    exec->status = XML_REGEXP_NOT_FOUND;
+    xmlRegExecSetErrString(exec, value);
+    return(exec->status);
 }
 
 /**
@@ -3857,7 +3699,7 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
 	return(-1);
     if (exec->comp == NULL)
 	return(-1);
-    if (exec->status != 0)
+    if (exec->status != XML_REGEXP_OK)
 	return(exec->status);
 
     if (exec->comp->compact != NULL)
@@ -3869,9 +3711,6 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
 	final = 1;
     }
 
-#ifdef DEBUG_PUSH
-    printf("value pushed: %s\n", value);
-#endif
     /*
      * If we have an active rollback stack push the new value there
      * and get back to where we were left
@@ -3880,12 +3719,9 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
 	xmlFARegExecSaveInputString(exec, value, data);
 	value = exec->inputStack[exec->index].value;
 	data = exec->inputStack[exec->index].data;
-#ifdef DEBUG_PUSH
-	printf("value loaded: %s\n", value);
-#endif
     }
 
-    while ((exec->status == 0) &&
+    while ((exec->status == XML_REGEXP_OK) &&
 	   ((value != NULL) ||
 	    ((final == 1) &&
 	     (exec->state->type != XML_REGEXP_FINAL_STATE)))) {
@@ -3913,9 +3749,6 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
 
 		ret = 0;
 
-#ifdef DEBUG_PUSH
-		printf("testing all lax %d\n", trans->count);
-#endif
 		/*
 		 * Check all counted transitions from the current state
 		 */
@@ -3951,9 +3784,6 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
 
 		ret = 1;
 
-#ifdef DEBUG_PUSH
-		printf("testing all %d\n", trans->count);
-#endif
 		/*
 		 * Check all counted transitions from the current state
 		 */
@@ -3978,14 +3808,10 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
 
 		count = exec->counts[trans->count];
 		counter = &exec->comp->counters[trans->count];
-#ifdef DEBUG_PUSH
-		printf("testing count %d: val %d, min %d, max %d\n",
-		       trans->count, count, counter->min,  counter->max);
-#endif
 		ret = ((count >= counter->min) && (count <= counter->max));
 	    } else if (atom == NULL) {
 		fprintf(stderr, "epsilon transition left at runtime\n");
-		exec->status = -2;
+		exec->status = XML_REGEXP_INTERNAL_ERROR;
 		break;
 	    } else if (value != NULL) {
 		ret = xmlRegStrEqualWildcard(atom->valuep, value);
@@ -4027,9 +3853,6 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
 			exec->index++;
 			value = exec->inputStack[exec->index].value;
 			data = exec->inputStack[exec->index].data;
-#ifdef DEBUG_PUSH
-			printf("value loaded: %s\n", value);
-#endif
 
 			/*
 			 * End of input: stop here
@@ -4084,22 +3907,12 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
 		    xmlFARegExecSave(exec);
 		}
 		if (trans->counter >= 0) {
-#ifdef DEBUG_PUSH
-		    printf("Increasing count %d\n", trans->counter);
-#endif
 		    exec->counts[trans->counter]++;
 		}
 		if ((trans->count >= 0) &&
 		    (trans->count < REGEXP_ALL_COUNTER)) {
-#ifdef DEBUG_REGEXP_EXEC
-		    printf("resetting count %d on transition\n",
-		           trans->count);
-#endif
 		    exec->counts[trans->count] = 0;
 		}
-#ifdef DEBUG_PUSH
-		printf("entering state %d\n", trans->to);
-#endif
                 if ((exec->comp->states[trans->to] != NULL) &&
 		    (exec->comp->states[trans->to]->type ==
 		     XML_REGEXP_SINK_STATE)) {
@@ -4107,9 +3920,8 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
 		     * entering a sink state, save the current state as error
 		     * state.
 		     */
-		    if (exec->errString != NULL)
-			xmlFree(exec->errString);
-		    exec->errString = xmlStrdup(value);
+                    if (xmlRegExecSetErrString(exec, value) < 0)
+                        break;
 		    exec->errState = exec->state;
 		    memcpy(exec->errCounts, exec->counts,
 			   exec->comp->nbCounters * sizeof(int));
@@ -4122,27 +3934,18 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
 			if (exec->index < exec->inputStackNr) {
 			    value = exec->inputStack[exec->index].value;
 			    data = exec->inputStack[exec->index].data;
-#ifdef DEBUG_PUSH
-			    printf("value loaded: %s\n", value);
-#endif
 			} else {
 			    value = NULL;
 			    data = NULL;
-#ifdef DEBUG_PUSH
-			    printf("end of input\n");
-#endif
 			}
 		    } else {
 			value = NULL;
 			data = NULL;
-#ifdef DEBUG_PUSH
-			printf("end of input\n");
-#endif
 		    }
 		}
 		goto progress;
 	    } else if (ret < 0) {
-		exec->status = -4;
+		exec->status = XML_REGEXP_INTERNAL_ERROR;
 		break;
 	    }
 	}
@@ -4155,9 +3958,8 @@ rollback:
 	    if ((progress) && (exec->state != NULL) &&
 	        (exec->state->type != XML_REGEXP_SINK_STATE)) {
 	        progress = 0;
-		if (exec->errString != NULL)
-		    xmlFree(exec->errString);
-		exec->errString = xmlStrdup(value);
+                if (xmlRegExecSetErrString(exec, value) < 0)
+                    break;
 		exec->errState = exec->state;
                 if (exec->comp->nbCounters)
                     memcpy(exec->errCounts, exec->counts,
@@ -4169,12 +3971,10 @@ rollback:
 	     */
 	    exec->determinist = 0;
 	    xmlFARegExecRollBack(exec);
-	    if ((exec->inputStack != NULL ) && (exec->status == 0)) {
+	    if ((exec->inputStack != NULL ) &&
+                (exec->status == XML_REGEXP_OK)) {
 		value = exec->inputStack[exec->index].value;
 		data = exec->inputStack[exec->index].data;
-#ifdef DEBUG_PUSH
-		printf("value loaded: %s\n", value);
-#endif
 	    }
 	}
 	continue;
@@ -4182,14 +3982,9 @@ progress:
         progress = 1;
 	continue;
     }
-    if (exec->status == 0) {
+    if (exec->status == XML_REGEXP_OK) {
         return(exec->state->type == XML_REGEXP_FINAL_STATE);
     }
-#ifdef DEBUG_ERR
-    if (exec->status < 0) {
-	testerr(exec);
-    }
-#endif
     return(exec->status);
 }
 
@@ -4233,7 +4028,7 @@ xmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value,
 	return(-1);
     if (exec->comp == NULL)
 	return(-1);
-    if (exec->status != 0)
+    if (exec->status != XML_REGEXP_OK)
 	return(exec->status);
 
     if (value2 == NULL)
@@ -4245,7 +4040,7 @@ xmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value,
     if (150 < lenn + lenp + 2) {
 	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
 	if (str == NULL) {
-	    exec->status = -1;
+	    exec->status = XML_REGEXP_OUT_OF_MEMORY;
 	    return(-1);
 	}
     } else {
@@ -4362,10 +4157,8 @@ xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
 		continue;
 	    if (trans->count == REGEXP_ALL_LAX_COUNTER) {
 	        /* this should not be reached but ... */
-	        TODO;
 	    } else if (trans->count == REGEXP_ALL_COUNTER) {
 	        /* this should not be reached but ... */
-	        TODO;
 	    } else if (trans->counter >= 0) {
 		xmlRegCounterPtr counter = NULL;
 		int count;
@@ -4474,7 +4267,7 @@ xmlRegExecErrInfo(xmlRegExecCtxtPtr exec, const xmlChar **string,
     if (exec == NULL)
         return(-1);
     if (string != NULL) {
-        if (exec->status != 0)
+        if (exec->status != XML_REGEXP_OK)
 	    *string = exec->errString;
 	else
 	    *string = NULL;
@@ -4482,17 +4275,6 @@ xmlRegExecErrInfo(xmlRegExecCtxtPtr exec, const xmlChar **string,
     return(xmlRegExecGetValues(exec, 1, nbval, nbneg, values, terminal));
 }
 
-#ifdef DEBUG_ERR
-static void testerr(xmlRegExecCtxtPtr exec) {
-    const xmlChar *string;
-    xmlChar *values[5];
-    int nb = 5;
-    int nbneg;
-    int terminal;
-    xmlRegExecErrInfo(exec, &string, &nb, &nbneg, &values[0], &terminal);
-}
-#endif
-
 #if 0
 static int
 xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) {
@@ -4503,10 +4285,10 @@ xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) {
 
     if (exec == NULL)
 	return(-1);
-    if (exec->status != 0)
+    if (exec->status != XML_REGEXP_OK)
 	return(exec->status);
 
-    while ((exec->status == 0) &&
+    while ((exec->status == XML_REGEXP_OK) &&
 	   ((exec->inputString[exec->index] != 0) ||
 	    (exec->state->type != XML_REGEXP_FINAL_STATE))) {
 
@@ -4535,14 +4317,10 @@ xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) {
 
 		count = exec->counts[trans->count];
 		counter = &exec->comp->counters[trans->count];
-#ifdef DEBUG_REGEXP_EXEC
-		printf("testing count %d: val %d, min %d, max %d\n",
-		       trans->count, count, counter->min,  counter->max);
-#endif
 		ret = ((count >= counter->min) && (count <= counter->max));
 	    } else if (atom == NULL) {
 		fprintf(stderr, "epsilon transition left at runtime\n");
-		exec->status = -2;
+		exec->status = XML_REGEXP_INTERNAL_ERROR;
 		break;
 	    } else if (exec->inputString[exec->index] != 0) {
                 codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), len);
@@ -4612,20 +4390,11 @@ xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) {
 		 * restart count for expressions like this ((abc){2})*
 		 */
 		if (trans->count >= 0) {
-#ifdef DEBUG_REGEXP_EXEC
-		    printf("Reset count %d\n", trans->count);
-#endif
 		    exec->counts[trans->count] = 0;
 		}
 		if (trans->counter >= 0) {
-#ifdef DEBUG_REGEXP_EXEC
-		    printf("Increasing count %d\n", trans->counter);
-#endif
 		    exec->counts[trans->counter]++;
 		}
-#ifdef DEBUG_REGEXP_EXEC
-		printf("entering state %d\n", trans->to);
-#endif
 		exec->state = exec->comp->states[trans->to];
 		exec->transno = 0;
 		if (trans->atom != NULL) {
@@ -4633,7 +4402,7 @@ xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) {
 		}
 		goto progress;
 	    } else if (ret < 0) {
-		exec->status = -4;
+		exec->status = XML_REGEXP_INTERNAL_ERROR;
 		break;
 	    }
 	}
@@ -4668,7 +4437,12 @@ xmlFAIsChar(xmlRegParserCtxtPtr ctxt) {
     int cur;
     int len;
 
-    cur = CUR_SCHAR(ctxt->cur, len);
+    len = 4;
+    cur = xmlGetUTF8Char(ctxt->cur, &len);
+    if (cur < 0) {
+        ERROR("Invalid UTF-8");
+        return(0);
+    }
     if ((cur == '.') || (cur == '\\') || (cur == '?') ||
 	(cur == '*') || (cur == '+') || (cur == '(') ||
 	(cur == ')') || (cur == '|') || (cur == 0x5B) ||
@@ -4886,17 +4660,24 @@ xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
 	}
 	type = XML_REGEXP_BLOCK_NAME;
 	blockName = xmlStrndup(start, ctxt->cur - start);
+        if (blockName == NULL)
+	    xmlRegexpErrMemory(ctxt);
     } else {
 	ERROR("Unknown char property");
 	return;
     }
     if (ctxt->atom == NULL) {
 	ctxt->atom = xmlRegNewAtom(ctxt, type);
-	if (ctxt->atom != NULL)
-	    ctxt->atom->valuep = blockName;
+        if (ctxt->atom == NULL) {
+            xmlFree(blockName);
+            return;
+        }
+	ctxt->atom->valuep = blockName;
     } else if (ctxt->atom->type == XML_REGEXP_RANGES) {
-        xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
-		           type, 0, 0, blockName);
+        if (xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
+                               type, 0, 0, blockName) == NULL) {
+            xmlFree(blockName);
+        }
     }
 }
 
@@ -5151,7 +4932,12 @@ xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) {
 	end = start;
         len = 1;
     } else if ((cur != 0x5B) && (cur != 0x5D)) {
-        end = start = CUR_SCHAR(ctxt->cur, len);
+        len = 4;
+        end = start = xmlGetUTF8Char(ctxt->cur, &len);
+        if (start < 0) {
+            ERROR("Invalid UTF-8");
+            return;
+        }
     } else {
 	ERROR("Expecting a char range");
 	return;
@@ -5190,7 +4976,12 @@ xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) {
 	}
         len = 1;
     } else if ((cur != '\0') && (cur != 0x5B) && (cur != 0x5D)) {
-        end = CUR_SCHAR(ctxt->cur, len);
+        len = 4;
+        end = xmlGetUTF8Char(ctxt->cur, &len);
+        if (end < 0) {
+            ERROR("Invalid UTF-8");
+            return;
+        }
     } else {
 	ERROR("Expecting the end of a char range");
 	return;
@@ -5405,7 +5196,12 @@ xmlFAParseAtom(xmlRegParserCtxtPtr ctxt) {
 	ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_CHARVAL);
 	if (ctxt->atom == NULL)
 	    return(-1);
-	codepoint = CUR_SCHAR(ctxt->cur, len);
+        len = 4;
+        codepoint = xmlGetUTF8Char(ctxt->cur, &len);
+        if (codepoint < 0) {
+            ERROR("Invalid UTF-8");
+            return(-1);
+        }
 	ctxt->atom->codepoint = codepoint;
 	NEXTL(len);
 	return(1);
@@ -5500,8 +5296,12 @@ xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr to) {
 	xmlFAGenerateEpsilonTransition(ctxt, previous, to);
     } else {
 	if (xmlFAGenerateTransitions(ctxt, previous,
-	        (CUR=='|' || CUR==')' || CUR==0) ? to : NULL, ctxt->atom) < 0)
+	        (CUR=='|' || CUR==')' || CUR==0) ? to : NULL,
+                ctxt->atom) < 0) {
+            xmlRegFreeAtom(ctxt->atom);
+            ctxt->atom = NULL;
 	    return(-1);
+        }
 	previous = ctxt->state;
 	ctxt->atom = NULL;
     }
@@ -5510,8 +5310,11 @@ xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr to) {
 	if (ret != 0) {
 	    if (xmlFAGenerateTransitions(ctxt, previous,
 	            (CUR=='|' || CUR==')' || CUR==0) ? to : NULL,
-                    ctxt->atom) < 0)
-		    return(-1);
+                    ctxt->atom) < 0) {
+                xmlRegFreeAtom(ctxt->atom);
+                ctxt->atom = NULL;
+                return(-1);
+            }
 	    previous = ctxt->state;
 	    ctxt->atom = NULL;
 	}
@@ -5535,9 +5338,6 @@ xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) {
     ctxt->end = NULL;
     xmlFAParseBranch(ctxt, NULL);
     if (top) {
-#ifdef DEBUG_REGEXP_GRAPH
-	printf("State %d is final\n", ctxt->state->no);
-#endif
 	ctxt->state->type = XML_REGEXP_FINAL_STATE;
     }
     if (CUR != '|') {
@@ -5612,27 +5412,30 @@ xmlRegexpPrint(FILE *output, xmlRegexpPtr regexp) {
  */
 xmlRegexpPtr
 xmlRegexpCompile(const xmlChar *regexp) {
-    xmlRegexpPtr ret;
+    xmlRegexpPtr ret = NULL;
     xmlRegParserCtxtPtr ctxt;
 
+    if (regexp == NULL)
+        return(NULL);
+
     ctxt = xmlRegNewParserCtxt(regexp);
     if (ctxt == NULL)
 	return(NULL);
 
     /* initialize the parser */
+    ctxt->state = xmlRegStatePush(ctxt);
+    if (ctxt->state == NULL)
+        goto error;
+    ctxt->start = ctxt->state;
     ctxt->end = NULL;
-    ctxt->start = ctxt->state = xmlRegNewState(ctxt);
-    xmlRegStatePush(ctxt, ctxt->start);
 
     /* parse the expression building an automata */
     xmlFAParseRegExp(ctxt, 1);
     if (CUR != 0) {
 	ERROR("xmlFAParseRegExp: extra characters");
     }
-    if (ctxt->error != 0) {
-	xmlRegFreeParserCtxt(ctxt);
-	return(NULL);
-    }
+    if (ctxt->error != 0)
+        goto error;
     ctxt->end = ctxt->state;
     ctxt->start->type = XML_REGEXP_START_STATE;
     ctxt->end->type = XML_REGEXP_FINAL_STATE;
@@ -5641,11 +5444,11 @@ xmlRegexpCompile(const xmlChar *regexp) {
     xmlFAEliminateEpsilonTransitions(ctxt);
 
 
-    if (ctxt->error != 0) {
-	xmlRegFreeParserCtxt(ctxt);
-	return(NULL);
-    }
+    if (ctxt->error != 0)
+        goto error;
     ret = xmlRegEpxFromParse(ctxt);
+
+error:
     xmlRegFreeParserCtxt(ctxt);
     return(ret);
 }
@@ -5770,18 +5573,15 @@ xmlNewAutomata(void) {
 	return(NULL);
 
     /* initialize the parser */
-    ctxt->end = NULL;
-    ctxt->start = ctxt->state = xmlRegNewState(ctxt);
-    if (ctxt->start == NULL) {
+    ctxt->state = xmlRegStatePush(ctxt);
+    if (ctxt->state == NULL) {
 	xmlFreeAutomata(ctxt);
 	return(NULL);
     }
+    ctxt->start = ctxt->state;
+    ctxt->end = NULL;
+
     ctxt->start->type = XML_REGEXP_START_STATE;
-    if (xmlRegStatePush(ctxt, ctxt->start) < 0) {
-        xmlRegFreeState(ctxt->start);
-	xmlFreeAutomata(ctxt);
-	return(NULL);
-    }
     ctxt->flags = 0;
 
     return(ctxt);
@@ -5873,6 +5673,11 @@ xmlAutomataNewTransition(xmlAutomataPtr am, xmlAutomataStatePtr from,
         return(NULL);
     atom->data = data;
     atom->valuep = xmlStrdup(token);
+    if (atom->valuep == NULL) {
+        xmlRegFreeAtom(atom);
+        xmlRegexpErrMemory(am);
+        return(NULL);
+    }
 
     if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
         xmlRegFreeAtom(atom);
@@ -6044,6 +5849,8 @@ xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
 	return(NULL);
     if ((token2 == NULL) || (*token2 == 0)) {
 	atom->valuep = xmlStrdup(token);
+        if (atom->valuep == NULL)
+            goto error;
     } else {
 	int lenn, lenp;
 	xmlChar *str;
@@ -6052,10 +5859,8 @@ xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
 	lenp = strlen((char *) token);
 
 	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
-	if (str == NULL) {
-	    xmlRegFreeAtom(atom);
-	    return(NULL);
-	}
+	if (str == NULL)
+	    goto error;
 	memcpy(&str[0], token, lenp);
 	str[lenp] = '|';
 	memcpy(&str[lenp + 1], token2, lenn);
@@ -6074,16 +5879,20 @@ xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
      * associate a counter to the transition.
      */
     counter = xmlRegGetCounter(am);
+    if (counter < 0)
+        goto error;
     am->counters[counter].min = min;
     am->counters[counter].max = max;
 
     /* xmlFAGenerateTransitions(am, from, to, atom); */
     if (to == NULL) {
-        to = xmlRegNewState(am);
-	xmlRegStatePush(am, to);
+	to = xmlRegStatePush(am);
+        if (to == NULL)
+            goto error;
     }
     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
-    xmlRegAtomPush(am, atom);
+    if (xmlRegAtomPush(am, atom) < 0)
+        goto error;
     am->state = to;
 
     if (to == NULL)
@@ -6093,6 +5902,10 @@ xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
     if (min == 0)
 	xmlFAGenerateEpsilonTransition(am, from, to);
     return(to);
+
+error:
+    xmlRegFreeAtom(atom);
+    return(NULL);
 }
 
 /**
@@ -6129,6 +5942,8 @@ xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
     if (atom == NULL)
 	return(NULL);
     atom->valuep = xmlStrdup(token);
+    if (atom->valuep == NULL)
+        goto error;
     atom->data = data;
     if (min == 0)
 	atom->min = 1;
@@ -6140,16 +5955,20 @@ xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
      * associate a counter to the transition.
      */
     counter = xmlRegGetCounter(am);
+    if (counter < 0)
+        goto error;
     am->counters[counter].min = min;
     am->counters[counter].max = max;
 
     /* xmlFAGenerateTransitions(am, from, to, atom); */
     if (to == NULL) {
-        to = xmlRegNewState(am);
-	xmlRegStatePush(am, to);
+	to = xmlRegStatePush(am);
+        if (to == NULL)
+            goto error;
     }
     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
-    xmlRegAtomPush(am, atom);
+    if (xmlRegAtomPush(am, atom) < 0)
+        goto error;
     am->state = to;
 
     if (to == NULL)
@@ -6159,6 +5978,10 @@ xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
     if (min == 0)
 	xmlFAGenerateEpsilonTransition(am, from, to);
     return(to);
+
+error:
+    xmlRegFreeAtom(atom);
+    return(NULL);
 }
 
 /**
@@ -6199,6 +6022,8 @@ xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
 	return(NULL);
     if ((token2 == NULL) || (*token2 == 0)) {
 	atom->valuep = xmlStrdup(token);
+        if (atom->valuep == NULL)
+            goto error;
     } else {
 	int lenn, lenp;
 	xmlChar *str;
@@ -6207,10 +6032,8 @@ xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
 	lenp = strlen((char *) token);
 
 	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
-	if (str == NULL) {
-	    xmlRegFreeAtom(atom);
-	    return(NULL);
-	}
+	if (str == NULL)
+	    goto error;
 	memcpy(&str[0], token, lenp);
 	str[lenp] = '|';
 	memcpy(&str[lenp + 1], token2, lenn);
@@ -6226,18 +6049,26 @@ xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
      * associate a counter to the transition.
      */
     counter = xmlRegGetCounter(am);
+    if (counter < 0)
+        goto error;
     am->counters[counter].min = 1;
     am->counters[counter].max = 1;
 
     /* xmlFAGenerateTransitions(am, from, to, atom); */
     if (to == NULL) {
-	to = xmlRegNewState(am);
-	xmlRegStatePush(am, to);
+	to = xmlRegStatePush(am);
+        if (to == NULL)
+            goto error;
     }
     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
-    xmlRegAtomPush(am, atom);
+    if (xmlRegAtomPush(am, atom) < 0)
+        goto error;
     am->state = to;
     return(to);
+
+error:
+    xmlRegFreeAtom(atom);
+    return(NULL);
 }
 
 
@@ -6285,18 +6116,26 @@ xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
      * associate a counter to the transition.
      */
     counter = xmlRegGetCounter(am);
+    if (counter < 0)
+        goto error;
     am->counters[counter].min = 1;
     am->counters[counter].max = 1;
 
     /* xmlFAGenerateTransitions(am, from, to, atom); */
     if (to == NULL) {
-	to = xmlRegNewState(am);
-	xmlRegStatePush(am, to);
+	to = xmlRegStatePush(am);
+        if (to == NULL)
+            goto error;
     }
     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
-    xmlRegAtomPush(am, atom);
+    if (xmlRegAtomPush(am, atom) < 0)
+        goto error;
     am->state = to;
     return(to);
+
+error:
+    xmlRegFreeAtom(atom);
+    return(NULL);
 }
 
 /**
@@ -6309,13 +6148,9 @@ xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
  */
 xmlAutomataStatePtr
 xmlAutomataNewState(xmlAutomataPtr am) {
-    xmlAutomataStatePtr to;
-
     if (am == NULL)
 	return(NULL);
-    to = xmlRegNewState(am);
-    xmlRegStatePush(am, to);
-    return(to);
+    return(xmlRegStatePush(am));
 }
 
 /**
@@ -6454,6 +6289,8 @@ xmlAutomataCompile(xmlAutomataPtr am) {
 
     if ((am == NULL) || (am->error != 0)) return(NULL);
     xmlFAEliminateEpsilonTransitions(am);
+    if (am->error != 0)
+        return(NULL);
     /* xmlFAComputesDeterminism(am); */
     ret = xmlRegEpxFromParse(am);
 
@@ -6572,8 +6409,6 @@ xmlExpFreeCtxt(xmlExpCtxtPtr ctxt) {
  ************************************************************************/
 #define MAX_NODES 10000
 
-/* #define DEBUG_DERIV */
-
 /*
  * TODO:
  * - Wildcards
@@ -7248,14 +7083,8 @@ xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str)
 	    return(forbiddenExp);
 	case XML_EXP_ATOM:
 	    if (exp->exp_str == str) {
-#ifdef DEBUG_DERIV
-		printf("deriv atom: equal => Empty\n");
-#endif
 	        ret = emptyExp;
 	    } else {
-#ifdef DEBUG_DERIV
-		printf("deriv atom: mismatch => forbid\n");
-#endif
 	        /* TODO wildcards here */
 		ret = forbiddenExp;
 	    }
@@ -7263,9 +7092,6 @@ xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str)
 	case XML_EXP_OR: {
 	    xmlExpNodePtr tmp;
 
-#ifdef DEBUG_DERIV
-	    printf("deriv or: => or(derivs)\n");
-#endif
 	    tmp = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
 	    if (tmp == NULL) {
 		return(NULL);
@@ -7280,23 +7106,14 @@ xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str)
 	    return(ret);
 	}
 	case XML_EXP_SEQ:
-#ifdef DEBUG_DERIV
-	    printf("deriv seq: starting with left\n");
-#endif
 	    ret = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
 	    if (ret == NULL) {
 	        return(NULL);
 	    } else if (ret == forbiddenExp) {
 	        if (IS_NILLABLE(exp->exp_left)) {
-#ifdef DEBUG_DERIV
-		    printf("deriv seq: left failed but nillable\n");
-#endif
 		    ret = xmlExpStringDeriveInt(ctxt, exp->exp_right, str);
 		}
 	    } else {
-#ifdef DEBUG_DERIV
-		printf("deriv seq: left match => sequence\n");
-#endif
 	        exp->exp_right->ref++;
 	        ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, exp->exp_right,
 		                         NULL, 0, 0);
@@ -7312,9 +7129,6 @@ xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str)
 	    if (ret == NULL)
 	        return(NULL);
 	    if (ret == forbiddenExp) {
-#ifdef DEBUG_DERIV
-		printf("deriv count: pattern mismatch => forbid\n");
-#endif
 	        return(ret);
 	    }
 	    if (exp->exp_max == 1)
@@ -7331,14 +7145,8 @@ xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str)
 	    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left, NULL,
 				     NULL, min, max);
 	    if (ret == emptyExp) {
-#ifdef DEBUG_DERIV
-		printf("deriv count: match to empty => new count\n");
-#endif
 	        return(tmp);
 	    }
-#ifdef DEBUG_DERIV
-	    printf("deriv count: match => sequence with new count\n");
-#endif
 	    return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, tmp,
 	                              NULL, 0, 0));
 	}
@@ -7447,17 +7255,11 @@ xmlExpDivide(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub,
 	        *mult = tmp;
 	    else
 	        xmlExpFree(ctxt, tmp);
-#ifdef DEBUG_DERIV
-	    printf("Divide succeeded %d\n", i);
-#endif
 	    return(i);
 	}
 	xmlExpFree(ctxt, tmp);
 	xmlExpFree(ctxt, tmp2);
     }
-#ifdef DEBUG_DERIV
-    printf("Divide failed\n");
-#endif
     return(0);
 }
 
@@ -7483,25 +7285,16 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
      * amount, then the derivation is empty
      */
     if ((exp == sub) && (exp->c_max >= 0)) {
-#ifdef DEBUG_DERIV
-        printf("Equal(exp, sub) and finite -> Empty\n");
-#endif
         return(emptyExp);
     }
     /*
      * decompose sub sequence first
      */
     if (sub->type == XML_EXP_EMPTY) {
-#ifdef DEBUG_DERIV
-        printf("Empty(sub) -> Empty\n");
-#endif
 	exp->ref++;
         return(exp);
     }
     if (sub->type == XML_EXP_SEQ) {
-#ifdef DEBUG_DERIV
-        printf("Seq(sub) -> decompose\n");
-#endif
         tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left);
 	if (tmp == NULL)
 	    return(NULL);
@@ -7512,9 +7305,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 	return(ret);
     }
     if (sub->type == XML_EXP_OR) {
-#ifdef DEBUG_DERIV
-        printf("Or(sub) -> decompose\n");
-#endif
         tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left);
 	if (tmp == forbiddenExp)
 	    return(tmp);
@@ -7528,36 +7318,21 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 	return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, tmp, ret, NULL, 0, 0));
     }
     if (!xmlExpCheckCard(exp, sub)) {
-#ifdef DEBUG_DERIV
-        printf("CheckCard(exp, sub) failed -> Forbid\n");
-#endif
         return(forbiddenExp);
     }
     switch (exp->type) {
         case XML_EXP_EMPTY:
 	    if (sub == emptyExp)
 	        return(emptyExp);
-#ifdef DEBUG_DERIV
-	    printf("Empty(exp) -> Forbid\n");
-#endif
 	    return(forbiddenExp);
         case XML_EXP_FORBID:
-#ifdef DEBUG_DERIV
-	    printf("Forbid(exp) -> Forbid\n");
-#endif
 	    return(forbiddenExp);
         case XML_EXP_ATOM:
 	    if (sub->type == XML_EXP_ATOM) {
 	        /* TODO: handle wildcards */
 	        if (exp->exp_str == sub->exp_str) {
-#ifdef DEBUG_DERIV
-		    printf("Atom match -> Empty\n");
-#endif
 		    return(emptyExp);
                 }
-#ifdef DEBUG_DERIV
-		printf("Atom mismatch -> Forbid\n");
-#endif
 	        return(forbiddenExp);
 	    }
 	    if ((sub->type == XML_EXP_COUNT) &&
@@ -7565,32 +7340,17 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 	        (sub->exp_left->type == XML_EXP_ATOM)) {
 	        /* TODO: handle wildcards */
 	        if (exp->exp_str == sub->exp_left->exp_str) {
-#ifdef DEBUG_DERIV
-		    printf("Atom match -> Empty\n");
-#endif
 		    return(emptyExp);
 		}
-#ifdef DEBUG_DERIV
-		printf("Atom mismatch -> Forbid\n");
-#endif
 	        return(forbiddenExp);
 	    }
-#ifdef DEBUG_DERIV
-	    printf("Complex exp vs Atom -> Forbid\n");
-#endif
 	    return(forbiddenExp);
         case XML_EXP_SEQ:
 	    /* try to get the sequence consumed only if possible */
 	    if (xmlExpCheckCard(exp->exp_left, sub)) {
 		/* See if the sequence can be consumed directly */
-#ifdef DEBUG_DERIV
-		printf("Seq trying left only\n");
-#endif
 		ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
 		if ((ret != forbiddenExp) && (ret != NULL)) {
-#ifdef DEBUG_DERIV
-		    printf("Seq trying left only worked\n");
-#endif
 		    /*
 		     * TODO: assumption here that we are determinist
 		     *       i.e. we won't get to a nillable exp left
@@ -7602,25 +7362,15 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 		    return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret,
 					      exp->exp_right, NULL, 0, 0));
 		}
-#ifdef DEBUG_DERIV
-	    } else {
-		printf("Seq: left too short\n");
-#endif
 	    }
 	    /* Try instead to decompose */
 	    if (sub->type == XML_EXP_COUNT) {
 		int min, max;
 
-#ifdef DEBUG_DERIV
-		printf("Seq: sub is a count\n");
-#endif
 	        ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub->exp_left);
 		if (ret == NULL)
 		    return(NULL);
 		if (ret != forbiddenExp) {
-#ifdef DEBUG_DERIV
-		    printf("Seq , Count match on left\n");
-#endif
 		    if (sub->exp_max < 0)
 		        max = -1;
 	            else
@@ -7651,9 +7401,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 	    /* we made no progress on structured operations */
 	    break;
         case XML_EXP_OR:
-#ifdef DEBUG_DERIV
-	    printf("Or , trying both side\n");
-#endif
 	    ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
 	    if (ret == NULL)
 	        return(NULL);
@@ -7676,15 +7423,9 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 		if (tmp == forbiddenExp) {
 		    int mult;
 
-#ifdef DEBUG_DERIV
-		    printf("Count, Count inner don't subsume\n");
-#endif
 		    mult = xmlExpDivide(ctxt, sub->exp_left, exp->exp_left,
 		                        NULL, &tmp);
 		    if (mult <= 0) {
-#ifdef DEBUG_DERIV
-			printf("Count, Count not multiple => forbidden\n");
-#endif
                         return(forbiddenExp);
 		    }
 		    if (sub->exp_max == -1) {
@@ -7695,17 +7436,11 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 			    else
 			        min = exp->exp_min - sub->exp_min * mult;
 			} else {
-#ifdef DEBUG_DERIV
-			    printf("Count, Count finite can't subsume infinite\n");
-#endif
                             xmlExpFree(ctxt, tmp);
 			    return(forbiddenExp);
 			}
 		    } else {
 			if (exp->exp_max == -1) {
-#ifdef DEBUG_DERIV
-			    printf("Infinite loop consume mult finite loop\n");
-#endif
 			    if (exp->exp_min > sub->exp_min * mult) {
 				max = -1;
 				min = exp->exp_min - sub->exp_min * mult;
@@ -7715,9 +7450,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 			    }
 			} else {
 			    if (exp->exp_max < sub->exp_max * mult) {
-#ifdef DEBUG_DERIV
-				printf("loops max mult mismatch => forbidden\n");
-#endif
 				xmlExpFree(ctxt, tmp);
 				return(forbiddenExp);
 			    }
@@ -7733,30 +7465,18 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 		     * TODO: loop here to try to grow if working on finite
 		     *       blocks.
 		     */
-#ifdef DEBUG_DERIV
-		    printf("Count, Count remain not nillable => forbidden\n");
-#endif
 		    xmlExpFree(ctxt, tmp);
 		    return(forbiddenExp);
 		} else if (sub->exp_max == -1) {
 		    if (exp->exp_max == -1) {
 		        if (exp->exp_min <= sub->exp_min) {
-#ifdef DEBUG_DERIV
-			    printf("Infinite loops Okay => COUNT(0,Inf)\n");
-#endif
                             max = -1;
 			    min = 0;
 			} else {
-#ifdef DEBUG_DERIV
-			    printf("Infinite loops min => Count(X,Inf)\n");
-#endif
                             max = -1;
 			    min = exp->exp_min - sub->exp_min;
 			}
 		    } else if (exp->exp_min > sub->exp_min) {
-#ifdef DEBUG_DERIV
-			printf("loops min mismatch 1 => forbidden ???\n");
-#endif
 		        xmlExpFree(ctxt, tmp);
 		        return(forbiddenExp);
 		    } else {
@@ -7765,9 +7485,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 		    }
 		} else {
 		    if (exp->exp_max == -1) {
-#ifdef DEBUG_DERIV
-			printf("Infinite loop consume finite loop\n");
-#endif
 		        if (exp->exp_min > sub->exp_min) {
 			    max = -1;
 			    min = exp->exp_min - sub->exp_min;
@@ -7777,9 +7494,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 			}
 		    } else {
 		        if (exp->exp_max < sub->exp_max) {
-#ifdef DEBUG_DERIV
-			    printf("loops max mismatch => forbidden\n");
-#endif
 			    xmlExpFree(ctxt, tmp);
 			    return(forbiddenExp);
 			}
@@ -7790,9 +7504,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 			max = exp->exp_max - sub->exp_max;
 		    }
 		}
-#ifdef DEBUG_DERIV
-		printf("loops match => SEQ(COUNT())\n");
-#endif
 		exp->exp_left->ref++;
 		tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left,
 		                          NULL, NULL, min, max);
@@ -7807,9 +7518,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 	    if (tmp == NULL)
 		return(NULL);
 	    if (tmp == forbiddenExp) {
-#ifdef DEBUG_DERIV
-		printf("loop mismatch => forbidden\n");
-#endif
 		return(forbiddenExp);
 	    }
 	    if (exp->exp_min > 0)
@@ -7821,9 +7529,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 	    else
 		max = exp->exp_max - 1;
 
-#ifdef DEBUG_DERIV
-	    printf("loop match => SEQ(COUNT())\n");
-#endif
 	    exp->exp_left->ref++;
 	    tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left,
 				      NULL, NULL, min, max);
@@ -7835,9 +7540,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
 	}
     }
 
-#ifdef DEBUG_DERIV
-    printf("Fallback to derivative\n");
-#endif
     if (IS_NILLABLE(sub)) {
         if (!(IS_NILLABLE(exp)))
 	    return(forbiddenExp);
@@ -7935,15 +7637,9 @@ xmlExpExpDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
      * O(1) speedups
      */
     if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) {
-#ifdef DEBUG_DERIV
-	printf("Sub nillable and not exp : can't subsume\n");
-#endif
         return(forbiddenExp);
     }
     if (xmlExpCheckCard(exp, sub) == 0) {
-#ifdef DEBUG_DERIV
-	printf("sub generate longer sequences than exp : can't subsume\n");
-#endif
         return(forbiddenExp);
     }
     return(xmlExpExpDeriveInt(ctxt, exp, sub));
@@ -7975,22 +7671,12 @@ xmlExpSubsume(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
      * O(1) speedups
      */
     if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) {
-#ifdef DEBUG_DERIV
-	printf("Sub nillable and not exp : can't subsume\n");
-#endif
         return(0);
     }
     if (xmlExpCheckCard(exp, sub) == 0) {
-#ifdef DEBUG_DERIV
-	printf("sub generate longer sequences than exp : can't subsume\n");
-#endif
         return(0);
     }
     tmp = xmlExpExpDeriveInt(ctxt, exp, sub);
-#ifdef DEBUG_DERIV
-    printf("Result derivation :\n");
-    PRINT_EXP(tmp);
-#endif
     if (tmp == NULL)
         return(-1);
     if (tmp == forbiddenExp)
diff --git a/xmlsave.c b/xmlsave.c
index 9b42c66cac9a562e1c5f50c04b535c537ff70aa0..16b71d0a50aeb32c6c684111cd9512d13932bf7c 100644
--- a/xmlsave.c
+++ b/xmlsave.c
@@ -9,6 +9,8 @@
 #define IN_LIBXML
 #include "libxml.h"
 
+#include <limits.h>
+#include <stdlib.h>
 #include <string.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/parserInternals.h>
@@ -19,61 +21,15 @@
 
 #include <libxml/HTMLtree.h>
 
-#include "buf.h"
-#include "enc.h"
-#include "save.h"
-
-/************************************************************************
- *									*
- *			XHTML detection					*
- *									*
- ************************************************************************/
-#define XHTML_STRICT_PUBLIC_ID BAD_CAST \
-   "-//W3C//DTD XHTML 1.0 Strict//EN"
-#define XHTML_STRICT_SYSTEM_ID BAD_CAST \
-   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
-#define XHTML_FRAME_PUBLIC_ID BAD_CAST \
-   "-//W3C//DTD XHTML 1.0 Frameset//EN"
-#define XHTML_FRAME_SYSTEM_ID BAD_CAST \
-   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
-#define XHTML_TRANS_PUBLIC_ID BAD_CAST \
-   "-//W3C//DTD XHTML 1.0 Transitional//EN"
-#define XHTML_TRANS_SYSTEM_ID BAD_CAST \
-   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
-
-#define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml"
-/**
- * xmlIsXHTML:
- * @systemID:  the system identifier
- * @publicID:  the public identifier
- *
- * Try to find if the document correspond to an XHTML DTD
- *
- * Returns 1 if true, 0 if not and -1 in case of error
- */
-int
-xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) {
-    if ((systemID == NULL) && (publicID == NULL))
-	return(-1);
-    if (publicID != NULL) {
-	if (xmlStrEqual(publicID, XHTML_STRICT_PUBLIC_ID)) return(1);
-	if (xmlStrEqual(publicID, XHTML_FRAME_PUBLIC_ID)) return(1);
-	if (xmlStrEqual(publicID, XHTML_TRANS_PUBLIC_ID)) return(1);
-    }
-    if (systemID != NULL) {
-	if (xmlStrEqual(systemID, XHTML_STRICT_SYSTEM_ID)) return(1);
-	if (xmlStrEqual(systemID, XHTML_FRAME_SYSTEM_ID)) return(1);
-	if (xmlStrEqual(systemID, XHTML_TRANS_SYSTEM_ID)) return(1);
-    }
-    return(0);
-}
+#include "private/buf.h"
+#include "private/enc.h"
+#include "private/error.h"
+#include "private/io.h"
+#include "private/save.h"
 
 #ifdef LIBXML_OUTPUT_ENABLED
 
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
+#define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml"
 
 struct _xmlSaveCtxt {
     void *_private;
@@ -105,9 +61,11 @@ struct _xmlSaveCtxt {
  * Handle an out of memory condition
  */
 static void
-xmlSaveErrMemory(const char *extra)
+xmlSaveErrMemory(xmlOutputBufferPtr out)
 {
-    __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra);
+    if (out != NULL)
+        out->error = XML_ERR_NO_MEMORY;
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_OUTPUT, NULL);
 }
 
 /**
@@ -119,9 +77,23 @@ xmlSaveErrMemory(const char *extra)
  * Handle an out of memory condition
  */
 static void
-xmlSaveErr(int code, xmlNodePtr node, const char *extra)
+xmlSaveErr(xmlOutputBufferPtr out, int code, xmlNodePtr node,
+           const char *extra)
 {
     const char *msg = NULL;
+    int res;
+
+    /* Don't overwrite memory errors */
+    if ((out != NULL) && (out->error == XML_ERR_NO_MEMORY))
+        return;
+
+    if (code == XML_ERR_NO_MEMORY) {
+        xmlSaveErrMemory(out);
+        return;
+    }
+
+    if (out != NULL)
+        out->error = code;
 
     switch(code) {
         case XML_SAVE_NOT_UTF8:
@@ -139,7 +111,13 @@ xmlSaveErr(int code, xmlNodePtr node, const char *extra)
 	default:
 	    msg = "unexpected error number\n";
     }
-    __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra);
+
+    res = __xmlRaiseError(NULL, NULL, NULL, NULL, node,
+                          XML_FROM_OUTPUT, code, XML_ERR_ERROR, NULL, 0,
+                          extra, NULL, NULL, 0, 0,
+                          msg, extra);
+    if (res < 0)
+        xmlSaveErrMemory(out);
 }
 
 /************************************************************************
@@ -240,79 +218,52 @@ xmlEscapeEntities(unsigned char* out, int *outlen,
 	    *out++ = ';';
 	    in++;
 	    continue;
+	} else if (*in == 0xD) {
+	    if (outend - out < 5) break;
+	    *out++ = '&';
+	    *out++ = '#';
+	    *out++ = 'x';
+	    *out++ = 'D';
+	    *out++ = ';';
+	    in++;
 	} else if (((*in >= 0x20) && (*in < 0x80)) ||
-	           (*in == '\n') || (*in == '\t')) {
+	           (*in == 0xA) || (*in == 0x9)) {
 	    /*
 	     * default case, just copy !
 	     */
 	    *out++ = *in++;
 	    continue;
-	} else if (*in >= 0x80) {
-	    /*
-	     * We assume we have UTF-8 input.
-	     */
+	} else if (*in < 0x80) {
+            /* invalid control char */
+	    if (outend - out < 8) break;
+	    out = xmlSerializeHexCharRef(out, 0xFFFD);
+	    in++;
+	} else {
+            int len;
+
 	    if (outend - out < 11) break;
 
-	    if (*in < 0xC0) {
-		xmlSaveErr(XML_SAVE_NOT_UTF8, NULL, NULL);
-		in++;
-		goto error;
-	    } else if (*in < 0xE0) {
-		if (inend - in < 2) break;
-		val = (in[0]) & 0x1F;
-		val <<= 6;
-		val |= (in[1]) & 0x3F;
-		in += 2;
-	    } else if (*in < 0xF0) {
-		if (inend - in < 3) break;
-		val = (in[0]) & 0x0F;
-		val <<= 6;
-		val |= (in[1]) & 0x3F;
-		val <<= 6;
-		val |= (in[2]) & 0x3F;
-		in += 3;
-	    } else if (*in < 0xF8) {
-		if (inend - in < 4) break;
-		val = (in[0]) & 0x07;
-		val <<= 6;
-		val |= (in[1]) & 0x3F;
-		val <<= 6;
-		val |= (in[2]) & 0x3F;
-		val <<= 6;
-		val |= (in[3]) & 0x3F;
-		in += 4;
-	    } else {
-		xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);
-		in++;
-		goto error;
-	    }
-	    if (!IS_CHAR(val)) {
-		xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);
-		in++;
-		goto error;
-	    }
+            len = inend - in;
+            val = xmlGetUTF8Char(in, &len);
+
+            if (val < 0) {
+                val = 0xFFFD;
+                in++;
+            } else {
+                if (!IS_CHAR(val))
+                    val = 0xFFFD;
+                in += len;
+            }
 
 	    /*
 	     * We could do multiple things here. Just save as a char ref
 	     */
 	    out = xmlSerializeHexCharRef(out, val);
-	} else if (IS_BYTE_CHAR(*in)) {
-	    if (outend - out < 6) break;
-	    out = xmlSerializeHexCharRef(out, *in++);
-	} else {
-	    xmlGenericError(xmlGenericErrorContext,
-		"xmlEscapeEntities : char out of range\n");
-	    in++;
-	    goto error;
 	}
     }
     *outlen = out - outstart;
     *inlen = in - base;
     return(0);
-error:
-    *outlen = out - outstart;
-    *inlen = in - base;
-    return(-1);
 }
 
 /************************************************************************
@@ -382,15 +333,18 @@ xmlNewSaveCtxt(const char *encoding, int options)
 
     ret = (xmlSaveCtxtPtr) xmlMalloc(sizeof(xmlSaveCtxt));
     if (ret == NULL) {
-	xmlSaveErrMemory("creating saving context");
+	xmlSaveErrMemory(NULL);
 	return ( NULL );
     }
     memset(ret, 0, sizeof(xmlSaveCtxt));
 
     if (encoding != NULL) {
-        ret->handler = xmlFindCharEncodingHandler(encoding);
-	if (ret->handler == NULL) {
-	    xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
+        int res;
+
+        res = xmlOpenCharEncodingHandler(encoding, /* output */ 1,
+                                         &ret->handler);
+	if (res != XML_ERR_OK) {
+	    xmlSaveErr(NULL, res, NULL, encoding);
             xmlFreeSaveCtxt(ret);
 	    return(NULL);
 	}
@@ -439,14 +393,13 @@ xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr)
     while (children != NULL) {
         switch (children->type) {
             case XML_TEXT_NODE:
-	        xmlBufAttrSerializeTxtContent(buf->buffer, attr->doc,
-		                              attr, children->content);
+	        xmlBufAttrSerializeTxtContent(buf, attr->doc,
+		                              children->content);
 		break;
             case XML_ENTITY_REF_NODE:
-                xmlBufAdd(buf->buffer, BAD_CAST "&", 1);
-                xmlBufAdd(buf->buffer, children->name,
-                             xmlStrlen(children->name));
-                xmlBufAdd(buf->buffer, BAD_CAST ";", 1);
+                xmlOutputBufferWrite(buf, 1, "&");
+                xmlOutputBufferWriteString(buf, (const char *) children->name);
+                xmlOutputBufferWrite(buf, 1, ";");
                 break;
             default:
                 /* should not happen unless we have a badly built tree */
@@ -456,6 +409,46 @@ xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr)
     }
 }
 
+/**
+ * xmlBufDumpNotationDecl:
+ * @buf:  the XML buffer output
+ * @nota:  A notation declaration
+ *
+ * This will dump the content the notation declaration as an XML DTD definition
+ */
+static void
+xmlBufDumpNotationDecl(xmlOutputBufferPtr buf, xmlNotationPtr nota) {
+    xmlOutputBufferWrite(buf, 11, "<!NOTATION ");
+    xmlOutputBufferWriteString(buf, (const char *) nota->name);
+
+    if (nota->PublicID != NULL) {
+	xmlOutputBufferWrite(buf, 8, " PUBLIC ");
+	xmlOutputBufferWriteQuotedString(buf, nota->PublicID);
+	if (nota->SystemID != NULL) {
+	    xmlOutputBufferWrite(buf, 1, " ");
+	    xmlOutputBufferWriteQuotedString(buf, nota->SystemID);
+	}
+    } else {
+	xmlOutputBufferWrite(buf, 8, " SYSTEM ");
+	xmlOutputBufferWriteQuotedString(buf, nota->SystemID);
+    }
+
+    xmlOutputBufferWrite(buf, 3, " >\n");
+}
+
+/**
+ * xmlBufDumpNotationDeclScan:
+ * @nota:  A notation declaration
+ * @buf:  the XML buffer output
+ *
+ * This is called with the hash scan function, and just reverses args
+ */
+static void
+xmlBufDumpNotationDeclScan(void *nota, void *buf,
+                           const xmlChar *name ATTRIBUTE_UNUSED) {
+    xmlBufDumpNotationDecl((xmlOutputBufferPtr) buf, (xmlNotationPtr) nota);
+}
+
 /**
  * xmlBufDumpNotationTable:
  * @buf:  an xmlBufPtr output
@@ -463,20 +456,106 @@ xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr)
  *
  * This will dump the content of the notation table as an XML DTD definition
  */
-void
-xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table) {
-    xmlBufferPtr buffer;
-
-    buffer = xmlBufferCreate();
-    if (buffer == NULL) {
-        /*
-         * TODO set the error in buf
-         */
-        return;
+static void
+xmlBufDumpNotationTable(xmlOutputBufferPtr buf, xmlNotationTablePtr table) {
+    xmlHashScan(table, xmlBufDumpNotationDeclScan, buf);
+}
+
+/**
+ * xmlBufDumpElementOccur:
+ * @buf:  output buffer
+ * @cur:  element table
+ *
+ * Dump the occurrence operator of an element.
+ */
+static void
+xmlBufDumpElementOccur(xmlOutputBufferPtr buf, xmlElementContentPtr cur) {
+    switch (cur->ocur) {
+        case XML_ELEMENT_CONTENT_ONCE:
+            break;
+        case XML_ELEMENT_CONTENT_OPT:
+            xmlOutputBufferWrite(buf, 1, "?");
+            break;
+        case XML_ELEMENT_CONTENT_MULT:
+            xmlOutputBufferWrite(buf, 1, "*");
+            break;
+        case XML_ELEMENT_CONTENT_PLUS:
+            xmlOutputBufferWrite(buf, 1, "+");
+            break;
     }
-    xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
-    xmlDumpNotationTable(buffer, table);
-    xmlBufMergeBuffer(buf, buffer);
+}
+
+/**
+ * xmlBufDumpElementContent:
+ * @buf:  output buffer
+ * @content:  element table
+ *
+ * This will dump the content of the element table as an XML DTD definition
+ */
+static void
+xmlBufDumpElementContent(xmlOutputBufferPtr buf,
+                         xmlElementContentPtr content) {
+    xmlElementContentPtr cur;
+
+    if (content == NULL) return;
+
+    xmlOutputBufferWrite(buf, 1, "(");
+    cur = content;
+
+    do {
+        if (cur == NULL) return;
+
+        switch (cur->type) {
+            case XML_ELEMENT_CONTENT_PCDATA:
+                xmlOutputBufferWrite(buf, 7, "#PCDATA");
+                break;
+            case XML_ELEMENT_CONTENT_ELEMENT:
+                if (cur->prefix != NULL) {
+                    xmlOutputBufferWriteString(buf,
+                            (const char *) cur->prefix);
+                    xmlOutputBufferWrite(buf, 1, ":");
+                }
+                xmlOutputBufferWriteString(buf, (const char *) cur->name);
+                break;
+            case XML_ELEMENT_CONTENT_SEQ:
+            case XML_ELEMENT_CONTENT_OR:
+                if ((cur != content) &&
+                    (cur->parent != NULL) &&
+                    ((cur->type != cur->parent->type) ||
+                     (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
+                    xmlOutputBufferWrite(buf, 1, "(");
+                cur = cur->c1;
+                continue;
+        }
+
+        while (cur != content) {
+            xmlElementContentPtr parent = cur->parent;
+
+            if (parent == NULL) return;
+
+            if (((cur->type == XML_ELEMENT_CONTENT_OR) ||
+                 (cur->type == XML_ELEMENT_CONTENT_SEQ)) &&
+                ((cur->type != parent->type) ||
+                 (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
+                xmlOutputBufferWrite(buf, 1, ")");
+            xmlBufDumpElementOccur(buf, cur);
+
+            if (cur == parent->c1) {
+                if (parent->type == XML_ELEMENT_CONTENT_SEQ)
+                    xmlOutputBufferWrite(buf, 3, " , ");
+                else if (parent->type == XML_ELEMENT_CONTENT_OR)
+                    xmlOutputBufferWrite(buf, 3, " | ");
+
+                cur = parent->c2;
+                break;
+            }
+
+            cur = parent;
+        }
+    } while (cur != content);
+
+    xmlOutputBufferWrite(buf, 1, ")");
+    xmlBufDumpElementOccur(buf, content);
 }
 
 /**
@@ -487,44 +566,174 @@ xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table) {
  * This will dump the content of the element declaration as an XML
  * DTD definition
  */
-void
-xmlBufDumpElementDecl(xmlBufPtr buf, xmlElementPtr elem) {
-    xmlBufferPtr buffer;
-
-    buffer = xmlBufferCreate();
-    if (buffer == NULL) {
-        /*
-         * TODO set the error in buf
-         */
-        return;
+static void
+xmlBufDumpElementDecl(xmlOutputBufferPtr buf, xmlElementPtr elem) {
+    xmlOutputBufferWrite(buf, 10, "<!ELEMENT ");
+    if (elem->prefix != NULL) {
+        xmlOutputBufferWriteString(buf, (const char *) elem->prefix);
+        xmlOutputBufferWrite(buf, 1, ":");
     }
-    xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
-    xmlDumpElementDecl(buffer, elem);
-    xmlBufMergeBuffer(buf, buffer);
+    xmlOutputBufferWriteString(buf, (const char *) elem->name);
+    xmlOutputBufferWrite(buf, 1, " ");
+
+    switch (elem->etype) {
+	case XML_ELEMENT_TYPE_EMPTY:
+	    xmlOutputBufferWrite(buf, 5, "EMPTY");
+	    break;
+	case XML_ELEMENT_TYPE_ANY:
+	    xmlOutputBufferWrite(buf, 3, "ANY");
+	    break;
+	case XML_ELEMENT_TYPE_MIXED:
+	case XML_ELEMENT_TYPE_ELEMENT:
+	    xmlBufDumpElementContent(buf, elem->content);
+	    break;
+        default:
+            /* assert(0); */
+            break;
+    }
+
+    xmlOutputBufferWrite(buf, 2, ">\n");
 }
 
+/**
+ * xmlBufDumpEnumeration:
+ * @buf:  output buffer
+ * @enum:  An enumeration
+ *
+ * This will dump the content of the enumeration
+ */
+static void
+xmlBufDumpEnumeration(xmlOutputBufferPtr buf, xmlEnumerationPtr cur) {
+    while (cur != NULL) {
+        xmlOutputBufferWriteString(buf, (const char *) cur->name);
+        if (cur->next != NULL)
+            xmlOutputBufferWrite(buf, 3, " | ");
+
+        cur = cur->next;
+    }
+
+    xmlOutputBufferWrite(buf, 1, ")");
+}
 /**
  * xmlBufDumpAttributeDecl:
- * @buf:  an xmlBufPtr output
+ * @buf:  output buffer
  * @attr:  An attribute declaration
  *
  * This will dump the content of the attribute declaration as an XML
  * DTD definition
  */
-void
-xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr) {
-    xmlBufferPtr buffer;
-
-    buffer = xmlBufferCreate();
-    if (buffer == NULL) {
-        /*
-         * TODO set the error in buf
-         */
-        return;
+static void
+xmlBufDumpAttributeDecl(xmlOutputBufferPtr buf, xmlAttributePtr attr) {
+    xmlOutputBufferWrite(buf, 10, "<!ATTLIST ");
+    xmlOutputBufferWriteString(buf, (const char *) attr->elem);
+    xmlOutputBufferWrite(buf, 1, " ");
+    if (attr->prefix != NULL) {
+	xmlOutputBufferWriteString(buf, (const char *) attr->prefix);
+	xmlOutputBufferWrite(buf, 1, ":");
+    }
+    xmlOutputBufferWriteString(buf, (const char *) attr->name);
+
+    switch (attr->atype) {
+	case XML_ATTRIBUTE_CDATA:
+	    xmlOutputBufferWrite(buf, 6, " CDATA");
+	    break;
+	case XML_ATTRIBUTE_ID:
+	    xmlOutputBufferWrite(buf, 3, " ID");
+	    break;
+	case XML_ATTRIBUTE_IDREF:
+	    xmlOutputBufferWrite(buf, 6, " IDREF");
+	    break;
+	case XML_ATTRIBUTE_IDREFS:
+	    xmlOutputBufferWrite(buf, 7, " IDREFS");
+	    break;
+	case XML_ATTRIBUTE_ENTITY:
+	    xmlOutputBufferWrite(buf, 7, " ENTITY");
+	    break;
+	case XML_ATTRIBUTE_ENTITIES:
+	    xmlOutputBufferWrite(buf, 9, " ENTITIES");
+	    break;
+	case XML_ATTRIBUTE_NMTOKEN:
+	    xmlOutputBufferWrite(buf, 8, " NMTOKEN");
+	    break;
+	case XML_ATTRIBUTE_NMTOKENS:
+	    xmlOutputBufferWrite(buf, 9, " NMTOKENS");
+	    break;
+	case XML_ATTRIBUTE_ENUMERATION:
+	    xmlOutputBufferWrite(buf, 2, " (");
+	    xmlBufDumpEnumeration(buf, attr->tree);
+	    break;
+	case XML_ATTRIBUTE_NOTATION:
+	    xmlOutputBufferWrite(buf, 11, " NOTATION (");
+	    xmlBufDumpEnumeration(buf, attr->tree);
+	    break;
+	default:
+            /* assert(0); */
+            break;
+    }
+
+    switch (attr->def) {
+	case XML_ATTRIBUTE_NONE:
+	    break;
+	case XML_ATTRIBUTE_REQUIRED:
+	    xmlOutputBufferWrite(buf, 10, " #REQUIRED");
+	    break;
+	case XML_ATTRIBUTE_IMPLIED:
+	    xmlOutputBufferWrite(buf, 9, " #IMPLIED");
+	    break;
+	case XML_ATTRIBUTE_FIXED:
+	    xmlOutputBufferWrite(buf, 7, " #FIXED");
+	    break;
+	default:
+            /* assert(0); */
+            break;
+    }
+
+    if (attr->defaultValue != NULL) {
+	xmlOutputBufferWrite(buf, 1, " ");
+	xmlOutputBufferWriteQuotedString(buf, attr->defaultValue);
+    }
+
+    xmlOutputBufferWrite(buf, 2, ">\n");
+}
+
+/**
+ * xmlBufDumpEntityContent:
+ * @buf:  output buffer
+ * @content:  entity content.
+ *
+ * This will dump the quoted string value, taking care of the special
+ * treatment required by %
+ */
+static void
+xmlBufDumpEntityContent(xmlOutputBufferPtr buf, const xmlChar *content) {
+    if (xmlStrchr(content, '%')) {
+        const char * base, *cur;
+
+	xmlOutputBufferWrite(buf, 1, "\"");
+	base = cur = (const char *) content;
+	while (*cur != 0) {
+	    if (*cur == '"') {
+		if (base != cur)
+		    xmlOutputBufferWrite(buf, cur - base, base);
+		xmlOutputBufferWrite(buf, 6, "&quot;");
+		cur++;
+		base = cur;
+	    } else if (*cur == '%') {
+		if (base != cur)
+		    xmlOutputBufferWrite(buf, cur - base, base);
+		xmlOutputBufferWrite(buf, 6, "&#x25;");
+		cur++;
+		base = cur;
+	    } else {
+		cur++;
+	    }
+	}
+	if (base != cur)
+	    xmlOutputBufferWrite(buf, cur - base, base);
+	xmlOutputBufferWrite(buf, 1, "\"");
+    } else {
+        xmlOutputBufferWriteQuotedString(buf, content);
     }
-    xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
-    xmlDumpAttributeDecl(buffer, attr);
-    xmlBufMergeBuffer(buf, buffer);
 }
 
 /**
@@ -534,20 +743,48 @@ xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr) {
  *
  * This will dump the content of the entity table as an XML DTD definition
  */
-void
-xmlBufDumpEntityDecl(xmlBufPtr buf, xmlEntityPtr ent) {
-    xmlBufferPtr buffer;
-
-    buffer = xmlBufferCreate();
-    if (buffer == NULL) {
-        /*
-         * TODO set the error in buf
-         */
-        return;
+static void
+xmlBufDumpEntityDecl(xmlOutputBufferPtr buf, xmlEntityPtr ent) {
+    if ((ent->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
+        (ent->etype == XML_EXTERNAL_PARAMETER_ENTITY))
+        xmlOutputBufferWrite(buf, 11, "<!ENTITY % ");
+    else
+        xmlOutputBufferWrite(buf, 9, "<!ENTITY ");
+    xmlOutputBufferWriteString(buf, (const char *) ent->name);
+    xmlOutputBufferWrite(buf, 1, " ");
+
+    if ((ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
+        (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) ||
+        (ent->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
+        if (ent->ExternalID != NULL) {
+             xmlOutputBufferWrite(buf, 7, "PUBLIC ");
+             xmlOutputBufferWriteQuotedString(buf, ent->ExternalID);
+             xmlOutputBufferWrite(buf, 1, " ");
+        } else {
+             xmlOutputBufferWrite(buf, 7, "SYSTEM ");
+        }
+        xmlOutputBufferWriteQuotedString(buf, ent->SystemID);
     }
-    xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
-    xmlDumpEntityDecl(buffer, ent);
-    xmlBufMergeBuffer(buf, buffer);
+
+    if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
+        if (ent->content != NULL) { /* Should be true ! */
+            xmlOutputBufferWrite(buf, 7, " NDATA ");
+            if (ent->orig != NULL)
+                xmlOutputBufferWriteString(buf, (const char *) ent->orig);
+            else
+                xmlOutputBufferWriteString(buf, (const char *) ent->content);
+        }
+    }
+
+    if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
+        (ent->etype == XML_INTERNAL_PARAMETER_ENTITY)) {
+        if (ent->orig != NULL)
+            xmlOutputBufferWriteQuotedString(buf, ent->orig);
+        else
+            xmlBufDumpEntityContent(buf, ent->content);
+    }
+
+    xmlOutputBufferWrite(buf, 2, ">\n");
 }
 
 /************************************************************************
@@ -560,18 +797,21 @@ static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) {
     xmlOutputBufferPtr buf = ctxt->buf;
 
     if ((encoding != NULL) && (buf->encoder == NULL) && (buf->conv == NULL)) {
-	buf->encoder = xmlFindCharEncodingHandler((const char *)encoding);
-	if (buf->encoder == NULL) {
-	    xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL,
-		       (const char *)encoding);
-	    return(-1);
-	}
+        xmlCharEncodingHandler *handler;
+        int res;
+
+	res = xmlOpenCharEncodingHandler(encoding, /* output */ 1, &handler);
+        if (res != XML_ERR_OK) {
+            xmlSaveErr(buf, res, NULL, encoding);
+            return(-1);
+        }
 	buf->conv = xmlBufCreate();
 	if (buf->conv == NULL) {
-	    xmlCharEncCloseFunc(buf->encoder);
-	    xmlSaveErrMemory("creating encoding buffer");
+	    xmlCharEncCloseFunc(handler);
+            xmlSaveErrMemory(buf);
 	    return(-1);
 	}
+        buf->encoder = handler;
 	/*
 	 * initialize the state, e.g. if outputting a BOM
 	 */
@@ -595,7 +835,6 @@ static void
 xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
 #endif
 static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
-void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
 static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur);
 
 /**
@@ -631,7 +870,8 @@ xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra)
  * If @ctxt is supplied, @buf should be its buffer.
  */
 static void
-xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) {
+xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNsPtr cur,
+                xmlSaveCtxtPtr ctxt) {
     if ((cur == NULL) || (buf == NULL)) return;
     if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
 	if (xmlStrEqual(cur->prefix, BAD_CAST "xml"))
@@ -648,24 +888,12 @@ xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) {
 	    xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
 	} else
 	    xmlOutputBufferWrite(buf, 5, "xmlns");
-	xmlOutputBufferWrite(buf, 1, "=");
-	xmlBufWriteQuotedString(buf->buffer, cur->href);
+        xmlOutputBufferWrite(buf, 2, "=\"");
+        xmlBufAttrSerializeTxtContent(buf, doc, cur->href);
+        xmlOutputBufferWrite(buf, 1, "\"");
     }
 }
 
-/**
- * xmlNsDumpOutputCtxt
- * @ctxt: the save context
- * @cur:  a namespace
- *
- * Dump a local Namespace definition to a save context.
- * Should be called in the context of attribute dumps.
- */
-static void
-xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
-    xmlNsDumpOutput(ctxt->buf, cur, ctxt);
-}
-
 /**
  * xmlNsListDumpOutputCtxt
  * @ctxt: the save context
@@ -675,9 +903,9 @@ xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
  * Should be called in the context of attribute dumps.
  */
 static void
-xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
+xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlDocPtr doc, xmlNsPtr cur) {
     while (cur != NULL) {
-        xmlNsDumpOutput(ctxt->buf, cur, ctxt);
+        xmlNsDumpOutput(ctxt->buf, doc, cur, ctxt);
 	cur = cur->next;
     }
 }
@@ -693,7 +921,7 @@ xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
 void
 xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
     while (cur != NULL) {
-        xmlNsDumpOutput(buf, cur, NULL);
+        xmlNsDumpOutput(buf, NULL, cur, NULL);
 	cur = cur->next;
     }
 }
@@ -719,12 +947,12 @@ xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
     xmlOutputBufferWriteString(buf, (const char *)dtd->name);
     if (dtd->ExternalID != NULL) {
 	xmlOutputBufferWrite(buf, 8, " PUBLIC ");
-	xmlBufWriteQuotedString(buf->buffer, dtd->ExternalID);
+	xmlOutputBufferWriteQuotedString(buf, dtd->ExternalID);
 	xmlOutputBufferWrite(buf, 1, " ");
-	xmlBufWriteQuotedString(buf->buffer, dtd->SystemID);
+	xmlOutputBufferWriteQuotedString(buf, dtd->SystemID);
     }  else if (dtd->SystemID != NULL) {
 	xmlOutputBufferWrite(buf, 8, " SYSTEM ");
-	xmlBufWriteQuotedString(buf->buffer, dtd->SystemID);
+	xmlOutputBufferWriteQuotedString(buf, dtd->SystemID);
     }
     if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
         (dtd->attributes == NULL) && (dtd->notations == NULL) &&
@@ -739,8 +967,7 @@ xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
      */
     if ((dtd->notations != NULL) && ((dtd->doc == NULL) ||
         (dtd->doc->intSubset == dtd))) {
-        xmlBufDumpNotationTable(buf->buffer,
-                                (xmlNotationTablePtr) dtd->notations);
+        xmlBufDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
     }
     format = ctxt->format;
     level = ctxt->level;
@@ -778,7 +1005,19 @@ xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
     }
     xmlOutputBufferWriteString(buf, (const char *)cur->name);
     xmlOutputBufferWrite(buf, 2, "=\"");
-    xmlAttrSerializeContent(buf, cur);
+#ifdef LIBXML_HTML_ENABLED
+    if ((ctxt->options & XML_SAVE_XHTML) &&
+        (cur->ns == NULL) &&
+        ((cur->children == NULL) ||
+         (cur->children->content == NULL) ||
+         (cur->children->content[0] == 0)) &&
+        (htmlIsBooleanAttr(cur->name))) {
+        xmlOutputBufferWriteString(buf, (const char *) cur->name);
+    } else
+#endif
+    {
+        xmlAttrSerializeContent(buf, cur);
+    }
     xmlOutputBufferWrite(buf, 1, "\"");
 }
 
@@ -882,15 +1121,15 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
 	    break;
 
         case XML_ELEMENT_DECL:
-            xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
+            xmlBufDumpElementDecl(buf, (xmlElementPtr) cur);
             break;
 
         case XML_ATTRIBUTE_DECL:
-            xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
+            xmlBufDumpAttributeDecl(buf, (xmlAttributePtr) cur);
             break;
 
         case XML_ENTITY_DECL:
-            xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
+            xmlBufDumpEntityDecl(buf, (xmlEntityPtr) cur);
             break;
 
         case XML_ELEMENT_NODE:
@@ -918,7 +1157,7 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
             }
             xmlOutputBufferWriteString(buf, (const char *)cur->name);
             if (cur->nsDef)
-                xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
+                xmlNsListDumpOutputCtxt(ctxt, cur->doc, cur->nsDef);
             for (attr = cur->properties; attr != NULL; attr = attr->next)
                 xmlAttrDumpOutput(ctxt, attr);
 
@@ -1058,7 +1297,7 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
             break;
 
         case XML_NAMESPACE_DECL:
-            xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
+            xmlNsDumpOutput(buf, NULL, (xmlNsPtr) cur, ctxt);
             break;
 
         default:
@@ -1207,12 +1446,12 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
 	if ((ctxt->options & XML_SAVE_NO_DECL) == 0) {
 	    xmlOutputBufferWrite(buf, 14, "<?xml version=");
 	    if (cur->version != NULL)
-		xmlBufWriteQuotedString(buf->buffer, cur->version);
+		xmlOutputBufferWriteQuotedString(buf, cur->version);
 	    else
 		xmlOutputBufferWrite(buf, 5, "\"1.0\"");
 	    if (encoding != NULL) {
 		xmlOutputBufferWrite(buf, 10, " encoding=");
-		xmlBufWriteQuotedString(buf->buffer, (xmlChar *) encoding);
+		xmlOutputBufferWriteQuotedString(buf, (xmlChar *) encoding);
 	    }
 	    switch (cur->standalone) {
 		case 0:
@@ -1292,7 +1531,7 @@ xhtmlIsEmpty(xmlNodePtr node) {
 	return(0);
     if (node->children != NULL)
 	return(0);
-    switch (node->name[0]) {
+    switch (node->name ? node->name[0] : 0) {
 	case 'a':
 	    if (xmlStrEqual(node->name, BAD_CAST "area"))
 		return(1);
@@ -1372,17 +1611,6 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
 	if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) &&
 	    (xmlStrEqual(cur->ns->prefix, BAD_CAST "xml")))
 	    xml_lang = cur;
-	else if ((cur->ns == NULL) &&
-		 ((cur->children == NULL) ||
-		  (cur->children->content == NULL) ||
-		  (cur->children->content[0] == 0)) &&
-		 (htmlIsBooleanAttr(cur->name))) {
-	    if (cur->children != NULL)
-		xmlFreeNode(cur->children);
-	    cur->children = xmlNewDocText(cur->doc, cur->name);
-	    if (cur->children != NULL)
-		cur->children->parent = (xmlNodePtr) cur;
-	}
         xmlAttrDumpOutput(ctxt, cur);
 	cur = cur->next;
     }
@@ -1433,14 +1661,18 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
  */
 static void
 xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
-    int format = ctxt->format, addmeta;
-    xmlNodePtr tmp, root, unformattedNode = NULL;
+    int format = ctxt->format, addmeta, oldoptions;
+    xmlNodePtr tmp, root, unformattedNode = NULL, parent;
     xmlChar *start, *end;
     xmlOutputBufferPtr buf = ctxt->buf;
 
     if (cur == NULL) return;
 
+    oldoptions = ctxt->options;
+    ctxt->options |= XML_SAVE_XHTML;
+
     root = cur;
+    parent = cur->parent;
     while (1) {
         switch (cur->type) {
         case XML_DOCUMENT_NODE:
@@ -1449,7 +1681,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
 	    break;
 
         case XML_NAMESPACE_DECL:
-	    xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
+	    xmlNsDumpOutput(buf, NULL, (xmlNsPtr) cur, ctxt);
 	    break;
 
         case XML_DTD_NODE:
@@ -1457,22 +1689,24 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
 	    break;
 
         case XML_DOCUMENT_FRAG_NODE:
-            if (cur->children) {
+            /* Always validate cur->parent when descending. */
+            if ((cur->parent == parent) && (cur->children != NULL)) {
+                parent = cur;
                 cur = cur->children;
                 continue;
             }
             break;
 
         case XML_ELEMENT_DECL:
-            xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
+            xmlBufDumpElementDecl(buf, (xmlElementPtr) cur);
 	    break;
 
         case XML_ATTRIBUTE_DECL:
-            xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
+            xmlBufDumpAttributeDecl(buf, (xmlAttributePtr) cur);
 	    break;
 
         case XML_ENTITY_DECL:
-            xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
+            xmlBufDumpEntityDecl(buf, (xmlEntityPtr) cur);
 	    break;
 
         case XML_ELEMENT_NODE:
@@ -1484,6 +1718,16 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
 				      ctxt->indent_nr : ctxt->level),
 				     ctxt->indent);
 
+            /*
+             * Some users like lxml are known to pass nodes with a corrupted
+             * tree structure. Fall back to a recursive call to handle this
+             * case.
+             */
+            if ((cur->parent != parent) && (cur->children != NULL)) {
+                xhtmlNodeDumpOutput(ctxt, cur);
+                break;
+            }
+
             xmlOutputBufferWrite(buf, 1, "<");
             if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
                 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
@@ -1492,7 +1736,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
 
             xmlOutputBufferWriteString(buf, (const char *)cur->name);
             if (cur->nsDef)
-                xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
+                xmlNsListDumpOutputCtxt(ctxt, cur->doc, cur->nsDef);
             if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
                 (cur->ns == NULL) && (cur->nsDef == NULL))) {
                 /*
@@ -1504,10 +1748,10 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
             if (cur->properties != NULL)
                 xhtmlAttrListDumpOutput(ctxt, cur->properties);
 
-            if ((cur->parent != NULL) &&
-                (cur->parent->parent == (xmlNodePtr) cur->doc) &&
+            if ((parent != NULL) &&
+                (parent->parent == (xmlNodePtr) cur->doc) &&
                 xmlStrEqual(cur->name, BAD_CAST"head") &&
-                xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
+                xmlStrEqual(parent->name, BAD_CAST"html")) {
 
                 tmp = cur->children;
                 while (tmp != NULL) {
@@ -1613,6 +1857,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
 
                 if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
                 if (ctxt->level >= 0) ctxt->level++;
+                parent = cur;
                 cur = cur->children;
                 continue;
             }
@@ -1707,13 +1952,9 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
                 break;
             }
 
-            /*
-             * The parent should never be NULL here but we want to handle
-             * corrupted documents gracefully.
-             */
-            if (cur->parent == NULL)
-                return;
-            cur = cur->parent;
+            cur = parent;
+            /* cur->parent was validated when descending. */
+            parent = cur->parent;
 
             if (cur->type == XML_ELEMENT_NODE) {
                 if (ctxt->level > 0) ctxt->level--;
@@ -1740,6 +1981,8 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
             }
         }
     }
+
+    ctxt->options = oldoptions;
 }
 #endif
 
@@ -1890,7 +2133,7 @@ xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc)
 /**
  * xmlSaveTree:
  * @ctxt:  a document saving context
- * @node:  the top node of the subtree to save
+ * @cur:  the top node of the subtree to save
  *
  * Save a subtree starting at the node parameter to a saving context
  * TODO: The function is not fully implemented yet as it does not return the
@@ -1921,6 +2164,40 @@ xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr cur)
     return(ret);
 }
 
+/**
+ * xmlSaveNotationDecl:
+ * @ctxt:  save context
+ * @cur:  notation
+ *
+ * Serialize a notation declaration.
+ *
+ * Return 0 on succes, -1 on error.
+ */
+int
+xmlSaveNotationDecl(xmlSaveCtxtPtr ctxt, xmlNotationPtr cur) {
+    if (ctxt == NULL)
+        return(-1);
+    xmlBufDumpNotationDecl(ctxt->buf, cur);
+    return(0);
+}
+
+/**
+ * xmlSaveNotationTable:
+ * @ctxt:  save context
+ * @cur:  notation table
+ *
+ * Serialize notation declarations of a document.
+ *
+ * Return 0 on succes, -1 on error.
+ */
+int
+xmlSaveNotationTable(xmlSaveCtxtPtr ctxt, xmlNotationTablePtr cur) {
+    if (ctxt == NULL)
+        return(-1);
+    xmlBufDumpNotationTable(ctxt->buf, cur);
+    return(0);
+}
+
 /**
  * xmlSaveFlush:
  * @ctxt:  a document saving context
@@ -1958,6 +2235,30 @@ xmlSaveClose(xmlSaveCtxtPtr ctxt)
     return(ret);
 }
 
+/**
+ * xmlSaveFinish:
+ * @ctxt:  a document saving context
+ *
+ * Close a document saving context, i.e. make sure that all bytes have
+ * been output and free the associated data.
+ *
+ * Available since 2.13.0.
+ *
+ * Returns an xmlParserErrors code.
+ */
+int
+xmlSaveFinish(xmlSaveCtxtPtr ctxt)
+{
+    int ret;
+
+    if (ctxt == NULL)
+        return(XML_ERR_INTERNAL_ERROR);
+    xmlSaveFlush(ctxt);
+    ret = ctxt->buf->error;
+    xmlFreeSaveCtxt(ctxt);
+    return(ret);
+}
+
 /**
  * xmlSaveSetEscape:
  * @ctxt:  a document saving context
@@ -2000,63 +2301,62 @@ xmlSaveSetAttrEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
 
 /**
  * xmlBufAttrSerializeTxtContent:
- * @buf:  and xmlBufPtr output
+ * @buf:  output buffer
  * @doc:  the document
- * @attr: the attribute node
  * @string: the text content
  *
  * Serialize text attribute values to an xmlBufPtr
  */
 void
-xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc,
-                              xmlAttrPtr attr, const xmlChar * string)
+xmlBufAttrSerializeTxtContent(xmlOutputBufferPtr buf, xmlDocPtr doc,
+                              const xmlChar *string)
 {
-    xmlChar *base, *cur;
+    const xmlChar *base, *cur;
 
     if (string == NULL)
         return;
-    base = cur = (xmlChar *) string;
+    base = cur = string;
     while (*cur != 0) {
         if (*cur == '\n') {
             if (base != cur)
-                xmlBufAdd(buf, base, cur - base);
-            xmlBufAdd(buf, BAD_CAST "&#10;", 5);
+                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
+            xmlOutputBufferWrite(buf, 5, "&#10;");
             cur++;
             base = cur;
         } else if (*cur == '\r') {
             if (base != cur)
-                xmlBufAdd(buf, base, cur - base);
-            xmlBufAdd(buf, BAD_CAST "&#13;", 5);
+                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
+            xmlOutputBufferWrite(buf, 5, "&#13;");
             cur++;
             base = cur;
         } else if (*cur == '\t') {
             if (base != cur)
-                xmlBufAdd(buf, base, cur - base);
-            xmlBufAdd(buf, BAD_CAST "&#9;", 4);
+                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
+            xmlOutputBufferWrite(buf, 4, "&#9;");
             cur++;
             base = cur;
         } else if (*cur == '"') {
             if (base != cur)
-                xmlBufAdd(buf, base, cur - base);
-            xmlBufAdd(buf, BAD_CAST "&quot;", 6);
+                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
+            xmlOutputBufferWrite(buf, 6, "&quot;");
             cur++;
             base = cur;
         } else if (*cur == '<') {
             if (base != cur)
-                xmlBufAdd(buf, base, cur - base);
-            xmlBufAdd(buf, BAD_CAST "&lt;", 4);
+                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
+            xmlOutputBufferWrite(buf, 4, "&lt;");
             cur++;
             base = cur;
         } else if (*cur == '>') {
             if (base != cur)
-                xmlBufAdd(buf, base, cur - base);
-            xmlBufAdd(buf, BAD_CAST "&gt;", 4);
+                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
+            xmlOutputBufferWrite(buf, 4, "&gt;");
             cur++;
             base = cur;
         } else if (*cur == '&') {
             if (base != cur)
-                xmlBufAdd(buf, base, cur - base);
-            xmlBufAdd(buf, BAD_CAST "&amp;", 5);
+                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
+            xmlOutputBufferWrite(buf, 5, "&amp;");
             cur++;
             base = cur;
         } else if ((*cur >= 0x80) && (cur[1] != 0) &&
@@ -2065,61 +2365,34 @@ xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc,
              * We assume we have UTF-8 content.
              */
             unsigned char tmp[12];
-            int val = 0, l = 1;
+            int val = 0, l = 4;
 
             if (base != cur)
-                xmlBufAdd(buf, base, cur - base);
-            if (*cur < 0xC0) {
-                xmlSaveErr(XML_SAVE_NOT_UTF8, (xmlNodePtr) attr, NULL);
-		xmlSerializeHexCharRef(tmp, *cur);
-                xmlBufAdd(buf, (xmlChar *) tmp, -1);
-                cur++;
-                base = cur;
-                continue;
-            } else if (*cur < 0xE0) {
-                val = (cur[0]) & 0x1F;
-                val <<= 6;
-                val |= (cur[1]) & 0x3F;
-                l = 2;
-            } else if ((*cur < 0xF0) && (cur [2] != 0)) {
-                val = (cur[0]) & 0x0F;
-                val <<= 6;
-                val |= (cur[1]) & 0x3F;
-                val <<= 6;
-                val |= (cur[2]) & 0x3F;
-                l = 3;
-            } else if ((*cur < 0xF8) && (cur [2] != 0) && (cur[3] != 0)) {
-                val = (cur[0]) & 0x07;
-                val <<= 6;
-                val |= (cur[1]) & 0x3F;
-                val <<= 6;
-                val |= (cur[2]) & 0x3F;
-                val <<= 6;
-                val |= (cur[3]) & 0x3F;
-                l = 4;
-            }
-            if ((l == 1) || (!IS_CHAR(val))) {
-                xmlSaveErr(XML_SAVE_CHAR_INVALID, (xmlNodePtr) attr, NULL);
-		xmlSerializeHexCharRef(tmp, *cur);
-                xmlBufAdd(buf, (xmlChar *) tmp, -1);
+                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
+
+            val = xmlGetUTF8Char(cur, &l);
+            if (val < 0) {
+                val = 0xFFFD;
                 cur++;
-                base = cur;
-                continue;
+            } else {
+                if (!IS_CHAR(val))
+                    val = 0xFFFD;
+                cur += l;
             }
+
             /*
              * We could do multiple things here. Just save
              * as a char ref
              */
 	    xmlSerializeHexCharRef(tmp, val);
-            xmlBufAdd(buf, (xmlChar *) tmp, -1);
-            cur += l;
+            xmlOutputBufferWriteString(buf, (const char *) tmp);
             base = cur;
         } else {
             cur++;
         }
     }
     if (base != cur)
-        xmlBufAdd(buf, base, cur - base);
+        xmlOutputBufferWrite(buf, cur - base, (const char *) base);
 }
 
 /**
@@ -2133,17 +2406,19 @@ xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc,
  */
 void
 xmlAttrSerializeTxtContent(xmlBufferPtr buf, xmlDocPtr doc,
-                           xmlAttrPtr attr, const xmlChar * string)
+                           xmlAttrPtr attr ATTRIBUTE_UNUSED,
+                           const xmlChar *string)
 {
-    xmlBufPtr buffer;
+    xmlOutputBufferPtr out;
 
     if ((buf == NULL) || (string == NULL))
         return;
-    buffer = xmlBufFromBuffer(buf);
-    if (buffer == NULL)
-        return;
-    xmlBufAttrSerializeTxtContent(buffer, doc, attr, string);
-    xmlBufBackToBuffer(buffer);
+    out = xmlOutputBufferCreateBuffer(buf, NULL);
+    xmlBufAttrSerializeTxtContent(out, doc, string);
+    xmlOutputBufferFlush(out);
+    if ((out == NULL) || (out->error))
+        xmlFree(xmlBufferDetach(buf));
+    xmlOutputBufferClose(out);
 }
 
 /**
@@ -2171,6 +2446,10 @@ xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
 
     if ((buf == NULL) || (cur == NULL))
         return(-1);
+    if (level < 0)
+        level = 0;
+    else if (level > 100)
+        level = 100;
     buffer = xmlBufFromBuffer(buf);
     if (buffer == NULL)
         return(-1);
@@ -2178,7 +2457,7 @@ xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
     xmlBufBackToBuffer(buffer);
     if (ret > INT_MAX)
         return(-1);
-    return((int) ret);
+    return(ret);
 }
 
 /**
@@ -2202,30 +2481,22 @@ xmlBufNodeDump(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
             int format)
 {
     size_t use;
-    int ret;
+    size_t ret;
     xmlOutputBufferPtr outbuf;
     int oldalloc;
 
     xmlInitParser();
 
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlNodeDump : node == NULL\n");
-#endif
-        return (-1);
+        return ((size_t) -1);
     }
     if (buf == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlNodeDump : buf == NULL\n");
-#endif
-        return (-1);
+        return ((size_t) -1);
     }
     outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
     if (outbuf == NULL) {
-        xmlSaveErrMemory("creating buffer");
-        return (-1);
+        xmlSaveErrMemory(NULL);
+        return ((size_t) -1);
     }
     memset(outbuf, 0, (size_t) sizeof(xmlOutputBuffer));
     outbuf->buffer = buf;
@@ -2240,8 +2511,11 @@ xmlBufNodeDump(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
     xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
     xmlNodeDumpOutput(outbuf, doc, cur, level, format, NULL);
     xmlBufSetAllocationScheme(buf, oldalloc);
+    if (outbuf->error)
+        ret = (size_t) -1;
+    else
+        ret = xmlBufUse(buf) - use;
     xmlFree(outbuf);
-    ret = xmlBufUse(buf) - use;
     return (ret);
 }
 
@@ -2261,29 +2535,17 @@ xmlElemDump(FILE * f, xmlDocPtr doc, xmlNodePtr cur)
     xmlInitParser();
 
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlElemDump : cur == NULL\n");
-#endif
         return;
     }
-#ifdef DEBUG_TREE
-    if (doc == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlElemDump : doc == NULL\n");
-    }
-#endif
 
     outbuf = xmlOutputBufferCreateFile(f, NULL);
     if (outbuf == NULL)
         return;
-    if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
 #ifdef LIBXML_HTML_ENABLED
+    if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE))
         htmlNodeDumpOutput(outbuf, doc, cur, NULL);
-#else
-	xmlSaveErr(XML_ERR_INTERNAL_ERROR, cur, "HTML support not compiled in\n");
+    else
 #endif /* LIBXML_HTML_ENABLED */
-    } else
         xmlNodeDumpOutput(outbuf, doc, cur, 0, 1, NULL);
     xmlOutputBufferClose(outbuf);
 }
@@ -2317,10 +2579,17 @@ xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
     int is_xhtml = 0;
 #endif
 
+    (void) doc;
+
     xmlInitParser();
 
     if ((buf == NULL) || (cur == NULL)) return;
 
+    if (level < 0)
+        level = 0;
+    else if (level > 100)
+        level = 100;
+
     if (encoding == NULL)
         encoding = "UTF-8";
 
@@ -2396,16 +2665,19 @@ xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
     if (txt_encoding == NULL)
 	txt_encoding = (const char *) out_doc->encoding;
     if (txt_encoding != NULL) {
-	conv_hdlr = xmlFindCharEncodingHandler(txt_encoding);
-	if ( conv_hdlr == NULL ) {
-	    xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, (xmlNodePtr) out_doc,
-		       txt_encoding);
+        int res;
+
+	res = xmlOpenCharEncodingHandler(txt_encoding, /* output */ 1,
+                                         &conv_hdlr);
+	if (res != XML_ERR_OK) {
+            xmlSaveErr(NULL, res, NULL, txt_encoding);
 	    return;
 	}
     }
 
     if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) {
-        xmlSaveErrMemory("creating buffer");
+        xmlSaveErrMemory(NULL);
+        xmlCharEncCloseFunc(conv_hdlr);
         return;
     }
 
@@ -2418,21 +2690,18 @@ xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
     ctxt.options |= XML_SAVE_AS_XML;
     xmlDocContentDumpOutput(&ctxt, out_doc);
     xmlOutputBufferFlush(out_buff);
-    if (out_buff->conv != NULL) {
-	*doc_txt_len = xmlBufUse(out_buff->conv);
-	*doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->conv), *doc_txt_len);
-    } else {
-	*doc_txt_len = xmlBufUse(out_buff->buffer);
-	*doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->buffer),*doc_txt_len);
-    }
-    (void)xmlOutputBufferClose(out_buff);
 
-    if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) {
-        *doc_txt_len = 0;
-        xmlSaveErrMemory("creating output");
+    if (!out_buff->error) {
+        if (out_buff->conv != NULL) {
+            *doc_txt_len = xmlBufUse(out_buff->conv);
+            *doc_txt_ptr = xmlBufDetach(out_buff->conv);
+        } else {
+            *doc_txt_len = xmlBufUse(out_buff->buffer);
+            *doc_txt_ptr = xmlBufDetach(out_buff->buffer);
+        }
     }
 
-    return;
+    xmlOutputBufferClose(out_buff);
 }
 
 /**
@@ -2509,17 +2778,15 @@ xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) {
     int ret;
 
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlDocDump : document == NULL\n");
-#endif
 	return(-1);
     }
     encoding = (const char *) cur->encoding;
 
     if (encoding != NULL) {
-	handler = xmlFindCharEncodingHandler(encoding);
-	if (handler == NULL) {
+        int res;
+
+	res = xmlOpenCharEncodingHandler(encoding, /* output */ 1, &handler);
+	if (res != XML_ERR_OK) {
 	    xmlFree((char *) cur->encoding);
 	    cur->encoding = NULL;
 	    encoding = NULL;
@@ -2655,10 +2922,11 @@ xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur,
 	encoding = (const char *) cur->encoding;
 
     if (encoding != NULL) {
+        int res;
 
-	    handler = xmlFindCharEncodingHandler(encoding);
-	    if (handler == NULL)
-		return(-1);
+        res = xmlOpenCharEncodingHandler(encoding, /* output */ 1, &handler);
+        if (res != XML_ERR_OK)
+            return(-1);
     }
 
 #ifdef LIBXML_ZLIB_ENABLED
diff --git a/xmlschemas.c b/xmlschemas.c
index f31d3d1f618f7f8419f2d38fb5270000f3fe53a3..48b4e328ab83df28d0a94ba2050d5c32e63120a2 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -76,28 +76,11 @@
 #include <libxml/xmlreader.h>
 #endif
 
-/* #define DEBUG 1 */
-
-/* #define DEBUG_CONTENT 1 */
-
-/* #define DEBUG_TYPE 1 */
-
-/* #define DEBUG_CONTENT_REGEXP 1 */
-
-/* #define DEBUG_AUTOMATA 1 */
-
-/* #define DEBUG_IDC */
-
-/* #define DEBUG_IDC_NODE_TABLE */
+#include "private/error.h"
+#include "private/string.h"
 
 /* #define WXS_ELEM_DECL_CONS_ENABLED */
 
-#ifdef DEBUG_IDC
- #ifndef DEBUG_IDC_NODE_TABLE
-  #define DEBUG_IDC_NODE_TABLE
- #endif
-#endif
-
 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
 
 #define ENABLE_REDEFINE
@@ -113,10 +96,6 @@
 #endif
 
 #define UNBOUNDED (1 << 30)
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
 
 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
 
@@ -305,10 +284,20 @@ static const xmlChar *xmlNamespaceNs = (const xmlChar *)
 #define WXS_SCHEMA(ctx) (ctx)->schema
 
 #define WXS_ADD_LOCAL(ctx, item) \
-    xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
+    do { \
+        if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item) < 0) { \
+            xmlFree(item); \
+            item = NULL; \
+        } \
+    } while (0)
 
 #define WXS_ADD_GLOBAL(ctx, item) \
-    xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
+    do { \
+        if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item) < 0) { \
+            xmlFree(item); \
+            item = NULL; \
+        } \
+    } while (0)
 
 #define WXS_ADD_PENDING(ctx, item) \
     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
@@ -1905,22 +1894,6 @@ xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
  *									*
  ************************************************************************/
 
-#if 0
-static void
-xmlSchemaErrMemory(const char *msg)
-{
-    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
-                     msg);
-}
-#endif
-
-static void
-xmlSchemaPSimpleErr(const char *msg)
-{
-    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
-                     msg);
-}
-
 /**
  * xmlSchemaPErrMemory:
  * @node: a context node
@@ -1929,13 +1902,66 @@ xmlSchemaPSimpleErr(const char *msg)
  * Handle an out of memory condition
  */
 static void
-xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
-                    const char *extra, xmlNodePtr node)
+xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt)
 {
-    if (ctxt != NULL)
+    xmlGenericErrorFunc channel = NULL;
+    xmlStructuredErrorFunc schannel = NULL;
+    void *data = NULL;
+
+    if (ctxt != NULL) {
         ctxt->nberrors++;
-    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
-                     extra);
+        ctxt->err = XML_ERR_NO_MEMORY;
+        channel = ctxt->error;
+        schannel = ctxt->serror;
+        data = ctxt->errCtxt;
+    }
+
+    xmlRaiseMemoryError(schannel, channel, data, XML_FROM_SCHEMASP, NULL);
+}
+
+static void LIBXML_ATTR_FORMAT(11,12)
+xmlSchemaPErrFull(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
+                  xmlErrorLevel level, const char *file, int line,
+                  const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
+                  int col, const char *msg, ...) {
+    xmlGenericErrorFunc channel = NULL;
+    xmlStructuredErrorFunc schannel = NULL;
+    void *data = NULL;
+    int res;
+    va_list ap;
+
+    if (ctxt != NULL) {
+        /* Don't overwrite memory errors */
+        if (ctxt->err == XML_ERR_NO_MEMORY)
+            return;
+
+        if (level == XML_ERR_WARNING) {
+            channel = ctxt->warning;
+        } else {
+            ctxt->nberrors++;
+            ctxt->err = code;
+            channel = ctxt->error;
+        }
+        data = ctxt->errCtxt;
+        schannel = ctxt->serror;
+    }
+
+    if ((channel == NULL) && (schannel == NULL)) {
+        channel = xmlGenericError;
+        data = xmlGenericErrorContext;
+    }
+
+    va_start(ap, msg);
+    res = xmlVRaiseError(schannel, channel, data, ctxt, node,
+                         XML_FROM_SCHEMASP, code, level, file, line,
+                         (const char *) str1,
+                         (const char *) str2,
+                         (const char *) str3,
+                         0, col, msg, ap);
+    va_end(ap);
+
+    if (res < 0)
+        xmlSchemaPErrMemory(ctxt);
 }
 
 /**
@@ -1950,24 +1976,11 @@ xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
  * Handle a parser error
  */
 static void LIBXML_ATTR_FORMAT(4,0)
-xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
+xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
               const char *msg, const xmlChar * str1, const xmlChar * str2)
 {
-    xmlGenericErrorFunc channel = NULL;
-    xmlStructuredErrorFunc schannel = NULL;
-    void *data = NULL;
-
-    if (ctxt != NULL) {
-        ctxt->nberrors++;
-	ctxt->err = error;
-        channel = ctxt->error;
-        data = ctxt->errCtxt;
-	schannel = ctxt->serror;
-    }
-    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
-                    error, XML_ERR_ERROR, NULL, 0,
-                    (const char *) str1, (const char *) str2, NULL, 0, 0,
-                    msg, str1, str2);
+    xmlSchemaPErrFull(ctxt, node, code, XML_ERR_ERROR, NULL, 0,
+                      str1, str2, NULL, 0, msg, str1, str2);
 }
 
 /**
@@ -2012,29 +2025,15 @@ xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
  * Handle a parser error
  */
 static void LIBXML_ATTR_FORMAT(7,0)
-xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
+xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
 		const xmlChar * strData1, const xmlChar * strData2,
 		const xmlChar * strData3, const char *msg, const xmlChar * str1,
 		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
 		const xmlChar * str5)
 {
-
-    xmlGenericErrorFunc channel = NULL;
-    xmlStructuredErrorFunc schannel = NULL;
-    void *data = NULL;
-
-    if (ctxt != NULL) {
-        ctxt->nberrors++;
-	ctxt->err = error;
-        channel = ctxt->error;
-        data = ctxt->errCtxt;
-	schannel = ctxt->serror;
-    }
-    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
-                    error, XML_ERR_ERROR, NULL, 0,
-                    (const char *) strData1, (const char *) strData2,
-		    (const char *) strData3, 0, 0, msg, str1, str2,
-		    str3, str4, str5);
+    xmlSchemaPErrFull(ctxt, node, code, XML_ERR_ERROR, NULL, 0,
+                      strData1, strData2, strData3, 0,
+                      msg, str1, str2, str3, str4, str5);
 }
 
 /************************************************************************
@@ -2051,23 +2050,66 @@ xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
  * Handle an out of memory condition
  */
 static void
-xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
-                    const char *extra, xmlNodePtr node)
+xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt)
 {
+    xmlGenericErrorFunc channel = NULL;
+    xmlStructuredErrorFunc schannel = NULL;
+    void *data = NULL;
+
     if (ctxt != NULL) {
         ctxt->nberrors++;
-        ctxt->err = XML_SCHEMAV_INTERNAL;
+        ctxt->err = XML_ERR_NO_MEMORY;
+        channel = ctxt->error;
+        schannel = ctxt->serror;
+        data = ctxt->errCtxt;
     }
-    __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
-                     extra);
+
+    xmlRaiseMemoryError(schannel, channel, data, XML_FROM_SCHEMASV, NULL);
 }
 
-static void LIBXML_ATTR_FORMAT(2,0)
-xmlSchemaPSimpleInternalErr(xmlNodePtr node,
-			    const char *msg, const xmlChar *str)
-{
-     __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
-	 msg, (const char *) str);
+static void LIBXML_ATTR_FORMAT(11,12)
+xmlSchemaVErrFull(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int code,
+                  xmlErrorLevel level, const char *file, int line,
+                  const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
+                  int col, const char *msg, ...) {
+    xmlGenericErrorFunc channel = NULL;
+    xmlStructuredErrorFunc schannel = NULL;
+    void *data = NULL;
+    int res;
+    va_list ap;
+
+    if (ctxt != NULL) {
+        /* Don't overwrite memory errors */
+        if (ctxt->err == XML_ERR_NO_MEMORY)
+            return;
+
+        if (level == XML_ERR_WARNING) {
+            channel = ctxt->warning;
+        } else {
+            ctxt->nberrors++;
+            ctxt->err = code;
+            channel = ctxt->error;
+        }
+        data = ctxt->errCtxt;
+        schannel = ctxt->serror;
+    }
+
+    if ((channel == NULL) && (schannel == NULL)) {
+        channel = xmlGenericError;
+        data = xmlGenericErrorContext;
+    }
+
+    va_start(ap, msg);
+    res = xmlVRaiseError(schannel, channel, data, ctxt, node,
+                         XML_FROM_SCHEMASV, code, level, file, line,
+                         (const char *) str1,
+                         (const char *) str2,
+                         (const char *) str3,
+                         0, col, msg, ap);
+    va_end(ap);
+
+    if (res < 0)
+        xmlSchemaVErrMemory(ctxt);
 }
 
 #define WXS_ERROR_TYPE_ERROR 1
@@ -2090,28 +2132,15 @@ xmlSchemaPSimpleInternalErr(xmlNodePtr node,
 static void LIBXML_ATTR_FORMAT(6,0)
 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
 		  xmlErrorLevel errorLevel,
-		  int error, xmlNodePtr node, int line, const char *msg,
+		  int code, xmlNodePtr node, int line, const char *msg,
 		  const xmlChar *str1, const xmlChar *str2,
 		  const xmlChar *str3, const xmlChar *str4)
 {
-    xmlStructuredErrorFunc schannel = NULL;
-    xmlGenericErrorFunc channel = NULL;
-    void *data = NULL;
-
     if (ctxt != NULL) {
 	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
 	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
 	    const char *file = NULL;
 	    int col = 0;
-	    if (errorLevel != XML_ERR_WARNING) {
-		vctxt->nberrors++;
-		vctxt->err = error;
-		channel = vctxt->error;
-	    } else {
-		channel = vctxt->warning;
-	    }
-	    schannel = vctxt->serror;
-	    data = vctxt->errCtxt;
 
 	    /*
 	    * Error node. If we specify a line number, then
@@ -2130,8 +2159,14 @@ xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
 		    (vctxt->parserCtxt != NULL) &&
 		    (vctxt->parserCtxt->input != NULL)) {
 		    file = vctxt->parserCtxt->input->filename;
-		    line = vctxt->parserCtxt->input->line;
-		    col = vctxt->parserCtxt->input->col;
+                    if (vctxt->inode != NULL) {
+		        line = vctxt->inode->nodeLine;
+                        col = 0;
+                    } else {
+                        /* This is inaccurate. */
+		        line = vctxt->parserCtxt->input->line;
+		        col = vctxt->parserCtxt->input->col;
+                    }
 		}
 	    } else {
 		/*
@@ -2162,30 +2197,15 @@ xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
 	    if ((file == NULL) && (vctxt->filename != NULL))
 	        file = vctxt->filename;
 
-	    __xmlRaiseError(schannel, channel, data, ctxt,
-		node, XML_FROM_SCHEMASV,
-		error, errorLevel, file, line,
-		(const char *) str1, (const char *) str2,
-		(const char *) str3, 0, col, msg, str1, str2, str3, str4);
-
+            xmlSchemaVErrFull(vctxt, node, code, errorLevel,
+                              file, line, str1, str2, str3, col,
+                              msg, str1, str2, str3, str4);
 	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
 	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
-	    if (errorLevel != XML_ERR_WARNING) {
-		pctxt->nberrors++;
-		pctxt->err = error;
-		channel = pctxt->error;
-	    } else {
-		channel = pctxt->warning;
-	    }
-	    schannel = pctxt->serror;
-	    data = pctxt->errCtxt;
-	    __xmlRaiseError(schannel, channel, data, ctxt,
-		node, XML_FROM_SCHEMASP, error,
-		errorLevel, NULL, 0,
-		(const char *) str1, (const char *) str2,
-		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
-	} else {
-	    TODO
+
+            xmlSchemaPErrFull(pctxt, node, code, errorLevel,
+                              NULL, 0, str1, str2, str3, 0,
+                              msg, str1, str2, str3, str4);
 	}
     }
 }
@@ -2306,7 +2326,7 @@ xmlSchemaFormatNodeForError(xmlChar ** msg,
 	*/
 	*msg = xmlStrdup(BAD_CAST "");
     } else {
-	TODO
+	/* TODO */
 	return (NULL);
     }
 
@@ -3323,7 +3343,7 @@ xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
 
     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchema));
@@ -3370,7 +3390,7 @@ xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
 
     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaAnnot));
@@ -3385,8 +3405,7 @@ xmlSchemaItemListCreate(void)
 
     ret = xmlMalloc(sizeof(xmlSchemaItemList));
     if (ret == NULL) {
-	xmlSchemaPErrMemory(NULL,
-	    "allocating an item list structure", NULL);
+	xmlSchemaPErrMemory(NULL);
 	return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaItemList));
@@ -3407,23 +3426,17 @@ xmlSchemaItemListClear(xmlSchemaItemListPtr list)
 static int
 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
 {
-    if (list->items == NULL) {
-	list->items = (void **) xmlMalloc(
-	    20 * sizeof(void *));
-	if (list->items == NULL) {
-	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
-	    return(-1);
-	}
-	list->sizeItems = 20;
-    } else if (list->sizeItems <= list->nbItems) {
-	list->sizeItems *= 2;
-	list->items = (void **) xmlRealloc(list->items,
-	    list->sizeItems * sizeof(void *));
-	if (list->items == NULL) {
-	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
-	    list->sizeItems = 0;
+    if (list->sizeItems <= list->nbItems) {
+        void **tmp;
+        size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
+
+	tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
+	if (tmp == NULL) {
+	    xmlSchemaPErrMemory(NULL);
 	    return(-1);
 	}
+        list->items = tmp;
+	list->sizeItems = newSize;
     }
     list->items[list->nbItems++] = item;
     return(0);
@@ -3440,19 +3453,22 @@ xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
 	list->items = (void **) xmlMalloc(
 	    initialSize * sizeof(void *));
 	if (list->items == NULL) {
-	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
+	    xmlSchemaPErrMemory(NULL);
 	    return(-1);
 	}
 	list->sizeItems = initialSize;
     } else if (list->sizeItems <= list->nbItems) {
+        void **tmp;
+
 	list->sizeItems *= 2;
-	list->items = (void **) xmlRealloc(list->items,
+	tmp = (void **) xmlRealloc(list->items,
 	    list->sizeItems * sizeof(void *));
-	if (list->items == NULL) {
-	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
-	    list->sizeItems = 0;
+	if (tmp == NULL) {
+	    xmlSchemaPErrMemory(NULL);
+	    list->sizeItems /= 2;
 	    return(-1);
 	}
+        list->items = tmp;
     }
     list->items[list->nbItems++] = item;
     return(0);
@@ -3461,23 +3477,17 @@ xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
 static int
 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
 {
-    if (list->items == NULL) {
-	list->items = (void **) xmlMalloc(
-	    20 * sizeof(void *));
-	if (list->items == NULL) {
-	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
-	    return(-1);
-	}
-	list->sizeItems = 20;
-    } else if (list->sizeItems <= list->nbItems) {
-	list->sizeItems *= 2;
-	list->items = (void **) xmlRealloc(list->items,
-	    list->sizeItems * sizeof(void *));
-	if (list->items == NULL) {
-	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
-	    list->sizeItems = 0;
+    if (list->sizeItems <= list->nbItems) {
+        void **tmp;
+        size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
+
+	tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
+	if (tmp == NULL) {
+	    xmlSchemaPErrMemory(NULL);
 	    return(-1);
 	}
+        list->items = tmp;
+	list->sizeItems = newSize;
     }
     /*
     * Just append if the index is greater/equal than the item count.
@@ -3507,7 +3517,7 @@ xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
 	list->items = (void **) xmlMalloc(
 	    initialSize * sizeof(void *));
 	if (list->items == NULL) {
-	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
+	    xmlSchemaPErrMemory(NULL);
 	    return(-1);
 	}
 	list->sizeItems = initialSize;
@@ -3516,7 +3526,7 @@ xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
 	list->items = (void **) xmlRealloc(list->items,
 	    list->sizeItems * sizeof(void *));
 	if (list->items == NULL) {
-	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
+	    xmlSchemaPErrMemory(NULL);
 	    list->sizeItems = 0;
 	    return(-1);
 	}
@@ -3541,11 +3551,8 @@ static int
 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
 {
     int i;
-    if ((list->items == NULL) || (idx >= list->nbItems)) {
-	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
-	    "index error.\n");
+    if ((list->items == NULL) || (idx >= list->nbItems))
 	return(-1);
-    }
 
     if (list->nbItems == 1) {
 	/* TODO: Really free the list? */
@@ -3637,7 +3644,7 @@ xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
 	size = sizeof(xmlSchemaImport);
     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
     if (ret == NULL) {
-	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
+	xmlSchemaPErrMemory(NULL);
 	return(NULL);
     }
     memset(ret, 0, size);
@@ -3645,12 +3652,12 @@ xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
     ret->type = type;
     ret->globals = xmlSchemaItemListCreate();
     if (ret->globals == NULL) {
-	xmlFree(ret);
+	xmlSchemaBucketFree(ret);
 	return(NULL);
     }
     ret->locals = xmlSchemaItemListCreate();
     if (ret->locals == NULL) {
-	xmlFree(ret);
+	xmlSchemaBucketFree(ret);
 	return(NULL);
     }
     /*
@@ -3739,7 +3746,10 @@ xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
 		return(NULL);
 	    }
 	}
-	xmlSchemaItemListAdd(mainSchema->includes, ret);
+	if (xmlSchemaItemListAdd(mainSchema->includes, ret) < 0) {
+	    xmlSchemaBucketFree(ret);
+	    return(NULL);
+        }
     }
     /*
     * Add to list of all buckets; this is used for lookup
@@ -3758,8 +3768,7 @@ xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
 	if (*list == NULL)
 	    return(-1);
     }
-    xmlSchemaItemListAddSize(*list, initialSize, item);
-    return(0);
+    return(xmlSchemaItemListAddSize(*list, initialSize, item));
 }
 
 /**
@@ -3797,6 +3806,8 @@ xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
 {
     if (nota == NULL)
         return;
+    if (nota->annot != NULL)
+	xmlSchemaFreeAnnot(nota->annot);
     xmlFree(nota);
 }
 
@@ -4161,13 +4172,8 @@ xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
 		case XML_SCHEMA_EXTRA_QNAMEREF:
 		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
 		    break;
-		default: {
+		default:
 		    /* TODO: This should never be hit. */
-		    xmlSchemaPSimpleInternalErr(NULL,
-			"Internal error: xmlSchemaComponentListFree, "
-			"unexpected component type '%s'\n",
-			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
-			 }
 		    break;
 	    }
 	}
@@ -4186,9 +4192,6 @@ xmlSchemaFree(xmlSchemaPtr schema)
 {
     if (schema == NULL)
         return;
-    /* @volatiles is not used anymore :-/ */
-    if (schema->volatiles != NULL)
-	TODO
     /*
     * Note that those slots are not responsible for freeing
     * schema components anymore; this will now be done by
@@ -4606,83 +4609,6 @@ xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
     xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
 }
 
-#ifdef DEBUG_IDC_NODE_TABLE
-/**
- * xmlSchemaDebugDumpIDCTable:
- * @vctxt: the WXS validation context
- *
- * Displays the current IDC table for debug purposes.
- */
-static void
-xmlSchemaDebugDumpIDCTable(FILE * output,
-			   const xmlChar *namespaceName,
-			   const xmlChar *localName,
-			   xmlSchemaPSVIIDCBindingPtr bind)
-{
-    xmlChar *str = NULL;
-    const xmlChar *value;
-    xmlSchemaPSVIIDCNodePtr tab;
-    xmlSchemaPSVIIDCKeyPtr key;
-    int i, j, res;
-
-    fprintf(output, "IDC: TABLES on '%s'\n",
-	xmlSchemaFormatQName(&str, namespaceName, localName));
-    FREE_AND_NULL(str)
-
-    if (bind == NULL)
-	return;
-    do {
-	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
-	    xmlSchemaGetComponentQName(&str,
-		bind->definition), bind->nbNodes);
-	FREE_AND_NULL(str)
-	for (i = 0; i < bind->nbNodes; i++) {
-	    tab = bind->nodeTable[i];
-	    fprintf(output, "         ( ");
-	    for (j = 0; j < bind->definition->nbFields; j++) {
-		key = tab->keys[j];
-		if ((key != NULL) && (key->val != NULL)) {
-		    res = xmlSchemaGetCanonValue(key->val, &value);
-		    if (res >= 0)
-			fprintf(output, "'%s' ", value);
-		    else
-			fprintf(output, "CANON-VALUE-FAILED ");
-		    if (res == 0)
-			FREE_AND_NULL(value)
-		} else if (key != NULL)
-		    fprintf(output, "(no val), ");
-		else
-		    fprintf(output, "(key missing), ");
-	    }
-	    fprintf(output, ")\n");
-	}
-	if (bind->dupls && bind->dupls->nbItems) {
-	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
-	    for (i = 0; i < bind->dupls->nbItems; i++) {
-		tab = bind->dupls->items[i];
-		fprintf(output, "         ( ");
-		for (j = 0; j < bind->definition->nbFields; j++) {
-		    key = tab->keys[j];
-		    if ((key != NULL) && (key->val != NULL)) {
-			res = xmlSchemaGetCanonValue(key->val, &value);
-			if (res >= 0)
-			    fprintf(output, "'%s' ", value);
-			else
-			    fprintf(output, "CANON-VALUE-FAILED ");
-			if (res == 0)
-			    FREE_AND_NULL(value)
-		    } else if (key != NULL)
-		    fprintf(output, "(no val), ");
-			else
-			    fprintf(output, "(key missing), ");
-		}
-		fprintf(output, ")\n");
-	    }
-	}
-	bind = bind->next;
-    } while (bind != NULL);
-}
-#endif /* DEBUG_IDC */
 #endif /* LIBXML_OUTPUT_ENABLED */
 
 /************************************************************************
@@ -4757,6 +4683,8 @@ xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
 	val = xmlStrdup((xmlChar *)"");
     ret = xmlDictLookup(ctxt->dict, val, -1);
     xmlFree(val);
+    if (ret == NULL)
+        xmlSchemaPErrMemory(ctxt);
     return(ret);
 }
 
@@ -4836,15 +4764,6 @@ xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
 	WXS_FIND_GLOBAL_ITEM(elemDecl)
     }
 exit:
-#ifdef DEBUG
-    if (ret == NULL) {
-        if (nsName == NULL)
-            fprintf(stderr, "Unable to lookup element decl. %s", name);
-        else
-            fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
-                    nsName);
-    }
-#endif
     return (ret);
 }
 
@@ -4883,15 +4802,6 @@ xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
     }
 exit:
 
-#ifdef DEBUG
-    if (ret == NULL) {
-        if (nsName == NULL)
-            fprintf(stderr, "Unable to lookup type %s", name);
-        else
-            fprintf(stderr, "Unable to lookup type %s:%s", name,
-                    nsName);
-    }
-#endif
     return (ret);
 }
 
@@ -4917,15 +4827,6 @@ xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
 	WXS_FIND_GLOBAL_ITEM(attrDecl)
     }
 exit:
-#ifdef DEBUG
-    if (ret == NULL) {
-        if (nsName == NULL)
-            fprintf(stderr, "Unable to lookup attribute %s", name);
-        else
-            fprintf(stderr, "Unable to lookup attribute %s:%s", name,
-                    nsName);
-    }
-#endif
     return (ret);
 }
 
@@ -4957,15 +4858,6 @@ exit:
 	ret = ret->redef;
     }
     */
-#ifdef DEBUG
-    if (ret == NULL) {
-        if (nsName == NULL)
-            fprintf(stderr, "Unable to lookup attribute group %s", name);
-        else
-            fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
-                    nsName);
-    }
-#endif
     return (ret);
 }
 
@@ -4992,15 +4884,6 @@ xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
     }
 exit:
 
-#ifdef DEBUG
-    if (ret == NULL) {
-        if (nsName == NULL)
-            fprintf(stderr, "Unable to lookup group %s", name);
-        else
-            fprintf(stderr, "Unable to lookup group %s:%s", name,
-                    nsName);
-    }
-#endif
     return (ret);
 }
 
@@ -5060,7 +4943,7 @@ xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
 		name, targetNs));
 	default:
-	    TODO
+	    /* TODO */
 	    return (NULL);
     }
 }
@@ -5214,7 +5097,7 @@ xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
 
     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaNotation));
@@ -5251,7 +5134,7 @@ xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
 
     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaAttribute));
@@ -5291,7 +5174,7 @@ xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
 
     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
+        xmlSchemaPErrMemory(pctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
@@ -5320,8 +5203,7 @@ xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
     ret = (xmlSchemaRedefPtr)
 	xmlMalloc(sizeof(xmlSchemaRedef));
     if (ret == NULL) {
-	xmlSchemaPErrMemory(pctxt,
-	    "allocating redefinition info", NULL);
+	xmlSchemaPErrMemory(pctxt);
 	return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaRedef));
@@ -5365,7 +5247,7 @@ xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
     ret = (xmlSchemaAttributeGroupPtr)
         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
     if (ret == NULL) {
-	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
+	xmlSchemaPErrMemory(pctxt);
 	return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
@@ -5414,7 +5296,7 @@ xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
 
     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaElement));
@@ -5456,7 +5338,7 @@ xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
 
     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaType));
@@ -5492,8 +5374,7 @@ xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
     ret = (xmlSchemaQNameRefPtr)
 	xmlMalloc(sizeof(xmlSchemaQNameRef));
     if (ret == NULL) {
-	xmlSchemaPErrMemory(pctxt,
-	    "allocating QName reference item", NULL);
+	xmlSchemaPErrMemory(pctxt);
 	return (NULL);
     }
     ret->node = NULL;
@@ -5517,8 +5398,7 @@ xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
     ret = (xmlSchemaAttributeUseProhibPtr)
 	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
     if (ret == NULL) {
-	xmlSchemaPErrMemory(pctxt,
-	    "allocating attribute use prohibition", NULL);
+	xmlSchemaPErrMemory(pctxt);
 	return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
@@ -5554,8 +5434,7 @@ xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
     ret = (xmlSchemaModelGroupPtr)
 	xmlMalloc(sizeof(xmlSchemaModelGroup));
     if (ret == NULL) {
-	xmlSchemaPErrMemory(ctxt, "allocating model group component",
-	    NULL);
+	xmlSchemaPErrMemory(ctxt);
 	return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaModelGroup));
@@ -5590,14 +5469,10 @@ xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
     if (ctxt == NULL)
         return (NULL);
 
-#ifdef DEBUG
-    fprintf(stderr, "Adding particle component\n");
-#endif
     ret = (xmlSchemaParticlePtr)
 	xmlMalloc(sizeof(xmlSchemaParticle));
     if (ret == NULL) {
-	xmlSchemaPErrMemory(ctxt, "allocating particle component",
-	    NULL);
+	xmlSchemaPErrMemory(ctxt);
 	return (NULL);
     }
     ret->type = XML_SCHEMA_TYPE_PARTICLE;
@@ -5643,7 +5518,7 @@ xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
     ret = (xmlSchemaModelGroupDefPtr)
 	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(ctxt, "adding group", NULL);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
@@ -5682,7 +5557,7 @@ xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
     ret = (xmlSchemaWildcardNsPtr)
 	xmlMalloc(sizeof(xmlSchemaWildcardNs));
     if (ret == NULL) {
-	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
+	xmlSchemaPErrMemory(ctxt);
 	return (NULL);
     }
     ret->value = NULL;
@@ -5702,8 +5577,7 @@ xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
 
     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(ctxt,
-	    "allocating an identity-constraint definition", NULL);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaIDC));
@@ -5743,7 +5617,7 @@ xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
 
     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaWildcard));
@@ -5784,8 +5658,7 @@ xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
     /* Create a new substitution group. */
     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
     if (ret == NULL) {
-	xmlSchemaPErrMemory(NULL,
-	    "allocating a substitution group container", NULL);
+	xmlSchemaPErrMemory(NULL);
 	return(NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
@@ -6025,8 +5898,8 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
 	* NOTE: the IDness might have already be declared in the DTD
 	*/
 	if (attr->atype != XML_ATTRIBUTE_ID) {
-	    xmlIDPtr res;
 	    xmlChar *strip;
+            int res;
 
 	    /*
 	    * TODO: Use xmlSchemaStrip here; it's not exported at this
@@ -6037,8 +5910,10 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
 		xmlFree((xmlChar *) value);
 		value = strip;
 	    }
-	    res = xmlAddID(NULL, attr->doc, value, attr);
-	    if (res == NULL) {
+	    res = xmlAddIDSafe(attr, value);
+            if (res < 0) {
+                xmlSchemaPErrMemory(ctxt);
+	    } else if (res == 0) {
 		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
 		xmlSchemaPSimpleTypeErr(ctxt,
 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
@@ -6046,8 +5921,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
 		    NULL, NULL, "Duplicate value '%s' of simple "
 		    "type 'xs:ID'", value, NULL);
-	    } else
-		attr->atype = XML_ATTRIBUTE_ID;
+	    }
 	}
     } else if (ret > 0) {
 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
@@ -6100,6 +5974,8 @@ xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
     if (attr == NULL)
 	return (def);
     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
+    if (val == NULL)
+        return (def);
 
     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
 	if (max != UNBOUNDED) {
@@ -6174,6 +6050,8 @@ xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
     if (attr == NULL)
 	return (def);
     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
+    if (val == NULL)
+	return (def);
     cur = val;
     while (IS_BLANK_CH(*cur))
         cur++;
@@ -6732,7 +6610,7 @@ xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
 
     facet = xmlSchemaNewFacet();
     if (facet == NULL) {
-        xmlSchemaPErrMemory(ctxt, "allocating facet", node);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     facet->node = node;
@@ -6846,6 +6724,8 @@ xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
      */
     attr = xmlSchemaGetPropNode(node, "namespace");
     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
+    if (ns == NULL)
+        return (-1);
     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
 	wildc->any = 1;
     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
@@ -8140,8 +8020,7 @@ xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
 	    nsArray = (const xmlChar **) xmlMalloc(
 		(count * 2 + 1) * sizeof(const xmlChar *));
 	    if (nsArray == NULL) {
-		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
-		    NULL);
+		xmlSchemaPErrMemory(ctxt);
 		xmlFree(nsList);
 		return (-1);
 	    }
@@ -8184,7 +8063,7 @@ xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
 	return (annot);         \
     }                           \
     cur = item->annot;          \
-    if (cur->next != NULL) {    \
+    while (cur->next != NULL) { \
 	cur = cur->next;	\
     }                           \
     cur->next = annot;
@@ -8328,9 +8207,7 @@ xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
     */
     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
     if (item == NULL) {
-        xmlSchemaPErrMemory(ctxt,
-	    "allocating a 'selector' of an identity-constraint definition",
-	    NULL);
+        xmlSchemaPErrMemory(ctxt);
         return (NULL);
     }
     memset(item, 0, sizeof(xmlSchemaIDCSelect));
@@ -8994,6 +8871,8 @@ xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
 	xmlSchemaQNameRefPtr ref;
 
 	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
+        if (cur == NULL)
+            return (-1);
 	type->base = cur;
 	do {
 	    while (IS_BLANK_CH(*cur))
@@ -9004,6 +8883,10 @@ xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
 	    if (end == cur)
 		break;
 	    tmp = xmlStrndup(cur, end - cur);
+            if (tmp == NULL) {
+                xmlSchemaPErrMemory(ctxt);
+                return (-1);
+            }
 	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
 		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
 		/*
@@ -9012,8 +8895,8 @@ xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
 		link = (xmlSchemaTypeLinkPtr)
 		    xmlMalloc(sizeof(xmlSchemaTypeLink));
 		if (link == NULL) {
-		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
-			"allocating a type link", NULL);
+		    xmlSchemaPErrMemory(ctxt);
+	            FREE_AND_NULL(tmp)
 		    return (-1);
 		}
 		link->type = NULL;
@@ -9946,7 +9829,7 @@ xmlSchemaSchemaRelationCreate(void)
     ret = (xmlSchemaSchemaRelationPtr)
 	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
     if (ret == NULL) {
-	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
+	xmlSchemaPErrMemory(NULL);
 	return(NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
@@ -10003,23 +9886,20 @@ xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
     ret = (xmlSchemaConstructionCtxtPtr)
 	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(NULL,
-	    "allocating schema construction context", NULL);
+        xmlSchemaPErrMemory(NULL);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
 
     ret->buckets = xmlSchemaItemListCreate();
     if (ret->buckets == NULL) {
-	xmlSchemaPErrMemory(NULL,
-	    "allocating list of schema buckets", NULL);
+	xmlSchemaPErrMemory(NULL);
 	xmlFree(ret);
         return (NULL);
     }
     ret->pending = xmlSchemaItemListCreate();
     if (ret->pending == NULL) {
-	xmlSchemaPErrMemory(NULL,
-	    "allocating list of pending global components", NULL);
+	xmlSchemaPErrMemory(NULL);
 	xmlSchemaConstructionCtxtFree(ret);
         return (NULL);
     }
@@ -10035,8 +9915,7 @@ xmlSchemaParserCtxtCreate(void)
 
     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
     if (ret == NULL) {
-        xmlSchemaPErrMemory(NULL, "allocating schema parser context",
-                            NULL);
+        xmlSchemaPErrMemory(NULL);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
@@ -10621,10 +10500,13 @@ doc_load:
 
 	parserCtxt = xmlNewParserCtxt();
 	if (parserCtxt == NULL) {
-	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
-		"allocating a parser context", NULL);
+	    xmlSchemaPErrMemory(NULL);
 	    goto exit_failure;
 	}
+
+        if (pctxt->serror != NULL)
+            xmlCtxtSetErrorHandler(parserCtxt, pctxt->serror, pctxt->errCtxt);
+
 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
 	    /*
 	    * TODO: Do we have to burden the schema parser dict with all
@@ -10660,7 +10542,7 @@ doc_load:
 	* TODO: (2.2) is not supported.
 	*/
 	if (doc == NULL) {
-	    xmlErrorPtr lerr;
+	    const xmlError *lerr;
 	    lerr = xmlGetLastError();
 	    /*
 	    * Check if this a parser error, or if the document could
@@ -11149,17 +11031,6 @@ xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
 	    * differ from the resulting namespace.
 	    */
 	    isChameleon = 1;
-	    if (bucket->parsed &&
-		bucket->origTargetNamespace != NULL) {
-		xmlSchemaCustomErr(ACTXT_CAST pctxt,
-		    XML_SCHEMAP_SRC_INCLUDE,
-		    node, NULL,
-		    "The target namespace of the included/redefined schema "
-		    "'%s' has to be absent or the same as the "
-		    "including/redefining schema's target namespace",
-		    schemaLocation, NULL);
-		goto exit_error;
-	    }
 	    bucket->targetNamespace = pctxt->targetNamespace;
 	}
     }
@@ -11796,7 +11667,7 @@ xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
 		facetLink = (xmlSchemaFacetLinkPtr)
 		    xmlMalloc(sizeof(xmlSchemaFacetLink));
 		if (facetLink == NULL) {
-		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
+		    xmlSchemaPErrMemory(ctxt);
 		    xmlFree(facetLink);
 		    return (NULL);
 		}
@@ -13240,15 +13111,10 @@ xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
 	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
 	return;
 
-#ifdef DEBUG_CONTENT
-    xmlGenericError(xmlGenericErrorContext,
-                    "Building content model for %s\n", name);
-#endif
     ctxt->am = NULL;
     ctxt->am = xmlNewAutomata();
     if (ctxt->am == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-	    "Cannot create automata for complex type %s\n", type->name);
+	xmlSchemaPErrMemory(ctxt);
         return;
     }
     ctxt->state = xmlAutomataGetInitState(ctxt->am);
@@ -13270,11 +13136,6 @@ xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
 	    WXS_BASIC_CAST type, type->node,
 	    "The content model is not determinist", NULL);
     } else {
-#ifdef DEBUG_CONTENT_REGEXP
-        xmlGenericError(xmlGenericErrorContext,
-                        "Content model of %s:\n", type->name);
-        xmlRegexpPrint(stderr, type->contModel);
-#endif
     }
     ctxt->state = NULL;
     xmlFreeAutomata(ctxt->am);
@@ -13345,8 +13206,19 @@ xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
 	    * declaration `resolved` to by the `actual value`
 	    * of the substitutionGroup [attribute], if present"
 	    */
-	    if (elemDecl->subtypes == NULL)
-		elemDecl->subtypes = substHead->subtypes;
+	    if (elemDecl->subtypes == NULL) {
+                if (substHead->subtypes == NULL) {
+                    /*
+                     * This can happen with self-referencing substitution
+                     * groups. The cycle will be detected later, but we have
+                     * to set subtypes to avoid null-pointer dereferences.
+                     */
+	            elemDecl->subtypes = xmlSchemaGetBuiltInType(
+                            XML_SCHEMAS_ANYTYPE);
+                } else {
+		    elemDecl->subtypes = substHead->subtypes;
+                }
+            }
 	}
     }
     /*
@@ -13424,7 +13296,7 @@ xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
     while (memberType != NULL) {
 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
 	if (link == NULL) {
-	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
+	    xmlSchemaPErrMemory(ctxt);
 	    return (-1);
 	}
 	link->type = memberType;
@@ -14536,6 +14408,7 @@ xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
 	    {
 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
 		"failed to expand attributes");
+                return(-1);
 	    }
 	    if (pctxt->attrProhibs->nbItems != 0)
 		prohibs = pctxt->attrProhibs;
@@ -14546,6 +14419,7 @@ xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
 	    {
 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
 		"failed to expand attributes");
+                return(-1);
 	    }
 	}
     }
@@ -17863,8 +17737,7 @@ xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
 	    link = (xmlSchemaFacetLinkPtr)
 		xmlMalloc(sizeof(xmlSchemaFacetLink));
 	    if (link == NULL) {
-		xmlSchemaPErrMemory(pctxt,
-		    "deriving facets, creating a facet link", NULL);
+		xmlSchemaPErrMemory(pctxt);
 		return (-1);
 	    }
 	    link->facet = cur->facet;
@@ -17917,8 +17790,7 @@ xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
 			newLink = (xmlSchemaTypeLinkPtr)
 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
 			if (newLink == NULL) {
-			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
-				NULL);
+			    xmlSchemaPErrMemory(pctxt);
 			    return (-1);
 			}
 			newLink->type = subLink->type;
@@ -18125,59 +17997,6 @@ xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
     return(0);
 }
 
-#ifdef DEBUG_TYPE
-static void
-xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
-		       xmlSchemaTypePtr type)
-{
-    if (type->node != NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-                        "Type of %s : %s:%d :", name,
-                        type->node->doc->URL,
-                        xmlGetLineNo(type->node));
-    } else {
-        xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
-    }
-    if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
-	switch (type->contentType) {
-	    case XML_SCHEMA_CONTENT_SIMPLE:
-		xmlGenericError(xmlGenericErrorContext, "simple\n");
-		break;
-	    case XML_SCHEMA_CONTENT_ELEMENTS:
-		xmlGenericError(xmlGenericErrorContext, "elements\n");
-		break;
-	    case XML_SCHEMA_CONTENT_UNKNOWN:
-		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
-		break;
-	    case XML_SCHEMA_CONTENT_EMPTY:
-		xmlGenericError(xmlGenericErrorContext, "empty\n");
-		break;
-	    case XML_SCHEMA_CONTENT_MIXED:
-		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
-		    type->subtypes))
-		    xmlGenericError(xmlGenericErrorContext,
-			"mixed as emptiable particle\n");
-		else
-		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
-		break;
-		/* Removed, since not used. */
-		/*
-		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
-		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
-		break;
-		*/
-	    case XML_SCHEMA_CONTENT_BASIC:
-		xmlGenericError(xmlGenericErrorContext, "basic\n");
-		break;
-	    default:
-		xmlGenericError(xmlGenericErrorContext,
-		    "not registered !!!\n");
-		break;
-	}
-    }
-}
-#endif
-
 /*
 * 3.14.6 Constraints on Simple Type Definition Schema Components
 */
@@ -18260,17 +18079,11 @@ xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
     xmlSchemaTypeFixupOptimFacets(type);
 
 exit_error:
-#ifdef DEBUG_TYPE
-    xmlSchemaDebugFixedType(pctxt, type);
-#endif
     if (olderrs != pctxt->nberrors)
 	return(pctxt->err);
     return(0);
 
 exit_failure:
-#ifdef DEBUG_TYPE
-    xmlSchemaDebugFixedType(pctxt, type);
-#endif
     return(-1);
 }
 
@@ -18608,7 +18421,7 @@ xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
 			"allowed to appear inside other model groups",
 			NULL, NULL);
 
-		} else if (! dummySequence) {
+		} else if ((!dummySequence) && (baseType->subtypes != NULL)) {
 		    xmlSchemaTreeItemPtr effectiveContent =
 			(xmlSchemaTreeItemPtr) type->subtypes;
 		    /*
@@ -18692,9 +18505,6 @@ xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
     res = xmlSchemaCheckCTComponent(pctxt, type);
     HFAILURE HERROR
 
-#ifdef DEBUG_TYPE
-    xmlSchemaDebugFixedType(pctxt, type);
-#endif
     if (olderrs != pctxt->nberrors)
 	return(pctxt->err);
     else
@@ -18702,16 +18512,10 @@ xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
 
 exit_error:
     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
-#ifdef DEBUG_TYPE
-    xmlSchemaDebugFixedType(pctxt, type);
-#endif
     return(pctxt->err);
 
 exit_failure:
     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
-#ifdef DEBUG_TYPE
-    xmlSchemaDebugFixedType(pctxt, type);
-#endif
     return(-1);
 }
 
@@ -18866,7 +18670,7 @@ xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
 			PERROR_INT("xmlSchemaCheckFacet",
 			    "value was not computed");
 		    }
-		    TODO
+		    /* TODO */
 		}
                 break;
             }
@@ -19946,7 +19750,8 @@ xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
 	    /*
 	    * The set of all {derivation method}s involved in the derivation
 	    */
-	    while ((type != NULL) && (type != headType)) {
+	    while ((type != NULL) && (type != headType) &&
+                   (type != type->baseType)) {
 		if ((WXS_IS_EXTENSION(type)) &&
 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
@@ -21432,7 +21237,8 @@ xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
     * the API; i.e. not automatically by the validated instance document.
     */
 
-    xmlSchemaInitTypes();
+    if (xmlSchemaInitTypes() < 0)
+        return (NULL);
 
     if (ctxt == NULL)
         return (NULL);
@@ -21452,7 +21258,7 @@ xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
     if (ctxt->constructor == NULL) {
 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
 	if (ctxt->constructor == NULL)
-	    return(NULL);
+	    goto exit_failure;
 	/* Take ownership of the constructor to be able to free it. */
 	ctxt->ownsConstructor = 1;
     }
@@ -21541,6 +21347,8 @@ exit_failure:
  * @warn:  the warning callback
  * @ctx:  contextual data for the callbacks
  *
+ * DEPRECATED: Use xmlSchemaSetParserStructuredErrors.
+ *
  * Set the callback functions used to handle errors for a validation context
  */
 void
@@ -21861,7 +21669,6 @@ xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
 {
     const xmlChar *cur, *end;
     const xmlChar *nsname = NULL, *location;
-    int count = 0;
     int ret = 0;
     xmlSchemaAttrInfoPtr iattr;
 
@@ -21896,7 +21703,7 @@ xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
 		end++;
 	    if (end == cur)
 		break;
-	    count++; /* TODO: Don't use the schema's dict. */
+	    /* TODO: Don't use the schema's dict. */
 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
 	    cur = end;
 	}
@@ -21923,7 +21730,7 @@ xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
 	    }
 	    break;
 	}
-	count++; /* TODO: Don't use the schema's dict. */
+	/* TODO: Don't use the schema's dict. */
 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
 	cur = end;
 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
@@ -22118,9 +21925,7 @@ xmlSchemaAugmentIDC(void *payload, void *data,
 
     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
     if (aidc == NULL) {
-	xmlSchemaVErrMemory(vctxt,
-	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
-	    NULL);
+	xmlSchemaVErrMemory(vctxt);
 	return;
     }
     aidc->keyrefDepth = -1;
@@ -22172,8 +21977,7 @@ xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
 	    sizeof(xmlSchemaPSVIIDCBinding));
     if (ret == NULL) {
-	xmlSchemaVErrMemory(NULL,
-	    "allocating a PSVI IDC binding item", NULL);
+	xmlSchemaVErrMemory(NULL);
 	return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
@@ -22203,8 +22007,7 @@ xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
 	if (vctxt->idcNodes == NULL) {
-	    xmlSchemaVErrMemory(vctxt,
-		"allocating the IDC node table item list", NULL);
+	    xmlSchemaVErrMemory(vctxt);
 	    return (-1);
 	}
 	vctxt->sizeIdcNodes = 20;
@@ -22214,8 +22017,7 @@ xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
 	    sizeof(xmlSchemaPSVIIDCNodePtr));
 	if (vctxt->idcNodes == NULL) {
-	    xmlSchemaVErrMemory(vctxt,
-		"re-allocating the IDC node table item list", NULL);
+	    xmlSchemaVErrMemory(vctxt);
 	    return (-1);
 	}
     }
@@ -22244,8 +22046,7 @@ xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
 	if (vctxt->idcKeys == NULL) {
-	    xmlSchemaVErrMemory(vctxt,
-		"allocating the IDC key storage list", NULL);
+	    xmlSchemaVErrMemory(vctxt);
 	    return (-1);
 	}
 	vctxt->sizeIdcKeys = 40;
@@ -22255,8 +22056,7 @@ xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
 	    sizeof(xmlSchemaPSVIIDCKeyPtr));
 	if (vctxt->idcKeys == NULL) {
-	    xmlSchemaVErrMemory(vctxt,
-		"re-allocating the IDC key storage list", NULL);
+	    xmlSchemaVErrMemory(vctxt);
 	    return (-1);
 	}
     }
@@ -22283,8 +22083,7 @@ xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
 	if (bind->nodeTable == NULL) {
-	    xmlSchemaVErrMemory(NULL,
-		"allocating an array of IDC node-table items", NULL);
+	    xmlSchemaVErrMemory(NULL);
 	    return(-1);
 	}
     } else if (bind->sizeNodes <= bind->nbNodes) {
@@ -22293,8 +22092,7 @@ xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
 	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
 		sizeof(xmlSchemaPSVIIDCNodePtr));
 	if (bind->nodeTable == NULL) {
-	    xmlSchemaVErrMemory(NULL,
-		"re-allocating an array of IDC node-table items", NULL);
+	    xmlSchemaVErrMemory(NULL);
 	    return(-1);
 	}
     }
@@ -22554,8 +22352,7 @@ xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
 	*/
 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
 	if (sto == NULL) {
-	    xmlSchemaVErrMemory(NULL,
-		"allocating an IDC state object", NULL);
+	    xmlSchemaVErrMemory(NULL);
 	    return (-1);
 	}
 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
@@ -22589,10 +22386,6 @@ xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
     sto->sel = sel;
     sto->nbHistory = 0;
 
-#ifdef DEBUG_IDC
-    xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
-	sto->sel->xpath);
-#endif
     return (0);
 }
 
@@ -22618,30 +22411,12 @@ xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
 
     if (nodeType == XML_ATTRIBUTE_NODE)
 	depth++;
-#ifdef DEBUG_IDC
-    {
-	xmlChar *str = NULL;
-	xmlGenericError(xmlGenericErrorContext,
-	    "IDC: EVAL on %s, depth %d, type %d\n",
-	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
-		vctxt->inode->localName), depth, nodeType);
-	FREE_AND_NULL(str)
-    }
-#endif
     /*
     * Process all active XPath state objects.
     */
     first = vctxt->xpathStates;
     sto = first;
     while (sto != head) {
-#ifdef DEBUG_IDC
-	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
-	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
-		sto->matcher->aidc->def->name, sto->sel->xpath);
-	else
-	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
-		sto->matcher->aidc->def->name, sto->sel->xpath);
-#endif
 	if (nodeType == XML_ELEMENT_NODE)
 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
 		vctxt->inode->localName, vctxt->inode->nsName);
@@ -22659,18 +22434,13 @@ xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
 	/*
 	* Full match.
 	*/
-#ifdef DEBUG_IDC
-	xmlGenericError(xmlGenericErrorContext, "IDC:     "
-	    "MATCH\n");
-#endif
 	/*
 	* Register a match in the state object history.
 	*/
 	if (sto->history == NULL) {
 	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
 	    if (sto->history == NULL) {
-		xmlSchemaVErrMemory(NULL,
-		    "allocating the state object history", NULL);
+		xmlSchemaVErrMemory(NULL);
 		return(-1);
 	    }
 	    sto->sizeHistory = 5;
@@ -22679,28 +22449,18 @@ xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
 	    sto->history = (int *) xmlRealloc(sto->history,
 		sto->sizeHistory * sizeof(int));
 	    if (sto->history == NULL) {
-		xmlSchemaVErrMemory(NULL,
-		    "re-allocating the state object history", NULL);
+		xmlSchemaVErrMemory(NULL);
 		return(-1);
 	    }
 	}
 	sto->history[sto->nbHistory++] = depth;
 
-#ifdef DEBUG_IDC
-	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
-	    vctxt->depth);
-#endif
-
 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
 	    xmlSchemaIDCSelectPtr sel;
 	    /*
 	    * Activate state objects for the IDC fields of
 	    * the IDC selector.
 	    */
-#ifdef DEBUG_IDC
-	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
-		"activating field states\n");
-#endif
 	    sel = sto->matcher->aidc->def->fields;
 	    while (sel != NULL) {
 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
@@ -22712,10 +22472,6 @@ xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
 	    /*
 	    * An IDC key node was found by the IDC field.
 	    */
-#ifdef DEBUG_IDC
-	    xmlGenericError(xmlGenericErrorContext,
-		"IDC:     key found\n");
-#endif
 	    /*
 	    * Notify that the character value of this node is
 	    * needed.
@@ -22848,16 +22604,6 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
 	return (0);
     sto = vctxt->xpathStates;
 
-#ifdef DEBUG_IDC
-    {
-	xmlChar *str = NULL;
-	xmlGenericError(xmlGenericErrorContext,
-	    "IDC: BACK on %s, depth %d\n",
-	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
-		vctxt->inode->localName), vctxt->depth);
-	FREE_AND_NULL(str)
-    }
-#endif
     /*
     * Evaluate the state objects.
     */
@@ -22868,10 +22614,6 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
 		"calling xmlStreamPop()");
 	    return (-1);
 	}
-#ifdef DEBUG_IDC
-	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
-	    sto->sel->xpath);
-#endif
 	if (sto->nbHistory == 0)
 	    goto deregister_check;
 
@@ -22975,9 +22717,7 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
 			xmlMalloc(matcher->sizeKeySeqs *
 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
 		    if (matcher->keySeqs == NULL) {
-			xmlSchemaVErrMemory(NULL,
-			    "allocating an array of key-sequences",
-			    NULL);
+			xmlSchemaVErrMemory(NULL);
 			return(-1);
 		    }
 		    memset(matcher->keySeqs, 0,
@@ -22986,15 +22726,13 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
 		} else if (pos >= matcher->sizeKeySeqs) {
 		    int i = matcher->sizeKeySeqs;
 
-		    matcher->sizeKeySeqs *= 2;
+		    matcher->sizeKeySeqs = pos * 2;
 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
 			xmlRealloc(matcher->keySeqs,
 			matcher->sizeKeySeqs *
 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
 		    if (matcher->keySeqs == NULL) {
-			xmlSchemaVErrMemory(NULL,
-			    "reallocating an array of key-sequences",
-			    NULL);
+			xmlSchemaVErrMemory(NULL);
 			return (-1);
 		    }
 		    /*
@@ -23044,8 +22782,7 @@ create_sequence:
 		    matcher->aidc->def->nbFields *
 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
 		if (keySeq == NULL) {
-		    xmlSchemaVErrMemory(NULL,
-			"allocating an IDC key-sequence", NULL);
+		    xmlSchemaVErrMemory(NULL);
 		    return(-1);
 		}
 		memset(keySeq, 0, matcher->aidc->def->nbFields *
@@ -23059,8 +22796,7 @@ create_key:
 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
 			sizeof(xmlSchemaPSVIIDCKey));
 		    if (key == NULL) {
-			xmlSchemaVErrMemory(NULL,
-			    "allocating a IDC key", NULL);
+			xmlSchemaVErrMemory(NULL);
 			xmlFree(keySeq);
 			matcher->keySeqs[pos] = NULL;
 			return(-1);
@@ -23222,8 +22958,7 @@ create_key:
 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
 		sizeof(xmlSchemaPSVIIDCNode));
 	    if (ntItem == NULL) {
-		xmlSchemaVErrMemory(NULL,
-		    "allocating an IDC node-table item", NULL);
+		xmlSchemaVErrMemory(NULL);
 		xmlFree(*keySeq);
 		*keySeq = NULL;
 		return(-1);
@@ -23330,10 +23065,6 @@ deregister_check:
 	* Deregister state objects if they reach the depth of creation.
 	*/
 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
-#ifdef DEBUG_IDC
-	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
-		sto->sel->xpath);
-#endif
 	    if (vctxt->xpathStates != sto) {
 		VERROR_INT("xmlSchemaXPathProcessHistory",
 		    "The state object to be removed is not the first "
@@ -23378,16 +23109,6 @@ xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
     if (idc == NULL)
 	return (0);
 
-#ifdef DEBUG_IDC
-    {
-	xmlChar *str = NULL;
-	xmlGenericError(xmlGenericErrorContext,
-	    "IDC: REGISTER on %s, depth %d\n",
-	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
-		vctxt->inode->localName), vctxt->depth);
-	FREE_AND_NULL(str)
-    }
-#endif
     if (vctxt->inode->idcMatchers != NULL) {
 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
 	    "The chain of IDC matchers is expected to be empty");
@@ -23456,8 +23177,7 @@ xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
 	    matcher = (xmlSchemaIDCMatcherPtr)
 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
 	    if (matcher == NULL) {
-		xmlSchemaVErrMemory(vctxt,
-		    "allocating an IDC matcher", NULL);
+		xmlSchemaVErrMemory(vctxt);
 		return (-1);
 	    }
 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
@@ -23472,9 +23192,6 @@ xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
 	matcher->depth = vctxt->depth;
 	matcher->aidc = aidc;
 	matcher->idcType = aidc->def->type;
-#ifdef DEBUG_IDC
-	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
-#endif
 	/*
 	* Init the automaton state object.
 	*/
@@ -23872,8 +23589,7 @@ xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
 			    if (parBind->nodeTable == NULL) {
-				xmlSchemaVErrMemory(NULL,
-				    "allocating IDC list of node-table items", NULL);
+				xmlSchemaVErrMemory(NULL);
 				goto internal_error;
 			    }
 			    parBind->sizeNodes = 1;
@@ -23883,8 +23599,7 @@ xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
 				sizeof(xmlSchemaPSVIIDCNodePtr));
 			    if (parBind->nodeTable == NULL) {
-				xmlSchemaVErrMemory(NULL,
-				    "re-allocating IDC list of node-table items", NULL);
+				xmlSchemaVErrMemory(NULL);
 				goto internal_error;
 			    }
 			}
@@ -23937,9 +23652,7 @@ xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
 			xmlMalloc(bind->nbNodes *
 			sizeof(xmlSchemaPSVIIDCNodePtr));
 		    if (parBind->nodeTable == NULL) {
-			xmlSchemaVErrMemory(NULL,
-			    "allocating an array of IDC node-table "
-			    "items", NULL);
+			xmlSchemaVErrMemory(NULL);
 			xmlSchemaIDCFreeBinding(parBind);
 			goto internal_error;
 		    }
@@ -24148,8 +23861,7 @@ xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
 	vctxt->sizeAttrInfos = 1;
 	if (vctxt->attrInfos == NULL) {
-	    xmlSchemaVErrMemory(vctxt,
-		"allocating attribute info list", NULL);
+	    xmlSchemaVErrMemory(vctxt);
 	    return (NULL);
 	}
     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
@@ -24158,8 +23870,7 @@ xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
 	    xmlRealloc(vctxt->attrInfos,
 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
 	if (vctxt->attrInfos == NULL) {
-	    xmlSchemaVErrMemory(vctxt,
-		"re-allocating attribute info list", NULL);
+	    xmlSchemaVErrMemory(vctxt);
 	    return (NULL);
 	}
     } else {
@@ -24178,7 +23889,7 @@ xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
     iattr = (xmlSchemaAttrInfoPtr)
 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
     if (iattr == NULL) {
-	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
+	xmlSchemaVErrMemory(vctxt);
 	return (NULL);
     }
     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
@@ -24329,8 +24040,7 @@ xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
 	if (vctxt->elemInfos == NULL) {
-	    xmlSchemaVErrMemory(vctxt,
-		"allocating the element info array", NULL);
+	    xmlSchemaVErrMemory(vctxt);
 	    return (NULL);
 	}
 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
@@ -24343,8 +24053,7 @@ xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
 	    sizeof(xmlSchemaNodeInfoPtr));
 	if (vctxt->elemInfos == NULL) {
-	    xmlSchemaVErrMemory(vctxt,
-		"re-allocating the element info array", NULL);
+	    xmlSchemaVErrMemory(vctxt);
 	    return (NULL);
 	}
 	/*
@@ -24360,8 +24069,7 @@ xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
 	info = (xmlSchemaNodeInfoPtr)
 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
 	if (info == NULL) {
-	    xmlSchemaVErrMemory(vctxt,
-		"allocating an element info", NULL);
+	    xmlSchemaVErrMemory(vctxt);
 	    return (NULL);
 	}
 	vctxt->elemInfos[vctxt->depth] = info;
@@ -24824,7 +24532,6 @@ xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
 	    /*
 	    * Validation via a public API is not implemented yet.
 	    */
-	    TODO
 	    goto internal_error;
 	}
 	if (ret != 0) {
@@ -25637,7 +25344,6 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
 			if (wildIDs != 0) {
 			    /* VAL TODO */
 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
-			    TODO
 			    continue;
 			}
 			wildIDs++;
@@ -25655,7 +25361,6 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
                                     XML_SCHEMAS_ID)) {
                                     /* URGENT VAL TODO: implement */
                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
-                                    TODO
                                     break;
                                 }
                             }
@@ -25791,7 +25496,7 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
 			defAttrOwnerElem, iattr->nsName);
 		    if (ns == NULL) {
-			xmlChar prefix[12];
+			xmlChar prefix[13];
 			int counter = 0;
 
 			/*
@@ -25799,7 +25504,7 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
 			* root node if no namespace declaration is in scope.
 			*/
 			do {
-			    snprintf((char *) prefix, 12, "p%d", counter++);
+			    snprintf((char *) prefix, 13, "p%d", counter++);
 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
 				defAttrOwnerElem, BAD_CAST prefix);
 			    if (counter > 1000) {
@@ -25909,14 +25614,12 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
 	    */
 	    if (iattr->val == NULL) {
 		/* VAL TODO: A value was not precomputed. */
-		TODO
 		goto eval_idcs;
 	    }
 	    if ((iattr->use != NULL) &&
 		(iattr->use->defValue != NULL)) {
 		if (iattr->use->defVal == NULL) {
 		    /* VAL TODO: A default value was not precomputed. */
-		    TODO
 		    goto eval_idcs;
 		}
 		iattr->vcValue = iattr->use->defValue;
@@ -25931,7 +25634,6 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
 	    } else {
 		if (iattr->decl->defVal == NULL) {
 		    /* VAL TODO: A default value was not precomputed. */
-		    TODO
 		    goto eval_idcs;
 		}
 		iattr->vcValue = iattr->decl->defValue;
@@ -26185,25 +25887,6 @@ xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
     xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
     xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
     inode->decl = item;
-#ifdef DEBUG_CONTENT
-    {
-	xmlChar *str = NULL;
-
-	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
-	    xmlGenericError(xmlGenericErrorContext,
-		"AUTOMATON callback for '%s' [declaration]\n",
-		xmlSchemaFormatQName(&str,
-		inode->localName, inode->nsName));
-	} else {
-	    xmlGenericError(xmlGenericErrorContext,
-		    "AUTOMATON callback for '%s' [wildcard]\n",
-		    xmlSchemaFormatQName(&str,
-		    inode->localName, inode->nsName));
-
-	}
-	FREE_AND_NULL(str)
-    }
-#endif
 }
 
 static int
@@ -26294,10 +25977,6 @@ xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
 			"failed to create a regex context");
 		    goto internal_error;
 		}
-#ifdef DEBUG_AUTOMATA
-		xmlGenericError(xmlGenericErrorContext,
-		    "AUTOMATON create on '%s'\n", inode->localName);
-#endif
 	    }
 
 	    /*
@@ -26305,11 +25984,6 @@ xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
 	     */
 	    if (INODE_NILLED(inode)) {
 		ret = 0;
-#ifdef DEBUG_AUTOMATA
-		xmlGenericError(xmlGenericErrorContext,
-		    "AUTOMATON succeeded on nilled '%s'\n",
-		    inode->localName);
-#endif
                 goto skip_nilled;
 	    }
 
@@ -26331,21 +26005,11 @@ xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
 		    "Missing child element(s)",
 		    nbval, nbneg, values);
-#ifdef DEBUG_AUTOMATA
-		xmlGenericError(xmlGenericErrorContext,
-		    "AUTOMATON missing ERROR on '%s'\n",
-		    inode->localName);
-#endif
 	    } else {
 		/*
 		* Content model is satisfied.
 		*/
 		ret = 0;
-#ifdef DEBUG_AUTOMATA
-		xmlGenericError(xmlGenericErrorContext,
-		    "AUTOMATON succeeded on '%s'\n",
-		    inode->localName);
-#endif
 	    }
 
 	}
@@ -26648,12 +26312,6 @@ end_elem:
     * Merge/free the IDC table.
     */
     if (inode->idcTable != NULL) {
-#ifdef DEBUG_IDC_NODE_TABLE
-	xmlSchemaDebugDumpIDCTable(stdout,
-	    inode->nsName,
-	    inode->localName,
-	    inode->idcTable);
-#endif
 	if ((vctxt->depth > 0) &&
 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
 	{
@@ -26845,10 +26503,6 @@ xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
 		    return (-1);
 		}
 		pielem->regexCtxt = regexCtxt;
-#ifdef DEBUG_AUTOMATA
-		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
-		    pielem->localName);
-#endif
 	    }
 
 	    /*
@@ -26863,16 +26517,6 @@ xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
 		vctxt->inode->localName,
 		vctxt->inode->nsName,
 		vctxt->inode);
-#ifdef DEBUG_AUTOMATA
-	    if (ret < 0)
-		xmlGenericError(xmlGenericErrorContext,
-		"AUTOMATON push ERROR for '%s' on '%s'\n",
-		vctxt->inode->localName, pielem->localName);
-	    else
-		xmlGenericError(xmlGenericErrorContext,
-		"AUTOMATON push OK for '%s' on '%s'\n",
-		vctxt->inode->localName, pielem->localName);
-#endif
 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
 		VERROR_INT("xmlSchemaValidateChildElem",
 		    "calling xmlRegExecPushString2()");
@@ -27514,7 +27158,6 @@ xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
 	return;
     /* SAX VAL TODO: What to do here? */
-    TODO
 }
 
 static void
@@ -27575,9 +27218,7 @@ xmlSchemaSAXHandleStartElementNs(void *ctx,
 		    (const xmlChar **) xmlMalloc(10 *
 			sizeof(const xmlChar *));
 		if (ielem->nsBindings == NULL) {
-		    xmlSchemaVErrMemory(vctxt,
-			"allocating namespace bindings for SAX validation",
-			NULL);
+		    xmlSchemaVErrMemory(vctxt);
 		    goto internal_error;
 		}
 		ielem->nbNsBindings = 0;
@@ -27589,9 +27230,7 @@ xmlSchemaSAXHandleStartElementNs(void *ctx,
 			(void *) ielem->nsBindings,
 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
 		if (ielem->nsBindings == NULL) {
-		    xmlSchemaVErrMemory(vctxt,
-			"re-allocating namespace bindings for SAX validation",
-			NULL);
+		    xmlSchemaVErrMemory(vctxt);
 		    goto internal_error;
 		}
 	    }
@@ -27629,9 +27268,7 @@ xmlSchemaSAXHandleStartElementNs(void *ctx,
 	    valueLen = attributes[j+4] - attributes[j+3];
 	    value = xmlMallocAtomic(valueLen + 1);
 	    if (value == NULL) {
-		xmlSchemaVErrMemory(vctxt,
-		    "allocating string for decoded attribute",
-		    NULL);
+		xmlSchemaVErrMemory(vctxt);
 		goto internal_error;
 	    }
 	    for (k = 0, l = 0; k < valueLen; l++) {
@@ -27748,7 +27385,7 @@ xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
 
     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
     if (ret == NULL) {
-        xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
+        xmlSchemaVErrMemory(NULL);
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
@@ -28016,6 +27653,8 @@ xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
  * @warn: the warning function
  * @ctx: the functions context
  *
+ * DEPRECATED: Use xmlSchemaSetValidStructuredErrors.
+ *
  * Set the error and warning callback information
  */
 void
@@ -28691,28 +28330,28 @@ commentSplit(void *ctx, const xmlChar *value)
  * Varargs error callbacks to the user application, harder ...
  */
 
-static void XMLCDECL
+static void
 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
         (ctxt->user_sax->warning != NULL)) {
-	TODO
+	/* TODO */
     }
 }
-static void XMLCDECL
+static void
 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
         (ctxt->user_sax->error != NULL)) {
-	TODO
+	/* TODO */
     }
 }
-static void XMLCDECL
+static void
 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
         (ctxt->user_sax->fatalError != NULL)) {
-	TODO
+	/* TODO */
     }
 }
 
@@ -29042,6 +28681,55 @@ xmlSchemaValidateStreamLocator(void *ctx, const char **file,
     return(-1);
 }
 
+/**
+ * xmlSchemaValidateStreamInternal:
+ * @ctxt:  a schema validation context
+ * @pctxt:  a parser context
+ *
+ * Returns 0 if the document is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateStreamInternal(xmlSchemaValidCtxtPtr ctxt,
+                                 xmlParserCtxtPtr pctxt) {
+    xmlSchemaSAXPlugPtr plug = NULL;
+    int ret;
+
+    pctxt->linenumbers = 1;
+    xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
+
+    ctxt->parserCtxt = pctxt;
+    ctxt->input = pctxt->input->buf;
+
+    /*
+     * Plug the validation and launch the parsing
+     */
+    plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
+    if (plug == NULL) {
+        ret = -1;
+	goto done;
+    }
+    ctxt->input = pctxt->input->buf;
+    ctxt->sax = pctxt->sax;
+    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
+    ret = xmlSchemaVStart(ctxt);
+
+    if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
+	ret = ctxt->parserCtxt->errNo;
+	if (ret == 0)
+	    ret = 1;
+    }
+
+done:
+    ctxt->parserCtxt = NULL;
+    ctxt->sax = NULL;
+    ctxt->input = NULL;
+    if (plug != NULL) {
+        xmlSchemaSAXUnplug(plug);
+    }
+    return (ret);
+}
+
 /**
  * xmlSchemaValidateStream:
  * @ctxt:  a schema validation context
@@ -29062,8 +28750,6 @@ xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
                         xmlSAXHandlerPtr sax, void *user_data)
 {
-    xmlSchemaSAXPlugPtr plug = NULL;
-    xmlSAXHandlerPtr old_sax = NULL;
     xmlParserCtxtPtr pctxt = NULL;
     xmlParserInputPtr inputStream = NULL;
     int ret;
@@ -29074,18 +28760,22 @@ xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
     /*
      * prepare the parser
      */
-    pctxt = xmlNewParserCtxt();
-    if (pctxt == NULL)
-        return (-1);
-    old_sax = pctxt->sax;
-    pctxt->sax = sax;
-    pctxt->userData = user_data;
+    if (sax != NULL) {
+        pctxt = xmlNewSAXParserCtxt(sax, user_data);
+        if (pctxt == NULL)
+            return (-1);
+    } else {
+        pctxt = xmlNewParserCtxt();
+        if (pctxt == NULL)
+            return (-1);
+        /* We really want pctxt->sax to be NULL here. */
+        xmlFree(pctxt->sax);
+        pctxt->sax = NULL;
+    }
 #if 0
     if (options)
         xmlCtxtUseOptions(pctxt, options);
 #endif
-    pctxt->linenumbers = 1;
-    xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
 
     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
     if (inputStream == NULL) {
@@ -29093,39 +28783,14 @@ xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
 	goto done;
     }
     inputPush(pctxt, inputStream);
-    ctxt->parserCtxt = pctxt;
-    ctxt->input = input;
 
-    /*
-     * Plug the validation and launch the parsing
-     */
-    plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
-    if (plug == NULL) {
-        ret = -1;
-	goto done;
-    }
-    ctxt->input = input;
     ctxt->enc = enc;
-    ctxt->sax = pctxt->sax;
-    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
-    ret = xmlSchemaVStart(ctxt);
 
-    if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
-	ret = ctxt->parserCtxt->errNo;
-	if (ret == 0)
-	    ret = 1;
-    }
+    ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
 
 done:
-    ctxt->parserCtxt = NULL;
-    ctxt->sax = NULL;
-    ctxt->input = NULL;
-    if (plug != NULL) {
-        xmlSchemaSAXUnplug(plug);
-    }
     /* cleanup */
     if (pctxt != NULL) {
-	pctxt->sax = old_sax;
 	xmlFreeParserCtxt(pctxt);
     }
     return (ret);
@@ -29149,17 +28814,19 @@ xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
 		      int options ATTRIBUTE_UNUSED)
 {
     int ret;
-    xmlParserInputBufferPtr input;
+    xmlParserCtxtPtr pctxt = NULL;
 
     if ((ctxt == NULL) || (filename == NULL))
         return (-1);
 
-    input = xmlParserInputBufferCreateFilename(filename,
-	XML_CHAR_ENCODING_NONE);
-    if (input == NULL)
+    pctxt = xmlCreateURLParserCtxt(filename, 0);
+    if (pctxt == NULL)
 	return (-1);
-    ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
-	NULL, NULL);
+    /* We really want pctxt->sax to be NULL here. */
+    xmlFree(pctxt->sax);
+    pctxt->sax = NULL;
+    ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
+    xmlFreeParserCtxt(pctxt);
     return (ret);
 }
 
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
index 26c033d411dede163b3272307309f3af8feba712..5c6db292725da5a3b8a04ab90accabb511dd89dc 100644
--- a/xmlschemastypes.c
+++ b/xmlschemastypes.c
@@ -17,6 +17,7 @@
 
 #ifdef LIBXML_SCHEMAS_ENABLED
 
+#include <stdlib.h>
 #include <string.h>
 #include <math.h>
 #include <float.h>
@@ -25,15 +26,15 @@
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
 #include <libxml/hash.h>
-#include <libxml/valid.h>
 #include <libxml/xpath.h>
 #include <libxml/uri.h>
+#include <string.h>
 
 #include <libxml/xmlschemas.h>
 #include <libxml/schemasInternals.h>
 #include <libxml/xmlschemastypes.h>
 
-#define DEBUG
+#include "private/error.h"
 
 #ifndef LIBXML_XPATH_ENABLED
 extern double xmlXPathNAN;
@@ -41,11 +42,6 @@ extern double xmlXPathPINF;
 extern double xmlXPathNINF;
 #endif
 
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
-
 #define XML_SCHEMAS_NAMESPACE_NAME \
     (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
 
@@ -82,15 +78,11 @@ struct _xmlSchemaValDuration {
 
 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
 typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
-struct _xmlSchemaValDecimal {
-    /* would use long long but not portable */
-    unsigned long lo;
-    unsigned long mi;
-    unsigned long hi;
-    unsigned int extra;
-    unsigned int sign:1;
-    unsigned int frac:7;
-    unsigned int total:8;
+struct _xmlSchemaValDecimal
+{
+	xmlChar *str;
+	unsigned integralPlaces;
+	unsigned fractionalPlaces;
 };
 
 typedef struct _xmlSchemaValQName xmlSchemaValQName;
@@ -200,9 +192,9 @@ static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
  * Handle an out of memory condition
  */
 static void
-xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra)
+xmlSchemaTypeErrMemory(void)
 {
-    __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra);
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_DATATYPE, NULL);
 }
 
 /************************************************************************
@@ -236,6 +228,8 @@ static xmlSchemaFacetPtr
 xmlSchemaNewMinLengthFacet(int value)
 {
     xmlSchemaFacetPtr ret;
+    size_t bufsize;
+    xmlSchemaValDecimal *decimal;
 
     ret = xmlSchemaNewFacet();
     if (ret == NULL) {
@@ -245,9 +239,19 @@ xmlSchemaNewMinLengthFacet(int value)
     ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER);
     if (ret->val == NULL) {
         xmlFree(ret);
-	return(NULL);
+        return(NULL);
+    }
+    bufsize = snprintf(NULL, 0, "%+d.0", value) + 1;
+    decimal = &ret->val->value.decimal;
+    decimal->str = xmlMalloc(bufsize);
+    if (decimal->str == NULL)
+    {
+        xmlSchemaFreeFacet(ret);
+        return NULL;
     }
-    ret->val->value.decimal.lo = value;
+    snprintf((char *)decimal->str, bufsize, "%+d.0", value);
+    decimal->integralPlaces = bufsize - 4;
+    decimal->fractionalPlaces = 1;
     return (ret);
 }
 
@@ -265,7 +269,7 @@ xmlSchemaInitBasicType(const char *name, xmlSchemaValType type,
 
     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
     if (ret == NULL) {
-        xmlSchemaTypeErrMemory(NULL, "could not initialize basic types");
+        xmlSchemaTypeErrMemory();
 	return(NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaType));
@@ -326,6 +330,90 @@ xmlSchemaInitBasicType(const char *name, xmlSchemaValType type,
     return(ret);
 }
 
+static const xmlChar *
+xmlSchemaValDecimalGetFractionalPart(const xmlSchemaValDecimal *decimal)
+{
+    /* 2 = sign+dot */
+    return decimal->str+2+decimal->integralPlaces;
+}
+
+static int
+xmlSchemaValDecimalIsInteger(const xmlSchemaValDecimal *decimal)
+{
+    return decimal->fractionalPlaces == 1 && xmlSchemaValDecimalGetFractionalPart(decimal)[0] == '0';
+}
+
+static unsigned long
+xmlSchemaValDecimalGetSignificantDigitCount(const xmlSchemaValDecimal *decimal)
+{
+	unsigned fractionalPlaces = xmlSchemaValDecimalIsInteger(decimal) ? 0 : decimal->fractionalPlaces;
+	unsigned integralPlaces = decimal->integralPlaces;
+	if(integralPlaces == 1 && decimal->str[1] == '0')
+	{
+		integralPlaces = 0;
+	}
+	if(integralPlaces+fractionalPlaces == 0)
+	{
+		/* 0, but that's still 1 significant digit */
+		return 1;
+	}
+	return integralPlaces+fractionalPlaces;
+}
+
+/**
+ * @brief Compares two decimals
+ * 
+ * @param lhs 
+ * @param rhs 
+ * @return positive value if lhs > rhs, negative if lhs < rhs, or 0 if lhs == rhs
+ */
+static int xmlSchemaValDecimalCompare(const xmlSchemaValDecimal *lhs, const xmlSchemaValDecimal *rhs)
+{
+    int sign = 1;
+    /* may be +0 and -0 for some reason, handle */
+    if(strcmp((const char*)lhs->str+1, "0.0") == 0 &&
+        strcmp((const char*)rhs->str+1, "0.0") == 0)
+    {
+        return 0;
+    }
+    /* first take care of sign */
+    if(lhs->str[0] != rhs->str[0])
+    {
+        /* ASCII- > ASCII+ */
+        return rhs->str[0]-lhs->str[0];
+    }
+    /* signs are equal, but if negative the comparison must be reversed */
+    if(lhs->str[0] == '-')
+    {
+        sign = -1;
+    }
+    /* internal representation never contains leading zeroes, longer decimal representation = larger number */
+    if(lhs->integralPlaces != rhs->integralPlaces)
+    {
+        return ((int)lhs->integralPlaces-(int)rhs->integralPlaces)*sign;
+    }
+    /* same length, only digits => lexicographical sorting == numerical sorting.
+       If integral parts are equal it will compare compare fractional parts. Again, lexicographical is good enough,
+       length doesn't matter. We'll be starting from 0.1, always comparing like to like, and NULL < '0'
+       If one is shorter and is equal until end, it must be smaller, since there are no trailing zeroes
+       and the longer number must therefore have at least one non-zero digit after the other has ended.
+       +1 to skip the sign
+    */
+    return strcmp((const char*)lhs->str+1, (const char*)rhs->str+1)*sign;
+}
+
+static int xmlSchemaValDecimalCompareWithInteger(const xmlSchemaValDecimal *lhs, long rhs)
+{
+    /* can handle integers up to 128 bits, should be good for a while */
+    char buf[43];
+    xmlSchemaValDecimal tmpVal;
+    /* 3 = sign+dot+0+NULL */
+    tmpVal.integralPlaces = snprintf(buf, sizeof(buf), "%+ld.0", rhs)-3;
+    tmpVal.str = (xmlChar*)buf;
+    tmpVal.fractionalPlaces = 1;
+    return xmlSchemaValDecimalCompare(lhs, &tmpVal);
+}
+
 /*
 * WARNING: Those type reside normally in xmlschemas.c but are
 * redefined here locally in oder of being able to use them for xs:anyType-
@@ -373,7 +461,7 @@ xmlSchemaAddParticle(void)
     ret = (xmlSchemaParticlePtr)
 	xmlMalloc(sizeof(xmlSchemaParticle));
     if (ret == NULL) {
-	xmlSchemaTypeErrMemory(NULL, "allocating particle component");
+	xmlSchemaTypeErrMemory();
 	return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaParticle));
@@ -383,18 +471,61 @@ xmlSchemaAddParticle(void)
     return (ret);
 }
 
+static void
+xmlSchemaFreeTypeEntry(void *type, const xmlChar *name ATTRIBUTE_UNUSED) {
+    xmlSchemaFreeType((xmlSchemaTypePtr) type);
+}
+
+/**
+ * xmlSchemaCleanupTypesInternal:
+ *
+ * Cleanup the default XML Schemas type library
+ */
+static void
+xmlSchemaCleanupTypesInternal(void) {
+    xmlSchemaParticlePtr particle;
+
+    /*
+    * Free xs:anyType.
+    */
+    if (xmlSchemaTypeAnyTypeDef != NULL) {
+        /* Attribute wildcard. */
+        xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard);
+        /* Content type. */
+        particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes;
+        /* Wildcard. */
+        xmlSchemaFreeWildcard((xmlSchemaWildcardPtr)
+            particle->children->children->children);
+        xmlFree((xmlSchemaParticlePtr) particle->children->children);
+        /* Sequence model group. */
+        xmlFree((xmlSchemaModelGroupPtr) particle->children);
+        xmlFree((xmlSchemaParticlePtr) particle);
+        xmlSchemaTypeAnyTypeDef->subtypes = NULL;
+        xmlSchemaTypeAnyTypeDef = NULL;
+    }
+
+    xmlHashFree(xmlSchemaTypesBank, xmlSchemaFreeTypeEntry);
+    xmlSchemaTypesBank = NULL;
+    /* Note that the xmlSchemaType*Def pointers aren't set to NULL. */
+}
+
 /*
  * xmlSchemaInitTypes:
  *
  * Initialize the default XML Schemas type library
+ *
+ * Returns 0 on success, -1 on error.
  */
-void
+int
 xmlSchemaInitTypes(void)
 {
     if (xmlSchemaTypesInitialized != 0)
-        return;
+        return (0);
     xmlSchemaTypesBank = xmlHashCreate(40);
-
+    if (xmlSchemaTypesBank == NULL) {
+	xmlSchemaTypeErrMemory();
+        goto error;
+    }
 
     /*
     * 3.4.7 Built-in Complex Type Definition
@@ -402,6 +533,8 @@ xmlSchemaInitTypes(void)
     xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
                                                      XML_SCHEMAS_ANYTYPE,
 						     NULL);
+    if (xmlSchemaTypeAnyTypeDef == NULL)
+        goto error;
     xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef;
     xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
     /*
@@ -415,14 +548,14 @@ xmlSchemaInitTypes(void)
 	/* First particle. */
 	particle = xmlSchemaAddParticle();
 	if (particle == NULL)
-	    return;
+	    goto error;
 	xmlSchemaTypeAnyTypeDef->subtypes = (xmlSchemaTypePtr) particle;
 	/* Sequence model group. */
 	sequence = (xmlSchemaModelGroupPtr)
 	    xmlMalloc(sizeof(xmlSchemaModelGroup));
 	if (sequence == NULL) {
-	    xmlSchemaTypeErrMemory(NULL, "allocating model group component");
-	    return;
+	    xmlSchemaTypeErrMemory();
+	    goto error;
 	}
 	memset(sequence, 0, sizeof(xmlSchemaModelGroup));
 	sequence->type = XML_SCHEMA_TYPE_SEQUENCE;
@@ -430,15 +563,15 @@ xmlSchemaInitTypes(void)
 	/* Second particle. */
 	particle = xmlSchemaAddParticle();
 	if (particle == NULL)
-	    return;
+	    goto error;
 	particle->minOccurs = 0;
 	particle->maxOccurs = UNBOUNDED;
 	sequence->children = (xmlSchemaTreeItemPtr) particle;
 	/* The wildcard */
 	wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
 	if (wild == NULL) {
-	    xmlSchemaTypeErrMemory(NULL, "allocating wildcard component");
-	    return;
+	    xmlSchemaTypeErrMemory();
+	    goto error;
 	}
 	memset(wild, 0, sizeof(xmlSchemaWildcard));
 	wild->type = XML_SCHEMA_TYPE_ANY;
@@ -450,9 +583,8 @@ xmlSchemaInitTypes(void)
 	*/
 	wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
 	if (wild == NULL) {
-	    xmlSchemaTypeErrMemory(NULL, "could not create an attribute "
-		"wildcard on anyType");
-	    return;
+	    xmlSchemaTypeErrMemory();
+	    goto error;
 	}
 	memset(wild, 0, sizeof(xmlSchemaWildcard));
 	wild->any = 1;
@@ -462,66 +594,106 @@ xmlSchemaInitTypes(void)
     xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType",
                                                            XML_SCHEMAS_ANYSIMPLETYPE,
 							   xmlSchemaTypeAnyTypeDef);
+    if (xmlSchemaTypeAnySimpleTypeDef == NULL)
+        goto error;
     /*
     * primitive datatypes
     */
     xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
                                                     XML_SCHEMAS_STRING,
 						    xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeStringDef == NULL)
+        goto error;
     xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
                                                      XML_SCHEMAS_DECIMAL,
 						     xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeDecimalDef == NULL)
+        goto error;
     xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
                                                   XML_SCHEMAS_DATE,
 						  xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeDateDef == NULL)
+        goto error;
     xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
                                                       XML_SCHEMAS_DATETIME,
 						      xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeDatetimeDef == NULL)
+        goto error;
     xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
                                                   XML_SCHEMAS_TIME,
 						  xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeTimeDef == NULL)
+        goto error;
     xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
                                                    XML_SCHEMAS_GYEAR,
 						   xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeGYearDef == NULL)
+        goto error;
     xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
                                                         XML_SCHEMAS_GYEARMONTH,
 							xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeGYearMonthDef == NULL)
+        goto error;
     xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
                                                     XML_SCHEMAS_GMONTH,
 						    xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeGMonthDef == NULL)
+        goto error;
     xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
                                                        XML_SCHEMAS_GMONTHDAY,
 						       xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeGMonthDayDef == NULL)
+        goto error;
     xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
                                                   XML_SCHEMAS_GDAY,
 						  xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeGDayDef == NULL)
+        goto error;
     xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
                                                       XML_SCHEMAS_DURATION,
 						      xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeDurationDef == NULL)
+        goto error;
     xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
                                                    XML_SCHEMAS_FLOAT,
 						   xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeFloatDef == NULL)
+        goto error;
     xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
                                                     XML_SCHEMAS_DOUBLE,
 						    xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeDoubleDef == NULL)
+        goto error;
     xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
                                                      XML_SCHEMAS_BOOLEAN,
 						     xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeBooleanDef == NULL)
+        goto error;
     xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
                                                     XML_SCHEMAS_ANYURI,
 						    xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeAnyURIDef == NULL)
+        goto error;
     xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
                                                      XML_SCHEMAS_HEXBINARY,
 						     xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeHexBinaryDef == NULL)
+        goto error;
     xmlSchemaTypeBase64BinaryDef
         = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY,
 	xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeBase64BinaryDef == NULL)
+        goto error;
     xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
                                                     XML_SCHEMAS_NOTATION,
 						    xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeNotationDef == NULL)
+        goto error;
     xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
                                                    XML_SCHEMAS_QNAME,
 						   xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeQNameDef == NULL)
+        goto error;
 
     /*
      * derived datatypes
@@ -529,69 +701,113 @@ xmlSchemaInitTypes(void)
     xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
                                                      XML_SCHEMAS_INTEGER,
 						     xmlSchemaTypeDecimalDef);
+    if (xmlSchemaTypeIntegerDef == NULL)
+        goto error;
     xmlSchemaTypeNonPositiveIntegerDef =
         xmlSchemaInitBasicType("nonPositiveInteger",
                                XML_SCHEMAS_NPINTEGER,
 			       xmlSchemaTypeIntegerDef);
+    if (xmlSchemaTypeNonPositiveIntegerDef == NULL)
+        goto error;
     xmlSchemaTypeNegativeIntegerDef =
         xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER,
 	xmlSchemaTypeNonPositiveIntegerDef);
+    if (xmlSchemaTypeNegativeIntegerDef == NULL)
+        goto error;
     xmlSchemaTypeLongDef =
         xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG,
 	xmlSchemaTypeIntegerDef);
+    if (xmlSchemaTypeLongDef == NULL)
+        goto error;
     xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT,
 	xmlSchemaTypeLongDef);
+    if (xmlSchemaTypeIntDef == NULL)
+        goto error;
     xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
                                                    XML_SCHEMAS_SHORT,
 						   xmlSchemaTypeIntDef);
+    if (xmlSchemaTypeShortDef == NULL)
+        goto error;
     xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
                                                   XML_SCHEMAS_BYTE,
 						  xmlSchemaTypeShortDef);
+    if (xmlSchemaTypeByteDef == NULL)
+        goto error;
     xmlSchemaTypeNonNegativeIntegerDef =
         xmlSchemaInitBasicType("nonNegativeInteger",
                                XML_SCHEMAS_NNINTEGER,
 			       xmlSchemaTypeIntegerDef);
+    if (xmlSchemaTypeNonNegativeIntegerDef == NULL)
+        goto error;
     xmlSchemaTypeUnsignedLongDef =
         xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG,
 	xmlSchemaTypeNonNegativeIntegerDef);
+    if (xmlSchemaTypeUnsignedLongDef == NULL)
+        goto error;
     xmlSchemaTypeUnsignedIntDef =
         xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT,
 	xmlSchemaTypeUnsignedLongDef);
+    if (xmlSchemaTypeUnsignedIntDef == NULL)
+        goto error;
     xmlSchemaTypeUnsignedShortDef =
         xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT,
 	xmlSchemaTypeUnsignedIntDef);
+    if (xmlSchemaTypeUnsignedShortDef == NULL)
+        goto error;
     xmlSchemaTypeUnsignedByteDef =
         xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE,
 	xmlSchemaTypeUnsignedShortDef);
+    if (xmlSchemaTypeUnsignedByteDef == NULL)
+        goto error;
     xmlSchemaTypePositiveIntegerDef =
         xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER,
 	xmlSchemaTypeNonNegativeIntegerDef);
+    if (xmlSchemaTypePositiveIntegerDef == NULL)
+        goto error;
     xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
                                                         XML_SCHEMAS_NORMSTRING,
 							xmlSchemaTypeStringDef);
+    if (xmlSchemaTypeNormStringDef == NULL)
+        goto error;
     xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
                                                    XML_SCHEMAS_TOKEN,
 						   xmlSchemaTypeNormStringDef);
+    if (xmlSchemaTypeTokenDef == NULL)
+        goto error;
     xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
                                                       XML_SCHEMAS_LANGUAGE,
 						      xmlSchemaTypeTokenDef);
+    if (xmlSchemaTypeLanguageDef == NULL)
+        goto error;
     xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
                                                   XML_SCHEMAS_NAME,
 						  xmlSchemaTypeTokenDef);
+    if (xmlSchemaTypeNameDef == NULL)
+        goto error;
     xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
                                                      XML_SCHEMAS_NMTOKEN,
 						     xmlSchemaTypeTokenDef);
+    if (xmlSchemaTypeNmtokenDef == NULL)
+        goto error;
     xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
                                                     XML_SCHEMAS_NCNAME,
 						    xmlSchemaTypeNameDef);
+    if (xmlSchemaTypeNCNameDef == NULL)
+        goto error;
     xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID,
 						    xmlSchemaTypeNCNameDef);
+    if (xmlSchemaTypeIdDef == NULL)
+        goto error;
     xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
                                                    XML_SCHEMAS_IDREF,
 						   xmlSchemaTypeNCNameDef);
+    if (xmlSchemaTypeIdrefDef == NULL)
+        goto error;
     xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
                                                     XML_SCHEMAS_ENTITY,
 						    xmlSchemaTypeNCNameDef);
+    if (xmlSchemaTypeEntityDef == NULL)
+        goto error;
     /*
     * Derived list types.
     */
@@ -599,25 +815,31 @@ xmlSchemaInitTypes(void)
     xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
                                                       XML_SCHEMAS_ENTITIES,
 						      xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeEntitiesDef == NULL)
+        goto error;
     xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef;
     /* IDREFS */
     xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
                                                     XML_SCHEMAS_IDREFS,
 						    xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeIdrefsDef == NULL)
+        goto error;
     xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef;
 
     /* NMTOKENS */
     xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
                                                       XML_SCHEMAS_NMTOKENS,
 						      xmlSchemaTypeAnySimpleTypeDef);
+    if (xmlSchemaTypeNmtokensDef == NULL)
+        goto error;
     xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef;
 
     xmlSchemaTypesInitialized = 1;
-}
+    return (0);
 
-static void
-xmlSchemaFreeTypeEntry(void *type, const xmlChar *name ATTRIBUTE_UNUSED) {
-    xmlSchemaFreeType((xmlSchemaTypePtr) type);
+error:
+    xmlSchemaCleanupTypesInternal();
+    return (-1);
 }
 
 /**
@@ -626,34 +848,16 @@ xmlSchemaFreeTypeEntry(void *type, const xmlChar *name ATTRIBUTE_UNUSED) {
  * DEPRECATED: This function will be made private. Call xmlCleanupParser
  * to free global state but see the warnings there. xmlCleanupParser
  * should be only called once at program exit. In most cases, you don't
- * have call cleanup functions at all.
+ * have to call cleanup functions at all.
  *
  * Cleanup the default XML Schemas type library
  */
 void
 xmlSchemaCleanupTypes(void) {
-    if (xmlSchemaTypesInitialized == 0)
-	return;
-    /*
-    * Free xs:anyType.
-    */
-    {
-	xmlSchemaParticlePtr particle;
-	/* Attribute wildcard. */
-	xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard);
-	/* Content type. */
-	particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes;
-	/* Wildcard. */
-	xmlSchemaFreeWildcard((xmlSchemaWildcardPtr)
-	    particle->children->children->children);
-	xmlFree((xmlSchemaParticlePtr) particle->children->children);
-	/* Sequence model group. */
-	xmlFree((xmlSchemaModelGroupPtr) particle->children);
-	xmlFree((xmlSchemaParticlePtr) particle);
-	xmlSchemaTypeAnyTypeDef->subtypes = NULL;
+    if (xmlSchemaTypesInitialized != 0) {
+        xmlSchemaCleanupTypesInternal();
+        xmlSchemaTypesInitialized = 0;
     }
-    xmlHashFree(xmlSchemaTypesBank, xmlSchemaFreeTypeEntry);
-    xmlSchemaTypesInitialized = 0;
 }
 
 /**
@@ -748,8 +952,9 @@ xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType)
 xmlSchemaTypePtr
 xmlSchemaGetBuiltInType(xmlSchemaValType type)
 {
-    if (xmlSchemaTypesInitialized == 0)
-	xmlSchemaInitTypes();
+    if ((xmlSchemaTypesInitialized == 0) &&
+	(xmlSchemaInitTypes() < 0))
+        return (NULL);
     switch (type) {
 
 	case XML_SCHEMAS_ANYSIMPLETYPE:
@@ -1061,6 +1266,23 @@ xmlSchemaFreeValue(xmlSchemaValPtr value) {
 		if (value->value.base64.str != NULL)
 		    xmlFree(value->value.base64.str);
 		break;
+	    case XML_SCHEMAS_DECIMAL:
+	    case XML_SCHEMAS_INTEGER:
+	    case XML_SCHEMAS_NNINTEGER:
+	    case XML_SCHEMAS_PINTEGER:
+	    case XML_SCHEMAS_NPINTEGER:
+	    case XML_SCHEMAS_NINTEGER:
+	    case XML_SCHEMAS_INT:
+	    case XML_SCHEMAS_UINT:
+	    case XML_SCHEMAS_LONG:
+	    case XML_SCHEMAS_ULONG:
+	    case XML_SCHEMAS_SHORT:
+	    case XML_SCHEMAS_USHORT:
+	    case XML_SCHEMAS_BYTE:
+	    case XML_SCHEMAS_UBYTE:
+		if (value->value.decimal.str != NULL)
+		    xmlFree(value->value.decimal.str);
+		break;
 	    default:
 		break;
 	}
@@ -1081,8 +1303,9 @@ xmlSchemaFreeValue(xmlSchemaValPtr value) {
  */
 xmlSchemaTypePtr
 xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
-    if (xmlSchemaTypesInitialized == 0)
-	xmlSchemaInitTypes();
+    if ((xmlSchemaTypesInitialized == 0) &&
+	(xmlSchemaInitTypes() < 0))
+        return (NULL);
     if (name == NULL)
 	return(NULL);
     return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
@@ -1154,7 +1377,7 @@ static const unsigned int daysInMonthLeap[12] =
 	((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0)
 
 #define VALID_TIME(dt)						\
-	(((VALID_HOUR(dt->hour) && VALID_MIN(dt->min) &&	\
+	(((VALID_HOUR((int)dt->hour) && VALID_MIN((int)dt->min) &&	\
 	  VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) &&	\
 	 VALID_TZO(dt->tzo))
 
@@ -1178,25 +1401,6 @@ static const long dayInLeapYearByMonth[12] =
                 dayInLeapYearByMonth[month - 1] :		\
                 dayInYearByMonth[month - 1]) + day)
 
-#ifdef DEBUG
-#define DEBUG_DATE(dt)                                                  \
-    xmlGenericError(xmlGenericErrorContext,                             \
-        "type=%o %04ld-%02u-%02uT%02u:%02u:%03f",                       \
-        dt->type,dt->value.date.year,dt->value.date.mon,                \
-        dt->value.date.day,dt->value.date.hour,dt->value.date.min,      \
-        dt->value.date.sec);                                            \
-    if (dt->value.date.tz_flag)                                         \
-        if (dt->value.date.tzo != 0)                                    \
-            xmlGenericError(xmlGenericErrorContext,                     \
-                "%+05d\n",dt->value.date.tzo);                          \
-        else                                                            \
-            xmlGenericError(xmlGenericErrorContext, "Z\n");             \
-    else                                                                \
-        xmlGenericError(xmlGenericErrorContext,"\n")
-#else
-#define DEBUG_DATE(dt)
-#endif
-
 /**
  * _xmlSchemaParseGYear:
  * @dt:  pointer to a date structure
@@ -2138,21 +2342,16 @@ xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
 /**
  * xmlSchemaParseUInt:
  * @str: pointer to the string R/W
- * @llo: pointer to the low result
- * @lmi: pointer to the mid result
- * @lhi: pointer to the high result
+ * @val: pointer to the resulting decimal
  *
- * Parse an unsigned long into 3 fields.
+ * Parse an unsigned long into a decimal.
  *
  * Returns the number of significant digits in the number or
  * -1 if overflow of the capacity and -2 if it's not a number.
  */
-static int
-xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
-                   unsigned long *lmi, unsigned long *lhi) {
-    unsigned long lo = 0, mi = 0, hi = 0;
-    const xmlChar *tmp, *cur = *str;
-    int ret = 0, i = 0;
+static int xmlSchemaParseUInt(const xmlChar **str, xmlSchemaValDecimalPtr val) {
+	const xmlChar *tmp, *cur = *str;
+	int ret = 0, i = 0;
 
     if (!((*cur >= '0') && (*cur <= '9')))
         return(-2);
@@ -2160,31 +2359,29 @@ xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
     while (*cur == '0') {        /* ignore leading zeroes */
         cur++;
     }
+    /* back up in case there is nothing after the leading zeroes */
+    if(!(*cur >= '0' && *cur <= '9'))
+    {
+        --cur;
+    }
     tmp = cur;
     while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
         i++;tmp++;ret++;
     }
-    if (i > 24) {
-        *str = tmp;
-        return(-1);
-    }
-    while (i > 16) {
-        hi = hi * 10 + (*cur++ - '0');
-        i--;
-    }
-    while (i > 8) {
-        mi = mi * 10 + (*cur++ - '0');
-        i--;
-    }
-    while (i > 0) {
-        lo = lo * 10 + (*cur++ - '0');
-        i--;
+    if (val->integralPlaces + val->fractionalPlaces < (unsigned)i + 1)
+    {
+        if (val->str != NULL)
+        {
+            xmlFree(val->str);
+        }
+        /*  sign, dot, fractional 0 and NULL terminator */
+        val->str = xmlMalloc(i + 4);
     }
+    val->fractionalPlaces = 1;
+    val->integralPlaces = i;
+    snprintf((char *)val->str, i + 4, "+%.*s.0", i, cur);
 
-    *str = cur;
-    *llo = lo;
-    *lmi = mi;
-    *lhi = hi;
+    *str = tmp;
     return(ret);
 }
 
@@ -2251,8 +2448,9 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
     xmlChar *norm = NULL;
     int ret = 0;
 
-    if (xmlSchemaTypesInitialized == 0)
-        xmlSchemaInitTypes();
+    if ((xmlSchemaTypesInitialized == 0) &&
+	(xmlSchemaInitTypes() < 0))
+        return (-1);
     if (type == NULL)
         return (-1);
 
@@ -2371,9 +2569,11 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
             }
         case XML_SCHEMAS_DECIMAL:{
                 const xmlChar *cur = value;
-                unsigned int len, neg, integ, hasLeadingZeroes;
-		xmlChar cval[25];
-		xmlChar *cptr = cval;
+                const xmlChar *numStart, *numEnd;
+                xmlSchemaValDecimal decimal;
+                xmlChar sign;
+
+                memset(&decimal, 0, sizeof(decimal));
 
                 if ((cur == NULL) || (*cur == 0))
                     goto return1;
@@ -2387,9 +2587,9 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
 		/*
 		* First we handle an optional sign.
 		*/
-		neg = 0;
+                sign = '+';
                 if (*cur == '-') {
-		    neg = 1;
+                    sign = '-';
                     cur++;
 		} else if (*cur == '+')
                     cur++;
@@ -2398,47 +2598,44 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
 		*/
 		if (*cur == 0)
 		    goto return1;
-		/*
-		 * Next we "pre-parse" the number, in preparation for calling
-		 * the common routine xmlSchemaParseUInt.  We get rid of any
-		 * leading zeroes (because we have reserved only 25 chars),
-		 * and note the position of a decimal point.
-		 */
-		len = 0;
-		integ = ~0u;
-		hasLeadingZeroes = 0;
+
 		/*
 		* Skip leading zeroes.
 		*/
 		while (*cur == '0') {
 		    cur++;
-		    hasLeadingZeroes = 1;
-		}
-		if (*cur != 0) {
-		    do {
-			if ((*cur >= '0') && (*cur <= '9')) {
-			    *cptr++ = *cur++;
-			    len++;
-			} else if (*cur == '.') {
-			    cur++;
-			    integ = len;
-			    do {
-				if ((*cur >= '0') && (*cur <= '9')) {
-				    *cptr++ = *cur++;
-				    len++;
-				} else
-				    break;
-			    } while (len < 24);
-			    /*
-			    * Disallow "." but allow "00."
-			    */
-			    if ((len == 0) && (!hasLeadingZeroes))
-				goto return1;
-			    break;
-			} else
-			    break;
-		    } while (len < 24);
 		}
+
+                numStart = cur;
+
+                while ((*cur >= '0') && (*cur <= '9')) {
+                    ++cur;
+                    ++decimal.integralPlaces;
+                }
+                if (*cur == '.') {
+                    ++cur;
+                }
+                while ((*cur >= '0') && (*cur <= '9')) {
+                    ++cur;
+                    ++decimal.fractionalPlaces;
+                }
+
+                /*  disallow "." */
+                if (
+                    decimal.fractionalPlaces == 0 && decimal.integralPlaces == 0
+                    && (numStart == value || numStart[-1] != '0')
+                ) {
+                    goto return1;
+                }
+
+                numEnd = cur;
+
+                /*  find if there are trailing FRACTIONAL zeroes, and deal with them if necessary */
+                while (numEnd > numStart && decimal.fractionalPlaces && numEnd[-1] == '0') {
+                    --numEnd;
+                    --decimal.fractionalPlaces;
+                }
+
 		if (normOnTheFly)
 		    while IS_WSP_BLANK_CH(*cur) cur++;
 		if (*cur != 0)
@@ -2446,50 +2643,36 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
                 if (val != NULL) {
                     v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
                     if (v != NULL) {
-			/*
-			* Now evaluate the significant digits of the number
-			*/
-			if (len != 0) {
-
-			    if (integ != ~0u) {
-				/*
-				* Get rid of trailing zeroes in the
-				* fractional part.
-				*/
-				while ((len != integ) && (*(cptr-1) == '0')) {
-				    cptr--;
-				    len--;
-				}
-			    }
-			    /*
-			    * Terminate the (preparsed) string.
-			    */
-			    if (len != 0) {
-				*cptr = 0;
-				cptr = cval;
-
-				xmlSchemaParseUInt((const xmlChar **)&cptr,
-				    &v->value.decimal.lo,
-				    &v->value.decimal.mi,
-				    &v->value.decimal.hi);
-			    }
-			}
-			/*
-			* Set the total digits to 1 if a zero value.
-			*/
-                        v->value.decimal.sign = neg;
-			if (len == 0) {
-			    /* Speedup for zero values. */
-			    v->value.decimal.total = 1;
-			} else {
-			    v->value.decimal.total = len;
-			    if (integ == ~0u)
-				v->value.decimal.frac = 0;
-			    else
-				v->value.decimal.frac = len - integ;
-			}
+                        /*  create a standardized representation */
+                        size_t bufsize;
+                        const char *integralStart = (const char *)numStart;
+                        const char *fractionalStart = (const char *)numEnd - decimal.fractionalPlaces;
+                        if (decimal.integralPlaces == 0)
+                        {
+                            integralStart = "0";
+                            decimal.integralPlaces = 1;
+                        }
+                        if (decimal.fractionalPlaces == 0)
+                        {
+                            fractionalStart = "0";
+                            decimal.fractionalPlaces = 1;
+                        }
+                        /*  3 = sign, dot, NULL terminator */
+                        bufsize = decimal.integralPlaces + decimal.fractionalPlaces + 3;
+                        decimal.str = xmlMalloc(bufsize);
+                        if (!decimal.str)
+                        {
+                            goto error;
+                        }
+                        snprintf((char *)decimal.str, bufsize, "%c%.*s.%.*s", sign, decimal.integralPlaces, integralStart,
+                                decimal.fractionalPlaces, fractionalStart);
+                        v->value.decimal = decimal;
                         *val = v;
                     }
+                    else
+                    {
+                        goto error;
+                    }
                 }
                 goto return0;
             }
@@ -2869,19 +3052,19 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
                  * NOTE: the IDness might have already be declared in the DTD
                  */
                 if (attr->atype != XML_ATTRIBUTE_ID) {
-                    xmlIDPtr res;
                     xmlChar *strip;
+                    int res;
 
                     strip = xmlSchemaStrip(value);
                     if (strip != NULL) {
-                        res = xmlAddID(NULL, node->doc, strip, attr);
+                        res = xmlAddIDSafe(attr, strip);
                         xmlFree(strip);
                     } else
-                        res = xmlAddID(NULL, node->doc, value, attr);
-                    if (res == NULL) {
+                        res = xmlAddIDSafe(attr, value);
+                    if (res < 0) {
+                        goto error;
+                    } else if (res == 0) {
                         ret = 2;
-                    } else {
-                        attr->atype = XML_ATTRIBUTE_ID;
                     }
                 }
             }
@@ -2945,7 +3128,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
                         ret = 4;
                 }
                 if ((ret == 0) && (val != NULL)) {
-                    TODO;
+                    /* TODO */
                 }
                 if ((ret == 0) && (node != NULL) &&
                     (node->type == XML_ATTRIBUTE_NODE)) {
@@ -3034,6 +3217,8 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
 			    value = norm;
 		    }
 		    tmpval = xmlStrdup(value);
+                    if (tmpval == NULL)
+                        goto error;
 		    for (cur = tmpval; *cur; ++cur) {
 			if (*cur < 32 || *cur >= 127 || *cur == ' ' ||
 			    *cur == '<' || *cur == '>' || *cur == '"' ||
@@ -3095,7 +3280,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
 		    */
                     cur = xmlStrndup(start, i);
                     if (cur == NULL) {
-		        xmlSchemaTypeErrMemory(node, "allocating hexbin data");
+		        xmlSchemaTypeErrMemory();
                         xmlFree(v);
                         goto return1;
                     }
@@ -3220,10 +3405,9 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
                     if (v == NULL)
                         goto error;
                     base =
-                        (xmlChar *) xmlMallocAtomic((i + pad + 1) *
-                                                    sizeof(xmlChar));
+                        (xmlChar *) xmlMallocAtomic(i + pad + 1);
                     if (base == NULL) {
-		        xmlSchemaTypeErrMemory(node, "allocating base64 data");
+		        xmlSchemaTypeErrMemory();
                         xmlFree(v);
                         goto return1;
                     }
@@ -3243,201 +3427,152 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
         case XML_SCHEMAS_PINTEGER:
         case XML_SCHEMAS_NPINTEGER:
         case XML_SCHEMAS_NINTEGER:
-        case XML_SCHEMAS_NNINTEGER:{
-                const xmlChar *cur = value;
-                unsigned long lo, mi, hi;
-                int sign = 0;
-
-                if (cur == NULL)
-                    goto return1;
-		if (normOnTheFly)
-		    while IS_WSP_BLANK_CH(*cur) cur++;
-                if (*cur == '-') {
-                    sign = 1;
-                    cur++;
-                } else if (*cur == '+')
-                    cur++;
-                ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
-                if (ret < 0)
-                    goto return1;
-		if (normOnTheFly)
-		    while IS_WSP_BLANK_CH(*cur) cur++;
-                if (*cur != 0)
-                    goto return1;
-                if (type->builtInType == XML_SCHEMAS_NPINTEGER) {
-                    if ((sign == 0) &&
-                        ((hi != 0) || (mi != 0) || (lo != 0)))
-                        goto return1;
-                } else if (type->builtInType == XML_SCHEMAS_PINTEGER) {
-                    if (sign == 1)
-                        goto return1;
-                    if ((hi == 0) && (mi == 0) && (lo == 0))
-                        goto return1;
-                } else if (type->builtInType == XML_SCHEMAS_NINTEGER) {
-                    if (sign == 0)
-                        goto return1;
-                    if ((hi == 0) && (mi == 0) && (lo == 0))
-                        goto return1;
-                } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) {
-                    if ((sign == 1) &&
-                        ((hi != 0) || (mi != 0) || (lo != 0)))
-                        goto return1;
-                }
-                if (val != NULL) {
-                    v = xmlSchemaNewValue(type->builtInType);
-                    if (v != NULL) {
-			if (ret == 0)
-			    ret++;
-                        v->value.decimal.lo = lo;
-                        v->value.decimal.mi = mi;
-                        v->value.decimal.hi = hi;
-                        v->value.decimal.sign = sign;
-                        v->value.decimal.frac = 0;
-                        v->value.decimal.total = ret;
-                        *val = v;
-                    }
-                }
-                goto return0;
-            }
+        case XML_SCHEMAS_NNINTEGER:
         case XML_SCHEMAS_LONG:
         case XML_SCHEMAS_BYTE:
         case XML_SCHEMAS_SHORT:
-        case XML_SCHEMAS_INT:{
+        case XML_SCHEMAS_INT:
+        case XML_SCHEMAS_UINT:
+        case XML_SCHEMAS_ULONG:
+        case XML_SCHEMAS_USHORT:
+        case XML_SCHEMAS_UBYTE: {
                 const xmlChar *cur = value;
-                unsigned long lo, mi, hi;
-                int sign = 0;
+                xmlSchemaValDecimal decimal;
+                xmlChar sign = '+';
+
+                memset(&decimal, 0, sizeof(decimal));
 
                 if (cur == NULL)
                     goto return1;
-		if (normOnTheFly)
+ 		if (normOnTheFly)
 		    while IS_WSP_BLANK_CH(*cur) cur++;
                 if (*cur == '-') {
-                    sign = 1;
+                    sign = '-';
                     cur++;
                 } else if (*cur == '+')
                     cur++;
-                ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
+                ret = xmlSchemaParseUInt(&cur, &decimal);
+                /* add sign */
                 if (ret < 0)
-                    goto return1;
+                    goto valIntegerReturn1;
+                decimal.str[0] = sign;
 		if (normOnTheFly)
 		    while IS_WSP_BLANK_CH(*cur) cur++;
                 if (*cur != 0)
-                    goto return1;
-                if (type->builtInType == XML_SCHEMAS_LONG) {
-                    if (hi >= 922) {
-                        if (hi > 922)
-                            goto return1;
-                        if (mi >= 33720368) {
-                            if (mi > 33720368)
-                                goto return1;
-                            if ((sign == 0) && (lo > 54775807))
-                                goto return1;
-                            if ((sign == 1) && (lo > 54775808))
-                                goto return1;
-                        }
-                    }
-                } else if (type->builtInType == XML_SCHEMAS_INT) {
-                    if (hi != 0)
-                        goto return1;
-                    if (mi >= 21) {
-                        if (mi > 21)
-                            goto return1;
-                        if ((sign == 0) && (lo > 47483647))
-                            goto return1;
-                        if ((sign == 1) && (lo > 47483648))
-                            goto return1;
-                    }
-                } else if (type->builtInType == XML_SCHEMAS_SHORT) {
-                    if ((mi != 0) || (hi != 0))
-                        goto return1;
-                    if ((sign == 1) && (lo > 32768))
-                        goto return1;
-                    if ((sign == 0) && (lo > 32767))
-                        goto return1;
-                } else if (type->builtInType == XML_SCHEMAS_BYTE) {
-                    if ((mi != 0) || (hi != 0))
-                        goto return1;
-                    if ((sign == 1) && (lo > 128))
-                        goto return1;
-                    if ((sign == 0) && (lo > 127))
-                        goto return1;
+                    goto valIntegerReturn1;
+                if (type->builtInType == XML_SCHEMAS_NPINTEGER)
+                {
+                    if(xmlSchemaValDecimalCompareWithInteger(&decimal, 0) > 0)
+                        goto valIntegerReturn1;
                 }
-                if (val != NULL) {
-                    v = xmlSchemaNewValue(type->builtInType);
-                    if (v != NULL) {
-                        v->value.decimal.lo = lo;
-                        v->value.decimal.mi = mi;
-                        v->value.decimal.hi = hi;
-                        v->value.decimal.sign = sign;
-                        v->value.decimal.frac = 0;
-                        v->value.decimal.total = ret;
-                        *val = v;
-                    }
+                else if (type->builtInType == XML_SCHEMAS_PINTEGER)
+                {
+                    if (sign == '-')
+                        goto valIntegerReturn1;
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) <= 0)
+                        goto valIntegerReturn1;
                 }
-                goto return0;
-            }
-        case XML_SCHEMAS_UINT:
-        case XML_SCHEMAS_ULONG:
-        case XML_SCHEMAS_USHORT:
-        case XML_SCHEMAS_UBYTE:{
-                const xmlChar *cur = value;
-                unsigned long lo, mi, hi;
-
-                if (cur == NULL)
-                    goto return1;
-		if (normOnTheFly)
-		    while IS_WSP_BLANK_CH(*cur) cur++;
-                ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
-                if (ret < 0)
-                    goto return1;
-		if (normOnTheFly)
-		    while IS_WSP_BLANK_CH(*cur) cur++;
-                if (*cur != 0)
-                    goto return1;
-                if (type->builtInType == XML_SCHEMAS_ULONG) {
-                    if (hi >= 1844) {
-                        if (hi > 1844)
-                            goto return1;
-                        if (mi >= 67440737) {
-                            if (mi > 67440737)
-                                goto return1;
-                            if (lo > 9551615)
-                                goto return1;
-                        }
-                    }
-                } else if (type->builtInType == XML_SCHEMAS_UINT) {
-                    if (hi != 0)
-                        goto return1;
-                    if (mi >= 42) {
-                        if (mi > 42)
-                            goto return1;
-                        if (lo > 94967295)
-                            goto return1;
-                    }
-                } else if (type->builtInType == XML_SCHEMAS_USHORT) {
-                    if ((mi != 0) || (hi != 0))
-                        goto return1;
-                    if (lo > 65535)
-                        goto return1;
-                } else if (type->builtInType == XML_SCHEMAS_UBYTE) {
-                    if ((mi != 0) || (hi != 0))
-                        goto return1;
-                    if (lo > 255)
-                        goto return1;
+                else if (type->builtInType == XML_SCHEMAS_NINTEGER)
+                {
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) >= 0)
+                        goto valIntegerReturn1;
+                }
+                else if (type->builtInType == XML_SCHEMAS_NNINTEGER)
+                {
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0)
+                        goto valIntegerReturn1;
+                }
+                else if(type->builtInType == XML_SCHEMAS_LONG)
+                {
+                    /* (u)int64_t may not be available on 32 bit platform, just use decimal */
+                    xmlSchemaValDecimal tmpDecimal;
+                    static const char maxLong[] = "+9223372036854775807.0";
+                    static const char minLong[] = "-9223372036854775808.0";
+                    tmpDecimal.fractionalPlaces = 1;
+                    tmpDecimal.integralPlaces = 19;
+                    tmpDecimal.str = BAD_CAST maxLong;
+                    if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) > 0)
+                        goto valIntegerReturn1;
+                    tmpDecimal.str = BAD_CAST minLong;
+                    if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) < 0)
+                        goto valIntegerReturn1;
+                }
+                else if(type->builtInType == XML_SCHEMAS_ULONG)
+                {
+                    xmlSchemaValDecimal tmpDecimal;
+                    static const char maxULong[] = "+18446744073709551615.0";
+                    tmpDecimal.fractionalPlaces = 1;
+                    tmpDecimal.integralPlaces = 20;
+                    tmpDecimal.str = (xmlChar*)maxULong;
+                    if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) > 0)
+                        goto valIntegerReturn1;
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0)
+                        goto valIntegerReturn1;
+                }
+                else if(type->builtInType == XML_SCHEMAS_INT)
+                {
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0x7fffffff) > 0) /* INT32_MAX */
+                        goto valIntegerReturn1;
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, -0x7fffffff-1) < 0) /* INT32_MIN */
+                        goto valIntegerReturn1;
+                }
+                else if(type->builtInType == XML_SCHEMAS_SHORT)
+                {
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0x7fff) > 0) /* INT16_MAX */
+                        goto valIntegerReturn1;
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, -0x8000) < 0) /* INT16_MIN */
+                        goto valIntegerReturn1;
+                }
+                else if(type->builtInType == XML_SCHEMAS_BYTE)
+                {if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0x7f) > 0) /* INT8_MAX */
+                        goto valIntegerReturn1;
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, -0x80) < 0) /* INT8_MIN */
+                        goto valIntegerReturn1;
+                }
+                else if(type->builtInType == XML_SCHEMAS_UINT)
+                {
+                    xmlSchemaValDecimal tmpDecimal;
+                    static const char maxUInt[] = "+4294967295.0";
+                    tmpDecimal.fractionalPlaces = 1;
+                    tmpDecimal.integralPlaces = 10;
+                    tmpDecimal.str = (xmlChar*)maxUInt;
+                    if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) > 0)
+                        goto valIntegerReturn1;
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0)
+                        goto valIntegerReturn1;
+                }
+                else if(type->builtInType == XML_SCHEMAS_USHORT)
+                {
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0xffff) > 0) /* UINT16_MAX */
+                        goto valIntegerReturn1;
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0)
+                        goto valIntegerReturn1;
+                }
+                else if(type->builtInType == XML_SCHEMAS_UBYTE)
+                {
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0xff) > 0) /* UINT8_MAX */
+                        goto valIntegerReturn1;
+                    if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0)
+                        goto valIntegerReturn1;
                 }
                 if (val != NULL) {
                     v = xmlSchemaNewValue(type->builtInType);
                     if (v != NULL) {
-                        v->value.decimal.lo = lo;
-                        v->value.decimal.mi = mi;
-                        v->value.decimal.hi = hi;
-                        v->value.decimal.sign = 0;
-                        v->value.decimal.frac = 0;
-                        v->value.decimal.total = ret;
+                        v->value.decimal = decimal;
                         *val = v;
                     }
                 }
+                else if(decimal.str != NULL)
+                {
+                    xmlFree(decimal.str);
+                }
                 goto return0;
+            valIntegerReturn1:
+                if(decimal.str != NULL)
+                {
+                    xmlFree(decimal.str);
+                }
+                goto return1;
             }
     }
 
@@ -3534,139 +3669,16 @@ xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
 static int
 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
 {
-    xmlSchemaValPtr swp;
-    int order = 1, integx, integy, dlen;
-    unsigned long hi, mi, lo;
-
-    /*
-     * First test: If x is -ve and not zero
-     */
-    if ((x->value.decimal.sign) &&
-	((x->value.decimal.lo != 0) ||
-	 (x->value.decimal.mi != 0) ||
-	 (x->value.decimal.hi != 0))) {
-	/*
-	 * Then if y is -ve and not zero reverse the compare
-	 */
-	if ((y->value.decimal.sign) &&
-	    ((y->value.decimal.lo != 0) ||
-	     (y->value.decimal.mi != 0) ||
-	     (y->value.decimal.hi != 0)))
-	    order = -1;
-	/*
-	 * Otherwise (y >= 0) we have the answer
-	 */
-	else
-	    return (-1);
-    /*
-     * If x is not -ve and y is -ve we have the answer
-     */
-    } else if ((y->value.decimal.sign) &&
-	       ((y->value.decimal.lo != 0) ||
-		(y->value.decimal.mi != 0) ||
-		(y->value.decimal.hi != 0))) {
-        return (1);
-    }
-    /*
-     * If it's not simply determined by a difference in sign,
-     * then we need to compare the actual values of the two nums.
-     * To do this, we start by looking at the integral parts.
-     * If the number of integral digits differ, then we have our
-     * answer.
-     */
-    integx = x->value.decimal.total - x->value.decimal.frac;
-    integy = y->value.decimal.total - y->value.decimal.frac;
-    /*
-    * NOTE: We changed the "total" for values like "0.1"
-    *   (or "-0.1" or ".1") to be 1, which was 2 previously.
-    *   Therefore the special case, when such values are
-    *   compared with 0, needs to be handled separately;
-    *   otherwise a zero would be recognized incorrectly as
-    *   greater than those values. This has the nice side effect
-    *   that we gain an overall optimized comparison with zeroes.
-    * Note that a "0" has a "total" of 1 already.
-    */
-    if (integx == 1) {
-	if (x->value.decimal.lo == 0) {
-	    if (integy != 1)
-		return -order;
-	    else if (y->value.decimal.lo != 0)
-		return -order;
-	    else
-		return(0);
-	}
-    }
-    if (integy == 1) {
-	if (y->value.decimal.lo == 0) {
-	    if (integx != 1)
-		return order;
-	    else if (x->value.decimal.lo != 0)
-		return order;
-	    else
-		return(0);
-	}
-    }
-
-    if (integx > integy)
-	return order;
-    else if (integy > integx)
-	return -order;
-
-    /*
-     * If the number of integral digits is the same for both numbers,
-     * then things get a little more complicated.  We need to "normalize"
-     * the numbers in order to properly compare them.  To do this, we
-     * look at the total length of each number (length => number of
-     * significant digits), and divide the "shorter" by 10 (decreasing
-     * the length) until they are of equal length.
-     */
-    dlen = x->value.decimal.total - y->value.decimal.total;
-    if (dlen < 0) {	/* y has more digits than x */
-	swp = x;
-	hi = y->value.decimal.hi;
-	mi = y->value.decimal.mi;
-	lo = y->value.decimal.lo;
-	dlen = -dlen;
-	order = -order;
-    } else {		/* x has more digits than y */
-	swp = y;
-	hi = x->value.decimal.hi;
-	mi = x->value.decimal.mi;
-	lo = x->value.decimal.lo;
-    }
-    while (dlen > 8) {	/* in effect, right shift by 10**8 */
-	lo = mi;
-	mi = hi;
-	hi = 0;
-	dlen -= 8;
-    }
-    while (dlen > 0) {
-	unsigned long rem1, rem2;
-	rem1 = (hi % 10) * 100000000L;
-	hi = hi / 10;
-	rem2 = (mi % 10) * 100000000L;
-	mi = (mi + rem1) / 10;
-	lo = (lo + rem2) / 10;
-	dlen--;
+    int res = xmlSchemaValDecimalCompare(&x->value.decimal, &y->value.decimal);
+    if(res > 0)
+    {
+        return 1;
     }
-    if (hi > swp->value.decimal.hi) {
-	return order;
-    } else if (hi == swp->value.decimal.hi) {
-	if (mi > swp->value.decimal.mi) {
-	    return order;
-	} else if (mi == swp->value.decimal.mi) {
-	    if (lo > swp->value.decimal.lo) {
-		return order;
-	    } else if (lo == swp->value.decimal.lo) {
-		if (x->value.decimal.total == y->value.decimal.total) {
-		    return 0;
-		} else {
-		    return order;
-		}
-	    }
-	}
+    if(res < 0)
+    {
+        return -1;
     }
-    return -order;
+    return 0;
 }
 
 /**
@@ -3853,6 +3865,24 @@ xmlSchemaCopyValue(xmlSchemaValPtr val)
 		    cur->value.base64.str =
                     xmlStrdup(BAD_CAST val->value.base64.str);
 		break;
+            case XML_SCHEMAS_DECIMAL:
+            case XML_SCHEMAS_INTEGER:
+            case XML_SCHEMAS_PINTEGER:
+            case XML_SCHEMAS_NPINTEGER:
+            case XML_SCHEMAS_NINTEGER:
+            case XML_SCHEMAS_NNINTEGER:
+            case XML_SCHEMAS_LONG:
+            case XML_SCHEMAS_BYTE:
+            case XML_SCHEMAS_SHORT:
+            case XML_SCHEMAS_INT:
+            case XML_SCHEMAS_UINT:
+            case XML_SCHEMAS_ULONG:
+            case XML_SCHEMAS_USHORT:
+            case XML_SCHEMAS_UBYTE:
+                cur = xmlSchemaDupVal(val);
+                if (val->value.decimal.str != NULL)
+                    cur->value.decimal.str = xmlStrdup(BAD_CAST val->value.decimal.str);
+		break;
 	    default:
 		cur = xmlSchemaDupVal(val);
 		break;
@@ -4141,9 +4171,15 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
 
         if (!y->value.date.tz_flag) {
             p1 = xmlSchemaDateNormalize(x, 0);
+            if (p1 == NULL)
+                return -2;
             p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
             /* normalize y + 14:00 */
             q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
+            if (q1 == NULL) {
+		xmlSchemaFreeValue(p1);
+                return -2;
+            }
 
             q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
             if (p1d < q1d) {
@@ -4162,6 +4198,11 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
 		    int ret = 0;
                     /* normalize y - 14:00 */
                     q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
+                    if (q2 == NULL) {
+                        xmlSchemaFreeValue(p1);
+                        xmlSchemaFreeValue(q1);
+                        return -2;
+                    }
                     q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
                     if (p1d > q2d)
                         ret = 1;
@@ -4185,10 +4226,16 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
         }
     } else if (y->value.date.tz_flag) {
         q1 = xmlSchemaDateNormalize(y, 0);
+        if (q1 == NULL)
+            return -2;
         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
 
         /* normalize x - 14:00 */
         p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
+        if (p1 == NULL) {
+	    xmlSchemaFreeValue(q1);
+            return -2;
+        }
         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
 
         if (p1d < q1d) {
@@ -4207,6 +4254,11 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
 	        int ret = 0;
                 /* normalize x + 14:00 */
                 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
+                if (p2 == NULL) {
+                    xmlSchemaFreeValue(p1);
+                    xmlSchemaFreeValue(q1);
+                    return -2;
+                }
                 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
 
                 if (p2d > q1d) {
@@ -4236,9 +4288,15 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
     if (x->type == y->type) {
         int ret = 0;
         q1 = xmlSchemaDateNormalize(y, 0);
+        if (q1 == NULL)
+            return -2;
         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
 
         p1 = xmlSchemaDateNormalize(x, 0);
+        if (p1 == NULL) {
+	    xmlSchemaFreeValue(q1);
+            return -2;
+        }
         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
 
         if (p1d < q1d) {
@@ -4915,7 +4973,7 @@ xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
 	    * TODO: Compare those against QName.
 	    */
 	    if (ytype == XML_SCHEMAS_QNAME) {
-		TODO
+		/* TODO */
 		if (y == NULL)
 		    return(-2);
 		return (-2);
@@ -5040,7 +5098,7 @@ xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
         case XML_SCHEMAS_IDREFS:
         case XML_SCHEMAS_ENTITIES:
         case XML_SCHEMAS_NMTOKENS:
-	    TODO
+	    /* TODO */
 	    break;
     }
     return -2;
@@ -5190,9 +5248,10 @@ xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
     /*
     * TODO: Check if this is a decimal.
     */
+    char *discard;
     if (facet == NULL || facet->val == NULL)
         return 0;
-    return ((unsigned long) facet->val->value.decimal.lo);
+    return strtoul((const char*)facet->val->value.decimal.str+1, &discard, 10);
 }
 
 /**
@@ -5220,21 +5279,21 @@ xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
     * (compare value.decimal.mi and value.decimal.hi as well?).
     */
     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
-	if (actualLen != facet->val->value.decimal.lo) {
+        if (actualLen != xmlSchemaGetFacetValueAsULong(facet)) {
 	    if (expectedLen != NULL)
-		*expectedLen = facet->val->value.decimal.lo;
+                *expectedLen = xmlSchemaGetFacetValueAsULong(facet);
 	    return (XML_SCHEMAV_CVC_LENGTH_VALID);
 	}
     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
-	if (actualLen < facet->val->value.decimal.lo) {
+        if (actualLen < xmlSchemaGetFacetValueAsULong(facet)) {
 	    if (expectedLen != NULL)
-		*expectedLen = facet->val->value.decimal.lo;
+                *expectedLen = xmlSchemaGetFacetValueAsULong(facet);
 	    return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
 	}
     } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
-	if (actualLen > facet->val->value.decimal.lo) {
+        if (actualLen > xmlSchemaGetFacetValueAsULong(facet)) {
 	    if (expectedLen != NULL)
-		*expectedLen = facet->val->value.decimal.lo;
+                *expectedLen = xmlSchemaGetFacetValueAsULong(facet);
 	    return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
 	}
     } else
@@ -5287,7 +5346,8 @@ xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
     if ((facet->val == NULL) ||
 	((facet->val->type != XML_SCHEMAS_DECIMAL) &&
 	 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
-	(facet->val->value.decimal.frac != 0)) {
+	!(xmlSchemaValDecimalIsInteger(&facet->val->value.decimal)))
+ {
 	return(-1);
     }
     if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
@@ -5341,21 +5401,22 @@ xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
 		*/
 		return (0);
 	    default:
-		TODO
+		/* TODO */
+                break;
 	}
     }
     *length = (unsigned long) len;
     /*
-    * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
+    * TODO: Return the whole expected value. (This may be possible now with xmlSchemaValDecimalCompareWithInteger)
     */
     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
-	if (len != facet->val->value.decimal.lo)
+        if (len != xmlSchemaGetFacetValueAsULong(facet))
 	    return(XML_SCHEMAV_CVC_LENGTH_VALID);
     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
-	if (len < facet->val->value.decimal.lo)
+        if (len < xmlSchemaGetFacetValueAsULong(facet))
 	    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
     } else {
-	if (len > facet->val->value.decimal.lo)
+        if (len > xmlSchemaGetFacetValueAsULong(facet))
 	    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
     }
 
@@ -5551,7 +5612,7 @@ xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
 	    if ((facet->val == NULL) ||
 		((facet->val->type != XML_SCHEMAS_DECIMAL) &&
 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
-		(facet->val->value.decimal.frac != 0)) {
+		!xmlSchemaValDecimalIsInteger(&facet->val->value.decimal)) {
 		return(-1);
 	    }
 	    if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
@@ -5595,18 +5656,18 @@ xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
 			    len = xmlSchemaNormLen(value);
 			break;
 		    default:
-		        TODO
+		        /* TODO */
+                        break;
 		}
 	    }
 	    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
-		if (len != facet->val->value.decimal.lo)
+                if (len != xmlSchemaGetFacetValueAsULong(facet))
 		    return(XML_SCHEMAV_CVC_LENGTH_VALID);
 	    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
-		if (len < facet->val->value.decimal.lo)
+                if (len < xmlSchemaGetFacetValueAsULong(facet))
 		    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
-	    } else {
-		if (len > facet->val->value.decimal.lo)
-		    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
+	    } else if (len > xmlSchemaGetFacetValueAsULong(facet)) {
+                return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
 	    }
 	    break;
 	}
@@ -5616,7 +5677,7 @@ xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
 	    if ((facet->val == NULL) ||
 		((facet->val->type != XML_SCHEMAS_PINTEGER) &&
 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
-		(facet->val->value.decimal.frac != 0)) {
+		!xmlSchemaValDecimalIsInteger(&facet->val->value.decimal)) {
 		return(-1);
 	    }
 	    if ((val == NULL) ||
@@ -5637,16 +5698,17 @@ xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
 		return(-1);
 	    }
 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
-	        if (val->value.decimal.total > facet->val->value.decimal.lo)
+                if (xmlSchemaValDecimalGetSignificantDigitCount(&val->value.decimal) > xmlSchemaGetFacetValueAsULong(facet))
 	            return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID);
 
 	    } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
-	        if (val->value.decimal.frac > facet->val->value.decimal.lo)
+			if ((xmlSchemaValDecimalIsInteger(&val->value.decimal) ? 0 : val->value.decimal.fractionalPlaces) > xmlSchemaGetFacetValueAsULong(facet))
 		    return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID);
 	    }
 	    break;
 	default:
-	    TODO
+	    /* TODO */
+            break;
     }
     return(0);
 
@@ -5872,75 +5934,13 @@ xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
 		    BAD_CAST val->value.qname.uri);
 	    }
 	    break;
-	case XML_SCHEMAS_DECIMAL:
-	    /*
-	    * TODO: Lookout for a more simple implementation.
-	    */
-	    if ((val->value.decimal.total == 1) &&
-		(val->value.decimal.lo == 0)) {
-		*retValue = xmlStrdup(BAD_CAST "0.0");
-	    } else {
-		xmlSchemaValDecimal dec = val->value.decimal;
-		int bufsize;
-		char *buf = NULL, *offs;
-
-		/* Add room for the decimal point as well. */
-		bufsize = dec.total + 2;
-		if (dec.sign)
-		    bufsize++;
-		/* Add room for leading/trailing zero. */
-		if ((dec.frac == 0) || (dec.frac == dec.total))
-		    bufsize++;
-		buf = xmlMalloc(bufsize);
-		if (buf == NULL)
-		    return(-1);
-		offs = buf;
-		if (dec.sign)
-		    *offs++ = '-';
-		if (dec.frac == dec.total) {
-		    *offs++ = '0';
-		    *offs++ = '.';
-		}
-		if (dec.hi != 0)
-		    snprintf(offs, bufsize - (offs - buf),
-			"%lu%lu%lu", dec.hi, dec.mi, dec.lo);
-		else if (dec.mi != 0)
-		    snprintf(offs, bufsize - (offs - buf),
-			"%lu%lu", dec.mi, dec.lo);
-		else
-		    snprintf(offs, bufsize - (offs - buf),
-			"%lu", dec.lo);
-
-		if (dec.frac != 0) {
-		    if (dec.frac != dec.total) {
-			int diff = dec.total - dec.frac;
-			/*
-			* Insert the decimal point.
-			*/
-			memmove(offs + diff + 1, offs + diff, dec.frac +1);
-			offs[diff] = '.';
-		    } else {
-			unsigned int i = 0;
-			/*
-			* Insert missing zeroes behind the decimal point.
-			*/
-			while (*(offs + i) != 0)
-			    i++;
-			if (i < dec.total) {
-			    memmove(offs + (dec.total - i), offs, i +1);
-			    memset(offs, '0', dec.total - i);
-			}
-		    }
-		} else {
-		    /*
-		    * Append decimal point and zero.
-		    */
-		    offs = buf + bufsize - 1;
-		    *offs-- = 0;
-		    *offs-- = '0';
-		    *offs-- = '.';
-		}
-		*retValue = BAD_CAST buf;
+	case XML_SCHEMAS_DECIMAL: {
+                xmlChar *start = val->value.decimal.str;
+                if(start[0] == '+')
+                {
+                    start += 1;
+                }
+                *retValue = xmlStrdup(start);
 	    }
 	    break;
 	case XML_SCHEMAS_INTEGER:
@@ -5955,40 +5955,20 @@ xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
 	case XML_SCHEMAS_UINT:
         case XML_SCHEMAS_ULONG:
         case XML_SCHEMAS_USHORT:
-        case XML_SCHEMAS_UBYTE:
-	    if ((val->value.decimal.total == 1) &&
-		(val->value.decimal.lo == 0))
-		*retValue = xmlStrdup(BAD_CAST "0");
-	    else {
-		xmlSchemaValDecimal dec = val->value.decimal;
-		int bufsize = dec.total + 1;
-
-		/* Add room for the decimal point as well. */
-		if (dec.sign)
-		    bufsize++;
-		*retValue = xmlMalloc(bufsize);
-		if (*retValue == NULL)
-		    return(-1);
-		if (dec.hi != 0) {
-		    if (dec.sign)
-			snprintf((char *) *retValue, bufsize,
-			    "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
-		    else
-			snprintf((char *) *retValue, bufsize,
-			    "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
-		} else if (dec.mi != 0) {
-		    if (dec.sign)
-			snprintf((char *) *retValue, bufsize,
-			    "-%lu%lu", dec.mi, dec.lo);
-		    else
-			snprintf((char *) *retValue, bufsize,
-			    "%lu%lu", dec.mi, dec.lo);
-		} else {
-		    if (dec.sign)
-			snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
-		    else
-			snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
-		}
+        case XML_SCHEMAS_UBYTE: {
+            xmlChar *start = val->value.decimal.str;
+            /* 2 = sign+NULL */
+            size_t bufSize = val->value.decimal.integralPlaces+2;
+            if(start[0] == '+')
+            {
+                start += 1;
+                bufSize -= 1;
+            }
+            *retValue = xmlMalloc(bufSize);
+            if(*retValue) {
+                /* no need to limit string length in format, it will only print bufSize-1 chars anyways */
+                snprintf((char*)*retValue, bufSize, "%s", start);
+            }
 	    }
 	    break;
 	case XML_SCHEMAS_BOOLEAN:
diff --git a/xmlstring.c b/xmlstring.c
index 46301c3b2b76650e87df2a759231bcac8ef046bd..258ecc92c3bfe2fec9ce195f9882e86ff1b055d1 100644
--- a/xmlstring.c
+++ b/xmlstring.c
@@ -23,6 +23,17 @@
 #include <libxml/parserInternals.h>
 #include <libxml/xmlstring.h>
 
+#include "private/parser.h"
+#include "private/string.h"
+
+#ifndef va_copy
+  #ifdef __va_copy
+    #define va_copy(dest, src) __va_copy(dest, src)
+  #else
+    #define va_copy(dest, src) memcpy(dest, src, sizeof(va_list))
+  #endif
+#endif
+
 /************************************************************************
  *                                                                      *
  *                Commodity functions to handle xmlChars                *
@@ -43,12 +54,11 @@ xmlStrndup(const xmlChar *cur, int len) {
     xmlChar *ret;
 
     if ((cur == NULL) || (len < 0)) return(NULL);
-    ret = (xmlChar *) xmlMallocAtomic(((size_t) len + 1) * sizeof(xmlChar));
+    ret = (xmlChar *) xmlMallocAtomic((size_t) len + 1);
     if (ret == NULL) {
-        xmlErrMemory(NULL, NULL);
         return(NULL);
     }
-    memcpy(ret, cur, len * sizeof(xmlChar));
+    memcpy(ret, cur, len);
     ret[len] = 0;
     return(ret);
 }
@@ -88,12 +98,12 @@ xmlCharStrndup(const char *cur, int len) {
     xmlChar *ret;
 
     if ((cur == NULL) || (len < 0)) return(NULL);
-    ret = (xmlChar *) xmlMallocAtomic(((size_t) len + 1) * sizeof(xmlChar));
+    ret = (xmlChar *) xmlMallocAtomic((size_t) len + 1);
     if (ret == NULL) {
-        xmlErrMemory(NULL, NULL);
         return(NULL);
     }
     for (i = 0;i < len;i++) {
+        /* Explicit sign change */
         ret[i] = (xmlChar) cur[i];
         if (ret[i] == 0) return(ret);
     }
@@ -457,12 +467,12 @@ xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
     size = xmlStrlen(cur);
     if ((size < 0) || (size > INT_MAX - len))
         return(NULL);
-    ret = (xmlChar *) xmlRealloc(cur, ((size_t) size + len + 1) * sizeof(xmlChar));
+    ret = (xmlChar *) xmlRealloc(cur, (size_t) size + len + 1);
     if (ret == NULL) {
-        xmlErrMemory(NULL, NULL);
-        return(cur);
+        xmlFree(cur);
+        return(NULL);
     }
-    memcpy(&ret[size], add, len * sizeof(xmlChar));
+    memcpy(&ret[size], add, len);
     ret[size + len] = 0;
     return(ret);
 }
@@ -489,21 +499,19 @@ xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len) {
         if (len < 0)
             return(NULL);
     }
-    if ((str2 == NULL) || (len == 0))
-        return(xmlStrdup(str1));
     if (str1 == NULL)
         return(xmlStrndup(str2, len));
+    if ((str2 == NULL) || (len == 0))
+        return(xmlStrdup(str1));
 
     size = xmlStrlen(str1);
     if ((size < 0) || (size > INT_MAX - len))
         return(NULL);
-    ret = (xmlChar *) xmlMalloc(((size_t) size + len + 1) * sizeof(xmlChar));
-    if (ret == NULL) {
-        xmlErrMemory(NULL, NULL);
-        return(xmlStrndup(str1, size));
-    }
-    memcpy(ret, str1, size * sizeof(xmlChar));
-    memcpy(&ret[size], str2, len * sizeof(xmlChar));
+    ret = (xmlChar *) xmlMalloc((size_t) size + len + 1);
+    if (ret == NULL)
+        return(NULL);
+    memcpy(ret, str1, size);
+    memcpy(&ret[size], str2, len);
     ret[size + len] = 0;
     return(ret);
 }
@@ -543,7 +551,7 @@ xmlStrcat(xmlChar *cur, const xmlChar *add) {
  *
  * Returns the number of characters written to @buf or -1 if an error occurs.
  */
-int XMLCDECL
+int
 xmlStrPrintf(xmlChar *buf, int len, const char *msg, ...) {
     va_list args;
     int ret;
@@ -585,6 +593,148 @@ xmlStrVPrintf(xmlChar *buf, int len, const char *msg, va_list ap) {
     return(ret);
 }
 
+/**
+ * xmlStrVASPrintf:
+ * @out:  pointer to the resulting string
+ * @maxSize:  maximum size of the output buffer
+ * @msg:  printf format string
+ * @ap:  arguments for format string
+ *
+ * Creates a newly allocated string according to format.
+ *
+ * Returns 0 on success, 1 if the result was truncated or on other
+ * errors, -1 if a memory allocation failed.
+ */
+int
+xmlStrVASPrintf(xmlChar **out, int maxSize, const char *msg, va_list ap) {
+    char empty[1];
+    va_list copy;
+    xmlChar *buf;
+    int res, size;
+    int truncated = 0;
+
+    if (out == NULL)
+        return(1);
+    *out = NULL;
+    if (msg == NULL)
+        return(1);
+    if (maxSize < 32)
+        maxSize = 32;
+
+    va_copy(copy, ap);
+    res = vsnprintf(empty, 1, msg, copy);
+    va_end(copy);
+
+    if (res > 0) {
+        /* snprintf seems to work according to C99. */
+
+        if (res < maxSize) {
+            size = res + 1;
+        } else {
+            size = maxSize;
+            truncated = 1;
+        }
+        buf = xmlMalloc(size);
+        if (buf == NULL)
+            return(-1);
+        if (vsnprintf((char *) buf, size, msg, ap) < 0) {
+            xmlFree(buf);
+            return(1);
+        }
+    } else {
+        /*
+         * Unfortunately, older snprintf implementations don't follow the
+         * C99 spec. If the output exceeds the size of the buffer, they can
+         * return -1, 0 or the number of characters written instead of the
+         * needed size. Older MSCVRT also won't write a terminating null
+         * byte if the buffer is too small.
+         *
+         * If the value returned is non-negative and strictly less than
+         * the buffer size (without terminating null), the result should
+         * have been written completely, so we double the buffer size
+         * until this condition is true. This assumes that snprintf will
+         * eventually return a non-negative value. Otherwise, we will
+         * allocate more and more memory until we run out.
+         *
+         * Note that this code path is also executed on conforming
+         * platforms if the output is the empty string.
+         */
+
+        buf = NULL;
+        size = 32;
+        while (1) {
+            buf = xmlMalloc(size);
+            if (buf == NULL)
+                return(-1);
+
+            va_copy(copy, ap);
+            res = vsnprintf((char *) buf, size, msg, copy);
+            va_end(copy);
+            if ((res >= 0) && (res < size - 1))
+                break;
+
+            if (size >= maxSize) {
+                truncated = 1;
+                break;
+            }
+
+            xmlFree(buf);
+
+            if (size > maxSize / 2)
+                size = maxSize;
+            else
+                size *= 2;
+        }
+    }
+
+    /*
+     * If the output was truncated, make sure that the buffer doesn't
+     * end with a truncated UTF-8 sequence.
+     */
+    if (truncated != 0) {
+        int i = size - 1;
+
+        while (i > 0) {
+            /* Break after ASCII */
+            if (buf[i-1] < 0x80)
+                break;
+            i -= 1;
+            /* Break before non-ASCII */
+            if (buf[i] >= 0xc0)
+                break;
+        }
+
+        buf[i] = 0;
+    }
+
+    *out = (xmlChar *) buf;
+    return(truncated);
+}
+
+/**
+ * xmlStrASPrintf:
+ * @out:  pointer to the resulting string
+ * @maxSize:  maximum size of the output buffer
+ * @msg:  printf format string
+ * @...:  arguments for format string
+ *
+ * See xmlStrVASPrintf.
+ *
+ * Returns 0 on success, 1 if the result was truncated or on other
+ * errors, -1 if a memory allocation failed.
+ */
+int
+xmlStrASPrintf(xmlChar **out, int maxSize, const char *msg, ...) {
+    va_list ap;
+    int ret;
+
+    va_start(ap, msg);
+    ret = xmlStrVASPrintf(out, maxSize, msg, ap);
+    va_end(ap);
+
+    return(ret);
+}
+
 /************************************************************************
  *                                                                      *
  *              Generic UTF8 handling routines                          *
@@ -712,47 +862,47 @@ xmlGetUTF8Char(const unsigned char *utf, int *len) {
         goto error;
     if (len == NULL)
         goto error;
-    if (*len < 1)
-        goto error;
 
     c = utf[0];
-    if (c & 0x80) {
-        if (*len < 2)
+    if (c < 0x80) {
+        if (*len < 1)
             goto error;
-        if ((utf[1] & 0xc0) != 0x80)
+        /* 1-byte code */
+        *len = 1;
+    } else {
+        if ((*len < 2) || ((utf[1] & 0xc0) != 0x80))
             goto error;
-        if ((c & 0xe0) == 0xe0) {
-            if (*len < 3)
+        if (c < 0xe0) {
+            if (c < 0xc2)
                 goto error;
-            if ((utf[2] & 0xc0) != 0x80)
+            /* 2-byte code */
+            *len = 2;
+            c = (c & 0x1f) << 6;
+            c |= utf[1] & 0x3f;
+        } else {
+            if ((*len < 3) || ((utf[2] & 0xc0) != 0x80))
                 goto error;
-            if ((c & 0xf0) == 0xf0) {
-                if (*len < 4)
+            if (c < 0xf0) {
+                /* 3-byte code */
+                *len = 3;
+                c = (c & 0xf) << 12;
+                c |= (utf[1] & 0x3f) << 6;
+                c |= utf[2] & 0x3f;
+                if ((c < 0x800) || ((c >= 0xd800) && (c < 0xe000)))
                     goto error;
-                if ((c & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
+            } else {
+                if ((*len < 4) || ((utf[3] & 0xc0) != 0x80))
                     goto error;
                 *len = 4;
                 /* 4-byte code */
-                c = (utf[0] & 0x7) << 18;
+                c = (c & 0x7) << 18;
                 c |= (utf[1] & 0x3f) << 12;
                 c |= (utf[2] & 0x3f) << 6;
                 c |= utf[3] & 0x3f;
-            } else {
-              /* 3-byte code */
-                *len = 3;
-                c = (utf[0] & 0xf) << 12;
-                c |= (utf[1] & 0x3f) << 6;
-                c |= utf[2] & 0x3f;
+                if ((c < 0x10000) || (c >= 0x110000))
+                    goto error;
             }
-        } else {
-          /* 2-byte code */
-            *len = 2;
-            c = (utf[0] & 0x1f) << 6;
-            c |= utf[1] & 0x3f;
         }
-    } else {
-        /* 1-byte code */
-        *len = 1;
     }
     return(c);
 
@@ -871,11 +1021,11 @@ xmlUTF8Strndup(const xmlChar *utf, int len) {
 
     if ((utf == NULL) || (len < 0)) return(NULL);
     i = xmlUTF8Strsize(utf, len);
-    ret = (xmlChar *) xmlMallocAtomic(((size_t) i + 1) * sizeof(xmlChar));
+    ret = (xmlChar *) xmlMallocAtomic((size_t) i + 1);
     if (ret == NULL) {
         return(NULL);
     }
-    memcpy(ret, utf, i * sizeof(xmlChar));
+    memcpy(ret, utf, i);
     ret[i] = 0;
     return(ret);
 }
@@ -956,8 +1106,9 @@ xmlUTF8Strloc(const xmlChar *utf, const xmlChar *utfchar) {
  * Create a substring from a given UTF-8 string
  * Note:  positions are given in units of UTF-8 chars
  *
- * Returns a pointer to a newly created string
- * or NULL if any problem
+ * Returns a pointer to a newly created string or NULL if the
+ * start index is out of bounds or a memory allocation failed.
+ * If len is too large, the result is truncated.
  */
 
 xmlChar *
@@ -972,16 +1123,18 @@ xmlUTF8Strsub(const xmlChar *utf, int start, int len) {
     /*
      * Skip over any leading chars
      */
-    for (i = 0;i < start;i++) {
-        if ((ch=*utf++) == 0) return(NULL);
-        if ( ch & 0x80 ) {
-            /* if not simple ascii, verify proper format */
-            if ( (ch & 0xc0) != 0xc0 )
-                return(NULL);
-            /* then skip over remaining bytes for this char */
-            while ( (ch <<= 1) & 0x80 )
-                if ( (*utf++ & 0xc0) != 0x80 )
+    for (i = 0; i < start; i++) {
+        ch = *utf++;
+        if (ch == 0)
+            return(NULL);
+        /* skip over remaining bytes for this char */
+        if (ch & 0x80) {
+            ch <<= 1;
+            while (ch & 0x80) {
+                if (*utf++ == 0)
                     return(NULL);
+                ch <<= 1;
+            }
         }
     }
 
@@ -1022,13 +1175,12 @@ xmlEscapeFormatString(xmlChar **msg)
     if ((count > INT_MAX) || (msgLen > INT_MAX - count))
         return(NULL);
     resultLen = msgLen + count + 1;
-    result = (xmlChar *) xmlMallocAtomic(resultLen * sizeof(xmlChar));
+    result = (xmlChar *) xmlMallocAtomic(resultLen);
     if (result == NULL) {
         /* Clear *msg to prevent format string vulnerabilities in
            out-of-memory situations. */
         xmlFree(*msg);
         *msg = NULL;
-        xmlErrMemory(NULL, NULL);
         return(NULL);
     }
 
diff --git a/xmlwriter.c b/xmlwriter.c
index 85c19558d9db2a6c19d13f668843c9ca80c8230b..f648dc0520b388addc28d0fdc3b23681b9059f7a 100644
--- a/xmlwriter.c
+++ b/xmlwriter.c
@@ -11,43 +11,32 @@
 #define IN_LIBXML
 #include "libxml.h"
 #include <string.h>
+#include <stdarg.h>
 
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
+#include <libxml/parserInternals.h>
 #include <libxml/uri.h>
 #include <libxml/HTMLtree.h>
+#include <libxml/SAX2.h>
 
 #ifdef LIBXML_WRITER_ENABLED
 
 #include <libxml/xmlwriter.h>
 
-#include "buf.h"
-#include "enc.h"
-#include "save.h"
+#include "private/buf.h"
+#include "private/enc.h"
+#include "private/error.h"
+#include "private/save.h"
 
 #define B64LINELEN 72
 #define B64CRLF "\r\n"
 
-/*
- * The following VA_COPY was coded following an example in
- * the Samba project.  It may not be sufficient for some
- * esoteric implementations of va_list but (hopefully) will
- * be sufficient for libxml2.
- */
-#ifndef VA_COPY
-  #ifdef HAVE_VA_COPY
-    #define VA_COPY(dest, src) va_copy(dest, src)
+#ifndef va_copy
+  #ifdef __va_copy
+    #define va_copy(dest, src) __va_copy(dest, src)
   #else
-    #ifdef HAVE___VA_COPY
-      #define VA_COPY(dest,src) __va_copy(dest, src)
-    #else
-      #ifndef VA_LIST_IS_ARRAY
-        #define VA_COPY(dest,src) (dest) = (src)
-      #else
-        #include <string.h>
-        #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
-      #endif
-    #endif
+    #define va_copy(dest, src) memcpy(dest, src, sizeof(va_list))
   #endif
 #endif
 
@@ -188,7 +177,7 @@ xmlNewTextWriter(xmlOutputBufferPtr out)
                         "xmlNewTextWriter : out of memory!\n");
         return NULL;
     }
-    memset(ret, 0, (size_t) sizeof(xmlTextWriter));
+    memset(ret, 0, sizeof(xmlTextWriter));
 
     ret->nodes = xmlListCreate(xmlFreeTextWriterStackEntry,
                                xmlCmpTextWriterStackEntry);
@@ -708,7 +697,11 @@ xmlTextWriterEndDocument(xmlTextWriterPtr writer)
         sum += count;
     }
 
-    sum += xmlTextWriterFlush(writer);
+    count = xmlTextWriterFlush(writer);
+    if (count < 0)
+        return -1;
+    sum += count;
+
 
     return sum;
 }
@@ -863,7 +856,7 @@ xmlTextWriterEndComment(xmlTextWriterPtr writer)
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
                                 const char *format, ...)
 {
@@ -1291,7 +1284,7 @@ xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
                             ...)
 {
@@ -1417,7 +1410,7 @@ xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
                                ...)
 {
@@ -1503,8 +1496,8 @@ xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
                     break;
                 case XML_TEXTWRITER_ATTRIBUTE:
                     buf = NULL;
-                    xmlBufAttrSerializeTxtContent(writer->out->buffer,
-                                                  writer->doc, NULL, content);
+                    xmlBufAttrSerializeTxtContent(writer->out, writer->doc,
+                                                  content);
                     break;
 		default:
 		    break;
@@ -1963,7 +1956,7 @@ xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
                                   const xmlChar * name, const char *format,
                                   ...)
@@ -2058,7 +2051,7 @@ xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
                                     const xmlChar * prefix,
                                     const xmlChar * name,
@@ -2166,7 +2159,7 @@ xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
                                 const xmlChar * name, const char *format,
                                 ...)
@@ -2263,7 +2256,7 @@ xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
                                   const xmlChar * prefix,
                                   const xmlChar * name,
@@ -2520,7 +2513,7 @@ xmlTextWriterEndPI(xmlTextWriterPtr writer)
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
                            const char *format, ...)
 {
@@ -2735,7 +2728,7 @@ xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
                               ...)
 {
@@ -3044,7 +3037,7 @@ xmlTextWriterEndDTD(xmlTextWriterPtr writer)
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
                             const xmlChar * name,
                             const xmlChar * pubid,
@@ -3288,7 +3281,7 @@ xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
                                    const xmlChar * name,
                                    const char *format, ...)
@@ -3525,7 +3518,7 @@ xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
                                    const xmlChar * name,
                                    const char *format, ...)
@@ -3783,7 +3776,7 @@ xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
  *
  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
  */
-int XMLCDECL
+int
 xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
                                           int pe,
                                           const xmlChar * name,
@@ -4243,6 +4236,35 @@ xmlTextWriterFlush(xmlTextWriterPtr writer)
     return count;
 }
 
+/**
+ * xmlTextWriterClose:
+ * @writer:  the xmlTextWriterPtr
+ *
+ * Flushes and closes the output buffer.
+ *
+ * Available since 2.13.0.
+ *
+ * Returns an xmlParserErrors code.
+ */
+int
+xmlTextWriterClose(xmlTextWriterPtr writer)
+{
+    int result;
+
+    if ((writer == NULL) || (writer->out == NULL))
+        return XML_ERR_ARGUMENT;
+
+    result = xmlOutputBufferClose(writer->out);
+    writer->out = NULL;
+
+    if (result >= 0)
+        result = XML_ERR_OK;
+    else
+        result = -result;
+
+    return result;
+}
+
 /**
  * misc
  */
@@ -4480,7 +4502,7 @@ xmlTextWriterVSprintf(const char *format, va_list argptr)
         return NULL;
     }
 
-    VA_COPY(locarg, argptr);
+    va_copy(locarg, argptr);
     while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
            || (count == size - 1) || (count == size) || (count > size)) {
 	va_end(locarg);
@@ -4492,7 +4514,7 @@ xmlTextWriterVSprintf(const char *format, va_list argptr)
                             "xmlTextWriterVSprintf : out of memory!\n");
             return NULL;
         }
-	VA_COPY(locarg, argptr);
+	va_copy(locarg, argptr);
     }
     va_end(locarg);
 
@@ -4511,28 +4533,17 @@ xmlTextWriterStartDocumentCallback(void *ctx)
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlDocPtr doc;
 
-    if (ctxt->html) {
 #ifdef LIBXML_HTML_ENABLED
+    if (ctxt->html) {
         if (ctxt->myDoc == NULL)
             ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
         if (ctxt->myDoc == NULL) {
-            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-                ctxt->sax->error(ctxt->userData,
-                                 "SAX.startDocument(): out of memory\n");
-            ctxt->errNo = XML_ERR_NO_MEMORY;
-            ctxt->instate = XML_PARSER_EOF;
-            ctxt->disableSAX = 1;
+            xmlCtxtErrMemory(ctxt);
             return;
         }
-#else
-        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
-                        "libxml2 built without HTML support\n");
-        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
-        ctxt->instate = XML_PARSER_EOF;
-        ctxt->disableSAX = 1;
-        return;
+    } else
 #endif
-    } else {
+    {
         doc = ctxt->myDoc;
         if (doc == NULL)
             doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
@@ -4545,12 +4556,7 @@ xmlTextWriterStartDocumentCallback(void *ctx)
                 doc->standalone = ctxt->standalone;
             }
         } else {
-            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-                ctxt->sax->error(ctxt->userData,
-                                 "SAX.startDocument(): out of memory\n");
-            ctxt->errNo = XML_ERR_NO_MEMORY;
-            ctxt->instate = XML_PARSER_EOF;
-            ctxt->disableSAX = 1;
+            xmlCtxtErrMemory(ctxt);
             return;
         }
     }
diff --git a/xpath.c b/xpath.c
index 4a6f0e216e7e823397efaee21be5bbd760ead525..033de6219d8e14135e02bef55ed190e6f3fa633d 100644
--- a/xpath.c
+++ b/xpath.c
@@ -31,7 +31,6 @@
 
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
-#include <libxml/valid.h>
 #include <libxml/xpath.h>
 #include <libxml/xpathInternals.h>
 #include <libxml/parserInternals.h>
@@ -44,21 +43,20 @@
 #endif
 #include <libxml/xmlerror.h>
 #include <libxml/threads.h>
-#include <libxml/globals.h>
 #ifdef LIBXML_PATTERN_ENABLED
 #include <libxml/pattern.h>
 #endif
 
-#include "buf.h"
+#include "private/buf.h"
+#include "private/error.h"
+#include "private/xpath.h"
 
+/* Disabled for now */
+#if 0
 #ifdef LIBXML_PATTERN_ENABLED
 #define XPATH_STREAMING
 #endif
-
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
+#endif
 
 /**
  * WITH_TIM_SORT:
@@ -87,13 +85,6 @@
 */
 #define XP_OPTIMIZED_FILTER_FIRST
 
-/*
-* XP_DEBUG_OBJ_USAGE:
-* Internal flag to enable tracking of how much XPath objects have been
-* created.
-*/
-/* #define XP_DEBUG_OBJ_USAGE */
-
 /*
  * XPATH_MAX_STEPS:
  * when compiling an XPath expression we arbitrary limit the maximum
@@ -129,6 +120,9 @@
  */
 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 #define XPATH_MAX_RECURSION_DEPTH 500
+#elif defined(_WIN32)
+/* Windows typically limits stack size to 1MB. */
+#define XPATH_MAX_RECURSION_DEPTH 1000
 #else
 #define XPATH_MAX_RECURSION_DEPTH 5000
 #endif
@@ -140,6 +134,116 @@
  * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
  */
 
+#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
+
+/************************************************************************
+ *									*
+ *			Floating point stuff				*
+ *									*
+ ************************************************************************/
+
+double xmlXPathNAN = 0.0;
+double xmlXPathPINF = 0.0;
+double xmlXPathNINF = 0.0;
+
+/**
+ * xmlXPathInit:
+ *
+ * DEPRECATED: Alias for xmlInitParser.
+ */
+void
+xmlXPathInit(void) {
+    xmlInitParser();
+}
+
+/**
+ * xmlInitXPathInternal:
+ *
+ * Initialize the XPath environment
+ */
+ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
+void
+xmlInitXPathInternal(void) {
+#if defined(NAN) && defined(INFINITY)
+    xmlXPathNAN = NAN;
+    xmlXPathPINF = INFINITY;
+    xmlXPathNINF = -INFINITY;
+#else
+    /* MSVC doesn't allow division by zero in constant expressions. */
+    double zero = 0.0;
+    xmlXPathNAN = 0.0 / zero;
+    xmlXPathPINF = 1.0 / zero;
+    xmlXPathNINF = -xmlXPathPINF;
+#endif
+}
+
+/**
+ * xmlXPathIsNaN:
+ * @val:  a double value
+ *
+ * Checks whether a double is a NaN.
+ *
+ * Returns 1 if the value is a NaN, 0 otherwise
+ */
+int
+xmlXPathIsNaN(double val) {
+#ifdef isnan
+    return isnan(val);
+#else
+    return !(val == val);
+#endif
+}
+
+/**
+ * xmlXPathIsInf:
+ * @val:  a double value
+ *
+ * Checks whether a double is an infinity.
+ *
+ * Returns 1 if the value is +Infinite, -1 if -Infinite, 0 otherwise
+ */
+int
+xmlXPathIsInf(double val) {
+#ifdef isinf
+    return isinf(val) ? (val > 0 ? 1 : -1) : 0;
+#else
+    if (val >= xmlXPathPINF)
+        return 1;
+    if (val <= -xmlXPathPINF)
+        return -1;
+    return 0;
+#endif
+}
+
+#endif /* SCHEMAS or XPATH */
+
+#ifdef LIBXML_XPATH_ENABLED
+
+/*
+ * TODO: when compatibility allows remove all "fake node libxslt" strings
+ *       the test should just be name[0] = ' '
+ */
+
+static const xmlNs xmlXPathXMLNamespaceStruct = {
+    NULL,
+    XML_NAMESPACE_DECL,
+    XML_XML_NAMESPACE,
+    BAD_CAST "xml",
+    NULL,
+    NULL
+};
+static const xmlNs *const xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct;
+#ifndef LIBXML_THREAD_ENABLED
+/*
+ * Optimizer is disabled only when threaded apps are detected while
+ * the library ain't compiled for thread safety.
+ */
+static int xmlXPathDisableOptimizer = 0;
+#endif
+
+static void
+xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes);
+
 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
 /**
  * xmlXPathCmpNodesExt:
@@ -467,107 +571,6 @@ int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
 #include "timsort.h"
 #endif /* WITH_TIM_SORT */
 
-#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
-
-/************************************************************************
- *									*
- *			Floating point stuff				*
- *									*
- ************************************************************************/
-
-double xmlXPathNAN = 0.0;
-double xmlXPathPINF = 0.0;
-double xmlXPathNINF = 0.0;
-
-/**
- * xmlXPathInit:
- *
- * DEPRECATED: This function will be made private. Call xmlInitParser to
- * initialize the library.
- *
- * Initialize the XPath environment
- */
-ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
-void
-xmlXPathInit(void) {
-#if defined(NAN) && defined(INFINITY)
-    xmlXPathNAN = NAN;
-    xmlXPathPINF = INFINITY;
-    xmlXPathNINF = -INFINITY;
-#else
-    /* MSVC doesn't allow division by zero in constant expressions. */
-    double zero = 0.0;
-    xmlXPathNAN = 0.0 / zero;
-    xmlXPathPINF = 1.0 / zero;
-    xmlXPathNINF = -xmlXPathPINF;
-#endif
-}
-
-/**
- * xmlXPathIsNaN:
- * @val:  a double value
- *
- * Returns 1 if the value is a NaN, 0 otherwise
- */
-int
-xmlXPathIsNaN(double val) {
-#ifdef isnan
-    return isnan(val);
-#else
-    return !(val == val);
-#endif
-}
-
-/**
- * xmlXPathIsInf:
- * @val:  a double value
- *
- * Returns 1 if the value is +Infinite, -1 if -Infinite, 0 otherwise
- */
-int
-xmlXPathIsInf(double val) {
-#ifdef isinf
-    return isinf(val) ? (val > 0 ? 1 : -1) : 0;
-#else
-    if (val >= xmlXPathPINF)
-        return 1;
-    if (val <= -xmlXPathPINF)
-        return -1;
-    return 0;
-#endif
-}
-
-#endif /* SCHEMAS or XPATH */
-
-#ifdef LIBXML_XPATH_ENABLED
-
-/*
- * TODO: when compatibility allows remove all "fake node libxslt" strings
- *       the test should just be name[0] = ' '
- */
-#ifdef DEBUG_XPATH_EXPRESSION
-#define DEBUG_STEP
-#define DEBUG_EXPR
-#define DEBUG_EVAL_COUNTS
-#endif
-
-static xmlNs xmlXPathXMLNamespaceStruct = {
-    NULL,
-    XML_NAMESPACE_DECL,
-    XML_XML_NAMESPACE,
-    BAD_CAST "xml",
-    NULL,
-    NULL
-};
-static xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct;
-#ifndef LIBXML_THREAD_ENABLED
-/*
- * Optimizer is disabled only when threaded apps are detected while
- * the library ain't compiled for thread safety.
- */
-static int xmlXPathDisableOptimizer = 0;
-#endif
-
 /************************************************************************
  *									*
  *			Error handling routines				*
@@ -621,120 +624,100 @@ static const char* const xmlXPathErrorMessages[] = {
 /**
  * xmlXPathErrMemory:
  * @ctxt:  an XPath context
- * @extra:  extra information
  *
- * Handle a redefinition of attribute error
+ * Handle a memory allocation failure.
  */
-static void
-xmlXPathErrMemory(xmlXPathContextPtr ctxt, const char *extra)
+void
+xmlXPathErrMemory(xmlXPathContextPtr ctxt)
 {
-    if (ctxt != NULL) {
-        xmlResetError(&ctxt->lastError);
-        if (extra) {
-            xmlChar buf[200];
-
-            xmlStrPrintf(buf, 200,
-                         "Memory allocation failed : %s\n",
-                         extra);
-            ctxt->lastError.message = (char *) xmlStrdup(buf);
-        } else {
-            ctxt->lastError.message = (char *)
-	       xmlStrdup(BAD_CAST "Memory allocation failed\n");
-        }
-        ctxt->lastError.domain = XML_FROM_XPATH;
-        ctxt->lastError.code = XML_ERR_NO_MEMORY;
-	if (ctxt->error != NULL)
-	    ctxt->error(ctxt->userData, &ctxt->lastError);
-    } else {
-        if (extra)
-            __xmlRaiseError(NULL, NULL, NULL,
-                            NULL, NULL, XML_FROM_XPATH,
-                            XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
-                            extra, NULL, NULL, 0, 0,
-                            "Memory allocation failed : %s\n", extra);
-        else
-            __xmlRaiseError(NULL, NULL, NULL,
-                            NULL, NULL, XML_FROM_XPATH,
-                            XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
-                            NULL, NULL, NULL, 0, 0,
-                            "Memory allocation failed\n");
-    }
+    if (ctxt == NULL)
+        return;
+    xmlRaiseMemoryError(ctxt->error, NULL, ctxt->userData, XML_FROM_XPATH,
+                        &ctxt->lastError);
 }
 
 /**
  * xmlXPathPErrMemory:
  * @ctxt:  an XPath parser context
- * @extra:  extra information
  *
- * Handle a redefinition of attribute error
+ * Handle a memory allocation failure.
  */
-static void
-xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt, const char *extra)
+void
+xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt)
 {
     if (ctxt == NULL)
-	xmlXPathErrMemory(NULL, extra);
-    else {
-	ctxt->error = XPATH_MEMORY_ERROR;
-	xmlXPathErrMemory(ctxt->context, extra);
-    }
+        return;
+    ctxt->error = XPATH_MEMORY_ERROR;
+    xmlXPathErrMemory(ctxt->context);
 }
 
 /**
  * xmlXPathErr:
  * @ctxt:  a XPath parser context
- * @error:  the error code
+ * @code:  the error code
  *
  * Handle an XPath error
  */
 void
-xmlXPathErr(xmlXPathParserContextPtr ctxt, int error)
+xmlXPathErr(xmlXPathParserContextPtr ctxt, int code)
 {
-    if ((error < 0) || (error > MAXERRNO))
-	error = MAXERRNO;
-    if (ctxt == NULL) {
-	__xmlRaiseError(NULL, NULL, NULL,
-			NULL, NULL, XML_FROM_XPATH,
-			error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
-			XML_ERR_ERROR, NULL, 0,
-			NULL, NULL, NULL, 0, 0,
-			"%s", xmlXPathErrorMessages[error]);
-	return;
-    }
-    ctxt->error = error;
-    if (ctxt->context == NULL) {
-	__xmlRaiseError(NULL, NULL, NULL,
-			NULL, NULL, XML_FROM_XPATH,
-			error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
-			XML_ERR_ERROR, NULL, 0,
-			(const char *) ctxt->base, NULL, NULL,
-			ctxt->cur - ctxt->base, 0,
-			"%s", xmlXPathErrorMessages[error]);
-	return;
-    }
+    xmlStructuredErrorFunc schannel = NULL;
+    xmlGenericErrorFunc channel = NULL;
+    void *data = NULL;
+    xmlNodePtr node = NULL;
+    int res;
+
+    if (ctxt == NULL)
+        return;
+    if ((code < 0) || (code > MAXERRNO))
+	code = MAXERRNO;
+    /* Only report the first error */
+    if (ctxt->error != 0)
+        return;
 
-    /* cleanup current last error */
-    xmlResetError(&ctxt->context->lastError);
+    ctxt->error = code;
 
-    ctxt->context->lastError.domain = XML_FROM_XPATH;
-    ctxt->context->lastError.code = error + XML_XPATH_EXPRESSION_OK -
-                           XPATH_EXPRESSION_OK;
-    ctxt->context->lastError.level = XML_ERR_ERROR;
-    ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base);
-    ctxt->context->lastError.int1 = ctxt->cur - ctxt->base;
-    ctxt->context->lastError.node = ctxt->context->debugNode;
-    if (ctxt->context->error != NULL) {
-	ctxt->context->error(ctxt->context->userData,
-	                     &ctxt->context->lastError);
-    } else {
-	__xmlRaiseError(NULL, NULL, NULL,
-			NULL, ctxt->context->debugNode, XML_FROM_XPATH,
-			error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
-			XML_ERR_ERROR, NULL, 0,
-			(const char *) ctxt->base, NULL, NULL,
-			ctxt->cur - ctxt->base, 0,
-			"%s", xmlXPathErrorMessages[error]);
+    if (ctxt->context != NULL) {
+        xmlErrorPtr err = &ctxt->context->lastError;
+
+        /* Don't overwrite memory error. */
+        if (err->code == XML_ERR_NO_MEMORY)
+            return;
+
+        /* cleanup current last error */
+        xmlResetError(err);
+
+        err->domain = XML_FROM_XPATH;
+        err->code = code + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK;
+        err->level = XML_ERR_ERROR;
+        if (ctxt->base != NULL) {
+            err->str1 = (char *) xmlStrdup(ctxt->base);
+            if (err->str1 == NULL) {
+                xmlXPathPErrMemory(ctxt);
+                return;
+            }
+        }
+        err->int1 = ctxt->cur - ctxt->base;
+        err->node = ctxt->context->debugNode;
+
+        schannel = ctxt->context->error;
+        data = ctxt->context->userData;
+        node = ctxt->context->debugNode;
+    }
+
+    if (schannel == NULL) {
+        channel = xmlGenericError;
+        data = xmlGenericErrorContext;
     }
 
+    res = __xmlRaiseError(schannel, channel, data, NULL, node, XML_FROM_XPATH,
+                          code + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
+                          XML_ERR_ERROR, NULL, 0,
+                          (const char *) ctxt->base, NULL, NULL,
+                          ctxt->cur - ctxt->base, 0,
+                          "%s", xmlXPathErrorMessages[code]);
+    if (res < 0)
+        xmlXPathPErrMemory(ctxt);
 }
 
 /**
@@ -780,113 +763,13 @@ xmlXPathCheckOpLimit(xmlXPathParserContextPtr ctxt, unsigned long opCount) {
 
 /************************************************************************
  *									*
- *			Utilities					*
+ *			Parser Types					*
  *									*
  ************************************************************************/
 
-/**
- * xsltPointerList:
- *
- * Pointer-list for various purposes.
- */
-typedef struct _xmlPointerList xmlPointerList;
-typedef xmlPointerList *xmlPointerListPtr;
-struct _xmlPointerList {
-    void **items;
-    int number;
-    int size;
-};
 /*
-* TODO: Since such a list-handling is used in xmlschemas.c and libxslt
-* and here, we should make the functions public.
-*/
-static int
-xmlPointerListAddSize(xmlPointerListPtr list,
-		       void *item,
-		       int initialSize)
-{
-    if (list->items == NULL) {
-	if (initialSize <= 0)
-	    initialSize = 1;
-	list->items = (void **) xmlMalloc(initialSize * sizeof(void *));
-	if (list->items == NULL) {
-	    xmlXPathErrMemory(NULL,
-		"xmlPointerListCreate: allocating item\n");
-	    return(-1);
-	}
-	list->number = 0;
-	list->size = initialSize;
-    } else if (list->size <= list->number) {
-        if (list->size > 50000000) {
-	    xmlXPathErrMemory(NULL,
-		"xmlPointerListAddSize: re-allocating item\n");
-            return(-1);
-        }
-	list->size *= 2;
-	list->items = (void **) xmlRealloc(list->items,
-	    list->size * sizeof(void *));
-	if (list->items == NULL) {
-	    xmlXPathErrMemory(NULL,
-		"xmlPointerListAddSize: re-allocating item\n");
-	    list->size = 0;
-	    return(-1);
-	}
-    }
-    list->items[list->number++] = item;
-    return(0);
-}
-
-/**
- * xsltPointerListCreate:
- *
- * Creates an xsltPointerList structure.
- *
- * Returns a xsltPointerList structure or NULL in case of an error.
- */
-static xmlPointerListPtr
-xmlPointerListCreate(int initialSize)
-{
-    xmlPointerListPtr ret;
-
-    ret = xmlMalloc(sizeof(xmlPointerList));
-    if (ret == NULL) {
-	xmlXPathErrMemory(NULL,
-	    "xmlPointerListCreate: allocating item\n");
-	return (NULL);
-    }
-    memset(ret, 0, sizeof(xmlPointerList));
-    if (initialSize > 0) {
-	xmlPointerListAddSize(ret, NULL, initialSize);
-	ret->number = 0;
-    }
-    return (ret);
-}
-
-/**
- * xsltPointerListFree:
- *
- * Frees the xsltPointerList structure. This does not free
- * the content of the list.
- */
-static void
-xmlPointerListFree(xmlPointerListPtr list)
-{
-    if (list == NULL)
-	return;
-    if (list->items != NULL)
-	xmlFree(list->items);
-    xmlFree(list);
-}
-
-/************************************************************************
- *									*
- *			Parser Types					*
- *									*
- ************************************************************************/
-
-/*
- * Types are private:
- */
+ * Types are private:
+ */
 
 typedef enum {
     XPATH_OP_END=0,
@@ -966,10 +849,6 @@ struct _xmlXPathCompExpr {
     int last;			/* index of last step in expression */
     xmlChar *expr;		/* the expression being computed */
     xmlDictPtr dict;		/* the dictionary to use if any */
-#ifdef DEBUG_EVAL_COUNTS
-    int nb;
-    xmlChar *string;
-#endif
 #ifdef XPATH_STREAMING
     xmlPatternPtr stream;
 #endif
@@ -980,8 +859,7 @@ struct _xmlXPathCompExpr {
  *			Forward declarations				*
  *									*
  ************************************************************************/
-static void
-xmlXPathFreeValueTree(xmlNodeSetPtr obj);
+
 static void
 xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj);
 static int
@@ -1012,25 +890,19 @@ xmlXPathNewCompExpr(void) {
     xmlXPathCompExprPtr cur;
 
     cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr));
-    if (cur == NULL) {
-        xmlXPathErrMemory(NULL, "allocating component\n");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlXPathCompExpr));
     cur->maxStep = 10;
     cur->nbStep = 0;
     cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep *
 	                                   sizeof(xmlXPathStepOp));
     if (cur->steps == NULL) {
-        xmlXPathErrMemory(NULL, "allocating steps\n");
 	xmlFree(cur);
 	return(NULL);
     }
     memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp));
     cur->last = -1;
-#ifdef DEBUG_EVAL_COUNTS
-    cur->nb = 0;
-#endif
     return(cur);
 }
 
@@ -1073,11 +945,6 @@ xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
     if (comp->steps != NULL) {
         xmlFree(comp->steps);
     }
-#ifdef DEBUG_EVAL_COUNTS
-    if (comp->string != NULL) {
-        xmlFree(comp->string);
-    }
-#endif
 #ifdef XPATH_STREAMING
     if (comp->stream != NULL) {
         xmlFreePatternList(comp->stream);
@@ -1115,7 +982,7 @@ xmlXPathCompExprAdd(xmlXPathParserContextPtr ctxt, int ch1, int ch2,
 	xmlXPathStepOp *real;
 
         if (comp->maxStep >= XPATH_MAX_STEPS) {
-	    xmlXPathPErrMemory(ctxt, "adding step\n");
+	    xmlXPathPErrMemory(ctxt);
 	    return(-1);
         }
 	comp->maxStep *= 2;
@@ -1123,7 +990,7 @@ xmlXPathCompExprAdd(xmlXPathParserContextPtr ctxt, int ch1, int ch2,
 		                      comp->maxStep * sizeof(xmlXPathStepOp));
 	if (real == NULL) {
 	    comp->maxStep /= 2;
-	    xmlXPathPErrMemory(ctxt, "adding step\n");
+	    xmlXPathPErrMemory(ctxt);
 	    return(-1);
 	}
 	comp->steps = real;
@@ -1209,48 +1076,15 @@ xmlXPathCompExprAdd(ctxt, (ch1), (ch2), (op),			\
 
 /* #define XP_DEFAULT_CACHE_ON */
 
-#define XP_HAS_CACHE(c) ((c != NULL) && ((c)->cache != NULL))
-
 typedef struct _xmlXPathContextCache xmlXPathContextCache;
 typedef xmlXPathContextCache *xmlXPathContextCachePtr;
 struct _xmlXPathContextCache {
-    xmlPointerListPtr nodesetObjs;  /* contains xmlXPathObjectPtr */
-    xmlPointerListPtr stringObjs;   /* contains xmlXPathObjectPtr */
-    xmlPointerListPtr booleanObjs;  /* contains xmlXPathObjectPtr */
-    xmlPointerListPtr numberObjs;   /* contains xmlXPathObjectPtr */
-    xmlPointerListPtr miscObjs;     /* contains xmlXPathObjectPtr */
+    xmlXPathObjectPtr nodesetObjs;  /* stringval points to next */
+    xmlXPathObjectPtr miscObjs;     /* stringval points to next */
+    int numNodeset;
     int maxNodeset;
-    int maxString;
-    int maxBoolean;
-    int maxNumber;
+    int numMisc;
     int maxMisc;
-#ifdef XP_DEBUG_OBJ_USAGE
-    int dbgCachedAll;
-    int dbgCachedNodeset;
-    int dbgCachedString;
-    int dbgCachedBool;
-    int dbgCachedNumber;
-    int dbgCachedPoint;
-    int dbgCachedRange;
-    int dbgCachedLocset;
-    int dbgCachedUsers;
-    int dbgCachedXSLTTree;
-    int dbgCachedUndefined;
-
-
-    int dbgReusedAll;
-    int dbgReusedNodeset;
-    int dbgReusedString;
-    int dbgReusedBool;
-    int dbgReusedNumber;
-    int dbgReusedPoint;
-    int dbgReusedRange;
-    int dbgReusedLocset;
-    int dbgReusedUsers;
-    int dbgReusedXSLTTree;
-    int dbgReusedUndefined;
-
-#endif
 };
 
 /************************************************************************
@@ -1259,11 +1093,6 @@ struct _xmlXPathContextCache {
  *									*
  ************************************************************************/
 
-#define STRANGE							\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Internal error at %s:%d\n",				\
-            __FILE__, __LINE__);
-
 #ifdef LIBXML_DEBUG_ENABLED
 static void
 xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
@@ -1707,478 +1536,6 @@ xmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp,
     }
 }
 
-#ifdef XP_DEBUG_OBJ_USAGE
-
-/*
-* XPath object usage related debugging variables.
-*/
-static int xmlXPathDebugObjCounterUndefined = 0;
-static int xmlXPathDebugObjCounterNodeset = 0;
-static int xmlXPathDebugObjCounterBool = 0;
-static int xmlXPathDebugObjCounterNumber = 0;
-static int xmlXPathDebugObjCounterString = 0;
-static int xmlXPathDebugObjCounterPoint = 0;
-static int xmlXPathDebugObjCounterRange = 0;
-static int xmlXPathDebugObjCounterLocset = 0;
-static int xmlXPathDebugObjCounterUsers = 0;
-static int xmlXPathDebugObjCounterXSLTTree = 0;
-static int xmlXPathDebugObjCounterAll = 0;
-
-static int xmlXPathDebugObjTotalUndefined = 0;
-static int xmlXPathDebugObjTotalNodeset = 0;
-static int xmlXPathDebugObjTotalBool = 0;
-static int xmlXPathDebugObjTotalNumber = 0;
-static int xmlXPathDebugObjTotalString = 0;
-static int xmlXPathDebugObjTotalPoint = 0;
-static int xmlXPathDebugObjTotalRange = 0;
-static int xmlXPathDebugObjTotalLocset = 0;
-static int xmlXPathDebugObjTotalUsers = 0;
-static int xmlXPathDebugObjTotalXSLTTree = 0;
-static int xmlXPathDebugObjTotalAll = 0;
-
-static int xmlXPathDebugObjMaxUndefined = 0;
-static int xmlXPathDebugObjMaxNodeset = 0;
-static int xmlXPathDebugObjMaxBool = 0;
-static int xmlXPathDebugObjMaxNumber = 0;
-static int xmlXPathDebugObjMaxString = 0;
-static int xmlXPathDebugObjMaxPoint = 0;
-static int xmlXPathDebugObjMaxRange = 0;
-static int xmlXPathDebugObjMaxLocset = 0;
-static int xmlXPathDebugObjMaxUsers = 0;
-static int xmlXPathDebugObjMaxXSLTTree = 0;
-static int xmlXPathDebugObjMaxAll = 0;
-
-static void
-xmlXPathDebugObjUsageReset(xmlXPathContextPtr ctxt)
-{
-    if (ctxt != NULL) {
-	if (ctxt->cache != NULL) {
-	    xmlXPathContextCachePtr cache =
-		(xmlXPathContextCachePtr) ctxt->cache;
-
-	    cache->dbgCachedAll = 0;
-	    cache->dbgCachedNodeset = 0;
-	    cache->dbgCachedString = 0;
-	    cache->dbgCachedBool = 0;
-	    cache->dbgCachedNumber = 0;
-	    cache->dbgCachedPoint = 0;
-	    cache->dbgCachedRange = 0;
-	    cache->dbgCachedLocset = 0;
-	    cache->dbgCachedUsers = 0;
-	    cache->dbgCachedXSLTTree = 0;
-	    cache->dbgCachedUndefined = 0;
-
-	    cache->dbgReusedAll = 0;
-	    cache->dbgReusedNodeset = 0;
-	    cache->dbgReusedString = 0;
-	    cache->dbgReusedBool = 0;
-	    cache->dbgReusedNumber = 0;
-	    cache->dbgReusedPoint = 0;
-	    cache->dbgReusedRange = 0;
-	    cache->dbgReusedLocset = 0;
-	    cache->dbgReusedUsers = 0;
-	    cache->dbgReusedXSLTTree = 0;
-	    cache->dbgReusedUndefined = 0;
-	}
-    }
-
-    xmlXPathDebugObjCounterUndefined = 0;
-    xmlXPathDebugObjCounterNodeset = 0;
-    xmlXPathDebugObjCounterBool = 0;
-    xmlXPathDebugObjCounterNumber = 0;
-    xmlXPathDebugObjCounterString = 0;
-    xmlXPathDebugObjCounterPoint = 0;
-    xmlXPathDebugObjCounterRange = 0;
-    xmlXPathDebugObjCounterLocset = 0;
-    xmlXPathDebugObjCounterUsers = 0;
-    xmlXPathDebugObjCounterXSLTTree = 0;
-    xmlXPathDebugObjCounterAll = 0;
-
-    xmlXPathDebugObjTotalUndefined = 0;
-    xmlXPathDebugObjTotalNodeset = 0;
-    xmlXPathDebugObjTotalBool = 0;
-    xmlXPathDebugObjTotalNumber = 0;
-    xmlXPathDebugObjTotalString = 0;
-    xmlXPathDebugObjTotalPoint = 0;
-    xmlXPathDebugObjTotalRange = 0;
-    xmlXPathDebugObjTotalLocset = 0;
-    xmlXPathDebugObjTotalUsers = 0;
-    xmlXPathDebugObjTotalXSLTTree = 0;
-    xmlXPathDebugObjTotalAll = 0;
-
-    xmlXPathDebugObjMaxUndefined = 0;
-    xmlXPathDebugObjMaxNodeset = 0;
-    xmlXPathDebugObjMaxBool = 0;
-    xmlXPathDebugObjMaxNumber = 0;
-    xmlXPathDebugObjMaxString = 0;
-    xmlXPathDebugObjMaxPoint = 0;
-    xmlXPathDebugObjMaxRange = 0;
-    xmlXPathDebugObjMaxLocset = 0;
-    xmlXPathDebugObjMaxUsers = 0;
-    xmlXPathDebugObjMaxXSLTTree = 0;
-    xmlXPathDebugObjMaxAll = 0;
-
-}
-
-static void
-xmlXPathDebugObjUsageRequested(xmlXPathContextPtr ctxt,
-			      xmlXPathObjectType objType)
-{
-    int isCached = 0;
-
-    if (ctxt != NULL) {
-	if (ctxt->cache != NULL) {
-	    xmlXPathContextCachePtr cache =
-		(xmlXPathContextCachePtr) ctxt->cache;
-
-	    isCached = 1;
-
-	    cache->dbgReusedAll++;
-	    switch (objType) {
-		case XPATH_UNDEFINED:
-		    cache->dbgReusedUndefined++;
-		    break;
-		case XPATH_NODESET:
-		    cache->dbgReusedNodeset++;
-		    break;
-		case XPATH_BOOLEAN:
-		    cache->dbgReusedBool++;
-		    break;
-		case XPATH_NUMBER:
-		    cache->dbgReusedNumber++;
-		    break;
-		case XPATH_STRING:
-		    cache->dbgReusedString++;
-		    break;
-#ifdef LIBXML_XPTR_LOCS_ENABLED
-		case XPATH_POINT:
-		    cache->dbgReusedPoint++;
-		    break;
-		case XPATH_RANGE:
-		    cache->dbgReusedRange++;
-		    break;
-		case XPATH_LOCATIONSET:
-		    cache->dbgReusedLocset++;
-		    break;
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
-		case XPATH_USERS:
-		    cache->dbgReusedUsers++;
-		    break;
-		case XPATH_XSLT_TREE:
-		    cache->dbgReusedXSLTTree++;
-		    break;
-		default:
-		    break;
-	    }
-	}
-    }
-
-    switch (objType) {
-	case XPATH_UNDEFINED:
-	    if (! isCached)
-		xmlXPathDebugObjTotalUndefined++;
-	    xmlXPathDebugObjCounterUndefined++;
-	    if (xmlXPathDebugObjCounterUndefined >
-		xmlXPathDebugObjMaxUndefined)
-		xmlXPathDebugObjMaxUndefined =
-		    xmlXPathDebugObjCounterUndefined;
-	    break;
-	case XPATH_NODESET:
-	    if (! isCached)
-		xmlXPathDebugObjTotalNodeset++;
-	    xmlXPathDebugObjCounterNodeset++;
-	    if (xmlXPathDebugObjCounterNodeset >
-		xmlXPathDebugObjMaxNodeset)
-		xmlXPathDebugObjMaxNodeset =
-		    xmlXPathDebugObjCounterNodeset;
-	    break;
-	case XPATH_BOOLEAN:
-	    if (! isCached)
-		xmlXPathDebugObjTotalBool++;
-	    xmlXPathDebugObjCounterBool++;
-	    if (xmlXPathDebugObjCounterBool >
-		xmlXPathDebugObjMaxBool)
-		xmlXPathDebugObjMaxBool =
-		    xmlXPathDebugObjCounterBool;
-	    break;
-	case XPATH_NUMBER:
-	    if (! isCached)
-		xmlXPathDebugObjTotalNumber++;
-	    xmlXPathDebugObjCounterNumber++;
-	    if (xmlXPathDebugObjCounterNumber >
-		xmlXPathDebugObjMaxNumber)
-		xmlXPathDebugObjMaxNumber =
-		    xmlXPathDebugObjCounterNumber;
-	    break;
-	case XPATH_STRING:
-	    if (! isCached)
-		xmlXPathDebugObjTotalString++;
-	    xmlXPathDebugObjCounterString++;
-	    if (xmlXPathDebugObjCounterString >
-		xmlXPathDebugObjMaxString)
-		xmlXPathDebugObjMaxString =
-		    xmlXPathDebugObjCounterString;
-	    break;
-#ifdef LIBXML_XPTR_LOCS_ENABLED
-	case XPATH_POINT:
-	    if (! isCached)
-		xmlXPathDebugObjTotalPoint++;
-	    xmlXPathDebugObjCounterPoint++;
-	    if (xmlXPathDebugObjCounterPoint >
-		xmlXPathDebugObjMaxPoint)
-		xmlXPathDebugObjMaxPoint =
-		    xmlXPathDebugObjCounterPoint;
-	    break;
-	case XPATH_RANGE:
-	    if (! isCached)
-		xmlXPathDebugObjTotalRange++;
-	    xmlXPathDebugObjCounterRange++;
-	    if (xmlXPathDebugObjCounterRange >
-		xmlXPathDebugObjMaxRange)
-		xmlXPathDebugObjMaxRange =
-		    xmlXPathDebugObjCounterRange;
-	    break;
-	case XPATH_LOCATIONSET:
-	    if (! isCached)
-		xmlXPathDebugObjTotalLocset++;
-	    xmlXPathDebugObjCounterLocset++;
-	    if (xmlXPathDebugObjCounterLocset >
-		xmlXPathDebugObjMaxLocset)
-		xmlXPathDebugObjMaxLocset =
-		    xmlXPathDebugObjCounterLocset;
-	    break;
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
-	case XPATH_USERS:
-	    if (! isCached)
-		xmlXPathDebugObjTotalUsers++;
-	    xmlXPathDebugObjCounterUsers++;
-	    if (xmlXPathDebugObjCounterUsers >
-		xmlXPathDebugObjMaxUsers)
-		xmlXPathDebugObjMaxUsers =
-		    xmlXPathDebugObjCounterUsers;
-	    break;
-	case XPATH_XSLT_TREE:
-	    if (! isCached)
-		xmlXPathDebugObjTotalXSLTTree++;
-	    xmlXPathDebugObjCounterXSLTTree++;
-	    if (xmlXPathDebugObjCounterXSLTTree >
-		xmlXPathDebugObjMaxXSLTTree)
-		xmlXPathDebugObjMaxXSLTTree =
-		    xmlXPathDebugObjCounterXSLTTree;
-	    break;
-	default:
-	    break;
-    }
-    if (! isCached)
-	xmlXPathDebugObjTotalAll++;
-    xmlXPathDebugObjCounterAll++;
-    if (xmlXPathDebugObjCounterAll >
-	xmlXPathDebugObjMaxAll)
-	xmlXPathDebugObjMaxAll =
-	    xmlXPathDebugObjCounterAll;
-}
-
-static void
-xmlXPathDebugObjUsageReleased(xmlXPathContextPtr ctxt,
-			      xmlXPathObjectType objType)
-{
-    int isCached = 0;
-
-    if (ctxt != NULL) {
-	if (ctxt->cache != NULL) {
-	    xmlXPathContextCachePtr cache =
-		(xmlXPathContextCachePtr) ctxt->cache;
-
-	    isCached = 1;
-
-	    cache->dbgCachedAll++;
-	    switch (objType) {
-		case XPATH_UNDEFINED:
-		    cache->dbgCachedUndefined++;
-		    break;
-		case XPATH_NODESET:
-		    cache->dbgCachedNodeset++;
-		    break;
-		case XPATH_BOOLEAN:
-		    cache->dbgCachedBool++;
-		    break;
-		case XPATH_NUMBER:
-		    cache->dbgCachedNumber++;
-		    break;
-		case XPATH_STRING:
-		    cache->dbgCachedString++;
-		    break;
-#ifdef LIBXML_XPTR_LOCS_ENABLED
-		case XPATH_POINT:
-		    cache->dbgCachedPoint++;
-		    break;
-		case XPATH_RANGE:
-		    cache->dbgCachedRange++;
-		    break;
-		case XPATH_LOCATIONSET:
-		    cache->dbgCachedLocset++;
-		    break;
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
-		case XPATH_USERS:
-		    cache->dbgCachedUsers++;
-		    break;
-		case XPATH_XSLT_TREE:
-		    cache->dbgCachedXSLTTree++;
-		    break;
-		default:
-		    break;
-	    }
-
-	}
-    }
-    switch (objType) {
-	case XPATH_UNDEFINED:
-	    xmlXPathDebugObjCounterUndefined--;
-	    break;
-	case XPATH_NODESET:
-	    xmlXPathDebugObjCounterNodeset--;
-	    break;
-	case XPATH_BOOLEAN:
-	    xmlXPathDebugObjCounterBool--;
-	    break;
-	case XPATH_NUMBER:
-	    xmlXPathDebugObjCounterNumber--;
-	    break;
-	case XPATH_STRING:
-	    xmlXPathDebugObjCounterString--;
-	    break;
-#ifdef LIBXML_XPTR_LOCS_ENABLED
-	case XPATH_POINT:
-	    xmlXPathDebugObjCounterPoint--;
-	    break;
-	case XPATH_RANGE:
-	    xmlXPathDebugObjCounterRange--;
-	    break;
-	case XPATH_LOCATIONSET:
-	    xmlXPathDebugObjCounterLocset--;
-	    break;
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
-	case XPATH_USERS:
-	    xmlXPathDebugObjCounterUsers--;
-	    break;
-	case XPATH_XSLT_TREE:
-	    xmlXPathDebugObjCounterXSLTTree--;
-	    break;
-	default:
-	    break;
-    }
-    xmlXPathDebugObjCounterAll--;
-}
-
-static void
-xmlXPathDebugObjUsageDisplay(xmlXPathContextPtr ctxt)
-{
-    int reqAll, reqNodeset, reqString, reqBool, reqNumber,
-	reqXSLTTree, reqUndefined;
-    int caAll = 0, caNodeset = 0, caString = 0, caBool = 0,
-	caNumber = 0, caXSLTTree = 0, caUndefined = 0;
-    int reAll = 0, reNodeset = 0, reString = 0, reBool = 0,
-	reNumber = 0, reXSLTTree = 0, reUndefined = 0;
-    int leftObjs = xmlXPathDebugObjCounterAll;
-
-    reqAll = xmlXPathDebugObjTotalAll;
-    reqNodeset = xmlXPathDebugObjTotalNodeset;
-    reqString = xmlXPathDebugObjTotalString;
-    reqBool = xmlXPathDebugObjTotalBool;
-    reqNumber = xmlXPathDebugObjTotalNumber;
-    reqXSLTTree = xmlXPathDebugObjTotalXSLTTree;
-    reqUndefined = xmlXPathDebugObjTotalUndefined;
-
-    printf("# XPath object usage:\n");
-
-    if (ctxt != NULL) {
-	if (ctxt->cache != NULL) {
-	    xmlXPathContextCachePtr cache =
-		(xmlXPathContextCachePtr) ctxt->cache;
-
-	    reAll = cache->dbgReusedAll;
-	    reqAll += reAll;
-	    reNodeset = cache->dbgReusedNodeset;
-	    reqNodeset += reNodeset;
-	    reString = cache->dbgReusedString;
-	    reqString += reString;
-	    reBool = cache->dbgReusedBool;
-	    reqBool += reBool;
-	    reNumber = cache->dbgReusedNumber;
-	    reqNumber += reNumber;
-	    reXSLTTree = cache->dbgReusedXSLTTree;
-	    reqXSLTTree += reXSLTTree;
-	    reUndefined = cache->dbgReusedUndefined;
-	    reqUndefined += reUndefined;
-
-	    caAll = cache->dbgCachedAll;
-	    caBool = cache->dbgCachedBool;
-	    caNodeset = cache->dbgCachedNodeset;
-	    caString = cache->dbgCachedString;
-	    caNumber = cache->dbgCachedNumber;
-	    caXSLTTree = cache->dbgCachedXSLTTree;
-	    caUndefined = cache->dbgCachedUndefined;
-
-	    if (cache->nodesetObjs)
-		leftObjs -= cache->nodesetObjs->number;
-	    if (cache->stringObjs)
-		leftObjs -= cache->stringObjs->number;
-	    if (cache->booleanObjs)
-		leftObjs -= cache->booleanObjs->number;
-	    if (cache->numberObjs)
-		leftObjs -= cache->numberObjs->number;
-	    if (cache->miscObjs)
-		leftObjs -= cache->miscObjs->number;
-	}
-    }
-
-    printf("# all\n");
-    printf("#   total  : %d\n", reqAll);
-    printf("#   left  : %d\n", leftObjs);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalAll);
-    printf("#   reused : %d\n", reAll);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxAll);
-
-    printf("# node-sets\n");
-    printf("#   total  : %d\n", reqNodeset);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalNodeset);
-    printf("#   reused : %d\n", reNodeset);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxNodeset);
-
-    printf("# strings\n");
-    printf("#   total  : %d\n", reqString);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalString);
-    printf("#   reused : %d\n", reString);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxString);
-
-    printf("# booleans\n");
-    printf("#   total  : %d\n", reqBool);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalBool);
-    printf("#   reused : %d\n", reBool);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxBool);
-
-    printf("# numbers\n");
-    printf("#   total  : %d\n", reqNumber);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalNumber);
-    printf("#   reused : %d\n", reNumber);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxNumber);
-
-    printf("# XSLT result tree fragments\n");
-    printf("#   total  : %d\n", reqXSLTTree);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalXSLTTree);
-    printf("#   reused : %d\n", reXSLTTree);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxXSLTTree);
-
-    printf("# undefined\n");
-    printf("#   total  : %d\n", reqUndefined);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalUndefined);
-    printf("#   reused : %d\n", reUndefined);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxUndefined);
-
-}
-
-#endif /* XP_DEBUG_OBJ_USAGE */
-
 #endif /* LIBXML_DEBUG_ENABLED */
 
 /************************************************************************
@@ -2200,45 +1557,31 @@ xmlXPathNewCache(void)
     xmlXPathContextCachePtr ret;
 
     ret = (xmlXPathContextCachePtr) xmlMalloc(sizeof(xmlXPathContextCache));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating object cache\n");
+    if (ret == NULL)
 	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathContextCache));
+    memset(ret, 0 , sizeof(xmlXPathContextCache));
     ret->maxNodeset = 100;
-    ret->maxString = 100;
-    ret->maxBoolean = 100;
-    ret->maxNumber = 100;
     ret->maxMisc = 100;
     return(ret);
 }
 
 static void
-xmlXPathCacheFreeObjectList(xmlPointerListPtr list)
+xmlXPathCacheFreeObjectList(xmlXPathObjectPtr list)
 {
-    int i;
-    xmlXPathObjectPtr obj;
+    while (list != NULL) {
+        xmlXPathObjectPtr next;
 
-    if (list == NULL)
-	return;
+        next = (void *) list->stringval;
 
-    for (i = 0; i < list->number; i++) {
-	obj = list->items[i];
-	/*
-	* Note that it is already assured that we don't need to
-	* look out for namespace nodes in the node-set.
-	*/
-	if (obj->nodesetval != NULL) {
-	    if (obj->nodesetval->nodeTab != NULL)
-		xmlFree(obj->nodesetval->nodeTab);
-	    xmlFree(obj->nodesetval);
+	if (list->nodesetval != NULL) {
+	    if (list->nodesetval->nodeTab != NULL)
+		xmlFree(list->nodesetval->nodeTab);
+	    xmlFree(list->nodesetval);
 	}
-	xmlFree(obj);
-#ifdef XP_DEBUG_OBJ_USAGE
-	xmlXPathDebugObjCounterAll--;
-#endif
+	xmlFree(list);
+
+        list = next;
     }
-    xmlPointerListFree(list);
 }
 
 static void
@@ -2248,12 +1591,6 @@ xmlXPathFreeCache(xmlXPathContextCachePtr cache)
 	return;
     if (cache->nodesetObjs)
 	xmlXPathCacheFreeObjectList(cache->nodesetObjs);
-    if (cache->stringObjs)
-	xmlXPathCacheFreeObjectList(cache->stringObjs);
-    if (cache->booleanObjs)
-	xmlXPathCacheFreeObjectList(cache->booleanObjs);
-    if (cache->numberObjs)
-	xmlXPathCacheFreeObjectList(cache->numberObjs);
     if (cache->miscObjs)
 	xmlXPathCacheFreeObjectList(cache->miscObjs);
     xmlFree(cache);
@@ -2275,8 +1612,8 @@ xmlXPathFreeCache(xmlXPathContextCachePtr cache)
  *      @value:
  *        This will set the maximum number of XPath objects
  *        to be cached per slot
- *        There are 5 slots for: node-set, string, number, boolean, and
- *        misc objects. Use <0 for the default number (100).
+ *        There are two slots for node-set and misc objects.
+ *        Use <0 for the default number (100).
  *   Other values for @options have currently no effect.
  *
  * Returns 0 if the setting succeeded, and -1 on API or internal errors.
@@ -2294,17 +1631,16 @@ xmlXPathContextSetCache(xmlXPathContextPtr ctxt,
 
 	if (ctxt->cache == NULL) {
 	    ctxt->cache = xmlXPathNewCache();
-	    if (ctxt->cache == NULL)
+	    if (ctxt->cache == NULL) {
+                xmlXPathErrMemory(ctxt);
 		return(-1);
+            }
 	}
 	cache = (xmlXPathContextCachePtr) ctxt->cache;
 	if (options == 0) {
 	    if (value < 0)
 		value = 100;
 	    cache->maxNodeset = value;
-	    cache->maxString = value;
-	    cache->maxNumber = value;
-	    cache->maxBoolean = value;
 	    cache->maxMisc = value;
 	}
     } else if (ctxt->cache != NULL) {
@@ -2316,44 +1652,46 @@ xmlXPathContextSetCache(xmlXPathContextPtr ctxt,
 
 /**
  * xmlXPathCacheWrapNodeSet:
- * @ctxt: the XPath context
+ * @pctxt: the XPath context
  * @val:  the NodePtr value
  *
  * This is the cached version of xmlXPathWrapNodeSet().
  * Wrap the Nodeset @val in a new xmlXPathObjectPtr
  *
  * Returns the created or reused object.
+ *
+ * In case of error the node set is destroyed and NULL is returned.
  */
 static xmlXPathObjectPtr
-xmlXPathCacheWrapNodeSet(xmlXPathContextPtr ctxt, xmlNodeSetPtr val)
+xmlXPathCacheWrapNodeSet(xmlXPathParserContextPtr pctxt, xmlNodeSetPtr val)
 {
+    xmlXPathObjectPtr ret;
+    xmlXPathContextPtr ctxt = pctxt->context;
+
     if ((ctxt != NULL) && (ctxt->cache != NULL)) {
 	xmlXPathContextCachePtr cache =
 	    (xmlXPathContextCachePtr) ctxt->cache;
 
-	if ((cache->miscObjs != NULL) &&
-	    (cache->miscObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
-
-	    ret = (xmlXPathObjectPtr)
-		cache->miscObjs->items[--cache->miscObjs->number];
+	if (cache->miscObjs != NULL) {
+	    ret = cache->miscObjs;
+            cache->miscObjs = (void *) ret->stringval;
+            cache->numMisc -= 1;
+            ret->stringval = NULL;
 	    ret->type = XPATH_NODESET;
 	    ret->nodesetval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
-#endif
 	    return(ret);
 	}
     }
 
-    return(xmlXPathWrapNodeSet(val));
-
+    ret = xmlXPathWrapNodeSet(val);
+    if (ret == NULL)
+        xmlXPathPErrMemory(pctxt);
+    return(ret);
 }
 
 /**
  * xmlXPathCacheWrapString:
- * @ctxt: the XPath context
+ * @pctxt the XPath context
  * @val:  the xmlChar * value
  *
  * This is the cached version of xmlXPathWrapString().
@@ -2362,49 +1700,33 @@ xmlXPathCacheWrapNodeSet(xmlXPathContextPtr ctxt, xmlNodeSetPtr val)
  * Returns the created or reused object.
  */
 static xmlXPathObjectPtr
-xmlXPathCacheWrapString(xmlXPathContextPtr ctxt, xmlChar *val)
+xmlXPathCacheWrapString(xmlXPathParserContextPtr pctxt, xmlChar *val)
 {
+    xmlXPathObjectPtr ret;
+    xmlXPathContextPtr ctxt = pctxt->context;
+
     if ((ctxt != NULL) && (ctxt->cache != NULL)) {
 	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
 
-	if ((cache->stringObjs != NULL) &&
-	    (cache->stringObjs->number != 0))
-	{
-
-	    xmlXPathObjectPtr ret;
-
-	    ret = (xmlXPathObjectPtr)
-		cache->stringObjs->items[--cache->stringObjs->number];
-	    ret->type = XPATH_STRING;
-	    ret->stringval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
-#endif
-	    return(ret);
-	} else if ((cache->miscObjs != NULL) &&
-	    (cache->miscObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
-	    /*
-	    * Fallback to misc-cache.
-	    */
-	    ret = (xmlXPathObjectPtr)
-		cache->miscObjs->items[--cache->miscObjs->number];
-
+	if (cache->miscObjs != NULL) {
+	    ret = cache->miscObjs;
+            cache->miscObjs = (void *) ret->stringval;
+            cache->numMisc -= 1;
 	    ret->type = XPATH_STRING;
 	    ret->stringval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
-#endif
 	    return(ret);
 	}
     }
-    return(xmlXPathWrapString(val));
+
+    ret = xmlXPathWrapString(val);
+    if (ret == NULL)
+        xmlXPathPErrMemory(pctxt);
+    return(ret);
 }
 
 /**
  * xmlXPathCacheNewNodeSet:
- * @ctxt: the XPath context
+ * @pctxt the XPath context
  * @val:  the NodePtr value
  *
  * This is the cached version of xmlXPathNewNodeSet().
@@ -2414,117 +1736,67 @@ xmlXPathCacheWrapString(xmlXPathContextPtr ctxt, xmlChar *val)
  * Returns the created or reused object.
  */
 static xmlXPathObjectPtr
-xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val)
+xmlXPathCacheNewNodeSet(xmlXPathParserContextPtr pctxt, xmlNodePtr val)
 {
-    if ((ctxt != NULL) && (ctxt->cache)) {
+    xmlXPathObjectPtr ret;
+    xmlXPathContextPtr ctxt = pctxt->context;
+
+    if ((ctxt != NULL) && (ctxt->cache != NULL)) {
 	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
 
-	if ((cache->nodesetObjs != NULL) &&
-	    (cache->nodesetObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
+	if (cache->nodesetObjs != NULL) {
 	    /*
 	    * Use the nodeset-cache.
 	    */
-	    ret = (xmlXPathObjectPtr)
-		cache->nodesetObjs->items[--cache->nodesetObjs->number];
+	    ret = cache->nodesetObjs;
+            cache->nodesetObjs = (void *) ret->stringval;
+            cache->numNodeset -= 1;
+            ret->stringval = NULL;
 	    ret->type = XPATH_NODESET;
 	    ret->boolval = 0;
 	    if (val) {
 		if ((ret->nodesetval->nodeMax == 0) ||
 		    (val->type == XML_NAMESPACE_DECL))
 		{
-                    /* TODO: Check memory error. */
-		    xmlXPathNodeSetAddUnique(ret->nodesetval, val);
+		    if (xmlXPathNodeSetAddUnique(ret->nodesetval, val) < 0)
+                        xmlXPathPErrMemory(pctxt);
 		} else {
 		    ret->nodesetval->nodeTab[0] = val;
 		    ret->nodesetval->nodeNr = 1;
 		}
 	    }
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
-#endif
 	    return(ret);
-	} else if ((cache->miscObjs != NULL) &&
-	    (cache->miscObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
+	} else if (cache->miscObjs != NULL) {
+            xmlNodeSetPtr set;
 	    /*
 	    * Fallback to misc-cache.
 	    */
 
-	    ret = (xmlXPathObjectPtr)
-		cache->miscObjs->items[--cache->miscObjs->number];
-
-	    ret->type = XPATH_NODESET;
-	    ret->boolval = 0;
-	    ret->nodesetval = xmlXPathNodeSetCreate(val);
-	    if (ret->nodesetval == NULL) {
-		ctxt->lastError.domain = XML_FROM_XPATH;
-		ctxt->lastError.code = XML_ERR_NO_MEMORY;
+	    set = xmlXPathNodeSetCreate(val);
+	    if (set == NULL) {
+                xmlXPathPErrMemory(pctxt);
 		return(NULL);
 	    }
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
-#endif
-	    return(ret);
-	}
-    }
-    return(xmlXPathNewNodeSet(val));
-}
-
-/**
- * xmlXPathCacheNewCString:
- * @ctxt: the XPath context
- * @val:  the char * value
- *
- * This is the cached version of xmlXPathNewCString().
- * Acquire an xmlXPathObjectPtr of type string and of value @val
- *
- * Returns the created or reused object.
- */
-static xmlXPathObjectPtr
-xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val)
-{
-    if ((ctxt != NULL) && (ctxt->cache)) {
-	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
-
-	if ((cache->stringObjs != NULL) &&
-	    (cache->stringObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
-
-	    ret = (xmlXPathObjectPtr)
-		cache->stringObjs->items[--cache->stringObjs->number];
-
-	    ret->type = XPATH_STRING;
-	    ret->stringval = xmlStrdup(BAD_CAST val);
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
-#endif
-	    return(ret);
-	} else if ((cache->miscObjs != NULL) &&
-	    (cache->miscObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
-
-	    ret = (xmlXPathObjectPtr)
-		cache->miscObjs->items[--cache->miscObjs->number];
 
-	    ret->type = XPATH_STRING;
-	    ret->stringval = xmlStrdup(BAD_CAST val);
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
-#endif
+	    ret = cache->miscObjs;
+            cache->miscObjs = (void *) ret->stringval;
+            cache->numMisc -= 1;
+            ret->stringval = NULL;
+	    ret->type = XPATH_NODESET;
+	    ret->boolval = 0;
+	    ret->nodesetval = set;
 	    return(ret);
 	}
     }
-    return(xmlXPathNewCString(val));
+    ret = xmlXPathNewNodeSet(val);
+    if (ret == NULL)
+        xmlXPathPErrMemory(pctxt);
+    return(ret);
 }
 
 /**
  * xmlXPathCacheNewString:
- * @ctxt: the XPath context
+ * @pctxt the XPath context
  * @val:  the xmlChar * value
  *
  * This is the cached version of xmlXPathNewString().
@@ -2533,276 +1805,172 @@ xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val)
  * Returns the created or reused object.
  */
 static xmlXPathObjectPtr
-xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val)
+xmlXPathCacheNewString(xmlXPathParserContextPtr pctxt, const xmlChar *val)
 {
-    if ((ctxt != NULL) && (ctxt->cache)) {
-	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
+    xmlXPathObjectPtr ret;
+    xmlXPathContextPtr ctxt = pctxt->context;
 
-	if ((cache->stringObjs != NULL) &&
-	    (cache->stringObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
+    if ((ctxt != NULL) && (ctxt->cache != NULL)) {
+	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
 
-	    ret = (xmlXPathObjectPtr)
-		cache->stringObjs->items[--cache->stringObjs->number];
-	    ret->type = XPATH_STRING;
-	    if (val != NULL)
-		ret->stringval = xmlStrdup(val);
-	    else
-		ret->stringval = xmlStrdup((const xmlChar *)"");
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
-#endif
-	    return(ret);
-	} else if ((cache->miscObjs != NULL) &&
-	    (cache->miscObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
+	if (cache->miscObjs != NULL) {
+            xmlChar *copy;
 
-	    ret = (xmlXPathObjectPtr)
-		cache->miscObjs->items[--cache->miscObjs->number];
+            if (val == NULL)
+                val = BAD_CAST "";
+            copy = xmlStrdup(val);
+            if (copy == NULL) {
+                xmlXPathPErrMemory(pctxt);
+                return(NULL);
+            }
 
+	    ret = cache->miscObjs;
+            cache->miscObjs = (void *) ret->stringval;
+            cache->numMisc -= 1;
 	    ret->type = XPATH_STRING;
-	    if (val != NULL)
-		ret->stringval = xmlStrdup(val);
-	    else
-		ret->stringval = xmlStrdup((const xmlChar *)"");
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
-#endif
+            ret->stringval = copy;
 	    return(ret);
 	}
     }
-    return(xmlXPathNewString(val));
-}
 
-/**
- * xmlXPathCacheNewBoolean:
- * @ctxt: the XPath context
- * @val:  the boolean value
- *
- * This is the cached version of xmlXPathNewBoolean().
- * Acquires an xmlXPathObjectPtr of type boolean and of value @val
- *
- * Returns the created or reused object.
- */
-static xmlXPathObjectPtr
-xmlXPathCacheNewBoolean(xmlXPathContextPtr ctxt, int val)
-{
-    if ((ctxt != NULL) && (ctxt->cache)) {
-	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
-
-	if ((cache->booleanObjs != NULL) &&
-	    (cache->booleanObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
-
-	    ret = (xmlXPathObjectPtr)
-		cache->booleanObjs->items[--cache->booleanObjs->number];
-	    ret->type = XPATH_BOOLEAN;
-	    ret->boolval = (val != 0);
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN);
-#endif
-	    return(ret);
-	} else if ((cache->miscObjs != NULL) &&
-	    (cache->miscObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
-
-	    ret = (xmlXPathObjectPtr)
-		cache->miscObjs->items[--cache->miscObjs->number];
-
-	    ret->type = XPATH_BOOLEAN;
-	    ret->boolval = (val != 0);
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN);
-#endif
-	    return(ret);
-	}
-    }
-    return(xmlXPathNewBoolean(val));
+    ret = xmlXPathNewString(val);
+    if (ret == NULL)
+        xmlXPathPErrMemory(pctxt);
+    return(ret);
 }
 
 /**
- * xmlXPathCacheNewFloat:
- * @ctxt: the XPath context
- * @val:  the double value
+ * xmlXPathCacheNewCString:
+ * @pctxt the XPath context
+ * @val:  the char * value
  *
- * This is the cached version of xmlXPathNewFloat().
- * Acquires an xmlXPathObjectPtr of type double and of value @val
+ * This is the cached version of xmlXPathNewCString().
+ * Acquire an xmlXPathObjectPtr of type string and of value @val
  *
  * Returns the created or reused object.
  */
 static xmlXPathObjectPtr
-xmlXPathCacheNewFloat(xmlXPathContextPtr ctxt, double val)
+xmlXPathCacheNewCString(xmlXPathParserContextPtr pctxt, const char *val)
 {
-     if ((ctxt != NULL) && (ctxt->cache)) {
-	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
-
-	if ((cache->numberObjs != NULL) &&
-	    (cache->numberObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
-
-	    ret = (xmlXPathObjectPtr)
-		cache->numberObjs->items[--cache->numberObjs->number];
-	    ret->type = XPATH_NUMBER;
-	    ret->floatval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER);
-#endif
-	    return(ret);
-	} else if ((cache->miscObjs != NULL) &&
-	    (cache->miscObjs->number != 0))
-	{
-	    xmlXPathObjectPtr ret;
-
-	    ret = (xmlXPathObjectPtr)
-		cache->miscObjs->items[--cache->miscObjs->number];
-
-	    ret->type = XPATH_NUMBER;
-	    ret->floatval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER);
-#endif
-	    return(ret);
-	}
-    }
-    return(xmlXPathNewFloat(val));
-}
-
-/**
- * xmlXPathCacheConvertString:
- * @ctxt: the XPath context
- * @val:  an XPath object
- *
- * This is the cached version of xmlXPathConvertString().
- * Converts an existing object to its string() equivalent
- *
- * Returns a created or reused object, the old one is freed (cached)
- *         (or the operation is done directly on @val)
- */
-
-static xmlXPathObjectPtr
-xmlXPathCacheConvertString(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) {
-    xmlChar *res = NULL;
-
-    if (val == NULL)
-	return(xmlXPathCacheNewCString(ctxt, ""));
-
-    switch (val->type) {
-    case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
-#endif
-	break;
-    case XPATH_NODESET:
-    case XPATH_XSLT_TREE:
-	res = xmlXPathCastNodeSetToString(val->nodesetval);
-	break;
-    case XPATH_STRING:
-	return(val);
-    case XPATH_BOOLEAN:
-	res = xmlXPathCastBooleanToString(val->boolval);
-	break;
-    case XPATH_NUMBER:
-	res = xmlXPathCastNumberToString(val->floatval);
-	break;
-    case XPATH_USERS:
-#ifdef LIBXML_XPTR_LOCS_ENABLED
-    case XPATH_POINT:
-    case XPATH_RANGE:
-    case XPATH_LOCATIONSET:
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
-	TODO;
-	break;
-    }
-    xmlXPathReleaseObject(ctxt, val);
-    if (res == NULL)
-	return(xmlXPathCacheNewCString(ctxt, ""));
-    return(xmlXPathCacheWrapString(ctxt, res));
+    return xmlXPathCacheNewString(pctxt, BAD_CAST val);
 }
 
 /**
- * xmlXPathCacheObjectCopy:
- * @ctxt: the XPath context
- * @val:  the original object
+ * xmlXPathCacheNewBoolean:
+ * @pctxt the XPath context
+ * @val:  the boolean value
  *
- * This is the cached version of xmlXPathObjectCopy().
- * Acquire a copy of a given object
+ * This is the cached version of xmlXPathNewBoolean().
+ * Acquires an xmlXPathObjectPtr of type boolean and of value @val
  *
- * Returns a created or reused created object.
+ * Returns the created or reused object.
  */
 static xmlXPathObjectPtr
-xmlXPathCacheObjectCopy(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val)
+xmlXPathCacheNewBoolean(xmlXPathParserContextPtr pctxt, int val)
 {
-    if (val == NULL)
-	return(NULL);
+    xmlXPathObjectPtr ret;
+    xmlXPathContextPtr ctxt = pctxt->context;
 
-    if (XP_HAS_CACHE(ctxt)) {
-	switch (val->type) {
-	    case XPATH_NODESET:
-		return(xmlXPathCacheWrapNodeSet(ctxt,
-		    xmlXPathNodeSetMerge(NULL, val->nodesetval)));
-	    case XPATH_STRING:
-		return(xmlXPathCacheNewString(ctxt, val->stringval));
-	    case XPATH_BOOLEAN:
-		return(xmlXPathCacheNewBoolean(ctxt, val->boolval));
-	    case XPATH_NUMBER:
-		return(xmlXPathCacheNewFloat(ctxt, val->floatval));
-	    default:
-		break;
+    if ((ctxt != NULL) && (ctxt->cache != NULL)) {
+	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
+
+	if (cache->miscObjs != NULL) {
+	    ret = cache->miscObjs;
+            cache->miscObjs = (void *) ret->stringval;
+            cache->numMisc -= 1;
+            ret->stringval = NULL;
+	    ret->type = XPATH_BOOLEAN;
+	    ret->boolval = (val != 0);
+	    return(ret);
 	}
     }
-    return(xmlXPathObjectCopy(val));
+
+    ret = xmlXPathNewBoolean(val);
+    if (ret == NULL)
+        xmlXPathPErrMemory(pctxt);
+    return(ret);
 }
 
 /**
- * xmlXPathCacheConvertBoolean:
- * @ctxt: the XPath context
- * @val:  an XPath object
+ * xmlXPathCacheNewFloat:
+ * @pctxt the XPath context
+ * @val:  the double value
  *
- * This is the cached version of xmlXPathConvertBoolean().
- * Converts an existing object to its boolean() equivalent
+ * This is the cached version of xmlXPathNewFloat().
+ * Acquires an xmlXPathObjectPtr of type double and of value @val
  *
- * Returns a created or reused object, the old one is freed (or the operation
- *         is done directly on @val)
+ * Returns the created or reused object.
  */
 static xmlXPathObjectPtr
-xmlXPathCacheConvertBoolean(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) {
+xmlXPathCacheNewFloat(xmlXPathParserContextPtr pctxt, double val)
+{
     xmlXPathObjectPtr ret;
+    xmlXPathContextPtr ctxt = pctxt->context;
 
-    if (val == NULL)
-	return(xmlXPathCacheNewBoolean(ctxt, 0));
-    if (val->type == XPATH_BOOLEAN)
-	return(val);
-    ret = xmlXPathCacheNewBoolean(ctxt, xmlXPathCastToBoolean(val));
-    xmlXPathReleaseObject(ctxt, val);
+    if ((ctxt != NULL) && (ctxt->cache != NULL)) {
+	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
+
+	if (cache->miscObjs != NULL) {
+	    ret = cache->miscObjs;
+            cache->miscObjs = (void *) ret->stringval;
+            cache->numMisc -= 1;
+            ret->stringval = NULL;
+	    ret->type = XPATH_NUMBER;
+	    ret->floatval = val;
+	    return(ret);
+	}
+    }
+
+    ret = xmlXPathNewFloat(val);
+    if (ret == NULL)
+        xmlXPathPErrMemory(pctxt);
     return(ret);
 }
 
 /**
- * xmlXPathCacheConvertNumber:
- * @ctxt: the XPath context
- * @val:  an XPath object
+ * xmlXPathCacheObjectCopy:
+ * @pctxt the XPath context
+ * @val:  the original object
  *
- * This is the cached version of xmlXPathConvertNumber().
- * Converts an existing object to its number() equivalent
+ * This is the cached version of xmlXPathObjectCopy().
+ * Acquire a copy of a given object
  *
- * Returns a created or reused object, the old one is freed (or the operation
- *         is done directly on @val)
+ * Returns a created or reused created object.
  */
 static xmlXPathObjectPtr
-xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) {
+xmlXPathCacheObjectCopy(xmlXPathParserContextPtr pctxt, xmlXPathObjectPtr val)
+{
     xmlXPathObjectPtr ret;
+    xmlXPathContextPtr ctxt = pctxt->context;
 
     if (val == NULL)
-	return(xmlXPathCacheNewFloat(ctxt, 0.0));
-    if (val->type == XPATH_NUMBER)
-	return(val);
-    ret = xmlXPathCacheNewFloat(ctxt, xmlXPathCastToNumber(val));
-    xmlXPathReleaseObject(ctxt, val);
+	return(NULL);
+
+    if ((ctxt != NULL) && (ctxt->cache != NULL)) {
+	switch (val->type) {
+            case XPATH_NODESET: {
+                xmlNodeSetPtr set;
+
+                set = xmlXPathNodeSetMerge(NULL, val->nodesetval);
+                if (set == NULL) {
+                    xmlXPathPErrMemory(pctxt);
+                    return(NULL);
+                }
+                return(xmlXPathCacheWrapNodeSet(pctxt, set));
+            }
+	    case XPATH_STRING:
+		return(xmlXPathCacheNewString(pctxt, val->stringval));
+	    case XPATH_BOOLEAN:
+		return(xmlXPathCacheNewBoolean(pctxt, val->boolval));
+	    case XPATH_NUMBER:
+		return(xmlXPathCacheNewFloat(pctxt, val->floatval));
+	    default:
+		break;
+	}
+    }
+    ret = xmlXPathObjectCopy(val);
+    if (ret == NULL)
+        xmlXPathPErrMemory(pctxt);
     return(ret);
 }
 
@@ -2813,39 +1981,59 @@ xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) {
  ************************************************************************/
 
 /**
- * xmlXPathSetFrame:
- * @ctxt: an XPath parser context
+ * xmlXPathCastToNumberInternal:
+ * @ctxt:  parser context
+ * @val:  an XPath object
  *
- * Set the callee evaluation frame
+ * Converts an XPath object to its number value
  *
- * Returns the previous frame value to be restored once done
+ * Returns the number value
  */
-static int
-xmlXPathSetFrame(xmlXPathParserContextPtr ctxt) {
-    int ret;
+static double
+xmlXPathCastToNumberInternal(xmlXPathParserContextPtr ctxt,
+                             xmlXPathObjectPtr val) {
+    double ret = 0.0;
 
-    if (ctxt == NULL)
-        return(0);
-    ret = ctxt->valueFrame;
-    ctxt->valueFrame = ctxt->valueNr;
-    return(ret);
-}
+    if (val == NULL)
+	return(xmlXPathNAN);
+    switch (val->type) {
+    case XPATH_UNDEFINED:
+	ret = xmlXPathNAN;
+	break;
+    case XPATH_NODESET:
+    case XPATH_XSLT_TREE: {
+        xmlChar *str;
 
-/**
- * xmlXPathPopFrame:
- * @ctxt: an XPath parser context
- * @frame: the previous frame value
- *
- * Remove the callee evaluation frame
- */
-static void
-xmlXPathPopFrame(xmlXPathParserContextPtr ctxt, int frame) {
-    if (ctxt == NULL)
-        return;
-    if (ctxt->valueNr < ctxt->valueFrame) {
-        xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
+	str = xmlXPathCastNodeSetToString(val->nodesetval);
+        if (str == NULL) {
+            xmlXPathPErrMemory(ctxt);
+            ret = xmlXPathNAN;
+        } else {
+	    ret = xmlXPathCastStringToNumber(str);
+            xmlFree(str);
+        }
+	break;
+    }
+    case XPATH_STRING:
+	ret = xmlXPathCastStringToNumber(val->stringval);
+	break;
+    case XPATH_NUMBER:
+	ret = val->floatval;
+	break;
+    case XPATH_BOOLEAN:
+	ret = xmlXPathCastBooleanToNumber(val->boolval);
+	break;
+    case XPATH_USERS:
+#ifdef LIBXML_XPTR_LOCS_ENABLED
+    case XPATH_POINT:
+    case XPATH_RANGE:
+    case XPATH_LOCATIONSET:
+#endif /* LIBXML_XPTR_LOCS_ENABLED */
+	/* TODO */
+	ret = xmlXPathNAN;
+	break;
     }
-    ctxt->valueFrame = frame;
+    return(ret);
 }
 
 /**
@@ -2864,11 +2052,6 @@ valuePop(xmlXPathParserContextPtr ctxt)
     if ((ctxt == NULL) || (ctxt->valueNr <= 0))
         return (NULL);
 
-    if (ctxt->valueNr <= ctxt->valueFrame) {
-        xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
-        return (NULL);
-    }
-
     ctxt->valueNr--;
     if (ctxt->valueNr > 0)
         ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
@@ -2887,6 +2070,8 @@ valuePop(xmlXPathParserContextPtr ctxt)
  * a memory error is recorded in the parser context.
  *
  * Returns the number of items on the value stack, or -1 in case of error.
+ *
+ * The object is destroyed in case of error.
  */
 int
 valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
@@ -2894,24 +2079,25 @@ valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
     if (ctxt == NULL) return(-1);
     if (value == NULL) {
         /*
-         * A NULL value typically indicates that a memory allocation failed,
-         * so we set ctxt->error here to propagate the error.
+         * A NULL value typically indicates that a memory allocation failed.
          */
-	ctxt->error = XPATH_MEMORY_ERROR;
+        xmlXPathPErrMemory(ctxt);
         return(-1);
     }
     if (ctxt->valueNr >= ctxt->valueMax) {
         xmlXPathObjectPtr *tmp;
 
         if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) {
-            xmlXPathPErrMemory(ctxt, "XPath stack depth limit reached\n");
+            xmlXPathPErrMemory(ctxt);
+            xmlXPathFreeObject(value);
             return (-1);
         }
         tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
                                              2 * ctxt->valueMax *
                                              sizeof(ctxt->valueTab[0]));
         if (tmp == NULL) {
-            xmlXPathPErrMemory(ctxt, "pushing value\n");
+            xmlXPathPErrMemory(ctxt);
+            xmlXPathFreeObject(value);
             return (-1);
         }
         ctxt->valueMax *= 2;
@@ -2969,7 +2155,7 @@ xmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
 	return(0);
     }
     if (obj->type != XPATH_NUMBER)
-	ret = xmlXPathCastToNumber(obj);
+	ret = xmlXPathCastToNumberInternal(ctxt, obj);
     else
         ret = obj->floatval;
     xmlXPathReleaseObject(ctxt->context, obj);
@@ -2995,10 +2181,9 @@ xmlXPathPopString (xmlXPathParserContextPtr ctxt) {
 	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
 	return(NULL);
     }
-    ret = xmlXPathCastToString(obj);	/* this does required strdup */
-    /* TODO: needs refactoring somewhere else */
-    if (obj->stringval == ret)
-	obj->stringval = NULL;
+    ret = xmlXPathCastToString(obj);
+    if (ret == NULL)
+        xmlXPathPErrMemory(ctxt);
     xmlXPathReleaseObject(ctxt->context, obj);
     return(ret);
 }
@@ -3097,7 +2282,7 @@ xmlXPathPopExternal (xmlXPathParserContextPtr ctxt) {
 #define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)
 
 #define COPY_BUF(l,b,i,v)                                              \
-    if (l == 1) b[i++] = (xmlChar) v;                                  \
+    if (l == 1) b[i++] = v;                                            \
     else i += xmlCopyChar(l,&b[i],v)
 
 #define NEXTL(l)  ctxt->cur += l
@@ -3304,7 +2489,7 @@ xmlXPathOrderDocElems(xmlDocPtr doc) {
 	    }
 	} while (cur != NULL);
     }
-    return((long) count);
+    return(count);
 }
 
 /**
@@ -3527,16 +2712,25 @@ xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
      * Allocate a new Namespace and fill the fields.
      */
     cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
-    if (cur == NULL) {
-        xmlXPathErrMemory(NULL, "duplicating namespace\n");
+    if (cur == NULL)
 	return(NULL);
-    }
     memset(cur, 0, sizeof(xmlNs));
     cur->type = XML_NAMESPACE_DECL;
-    if (ns->href != NULL)
+    if (ns->href != NULL) {
 	cur->href = xmlStrdup(ns->href);
-    if (ns->prefix != NULL)
+        if (cur->href == NULL) {
+            xmlFree(cur);
+            return(NULL);
+        }
+    }
+    if (ns->prefix != NULL) {
 	cur->prefix = xmlStrdup(ns->prefix);
+        if (cur->prefix == NULL) {
+            xmlFree((xmlChar *) cur->href);
+            xmlFree(cur);
+            return(NULL);
+        }
+    }
     cur->next = (xmlNsPtr) node;
     return((xmlNodePtr) cur);
 }
@@ -3576,28 +2770,28 @@ xmlXPathNodeSetCreate(xmlNodePtr val) {
     xmlNodeSetPtr ret;
 
     ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating nodeset\n");
+    if (ret == NULL)
 	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlNodeSet));
+    memset(ret, 0 , sizeof(xmlNodeSet));
     if (val != NULL) {
         ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
 					     sizeof(xmlNodePtr));
 	if (ret->nodeTab == NULL) {
-	    xmlXPathErrMemory(NULL, "creating nodeset\n");
 	    xmlFree(ret);
 	    return(NULL);
 	}
 	memset(ret->nodeTab, 0 ,
-	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+	       XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
         ret->nodeMax = XML_NODESET_DEFAULT;
 	if (val->type == XML_NAMESPACE_DECL) {
 	    xmlNsPtr ns = (xmlNsPtr) val;
+            xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
 
-            /* TODO: Check memory error. */
-	    ret->nodeTab[ret->nodeNr++] =
-		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
+            if (nsNode == NULL) {
+                xmlXPathFreeNodeSet(ret);
+                return(NULL);
+            }
+	    ret->nodeTab[ret->nodeNr++] = nsNode;
 	} else
 	    ret->nodeTab[ret->nodeNr++] = val;
     }
@@ -3654,7 +2848,7 @@ xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
 int
 xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
     int i;
-
+    xmlNodePtr nsNode;
 
     if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
         (ns->type != XML_NAMESPACE_DECL) ||
@@ -3679,31 +2873,27 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
     if (cur->nodeMax == 0) {
         cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
 					     sizeof(xmlNodePtr));
-	if (cur->nodeTab == NULL) {
-	    xmlXPathErrMemory(NULL, "growing nodeset\n");
+	if (cur->nodeTab == NULL)
 	    return(-1);
-	}
 	memset(cur->nodeTab, 0 ,
-	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+	       XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
         cur->nodeMax = XML_NODESET_DEFAULT;
     } else if (cur->nodeNr == cur->nodeMax) {
         xmlNodePtr *temp;
 
-        if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
-            xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
+        if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
             return(-1);
-        }
 	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
 				      sizeof(xmlNodePtr));
-	if (temp == NULL) {
-	    xmlXPathErrMemory(NULL, "growing nodeset\n");
+	if (temp == NULL)
 	    return(-1);
-	}
         cur->nodeMax *= 2;
 	cur->nodeTab = temp;
     }
-    /* TODO: Check memory error. */
-    cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
+    nsNode = xmlXPathNodeSetDupNs(node, ns);
+    if(nsNode == NULL)
+        return(-1);
+    cur->nodeTab[cur->nodeNr++] = nsNode;
     return(0);
 }
 
@@ -3735,35 +2925,30 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
     if (cur->nodeMax == 0) {
         cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
 					     sizeof(xmlNodePtr));
-	if (cur->nodeTab == NULL) {
-	    xmlXPathErrMemory(NULL, "growing nodeset\n");
+	if (cur->nodeTab == NULL)
 	    return(-1);
-	}
 	memset(cur->nodeTab, 0 ,
-	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+	       XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
         cur->nodeMax = XML_NODESET_DEFAULT;
     } else if (cur->nodeNr == cur->nodeMax) {
         xmlNodePtr *temp;
 
-        if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
-            xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
+        if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
             return(-1);
-        }
 	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
 				      sizeof(xmlNodePtr));
-	if (temp == NULL) {
-	    xmlXPathErrMemory(NULL, "growing nodeset\n");
+	if (temp == NULL)
 	    return(-1);
-	}
         cur->nodeMax *= 2;
 	cur->nodeTab = temp;
     }
     if (val->type == XML_NAMESPACE_DECL) {
 	xmlNsPtr ns = (xmlNsPtr) val;
+        xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
 
-        /* TODO: Check memory error. */
-	cur->nodeTab[cur->nodeNr++] =
-	    xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
+        if (nsNode == NULL)
+            return(-1);
+	cur->nodeTab[cur->nodeNr++] = nsNode;
     } else
 	cur->nodeTab[cur->nodeNr++] = val;
     return(0);
@@ -3790,35 +2975,30 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
     if (cur->nodeMax == 0) {
         cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
 					     sizeof(xmlNodePtr));
-	if (cur->nodeTab == NULL) {
-	    xmlXPathErrMemory(NULL, "growing nodeset\n");
+	if (cur->nodeTab == NULL)
 	    return(-1);
-	}
 	memset(cur->nodeTab, 0 ,
-	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+	       XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
         cur->nodeMax = XML_NODESET_DEFAULT;
     } else if (cur->nodeNr == cur->nodeMax) {
         xmlNodePtr *temp;
 
-        if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
-            xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
+        if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
             return(-1);
-        }
 	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
 				      sizeof(xmlNodePtr));
-	if (temp == NULL) {
-	    xmlXPathErrMemory(NULL, "growing nodeset\n");
+	if (temp == NULL)
 	    return(-1);
-	}
 	cur->nodeTab = temp;
         cur->nodeMax *= 2;
     }
     if (val->type == XML_NAMESPACE_DECL) {
 	xmlNsPtr ns = (xmlNsPtr) val;
+        xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
 
-        /* TODO: Check memory error. */
-	cur->nodeTab[cur->nodeNr++] =
-	    xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
+        if (nsNode == NULL)
+            return(-1);
+	cur->nodeTab[cur->nodeNr++] = nsNode;
     } else
 	cur->nodeTab[cur->nodeNr++] = val;
     return(0);
@@ -3833,45 +3013,21 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
  * if @val1 is NULL, a new set is created and copied from @val2
  *
  * Returns @val1 once extended or NULL in case of error.
+ *
+ * Frees @val1 in case of error.
  */
 xmlNodeSetPtr
 xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
     int i, j, initNr, skip;
     xmlNodePtr n1, n2;
 
-    if (val2 == NULL) return(val1);
     if (val1 == NULL) {
 	val1 = xmlXPathNodeSetCreate(NULL);
-    if (val1 == NULL)
-        return (NULL);
-#if 0
-	/*
-	* TODO: The optimization won't work in every case, since
-	*  those nasty namespace nodes need to be added with
-	*  xmlXPathNodeSetDupNs() to the set; thus a pure
-	*  memcpy is not possible.
-	*  If there was a flag on the nodesetval, indicating that
-	*  some temporary nodes are in, that would be helpful.
-	*/
-	/*
-	* Optimization: Create an equally sized node-set
-	* and memcpy the content.
-	*/
-	val1 = xmlXPathNodeSetCreateSize(val2->nodeNr);
-	if (val1 == NULL)
-	    return(NULL);
-	if (val2->nodeNr != 0) {
-	    if (val2->nodeNr == 1)
-		*(val1->nodeTab) = *(val2->nodeTab);
-	    else {
-		memcpy(val1->nodeTab, val2->nodeTab,
-		    val2->nodeNr * sizeof(xmlNodePtr));
-	    }
-	    val1->nodeNr = val2->nodeNr;
-	}
-	return(val1);
-#endif
+        if (val1 == NULL)
+            return (NULL);
     }
+    if (val2 == NULL)
+        return(val1);
 
     /* @@ with_ns to check whether namespace nodes should be looked at @@ */
     initNr = val1->nodeNr;
@@ -3907,40 +3063,39 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
 	if (val1->nodeMax == 0) {
 	    val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
 						    sizeof(xmlNodePtr));
-	    if (val1->nodeTab == NULL) {
-	        xmlXPathErrMemory(NULL, "merging nodeset\n");
-		return(NULL);
-	    }
+	    if (val1->nodeTab == NULL)
+		goto error;
 	    memset(val1->nodeTab, 0 ,
-		   XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+		   XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
 	    val1->nodeMax = XML_NODESET_DEFAULT;
 	} else if (val1->nodeNr == val1->nodeMax) {
 	    xmlNodePtr *temp;
 
-            if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
-                xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
-                return(NULL);
-            }
+            if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
+                goto error;
 	    temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
 					     sizeof(xmlNodePtr));
-	    if (temp == NULL) {
-	        xmlXPathErrMemory(NULL, "merging nodeset\n");
-		return(NULL);
-	    }
+	    if (temp == NULL)
+		goto error;
 	    val1->nodeTab = temp;
 	    val1->nodeMax *= 2;
 	}
 	if (n2->type == XML_NAMESPACE_DECL) {
 	    xmlNsPtr ns = (xmlNsPtr) n2;
+            xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
 
-            /* TODO: Check memory error. */
-	    val1->nodeTab[val1->nodeNr++] =
-		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
+            if (nsNode == NULL)
+                goto error;
+	    val1->nodeTab[val1->nodeNr++] = nsNode;
 	} else
 	    val1->nodeTab[val1->nodeNr++] = n2;
     }
 
     return(val1);
+
+error:
+    xmlXPathFreeNodeSet(val1);
+    return(NULL);
 }
 
 
@@ -3953,6 +3108,8 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
  * Checks for duplicate nodes. Clears set2.
  *
  * Returns @set1 once extended or NULL in case of error.
+ *
+ * Frees @set1 in case of error.
  */
 static xmlNodeSetPtr
 xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
@@ -3981,7 +3138,6 @@ xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
 			/*
 			* Free the namespace node.
 			*/
-			set2->nodeTab[i] = NULL;
 			xmlXPathNodeSetFreeNs((xmlNsPtr) n2);
 			goto skip_node;
 		    }
@@ -3993,36 +3149,35 @@ xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
 	    if (set1->nodeMax == 0) {
 		set1->nodeTab = (xmlNodePtr *) xmlMalloc(
 		    XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
-		if (set1->nodeTab == NULL) {
-		    xmlXPathErrMemory(NULL, "merging nodeset\n");
-		    return(NULL);
-		}
+		if (set1->nodeTab == NULL)
+		    goto error;
 		memset(set1->nodeTab, 0,
-		    XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+		    XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
 		set1->nodeMax = XML_NODESET_DEFAULT;
 	    } else if (set1->nodeNr >= set1->nodeMax) {
 		xmlNodePtr *temp;
 
-                if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
-                    xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
-                    return(NULL);
-                }
+                if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
+                    goto error;
 		temp = (xmlNodePtr *) xmlRealloc(
 		    set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
-		if (temp == NULL) {
-		    xmlXPathErrMemory(NULL, "merging nodeset\n");
-		    return(NULL);
-		}
+		if (temp == NULL)
+		    goto error;
 		set1->nodeTab = temp;
 		set1->nodeMax *= 2;
 	    }
 	    set1->nodeTab[set1->nodeNr++] = n2;
 skip_node:
-	    {}
+            set2->nodeTab[i] = NULL;
 	}
     }
     set2->nodeNr = 0;
     return(set1);
+
+error:
+    xmlXPathFreeNodeSet(set1);
+    xmlXPathNodeSetClear(set2, 1);
+    return(NULL);
 }
 
 /**
@@ -4034,6 +3189,8 @@ skip_node:
  * Doesn't check for duplicate nodes. Clears set2.
  *
  * Returns @set1 once extended or NULL in case of error.
+ *
+ * Frees @set1 in case of error.
  */
 static xmlNodeSetPtr
 xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
@@ -4047,34 +3204,34 @@ xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
 	    if (set1->nodeMax == 0) {
 		set1->nodeTab = (xmlNodePtr *) xmlMalloc(
 		    XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
-		if (set1->nodeTab == NULL) {
-		    xmlXPathErrMemory(NULL, "merging nodeset\n");
-		    return(NULL);
-		}
+		if (set1->nodeTab == NULL)
+		    goto error;
 		memset(set1->nodeTab, 0,
-		    XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+		    XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
 		set1->nodeMax = XML_NODESET_DEFAULT;
 	    } else if (set1->nodeNr >= set1->nodeMax) {
 		xmlNodePtr *temp;
 
-                if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
-                    xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
-                    return(NULL);
-                }
+                if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
+                    goto error;
 		temp = (xmlNodePtr *) xmlRealloc(
 		    set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
-		if (temp == NULL) {
-		    xmlXPathErrMemory(NULL, "merging nodeset\n");
-		    return(NULL);
-		}
+		if (temp == NULL)
+		    goto error;
 		set1->nodeTab = temp;
 		set1->nodeMax *= 2;
 	    }
 	    set1->nodeTab[set1->nodeNr++] = n2;
+            set2->nodeTab[i] = NULL;
 	}
     }
     set2->nodeNr = 0;
     return(set1);
+
+error:
+    xmlXPathFreeNodeSet(set1);
+    xmlXPathNodeSetClear(set2, 1);
+    return(NULL);
 }
 
 /**
@@ -4098,11 +3255,6 @@ xmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
         if (cur->nodeTab[i] == val) break;
 
     if (i >= cur->nodeNr) {	/* not found */
-#ifdef DEBUG
-        xmlGenericError(xmlGenericErrorContext,
-	        "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n",
-		val->name);
-#endif
         return;
     }
     if ((cur->nodeTab[i] != NULL) &&
@@ -4224,75 +3376,6 @@ xmlXPathNodeSetKeepLast(xmlNodeSetPtr set)
     set->nodeNr = 1;
 }
 
-/**
- * xmlXPathFreeValueTree:
- * @obj:  the xmlNodeSetPtr to free
- *
- * Free the NodeSet compound and the actual tree, this is different
- * from xmlXPathFreeNodeSet()
- */
-static void
-xmlXPathFreeValueTree(xmlNodeSetPtr obj) {
-    int i;
-
-    if (obj == NULL) return;
-
-    if (obj->nodeTab != NULL) {
-	for (i = 0;i < obj->nodeNr;i++) {
-	    if (obj->nodeTab[i] != NULL) {
-		if (obj->nodeTab[i]->type == XML_NAMESPACE_DECL) {
-		    xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
-		} else {
-		    xmlFreeNodeList(obj->nodeTab[i]);
-		}
-	    }
-	}
-	xmlFree(obj->nodeTab);
-    }
-    xmlFree(obj);
-}
-
-#if defined(DEBUG) || defined(DEBUG_STEP)
-/**
- * xmlGenericErrorContextNodeSet:
- * @output:  a FILE * for the output
- * @obj:  the xmlNodeSetPtr to display
- *
- * Quick display of a NodeSet
- */
-void
-xmlGenericErrorContextNodeSet(FILE *output, xmlNodeSetPtr obj) {
-    int i;
-
-    if (output == NULL) output = xmlGenericErrorContext;
-    if (obj == NULL)  {
-        fprintf(output, "NodeSet == NULL !\n");
-	return;
-    }
-    if (obj->nodeNr == 0) {
-        fprintf(output, "NodeSet is empty\n");
-	return;
-    }
-    if (obj->nodeTab == NULL) {
-	fprintf(output, " nodeTab == NULL !\n");
-	return;
-    }
-    for (i = 0; i < obj->nodeNr; i++) {
-        if (obj->nodeTab[i] == NULL) {
-	    fprintf(output, " NULL !\n");
-	    return;
-        }
-	if ((obj->nodeTab[i]->type == XML_DOCUMENT_NODE) ||
-	    (obj->nodeTab[i]->type == XML_HTML_DOCUMENT_NODE))
-	    fprintf(output, " /");
-	else if (obj->nodeTab[i]->name == NULL)
-	    fprintf(output, " noname!");
-	else fprintf(output, " %s", obj->nodeTab[i]->name);
-    }
-    fprintf(output, "\n");
-}
-#endif
-
 /**
  * xmlXPathNewNodeSet:
  * @val:  the NodePtr value
@@ -4307,19 +3390,17 @@ xmlXPathNewNodeSet(xmlNodePtr val) {
     xmlXPathObjectPtr ret;
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating nodeset\n");
+    if (ret == NULL)
 	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_NODESET;
     ret->boolval = 0;
-    /* TODO: Check memory error. */
     ret->nodesetval = xmlXPathNodeSetCreate(val);
+    if (ret->nodesetval == NULL) {
+        xmlFree(ret);
+        return(NULL);
+    }
     /* @@ with_ns to check whether namespace nodes should be looked at @@ */
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_NODESET);
-#endif
     return(ret);
 }
 
@@ -4336,19 +3417,11 @@ xmlXPathObjectPtr
 xmlXPathNewValueTree(xmlNodePtr val) {
     xmlXPathObjectPtr ret;
 
-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating result value tree\n");
+    ret = xmlXPathNewNodeSet(val);
+    if (ret == NULL)
 	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
     ret->type = XPATH_XSLT_TREE;
-    ret->boolval = 1;
-    ret->user = (void *) val;
-    ret->nodesetval = xmlXPathNodeSetCreate(val);
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_XSLT_TREE);
-#endif
+
     return(ret);
 }
 
@@ -4365,7 +3438,6 @@ xmlXPathObjectPtr
 xmlXPathNewNodeSetList(xmlNodeSetPtr val)
 {
     xmlXPathObjectPtr ret;
-    int i;
 
     if (val == NULL)
         ret = NULL;
@@ -4374,12 +3446,12 @@ xmlXPathNewNodeSetList(xmlNodeSetPtr val)
     else {
         ret = xmlXPathNewNodeSet(val->nodeTab[0]);
         if (ret) {
-            for (i = 1; i < val->nodeNr; ++i) {
-                /* TODO: Propagate memory error. */
-                if (xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i])
-		    < 0) break;
-	    }
-	}
+            ret->nodesetval = xmlXPathNodeSetMerge(NULL, val);
+            if (ret->nodesetval == NULL) {
+                xmlFree(ret);
+                return(NULL);
+            }
+        }
     }
 
     return (ret);
@@ -4392,6 +3464,8 @@ xmlXPathNewNodeSetList(xmlNodeSetPtr val)
  * Wrap the Nodeset @val in a new xmlXPathObjectPtr
  *
  * Returns the newly created object.
+ *
+ * In case of error the node set is destroyed and NULL is returned.
  */
 xmlXPathObjectPtr
 xmlXPathWrapNodeSet(xmlNodeSetPtr val) {
@@ -4399,15 +3473,12 @@ xmlXPathWrapNodeSet(xmlNodeSetPtr val) {
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
     if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating node set object\n");
+        xmlXPathFreeNodeSet(val);
 	return(NULL);
     }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_NODESET;
     ret->nodesetval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_NODESET);
-#endif
     return(ret);
 }
 
@@ -4421,9 +3492,6 @@ xmlXPathWrapNodeSet(xmlNodeSetPtr val) {
 void
 xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
     if (obj == NULL) return;
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageReleased(NULL, obj->type);
-#endif
     xmlFree(obj);
 }
 
@@ -4447,8 +3515,9 @@ xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
     if (xmlXPathNodeSetIsEmpty(nodes2))
 	return(nodes1);
 
-    /* TODO: Check memory error. */
     ret = xmlXPathNodeSetCreate(NULL);
+    if (ret == NULL)
+        return(NULL);
     if (xmlXPathNodeSetIsEmpty(nodes1))
 	return(ret);
 
@@ -4457,9 +3526,10 @@ xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
     for (i = 0; i < l1; i++) {
 	cur = xmlXPathNodeSetItem(nodes1, i);
 	if (!xmlXPathNodeSetContains(nodes2, cur)) {
-            /* TODO: Propagate memory error. */
-	    if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
-	        break;
+	    if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
+                xmlXPathFreeNodeSet(ret);
+	        return(NULL);
+            }
 	}
     }
     return(ret);
@@ -4494,9 +3564,10 @@ xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
     for (i = 0; i < l1; i++) {
 	cur = xmlXPathNodeSetItem(nodes1, i);
 	if (xmlXPathNodeSetContains(nodes2, cur)) {
-            /* TODO: Propagate memory error. */
-	    if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
-	        break;
+	    if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
+                xmlXPathFreeNodeSet(ret);
+	        return(NULL);
+            }
 	}
     }
     return(ret);
@@ -4532,16 +3603,23 @@ xmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
 	cur = xmlXPathNodeSetItem(nodes, i);
 	strval = xmlXPathCastNodeToString(cur);
 	if (xmlHashLookup(hash, strval) == NULL) {
-	    xmlHashAddEntry(hash, strval, strval);
-            /* TODO: Propagate memory error. */
+	    if (xmlHashAddEntry(hash, strval, strval) < 0) {
+                xmlFree(strval);
+                goto error;
+            }
 	    if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
-	        break;
+	        goto error;
 	} else {
 	    xmlFree(strval);
 	}
     }
     xmlHashFree(hash, xmlHashDefaultDeallocator);
     return(ret);
+
+error:
+    xmlHashFree(hash, xmlHashDefaultDeallocator);
+    xmlXPathFreeNodeSet(ret);
+    return(NULL);
 }
 
 /**
@@ -4627,9 +3705,10 @@ xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
 	cur = xmlXPathNodeSetItem(nodes, i);
 	if (cur == node)
 	    break;
-        /* TODO: Propagate memory error. */
-	if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
-	    break;
+	if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
+            xmlXPathFreeNodeSet(ret);
+	    return(NULL);
+        }
     }
     return(ret);
 }
@@ -4733,9 +3812,10 @@ xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
 	cur = xmlXPathNodeSetItem(nodes, i);
 	if (cur == node)
 	    break;
-        /* TODO: Propagate memory error. */
-	if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
-	    break;
+	if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
+            xmlXPathFreeNodeSet(ret);
+	    return(NULL);
+        }
     }
     xmlXPathNodeSetSort(ret);	/* bug 413451 */
     return(ret);
@@ -4843,6 +3923,8 @@ xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
 int
 xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name,
 		       const xmlChar *ns_uri, xmlXPathFunction f) {
+    int ret;
+
     if (ctxt == NULL)
 	return(-1);
     if (name == NULL)
@@ -4850,13 +3932,21 @@ xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name,
 
     if (ctxt->funcHash == NULL)
 	ctxt->funcHash = xmlHashCreate(0);
-    if (ctxt->funcHash == NULL)
+    if (ctxt->funcHash == NULL) {
+        xmlXPathErrMemory(ctxt);
 	return(-1);
+    }
     if (f == NULL)
         return(xmlHashRemoveEntry2(ctxt->funcHash, name, ns_uri, NULL));
-XML_IGNORE_PEDANTIC_WARNINGS
-    return(xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, (void *) f));
+XML_IGNORE_FPTR_CAST_WARNINGS
+    ret = xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, (void *) f);
 XML_POP_WARNINGS
+    if (ret < 0) {
+        xmlXPathErrMemory(ctxt);
+        return(-1);
+    }
+
+    return(0);
 }
 
 /**
@@ -4937,7 +4027,7 @@ xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
     if (ctxt->funcHash == NULL)
 	return(NULL);
 
-XML_IGNORE_PEDANTIC_WARNINGS
+XML_IGNORE_FPTR_CAST_WARNINGS
     ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);
 XML_POP_WARNINGS
     return(ret);
@@ -5085,8 +4175,7 @@ xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
     if (name == NULL)
 	return(NULL);
 
-    return(xmlXPathCacheObjectCopy(ctxt, (xmlXPathObjectPtr)
-		xmlHashLookup2(ctxt->varHash, name, ns_uri)));
+    return(xmlXPathObjectCopy(xmlHashLookup2(ctxt->varHash, name, ns_uri)));
 }
 
 /**
@@ -5118,6 +4207,8 @@ xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
 int
 xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
 			   const xmlChar *ns_uri) {
+    xmlChar *copy;
+
     if (ctxt == NULL)
 	return(-1);
     if (prefix == NULL)
@@ -5127,13 +4218,27 @@ xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
 
     if (ctxt->nsHash == NULL)
 	ctxt->nsHash = xmlHashCreate(10);
-    if (ctxt->nsHash == NULL)
+    if (ctxt->nsHash == NULL) {
+        xmlXPathErrMemory(ctxt);
 	return(-1);
+    }
     if (ns_uri == NULL)
         return(xmlHashRemoveEntry(ctxt->nsHash, prefix,
 	                          xmlHashDefaultDeallocator));
-    return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) xmlStrdup(ns_uri),
-			      xmlHashDefaultDeallocator));
+
+    copy = xmlStrdup(ns_uri);
+    if (copy == NULL) {
+        xmlXPathErrMemory(ctxt);
+        return(-1);
+    }
+    if (xmlHashUpdateEntry(ctxt->nsHash, prefix, copy,
+                           xmlHashDefaultDeallocator) < 0) {
+        xmlXPathErrMemory(ctxt);
+        xmlFree(copy);
+        return(-1);
+    }
+
+    return(0);
 }
 
 /**
@@ -5153,10 +4258,8 @@ xmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) {
     if (prefix == NULL)
 	return(NULL);
 
-#ifdef XML_XML_NAMESPACE
     if (xmlStrEqual(prefix, (const xmlChar *) "xml"))
 	return(XML_XML_NAMESPACE);
-#endif
 
     if (ctxt->namespaces != NULL) {
 	int i;
@@ -5207,16 +4310,11 @@ xmlXPathNewFloat(double val) {
     xmlXPathObjectPtr ret;
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating float object\n");
+    if (ret == NULL)
 	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_NUMBER;
     ret->floatval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_NUMBER);
-#endif
     return(ret);
 }
 
@@ -5233,16 +4331,11 @@ xmlXPathNewBoolean(int val) {
     xmlXPathObjectPtr ret;
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating boolean object\n");
+    if (ret == NULL)
 	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_BOOLEAN;
     ret->boolval = (val != 0);
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_BOOLEAN);
-#endif
     return(ret);
 }
 
@@ -5259,19 +4352,17 @@ xmlXPathNewString(const xmlChar *val) {
     xmlXPathObjectPtr ret;
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating string object\n");
+    if (ret == NULL)
 	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_STRING;
-    if (val != NULL)
-	ret->stringval = xmlStrdup(val);
-    else
-	ret->stringval = xmlStrdup((const xmlChar *)"");
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING);
-#endif
+    if (val == NULL)
+        val = BAD_CAST "";
+    ret->stringval = xmlStrdup(val);
+    if (ret->stringval == NULL) {
+        xmlFree(ret);
+        return(NULL);
+    }
     return(ret);
 }
 
@@ -5282,6 +4373,8 @@ xmlXPathNewString(const xmlChar *val) {
  * Wraps the @val string into an XPath object.
  *
  * Returns the newly created object.
+ *
+ * Frees @val in case of error.
  */
 xmlXPathObjectPtr
 xmlXPathWrapString (xmlChar *val) {
@@ -5289,15 +4382,12 @@ xmlXPathWrapString (xmlChar *val) {
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
     if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating string object\n");
+        xmlFree(val);
 	return(NULL);
     }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_STRING;
     ret->stringval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING);
-#endif
     return(ret);
 }
 
@@ -5311,20 +4401,7 @@ xmlXPathWrapString (xmlChar *val) {
  */
 xmlXPathObjectPtr
 xmlXPathNewCString(const char *val) {
-    xmlXPathObjectPtr ret;
-
-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating string object\n");
-	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
-    ret->type = XPATH_STRING;
-    ret->stringval = xmlStrdup(BAD_CAST val);
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING);
-#endif
-    return(ret);
+    return(xmlXPathNewString(BAD_CAST val));
 }
 
 /**
@@ -5353,16 +4430,11 @@ xmlXPathWrapExternal (void *val) {
     xmlXPathObjectPtr ret;
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating user object\n");
+    if (ret == NULL)
 	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_USERS;
     ret->user = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_USERS);
-#endif
     return(ret);
 }
 
@@ -5382,14 +4454,9 @@ xmlXPathObjectCopy(xmlXPathObjectPtr val) {
 	return(NULL);
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "copying object\n");
+    if (ret == NULL)
 	return(NULL);
-    }
-    memcpy(ret, val , (size_t) sizeof(xmlXPathObject));
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, val->type);
-#endif
+    memcpy(ret, val , sizeof(xmlXPathObject));
     switch (val->type) {
 	case XPATH_BOOLEAN:
 	case XPATH_NUMBER:
@@ -5400,6 +4467,10 @@ xmlXPathObjectCopy(xmlXPathObjectPtr val) {
 	    break;
 	case XPATH_STRING:
 	    ret->stringval = xmlStrdup(val->stringval);
+            if (ret->stringval == NULL) {
+                xmlFree(ret);
+                return(NULL);
+            }
 	    break;
 	case XPATH_XSLT_TREE:
 #if 0
@@ -5435,8 +4506,11 @@ xmlXPathObjectCopy(xmlXPathObjectPtr val) {
 	    break;
 #endif
 	case XPATH_NODESET:
-            /* TODO: Check memory error. */
 	    ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
+            if (ret->nodesetval == NULL) {
+                xmlFree(ret);
+                return(NULL);
+            }
 	    /* Do not deallocate the copied tree value */
 	    ret->boolval = 0;
 	    break;
@@ -5451,10 +4525,9 @@ xmlXPathObjectCopy(xmlXPathObjectPtr val) {
         case XPATH_USERS:
 	    ret->user = val->user;
 	    break;
-        case XPATH_UNDEFINED:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "xmlXPathObjectCopy: unsupported type %d\n",
-		    val->type);
+        default:
+            xmlFree(ret);
+            ret = NULL;
 	    break;
     }
     return(ret);
@@ -5470,20 +4543,8 @@ void
 xmlXPathFreeObject(xmlXPathObjectPtr obj) {
     if (obj == NULL) return;
     if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
-	if (obj->boolval) {
-#if 0
-	    if (obj->user != NULL) {
-                xmlXPathFreeNodeSet(obj->nodesetval);
-		xmlFreeNodeList((xmlNodePtr) obj->user);
-	    } else
-#endif
-	    obj->type = XPATH_XSLT_TREE; /* TODO: Just for debugging. */
-	    if (obj->nodesetval != NULL)
-		xmlXPathFreeValueTree(obj->nodesetval);
-	} else {
-	    if (obj->nodesetval != NULL)
-		xmlXPathFreeNodeSet(obj->nodesetval);
-	}
+        if (obj->nodesetval != NULL)
+            xmlXPathFreeNodeSet(obj->nodesetval);
 #ifdef LIBXML_XPTR_LOCS_ENABLED
     } else if (obj->type == XPATH_LOCATIONSET) {
 	if (obj->user != NULL)
@@ -5493,9 +4554,6 @@ xmlXPathFreeObject(xmlXPathObjectPtr obj) {
 	if (obj->stringval != NULL)
 	    xmlFree(obj->stringval);
     }
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageReleased(NULL, obj->type);
-#endif
     xmlFree(obj);
 }
 
@@ -5514,12 +4572,6 @@ xmlXPathFreeObjectEntry(void *obj, const xmlChar *name ATTRIBUTE_UNUSED) {
 static void
 xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj)
 {
-#define XP_CACHE_ADD(sl, o) if (sl == NULL) { \
-	sl = xmlPointerListCreate(10); if (sl == NULL) goto free_obj; } \
-    if (xmlPointerListAddSize(sl, obj, 0) == -1) goto free_obj;
-
-#define XP_CACHE_WANTS(sl, n) ((sl == NULL) || ((sl)->number < n))
-
     if (obj == NULL)
 	return;
     if ((ctxt == NULL) || (ctxt->cache == NULL)) {
@@ -5532,20 +4584,11 @@ xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj)
 	    case XPATH_NODESET:
 	    case XPATH_XSLT_TREE:
 		if (obj->nodesetval != NULL) {
-		    if (obj->boolval) {
-			/*
-			* It looks like the @boolval is used for
-			* evaluation if this an XSLT Result Tree Fragment.
-			* TODO: Check if this assumption is correct.
-			*/
-			obj->type = XPATH_XSLT_TREE; /* just for debugging */
-			xmlXPathFreeValueTree(obj->nodesetval);
-			obj->nodesetval = NULL;
-		    } else if ((obj->nodesetval->nodeMax <= 40) &&
-			(XP_CACHE_WANTS(cache->nodesetObjs,
-					cache->maxNodeset)))
-		    {
-			XP_CACHE_ADD(cache->nodesetObjs, obj);
+		    if ((obj->nodesetval->nodeMax <= 40) &&
+			(cache->numNodeset < cache->maxNodeset)) {
+                        obj->stringval = (void *) cache->nodesetObjs;
+                        cache->nodesetObjs = obj;
+                        cache->numNodeset += 1;
 			goto obj_cached;
 		    } else {
 			xmlXPathFreeNodeSet(obj->nodesetval);
@@ -5556,23 +4599,10 @@ xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj)
 	    case XPATH_STRING:
 		if (obj->stringval != NULL)
 		    xmlFree(obj->stringval);
-
-		if (XP_CACHE_WANTS(cache->stringObjs, cache->maxString)) {
-		    XP_CACHE_ADD(cache->stringObjs, obj);
-		    goto obj_cached;
-		}
+                obj->stringval = NULL;
 		break;
 	    case XPATH_BOOLEAN:
-		if (XP_CACHE_WANTS(cache->booleanObjs, cache->maxBoolean)) {
-		    XP_CACHE_ADD(cache->booleanObjs, obj);
-		    goto obj_cached;
-		}
-		break;
 	    case XPATH_NUMBER:
-		if (XP_CACHE_WANTS(cache->numberObjs, cache->maxNumber)) {
-		    XP_CACHE_ADD(cache->numberObjs, obj);
-		    goto obj_cached;
-		}
 		break;
 #ifdef LIBXML_XPTR_LOCS_ENABLED
 	    case XPATH_LOCATIONSET:
@@ -5588,27 +4618,22 @@ xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj)
 	/*
 	* Fallback to adding to the misc-objects slot.
 	*/
-	if (XP_CACHE_WANTS(cache->miscObjs, cache->maxMisc)) {
-	    XP_CACHE_ADD(cache->miscObjs, obj);
-	} else
+        if (cache->numMisc >= cache->maxMisc)
 	    goto free_obj;
+        obj->stringval = (void *) cache->miscObjs;
+        cache->miscObjs = obj;
+        cache->numMisc += 1;
 
 obj_cached:
-
-#ifdef XP_DEBUG_OBJ_USAGE
-	xmlXPathDebugObjUsageReleased(ctxt, obj->type);
-#endif
-
+        obj->boolval = 0;
 	if (obj->nodesetval != NULL) {
 	    xmlNodeSetPtr tmpset = obj->nodesetval;
 
 	    /*
-	    * TODO: Due to those nasty ns-nodes, we need to traverse
-	    *  the list and free the ns-nodes.
-	    * URGENT TODO: Check if it's actually slowing things down.
-	    *  Maybe we shouldn't try to preserve the list.
+	    * Due to those nasty ns-nodes, we need to traverse
+	    * the list and free the ns-nodes.
 	    */
-	    if (tmpset->nodeNr > 1) {
+	    if (tmpset->nodeNr > 0) {
 		int i;
 		xmlNodePtr node;
 
@@ -5620,16 +4645,9 @@ obj_cached:
 			xmlXPathNodeSetFreeNs((xmlNsPtr) node);
 		    }
 		}
-	    } else if (tmpset->nodeNr == 1) {
-		if ((tmpset->nodeTab[0] != NULL) &&
-		    (tmpset->nodeTab[0]->type == XML_NAMESPACE_DECL))
-		    xmlXPathNodeSetFreeNs((xmlNsPtr) tmpset->nodeTab[0]);
 	    }
 	    tmpset->nodeNr = 0;
-	    memset(obj, 0, sizeof(xmlXPathObject));
-	    obj->nodesetval = tmpset;
-	} else
-	    memset(obj, 0, sizeof(xmlXPathObject));
+        }
 
 	return;
 
@@ -5639,9 +4657,6 @@ free_obj:
 	*/
 	if (obj->nodesetval != NULL)
 	    xmlXPathFreeNodeSet(obj->nodesetval);
-#ifdef XP_DEBUG_OBJ_USAGE
-	xmlXPathDebugObjUsageReleased(NULL, obj->type);
-#endif
 	xmlFree(obj);
     }
     return;
@@ -5717,10 +4732,7 @@ xmlXPathCastNumberToString (double val) {
  */
 xmlChar *
 xmlXPathCastNodeToString (xmlNodePtr node) {
-xmlChar *ret;
-    if ((ret = xmlNodeGetContent(node)) == NULL)
-	ret = xmlStrdup((const xmlChar *) "");
-    return(ret);
+    return(xmlNodeGetContent(node));
 }
 
 /**
@@ -5758,9 +4770,6 @@ xmlXPathCastToString(xmlXPathObjectPtr val) {
 	return(xmlStrdup((const xmlChar *) ""));
     switch (val->type) {
 	case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	    xmlGenericError(xmlGenericErrorContext, "String: undefined\n");
-#endif
 	    ret = xmlStrdup((const xmlChar *) "");
 	    break;
         case XPATH_NODESET:
@@ -5782,7 +4791,7 @@ xmlXPathCastToString(xmlXPathObjectPtr val) {
 	case XPATH_RANGE:
 	case XPATH_LOCATIONSET:
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
-	    TODO
+	    /* TODO */
 	    ret = xmlStrdup((const xmlChar *) "");
 	    break;
     }
@@ -5807,9 +4816,6 @@ xmlXPathConvertString(xmlXPathObjectPtr val) {
 
     switch (val->type) {
     case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
-#endif
 	break;
     case XPATH_NODESET:
     case XPATH_XSLT_TREE:
@@ -5829,7 +4835,7 @@ xmlXPathConvertString(xmlXPathObjectPtr val) {
     case XPATH_RANGE:
     case XPATH_LOCATIONSET:
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
-	TODO;
+	/* TODO */
 	break;
     }
     xmlXPathFreeObject(val);
@@ -5867,29 +4873,44 @@ xmlXPathCastStringToNumber(const xmlChar * val) {
 }
 
 /**
- * xmlXPathCastNodeToNumber:
+ * xmlXPathNodeToNumberInternal:
  * @node:  a node
  *
  * Converts a node to its number value
  *
  * Returns the number value
  */
-double
-xmlXPathCastNodeToNumber (xmlNodePtr node) {
+static double
+xmlXPathNodeToNumberInternal(xmlXPathParserContextPtr ctxt, xmlNodePtr node) {
     xmlChar *strval;
     double ret;
 
     if (node == NULL)
 	return(xmlXPathNAN);
     strval = xmlXPathCastNodeToString(node);
-    if (strval == NULL)
+    if (strval == NULL) {
+        xmlXPathPErrMemory(ctxt);
 	return(xmlXPathNAN);
+    }
     ret = xmlXPathCastStringToNumber(strval);
     xmlFree(strval);
 
     return(ret);
 }
 
+/**
+ * xmlXPathCastNodeToNumber:
+ * @node:  a node
+ *
+ * Converts a node to its number value
+ *
+ * Returns the number value
+ */
+double
+xmlXPathCastNodeToNumber (xmlNodePtr node) {
+    return(xmlXPathNodeToNumberInternal(NULL, node));
+}
+
 /**
  * xmlXPathCastNodeSetToNumber:
  * @ns:  a node-set
@@ -5921,41 +4942,7 @@ xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
  */
 double
 xmlXPathCastToNumber(xmlXPathObjectPtr val) {
-    double ret = 0.0;
-
-    if (val == NULL)
-	return(xmlXPathNAN);
-    switch (val->type) {
-    case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
-#endif
-	ret = xmlXPathNAN;
-	break;
-    case XPATH_NODESET:
-    case XPATH_XSLT_TREE:
-	ret = xmlXPathCastNodeSetToNumber(val->nodesetval);
-	break;
-    case XPATH_STRING:
-	ret = xmlXPathCastStringToNumber(val->stringval);
-	break;
-    case XPATH_NUMBER:
-	ret = val->floatval;
-	break;
-    case XPATH_BOOLEAN:
-	ret = xmlXPathCastBooleanToNumber(val->boolval);
-	break;
-    case XPATH_USERS:
-#ifdef LIBXML_XPTR_LOCS_ENABLED
-    case XPATH_POINT:
-    case XPATH_RANGE:
-    case XPATH_LOCATIONSET:
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
-	TODO;
-	ret = xmlXPathNAN;
-	break;
-    }
-    return(ret);
+    return(xmlXPathCastToNumberInternal(NULL, val));
 }
 
 /**
@@ -6041,9 +5028,6 @@ xmlXPathCastToBoolean (xmlXPathObjectPtr val) {
 	return(0);
     switch (val->type) {
     case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext, "BOOLEAN: undefined\n");
-#endif
 	ret = 0;
 	break;
     case XPATH_NODESET:
@@ -6065,7 +5049,7 @@ xmlXPathCastToBoolean (xmlXPathObjectPtr val) {
     case XPATH_RANGE:
     case XPATH_LOCATIONSET:
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
-	TODO;
+	/* TODO */
 	ret = 0;
 	break;
     }
@@ -6114,11 +5098,9 @@ xmlXPathNewContext(xmlDocPtr doc) {
     xmlXPathContextPtr ret;
 
     ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
-    if (ret == NULL) {
-        xmlXPathErrMemory(NULL, "creating context\n");
+    if (ret == NULL)
 	return(NULL);
-    }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathContext));
+    memset(ret, 0 , sizeof(xmlXPathContext));
     ret->doc = doc;
     ret->node = NULL;
 
@@ -6128,8 +5110,6 @@ xmlXPathNewContext(xmlDocPtr doc) {
     ret->max_types = 0;
     ret->types = NULL;
 
-    ret->funcHash = xmlHashCreate(0);
-
     ret->nb_axis = 0;
     ret->max_axis = 0;
     ret->axis = NULL;
@@ -6149,6 +5129,11 @@ xmlXPathNewContext(xmlDocPtr doc) {
 
     xmlXPathRegisterAllFunctions(ret);
 
+    if (ret->lastError.code != XML_ERR_OK) {
+	xmlXPathFreeContext(ret);
+	return(NULL);
+    }
+
     return(ret);
 }
 
@@ -6171,43 +5156,33 @@ xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
     xmlFree(ctxt);
 }
 
+/**
+ * xmlXPathSetErrorHandler:
+ * @ctxt:  the XPath context
+ * @handler:  error handler
+ * @data:  user data which will be passed to the handler
+ *
+ * Register a callback function that will be called on errors and
+ * warnings. If handler is NULL, the error handler will be deactivated.
+ *
+ * Available since 2.13.0.
+ */
+void
+xmlXPathSetErrorHandler(xmlXPathContextPtr ctxt,
+                        xmlStructuredErrorFunc handler, void *data) {
+    if (ctxt == NULL)
+        return;
+
+    ctxt->error = handler;
+    ctxt->userData = data;
+}
+
 /************************************************************************
  *									*
  *		Routines to handle XPath parser contexts		*
  *									*
  ************************************************************************/
 
-#define CHECK_CTXT(ctxt)						\
-    if (ctxt == NULL) {						\
-	__xmlRaiseError(NULL, NULL, NULL,				\
-		NULL, NULL, XML_FROM_XPATH,				\
-		XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL,			\
-		__FILE__, __LINE__,					\
-		NULL, NULL, NULL, 0, 0,					\
-		"NULL context pointer\n");				\
-	return(NULL);							\
-    }									\
-
-#define CHECK_CTXT_NEG(ctxt)						\
-    if (ctxt == NULL) {						\
-	__xmlRaiseError(NULL, NULL, NULL,				\
-		NULL, NULL, XML_FROM_XPATH,				\
-		XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL,			\
-		__FILE__, __LINE__,					\
-		NULL, NULL, NULL, 0, 0,					\
-		"NULL context pointer\n");				\
-	return(-1);							\
-    }									\
-
-
-#define CHECK_CONTEXT(ctxt)						\
-    if ((ctxt == NULL) || (ctxt->doc == NULL) ||			\
-        (ctxt->doc->children == NULL)) {				\
-	xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_INVALID_CTXT);	\
-	return(NULL);							\
-    }
-
-
 /**
  * xmlXPathNewParserContext:
  * @str:  the XPath expression
@@ -6223,15 +5198,16 @@ xmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) {
 
     ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
     if (ret == NULL) {
-        xmlXPathErrMemory(ctxt, "creating parser context\n");
+        xmlXPathErrMemory(ctxt);
 	return(NULL);
     }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
+    memset(ret, 0 , sizeof(xmlXPathParserContext));
     ret->cur = ret->base = str;
     ret->context = ctxt;
 
     ret->comp = xmlXPathNewCompExpr();
     if (ret->comp == NULL) {
+        xmlXPathErrMemory(ctxt);
 	xmlFree(ret->valueTab);
 	xmlFree(ret);
 	return(NULL);
@@ -6259,23 +5235,22 @@ xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
 
     ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
     if (ret == NULL) {
-        xmlXPathErrMemory(ctxt, "creating evaluation context\n");
+        xmlXPathErrMemory(ctxt);
 	return(NULL);
     }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
+    memset(ret, 0 , sizeof(xmlXPathParserContext));
 
     /* Allocate the value stack */
     ret->valueTab = (xmlXPathObjectPtr *)
                      xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
     if (ret->valueTab == NULL) {
 	xmlFree(ret);
-	xmlXPathErrMemory(ctxt, "creating evaluation context\n");
+	xmlXPathErrMemory(ctxt);
 	return(NULL);
     }
     ret->valueNr = 0;
     ret->valueMax = 10;
     ret->value = NULL;
-    ret->valueFrame = 0;
 
     ret->context = ctxt;
     ret->comp = comp;
@@ -6360,16 +5335,14 @@ xmlXPathNodeValHash(xmlNodePtr node) {
 		return(0);
 	    if (string[0] == 0)
 		return(0);
-	    return(((unsigned int) string[0]) +
-		   (((unsigned int) string[1]) << 8));
+	    return(string[0] + (string[1] << 8));
 	case XML_NAMESPACE_DECL:
 	    string = ((xmlNsPtr)node)->href;
 	    if (string == NULL)
 		return(0);
 	    if (string[0] == 0)
 		return(0);
-	    return(((unsigned int) string[0]) +
-		   (((unsigned int) string[1]) << 8));
+	    return(string[0] + (string[1] << 8));
 	case XML_ATTRIBUTE_NODE:
 	    tmp = ((xmlAttrPtr) node)->children;
 	    break;
@@ -6391,24 +5364,24 @@ xmlXPathNodeValHash(xmlNodePtr node) {
 	}
 	if ((string != NULL) && (string[0] != 0)) {
 	    if (len == 1) {
-		return(ret + (((unsigned int) string[0]) << 8));
+		return(ret + (string[0] << 8));
 	    }
 	    if (string[1] == 0) {
 		len = 1;
-		ret = (unsigned int) string[0];
+		ret = string[0];
 	    } else {
-		return(((unsigned int) string[0]) +
-		       (((unsigned int) string[1]) << 8));
+		return(string[0] + (string[1] << 8));
 	    }
 	}
 	/*
 	 * Skip to next node
 	 */
-	if ((tmp->children != NULL) && (tmp->type != XML_DTD_NODE)) {
-	    if (tmp->children->type != XML_ENTITY_DECL) {
-		tmp = tmp->children;
-		continue;
-	    }
+        if ((tmp->children != NULL) &&
+            (tmp->type != XML_DTD_NODE) &&
+            (tmp->type != XML_ENTITY_REF_NODE) &&
+            (tmp->children->type != XML_ENTITY_DECL)) {
+            tmp = tmp->children;
+            continue;
 	}
 	if (tmp == node)
 	    break;
@@ -6447,11 +5420,10 @@ xmlXPathNodeValHash(xmlNodePtr node) {
 static unsigned int
 xmlXPathStringHash(const xmlChar * string) {
     if (string == NULL)
-	return((unsigned int) 0);
+	return(0);
     if (string[0] == 0)
 	return(0);
-    return(((unsigned int) string[0]) +
-	   (((unsigned int) string[1]) << 8));
+    return(string[0] + (string[1] << 8));
 }
 
 /**
@@ -6494,15 +5466,16 @@ xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict,
 	for (i = 0;i < ns->nodeNr;i++) {
 	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
 	     if (str2 != NULL) {
-		 valuePush(ctxt,
-			   xmlXPathCacheNewString(ctxt->context, str2));
+		 valuePush(ctxt, xmlXPathCacheNewString(ctxt, str2));
 		 xmlFree(str2);
 		 xmlXPathNumberFunction(ctxt, 1);
-		 valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt->context, f));
+		 valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, f));
 		 ret = xmlXPathCompareValues(ctxt, inf, strict);
 		 if (ret)
 		     break;
-	     }
+	     } else {
+                 xmlXPathPErrMemory(ctxt);
+             }
 	}
     }
     xmlXPathReleaseObject(ctxt->context, arg);
@@ -6550,13 +5523,15 @@ xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
 	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
 	     if (str2 != NULL) {
 		 valuePush(ctxt,
-			   xmlXPathCacheNewString(ctxt->context, str2));
+			   xmlXPathCacheNewString(ctxt, str2));
 		 xmlFree(str2);
-		 valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt->context, s));
+		 valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, s));
 		 ret = xmlXPathCompareValues(ctxt, inf, strict);
 		 if (ret)
 		     break;
-	     }
+	     } else {
+                 xmlXPathPErrMemory(ctxt);
+             }
 	}
     }
     xmlXPathReleaseObject(ctxt->context, arg);
@@ -6593,7 +5568,7 @@ xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
  * and then the comparison must be done when possible
  */
 static int
-xmlXPathCompareNodeSets(int inf, int strict,
+xmlXPathCompareNodeSets(xmlXPathParserContextPtr ctxt, int inf, int strict,
 	                xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
     int i, j, init = 0;
     double val1;
@@ -6630,19 +5605,19 @@ xmlXPathCompareNodeSets(int inf, int strict,
 
     values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double));
     if (values2 == NULL) {
-        /* TODO: Propagate memory error. */
-        xmlXPathErrMemory(NULL, "comparing nodesets\n");
+        xmlXPathPErrMemory(ctxt);
 	xmlXPathFreeObject(arg1);
 	xmlXPathFreeObject(arg2);
 	return(0);
     }
     for (i = 0;i < ns1->nodeNr;i++) {
-	val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]);
+	val1 = xmlXPathNodeToNumberInternal(ctxt, ns1->nodeTab[i]);
 	if (xmlXPathIsNaN(val1))
 	    continue;
 	for (j = 0;j < ns2->nodeNr;j++) {
 	    if (init == 0) {
-		values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]);
+		values2[j] = xmlXPathNodeToNumberInternal(ctxt,
+                                                          ns2->nodeTab[j]);
 	    }
 	    if (xmlXPathIsNaN(values2[j]))
 		continue;
@@ -6700,7 +5675,7 @@ xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
 	    return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val));
         case XPATH_NODESET:
         case XPATH_XSLT_TREE:
-	    return(xmlXPathCompareNodeSets(inf, strict, arg, val));
+	    return(xmlXPathCompareNodeSets(ctxt, inf, strict, arg, val));
         case XPATH_STRING:
 	    return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val));
         case XPATH_BOOLEAN:
@@ -6709,10 +5684,6 @@ xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
 	    valuePush(ctxt, val);
 	    return(xmlXPathCompareValues(ctxt, inf, strict));
 	default:
-            xmlGenericError(xmlGenericErrorContext,
-                    "xmlXPathCompareNodeSetValue: Can't compare node set "
-                    "and object of type %d\n",
-                    val->type);
             xmlXPathReleaseObject(ctxt->context, arg);
             xmlXPathReleaseObject(ctxt->context, val);
             XP_ERROR0(XPATH_INVALID_TYPE);
@@ -6735,7 +5706,8 @@ xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
  * Returns 0 or 1 depending on the results of the test.
  */
 static int
-xmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar * str, int neq)
+xmlXPathEqualNodeSetString(xmlXPathParserContextPtr ctxt,
+                           xmlXPathObjectPtr arg, const xmlChar * str, int neq)
 {
     int i;
     xmlNodeSetPtr ns;
@@ -6756,22 +5728,20 @@ xmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar * str, int neq)
     for (i = 0; i < ns->nodeNr; i++) {
         if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) {
             str2 = xmlNodeGetContent(ns->nodeTab[i]);
-            if ((str2 != NULL) && (xmlStrEqual(str, str2))) {
+            if (str2 == NULL) {
+                xmlXPathPErrMemory(ctxt);
+                return(0);
+            }
+            if (xmlStrEqual(str, str2)) {
                 xmlFree(str2);
 		if (neq)
 		    continue;
                 return (1);
-	    } else if ((str2 == NULL) && (xmlStrEqual(str, BAD_CAST ""))) {
-		if (neq)
-		    continue;
-                return (1);
             } else if (neq) {
-		if (str2 != NULL)
-		    xmlFree(str2);
+		xmlFree(str2);
 		return (1);
 	    }
-            if (str2 != NULL)
-                xmlFree(str2);
+            xmlFree(str2);
         } else if (neq)
 	    return (1);
     }
@@ -6811,9 +5781,10 @@ xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,
 	for (i=0;i<ns->nodeNr;i++) {
 	    str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
 	    if (str2 != NULL) {
-		valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, str2));
+		valuePush(ctxt, xmlXPathCacheNewString(ctxt, str2));
 		xmlFree(str2);
 		xmlXPathNumberFunction(ctxt, 1);
+                CHECK_ERROR0;
 		val = valuePop(ctxt);
 		v = val->floatval;
 		xmlXPathReleaseObject(ctxt->context, val);
@@ -6829,7 +5800,9 @@ xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,
 		    if (neq)
 			ret = 1;
 		}
-	    }
+	    } else {
+                xmlXPathPErrMemory(ctxt);
+            }
 	}
     }
 
@@ -6855,7 +5828,8 @@ xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,
  * Returns 0 or 1 depending on the results of the test.
  */
 static int
-xmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) {
+xmlXPathEqualNodeSets(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr arg1,
+                      xmlXPathObjectPtr arg2, int neq) {
     int i, j;
     unsigned int *hashs1;
     unsigned int *hashs2;
@@ -6891,30 +5865,26 @@ xmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) {
 
     values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *));
     if (values1 == NULL) {
-        /* TODO: Propagate memory error. */
-        xmlXPathErrMemory(NULL, "comparing nodesets\n");
+        xmlXPathPErrMemory(ctxt);
 	return(0);
     }
     hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int));
     if (hashs1 == NULL) {
-        /* TODO: Propagate memory error. */
-        xmlXPathErrMemory(NULL, "comparing nodesets\n");
+        xmlXPathPErrMemory(ctxt);
 	xmlFree(values1);
 	return(0);
     }
     memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *));
     values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *));
     if (values2 == NULL) {
-        /* TODO: Propagate memory error. */
-        xmlXPathErrMemory(NULL, "comparing nodesets\n");
+        xmlXPathPErrMemory(ctxt);
 	xmlFree(hashs1);
 	xmlFree(values1);
 	return(0);
     }
     hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int));
     if (hashs2 == NULL) {
-        /* TODO: Propagate memory error. */
-        xmlXPathErrMemory(NULL, "comparing nodesets\n");
+        xmlXPathPErrMemory(ctxt);
 	xmlFree(hashs1);
 	xmlFree(values1);
 	xmlFree(values2);
@@ -6933,10 +5903,16 @@ xmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) {
 		}
 	    }
 	    else {
-		if (values1[i] == NULL)
+		if (values1[i] == NULL) {
 		    values1[i] = xmlNodeGetContent(ns1->nodeTab[i]);
-		if (values2[j] == NULL)
+                    if (values1[i] == NULL)
+                        xmlXPathPErrMemory(ctxt);
+                }
+		if (values2[j] == NULL) {
 		    values2[j] = xmlNodeGetContent(ns2->nodeTab[j]);
+                    if (values2[j] == NULL)
+                        xmlXPathPErrMemory(ctxt);
+                }
 		ret = xmlStrEqual(values1[i], values2[j]) ^ neq;
 		if (ret)
 		    break;
@@ -6968,25 +5944,12 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
      */
     switch (arg1->type) {
         case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	    xmlGenericError(xmlGenericErrorContext,
-		    "Equal: undefined\n");
-#endif
 	    break;
         case XPATH_BOOLEAN:
 	    switch (arg2->type) {
 	        case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-		    xmlGenericError(xmlGenericErrorContext,
-			    "Equal: undefined\n");
-#endif
 		    break;
 		case XPATH_BOOLEAN:
-#ifdef DEBUG_EXPR
-		    xmlGenericError(xmlGenericErrorContext,
-			    "Equal: %d boolean %d \n",
-			    arg1->boolval, arg2->boolval);
-#endif
 		    ret = (arg1->boolval == arg2->boolval);
 		    break;
 		case XPATH_NUMBER:
@@ -7006,7 +5969,7 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
 		case XPATH_RANGE:
 		case XPATH_LOCATIONSET:
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
-		    TODO
+		    /* TODO */
 		    break;
 		case XPATH_NODESET:
 		case XPATH_XSLT_TREE:
@@ -7016,10 +5979,6 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
         case XPATH_NUMBER:
 	    switch (arg2->type) {
 	        case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-		    xmlGenericError(xmlGenericErrorContext,
-			    "Equal: undefined\n");
-#endif
 		    break;
 		case XPATH_BOOLEAN:
 		    ret = (arg2->boolval==
@@ -7029,6 +5988,8 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
 		    valuePush(ctxt, arg2);
 		    xmlXPathNumberFunction(ctxt, 1);
 		    arg2 = valuePop(ctxt);
+                    if (ctxt->error)
+                        break;
                     /* Falls through. */
 		case XPATH_NUMBER:
 		    /* Hand check NaN and Infinity equalities */
@@ -7065,7 +6026,7 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
 		case XPATH_RANGE:
 		case XPATH_LOCATIONSET:
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
-		    TODO
+		    /* TODO */
 		    break;
 		case XPATH_NODESET:
 		case XPATH_XSLT_TREE:
@@ -7075,10 +6036,6 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
         case XPATH_STRING:
 	    switch (arg2->type) {
 	        case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-		    xmlGenericError(xmlGenericErrorContext,
-			    "Equal: undefined\n");
-#endif
 		    break;
 		case XPATH_BOOLEAN:
 		    if ((arg1->stringval == NULL) ||
@@ -7094,6 +6051,8 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
 		    valuePush(ctxt, arg1);
 		    xmlXPathNumberFunction(ctxt, 1);
 		    arg1 = valuePop(ctxt);
+                    if (ctxt->error)
+                        break;
 		    /* Hand check NaN and Infinity equalities */
 		    if (xmlXPathIsNaN(arg1->floatval) ||
 			    xmlXPathIsNaN(arg2->floatval)) {
@@ -7128,7 +6087,7 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
 		case XPATH_RANGE:
 		case XPATH_LOCATIONSET:
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
-		    TODO
+		    /* TODO */
 		    break;
 		case XPATH_NODESET:
 		case XPATH_XSLT_TREE:
@@ -7141,7 +6100,7 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
 	case XPATH_RANGE:
 	case XPATH_LOCATIONSET:
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
-	    TODO
+	    /* TODO */
 	    break;
 	case XPATH_NODESET:
 	case XPATH_XSLT_TREE:
@@ -7177,10 +6136,6 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
     }
 
     if (arg1 == arg2) {
-#ifdef DEBUG_EXPR
-        xmlGenericError(xmlGenericErrorContext,
-		"Equal: by pointer\n");
-#endif
 	xmlXPathFreeObject(arg1);
         return(1);
     }
@@ -7200,14 +6155,10 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
 	}
 	switch (arg2->type) {
 	    case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-		xmlGenericError(xmlGenericErrorContext,
-			"Equal: undefined\n");
-#endif
 		break;
 	    case XPATH_NODESET:
 	    case XPATH_XSLT_TREE:
-		ret = xmlXPathEqualNodeSets(arg1, arg2, 0);
+		ret = xmlXPathEqualNodeSets(ctxt, arg1, arg2, 0);
 		break;
 	    case XPATH_BOOLEAN:
 		if ((arg1->nodesetval == NULL) ||
@@ -7220,7 +6171,8 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
 		ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0);
 		break;
 	    case XPATH_STRING:
-		ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval, 0);
+		ret = xmlXPathEqualNodeSetString(ctxt, arg1,
+                                                 arg2->stringval, 0);
 		break;
 	    case XPATH_USERS:
 #ifdef LIBXML_XPTR_LOCS_ENABLED
@@ -7228,7 +6180,7 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
 	    case XPATH_RANGE:
 	    case XPATH_LOCATIONSET:
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
-		TODO
+		/* TODO */
 		break;
 	}
 	xmlXPathReleaseObject(ctxt->context, arg1);
@@ -7264,10 +6216,6 @@ xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
     }
 
     if (arg1 == arg2) {
-#ifdef DEBUG_EXPR
-        xmlGenericError(xmlGenericErrorContext,
-		"NotEqual: by pointer\n");
-#endif
 	xmlXPathReleaseObject(ctxt->context, arg1);
         return(0);
     }
@@ -7287,14 +6235,10 @@ xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
 	}
 	switch (arg2->type) {
 	    case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-		xmlGenericError(xmlGenericErrorContext,
-			"NotEqual: undefined\n");
-#endif
 		break;
 	    case XPATH_NODESET:
 	    case XPATH_XSLT_TREE:
-		ret = xmlXPathEqualNodeSets(arg1, arg2, 1);
+		ret = xmlXPathEqualNodeSets(ctxt, arg1, arg2, 1);
 		break;
 	    case XPATH_BOOLEAN:
 		if ((arg1->nodesetval == NULL) ||
@@ -7307,7 +6251,8 @@ xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
 		ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1);
 		break;
 	    case XPATH_STRING:
-		ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval,1);
+		ret = xmlXPathEqualNodeSetString(ctxt, arg1,
+                                                 arg2->stringval, 1);
 		break;
 	    case XPATH_USERS:
 #ifdef LIBXML_XPTR_LOCS_ENABLED
@@ -7315,7 +6260,7 @@ xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
 	    case XPATH_RANGE:
 	    case XPATH_LOCATIONSET:
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
-		TODO
+		/* TODO */
 		break;
 	}
 	xmlXPathReleaseObject(ctxt->context, arg1);
@@ -7375,7 +6320,7 @@ xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
 	 */
 	if (((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE)) &&
 	  ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE))){
-	    ret = xmlXPathCompareNodeSets(inf, strict, arg1, arg2);
+	    ret = xmlXPathCompareNodeSets(ctxt, inf, strict, arg1, arg2);
 	} else {
 	    if ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
 		ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict,
@@ -7393,21 +6338,13 @@ xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
 	xmlXPathNumberFunction(ctxt, 1);
 	arg1 = valuePop(ctxt);
     }
-    if (arg1->type != XPATH_NUMBER) {
-	xmlXPathFreeObject(arg1);
-	xmlXPathFreeObject(arg2);
-	XP_ERROR0(XPATH_INVALID_OPERAND);
-    }
     if (arg2->type != XPATH_NUMBER) {
 	valuePush(ctxt, arg2);
 	xmlXPathNumberFunction(ctxt, 1);
 	arg2 = valuePop(ctxt);
     }
-    if (arg2->type != XPATH_NUMBER) {
-	xmlXPathReleaseObject(ctxt->context, arg1);
-	xmlXPathReleaseObject(ctxt->context, arg2);
-	XP_ERROR0(XPATH_INVALID_OPERAND);
-    }
+    if (ctxt->error)
+        goto error;
     /*
      * Add tests for infinity and nan
      * => feedback on 3.4 for Inf and NaN
@@ -7457,6 +6394,7 @@ xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
 	    }
 	}
     }
+error:
     xmlXPathReleaseObject(ctxt->context, arg1);
     xmlXPathReleaseObject(ctxt->context, arg2);
     return(ret);
@@ -7494,7 +6432,7 @@ xmlXPathAddValues(xmlXPathParserContextPtr ctxt) {
     arg = valuePop(ctxt);
     if (arg == NULL)
 	XP_ERROR(XPATH_INVALID_OPERAND);
-    val = xmlXPathCastToNumber(arg);
+    val = xmlXPathCastToNumberInternal(ctxt, arg);
     xmlXPathReleaseObject(ctxt->context, arg);
     CAST_TO_NUMBER;
     CHECK_TYPE(XPATH_NUMBER);
@@ -7517,7 +6455,7 @@ xmlXPathSubValues(xmlXPathParserContextPtr ctxt) {
     arg = valuePop(ctxt);
     if (arg == NULL)
 	XP_ERROR(XPATH_INVALID_OPERAND);
-    val = xmlXPathCastToNumber(arg);
+    val = xmlXPathCastToNumberInternal(ctxt, arg);
     xmlXPathReleaseObject(ctxt->context, arg);
     CAST_TO_NUMBER;
     CHECK_TYPE(XPATH_NUMBER);
@@ -7540,7 +6478,7 @@ xmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
     arg = valuePop(ctxt);
     if (arg == NULL)
 	XP_ERROR(XPATH_INVALID_OPERAND);
-    val = xmlXPathCastToNumber(arg);
+    val = xmlXPathCastToNumberInternal(ctxt, arg);
     xmlXPathReleaseObject(ctxt->context, arg);
     CAST_TO_NUMBER;
     CHECK_TYPE(XPATH_NUMBER);
@@ -7564,7 +6502,7 @@ xmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
     arg = valuePop(ctxt);
     if (arg == NULL)
 	XP_ERROR(XPATH_INVALID_OPERAND);
-    val = xmlXPathCastToNumber(arg);
+    val = xmlXPathCastToNumberInternal(ctxt, arg);
     xmlXPathReleaseObject(ctxt->context, arg);
     CAST_TO_NUMBER;
     CHECK_TYPE(XPATH_NUMBER);
@@ -7587,7 +6525,7 @@ xmlXPathModValues(xmlXPathParserContextPtr ctxt) {
     arg = valuePop(ctxt);
     if (arg == NULL)
 	XP_ERROR(XPATH_INVALID_OPERAND);
-    arg2 = xmlXPathCastToNumber(arg);
+    arg2 = xmlXPathCastToNumberInternal(ctxt, arg);
     xmlXPathReleaseObject(ctxt->context, arg);
     CAST_TO_NUMBER;
     CHECK_TYPE(XPATH_NUMBER);
@@ -8391,14 +7329,17 @@ xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
     if (cur == NULL) {
         if (ctxt->context->tmpNsList != NULL)
 	    xmlFree(ctxt->context->tmpNsList);
-	ctxt->context->tmpNsList =
-	    xmlGetNsList(ctxt->context->doc, ctxt->context->node);
 	ctxt->context->tmpNsNr = 0;
-	if (ctxt->context->tmpNsList != NULL) {
-	    while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) {
-		ctxt->context->tmpNsNr++;
-	    }
-	}
+        if (xmlGetNsListSafe(ctxt->context->doc, ctxt->context->node,
+                             &ctxt->context->tmpNsList) < 0) {
+            xmlXPathPErrMemory(ctxt);
+            return(NULL);
+        }
+        if (ctxt->context->tmpNsList != NULL) {
+            while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) {
+                ctxt->context->tmpNsNr++;
+            }
+        }
 	return((xmlNodePtr) xmlXPathXMLNamespace);
     }
     if (ctxt->context->tmpNsNr > 0) {
@@ -8461,8 +7402,8 @@ void
 xmlXPathRoot(xmlXPathParserContextPtr ctxt) {
     if ((ctxt == NULL) || (ctxt->context == NULL))
 	return;
-    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
-	(xmlNodePtr) ctxt->context->doc));
+    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
+                                            (xmlNodePtr) ctxt->context->doc));
 }
 
 /************************************************************************
@@ -8487,12 +7428,7 @@ xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     CHECK_ARITY(0);
     if (ctxt->context->contextSize >= 0) {
 	valuePush(ctxt,
-	    xmlXPathCacheNewFloat(ctxt->context,
-		(double) ctxt->context->contextSize));
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext,
-		"last() : %d\n", ctxt->context->contextSize);
-#endif
+	    xmlXPathCacheNewFloat(ctxt, (double) ctxt->context->contextSize));
     } else {
 	XP_ERROR(XPATH_INVALID_CTXT_SIZE);
     }
@@ -8513,13 +7449,8 @@ void
 xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     CHECK_ARITY(0);
     if (ctxt->context->proximityPosition >= 0) {
-	valuePush(ctxt,
-	      xmlXPathCacheNewFloat(ctxt->context,
-		(double) ctxt->context->proximityPosition));
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext, "position() : %d\n",
-		ctxt->context->proximityPosition);
-#endif
+	valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
+            (double) ctxt->context->proximityPosition));
     } else {
 	XP_ERROR(XPATH_INVALID_CTXT_POSITION);
     }
@@ -8545,9 +7476,9 @@ xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     cur = valuePop(ctxt);
 
     if ((cur == NULL) || (cur->nodesetval == NULL))
-	valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0));
+	valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0.0));
     else
-	valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context,
+	valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
 	    (double) cur->nodesetval->nodeNr));
     xmlXPathReleaseObject(ctxt->context, cur);
 }
@@ -8581,28 +7512,33 @@ xmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) {
 	    cur++;
 
         ID = xmlStrndup(ids, cur - ids);
-	if (ID != NULL) {
-	    /*
-	     * We used to check the fact that the value passed
-	     * was an NCName, but this generated much troubles for
-	     * me and Aleksey Sanin, people blatantly violated that
-	     * constraint, like Visa3D spec.
-	     * if (xmlValidateNCName(ID, 1) == 0)
-	     */
-	    attr = xmlGetID(doc, ID);
-	    if (attr != NULL) {
-		if (attr->type == XML_ATTRIBUTE_NODE)
-		    elem = attr->parent;
-		else if (attr->type == XML_ELEMENT_NODE)
-		    elem = (xmlNodePtr) attr;
-		else
-		    elem = NULL;
-                /* TODO: Check memory error. */
-		if (elem != NULL)
-		    xmlXPathNodeSetAdd(ret, elem);
-	    }
-	    xmlFree(ID);
-	}
+	if (ID == NULL) {
+            xmlXPathFreeNodeSet(ret);
+            return(NULL);
+        }
+        /*
+         * We used to check the fact that the value passed
+         * was an NCName, but this generated much troubles for
+         * me and Aleksey Sanin, people blatantly violated that
+         * constraint, like Visa3D spec.
+         * if (xmlValidateNCName(ID, 1) == 0)
+         */
+        attr = xmlGetID(doc, ID);
+        xmlFree(ID);
+        if (attr != NULL) {
+            if (attr->type == XML_ATTRIBUTE_NODE)
+                elem = attr->parent;
+            else if (attr->type == XML_ELEMENT_NODE)
+                elem = (xmlNodePtr) attr;
+            else
+                elem = NULL;
+            if (elem != NULL) {
+                if (xmlXPathNodeSetAdd(ret, elem) < 0) {
+                    xmlXPathFreeNodeSet(ret);
+                    return(NULL);
+                }
+            }
+        }
 
 	while (IS_BLANK_CH(*cur)) cur++;
 	ids = cur;
@@ -8641,30 +7577,40 @@ xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) {
 	xmlNodeSetPtr ns;
 	int i;
 
-        /* TODO: Check memory error. */
 	ret = xmlXPathNodeSetCreate(NULL);
+        if (ret == NULL)
+            xmlXPathPErrMemory(ctxt);
 
 	if (obj->nodesetval != NULL) {
 	    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
 		tokens =
 		    xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
+                if (tokens == NULL)
+                    xmlXPathPErrMemory(ctxt);
 		ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
-                /* TODO: Check memory error. */
+                if (ns == NULL)
+                    xmlXPathPErrMemory(ctxt);
 		ret = xmlXPathNodeSetMerge(ret, ns);
+                if (ret == NULL)
+                    xmlXPathPErrMemory(ctxt);
 		xmlXPathFreeNodeSet(ns);
 		if (tokens != NULL)
 		    xmlFree(tokens);
 	    }
 	}
 	xmlXPathReleaseObject(ctxt->context, obj);
-	valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret));
+	valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, ret));
 	return;
     }
-    obj = xmlXPathCacheConvertString(ctxt->context, obj);
-    if (obj == NULL) return;
-    ret = xmlXPathGetElementsByIds(ctxt->context->doc, obj->stringval);
-    valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret));
+    tokens = xmlXPathCastToString(obj);
+    if (tokens == NULL)
+        xmlXPathPErrMemory(ctxt);
     xmlXPathReleaseObject(ctxt->context, obj);
+    ret = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
+    if (ret == NULL)
+        xmlXPathPErrMemory(ctxt);
+    xmlFree(tokens);
+    valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, ret));
     return;
 }
 
@@ -8688,8 +7634,7 @@ xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     if (ctxt == NULL) return;
 
     if (nargs == 0) {
-	valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
-	    ctxt->context->node));
+	valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
 	nargs = 1;
     }
 
@@ -8701,7 +7646,7 @@ xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     cur = valuePop(ctxt);
 
     if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
-	valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
+	valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
     } else {
 	int i = 0; /* Should be first in document order !!!!! */
 	switch (cur->nodesetval->nodeTab[i]->type) {
@@ -8709,18 +7654,17 @@ xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
 	case XML_ATTRIBUTE_NODE:
 	case XML_PI_NODE:
 	    if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
-		valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
+		valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
 	    else
-		valuePush(ctxt,
-		      xmlXPathCacheNewString(ctxt->context,
+		valuePush(ctxt, xmlXPathCacheNewString(ctxt,
 			cur->nodesetval->nodeTab[i]->name));
 	    break;
 	case XML_NAMESPACE_DECL:
-	    valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
+	    valuePush(ctxt, xmlXPathCacheNewString(ctxt,
 			((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix));
 	    break;
 	default:
-	    valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
+	    valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
 	}
     }
     xmlXPathReleaseObject(ctxt->context, cur);
@@ -8747,8 +7691,7 @@ xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     if (ctxt == NULL) return;
 
     if (nargs == 0) {
-	valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
-	    ctxt->context->node));
+	valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
 	nargs = 1;
     }
     CHECK_ARITY(1);
@@ -8759,20 +7702,20 @@ xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     cur = valuePop(ctxt);
 
     if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
-	valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
+	valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
     } else {
 	int i = 0; /* Should be first in document order !!!!! */
 	switch (cur->nodesetval->nodeTab[i]->type) {
 	case XML_ELEMENT_NODE:
 	case XML_ATTRIBUTE_NODE:
 	    if (cur->nodesetval->nodeTab[i]->ns == NULL)
-		valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
+		valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
 	    else
-		valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
+		valuePush(ctxt, xmlXPathCacheNewString(ctxt,
 			  cur->nodesetval->nodeTab[i]->ns->href));
 	    break;
 	default:
-	    valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
+	    valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
 	}
     }
     xmlXPathReleaseObject(ctxt->context, cur);
@@ -8806,8 +7749,7 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
     xmlXPathObjectPtr cur;
 
     if (nargs == 0) {
-	valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
-	    ctxt->context->node));
+	valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
         nargs = 1;
     }
 
@@ -8819,7 +7761,7 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
     cur = valuePop(ctxt);
 
     if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
-        valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
+        valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
     } else {
         int i = 0;              /* Should be first in document order !!!!! */
 
@@ -8828,11 +7770,10 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
             case XML_ATTRIBUTE_NODE:
 		if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
 		    valuePush(ctxt,
-			xmlXPathCacheNewCString(ctxt->context, ""));
+			xmlXPathCacheNewCString(ctxt, ""));
 		else if ((cur->nodesetval->nodeTab[i]->ns == NULL) ||
                          (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) {
-		    valuePush(ctxt,
-		        xmlXPathCacheNewString(ctxt->context,
+		    valuePush(ctxt, xmlXPathCacheNewString(ctxt,
 			    cur->nodesetval->nodeTab[i]->name));
 		} else {
 		    xmlChar *fullname;
@@ -8842,15 +7783,13 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
 				     NULL, 0);
 		    if (fullname == cur->nodesetval->nodeTab[i]->name)
 			fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name);
-		    if (fullname == NULL) {
-			XP_ERROR(XPATH_MEMORY_ERROR);
-		    }
-		    valuePush(ctxt, xmlXPathCacheWrapString(
-			ctxt->context, fullname));
+		    if (fullname == NULL)
+                        xmlXPathPErrMemory(ctxt);
+		    valuePush(ctxt, xmlXPathCacheWrapString(ctxt, fullname));
                 }
                 break;
             default:
-		valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
+		valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
 		    cur->nodesetval->nodeTab[i]));
                 xmlXPathLocalNameFunction(ctxt, 1);
         }
@@ -8898,19 +7837,28 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
 void
 xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     xmlXPathObjectPtr cur;
+    xmlChar *stringval;
 
     if (ctxt == NULL) return;
     if (nargs == 0) {
-    valuePush(ctxt,
-	xmlXPathCacheWrapString(ctxt->context,
-	    xmlXPathCastNodeToString(ctxt->context->node)));
+        stringval = xmlXPathCastNodeToString(ctxt->context->node);
+        if (stringval == NULL)
+            xmlXPathPErrMemory(ctxt);
+        valuePush(ctxt, xmlXPathCacheWrapString(ctxt, stringval));
 	return;
     }
 
     CHECK_ARITY(1);
     cur = valuePop(ctxt);
     if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
-    valuePush(ctxt, xmlXPathCacheConvertString(ctxt->context, cur));
+    if (cur->type != XPATH_STRING) {
+        stringval = xmlXPathCastToString(cur);
+        if (stringval == NULL)
+            xmlXPathPErrMemory(ctxt);
+        xmlXPathReleaseObject(ctxt->context, cur);
+        cur = xmlXPathCacheWrapString(ctxt, stringval);
+    }
+    valuePush(ctxt, cur);
 }
 
 /**
@@ -8933,12 +7881,14 @@ xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) {
         if ((ctxt == NULL) || (ctxt->context == NULL))
 	    return;
 	if (ctxt->context->node == NULL) {
-	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, 0));
+	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0));
 	} else {
 	    xmlChar *content;
 
 	    content = xmlXPathCastNodeToString(ctxt->context->node);
-	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context,
+            if (content == NULL)
+                xmlXPathPErrMemory(ctxt);
+	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
 		xmlUTF8Strlen(content)));
 	    xmlFree(content);
 	}
@@ -8948,7 +7898,7 @@ xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     CAST_TO_STRING;
     CHECK_TYPE(XPATH_STRING);
     cur = valuePop(ctxt);
-    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context,
+    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
 	xmlUTF8Strlen(cur->stringval)));
     xmlXPathReleaseObject(ctxt->context, cur);
 }
@@ -8989,6 +7939,8 @@ xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) {
 	    XP_ERROR(XPATH_INVALID_TYPE);
 	}
 	tmp = xmlStrcat(newobj->stringval, cur->stringval);
+        if (tmp == NULL)
+            xmlXPathPErrMemory(ctxt);
 	newobj->stringval = cur->stringval;
 	cur->stringval = tmp;
 	xmlXPathReleaseObject(ctxt->context, newobj);
@@ -9024,9 +7976,9 @@ xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) {
 	XP_ERROR(XPATH_INVALID_TYPE);
     }
     if (xmlStrstr(hay->stringval, needle->stringval))
-	valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1));
+	valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
     else
-	valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0));
+	valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
     xmlXPathReleaseObject(ctxt->context, hay);
     xmlXPathReleaseObject(ctxt->context, needle);
 }
@@ -9060,9 +8012,9 @@ xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     }
     n = xmlStrlen(needle->stringval);
     if (xmlStrncmp(hay->stringval, needle->stringval, n))
-        valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0));
+        valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
     else
-        valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1));
+        valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
     xmlXPathReleaseObject(ctxt->context, hay);
     xmlXPathReleaseObject(ctxt->context, needle);
 }
@@ -9154,12 +8106,17 @@ xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
         }
     }
 
-    if (i < j) {
-        xmlChar *ret = xmlUTF8Strsub(str->stringval, i - 1, j - i);
-	valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, ret));
+    i -= 1;
+    j -= 1;
+
+    if ((i < j) && (i < xmlUTF8Strlen(str->stringval))) {
+        xmlChar *ret = xmlUTF8Strsub(str->stringval, i, j - i);
+        if (ret == NULL)
+            xmlXPathPErrMemory(ctxt);
+	valuePush(ctxt, xmlXPathCacheNewString(ctxt, ret));
 	xmlFree(ret);
     } else {
-	valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
+	valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
     }
 
     xmlXPathReleaseObject(ctxt->context, str);
@@ -9180,31 +8137,34 @@ xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
  */
 void
 xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
-  xmlXPathObjectPtr str;
-  xmlXPathObjectPtr find;
-  xmlBufPtr target;
-  const xmlChar *point;
-  int offset;
-
-  CHECK_ARITY(2);
-  CAST_TO_STRING;
-  find = valuePop(ctxt);
-  CAST_TO_STRING;
-  str = valuePop(ctxt);
-
-  target = xmlBufCreate();
-  if (target) {
+    xmlXPathObjectPtr str = NULL;
+    xmlXPathObjectPtr find = NULL;
+    const xmlChar *point;
+    xmlChar *result;
+
+    CHECK_ARITY(2);
+    CAST_TO_STRING;
+    find = valuePop(ctxt);
+    CAST_TO_STRING;
+    str = valuePop(ctxt);
+    if (ctxt->error != 0)
+        goto error;
+
     point = xmlStrstr(str->stringval, find->stringval);
-    if (point) {
-      offset = (int)(point - str->stringval);
-      xmlBufAdd(target, str->stringval, offset);
+    if (point == NULL) {
+        result = xmlStrdup(BAD_CAST "");
+    } else {
+        result = xmlStrndup(str->stringval, point - str->stringval);
     }
-    valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
-	xmlBufContent(target)));
-    xmlBufFree(target);
-  }
-  xmlXPathReleaseObject(ctxt->context, str);
-  xmlXPathReleaseObject(ctxt->context, find);
+    if (result == NULL) {
+        xmlXPathPErrMemory(ctxt);
+        goto error;
+    }
+    valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result));
+
+error:
+    xmlXPathReleaseObject(ctxt->context, str);
+    xmlXPathReleaseObject(ctxt->context, find);
 }
 
 /**
@@ -9216,39 +8176,41 @@ xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
  *    string substring-after(string, string)
  * The substring-after function returns the substring of the first
  * argument string that follows the first occurrence of the second
- * argument string in the first argument string, or the empty stringi
+ * argument string in the first argument string, or the empty string
  * if the first argument string does not contain the second argument
  * string. For example, substring-after("1999/04/01","/") returns 04/01,
  * and substring-after("1999/04/01","19") returns 99/04/01.
  */
 void
 xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
-  xmlXPathObjectPtr str;
-  xmlXPathObjectPtr find;
-  xmlBufPtr target;
-  const xmlChar *point;
-  int offset;
-
-  CHECK_ARITY(2);
-  CAST_TO_STRING;
-  find = valuePop(ctxt);
-  CAST_TO_STRING;
-  str = valuePop(ctxt);
-
-  target = xmlBufCreate();
-  if (target) {
+    xmlXPathObjectPtr str = NULL;
+    xmlXPathObjectPtr find = NULL;
+    const xmlChar *point;
+    xmlChar *result;
+
+    CHECK_ARITY(2);
+    CAST_TO_STRING;
+    find = valuePop(ctxt);
+    CAST_TO_STRING;
+    str = valuePop(ctxt);
+    if (ctxt->error != 0)
+        goto error;
+
     point = xmlStrstr(str->stringval, find->stringval);
-    if (point) {
-      offset = (int)(point - str->stringval) + xmlStrlen(find->stringval);
-      xmlBufAdd(target, &str->stringval[offset],
-		   xmlStrlen(str->stringval) - offset);
+    if (point == NULL) {
+        result = xmlStrdup(BAD_CAST "");
+    } else {
+        result = xmlStrdup(point + xmlStrlen(find->stringval));
     }
-    valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
-	xmlBufContent(target)));
-    xmlBufFree(target);
-  }
-  xmlXPathReleaseObject(ctxt->context, str);
-  xmlXPathReleaseObject(ctxt->context, find);
+    if (result == NULL) {
+        xmlXPathPErrMemory(ctxt);
+        goto error;
+    }
+    valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result));
+
+error:
+    xmlXPathReleaseObject(ctxt->context, str);
+    xmlXPathReleaseObject(ctxt->context, find);
 }
 
 /**
@@ -9273,9 +8235,10 @@ xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     if (ctxt == NULL) return;
     if (nargs == 0) {
         /* Use current context node */
-        valuePush(ctxt,
-            xmlXPathCacheWrapString(ctxt->context,
-                xmlXPathCastNodeToString(ctxt->context->node)));
+        source = xmlXPathCastNodeToString(ctxt->context->node);
+        if (source == NULL)
+            xmlXPathPErrMemory(ctxt);
+        valuePush(ctxt, xmlXPathCacheWrapString(ctxt, source));
         nargs = 1;
     }
 
@@ -9331,14 +8294,14 @@ xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
  */
 void
 xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
-    xmlXPathObjectPtr str;
-    xmlXPathObjectPtr from;
-    xmlXPathObjectPtr to;
+    xmlXPathObjectPtr str = NULL;
+    xmlXPathObjectPtr from = NULL;
+    xmlXPathObjectPtr to = NULL;
     xmlBufPtr target;
     int offset, max;
-    xmlChar ch;
+    int ch;
     const xmlChar *point;
-    xmlChar *cptr;
+    xmlChar *cptr, *content;
 
     CHECK_ARITY(3);
 
@@ -9348,47 +8311,71 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     from = valuePop(ctxt);
     CAST_TO_STRING;
     str = valuePop(ctxt);
+    if (ctxt->error != 0)
+        goto error;
 
-    target = xmlBufCreate();
-    if (target) {
-	max = xmlUTF8Strlen(to->stringval);
-	for (cptr = str->stringval; (ch=*cptr); ) {
-	    offset = xmlUTF8Strloc(from->stringval, cptr);
-	    if (offset >= 0) {
-		if (offset < max) {
-		    point = xmlUTF8Strpos(to->stringval, offset);
-		    if (point)
-			xmlBufAdd(target, point, xmlUTF8Strsize(point, 1));
-		}
-	    } else
-		xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
-
-	    /* Step to next character in input */
-	    cptr++;
-	    if ( ch & 0x80 ) {
-		/* if not simple ascii, verify proper format */
-		if ( (ch & 0xc0) != 0xc0 ) {
-		    xmlGenericError(xmlGenericErrorContext,
-			"xmlXPathTranslateFunction: Invalid UTF8 string\n");
-                    /* not asserting an XPath error is probably better */
-		    break;
-		}
-		/* then skip over remaining bytes for this char */
-		while ( (ch <<= 1) & 0x80 )
-		    if ( (*cptr++ & 0xc0) != 0x80 ) {
-			xmlGenericError(xmlGenericErrorContext,
-			    "xmlXPathTranslateFunction: Invalid UTF8 string\n");
-                        /* not asserting an XPath error is probably better */
-			break;
-		    }
-		if (ch & 0x80) /* must have had error encountered */
-		    break;
-	    }
-	}
+    /*
+     * Account for quadratic runtime
+     */
+    if (ctxt->context->opLimit != 0) {
+        unsigned long f1 = xmlStrlen(from->stringval);
+        unsigned long f2 = xmlStrlen(str->stringval);
+
+        if ((f1 > 0) && (f2 > 0)) {
+            unsigned long p;
+
+            f1 = f1 / 10 + 1;
+            f2 = f2 / 10 + 1;
+            p = f1 > ULONG_MAX / f2 ? ULONG_MAX : f1 * f2;
+            if (xmlXPathCheckOpLimit(ctxt, p) < 0)
+                goto error;
+        }
+    }
+
+    target = xmlBufCreateSize(64);
+    if (target == NULL) {
+        xmlXPathPErrMemory(ctxt);
+        goto error;
     }
-    valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
-	xmlBufContent(target)));
+
+    max = xmlUTF8Strlen(to->stringval);
+    for (cptr = str->stringval; (ch=*cptr); ) {
+        offset = xmlUTF8Strloc(from->stringval, cptr);
+        if (offset >= 0) {
+            if (offset < max) {
+                point = xmlUTF8Strpos(to->stringval, offset);
+                if (point)
+                    xmlBufAdd(target, point, xmlUTF8Strsize(point, 1));
+            }
+        } else
+            xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
+
+        /* Step to next character in input */
+        cptr++;
+        if ( ch & 0x80 ) {
+            /* if not simple ascii, verify proper format */
+            if ( (ch & 0xc0) != 0xc0 ) {
+                xmlXPathErr(ctxt, XPATH_INVALID_CHAR_ERROR);
+                break;
+            }
+            /* then skip over remaining bytes for this char */
+            while ( (ch <<= 1) & 0x80 )
+                if ( (*cptr++ & 0xc0) != 0x80 ) {
+                    xmlXPathErr(ctxt, XPATH_INVALID_CHAR_ERROR);
+                    break;
+                }
+            if (ch & 0x80) /* must have had error encountered */
+                break;
+        }
+    }
+
+    content = xmlBufDetach(target);
+    if (content == NULL)
+        xmlXPathPErrMemory(ctxt);
+    else
+        valuePush(ctxt, xmlXPathCacheWrapString(ctxt, content));
     xmlBufFree(target);
+error:
     xmlXPathReleaseObject(ctxt->context, str);
     xmlXPathReleaseObject(ctxt->context, from);
     xmlXPathReleaseObject(ctxt->context, to);
@@ -9414,7 +8401,12 @@ xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     CHECK_ARITY(1);
     cur = valuePop(ctxt);
     if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
-    cur = xmlXPathCacheConvertBoolean(ctxt->context, cur);
+    if (cur->type != XPATH_BOOLEAN) {
+        int boolval = xmlXPathCastToBoolean(cur);
+
+        xmlXPathReleaseObject(ctxt->context, cur);
+        cur = xmlXPathCacheNewBoolean(ctxt, boolval);
+    }
     valuePush(ctxt, cur);
 }
 
@@ -9447,7 +8439,7 @@ xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) {
 void
 xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     CHECK_ARITY(0);
-    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1));
+    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
 }
 
 /**
@@ -9461,7 +8453,7 @@ xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) {
 void
 xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     CHECK_ARITY(0);
-    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0));
+    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
 }
 
 /**
@@ -9487,8 +8479,9 @@ xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) {
  */
 void
 xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) {
-    xmlXPathObjectPtr val = NULL;
-    const xmlChar *theLang = NULL;
+    xmlXPathObjectPtr val;
+    xmlNodePtr cur;
+    xmlChar *theLang;
     const xmlChar *lang;
     int ret = 0;
     int i;
@@ -9498,20 +8491,28 @@ xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     CHECK_TYPE(XPATH_STRING);
     val = valuePop(ctxt);
     lang = val->stringval;
-    theLang = xmlNodeGetLang(ctxt->context->node);
+    cur = ctxt->context->node;
+    while (cur != NULL) {
+        if (xmlNodeGetAttrValue(cur, BAD_CAST "lang", XML_XML_NAMESPACE,
+                                &theLang) < 0)
+            xmlXPathPErrMemory(ctxt);
+        if (theLang != NULL)
+            break;
+        cur = cur->parent;
+    }
     if ((theLang != NULL) && (lang != NULL)) {
         for (i = 0;lang[i] != 0;i++)
-	    if (toupper(lang[i]) != toupper(theLang[i]))
-	        goto not_equal;
-	if ((theLang[i] == 0) || (theLang[i] == '-'))
-	    ret = 1;
+            if (toupper(lang[i]) != toupper(theLang[i]))
+                goto not_equal;
+        if ((theLang[i] == 0) || (theLang[i] == '-'))
+            ret = 1;
     }
 not_equal:
     if (theLang != NULL)
 	xmlFree((void *)theLang);
 
     xmlXPathReleaseObject(ctxt->context, val);
-    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret));
+    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret));
 }
 
 /**
@@ -9530,12 +8531,14 @@ xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     if (ctxt == NULL) return;
     if (nargs == 0) {
 	if (ctxt->context->node == NULL) {
-	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, 0.0));
+	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0.0));
 	} else {
 	    xmlChar* content = xmlNodeGetContent(ctxt->context->node);
+            if (content == NULL)
+                xmlXPathPErrMemory(ctxt);
 
 	    res = xmlXPathStringEvalNumber(content);
-	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, res));
+	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, res));
 	    xmlFree(content);
 	}
 	return;
@@ -9543,7 +8546,14 @@ xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
 
     CHECK_ARITY(1);
     cur = valuePop(ctxt);
-    valuePush(ctxt, xmlXPathCacheConvertNumber(ctxt->context, cur));
+    if (cur->type != XPATH_NUMBER) {
+        double floatval;
+
+        floatval = xmlXPathCastToNumberInternal(ctxt, cur);
+        xmlXPathReleaseObject(ctxt->context, cur);
+        cur = xmlXPathCacheNewFloat(ctxt, floatval);
+    }
+    valuePush(ctxt, cur);
 }
 
 /**
@@ -9571,10 +8581,11 @@ xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) {
 
     if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) {
 	for (i = 0; i < cur->nodesetval->nodeNr; i++) {
-	    res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]);
+	    res += xmlXPathNodeToNumberInternal(ctxt,
+                                                cur->nodesetval->nodeTab[i]);
 	}
     }
-    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, res));
+    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, res));
     xmlXPathReleaseObject(ctxt->context, cur);
 }
 
@@ -9742,7 +8753,7 @@ xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
     } else {
 	/* 1-byte code */
 	*len = 1;
-	return((int) *cur);
+	return(*cur);
     }
 encoding_error:
     /*
@@ -9798,6 +8809,8 @@ xmlXPathParseNCName(xmlXPathParserContextPtr ctxt) {
 	    if (count == 0)
 		return(NULL);
 	    ret = xmlStrndup(ctxt->cur, count);
+            if (ret == NULL)
+                xmlXPathPErrMemory(ctxt);
 	    ctxt->cur = in;
 	    return(ret);
 	}
@@ -9879,6 +8892,8 @@ xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
                 XP_ERRORNULL(XPATH_EXPR_ERROR);
             }
 	    ret = xmlStrndup(ctxt->cur, count);
+            if (ret == NULL)
+                xmlXPathPErrMemory(ctxt);
 	    ctxt->cur = in;
 	    return(ret);
 	}
@@ -9888,6 +8903,7 @@ xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
 
 static xmlChar *
 xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
+    xmlChar *ret;
     xmlChar buf[XML_MAX_NAMELEN + 5];
     int len = 0, l;
     int c;
@@ -9924,9 +8940,10 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
             if (len > XML_MAX_NAME_LENGTH) {
                 XP_ERRORNULL(XPATH_EXPR_ERROR);
             }
-	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
+	    buffer = (xmlChar *) xmlMallocAtomic(max);
 	    if (buffer == NULL) {
-		XP_ERRORNULL(XPATH_MEMORY_ERROR);
+                xmlXPathPErrMemory(ctxt);
+                return(NULL);
 	    }
 	    memcpy(buffer, buf, len);
 	    while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
@@ -9941,11 +8958,11 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
                         XP_ERRORNULL(XPATH_EXPR_ERROR);
                     }
 		    max *= 2;
-		    tmp = (xmlChar *) xmlRealloc(buffer,
-			                         max * sizeof(xmlChar));
+		    tmp = (xmlChar *) xmlRealloc(buffer, max);
 		    if (tmp == NULL) {
                         xmlFree(buffer);
-			XP_ERRORNULL(XPATH_MEMORY_ERROR);
+                        xmlXPathPErrMemory(ctxt);
+                        return(NULL);
 		    }
                     buffer = tmp;
 		}
@@ -9959,7 +8976,10 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
     }
     if (len == 0)
 	return(NULL);
-    return(xmlStrndup(buf, len));
+    ret = xmlStrndup(buf, len);
+    if (ret == NULL)
+        xmlXPathPErrMemory(ctxt);
+    return(ret);
 }
 
 #define MAX_FRAC 20
@@ -9994,13 +9014,13 @@ xmlXPathStringEvalNumber(const xmlChar *str) {
 #endif
     if (cur == NULL) return(0);
     while (IS_BLANK_CH(*cur)) cur++;
-    if ((*cur != '.') && ((*cur < '0') || (*cur > '9')) && (*cur != '-')) {
-        return(xmlXPathNAN);
-    }
     if (*cur == '-') {
 	isneg = 1;
 	cur++;
     }
+    if ((*cur != '.') && ((*cur < '0') || (*cur > '9'))) {
+        return(xmlXPathNAN);
+    }
 
 #ifdef __GNUC__
     /*
@@ -10162,7 +9182,7 @@ xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
             exponent = -exponent;
         ret *= pow(10.0, (double) exponent);
     }
-    num = xmlXPathCacheNewFloat(ctxt->context, ret);
+    num = xmlXPathCacheNewFloat(ctxt, ret);
     if (num == NULL) {
 	ctxt->error = XPATH_MEMORY_ERROR;
     } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0, num,
@@ -10186,32 +9206,33 @@ static xmlChar *
 xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
     const xmlChar *q;
     xmlChar *ret = NULL;
+    int quote;
 
     if (CUR == '"') {
-        NEXT;
-	q = CUR_PTR;
-	while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
-	    NEXT;
-	if (!IS_CHAR_CH(CUR)) {
-	    XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR);
-	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
-	    NEXT;
-        }
+        quote = '"';
     } else if (CUR == '\'') {
-        NEXT;
-	q = CUR_PTR;
-	while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
-	    NEXT;
-	if (!IS_CHAR_CH(CUR)) {
-	    XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR);
-	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
-	    NEXT;
-        }
+        quote = '\'';
     } else {
 	XP_ERRORNULL(XPATH_START_LITERAL_ERROR);
     }
+
+    NEXT;
+    q = CUR_PTR;
+    while (CUR != quote) {
+        int ch;
+        int len = 4;
+
+        if (CUR == 0)
+            XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR);
+        ch = xmlGetUTF8Char(CUR_PTR, &len);
+        if ((ch < 0) || (IS_CHAR(ch) == 0))
+            XP_ERRORNULL(XPATH_INVALID_CHAR_ERROR);
+        CUR_PTR += len;
+    }
+    ret = xmlStrndup(q, CUR_PTR - q);
+    if (ret == NULL)
+        xmlXPathPErrMemory(ctxt);
+    NEXT;
     return(ret);
 }
 
@@ -10228,39 +9249,15 @@ xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
  */
 static void
 xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
-    const xmlChar *q;
     xmlChar *ret = NULL;
     xmlXPathObjectPtr lit;
 
-    if (CUR == '"') {
-        NEXT;
-	q = CUR_PTR;
-	while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
-	    NEXT;
-	if (!IS_CHAR_CH(CUR)) {
-	    XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
-	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
-	    NEXT;
-        }
-    } else if (CUR == '\'') {
-        NEXT;
-	q = CUR_PTR;
-	while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
-	    NEXT;
-	if (!IS_CHAR_CH(CUR)) {
-	    XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
-	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
-	    NEXT;
-        }
-    } else {
-	XP_ERROR(XPATH_START_LITERAL_ERROR);
-    }
-    if (ret == NULL) return;
-    lit = xmlXPathCacheNewString(ctxt->context, ret);
+    ret = xmlXPathParseLiteral(ctxt);
+    if (ret == NULL)
+        return;
+    lit = xmlXPathCacheNewString(ctxt, ret);
     if (lit == NULL) {
-	ctxt->error = XPATH_MEMORY_ERROR;
+        ctxt->error = XPATH_MEMORY_ERROR;
     } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0, lit,
                               NULL) == -1) {
         xmlXPathReleaseObject(ctxt->context, lit);
@@ -10363,14 +9360,6 @@ xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
 	XP_ERROR(XPATH_EXPR_ERROR);
     }
     SKIP_BLANKS;
-#ifdef DEBUG_EXPR
-    if (prefix == NULL)
-	xmlGenericError(xmlGenericErrorContext, "Calling function %s\n",
-			name);
-    else
-	xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n",
-			prefix, name);
-#endif
 
     if (CUR != '(') {
 	xmlFree(name);
@@ -10503,7 +9492,7 @@ xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) {
 
 static xmlChar *
 xmlXPathScanName(xmlXPathParserContextPtr ctxt) {
-    int len = 0, l;
+    int l;
     int c;
     const xmlChar *cur;
     xmlChar *ret;
@@ -10523,11 +9512,12 @@ xmlXPathScanName(xmlXPathParserContextPtr ctxt) {
 	    (c == '_') || (c == ':') ||
 	    (IS_COMBINING(c)) ||
 	    (IS_EXTENDER(c)))) {
-	len += l;
 	NEXTL(l);
 	c = CUR_CHAR(l);
     }
     ret = xmlStrndup(cur, ctxt->cur - cur);
+    if (ret == NULL)
+        xmlXPathPErrMemory(ctxt);
     ctxt->cur = cur;
     return(ret);
 }
@@ -10588,10 +9578,6 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
 	SKIP_BLANKS;
 	name = xmlXPathScanName(ctxt);
 	if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) {
-#ifdef DEBUG_STEP
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PathExpr: Axis\n");
-#endif
 	    lc = 1;
 	    xmlFree(name);
 	} else if (name != NULL) {
@@ -10601,29 +9587,17 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
 	    while (NXT(len) != 0) {
 		if (NXT(len) == '/') {
 		    /* element name */
-#ifdef DEBUG_STEP
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PathExpr: AbbrRelLocation\n");
-#endif
 		    lc = 1;
 		    break;
 		} else if (IS_BLANK_CH(NXT(len))) {
 		    /* ignore blanks */
 		    ;
 		} else if (NXT(len) == ':') {
-#ifdef DEBUG_STEP
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PathExpr: AbbrRelLocation\n");
-#endif
 		    lc = 1;
 		    break;
 		} else if ((NXT(len) == '(')) {
 		    /* Node Type or Function */
 		    if (xmlXPathIsNodeType(name)) {
-#ifdef DEBUG_STEP
-		        xmlGenericError(xmlGenericErrorContext,
-				"PathExpr: Type search\n");
-#endif
 			lc = 1;
 #ifdef LIBXML_XPTR_LOCS_ENABLED
                     } else if (ctxt->xptr &&
@@ -10631,19 +9605,11 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
                         lc = 1;
 #endif
 		    } else {
-#ifdef DEBUG_STEP
-		        xmlGenericError(xmlGenericErrorContext,
-				"PathExpr: function call\n");
-#endif
 			lc = 0;
 		    }
                     break;
 		} else if ((NXT(len) == '[')) {
 		    /* element name */
-#ifdef DEBUG_STEP
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PathExpr: AbbrRelLocation\n");
-#endif
 		    lc = 1;
 		    break;
 		} else if ((NXT(len) == '<') || (NXT(len) == '>') ||
@@ -10657,10 +9623,6 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
 		len++;
 	    }
 	    if (NXT(len) == 0) {
-#ifdef DEBUG_STEP
-		xmlGenericError(xmlGenericErrorContext,
-			"PathExpr: AbbrRelLocation\n");
-#endif
 		/* element name */
 		lc = 1;
 	    }
@@ -11064,7 +10026,6 @@ xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
     int blanks;
 
     if ((test == NULL) || (type == NULL) || (prefix == NULL)) {
-	STRANGE;
 	return(NULL);
     }
     *type = (xmlXPathTypeVal) 0;
@@ -11120,9 +10081,6 @@ xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
 	    name = NULL;
 	    if (CUR != ')') {
 		name = xmlXPathParseLiteral(ctxt);
-                if (name == NULL) {
-	            XP_ERRORNULL(XPATH_EXPR_ERROR);
-                }
 		*test = NODE_TEST_PI;
 		SKIP_BLANKS;
 	    }
@@ -11371,20 +10329,6 @@ xmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
 		xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR);
 	    }
 	}
-#ifdef DEBUG_STEP
-	xmlGenericError(xmlGenericErrorContext,
-		"Basis : computing new set\n");
-#endif
-
-#ifdef DEBUG_STEP
-	xmlGenericError(xmlGenericErrorContext, "Basis : ");
-	if (ctxt->value == NULL)
-	    xmlGenericError(xmlGenericErrorContext, "no value\n");
-	else if (ctxt->value->nodesetval == NULL)
-	    xmlGenericError(xmlGenericErrorContext, "Empty\n");
-	else
-	    xmlGenericErrorContextNodeSet(stdout, ctxt->value->nodesetval);
-#endif
 
 #ifdef LIBXML_XPTR_LOCS_ENABLED
 eval_predicates:
@@ -11408,16 +10352,6 @@ eval_predicates:
             xmlFree(name);
         }
     }
-#ifdef DEBUG_STEP
-    xmlGenericError(xmlGenericErrorContext, "Step : ");
-    if (ctxt->value == NULL)
-	xmlGenericError(xmlGenericErrorContext, "no value\n");
-    else if (ctxt->value->nodesetval == NULL)
-	xmlGenericError(xmlGenericErrorContext, "Empty\n");
-    else
-	xmlGenericErrorContextNodeSet(xmlGenericErrorContext,
-		ctxt->value->nodesetval);
-#endif
 }
 
 /**
@@ -11519,93 +10453,6 @@ xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) {
 static int
 xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
 
-#ifdef DEBUG_STEP
-static void
-xmlXPathDebugDumpStepAxis(xmlXPathStepOpPtr op,
-			  int nbNodes)
-{
-    xmlGenericError(xmlGenericErrorContext, "new step : ");
-    switch (op->value) {
-        case AXIS_ANCESTOR:
-            xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
-            break;
-        case AXIS_ANCESTOR_OR_SELF:
-            xmlGenericError(xmlGenericErrorContext,
-                            "axis 'ancestors-or-self' ");
-            break;
-        case AXIS_ATTRIBUTE:
-            xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
-            break;
-        case AXIS_CHILD:
-            xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
-            break;
-        case AXIS_DESCENDANT:
-            xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
-            break;
-        case AXIS_DESCENDANT_OR_SELF:
-            xmlGenericError(xmlGenericErrorContext,
-                            "axis 'descendant-or-self' ");
-            break;
-        case AXIS_FOLLOWING:
-            xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
-            break;
-        case AXIS_FOLLOWING_SIBLING:
-            xmlGenericError(xmlGenericErrorContext,
-                            "axis 'following-siblings' ");
-            break;
-        case AXIS_NAMESPACE:
-            xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
-            break;
-        case AXIS_PARENT:
-            xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
-            break;
-        case AXIS_PRECEDING:
-            xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
-            break;
-        case AXIS_PRECEDING_SIBLING:
-            xmlGenericError(xmlGenericErrorContext,
-                            "axis 'preceding-sibling' ");
-            break;
-        case AXIS_SELF:
-            xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
-            break;
-    }
-    xmlGenericError(xmlGenericErrorContext,
-	" context contains %d nodes\n", nbNodes);
-    switch (op->value2) {
-        case NODE_TEST_NONE:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for none !!!\n");
-            break;
-        case NODE_TEST_TYPE:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for type %d\n", op->value3);
-            break;
-        case NODE_TEST_PI:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for PI !!!\n");
-            break;
-        case NODE_TEST_ALL:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for *\n");
-            break;
-        case NODE_TEST_NS:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for namespace %s\n",
-                            op->value5);
-            break;
-        case NODE_TEST_NAME:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for name %s\n", op->value5);
-            if (op->value4)
-                xmlGenericError(xmlGenericErrorContext,
-                                "           with namespace %s\n", op->value4);
-            break;
-    }
-    xmlGenericError(xmlGenericErrorContext, "Testing : ");
-}
-#endif /* DEBUG_STEP */
-
 /**
  * xmlXPathNodeSetFilter:
  * @ctxt:  the XPath Parser context
@@ -11727,7 +10574,7 @@ xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
         tmp = (xmlNodePtr *) xmlRealloc(set->nodeTab,
                 nodeMax * sizeof(xmlNodePtr));
         if (tmp == NULL) {
-            xmlXPathPErrMemory(ctxt, "shrinking nodeset\n");
+            xmlXPathPErrMemory(ctxt);
         } else {
             set->nodeTab = tmp;
             set->nodeMax = nodeMax;
@@ -11845,7 +10692,7 @@ xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,
         tmp = (xmlXPathObjectPtr *) xmlRealloc(locset->locTab,
                 locMax * sizeof(xmlXPathObjectPtr));
         if (tmp == NULL) {
-            xmlXPathPErrMemory(ctxt, "shrinking locset\n");
+            xmlXPathPErrMemory(ctxt);
         } else {
             locset->locTab = tmp;
             locset->locMax = locMax;
@@ -11885,8 +10732,6 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
 	* Process inner predicates first.
 	*/
 	if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) {
-            xmlGenericError(xmlGenericErrorContext,
-                "xmlXPathCompOpEvalPredicate: Expected a predicate\n");
             XP_ERROR(XPATH_INVALID_OPERAND);
 	}
         if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
@@ -11969,11 +10814,11 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
     if (hasAxisRange != 0) { \
 	if (++pos == maxPos) { \
 	    if (addNode(seq, cur) < 0) \
-	        ctxt->error = XPATH_MEMORY_ERROR; \
+	        xmlXPathPErrMemory(ctxt); \
 	    goto axis_range_end; } \
     } else { \
 	if (addNode(seq, cur) < 0) \
-	    ctxt->error = XPATH_MEMORY_ERROR; \
+	    xmlXPathPErrMemory(ctxt); \
 	if (breakOnFirstHit) goto first_hit; }
 
 #define XP_TEST_HIT_NS \
@@ -11981,12 +10826,12 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
 	if (++pos == maxPos) { \
 	    hasNsNodes = 1; \
 	    if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
-	        ctxt->error = XPATH_MEMORY_ERROR; \
+	        xmlXPathPErrMemory(ctxt); \
 	goto axis_range_end; } \
     } else { \
 	hasNsNodes = 1; \
 	if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
-	    ctxt->error = XPATH_MEMORY_ERROR; \
+	    xmlXPathPErrMemory(ctxt); \
 	if (breakOnFirstHit) goto first_hit; }
 
     xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
@@ -11996,9 +10841,6 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
     const xmlChar *name = op->value5;
     const xmlChar *URI = NULL;
 
-#ifdef DEBUG_STEP
-    int nbMatches = 0, prevMatches = 0;
-#endif
     int total = 0, hasNsNodes = 0;
     /* The popped object holding the context nodes */
     xmlXPathObjectPtr obj;
@@ -12123,19 +10965,13 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
             break;
     }
 
-#ifdef DEBUG_STEP
-    xmlXPathDebugDumpStepAxis(op,
-	(obj->nodesetval != NULL) ? obj->nodesetval->nodeNr : 0);
-#endif
-
     if (next == NULL) {
 	xmlXPathReleaseObject(xpctxt, obj);
         return(0);
     }
     contextSeq = obj->nodesetval;
     if ((contextSeq == NULL) || (contextSeq->nodeNr <= 0)) {
-	xmlXPathReleaseObject(xpctxt, obj);
-        valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, NULL));
+        valuePush(ctxt, obj);
         return(0);
     }
     /*
@@ -12210,7 +11046,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
 	if (seq == NULL) {
 	    seq = xmlXPathNodeSetCreate(NULL);
 	    if (seq == NULL) {
-                /* TODO: Propagate memory error. */
+                xmlXPathPErrMemory(ctxt);
 		total = 0;
 		goto error;
 	    }
@@ -12261,14 +11097,9 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
 
             total++;
 
-#ifdef DEBUG_STEP
-            xmlGenericError(xmlGenericErrorContext, " %s", cur->name);
-#endif
-
 	    switch (test) {
                 case NODE_TEST_NONE:
 		    total = 0;
-                    STRANGE
 		    goto error;
                 case NODE_TEST_TYPE:
 		    if (type == NODE_TYPE_NODE) {
@@ -12346,7 +11177,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
                     }
                     break;
                 case NODE_TEST_NS:{
-                        TODO;
+                        /* TODO */
                         break;
                     }
                 case NODE_TEST_NAME:
@@ -12428,9 +11259,11 @@ axis_range_end: /* ----------------------------------------------------- */
 	if (outSeq == NULL) {
 	    outSeq = seq;
 	    seq = NULL;
-	} else
-            /* TODO: Check memory error. */
+	} else {
 	    outSeq = mergeAndClear(outSeq, seq);
+            if (outSeq == NULL)
+                xmlXPathPErrMemory(ctxt);
+        }
 	/*
 	* Break if only a true/false result was requested.
 	*/
@@ -12446,16 +11279,13 @@ first_hit: /* ---------------------------------------------------------- */
 	if (outSeq == NULL) {
 	    outSeq = seq;
 	    seq = NULL;
-	} else
-            /* TODO: Check memory error. */
+	} else {
 	    outSeq = mergeAndClear(outSeq, seq);
+            if (outSeq == NULL)
+                xmlXPathPErrMemory(ctxt);
+        }
 	break;
 
-#ifdef DEBUG_STEP
-	if (seq != NULL)
-	    nbMatches += seq->nodeNr;
-#endif
-
 apply_predicates: /* --------------------------------------------------- */
         if (ctxt->error != XPATH_EXPRESSION_OK)
 	    goto error;
@@ -12513,8 +11343,9 @@ apply_predicates: /* --------------------------------------------------- */
 		outSeq = seq;
 		seq = NULL;
 	    } else {
-                /* TODO: Check memory error. */
 		outSeq = mergeAndClear(outSeq, seq);
+                if (outSeq == NULL)
+                    xmlXPathPErrMemory(ctxt);
 	    }
 
             if (toBool)
@@ -12540,11 +11371,13 @@ error:
     * Ensure we return at least an empty set.
     */
     if (outSeq == NULL) {
-	if ((seq != NULL) && (seq->nodeNr == 0))
+	if ((seq != NULL) && (seq->nodeNr == 0)) {
 	    outSeq = seq;
-	else
-            /* TODO: Check memory error. */
+        } else {
 	    outSeq = xmlXPathNodeSetCreate(NULL);
+            if (outSeq == NULL)
+                xmlXPathPErrMemory(ctxt);
+        }
     }
     if ((seq != NULL) && (seq != outSeq)) {
 	 xmlXPathFreeNodeSet(seq);
@@ -12553,7 +11386,7 @@ error:
     * Hand over the result. Better to push the set also in
     * case of errors.
     */
-    valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, outSeq));
+    valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, outSeq));
     /*
     * Reset the context node.
     */
@@ -12567,12 +11400,6 @@ error:
         xpctxt->tmpNsList = NULL;
     }
 
-#ifdef DEBUG_STEP
-    xmlGenericError(xmlGenericErrorContext,
-	"\nExamined %d nodes, found %d nodes at that step\n",
-	total, nbMatches);
-#endif
-
     return(total);
 }
 
@@ -12657,9 +11484,13 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
                 break;
             }
 
-            /* TODO: Check memory error. */
-            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
-                                                    arg2->nodesetval);
+            if ((arg2->nodesetval != NULL) &&
+                (arg2->nodesetval->nodeNr != 0)) {
+                arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
+                                                        arg2->nodesetval);
+                if (arg1->nodesetval == NULL)
+                    xmlXPathPErrMemory(ctxt);
+            }
             valuePush(ctxt, arg1);
 	    xmlXPathReleaseObject(ctxt->context, arg2);
             /* optimizer */
@@ -12677,7 +11508,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
             if (op->ch2 != -1)
                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    CHECK_ERROR0;
-	    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
+	    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
 		ctxt->context->node));
             break;
         case XPATH_OP_COLLECT:{
@@ -12691,9 +11522,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
                 break;
             }
         case XPATH_OP_VALUE:
-            valuePush(ctxt,
-                      xmlXPathCacheObjectCopy(ctxt->context,
-			(xmlXPathObjectPtr) op->value4));
+            valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
             break;
         case XPATH_OP_SORT:
             if (op->ch1 != -1)
@@ -12797,9 +11626,13 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
                 break;
             }
 
-            /* TODO: Check memory error. */
-            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
-                                                    arg2->nodesetval);
+            if ((arg2->nodesetval != NULL) &&
+                (arg2->nodesetval->nodeNr != 0)) {
+                arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
+                                                        arg2->nodesetval);
+                if (arg1->nodesetval == NULL)
+                    xmlXPathPErrMemory(ctxt);
+            }
             valuePush(ctxt, arg1);
 	    xmlXPathReleaseObject(ctxt->context, arg2);
             /* optimizer */
@@ -12817,7 +11650,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
             if (op->ch2 != -1)
                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    CHECK_ERROR0;
-	    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
+	    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
 		ctxt->context->node));
             break;
         case XPATH_OP_COLLECT:{
@@ -12831,9 +11664,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
                 break;
             }
         case XPATH_OP_VALUE:
-            valuePush(ctxt,
-                      xmlXPathCacheObjectCopy(ctxt->context,
-			(xmlXPathObjectPtr) op->value4));
+            valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
             break;
         case XPATH_OP_SORT:
             if (op->ch1 != -1)
@@ -12863,6 +11694,7 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
 {
     int total = 0;
     xmlXPathCompExprPtr comp;
+    xmlXPathObjectPtr obj;
     xmlNodeSetPtr set;
 
     CHECK_ERROR0;
@@ -12930,13 +11762,20 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
     }
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
 
+    /*
+     * In case of errors, xmlXPathNodeSetFilter can pop additional nodes from
+     * the stack. We have to temporarily remove the nodeset object from the
+     * stack to avoid freeing it prematurely.
+     */
     CHECK_TYPE0(XPATH_NODESET);
-    set = ctxt->value->nodesetval;
+    obj = valuePop(ctxt);
+    set = obj->nodesetval;
     if (set != NULL) {
         xmlXPathNodeSetFilter(ctxt, set, op->ch2, 1, 1, 1);
         if (set->nodeNr > 0)
             *first = set->nodeTab[0];
     }
+    valuePush(ctxt, obj);
 
     return (total);
 }
@@ -13011,7 +11850,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
 		equal = xmlXPathEqualValues(ctxt);
 	    else
 		equal = xmlXPathNotEqualValues(ctxt);
-	    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, equal));
+	    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, equal));
             break;
         case XPATH_OP_CMP:
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
@@ -13019,7 +11858,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    CHECK_ERROR0;
             ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
-	    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret));
+	    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret));
             break;
         case XPATH_OP_PLUS:
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
@@ -13077,13 +11916,13 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                 break;
             }
 
-	    if ((arg1->nodesetval == NULL) ||
-		((arg2->nodesetval != NULL) &&
+	    if (((arg2->nodesetval != NULL) &&
 		 (arg2->nodesetval->nodeNr != 0)))
 	    {
-                /* TODO: Check memory error. */
 		arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
 							arg2->nodesetval);
+                if (arg1->nodesetval == NULL)
+                    xmlXPathPErrMemory(ctxt);
 	    }
 
             valuePush(ctxt, arg1);
@@ -13099,8 +11938,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
             if (op->ch2 != -1)
                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    CHECK_ERROR0;
-	    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
-		ctxt->context->node));
+	    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
+                                                    ctxt->context->node));
             break;
         case XPATH_OP_COLLECT:{
                 if (op->ch1 == -1)
@@ -13113,9 +11952,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                 break;
             }
         case XPATH_OP_VALUE:
-            valuePush(ctxt,
-                      xmlXPathCacheObjectCopy(ctxt->context,
-			(xmlXPathObjectPtr) op->value4));
+            valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
             break;
         case XPATH_OP_VARIABLE:{
 		xmlXPathObjectPtr val;
@@ -13133,10 +11970,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
 
                     URI = xmlXPathNsLookup(ctxt->context, op->value5);
                     if (URI == NULL) {
-                        xmlGenericError(xmlGenericErrorContext,
-            "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n",
-                                    (char *) op->value4, (char *)op->value5);
-                        ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
+                        XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
                         break;
                     }
 		    val = xmlXPathVariableLookupNS(ctxt->context,
@@ -13153,30 +11987,18 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
 		int i;
                 int frame;
 
-                frame = xmlXPathSetFrame(ctxt);
+                frame = ctxt->valueNr;
                 if (op->ch1 != -1) {
                     total +=
                         xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
-                    if (ctxt->error != XPATH_EXPRESSION_OK) {
-                        xmlXPathPopFrame(ctxt, frame);
+                    if (ctxt->error != XPATH_EXPRESSION_OK)
                         break;
-                    }
                 }
-		if (ctxt->valueNr < ctxt->valueFrame + op->value) {
-		    xmlGenericError(xmlGenericErrorContext,
-			    "xmlXPathCompOpEval: parameter error\n");
-		    ctxt->error = XPATH_INVALID_OPERAND;
-                    xmlXPathPopFrame(ctxt, frame);
-		    break;
-		}
+		if (ctxt->valueNr < frame + op->value)
+		    XP_ERROR0(XPATH_INVALID_OPERAND);
 		for (i = 0; i < op->value; i++) {
-		    if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
-			xmlGenericError(xmlGenericErrorContext,
-				"xmlXPathCompOpEval: parameter error\n");
-			ctxt->error = XPATH_INVALID_OPERAND;
-                        xmlXPathPopFrame(ctxt, frame);
-			break;
-		    }
+		    if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL)
+			XP_ERROR0(XPATH_INVALID_OPERAND);
                 }
                 if (op->cache != NULL)
                     func = op->cache;
@@ -13189,23 +12011,13 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                                                    op->value4);
                     else {
                         URI = xmlXPathNsLookup(ctxt->context, op->value5);
-                        if (URI == NULL) {
-                            xmlGenericError(xmlGenericErrorContext,
-            "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
-                                    (char *)op->value4, (char *)op->value5);
-                            xmlXPathPopFrame(ctxt, frame);
-                            ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
-                            break;
-                        }
+                        if (URI == NULL)
+                            XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
                         func = xmlXPathFunctionLookupNS(ctxt->context,
                                                         op->value4, URI);
                     }
-                    if (func == NULL) {
-                        xmlGenericError(xmlGenericErrorContext,
-                                "xmlXPathCompOpEval: function %s not found\n",
-                                        (char *)op->value4);
+                    if (func == NULL)
                         XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
-                    }
                     op->cache = func;
                     op->cacheURI = (void *) URI;
                 }
@@ -13217,9 +12029,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                 ctxt->context->function = oldFunc;
                 ctxt->context->functionURI = oldFuncURI;
                 if ((ctxt->error == XPATH_EXPRESSION_OK) &&
-                    (ctxt->valueNr != ctxt->valueFrame + 1))
+                    (ctxt->valueNr != frame + 1))
                     XP_ERROR0(XPATH_STACK_ERROR);
-                xmlXPathPopFrame(ctxt, frame);
                 break;
             }
         case XPATH_OP_ARG:
@@ -13234,6 +12045,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
             break;
         case XPATH_OP_PREDICATE:
         case XPATH_OP_FILTER:{
+                xmlXPathObjectPtr obj;
                 xmlNodeSetPtr set;
 
                 /*
@@ -13348,11 +12160,19 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                 }
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
 
+                /*
+                 * In case of errors, xmlXPathNodeSetFilter can pop additional
+                 * nodes from the stack. We have to temporarily remove the
+                 * nodeset object from the stack to avoid freeing it
+                 * prematurely.
+                 */
                 CHECK_TYPE0(XPATH_NODESET);
-                set = ctxt->value->nodesetval;
+                obj = valuePop(ctxt);
+                set = obj->nodesetval;
                 if (set != NULL)
                     xmlXPathNodeSetFilter(ctxt, set, op->ch2,
                                           1, set->nodeNr, 1);
+                valuePush(ctxt, obj);
                 break;
             }
         case XPATH_OP_SORT:
@@ -13416,8 +12236,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                         ctxt->context->node = oldlocset->locTab[i]->user;
                         ctxt->context->contextSize = oldlocset->locNr;
                         ctxt->context->proximityPosition = i + 1;
-			tmp = xmlXPathCacheNewNodeSet(ctxt->context,
-			    ctxt->context->node);
+                        tmp = xmlXPathCacheNewNodeSet(ctxt,
+                                                      ctxt->context->node);
                         valuePush(ctxt, tmp);
 
                         if (op->ch2 != -1)
@@ -13479,8 +12299,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
 			    /*
 			    * OPTIMIZE TODO: Avoid recreation for every iteration.
 			    */
-			    tmp = xmlXPathCacheNewNodeSet(ctxt->context,
-				ctxt->context->node);
+                            tmp = xmlXPathCacheNewNodeSet(ctxt,
+                                                          ctxt->context->node);
                             valuePush(ctxt, tmp);
 
                             if (op->ch2 != -1)
@@ -13527,9 +12347,7 @@ rangeto_error:
             }
 #endif /* LIBXML_XPTR_LOCS_ENABLED */
         default:
-            xmlGenericError(xmlGenericErrorContext,
-                            "XPath: unknown precompiled operation %d\n", op->op);
-            ctxt->error = XPATH_INVALID_OPERAND;
+            XP_ERROR0(XPATH_INVALID_OPERAND);
             break;
     }
 
@@ -13631,12 +12449,12 @@ start:
 #ifdef XPATH_STREAMING
 /**
  * xmlXPathRunStreamEval:
- * @ctxt:  the XPath parser context with the compiled expression
+ * @pctxt:  the XPath parser context with the compiled expression
  *
  * Evaluate the Precompiled Streamable XPath expression in the given context.
  */
 static int
-xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp,
+xmlXPathRunStreamEval(xmlXPathParserContextPtr pctxt, xmlPatternPtr comp,
 		      xmlXPathObjectPtr *resultSeq, int toBool)
 {
     int max_depth, min_depth;
@@ -13645,8 +12463,7 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp,
     int eval_all_nodes;
     xmlNodePtr cur = NULL, limit = NULL;
     xmlStreamCtxtPtr patstream = NULL;
-
-    int nb_nodes = 0;
+    xmlXPathContextPtr ctxt = pctxt->context;
 
     if ((ctxt == NULL) || (comp == NULL))
         return(-1);
@@ -13668,7 +12485,7 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp,
     if (! toBool) {
 	if (resultSeq == NULL)
 	    return(-1);
-	*resultSeq = xmlXPathCacheNewNodeSet(ctxt, NULL);
+	*resultSeq = xmlXPathCacheNewNodeSet(pctxt, NULL);
 	if (*resultSeq == NULL)
 	    return(-1);
     }
@@ -13677,20 +12494,24 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp,
      * handle the special cases of "/" amd "." being matched
      */
     if (min_depth == 0) {
+        int res;
+
 	if (from_root) {
 	    /* Select "/" */
 	    if (toBool)
 		return(1);
-            /* TODO: Check memory error. */
-	    xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
-		                     (xmlNodePtr) ctxt->doc);
+            res = xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
+                                           (xmlNodePtr) ctxt->doc);
 	} else {
 	    /* Select "self::node()" */
 	    if (toBool)
 		return(1);
-            /* TODO: Check memory error. */
-	    xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, ctxt->node);
+            res = xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
+                                           ctxt->node);
 	}
+
+        if (res < 0)
+            xmlXPathPErrMemory(pctxt);
     }
     if (max_depth == 0) {
 	return(0);
@@ -13732,10 +12553,8 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp,
 
     patstream = xmlPatternGetStreamCtxt(comp);
     if (patstream == NULL) {
-	/*
-	* QUESTION TODO: Is this an error?
-	*/
-	return(0);
+        xmlXPathPErrMemory(pctxt);
+	return(-1);
     }
 
     eval_all_nodes = xmlStreamWantsAnyNode(patstream);
@@ -13746,8 +12565,8 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp,
 	} else if (ret == 1) {
 	    if (toBool)
 		goto return_1;
-            /* TODO: Check memory error. */
-	    xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur);
+	    if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur) < 0)
+                xmlXPathPErrMemory(pctxt);
 	}
     }
     depth = 0;
@@ -13756,16 +12575,13 @@ next_node:
     do {
         if (ctxt->opLimit != 0) {
             if (ctxt->opCount >= ctxt->opLimit) {
-                xmlGenericError(xmlGenericErrorContext,
-                        "XPath operation limit exceeded\n");
+                xmlXPathErr(ctxt, XPATH_RECURSION_LIMIT_EXCEEDED);
                 xmlFreeStreamCtxt(patstream);
                 return(-1);
             }
             ctxt->opCount++;
         }
 
-        nb_nodes++;
-
 	switch (cur->type) {
 	    case XML_ELEMENT_NODE:
 	    case XML_TEXT_NODE:
@@ -13781,15 +12597,13 @@ next_node:
 		    break;
 
 		if (ret < 0) {
-		    /* NOP. */
+		    xmlXPathPErrMemory(pctxt);
 		} else if (ret == 1) {
 		    if (toBool)
 			goto return_1;
-		    if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur)
-		        < 0) {
-			ctxt->lastError.domain = XML_FROM_XPATH;
-			ctxt->lastError.code = XML_ERR_NO_MEMORY;
-		    }
+		    if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
+                                                 cur) < 0)
+                        xmlXPathPErrMemory(pctxt);
 		}
 		if ((cur->children == NULL) || (depth >= max_depth)) {
 		    ret = xmlStreamPop(patstream);
@@ -13857,11 +12671,6 @@ scan_children:
 
 done:
 
-#if 0
-    printf("stream eval: checked %d nodes selected %d\n",
-           nb_nodes, retObj->nodesetval->nodeNr);
-#endif
-
     if (patstream)
 	xmlFreeStreamCtxt(patstream);
     return(0);
@@ -13894,13 +12703,12 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
 	ctxt->valueTab = (xmlXPathObjectPtr *)
 			 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
 	if (ctxt->valueTab == NULL) {
-	    xmlXPathPErrMemory(ctxt, "creating evaluation context\n");
+	    xmlXPathPErrMemory(ctxt);
 	    return(-1);
 	}
 	ctxt->valueNr = 0;
 	ctxt->valueMax = 10;
 	ctxt->value = NULL;
-        ctxt->valueFrame = 0;
     }
 #ifdef XPATH_STREAMING
     if (ctxt->comp->stream) {
@@ -13910,8 +12718,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
 	    /*
 	    * Evaluation to boolean result.
 	    */
-	    res = xmlXPathRunStreamEval(ctxt->context,
-		ctxt->comp->stream, NULL, 1);
+	    res = xmlXPathRunStreamEval(ctxt, ctxt->comp->stream, NULL, 1);
 	    if (res != -1)
 		return(res);
 	} else {
@@ -13920,8 +12727,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
 	    /*
 	    * Evaluation to a sequence.
 	    */
-	    res = xmlXPathRunStreamEval(ctxt->context,
-		ctxt->comp->stream, &resObj, 0);
+	    res = xmlXPathRunStreamEval(ctxt, ctxt->comp->stream, &resObj, 0);
 
 	    if ((res != -1) && (resObj != NULL)) {
 		valuePush(ctxt, resObj);
@@ -13938,8 +12744,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
 #endif
     comp = ctxt->comp;
     if (comp->last < 0) {
-	xmlGenericError(xmlGenericErrorContext,
-	    "xmlXPathRunEval: last is less than zero\n");
+        xmlXPathErr(ctxt, XPATH_STACK_ERROR);
 	return(-1);
     }
     oldDepth = ctxt->context->depth;
@@ -13992,7 +12797,7 @@ xmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) {
 	    return((res->stringval != NULL) &&
 	           (xmlStrlen(res->stringval) != 0));
         default:
-	    STRANGE
+	    break;
     }
     return(0);
 }
@@ -14043,7 +12848,7 @@ xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
 	    }
 #endif
         default:
-	    STRANGE
+	    break;
     }
     return(0);
 }
@@ -14074,6 +12879,7 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
     if ((!xmlStrchr(str, '[')) && (!xmlStrchr(str, '(')) &&
         (!xmlStrchr(str, '@'))) {
 	const xmlChar *tmp;
+        int res;
 
 	/*
 	 * We don't try to handle expressions using the verbose axis
@@ -14094,7 +12900,7 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
 	    if (ctxt->nsNr > 0) {
 		namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*));
 		if (namespaces == NULL) {
-		    xmlXPathErrMemory(ctxt, "allocating namespaces array\n");
+		    xmlXPathErrMemory(ctxt);
 		    return(NULL);
 		}
 		for (i = 0, j = 0; (j < ctxt->nsNr); j++) {
@@ -14107,14 +12913,20 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
 	    }
 	}
 
-	stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH, namespaces);
+	res = xmlPatternCompileSafe(str, dict, XML_PATTERN_XPATH, namespaces,
+                                    &stream);
 	if (namespaces != NULL) {
 	    xmlFree((xmlChar **)namespaces);
 	}
+        if (res < 0) {
+            xmlXPathErrMemory(ctxt);
+            return(NULL);
+        }
 	if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) {
 	    comp = xmlXPathNewCompExpr();
 	    if (comp == NULL) {
-		xmlXPathErrMemory(ctxt, "allocating streamable expression\n");
+		xmlXPathErrMemory(ctxt);
+	        xmlFreePattern(stream);
 		return(NULL);
 	    }
 	    comp->stream = stream;
@@ -14218,6 +13030,7 @@ xmlXPathOptimizeExpression(xmlXPathParserContextPtr pctxt,
 xmlXPathCompExprPtr
 xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
     xmlXPathParserContextPtr pctxt;
+    xmlXPathContextPtr tmpctxt = NULL;
     xmlXPathCompExprPtr comp;
     int oldDepth = 0;
 
@@ -14229,18 +13042,32 @@ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
 
     xmlInitParser();
 
+    /*
+     * We need an xmlXPathContext for the depth check.
+     */
+    if (ctxt == NULL) {
+        tmpctxt = xmlXPathNewContext(NULL);
+        if (tmpctxt == NULL)
+            return(NULL);
+        ctxt = tmpctxt;
+    }
+
     pctxt = xmlXPathNewParserContext(str, ctxt);
-    if (pctxt == NULL)
+    if (pctxt == NULL) {
+        if (tmpctxt != NULL)
+            xmlXPathFreeContext(tmpctxt);
         return NULL;
-    if (ctxt != NULL)
-        oldDepth = ctxt->depth;
+    }
+
+    oldDepth = ctxt->depth;
     xmlXPathCompileExpr(pctxt, 1);
-    if (ctxt != NULL)
-        ctxt->depth = oldDepth;
+    ctxt->depth = oldDepth;
 
     if( pctxt->error != XPATH_EXPRESSION_OK )
     {
         xmlXPathFreeParserContext(pctxt);
+        if (tmpctxt != NULL)
+            xmlXPathFreeContext(tmpctxt);
         return(NULL);
     }
 
@@ -14265,13 +13092,11 @@ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
 	pctxt->comp = NULL;
     }
     xmlXPathFreeParserContext(pctxt);
+    if (tmpctxt != NULL)
+        xmlXPathFreeContext(tmpctxt);
 
     if (comp != NULL) {
 	comp->expr = xmlStrdup(str);
-#ifdef DEBUG_EVAL_COUNTS
-	comp->string = xmlStrdup(str);
-	comp->nb = 0;
-#endif
     }
     return(comp);
 }
@@ -14310,47 +13135,34 @@ xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,
 			     int toBool)
 {
     xmlXPathParserContextPtr pctxt;
-    xmlXPathObjectPtr resObj;
+    xmlXPathObjectPtr resObj = NULL;
 #ifndef LIBXML_THREAD_ENABLED
     static int reentance = 0;
 #endif
     int res;
 
-    CHECK_CTXT_NEG(ctxt)
-
     if (comp == NULL)
 	return(-1);
     xmlInitParser();
 
+    xmlResetError(&ctxt->lastError);
+
 #ifndef LIBXML_THREAD_ENABLED
     reentance++;
     if (reentance > 1)
 	xmlXPathDisableOptimizer = 1;
 #endif
 
-#ifdef DEBUG_EVAL_COUNTS
-    comp->nb++;
-    if ((comp->string != NULL) && (comp->nb > 100)) {
-	fprintf(stderr, "100 x %s\n", comp->string);
-	comp->nb = 0;
-    }
-#endif
     pctxt = xmlXPathCompParserContext(comp, ctxt);
+    if (pctxt == NULL)
+        return(-1);
     res = xmlXPathRunEval(pctxt, toBool);
 
-    if (pctxt->error != XPATH_EXPRESSION_OK) {
-        resObj = NULL;
-    } else {
-        resObj = valuePop(pctxt);
-        if (resObj == NULL) {
-            if (!toBool)
-                xmlGenericError(xmlGenericErrorContext,
-                    "xmlXPathCompiledEval: No result on the stack.\n");
-        } else if (pctxt->valueNr > 0) {
-            xmlGenericError(xmlGenericErrorContext,
-                "xmlXPathCompiledEval: %d object(s) left on the stack.\n",
-                pctxt->valueNr);
-        }
+    if (pctxt->error == XPATH_EXPRESSION_OK) {
+        if (pctxt->valueNr != ((toBool) ? 0 : 1))
+            xmlXPathErr(pctxt, XPATH_STACK_ERROR);
+        else if (!toBool)
+            resObj = valuePop(pctxt);
     }
 
     if (resObjPtr)
@@ -14418,10 +13230,18 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
 #endif
     int oldDepth = 0;
 
-    if (ctxt == NULL) return;
+    if (ctxt == NULL)
+        return;
+    if (ctxt->context->lastError.code != 0)
+        return;
 
 #ifdef XPATH_STREAMING
     comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base);
+    if ((comp == NULL) &&
+        (ctxt->context->lastError.code == XML_ERR_NO_MEMORY)) {
+        xmlXPathPErrMemory(ctxt);
+        return;
+    }
     if (comp != NULL) {
         if (ctxt->comp != NULL)
 	    xmlXPathFreeCompExpr(ctxt->comp);
@@ -14468,10 +13288,13 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
     xmlXPathParserContextPtr ctxt;
     xmlXPathObjectPtr res;
 
-    CHECK_CTXT(ctx)
+    if (ctx == NULL)
+        return(NULL);
 
     xmlInitParser();
 
+    xmlResetError(&ctx->lastError);
+
     ctxt = xmlXPathNewParserContext(str, ctx);
     if (ctxt == NULL)
         return NULL;
@@ -14479,16 +13302,11 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
 
     if (ctxt->error != XPATH_EXPRESSION_OK) {
 	res = NULL;
+    } else if (ctxt->valueNr != 1) {
+        xmlXPathErr(ctxt, XPATH_STACK_ERROR);
+	res = NULL;
     } else {
 	res = valuePop(ctxt);
-        if (res == NULL) {
-            xmlGenericError(xmlGenericErrorContext,
-                "xmlXPathCompiledEval: No result on the stack.\n");
-        } else if (ctxt->valueNr > 0) {
-            xmlGenericError(xmlGenericErrorContext,
-                "xmlXPathCompiledEval: %d object(s) left on the stack.\n",
-                ctxt->valueNr);
-        }
     }
 
     xmlXPathFreeParserContext(ctxt);
@@ -14621,7 +13439,7 @@ xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     CAST_TO_STRING;
     str = valuePop(ctxt);
 
-    target = xmlBufCreate();
+    target = xmlBufCreateSize(64);
 
     escape[0] = '%';
     escape[3] = 0;
@@ -14661,8 +13479,7 @@ xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
 	    }
 	}
     }
-    valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
-	xmlBufContent(target)));
+    valuePush(ctxt, xmlXPathCacheNewString(ctxt, xmlBufContent(target)));
     xmlBufFree(target);
     xmlXPathReleaseObject(ctxt->context, str);
 }
diff --git a/xpointer.c b/xpointer.c
index ba1e31e0d0b1df0353059660350691e9295cf541..87ea85bbf7034086264e41b0080e3c7a84c6b5ff 100644
--- a/xpointer.c
+++ b/xpointer.c
@@ -38,29 +38,14 @@
 #include <libxml/xpath.h>
 #include <libxml/xpathInternals.h>
 #include <libxml/xmlerror.h>
-#include <libxml/globals.h>
 
 #ifdef LIBXML_XPTR_ENABLED
 
 /* Add support of the xmlns() xpointer scheme to initialize the namespaces */
 #define XPTR_XMLNS_SCHEME
 
-/* #define DEBUG_RANGES */
-#ifdef DEBUG_RANGES
-#ifdef LIBXML_DEBUG_ENABLED
-#include <libxml/debugXML.h>
-#endif
-#endif
-
-#define TODO								\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Unimplemented block at %s:%d\n",				\
-            __FILE__, __LINE__);
-
-#define STRANGE							\
-    xmlGenericError(xmlGenericErrorContext,				\
-	    "Internal error at %s:%d\n",				\
-            __FILE__, __LINE__);
+#include "private/error.h"
+#include "private/xpath.h"
 
 /************************************************************************
  *									*
@@ -68,63 +53,59 @@
  *									*
  ************************************************************************/
 
-/**
- * xmlXPtrErrMemory:
- * @extra:  extra information
- *
- * Handle a redefinition of attribute error
- */
-static void
-xmlXPtrErrMemory(const char *extra)
-{
-    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_XPOINTER,
-		    XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra,
-		    NULL, NULL, 0, 0,
-		    "Memory allocation failed : %s\n", extra);
-}
-
 /**
  * xmlXPtrErr:
  * @ctxt:  an XPTR evaluation context
  * @extra:  extra information
  *
- * Handle a redefinition of attribute error
+ * Handle an XPointer error
  */
 static void LIBXML_ATTR_FORMAT(3,0)
-xmlXPtrErr(xmlXPathParserContextPtr ctxt, int error,
+xmlXPtrErr(xmlXPathParserContextPtr ctxt, int code,
            const char * msg, const xmlChar *extra)
 {
-    if (ctxt != NULL)
-        ctxt->error = error;
-    if ((ctxt == NULL) || (ctxt->context == NULL)) {
-	__xmlRaiseError(NULL, NULL, NULL,
-			NULL, NULL, XML_FROM_XPOINTER, error,
-			XML_ERR_ERROR, NULL, 0,
-			(const char *) extra, NULL, NULL, 0, 0,
-			msg, extra);
-	return;
-    }
+    xmlStructuredErrorFunc serror = NULL;
+    void *data = NULL;
+    xmlNodePtr node = NULL;
+    int res;
 
-    /* cleanup current last error */
-    xmlResetError(&ctxt->context->lastError);
+    if (ctxt == NULL)
+        return;
+    /* Only report the first error */
+    if (ctxt->error != 0)
+        return;
 
-    ctxt->context->lastError.domain = XML_FROM_XPOINTER;
-    ctxt->context->lastError.code = error;
-    ctxt->context->lastError.level = XML_ERR_ERROR;
-    ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base);
-    ctxt->context->lastError.int1 = ctxt->cur - ctxt->base;
-    ctxt->context->lastError.node = ctxt->context->debugNode;
-    if (ctxt->context->error != NULL) {
-	ctxt->context->error(ctxt->context->userData,
-	                     &ctxt->context->lastError);
-    } else {
-	__xmlRaiseError(NULL, NULL, NULL,
-			NULL, ctxt->context->debugNode, XML_FROM_XPOINTER,
-			error, XML_ERR_ERROR, NULL, 0,
-			(const char *) extra, (const char *) ctxt->base, NULL,
-			ctxt->cur - ctxt->base, 0,
-			msg, extra);
+    ctxt->error = code;
+
+    if (ctxt->context != NULL) {
+        xmlErrorPtr err = &ctxt->context->lastError;
+
+        /* cleanup current last error */
+        xmlResetError(err);
+
+        err->domain = XML_FROM_XPOINTER;
+        err->code = code;
+        err->level = XML_ERR_ERROR;
+        err->str1 = (char *) xmlStrdup(ctxt->base);
+        if (err->str1 == NULL) {
+            xmlXPathPErrMemory(ctxt);
+            return;
+        }
+        err->int1 = ctxt->cur - ctxt->base;
+        err->node = ctxt->context->debugNode;
+
+        serror = ctxt->context->error;
+        data = ctxt->context->userData;
+        node = ctxt->context->debugNode;
     }
+
+    res = __xmlRaiseError(serror, NULL, data, NULL, node,
+                          XML_FROM_XPOINTER, code, XML_ERR_ERROR, NULL, 0,
+                          (const char *) extra, (const char *) ctxt->base,
+                          NULL, ctxt->cur - ctxt->base, 0,
+                          msg, extra);
+    if (res < 0)
+        xmlXPathPErrMemory(ctxt);
 }
 
 /************************************************************************
@@ -214,6 +195,18 @@ xmlXPtrGetNthChild(xmlNodePtr cur, int no) {
  *									*
  ************************************************************************/
 
+/**
+ * xmlXPtrErrMemory:
+ * @extra:  extra information
+ *
+ * Handle a redefinition of attribute error
+ */
+static void
+xmlXPtrErrMemory(const char *extra ATTRIBUTE_UNUSED)
+{
+    xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_XPOINTER, NULL);
+}
+
 /**
  * xmlXPtrCmpPoints:
  * @node1:  the first node
@@ -266,7 +259,7 @@ xmlXPtrNewPoint(xmlNodePtr node, int indx) {
         xmlXPtrErrMemory("allocating point");
 	return(NULL);
     }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_POINT;
     ret->user = (void *) node;
     ret->index = indx;
@@ -586,7 +579,7 @@ xmlXPtrLocationSetCreate(xmlXPathObjectPtr val) {
         xmlXPtrErrMemory("allocating locationset");
 	return(NULL);
     }
-    memset(ret, 0 , (size_t) sizeof(xmlLocationSet));
+    memset(ret, 0 , sizeof(xmlLocationSet));
     if (val != NULL) {
         ret->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
 					     sizeof(xmlXPathObjectPtr));
@@ -596,7 +589,7 @@ xmlXPtrLocationSetCreate(xmlXPathObjectPtr val) {
 	    return(NULL);
 	}
 	memset(ret->locTab, 0 ,
-	       XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr));
+	       XML_RANGESET_DEFAULT * sizeof(xmlXPathObjectPtr));
         ret->locMax = XML_RANGESET_DEFAULT;
 	ret->locTab[ret->locNr++] = val;
     }
@@ -638,7 +631,7 @@ xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
 	    return;
 	}
 	memset(cur->locTab, 0 ,
-	       XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr));
+	       XML_RANGESET_DEFAULT * sizeof(xmlXPathObjectPtr));
         cur->locMax = XML_RANGESET_DEFAULT;
     } else if (cur->locNr == cur->locMax) {
         xmlXPathObjectPtr *temp;
@@ -703,10 +696,6 @@ xmlXPtrLocationSetDel(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
         if (cur->locTab[i] == val) break;
 
     if (i >= cur->locNr) {
-#ifdef DEBUG
-        xmlGenericError(xmlGenericErrorContext,
-	        "xmlXPtrLocationSetDel: Range wasn't found in RangeList\n");
-#endif
         return;
     }
     cur->locNr--;
@@ -771,7 +760,7 @@ xmlXPtrNewLocationSetNodes(xmlNodePtr start, xmlNodePtr end) {
         xmlXPtrErrMemory("allocating locationset");
 	return(NULL);
     }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_LOCATIONSET;
     if (end == NULL)
 	ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewCollapsedRange(start));
@@ -798,7 +787,7 @@ xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set) {
         xmlXPtrErrMemory("allocating locationset");
 	return(NULL);
     }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0, sizeof(xmlXPathObject));
     ret->type = XPATH_LOCATIONSET;
     if (set != NULL) {
 	int i;
@@ -834,7 +823,7 @@ xmlXPtrWrapLocationSet(xmlLocationSetPtr val) {
         xmlXPtrErrMemory("allocating locationset");
 	return(NULL);
     }
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    memset(ret, 0, sizeof(xmlXPathObject));
     ret->type = XPATH_LOCATIONSET;
     ret->user = (void *) val;
     return(ret);
@@ -967,9 +956,9 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
 
     len = xmlStrlen(ctxt->cur);
     len++;
-    buffer = (xmlChar *) xmlMallocAtomic(len * sizeof (xmlChar));
+    buffer = (xmlChar *) xmlMallocAtomic(len);
     if (buffer == NULL) {
-        xmlXPtrErrMemory("allocating buffer");
+        xmlXPathPErrMemory(ctxt);
         xmlFree(name);
 	return;
     }
@@ -1070,7 +1059,8 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
 	NEXT;
 	SKIP_BLANKS;
 
-	xmlXPathRegisterNs(ctxt->context, prefix, ctxt->cur);
+	if (xmlXPathRegisterNs(ctxt->context, prefix, ctxt->cur) < 0)
+            xmlXPathPErrMemory(ctxt);
         ctxt->base = oldBase;
         ctxt->cur = oldCur;
 	xmlFree(prefix);
@@ -1240,13 +1230,12 @@ xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) {
 	ctxt->valueTab = (xmlXPathObjectPtr *)
 			 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
 	if (ctxt->valueTab == NULL) {
-	    xmlXPtrErrMemory("allocating evaluation context");
+	    xmlXPathPErrMemory(ctxt);
 	    return;
 	}
 	ctxt->valueNr = 0;
 	ctxt->valueMax = 10;
 	ctxt->value = NULL;
-	ctxt->valueFrame = 0;
     }
     SKIP_BLANKS;
     if (CUR == '/') {
@@ -1362,10 +1351,16 @@ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
     if ((ctx == NULL) || (str == NULL))
 	return(NULL);
 
+    xmlResetError(&ctx->lastError);
+
     ctxt = xmlXPathNewParserContext(str, ctx);
-    if (ctxt == NULL)
+    if (ctxt == NULL) {
+        xmlXPathErrMemory(ctx);
 	return(NULL);
+    }
     xmlXPtrEvalXPointer(ctxt);
+    if (ctx->lastError.code != XML_ERR_OK)
+        goto error;
 
     if ((ctxt->value != NULL) &&
 #ifdef LIBXML_XPTR_LOCS_ENABLED
@@ -1403,11 +1398,12 @@ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
 		   "xmlXPtrEval: object(s) left on the eval stack\n",
 		   NULL);
     }
-    if (ctxt->error != XPATH_EXPRESSION_OK) {
+    if (ctx->lastError.code != XML_ERR_OK) {
 	xmlXPathFreeObject(res);
 	res = NULL;
     }
 
+error:
     xmlXPathFreeParserContext(ctxt);
     return(res);
 }
@@ -1546,7 +1542,7 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
 		    /* Do not copy DTD information */
 		    break;
 		case XML_ENTITY_DECL:
-		    TODO /* handle crossing entities -> stack needed */
+		    /* TODO: handle crossing entities -> stack needed */
 		    break;
 		case XML_XINCLUDE_START:
 		case XML_XINCLUDE_END:
@@ -1554,7 +1550,6 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
 		    break;
 		case XML_ATTRIBUTE_NODE:
 		    /* Humm, should not happen ! */
-		    STRANGE
 		    break;
 		default:
 		    tmp = xmlCopyNode(cur, 1);
@@ -1562,7 +1557,6 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
 	    }
 	    if (tmp != NULL) {
 		if ((list == NULL) || ((last == NULL) && (parent == NULL)))  {
-		    STRANGE
 		    return(NULL);
 		}
 		if (last != NULL)
@@ -1576,7 +1570,6 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
 	 * Skip to next node in document order
 	 */
 	if ((list == NULL) || ((last == NULL) && (parent == NULL)))  {
-	    STRANGE
 	    return(NULL);
 	}
 	cur = xmlXPtrAdvanceNode(cur, NULL);
@@ -2005,7 +1998,8 @@ xmlXPtrCoveringRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
 		}
 	    }
 	default:
-	    TODO /* missed one case ??? */
+	    /* TODO: missed one case ??? */
+            break;
     }
     return(NULL);
 }
@@ -2152,7 +2146,8 @@ xmlXPtrInsideRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
 	    }
         }
 	default:
-	    TODO /* missed one case ??? */
+	    /* TODO: missed one case ??? */
+            break;
     }
     return(NULL);
 }
@@ -2287,7 +2282,6 @@ found:
 	(cur->type != XML_HTML_DOCUMENT_NODE) &&
 	(cur->type != XML_CDATA_SECTION_NODE)) {
 	    if (cur->type == XML_ENTITY_REF_NODE) {	/* Shouldn't happen */
-		TODO
 		goto skip;
 	    }
 	    goto next;
@@ -2361,7 +2355,6 @@ xmlXPtrAdvanceChar(xmlNodePtr *node, int *indx, int bytes) {
 	}
 	if (pos > len) {
 	    /* Strange, the indx in the text node is greater than it's len */
-	    STRANGE
 	    pos = len;
 	}
 	if (pos + bytes >= len) {
@@ -2423,13 +2416,6 @@ xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex,
 	    if (len >= pos + stringlen) {
 		match = (!xmlStrncmp(&cur->content[pos], string, stringlen));
 		if (match) {
-#ifdef DEBUG_RANGES
-		    xmlGenericError(xmlGenericErrorContext,
-			    "found range %d bytes at index %d of ->",
-			    stringlen, pos + 1);
-		    xmlDebugDumpString(stdout, cur->content);
-		    xmlGenericError(xmlGenericErrorContext, "\n");
-#endif
 		    *end = cur;
 		    *endindex = pos + stringlen;
 		    return(1);
@@ -2440,13 +2426,6 @@ xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex,
                 int sub = len - pos;
 		match = (!xmlStrncmp(&cur->content[pos], string, sub));
 		if (match) {
-#ifdef DEBUG_RANGES
-		    xmlGenericError(xmlGenericErrorContext,
-			    "found subrange %d bytes at index %d of ->",
-			    sub, pos + 1);
-		    xmlDebugDumpString(stdout, cur->content);
-		    xmlGenericError(xmlGenericErrorContext, "\n");
-#endif
                     string = &string[sub];
 		    stringlen -= sub;
 		} else {
@@ -2506,13 +2485,6 @@ xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex,
 		    str = xmlStrchr(&cur->content[pos], first);
 		    if (str != NULL) {
 			pos = (str - (xmlChar *)(cur->content));
-#ifdef DEBUG_RANGES
-			xmlGenericError(xmlGenericErrorContext,
-				"found '%c' at index %d of ->",
-				first, pos + 1);
-			xmlDebugDumpString(stdout, cur->content);
-			xmlGenericError(xmlGenericErrorContext, "\n");
-#endif
 			if (xmlXPtrMatchString(string, cur, pos + 1,
 					       end, endindex)) {
 			    *start = cur;
@@ -2529,13 +2501,6 @@ xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex,
 		     * character of the string-value and after the final
 		     * character.
 		     */
-#ifdef DEBUG_RANGES
-		    xmlGenericError(xmlGenericErrorContext,
-			    "found '' at index %d of ->",
-			    pos + 1);
-		    xmlDebugDumpString(stdout, cur->content);
-		    xmlGenericError(xmlGenericErrorContext, "\n");
-#endif
 		    *start = cur;
 		    *startindex = pos + 1;
 		    *end = cur;
@@ -2785,25 +2750,12 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
      * the list of location set corresponding to that search
      */
     for (i = 0;i < oldset->locNr;i++) {
-#ifdef DEBUG_RANGES
-	xmlXPathDebugDumpObject(stdout, oldset->locTab[i], 0);
-#endif
 
 	xmlXPtrGetStartPoint(oldset->locTab[i], &start, &startindex);
 	xmlXPtrGetEndPoint(oldset->locTab[i], &end, &endindex);
 	xmlXPtrAdvanceChar(&start, &startindex, 0);
 	xmlXPtrGetLastChar(&end, &endindex);
 
-#ifdef DEBUG_RANGES
-	xmlGenericError(xmlGenericErrorContext,
-		"from index %d of ->", startindex);
-	xmlDebugDumpString(stdout, start->content);
-	xmlGenericError(xmlGenericErrorContext, "\n");
-	xmlGenericError(xmlGenericErrorContext,
-		"to index %d of ->", endindex);
-	xmlDebugDumpString(stdout, end->content);
-	xmlGenericError(xmlGenericErrorContext, "\n");
-#endif
 	do {
             fend = end;
             fendindex = endindex;
diff --git a/xzlib.c b/xzlib.c
index b2350b9053609135cf6db1cde3d2a27342155160..9a106b90e2c31549618f5e730f91200eed44d9da 100644
--- a/xzlib.c
+++ b/xzlib.c
@@ -14,9 +14,6 @@
 #include <stdlib.h>
 #include <errno.h>
 
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
@@ -25,6 +22,8 @@
 #endif
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#elif defined (_WIN32)
+#include <io.h>
 #endif
 #ifdef LIBXML_ZLIB_ENABLED
 #include <vtk_zlib.h>
@@ -33,7 +32,7 @@
 #include <lzma.h>
 #endif
 
-#include "xzlib.h"
+#include "private/xzlib.h"
 #include <libxml/xmlmemory.h>
 
 /* values for xz_state how */
@@ -134,6 +133,7 @@ static xzFile
 xz_open(const char *path, int fd, const char *mode ATTRIBUTE_UNUSED)
 {
     xz_statep state;
+    off_t offset;
 
     /* allocate xzFile structure to return */
     state = xmlMalloc(sizeof(xz_state));
@@ -168,9 +168,11 @@ xz_open(const char *path, int fd, const char *mode ATTRIBUTE_UNUSED)
     }
 
     /* save the current position for rewinding (only if reading) */
-    state->start = lseek(state->fd, 0, SEEK_CUR);
-    if (state->start == (uint64_t) - 1)
+    offset = lseek(state->fd, 0, SEEK_CUR);
+    if (offset == -1)
         state->start = 0;
+    else
+        state->start = offset;
 
     /* initialize stream */
     xz_reset(state);
@@ -193,6 +195,12 @@ xz_compressed(xzFile f) {
         case COPY:
 	    return(0);
 	case GZIP:
+#ifdef LIBXML_ZLIB_ENABLED
+            /* Don't use lzma for gzip */
+	    return(0);
+#else
+	    return(1);
+#endif
 	case LZMA:
 	    return(1);
     }
@@ -205,23 +213,10 @@ __libxml2_xzopen(const char *path, const char *mode)
     return xz_open(path, -1, mode);
 }
 
-int
-__libxml2_xzcompressed(xzFile f) {
-    return xz_compressed(f);
-}
-
 xzFile
-__libxml2_xzdopen(int fd, const char *mode)
+__libxml2_xzdopen(const char *path, int fd, const char *mode)
 {
-    char *path;                 /* identifier for error messages */
-    xzFile xz;
-
-    if (fd == -1 || (path = xmlMalloc(7 + 3 * sizeof(int))) == NULL)
-        return NULL;
-    sprintf(path, "<fd:%d>", fd);       /* for debugging */
-    xz = xz_open(path, fd, mode);
-    xmlFree(path);
-    return xz;
+    return xz_open(path, fd, mode);
 }
 
 static int
@@ -317,8 +312,12 @@ is_format_lzma(xz_statep state)
      * If someone complains, this will be reconsidered.
      */
     if (dict_size != UINT32_MAX) {
-        uint32_t d = dict_size - 1;
+        uint32_t d;
 
+        if (dict_size == 0)
+            return 0;
+
+        d = dict_size - 1;
         d |= d >> 2;
         d |= d >> 3;
         d |= d >> 4;
@@ -697,6 +696,13 @@ xz_skip(xz_statep state, uint64_t len)
     return 0;
 }
 
+int
+__libxml2_xzcompressed(xzFile f) {
+    xz_head(f);
+
+    return xz_compressed(f);
+}
+
 int
 __libxml2_xzread(xzFile file, void *buf, unsigned len)
 {