new dictionary module to keep a single instance of the names used by the

* dict.c include/libxml/dict.h Makefile.am include/libxml/Makefile.am:
  new dictionary module to keep a single instance of the names used
  by the parser
* DOCBparser.c HTMLparser.c parser.c parserInternals.c valid.c:
  switched all parsers to use the dictionary internally
* include/libxml/HTMLparser.h include/libxml/parser.h
  include/libxml/parserInternals.h include/libxml/valid.h:
  Some of the interfaces changed as a result to receive or return
  "const xmlChar *" instead of "xmlChar *", this is either
  insignificant from an user point of view or when the returning
  value changed, those function are really parser internal methods
  that no user code should really change
* doc/libxml2-api.xml doc/html/*: the API interface changed and
  the docs were regenerated
Daniel
diff --git a/HTMLparser.c b/HTMLparser.c
index 28617fe..bc30557 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -73,12 +73,12 @@
  * Returns 0 in case of error, the index in the stack otherwise
  */
 static int
-htmlnamePush(htmlParserCtxtPtr ctxt, xmlChar * value)
+htmlnamePush(htmlParserCtxtPtr ctxt, const xmlChar * value)
 {
     if (ctxt->nameNr >= ctxt->nameMax) {
         ctxt->nameMax *= 2;
-        ctxt->nameTab =
-            (xmlChar * *)xmlRealloc(ctxt->nameTab,
+        ctxt->nameTab = (const xmlChar * *)
+                         xmlRealloc(ctxt->nameTab,
                                     ctxt->nameMax *
                                     sizeof(ctxt->nameTab[0]));
         if (ctxt->nameTab == NULL) {
@@ -98,10 +98,10 @@
  *
  * Returns the name just removed
  */
-static xmlChar *
+static const xmlChar *
 htmlnamePop(htmlParserCtxtPtr ctxt)
 {
-    xmlChar *ret;
+    const xmlChar *ret;
 
     if (ctxt->nameNr <= 0)
         return (0);
@@ -975,15 +975,16 @@
  **/
 static int
 htmlGetEndPriority (const xmlChar *name) {
-	int i = 0;
+    int i = 0;
 
-	while ((htmlEndPriority[i].name != NULL) &&
-	       (!xmlStrEqual((const xmlChar *)htmlEndPriority[i].name, name)))
-	    i++;
+    while ((htmlEndPriority[i].name != NULL) &&
+	   (!xmlStrEqual((const xmlChar *)htmlEndPriority[i].name, name)))
+	i++;
 
-	return(htmlEndPriority[i].priority);
+    return(htmlEndPriority[i].priority);
 }
 
+
 /**
  * htmlCheckAutoClose:
  * @newtag:  The new tag name
@@ -996,28 +997,32 @@
  * Returns 0 if no, 1 if yes.
  */
 static int
-htmlCheckAutoClose(const xmlChar *newtag, const xmlChar *oldtag) {
+htmlCheckAutoClose(const xmlChar * newtag, const xmlChar * oldtag)
+{
     int i, indx;
     const char **closed = NULL;
 
-    if (htmlStartCloseIndexinitialized == 0) htmlInitAutoClose();
+    if (htmlStartCloseIndexinitialized == 0)
+        htmlInitAutoClose();
 
     /* inefficient, but not a big deal */
-    for (indx = 0; indx < 100;indx++) {
+    for (indx = 0; indx < 100; indx++) {
         closed = htmlStartCloseIndex[indx];
-	if (closed == NULL) return(0);
-	if (xmlStrEqual(BAD_CAST *closed, newtag)) break;
+        if (closed == NULL)
+            return (0);
+        if (xmlStrEqual(BAD_CAST * closed, newtag))
+            break;
     }
 
     i = closed - htmlStartClose;
     i++;
     while (htmlStartClose[i] != NULL) {
         if (xmlStrEqual(BAD_CAST htmlStartClose[i], oldtag)) {
-	    return(1);
-	}
-	i++;
+            return (1);
+        }
+        i++;
     }
-    return(0);
+    return (0);
 }
 
 /**
@@ -1029,58 +1034,69 @@
  * The HTML DTD allows an ending tag to implicitly close other tags.
  */
 static void
-htmlAutoCloseOnClose(htmlParserCtxtPtr ctxt, const xmlChar *newtag) {
-    const htmlElemDesc * info;
-    xmlChar *oldname;
+htmlAutoCloseOnClose(htmlParserCtxtPtr ctxt, const xmlChar * newtag)
+{
+    const htmlElemDesc *info;
+    const xmlChar *oldname;
     int i, priority;
 
 #ifdef DEBUG
-    xmlGenericError(xmlGenericErrorContext,"Close of %s stack: %d elements\n", newtag, ctxt->nameNr);
-    for (i = 0;i < ctxt->nameNr;i++) 
-        xmlGenericError(xmlGenericErrorContext,"%d : %s\n", i, ctxt->nameTab[i]);
+    xmlGenericError(xmlGenericErrorContext,
+                    "Close of %s stack: %d elements\n", newtag,
+                    ctxt->nameNr);
+    for (i = 0; i < ctxt->nameNr; i++)
+        xmlGenericError(xmlGenericErrorContext, "%d : %s\n", i,
+                        ctxt->nameTab[i]);
 #endif
 
-    priority = htmlGetEndPriority (newtag);
+    priority = htmlGetEndPriority(newtag);
 
-    for (i = (ctxt->nameNr - 1);i >= 0;i--) {
+    for (i = (ctxt->nameNr - 1); i >= 0; i--) {
 
-        if (xmlStrEqual(newtag, ctxt->nameTab[i])) break;
-	/*
-	 * A missplaced endtag can only close elements with lower
-	 * or equal priority, so if we find an element with higher
-	 * priority before we find an element with
-	 * matching name, we just ignore this endtag 
-	 */
-	if (htmlGetEndPriority (ctxt->nameTab[i]) > priority) return;
+        if (xmlStrEqual(newtag, ctxt->nameTab[i]))
+            break;
+        /*
+         * A missplaced endtag can only close elements with lower
+         * or equal priority, so if we find an element with higher
+         * priority before we find an element with
+         * matching name, we just ignore this endtag 
+         */
+        if (htmlGetEndPriority(ctxt->nameTab[i]) > priority)
+            return;
     }
-    if (i < 0) return;
+    if (i < 0)
+        return;
 
     while (!xmlStrEqual(newtag, ctxt->name)) {
-	info = htmlTagLookup(ctxt->name);
-	if ((info == NULL) || (info->endTag == 1)) {
+        info = htmlTagLookup(ctxt->name);
+        if ((info == NULL) || (info->endTag == 1)) {
 #ifdef DEBUG
-	    xmlGenericError(xmlGenericErrorContext,"htmlAutoCloseOnClose: %s closes %s\n", newtag, ctxt->name);
+            xmlGenericError(xmlGenericErrorContext,
+                            "htmlAutoCloseOnClose: %s closes %s\n", newtag,
+                            ctxt->name);
 #endif
         } else if (info->endTag == 3) {
 #ifdef DEBUG
-	    xmlGenericError(xmlGenericErrorContext,"End of tag %s: expecting %s\n", newtag, ctxt->name);
+            xmlGenericError(xmlGenericErrorContext,
+                            "End of tag %s: expecting %s\n", newtag,
+                            ctxt->name);
 
 #endif
-	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		ctxt->sax->error(ctxt->userData,
-		 "Opening and ending tag mismatch: %s and %s\n",
-				 newtag, ctxt->name);
-	    ctxt->wellFormed = 0;
-	}
-	if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
-	    ctxt->sax->endElement(ctxt->userData, ctxt->name);
-	oldname = htmlnamePop(ctxt);
-	if (oldname != NULL) {
+            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+                ctxt->sax->error(ctxt->userData,
+                                 "Opening and ending tag mismatch: %s and %s\n",
+                                 newtag, ctxt->name);
+            ctxt->wellFormed = 0;
+        }
+        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
+            ctxt->sax->endElement(ctxt->userData, ctxt->name);
+        oldname = htmlnamePop(ctxt);
 #ifdef DEBUG
-	    xmlGenericError(xmlGenericErrorContext,"htmlAutoCloseOnClose: popped %s\n", oldname);
+        if (oldname != NULL) {
+            xmlGenericError(xmlGenericErrorContext,
+                            "htmlAutoCloseOnClose: popped %s\n", oldname);
+        }
 #endif
-	    xmlFree(oldname);
-	}	
     }
 }
 
@@ -1091,29 +1107,32 @@
  * Close all remaining tags at the end of the stream
  */
 static void
-htmlAutoCloseOnEnd(htmlParserCtxtPtr ctxt) {
-    xmlChar *oldname;
+htmlAutoCloseOnEnd(htmlParserCtxtPtr ctxt)
+{
+    const xmlChar *oldname;
     int i;
 
     if (ctxt->nameNr == 0)
-	return;
+        return;
 #ifdef DEBUG
-    xmlGenericError(xmlGenericErrorContext,"Close of stack: %d elements\n", ctxt->nameNr);
+    xmlGenericError(xmlGenericErrorContext,
+                    "Close of stack: %d elements\n", ctxt->nameNr);
 #endif
 
-    for (i = (ctxt->nameNr - 1);i >= 0;i--) {
+    for (i = (ctxt->nameNr - 1); i >= 0; i--) {
 #ifdef DEBUG
-        xmlGenericError(xmlGenericErrorContext,"%d : %s\n", i, ctxt->nameTab[i]);
+        xmlGenericError(xmlGenericErrorContext, "%d : %s\n", i,
+                        ctxt->nameTab[i]);
 #endif
-	if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
-	    ctxt->sax->endElement(ctxt->userData, ctxt->name);
-	oldname = htmlnamePop(ctxt);
-	if (oldname != NULL) {
+        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
+            ctxt->sax->endElement(ctxt->userData, ctxt->name);
+        oldname = htmlnamePop(ctxt);
 #ifdef DEBUG
-	    xmlGenericError(xmlGenericErrorContext,"htmlAutoCloseOnEnd: popped %s\n", oldname);
+        if (oldname != NULL) {
+            xmlGenericError(xmlGenericErrorContext,
+                            "htmlAutoCloseOnEnd: popped %s\n", oldname);
+        }
 #endif
-	    xmlFree(oldname);
-	}	
     }
 }
 
@@ -1130,44 +1149,49 @@
  * and we should check 
  */
 static void
-htmlAutoClose(htmlParserCtxtPtr ctxt, const xmlChar *newtag) {
-    xmlChar *oldname;
-    while ((newtag != NULL) && (ctxt->name != NULL) && 
+htmlAutoClose(htmlParserCtxtPtr ctxt, const xmlChar * newtag)
+{
+    const xmlChar *oldname;
+
+    while ((newtag != NULL) && (ctxt->name != NULL) &&
            (htmlCheckAutoClose(newtag, ctxt->name))) {
 #ifdef DEBUG
-	xmlGenericError(xmlGenericErrorContext,"htmlAutoClose: %s closes %s\n", newtag, ctxt->name);
+        xmlGenericError(xmlGenericErrorContext,
+                        "htmlAutoClose: %s closes %s\n", newtag,
+                        ctxt->name);
 #endif
-	if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
-	    ctxt->sax->endElement(ctxt->userData, ctxt->name);
-	oldname = htmlnamePop(ctxt);
-	if (oldname != NULL) {
+        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
+            ctxt->sax->endElement(ctxt->userData, ctxt->name);
+        oldname = htmlnamePop(ctxt);
 #ifdef DEBUG
-	    xmlGenericError(xmlGenericErrorContext,"htmlAutoClose: popped %s\n", oldname);
-#endif
-	    xmlFree(oldname);
+        if (oldname != NULL) {
+            xmlGenericError(xmlGenericErrorContext,
+                            "htmlAutoClose: popped %s\n", oldname);
         }
+#endif
     }
     if (newtag == NULL) {
-	htmlAutoCloseOnEnd(ctxt);
-	return;
+        htmlAutoCloseOnEnd(ctxt);
+        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")))) {
+           ((xmlStrEqual(ctxt->name, BAD_CAST "head")) ||
+            (xmlStrEqual(ctxt->name, BAD_CAST "body")) ||
+            (xmlStrEqual(ctxt->name, BAD_CAST "html")))) {
 #ifdef DEBUG
-	xmlGenericError(xmlGenericErrorContext,"htmlAutoClose: EOF closes %s\n", ctxt->name);
+        xmlGenericError(xmlGenericErrorContext,
+                        "htmlAutoClose: EOF closes %s\n", ctxt->name);
 #endif
-	if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
-	    ctxt->sax->endElement(ctxt->userData, ctxt->name);
-	oldname = htmlnamePop(ctxt);
-	if (oldname != NULL) {
+        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
+            ctxt->sax->endElement(ctxt->userData, ctxt->name);
+        oldname = htmlnamePop(ctxt);
 #ifdef DEBUG
-	    xmlGenericError(xmlGenericErrorContext,"htmlAutoClose: popped %s\n", oldname);
-#endif
-	    xmlFree(oldname);
+        if (oldname != NULL) {
+            xmlGenericError(xmlGenericErrorContext,
+                            "htmlAutoClose: popped %s\n", oldname);
         }
-   }
+#endif
+    }
 
 }
 
@@ -1242,7 +1266,7 @@
 #ifdef DEBUG
 	xmlGenericError(xmlGenericErrorContext,"Implied element html: pushed html\n");
 #endif    
-	htmlnamePush(ctxt, xmlStrdup(BAD_CAST"html"));
+	htmlnamePush(ctxt, BAD_CAST"html");
 	if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
 	    ctxt->sax->startElement(ctxt->userData, BAD_CAST"html", NULL);
     }
@@ -1262,7 +1286,7 @@
 #ifdef DEBUG
 	    xmlGenericError(xmlGenericErrorContext,"Implied element head: pushed head\n");
 #endif    
-	    htmlnamePush(ctxt, xmlStrdup(BAD_CAST"head"));
+	    htmlnamePush(ctxt, BAD_CAST"head");
 	    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
 		ctxt->sax->startElement(ctxt->userData, BAD_CAST"head", NULL);
     } else if ((!xmlStrEqual(newtag, BAD_CAST"noframes")) &&
@@ -1281,7 +1305,7 @@
 #ifdef DEBUG
 	xmlGenericError(xmlGenericErrorContext,"Implied element body: pushed body\n");
 #endif    
-	htmlnamePush(ctxt, xmlStrdup(BAD_CAST"body"));
+	htmlnamePush(ctxt, BAD_CAST"body");
 	if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
 	    ctxt->sax->startElement(ctxt->userData, BAD_CAST"body", NULL);
     }
@@ -1309,7 +1333,7 @@
     if (tag == NULL) {
 	htmlAutoClose(ctxt, BAD_CAST"p");
 	htmlCheckImplied(ctxt, BAD_CAST"p");
-	htmlnamePush(ctxt, xmlStrdup(BAD_CAST"p"));
+	htmlnamePush(ctxt, BAD_CAST"p");
 	if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
 	    ctxt->sax->startElement(ctxt->userData, BAD_CAST"p", NULL);
 	return(1);
@@ -1323,7 +1347,7 @@
 #endif    
 	    htmlAutoClose(ctxt, BAD_CAST"p");
 	    htmlCheckImplied(ctxt, BAD_CAST"p");
-	    htmlnamePush(ctxt, xmlStrdup(BAD_CAST"p"));
+	    htmlnamePush(ctxt, BAD_CAST"p");
 	    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
 		ctxt->sax->startElement(ctxt->userData, BAD_CAST"p", NULL);
 	    return(1);
@@ -2150,7 +2174,7 @@
  *									*
  ************************************************************************/
 
-static xmlChar * htmlParseNameComplex(xmlParserCtxtPtr ctxt);
+static const xmlChar * htmlParseNameComplex(xmlParserCtxtPtr ctxt);
 
 /**
  * htmlParseHTMLName:
@@ -2162,9 +2186,8 @@
  * Returns the Tag Name parsed or NULL
  */
 
-static xmlChar *
+static const xmlChar *
 htmlParseHTMLName(htmlParserCtxtPtr ctxt) {
-    xmlChar *ret = NULL;
     int i = 0;
     xmlChar loc[HTML_PARSER_BUFFER_SIZE];
 
@@ -2181,9 +2204,7 @@
 	NEXT;
     }
     
-    ret = xmlStrndup(loc, i);
-
-    return(ret);
+    return(xmlDictLookup(ctxt->dict, loc, i));
 }
 
 /**
@@ -2195,10 +2216,10 @@
  * Returns the Name parsed or NULL
  */
 
-static xmlChar *
+static const xmlChar *
 htmlParseName(htmlParserCtxtPtr ctxt) {
     const xmlChar *in;
-    xmlChar *ret;
+    const xmlChar *ret;
     int count = 0;
 
     GROW;
@@ -2219,7 +2240,7 @@
 	    in++;
 	if ((*in > 0) && (*in < 0x80)) {
 	    count = in - ctxt->input->cur;
-	    ret = xmlStrndup(ctxt->input->cur, count);
+	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
 	    ctxt->input->cur = in;
 	    ctxt->nbChars += count;
 	    ctxt->input->col += count;
@@ -2229,9 +2250,8 @@
     return(htmlParseNameComplex(ctxt));
 }
 
-static xmlChar *
+static const xmlChar *
 htmlParseNameComplex(xmlParserCtxtPtr ctxt) {
-    xmlChar buf[XML_MAX_NAMELEN + 5];
     int len = 0, l;
     int c;
     int count = 0;
@@ -2257,54 +2277,11 @@
 	    count = 0;
 	    GROW;
 	}
-	COPY_BUF(l,buf,len,c);
+	len += l;
 	NEXTL(l);
 	c = CUR_CHAR(l);
-	if (len >= XML_MAX_NAMELEN) {
-	    /*
-	     * Okay someone managed to make a huge name, so he's ready to pay
-	     * for the processing speed.
-	     */
-	    xmlChar *buffer;
-	    int max = len * 2;
-	    
-	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
-	    if (buffer == NULL) {
-		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		    ctxt->sax->error(ctxt->userData,
-			             "htmlParseNameComplex: out of memory\n");
-		return(NULL);
-	    }
-	    memcpy(buffer, buf, len);
-	    while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
-		   (c == '.') || (c == '-') ||
-		   (c == '_') || (c == ':') || 
-		   (IS_COMBINING(c)) ||
-		   (IS_EXTENDER(c))) {
-		if (count++ > 100) {
-		    count = 0;
-		    GROW;
-		}
-		if (len + 10 > max) {
-		    max *= 2;
-		    buffer = (xmlChar *) xmlRealloc(buffer,
-			                            max * sizeof(xmlChar));
-		    if (buffer == NULL) {
-			if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-			    ctxt->sax->error(ctxt->userData,
-				     "htmlParseNameComplex: out of memory\n");
-			return(NULL);
-		    }
-		}
-		COPY_BUF(l,buffer,len,c);
-		NEXTL(l);
-		c = CUR_CHAR(l);
-	    }
-	    buffer[len] = 0;
-	    return(buffer);
-	}
     }
-    return(xmlStrndup(buf, len));
+    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
 }
 
 
@@ -2324,9 +2301,8 @@
     xmlChar *buffer = NULL;
     int buffer_size = 0;
     xmlChar *out = NULL;
-    xmlChar *name = NULL;
-
-    xmlChar *cur = NULL;
+    const xmlChar *name = NULL;
+    const xmlChar *cur = NULL;
     const htmlEntityDesc * ent;
 
     /*
@@ -2394,7 +2370,6 @@
 			}
 			*out++ = *cur++;
 		    }
-		    xmlFree(name);
 		} else {
 		    unsigned int c;
 		    int bits;
@@ -2418,7 +2393,6 @@
 		    for ( ; bits >= 0; bits-= 6) {
 			*out++  = ((c >> bits) & 0x3F) | 0x80;
 		    }
-		    xmlFree(name);
 		}
 	    }
 	} else {
@@ -2464,8 +2438,8 @@
  *         if non-NULL *str will have to be freed by the caller.
  */
 const htmlEntityDesc *
-htmlParseEntityRef(htmlParserCtxtPtr ctxt, xmlChar **str) {
-    xmlChar *name;
+htmlParseEntityRef(htmlParserCtxtPtr ctxt, const xmlChar **str) {
+    const xmlChar *name;
     const htmlEntityDesc * ent = NULL;
     *str = NULL;
 
@@ -3047,7 +3021,7 @@
 
 static void
 htmlParseDocTypeDecl(htmlParserCtxtPtr ctxt) {
-    xmlChar *name;
+    const xmlChar *name;
     xmlChar *ExternalID = NULL;
     xmlChar *URI = NULL;
 
@@ -3102,7 +3076,6 @@
      */
     if (URI != NULL) xmlFree(URI);
     if (ExternalID != NULL) xmlFree(ExternalID);
-    if (name != NULL) xmlFree(name);
 }
 
 /**
@@ -3126,9 +3099,10 @@
  * Returns the attribute name, and the value in *value.
  */
 
-static xmlChar *
+static const xmlChar *
 htmlParseAttribute(htmlParserCtxtPtr ctxt, xmlChar **value) {
-    xmlChar *name, *val = NULL;
+    const xmlChar *name;
+    xmlChar *val = NULL;
 
     *value = NULL;
     name = htmlParseHTMLName(ctxt);
@@ -3299,8 +3273,8 @@
 
 static void
 htmlParseStartTag(htmlParserCtxtPtr ctxt) {
-    xmlChar *name;
-    xmlChar *attname;
+    const xmlChar *name;
+    const xmlChar *attname;
     xmlChar *attvalue;
     const xmlChar **atts = NULL;
     int nbatts = 0;
@@ -3345,7 +3319,6 @@
 	    ctxt->sax->error(ctxt->userData, 
 	     "htmlParseStartTag: misplaced <html> tag\n");
 	ctxt->wellFormed = 0;
-	xmlFree(name);
 	return;
     }
     if ((ctxt->nameNr != 1) && 
@@ -3354,7 +3327,6 @@
 	    ctxt->sax->error(ctxt->userData, 
 	     "htmlParseStartTag: misplaced <head> tag\n");
 	ctxt->wellFormed = 0;
-	xmlFree(name);
 	return;
     }
     if (xmlStrEqual(name, BAD_CAST"body")) {
@@ -3365,7 +3337,6 @@
 		    ctxt->sax->error(ctxt->userData, 
 		     "htmlParseStartTag: misplaced <body> tag\n");
 		ctxt->wellFormed = 0;
-		xmlFree(name);
 		return;
 	    }
 	}
@@ -3396,7 +3367,6 @@
 			                 "Attribute %s redefined\n",
 			                 attname);
 		    ctxt->wellFormed = 0;
-		    xmlFree(attname);
 		    if (attvalue != NULL)
 			xmlFree(attvalue);
 		    goto failed;
@@ -3413,7 +3383,6 @@
 		    xmlGenericError(xmlGenericErrorContext,
 			    "malloc of %ld byte failed\n",
 			    maxatts * (long)sizeof(xmlChar *));
-		    if (name != NULL) xmlFree(name);
 		    return;
 		}
 	    } else if (nbatts + 4 > maxatts) {
@@ -3424,7 +3393,6 @@
 		    xmlGenericError(xmlGenericErrorContext,
 			    "realloc of %ld byte failed\n",
 			    maxatts * (long)sizeof(xmlChar *));
-		    if (name != NULL) xmlFree(name);
 		    return;
 		}
 	    }
@@ -3462,7 +3430,7 @@
     /*
      * SAX: Start of Element !
      */
-    htmlnamePush(ctxt, xmlStrdup(name));
+    htmlnamePush(ctxt, name);
 #ifdef DEBUG
     xmlGenericError(xmlGenericErrorContext,"Start of element %s: pushed %s\n", name, ctxt->name);
 #endif    
@@ -3470,13 +3438,12 @@
         ctxt->sax->startElement(ctxt->userData, name, atts);
 
     if (atts != NULL) {
-        for (i = 0;i < nbatts;i++) {
+        for (i = 1;i < nbatts;i += 2) {
 	    if (atts[i] != NULL)
 		xmlFree((xmlChar *) atts[i]);
 	}
 	xmlFree((void *) atts);
     }
-    if (name != NULL) xmlFree(name);
 }
 
 /**
@@ -3495,47 +3462,50 @@
  */
 
 static int
-htmlParseEndTag(htmlParserCtxtPtr ctxt) {
-    xmlChar *name;
-    xmlChar *oldname;
+htmlParseEndTag(htmlParserCtxtPtr ctxt)
+{
+    const xmlChar *name;
+    const xmlChar *oldname;
     int i, ret;
 
     if ((CUR != '<') || (NXT(1) != '/')) {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt->userData, "htmlParseEndTag: '</' not found\n");
-	ctxt->wellFormed = 0;
-	return(0);
+        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+            ctxt->sax->error(ctxt->userData,
+                             "htmlParseEndTag: '</' not found\n");
+        ctxt->wellFormed = 0;
+        return (0);
     }
     SKIP(2);
 
     name = htmlParseHTMLName(ctxt);
-    if (name == NULL) return(0);
+    if (name == NULL)
+        return (0);
 
     /*
      * We should definitely be at the ending "S? '>'" part
      */
     SKIP_BLANKS;
     if ((!IS_CHAR((unsigned int) CUR)) || (CUR != '>')) {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt->userData, "End tag : expected '>'\n");
-	ctxt->wellFormed = 0;
+        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+            ctxt->sax->error(ctxt->userData, "End tag : expected '>'\n");
+        ctxt->wellFormed = 0;
     } else
-	NEXT;
+        NEXT;
 
     /*
      * If the name read is not one of the element in the parsing stack
      * then return, it's just an error.
      */
-    for (i = (ctxt->nameNr - 1);i >= 0;i--) {
-        if (xmlStrEqual(name, ctxt->nameTab[i])) break;
+    for (i = (ctxt->nameNr - 1); i >= 0; i--) {
+        if (xmlStrEqual(name, ctxt->nameTab[i]))
+            break;
     }
     if (i < 0) {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt->userData,
-	     "Unexpected end tag : %s\n", name);
-	xmlFree(name);
-	ctxt->wellFormed = 0;
-	return(0);
+        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+            ctxt->sax->error(ctxt->userData,
+                             "Unexpected end tag : %s\n", name);
+        ctxt->wellFormed = 0;
+        return (0);
     }
 
 
@@ -3552,15 +3522,15 @@
      */
     if (!xmlStrEqual(name, ctxt->name)) {
 #ifdef DEBUG
-	xmlGenericError(xmlGenericErrorContext,"End of tag %s: expecting %s\n", name, ctxt->name);
+        xmlGenericError(xmlGenericErrorContext,
+                        "End of tag %s: expecting %s\n", name, ctxt->name);
 #endif
-        if ((ctxt->name != NULL) && 
-	    (!xmlStrEqual(ctxt->name, name))) {
-	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		ctxt->sax->error(ctxt->userData,
-		 "Opening and ending tag mismatch: %s and %s\n",
-		                 name, ctxt->name);
-	    ctxt->wellFormed = 0;
+        if ((ctxt->name != NULL) && (!xmlStrEqual(ctxt->name, name))) {
+            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+                ctxt->sax->error(ctxt->userData,
+                                 "Opening and ending tag mismatch: %s and %s\n",
+                                 name, ctxt->name);
+            ctxt->wellFormed = 0;
         }
     }
 
@@ -3569,28 +3539,25 @@
      */
     oldname = ctxt->name;
     if ((oldname != NULL) && (xmlStrEqual(oldname, name))) {
-	if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
-	    ctxt->sax->endElement(ctxt->userData, name);
-	oldname = htmlnamePop(ctxt);
-	if (oldname != NULL) {
+        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
+            ctxt->sax->endElement(ctxt->userData, name);
+        oldname = htmlnamePop(ctxt);
 #ifdef DEBUG
-	    xmlGenericError(xmlGenericErrorContext,"End of tag %s: popping out %s\n", name, oldname);
+        if (oldname != NULL) {
+            xmlGenericError(xmlGenericErrorContext,
+                            "End of tag %s: popping out %s\n", name,
+                            oldname);
+        } else {
+            xmlGenericError(xmlGenericErrorContext,
+                            "End of tag %s: stack empty !!!\n", name);
+        }
 #endif
-	    xmlFree(oldname);
-#ifdef DEBUG
-	} else {
-	    xmlGenericError(xmlGenericErrorContext,"End of tag %s: stack empty !!!\n", name);
-#endif
-	}
-	ret = 1;
+        ret = 1;
     } else {
-	ret = 0;
+        ret = 0;
     }
 
-    if (name != NULL)
-	xmlFree(name);
-
-    return(ret);
+    return (ret);
 }
 
 
@@ -3606,7 +3573,7 @@
 htmlParseReference(htmlParserCtxtPtr ctxt) {
     const htmlEntityDesc * ent;
     xmlChar out[6];
-    xmlChar *name;
+    const xmlChar *name;
     if (CUR != '&') return;
 
     if (NXT(1) == '#') {
@@ -3668,7 +3635,6 @@
 	    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
 		ctxt->sax->characters(ctxt->userData, out, i);
 	}
-	xmlFree(name);
     }
 }
 
@@ -3804,11 +3770,11 @@
 
 void
 htmlParseElement(htmlParserCtxtPtr ctxt) {
-    xmlChar *name;
+    const xmlChar *name;
     xmlChar *currentNode = NULL;
     const htmlElemDesc * info;
     htmlParserNodeInfo node_info;
-    xmlChar *oldname;
+    const xmlChar *oldname;
     int depth = ctxt->nameNr;
     const xmlChar *oldptr;
 
@@ -3819,7 +3785,7 @@
 	node_info.begin_line = ctxt->input->line;
     }
 
-    oldname = xmlStrdup(ctxt->name);
+    oldname = ctxt->name;
     htmlParseStartTag(ctxt);
     name = ctxt->name;
 #ifdef DEBUG
@@ -3837,12 +3803,8 @@
         (name == NULL)) {
 	if (CUR == '>')
 	    NEXT;
-	if (oldname != NULL)
-	    xmlFree(oldname);
         return;
     }
-    if (oldname != NULL)
-	xmlFree(oldname);
 
     /*
      * Lookup the info for that element.
@@ -3853,12 +3815,6 @@
 	    ctxt->sax->error(ctxt->userData, "Tag %s invalid\n",
 			     name);
 	ctxt->wellFormed = 0;
-    } else if (info->depr) {
-/***************************
-	if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-	    ctxt->sax->warning(ctxt->userData, "Tag %s is deprecated\n",
-			       name);
- ***************************/
     }
 
     /*
@@ -3872,8 +3828,6 @@
 #ifdef DEBUG
         xmlGenericError(xmlGenericErrorContext,"End of tag the XML way: popping out %s\n", oldname);
 #endif
-	if (oldname != NULL)
-	    xmlFree(oldname);
 	return;
     }
 
@@ -3895,8 +3849,6 @@
 #ifdef DEBUG
 	    xmlGenericError(xmlGenericErrorContext,"End of start tag problem: popping out %s\n", oldname);
 #endif
-	    if (oldname != NULL)
-		xmlFree(oldname);
 	}    
 
 	/*
@@ -3922,8 +3874,6 @@
 #ifdef DEBUG
 	xmlGenericError(xmlGenericErrorContext,"End of empty tag %s : popping out %s\n", name, oldname);
 #endif
-	if (oldname != NULL)
-	    xmlFree(oldname);
 	return;
     }
 
@@ -4082,6 +4032,12 @@
     if (ctxt == NULL) return;
     memset(ctxt, 0, sizeof(htmlParserCtxt));
 
+    ctxt->dict = xmlDictCreate();
+    if (ctxt->dict == NULL) {
+        xmlGenericError(xmlGenericErrorContext,
+		"xmlInitParserCtxt: out of memory\n");
+	return;
+    }
     sax = (htmlSAXHandler *) xmlMalloc(sizeof(htmlSAXHandler));
     if (sax == NULL) {
         xmlGenericError(xmlGenericErrorContext,
@@ -4127,7 +4083,7 @@
     ctxt->node = NULL;
 
     /* Allocate the Name stack */
-    ctxt->nameTab = (xmlChar **) xmlMalloc(10 * sizeof(xmlChar *));
+    ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *));
     if (ctxt->nameTab == NULL) {
         xmlGenericError(xmlGenericErrorContext,
 		"htmlInitParserCtxt: out of memory\n");
@@ -4685,7 +4641,7 @@
 		}
 		break;
             case XML_PARSER_START_TAG: {
-	        xmlChar *name, *oldname;
+	        const xmlChar *name, *oldname;
 		int depth = ctxt->nameNr;
 		const htmlElemDesc * info;
 
@@ -4713,7 +4669,7 @@
 		    (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 		    goto done;
 
-		oldname = xmlStrdup(ctxt->name);
+		oldname = ctxt->name;
 		htmlParseStartTag(ctxt);
 		name = ctxt->name;
 #ifdef DEBUG
@@ -4734,12 +4690,8 @@
 		    (name == NULL)) {
 		    if (CUR == '>')
 			NEXT;
-		    if (oldname != NULL)
-			xmlFree(oldname);
 		    break;
 		}
-		if (oldname != NULL)
-		    xmlFree(oldname);
 
 		/*
 		 * Lookup the info for that element.
@@ -4750,13 +4702,6 @@
 			ctxt->sax->error(ctxt->userData, "Tag %s invalid\n",
 					 name);
 		    ctxt->wellFormed = 0;
-		} else if (info->depr) {
-		    /***************************
-		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-			ctxt->sax->warning(ctxt->userData,
-			                   "Tag %s is deprecated\n",
-					   name);
-		     ***************************/
 		}
 
 		/*
@@ -4771,8 +4716,6 @@
 		    xmlGenericError(xmlGenericErrorContext,"End of tag the XML way: popping out %s\n",
 		            oldname);
 #endif
-		    if (oldname != NULL)
-			xmlFree(oldname);
 		    ctxt->instate = XML_PARSER_CONTENT;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
@@ -4800,8 +4743,6 @@
 			xmlGenericError(xmlGenericErrorContext,
 			 "End of start tag problem: popping out %s\n", oldname);
 #endif
-			if (oldname != NULL)
-			    xmlFree(oldname);
 		    }    
 
 		    ctxt->instate = XML_PARSER_CONTENT;
@@ -4822,8 +4763,6 @@
 #ifdef DEBUG
 		    xmlGenericError(xmlGenericErrorContext,"End of empty tag %s : popping out %s\n", name, oldname);
 #endif
-		    if (oldname != NULL)
-			xmlFree(oldname);
 		}
 		ctxt->instate = XML_PARSER_CONTENT;
 #ifdef DEBUG_PUSH