More validity stuff (ID) and corrct version of equal and compare for XPath, Daniel
diff --git a/valid.c b/valid.c
index b23824f..25ad9d5 100644
--- a/valid.c
+++ b/valid.c
@@ -1306,6 +1306,200 @@
 
 /************************************************************************
  *									*
+ *				NOTATIONs				*
+ *									*
+ ************************************************************************/
+/**
+ * xmlCreateIDTable:
+ *
+ * create and initialize an empty id hash table.
+ *
+ * Returns the xmlIDTablePtr just created or NULL in case
+ *                of error.
+ */
+xmlIDTablePtr
+xmlCreateIDTable(void) {
+    xmlIDTablePtr ret;
+
+    ret = (xmlIDTablePtr) 
+         malloc(sizeof(xmlIDTable));
+    if (ret == NULL) {
+        fprintf(stderr, "xmlCreateIDTable : malloc(%ld) failed\n",
+	        (long)sizeof(xmlIDTable));
+        return(NULL);
+    }
+    ret->max_ids = XML_MIN_NOTATION_TABLE;
+    ret->nb_ids = 0;
+    ret->table = (xmlIDPtr *) 
+         malloc(ret->max_ids * sizeof(xmlIDPtr));
+    if (ret == NULL) {
+        fprintf(stderr, "xmlCreateIDTable : malloc(%ld) failed\n",
+	        ret->max_ids * (long)sizeof(xmlID));
+	free(ret);
+        return(NULL);
+    }
+    return(ret);
+}
+
+
+/**
+ * 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, othervise the new xmlIDPtr
+ */
+xmlIDPtr 
+xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const CHAR *value,
+         xmlAttrPtr attr) {
+    xmlIDPtr ret, cur;
+    xmlIDTablePtr table;
+    int i;
+
+    if (doc == NULL) {
+        fprintf(stderr, "xmlAddIDDecl: doc == NULL\n");
+	return(NULL);
+    }
+    if (value == NULL) {
+        fprintf(stderr, "xmlAddIDDecl: value == NULL\n");
+	return(NULL);
+    }
+    if (attr == NULL) {
+        fprintf(stderr, "xmlAddIDDecl: attr == NULL\n");
+	return(NULL);
+    }
+
+    /*
+     * Create the ID table if needed.
+     */
+    table = doc->ids;
+    if (table == NULL) 
+        table = doc->ids = xmlCreateIDTable();
+    if (table == NULL) {
+	fprintf(stderr, "xmlAddID: Table creation failed!\n");
+        return(NULL);
+    }
+
+    /*
+     * Validity Check:
+     * Search the DTD for previous declarations of the ATTLIST
+     */
+    for (i = 0;i < table->nb_ids;i++) {
+        cur = table->table[i];
+	if (!xmlStrcmp(cur->value, value)) {
+	    /*
+	     * The id is already defined in this Dtd.
+	     */
+	    VERROR(ctxt->userData, "ID %s already defined\n", value);
+	    return(NULL);
+	}
+    }
+
+    /*
+     * Grow the table, if needed.
+     */
+    if (table->nb_ids >= table->max_ids) {
+        /*
+	 * need more ids.
+	 */
+	table->max_ids *= 2;
+	table->table = (xmlIDPtr *) 
+	    realloc(table->table, table->max_ids *
+	            sizeof(xmlIDPtr));
+	if (table->table == NULL) {
+	    fprintf(stderr, "xmlAddID: out of memory\n");
+	    return(NULL);
+	}
+    }
+    ret = (xmlIDPtr) malloc(sizeof(xmlID));
+    if (ret == NULL) {
+	fprintf(stderr, "xmlAddID: out of memory\n");
+	return(NULL);
+    }
+    table->table[table->nb_ids] = ret;
+
+    /*
+     * fill the structure.
+     */
+    ret->value = xmlStrdup(value);
+    ret->attr = attr;
+    table->nb_ids++;
+
+    return(ret);
+}
+
+/**
+ * xmlFreeID:
+ * @not:  A id
+ *
+ * Deallocate the memory used by an id definition
+ */
+void
+xmlFreeID(xmlIDPtr id) {
+    if (id == NULL) return;
+    if (id->value != NULL)
+	free((CHAR *) id->value);
+    memset(id, -1, sizeof(xmlID));
+    free(id);
+}
+
+/**
+ * xmlFreeIDTable:
+ * @table:  An id table
+ *
+ * Deallocate the memory used by an ID hash table.
+ */
+void
+xmlFreeIDTable(xmlIDTablePtr table) {
+    int i;
+
+    if (table == NULL) return;
+
+    for (i = 0;i < table->nb_ids;i++) {
+        xmlFreeID(table->table[i]);
+    }
+    free(table->table);
+    free(table);
+}
+
+/**
+ * xmlIsID
+ * @doc:  the document
+ * @elem:  the element carrying the attribute
+ * @attr:  the attribute
+ *
+ * Determine whether an attribute is of type ID. In case we have Dtd(s)
+ * then this is simple, otherwise we use an heuristic: name ID (upper
+ * or lowercase).
+ *
+ * Returns 0 or 1 depending on the lookup result
+ */
+int
+xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
+    if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
+        if (((attr->name[0] == 'I') || (attr->name[0] == 'i')) &&
+            ((attr->name[1] == 'D') || (attr->name[1] == 'd')) &&
+	    (attr->name[2] == 0)) return(1);
+    } else {
+	xmlAttributePtr attrDecl;
+
+	attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name);
+	if ((attrDecl == NULL) && (doc->extSubset != NULL))
+	    attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name,
+	                                 attr->name);
+
+        if ((attrDecl == NULL) || (attrDecl->type == XML_ATTRIBUTE_ID))
+	    return(1);
+    }
+    return(0);
+}
+
+/************************************************************************
+ *									*
  *		Routines for validity checking				*
  *									*
  ************************************************************************/