Added call to create/free parser contexts, + doc, Daniel.
diff --git a/parser.c b/parser.c
index bd65d70..4e10aa7 100644
--- a/parser.c
+++ b/parser.c
@@ -58,13 +58,16 @@
     return(ctxt->name##Nr++);						\
 }									\
 type name##Pop(xmlParserCtxtPtr ctxt) {					\
+    type ret;								\
     if (ctxt->name##Nr <= 0) return(0);					\
     ctxt->name##Nr--;							\
     if (ctxt->name##Nr > 0)						\
 	ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1];		\
     else								\
         ctxt->name = NULL;						\
-    return(ctxt->name);							\
+    ret = ctxt->name##Tab[ctxt->name##Nr];				\
+    ctxt->name##Tab[ctxt->name##Nr] = 0;				\
+    return(ret);							\
 }									\
 
 PUSH_AND_POP(xmlParserInputPtr, input)
@@ -148,6 +151,23 @@
 }
 
 /**
+ * xmlFreeInputStream:
+ * @input:  an xmlParserInputPtr
+ *
+ * Free up an input stream.
+ */
+void
+xmlFreeInputStream(xmlParserInputPtr input) {
+    if (input == NULL) return;
+
+    if (input->filename != NULL) return;
+    if ((input->free != NULL) && (input->base != NULL))
+        input->free((char *) input->base);
+    memset(input, -1, sizeof(xmlParserInput));
+    free(input);
+}
+
+/**
  * xmlNewEntityInputStream:
  * @ctxt:  an XML parser context
  * @entity:  an Entity pointer
@@ -182,6 +202,7 @@
     input->cur = entity->content;
     input->line = 1;
     input->col = 1;
+    input->free = NULL;
     return(input);
 }
 
@@ -214,6 +235,7 @@
     input->cur = string;
     input->line = 1;
     input->col = 1;
+    input->free = NULL;
     return(input);
 }
 
@@ -4397,6 +4419,43 @@
 }
 
 /**
+ * xmlCreateFileParserCtxt :
+ * @cur:  a pointer to an array of CHAR
+ *
+ * Create a parser context for an XML in-memory document.
+ *
+ * Returns the new parser context or NULL
+ */
+xmlParserCtxtPtr
+xmlCreateDocParserCtxt(CHAR *cur) {
+    xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
+
+    ctxt = (xmlParserCtxtPtr) malloc(sizeof(xmlParserCtxt));
+    if (ctxt == NULL) {
+        perror("malloc");
+	return(NULL);
+    }
+    xmlInitParserCtxt(ctxt);
+    input = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
+    if (input == NULL) {
+        perror("malloc");
+	free(ctxt);
+	return(NULL);
+    }
+
+    input->filename = NULL;
+    input->line = 1;
+    input->col = 1;
+    input->base = cur;
+    input->cur = cur;
+    input->free = NULL;
+
+    inputPush(ctxt, input);
+    return(ctxt);
+}
+
+/**
  * xmlSAXParseDoc :
  * @sax:  the SAX handler block
  * @cur:  a pointer to an array of CHAR
@@ -4414,32 +4473,13 @@
 xmlSAXParseDoc(xmlSAXHandlerPtr sax, CHAR *cur, int recovery) {
     xmlDocPtr ret;
     xmlParserCtxtPtr ctxt;
-    xmlParserInputPtr input;
 
     if (cur == NULL) return(NULL);
 
-    ctxt = (xmlParserCtxtPtr) malloc(sizeof(xmlParserCtxt));
-    if (ctxt == NULL) {
-        perror("malloc");
-	return(NULL);
-    }
-    xmlInitParserCtxt(ctxt);
+
+    ctxt = xmlCreateDocParserCtxt(cur);
+    if (ctxt == NULL) return(NULL);
     if (sax != NULL) ctxt->sax = sax;
-    input = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
-    if (input == NULL) {
-        perror("malloc");
-	free(ctxt);
-	return(NULL);
-    }
-
-    input->filename = NULL;
-    input->line = 1;
-    input->col = 1;
-    input->base = cur;
-    input->cur = cur;
-
-    inputPush(ctxt, input);
-
 
     xmlParseDocument(ctxt);
     if ((ctxt->wellFormed) || recovery) ret = ctxt->doc;
@@ -4448,12 +4488,7 @@
        xmlFreeDoc(ctxt->doc);
        ctxt->doc = NULL;
     }
-    free(ctxt->nodeTab);
-    free(ctxt->inputTab);
-    if (input->filename != NULL)
-	free((char *)input->filename);
-    free(input);
-    free(ctxt);
+    xmlFreeParserCtxt(ctxt);
     
     return(ret);
 }
@@ -4488,23 +4523,19 @@
 }
 
 /**
- * xmlSAXParseFile :
- * @sax:  the SAX handler block
+ * xmlCreateFileParserCtxt :
  * @filename:  the filename
- * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
- *             documents
  *
- * 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.
- * If sax is NULL, fallback to the default DOM tree building routines.
+ * 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 resulting document tree
+ * Returns the new parser context or NULL
  */
