added io1.c an example ox xmlIO usage and io1.res test result, fixed a

* doc/examples/*: added io1.c an example ox xmlIO usage and io1.res
  test result, fixed a awful lot of memory leaks showing up in
  testWriter.c, changed the examples and the Makefiles to test
  memory leaks.
* xmlwriter.c: fixed a memory leak
* Makefile.am: run the doc/examples regression tests as part of
  make tests
* xpath.c include/libxml/xpath.h: added xmlXPathCtxtCompile() to
  compile an XPath expression within a context, currently the goal
  is to be able to reuse the XSLT stylesheet dictionnary, but this
  opens the door to others possible optimizations.
* dict.c include/libxml/dict.h: added xmlDictCreateSub() which allows
  to build a new dictionnary based on another read-only dictionnary.
  This is needed for XSLT to keep the stylesheet dictionnary read-only
  while being able to reuse the strings for the transformation
  dictionnary.
* xinclude.c: fixed a dictionnar reference counting problem occuring
  when document parsing failed.
* testSAX.c: adding option --repeat for timing 100times the parsing
* doc/* : rebuilt all the docs
Daniel
diff --git a/dict.c b/dict.c
index 0a9aebe..2ffd6a5 100644
--- a/dict.c
+++ b/dict.c
@@ -65,6 +65,8 @@
     int size;
     int nbElems;
     xmlDictStringsPtr strings;
+
+    struct _xmlDict *subdict;
 };
 
 /*
@@ -181,11 +183,12 @@
  * Calculate the hash key
  */
 static unsigned long
-xmlDictComputeKey(xmlDictPtr dict, const xmlChar *name, int namelen) {
+xmlDictComputeKey(const xmlChar *name, int namelen) {
     unsigned long value = 0L;
     
     if (name == NULL) return(0);
-    value += 30 * (*name);
+    value = *name;
+    value <<= 5;
     if (namelen > 10) {
         value += name[namelen - 1];
         namelen = 10;
@@ -200,10 +203,9 @@
         case 4: value += name[3];
         case 3: value += name[2];
         case 2: value += name[1];
-        case 1: value += name[0];
         default: break;
     }
-    return (value % dict->size);
+    return(value);
 }
 
 /*
@@ -211,14 +213,13 @@
  * Calculate the hash key
  */
 static unsigned long
-xmlDictComputeQKey(xmlDictPtr dict, const xmlChar *prefix,
-                   const xmlChar *name, int len)
+xmlDictComputeQKey(const xmlChar *prefix, const xmlChar *name, int len)
 {
     unsigned long value = 0L;
     int plen;
     
     if (prefix == NULL)
-        return(xmlDictComputeKey(dict, name, len));
+        return(xmlDictComputeKey(name, len));
 
     plen = xmlStrlen(prefix);
     if (plen == 0)
@@ -263,7 +264,7 @@
         case 1: value += name[0];
         default: break;
     }
-    return (value % dict->size);
+    return(value);
 }
 
 /**
@@ -271,7 +272,7 @@
  *
  * Create a new dictionary
  *
- * Returns the newly created object, or NULL if an error occured.
+ * Returns the newly created dictionnary, or NULL if an error occured.
  */
 xmlDictPtr
 xmlDictCreate(void) {
@@ -285,6 +286,7 @@
 	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));
   	    return(dict);
@@ -295,6 +297,28 @@
 }
 
 /**
+ * xmlDictCreateSub:
+ * @sub: an existing dictionnary
+ *
+ * Create a new dictionary, inheriting strings from the read-only
+ * dictionnary @sub. On lookup, strings are first searched in the
+ * new dictionnary, then in @sub, and if not found are created in the
+ * new dictionnary.
+ *
+ * Returns the newly created dictionnary, or NULL if an error occured.
+ */
+xmlDictPtr
+xmlDictCreateSub(xmlDictPtr sub) {
+    xmlDictPtr dict = xmlDictCreate();
+  
+    if ((dict != NULL) && (sub != NULL)) {
+        dict->subdict = sub;
+	xmlDictReference(dict->subdict);
+    }
+    return(dict);
+}
+
+/**
  * xmlDictReference:
  * @dict: the dictionnary
  *
@@ -357,7 +381,7 @@
     for (i = 0; i < oldsize; i++) {
 	if (olddict[i].valid == 0) 
 	    continue;
-	key = xmlDictComputeKey(dict, olddict[i].name, olddict[i].len);
+	key = xmlDictComputeKey(olddict[i].name, olddict[i].len) % dict->size;
 	memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry));
 	dict->dict[key].next = NULL;
 #ifdef DEBUG_GROW
@@ -374,7 +398,7 @@
 	     * put back the entry in the new dict
 	     */
 
