change a small bit in the way valididy error messages get initialized

* parserInternals.c: change a small bit in the way valididy
  error messages get initialized
* python/TODO python/libxml.c python/libxml2-python-api.xml
  python/libxml2class.txt python/libxml_wrap.h python/types.c:
  added some memory debugging to track leaks at the libxml2 level
* python/tests/*.py: changed all tests to check for leaks,
  there is just one left in XPath extension registrations.
daniel
diff --git a/python/TODO b/python/TODO
index d1799fb..24f94d1 100644
--- a/python/TODO
+++ b/python/TODO
@@ -6,17 +6,11 @@
 -------------
 
 - SAX interfaces
-- memory debug interfaces
 - enums -> libxml.py
 - access to XPath variables
-- parserCtxt exposure:
-  - entry points
-  - wrappers
-  - decent interface for setting/getting behaviour
 - xmlBuffer exposure
 - xpathContext, being able to set/get info and clean it up
 - add regression tests
-   - check memory
    - build tree
    - saving
    - SAX flow
@@ -33,6 +27,7 @@
    - tests/Makefile.am: export the Python class path
    - xpath queries
    - xpath extension
+   - check memory
 - extensions based on a python.xml description of the new specific
   interfaces
    file libxml2-python-api.xml , first entry is xmlRegisterXPathFunction
@@ -43,5 +38,9 @@
 - handling of node.content
 - access to xmlParserCtxt and push mode
    - needed for SAX too
+   - entry points
+   - wrappers
+   - decent interface for setting/getting behaviour
+- memory debug interfaces
 
 Daniel Veillard
diff --git a/python/libxml.c b/python/libxml.c
index 57e370f..e37038a 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -15,12 +15,99 @@
 #include <libxml/xpath.h>
 #include <libxml/xmlerror.h>
 #include <libxml/xpathInternals.h>
+#include <libxml/xmlmemory.h>
 #include "libxml_wrap.h"
 #include "libxml2-py.h"
 
 /* #define DEBUG */
 /* #define DEBUG_XPATH */
 /* #define DEBUG_ERROR */