-
-xmlDocPtr xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
-                          int recovery) {
-    xmlDocPtr ret;
+xmlParserCtxtPtr
+xmlCreateFileParserCtxt(const char *filename)
+{
+    xmlParserCtxtPtr ctxt;
 #ifdef HAVE_ZLIB_H
     gzFile input;
 #else
@@ -4514,7 +4545,6 @@
     int len;
     struct stat buf;
     char *buffer;
-    xmlParserCtxtPtr ctxt;
     xmlParserInputPtr inputStream;
 
     res = stat(filename, &buf);
@@ -4583,7 +4613,6 @@
 	return(NULL);
     }
     xmlInitParserCtxt(ctxt);
-    if (sax != NULL) ctxt->sax = sax;
     inputStream = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
     if (inputStream == NULL) {
         perror("malloc");
@@ -4600,8 +4629,35 @@
      */
     inputStream->base = buffer;
     inputStream->cur = buffer;
+    inputStream->free = (xmlParserInputDeallocate) free;
 
     inputPush(ctxt, inputStream);
+    return(ctxt);
+}
+
+/**
+ * xmlSAXParseFile :
+ * @sax:  the SAX handler block
+ * @filename:  the filename
+ * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
+ *             documents
+ *
+ * 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.
+ * If sax is NULL, fallback to the default DOM tree building routines.
+ *
+ * Returns the resulting document tree
+ */
+
+xmlDocPtr xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
+                          int recovery) {
+    xmlDocPtr ret;
+    xmlParserCtxtPtr ctxt;
+
+    ctxt = xmlCreateFileParserCtxt(filename);
+    if (ctxt == NULL) return(NULL);
+    if (sax != NULL) ctxt->sax = sax;
 
     xmlParseDocument(ctxt);
 
@@ -4611,13 +4667,7 @@
        xmlFreeDoc(ctxt->doc);
        ctxt->doc = NULL;
     }
-    free(buffer);
-    free(ctxt->nodeTab);
-    free(ctxt->inputTab);
-    if (inputStream->filename != NULL)
-	free((char *)inputStream->filename);
-    free(inputStream);
-    free(ctxt);
+    xmlFreeParserCtxt(ctxt);
     
     return(ret);
 }
@@ -4652,25 +4702,16 @@
 }
 
 /**
- * xmlSAXParseMemory :
- * @sax:  the SAX handler block
+ * xmlCreateMemoryParserCtxt :
  * @buffer:  an pointer to a char array
  * @size:  the siwe of the array
- * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
- *             documents
  *
- * 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.
- * 
- * TODO : plug some encoding conversion routines here. !!!
+ * Create a parser context for an XML in-memory document.
  *
- * Returns the resulting document tree
+ * Returns the new parser context or NULL
  */