-	    key = xmlDictComputeKey(dict, iter->name, iter->len);
+	    key = xmlDictComputeKey(iter->name, iter->len) % dict->size;
 	    if (dict->dict[key].valid == 0) {
 		memcpy(&(dict->dict[key]), iter, sizeof(xmlDictEntry));
 		dict->dict[key].next = NULL;
@@ -425,6 +449,10 @@
     dict->ref_counter--;
     if (dict->ref_counter > 0) return;
 
+    if (dict->subdict != NULL) {
+        xmlDictFree(dict->subdict);
+    }
+
     if (dict->dict) {
 	for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) {
 	    iter = &(dict->dict[i]);
@@ -464,7 +492,7 @@
  */
 const xmlChar *
 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
-    unsigned long key, nbi = 0;
+    unsigned long key, okey, nbi = 0;
     xmlDictEntryPtr entry;
     xmlDictEntryPtr insert;
     const xmlChar *ret;
@@ -478,7 +506,8 @@
     /*
      * Check for duplicate and insertion location.
      */
-    key = xmlDictComputeKey(dict, name, len);
+    okey = xmlDictComputeKey(name, len);
+    key = okey % dict->size;
     if (dict->dict[key].valid == 0) {
 	insert = NULL;
     } else {
@@ -486,8 +515,7 @@
 	     insert = insert->next) {
 #ifdef __GNUC__
 	    if (insert->len == len) {
-	        register int tmp = memcmp(insert->name, name, len);
-		if (!tmp)
+		if (!memcmp(insert->name, name, len))
 		    return(insert->name);
 	    }
 #else
@@ -499,8 +527,7 @@
 	}
 #ifdef __GNUC__
 	if (insert->len == len) {
-	    register int tmp = memcmp(insert->name, name, len);
-	    if (!tmp)
+	    if (!memcmp(insert->name, name, len))
 		return(insert->name);
 	}
 #else
@@ -510,6 +537,39 @@
 #endif
     }
 
+    if (dict->subdict) {
+	key = okey % 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->len == len) {
+		    if (!memcmp(tmp->name, name, len))
+			return(tmp->name);
+		}
+#else
+		if ((tmp->len == len) &&
+		    (!xmlStrncmp(tmp->name, name, len)))
+		    return(tmp->name);
+#endif
+		nbi++;
+	    }
+#ifdef __GNUC__
+	    if (tmp->len == len) {
+		if (!memcmp(tmp->name, name, len))
+		    return(tmp->name);
+	    }
+#else
+	    if ((tmp->len == len) &&
+		(!xmlStrncmp(tmp->name, name, len)))
+		return(tmp->name);
+#endif
+	}
+	key = okey % dict->size;
+    }
+
     ret = xmlDictAddString(dict, name, len);
     if (ret == NULL)
         return(NULL);
@@ -551,7 +611,7 @@
  */
 const xmlChar *
 xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
-    unsigned long key, nbi = 0;
+    unsigned long okey, key, nbi = 0;
     xmlDictEntryPtr entry;
     xmlDictEntryPtr insert;
     const xmlChar *ret;
@@ -567,7 +627,8 @@
     /*
      * Check for duplicate and insertion location.
      */
-    key = xmlDictComputeQKey(dict, prefix, name, len);
+    okey = xmlDictComputeQKey(prefix, name, len);
+    key = okey % dict->size;
     if (dict->dict[key].valid == 0) {
 	insert = NULL;
     } else {
@@ -583,6 +644,24 @@
 	    return(insert->name);
     }
 
+    if (dict->subdict) {
+	key = okey % 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->len == len) &&
+		    (xmlStrQEqual(prefix, name, tmp->name)))
+		    return(tmp->name);
+		nbi++;
+	    }
+	    if ((tmp->len == len) &&
+		(xmlStrQEqual(prefix, name, tmp->name)))
+		return(tmp->name);
+	}
+	key = okey % dict->size;
+    }
+
     ret = xmlDictAddQString(dict, prefix, name, len);
     if (ret == NULL)
         return(NULL);
@@ -633,6 +712,8 @@
 	    return(1);
 	pool = pool->next;
     }
+    if (dict->subdict)
+        return(xmlDictOwns(dict->subdict, str));
     return(0);
 }
 
@@ -649,6 +730,8 @@
 xmlDictSize(xmlDictPtr dict) {
     if (dict == NULL)
 	return(-1);
+    if (dict->subdict)
+        return(dict->nbElems + dict->subdict->nbElems);
     return(dict->nbElems);
 }