+/* #define DEBUG_MEMORY */
+
+/************************************************************************
+ *									*
+ *		Memory debug interface					*
+ *									*
+ ************************************************************************/
+
+extern void xmlMemFree(void *ptr);
+extern void *xmlMemMalloc(size_t size);
+extern void *xmlMemRealloc(void *ptr,size_t size);
+extern char *xmlMemoryStrdup(const char *str);
+
+static int libxmlMemoryDebugActivated = 0;
+static long libxmlMemoryAllocatedBase = 0;
+
+static int libxmlMemoryDebug = 0;
+static xmlFreeFunc freeFunc = NULL;
+static xmlMallocFunc mallocFunc = NULL;
+static xmlReallocFunc reallocFunc = NULL;
+static xmlStrdupFunc strdupFunc = NULL;
+
+PyObject *
+libxml_xmlDebugMemory(PyObject *self, PyObject *args) {
+    int activate;
+    PyObject *py_retval;
+    long ret;
+
+    if (!PyArg_ParseTuple(args, "i:xmlDebugMemory", &activate))
+        return(NULL);
+
+#ifdef DEBUG_MEMORY
+    printf("libxml_xmlDebugMemory(%d) called\n", activate);
+#endif
+
+    if (activate != 0) {
+	if (libxmlMemoryDebug == 0) {
+	    /*
+	     * First initialize the library and grab the old memory handlers
+	     * and switch the library to memory debugging
+	     */
+	    xmlMemGet((xmlFreeFunc *) &freeFunc,
+		      (xmlMallocFunc *)&mallocFunc,
+		      (xmlReallocFunc *)&reallocFunc,
+		      (xmlStrdupFunc *) &strdupFunc);
+	    if ((freeFunc == xmlMemFree) && (mallocFunc == xmlMemMalloc) &&
+		(reallocFunc == xmlMemRealloc) &&
+		(strdupFunc == xmlMemoryStrdup)) {
+		libxmlMemoryAllocatedBase = xmlMemUsed();
+	    } else {
+		ret = (long) xmlMemSetup(xmlMemFree, xmlMemMalloc,
+			                 xmlMemRealloc, xmlMemoryStrdup);
+		if (ret < 0)
+		    goto error;
+		libxmlMemoryAllocatedBase = xmlMemUsed();
+	    }
+	    xmlInitParser();
+	    ret = 0;
+	} else if (libxmlMemoryDebugActivated == 0) {
+	    libxmlMemoryAllocatedBase = xmlMemUsed();
+	    ret = 0;
+	} else {
+	    ret = xmlMemUsed() - libxmlMemoryAllocatedBase;
+	}
+	libxmlMemoryDebug = 1;
+	libxmlMemoryDebugActivated = 1;
+    } else {
+	if (libxmlMemoryDebugActivated == 1)
+	    ret = xmlMemUsed() - libxmlMemoryAllocatedBase;
+	else
+	    ret = 0;
+	libxmlMemoryDebugActivated = 0;
+    }
+error:
+    py_retval = libxml_longWrap(ret);
+    return(py_retval);
+}
+
+PyObject *
+libxml_xmlDumpMemory(PyObject *self, PyObject *args) {
+
+    if (libxmlMemoryDebug != 0)
+	xmlMemoryDump();
+    Py_INCREF(Py_None);
+    return(Py_None);
+}
 
 /************************************************************************
  *									*
@@ -68,6 +155,36 @@
     return(pyret);
 }
 
+PyObject *
+libxml_htmlCreatePushParser(PyObject *self, PyObject *args) {
+    xmlChar *chunk;
+    int size;
+    xmlChar *URI;
+    PyObject *pyobj_SAX;
+    xmlSAXHandlerPtr SAX = NULL;
+    pySAXhandlerPtr SAXdata = NULL; 
+    xmlParserCtxtPtr ret;
+    PyObject *pyret;
+
+    if (!PyArg_ParseTuple(args, "Oziz:htmlCreatePushParser", &pyobj_SAX,
+		          &chunk, &size, &URI))
+        return(NULL);
+
+#ifdef DEBUG_ERROR
+    printf("libxml_htmlCreatePushParser(%p, %s, %d, %s) called\n",
+	   pyobj_SAX, chunk, size, URI);
+#endif
+    if (pyobj_SAX != Py_None) {
+	printf("htmlCreatePushParser: event interface not supported yet !\n");
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    ret = htmlCreatePushParserCtxt(SAX, SAXdata, chunk, size, URI,
+	                           XML_CHAR_ENCODING_NONE);
+    pyret = libxml_xmlParserCtxtPtrWrap(ret);
+    return(pyret);
+}
+
 /************************************************************************
  *									*
  *			Error message callback				*
diff --git a/python/libxml2-python-api.xml b/python/libxml2-python-api.xml
index 2c5eb04..a830c75 100644
--- a/python/libxml2-python-api.xml
+++ b/python/libxml2-python-api.xml
@@ -21,7 +21,15 @@
       <arg name='ctx' type='pythonObject' info='a context for the callback'/>
     </function>
     <function name='xmlCreatePushParser' file='python'>
-      <info>Create a progressive parser context to build either an event flow if the SAX object is not None, or a DOM tree otherwise.</info>
+      <info>Create a progressive XML parser context to build either an event flow if the SAX object is not None, or a DOM tree otherwise.</info>
+      <return type='xmlParserCtxtPtr' info="the parser context or None in case of error"/>
+      <arg name='SAX' type='pythonObject' info='the SAX callback object or None'/>
+      <arg name='chunk' type='xmlChar *' info='the initial data'/>
+      <arg name='size' type='int' info='the size of the initial data'/>
+      <arg name='URI' type='xmlChar *' info='The URI used for base computations'/>
+    </function>
+    <function name='htmlCreatePushParser' file='python'>
+      <info>Create a progressive HTML parser context to build either an event flow if the SAX object is not None, or a DOM tree otherwise.</info>
       <return type='xmlParserCtxtPtr' info="the parser context or None in case of error"/>
       <arg name='SAX' type='pythonObject' info='the SAX callback object or None'/>
       <arg name='chunk' type='xmlChar *' info='the initial data'/>
@@ -73,5 +81,14 @@
       <arg name='ctxt' type='xmlParserCtxtPtr' info='the parser context'/>
       <arg name='linenumbers' type='int' info='1 to save line numbers'/>
     </function>
+    <function name='xmlDebugMemory' file='python'>
+      <info>Switch on the generation of line number for elements nodes. Also returns the number of bytes allocated and not freed by libxml2 since memory debugging was switched on.</info>
+      <return type='int' info="returns the number of bytes allocated and not freed"/>
+      <arg name='activate' type='int' info='1 switch on memory debugging 0 switch it off'/>
+    </function>
+    <function name='xmlDumpMemory' file='python'>
+      <info>dump the memory allocated in the file .memdump</info>
+      <return type='void'/>
+    </function>
   </symbols>
 </api>
diff --git a/python/libxml2class.txt b/python/libxml2class.txt
index 374fe48..cb12a2f 100644
--- a/python/libxml2class.txt
+++ b/python/libxml2class.txt
@@ -115,6 +115,9 @@
 
 # functions from module python
 createPushParser()
+debugMemory()
+dumpMemory()
+htmlCreatePushParser()
 registerErrorHandler()
 
 # functions from module tree
diff --git a/python/libxml_wrap.h b/python/libxml_wrap.h
index d6d89aa..68daf01 100644
--- a/python/libxml_wrap.h
+++ b/python/libxml_wrap.h
@@ -35,6 +35,7 @@
 } PyparserCtxt_Object;
 
 PyObject * libxml_intWrap(int val);
+PyObject * libxml_longWrap(long val);
 PyObject * libxml_xmlCharPtrWrap(xmlChar *str);
 PyObject * libxml_constxmlCharPtrWrap(const xmlChar *str);
 PyObject * libxml_charPtrWrap(char *str);
diff --git a/python/tests/error.py b/python/tests/error.py
index 21cf558..9337945 100755
--- a/python/tests/error.py
+++ b/python/tests/error.py
@@ -6,6 +6,9 @@
 import sys
 import libxml2
 
+# Memory debug specific
+libxml2.debugMemory(1)
+
 expect='--> warning: --> failed to load external entity "missing.xml"\n'
 err=""
 def callback(ctx, str):
@@ -27,4 +30,10 @@
     err = ""
     i = i - 1
 
-print "OK"
+# Memory debug specific
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+    print "OK"
+else:
+    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+    libxml2.dumpMemory()
diff --git a/python/tests/push.py b/python/tests/push.py
index 738d3e9..5b60a16 100755
--- a/python/tests/push.py
+++ b/python/tests/push.py
@@ -2,6 +2,9 @@
 import sys
 import libxml2
 
+# Memory debug specific
+libxml2.debugMemory(1)
+
 ctxt = libxml2.createPushParser(None, "<foo", 4, "test.xml")
 ctxt.parseChunk("/>", 2, 1)
 doc = ctxt.doc()
@@ -22,4 +25,11 @@
     doc.freeDoc()
     i = i -1
 ctxt=None
-print "OK"
+
+# Memory debug specific
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+    print "OK"
+else:
+    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+    libxml2.dumpMemory()
diff --git a/python/tests/tst.py b/python/tests/tst.py
index dc6e4d4..9540cda 100755
--- a/python/tests/tst.py
+++ b/python/tests/tst.py
@@ -2,6 +2,9 @@
 import sys
 import libxml2
 
+# Memory debug specific
+libxml2.debugMemory(1)
+
 doc = libxml2.parseFile("tst.xml")
 if doc.name != "tst.xml":
     print "doc.name failed"
@@ -15,4 +18,11 @@
     print "child.name failed"
     sys.exit(1)
 doc.freeDoc()
-print "OK"
+
+# Memory debug specific
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+    print "OK"
+else:
+    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+    libxml2.dumpMemory()
diff --git a/python/tests/tstxpath.py b/python/tests/tstxpath.py
index 97d392c..9fc3d4c 100755
--- a/python/tests/tstxpath.py
+++ b/python/tests/tstxpath.py
@@ -2,6 +2,10 @@
 import sys
 import libxml2
 
+#memory debug specific
+libxml2.debugMemory(1)
+
+
 def foo(x):
     return x + 1
 
@@ -35,4 +39,12 @@
 	sys.exit(1)
     i = i - 1
 doc.freeDoc()
-print "OK"
+del ctxt
+
+#memory debug specific
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+    print "OK"
+else:
+    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+    libxml2.dumpMemory()
diff --git a/python/tests/validate.py b/python/tests/validate.py
index 5762f60..e9841a9 100755
--- a/python/tests/validate.py
+++ b/python/tests/validate.py
@@ -2,6 +2,9 @@
 import sys
 import libxml2
 
+# Memory debug specific
+libxml2.debugMemory(1)
+
 ctxt = libxml2.createFileParserCtxt("valid.xml")
 ctxt.validate(1)
 ctxt.parseDocument()
@@ -68,5 +71,12 @@
 	print "validity check failed"
 	sys.exit(1)
     i = i - 1
+del ctxt
 
-print "OK"
+# Memory debug specific
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+    print "OK"
+else:
+    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+    libxml2.dumpMemory()
diff --git a/python/tests/xpath.py b/python/tests/xpath.py
index 49a697f..0d35a99 100755
--- a/python/tests/xpath.py
+++ b/python/tests/xpath.py
@@ -6,6 +6,9 @@
 import sys
 import libxml2
 
+# Memory debug specific
+libxml2.debugMemory(1)
+
 doc = libxml2.parseFile("tst.xml")
 if doc.name != "tst.xml":
     print "doc.name error"
@@ -27,4 +30,12 @@
     res = ctxt.xpathEval("//*")
     doc.freeDoc()
     i = i -1
-print "OK"
+del ctxt
+
+# Memory debug specific
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+    print "OK"
+else:
+    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+    libxml2.dumpMemory()
diff --git a/python/tests/xpathext.py b/python/tests/xpathext.py
index 97d392c..14cb69f 100755
--- a/python/tests/xpathext.py
+++ b/python/tests/xpathext.py
@@ -2,6 +2,9 @@
 import sys
 import libxml2
 
+# Memory debug specific
+libxml2.debugMemory(1)
+
 def foo(x):
     return x + 1
 
@@ -35,4 +38,12 @@
 	sys.exit(1)
     i = i - 1
 doc.freeDoc()
-print "OK"
+del ctxt
+
+# Memory debug specific
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+    print "OK"
+else:
+    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+    libxml2.dumpMemory()
diff --git a/python/types.c b/python/types.c
index 07a178e..56f472f 100644
--- a/python/types.c
+++ b/python/types.c
@@ -20,6 +20,17 @@
 }
 
 PyObject *
+libxml_longWrap(long val) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_longWrap: val = %ld\n", val);
+#endif
+    ret = PyInt_FromLong(val);
+    return(ret);
+}
+
+PyObject *
 libxml_doubleWrap(double val) {
     PyObject *ret;