-xmlDocPtr
-xmlSAXParseMemory(xmlSAXHandlerPtr sax, char *buffer, int size,
-                            int recovery) {
-    xmlDocPtr ret;
+xmlParserCtxtPtr
+xmlCreateMemoryParserCtxt(char *buffer, int size) {
     xmlParserCtxtPtr ctxt;
     xmlParserInputPtr input;
 
@@ -4682,7 +4723,6 @@
 	return(NULL);
     }
     xmlInitParserCtxt(ctxt);
-    if (sax != NULL) ctxt->sax = sax;
     input = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
     if (input == NULL) {
         perror("malloc");
@@ -4701,8 +4741,36 @@
      */
     input->base = buffer;
     input->cur = buffer;
+    input->free = NULL;
 
     inputPush(ctxt, input);
+    return(ctxt);
+}
+
+/**
+ * xmlSAXParseMemory :
+ * @sax:  the SAX handler block
+ * @buffer:  an pointer to a char array
+ * @size:  the siwe of the array
+ * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
+ *             documents
+ *
+ * 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.
+ * 
+ * TODO : plug some encoding conversion routines here. !!!
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlSAXParseMemory(xmlSAXHandlerPtr sax, char *buffer, int size, int recovery) {
+    xmlDocPtr ret;
+    xmlParserCtxtPtr ctxt;
+
+    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
+    if (ctxt == NULL) return(NULL);
+    if (sax != NULL) ctxt->sax = sax;
 
     xmlParseDocument(ctxt);
 
@@ -4712,12 +4780,7 @@
        xmlFreeDoc(ctxt->doc);
        ctxt->doc = NULL;
     }
-    free(ctxt->nodeTab);
-    free(ctxt->inputTab);
-    if (input->filename != NULL)
-	free((char *)input->filename);
-    free(input);
-    free(ctxt);
+    xmlFreeParserCtxt(ctxt);
     
     return(ret);
 }
@@ -4761,23 +4824,47 @@
 void
 xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
 {
-  /* Allocate the Input stack */
-  ctxt->inputTab = (xmlParserInputPtr *) malloc(5 * sizeof(xmlParserInputPtr));
-  ctxt->inputNr = 0;
-  ctxt->inputMax = 5;
-  ctxt->input = NULL;
+    /* Allocate the Input stack */
+    ctxt->inputTab = (xmlParserInputPtr *) malloc(5 * sizeof(xmlParserInputPtr));
+    ctxt->inputNr = 0;
+    ctxt->inputMax = 5;
+    ctxt->input = NULL;
 
-  /* Allocate the Node stack */
-  ctxt->nodeTab = (xmlNodePtr *) malloc(10 * sizeof(xmlNodePtr));
-  ctxt->nodeNr = 0;
-  ctxt->nodeMax = 10;
-  ctxt->node = NULL;
+    /* Allocate the Node stack */
+    ctxt->nodeTab = (xmlNodePtr *) malloc(10 * sizeof(xmlNodePtr));
+    ctxt->nodeNr = 0;
+    ctxt->nodeMax = 10;
+    ctxt->node = NULL;
 
-  ctxt->sax = &xmlDefaultSAXHandler;
-  ctxt->doc = NULL;
-  ctxt->wellFormed = 1;
-  ctxt->record_info = 0;
-  xmlInitNodeInfoSeq(&ctxt->node_seq);
+    ctxt->sax = &xmlDefaultSAXHandler;
+    ctxt->doc = NULL;
+    ctxt->wellFormed = 1;
+    ctxt->record_info = 0;
+    xmlInitNodeInfoSeq(&ctxt->node_seq);
+}
+
+/**
+ * xmlFreeParserCtxt:
+ * @ctxt:  an XML parser context
+ *
+ * Free all the memory used by a parser context. However the parsed
+ * document in ctxt->doc is not freed.
+ */
+
+void
+xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
+{
+    xmlParserInputPtr input;
+
+    if (ctxt == NULL) return;
+
+    while ((input = inputPop(ctxt)) != NULL) {
+        xmlFreeInputStream(input);
+    }
+
+    if (ctxt->nodeTab != NULL) free(ctxt->nodeTab);
+    if (ctxt->inputTab != NULL) free(ctxt->inputTab);
+    free(ctxt);
 }
 
 /**