More work toward DTD parsing, informations on the mailing-list and Web, Daniel.
diff --git a/ChangeLog b/ChangeLog
index 0f620b1..96002ae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Sun Jan 31 22:06:48 CET 1999 Daniel Veillard <Daniel.Veillard@w3.org>
+
+	* valid.[ch], tree.c, parser.c : more work toward full parsing
+	  of XML DTDs.
+	* README: added informations about mailing-list and on-line
+	  documentation
+
 1999-01-27  Raja R Harinath  <harinath@cs.umn.edu>
 
 	* configure.in (XML_INCLUDEDIR): Use -I not -L for includes.
diff --git a/README b/README
index e69de29..39c315c 100644
--- a/README
+++ b/README
@@ -0,0 +1,14 @@
+
+                  XML parser for Gnome
+
+Documentation is available on-line at
+    http://rufus.w3.org/veillard/XML/xml.html
+
+A mailing-list has been set-up, to subscribe:
+    echo "subscribe xml" | mail majordomo@rufus.w3.org
+
+The list archive is at:
+    http://rufus.w3.org/veillard/XML/messages/
+
+
+Daniel.Veillard@w3.org
diff --git a/include/libxml/valid.h b/include/libxml/valid.h
index d6765ff..bef45dc 100644
--- a/include/libxml/valid.h
+++ b/include/libxml/valid.h
@@ -11,8 +11,25 @@
 #define __XML_VALID_H__
 #include "tree.h"
 
+/*
+ * ALl element declarations are stored in a table
+ * there is one table per DTD
+ */
+
+#define XML_MIN_ELEMENT_TABLE	32
+
+typedef struct xmlElementTable {
+    int nb_elements;		/* number of elements stored */
+    int max_elements;		/* maximum number of elements */
+    xmlElementPtr table;	/* the table of entities */
+} xmlElementTable, *xmlElementTablePtr;
+
 extern xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, char *name, int type, 
                                        xmlElementContentPtr content);
 extern xmlElementContentPtr xmlNewElementContent(CHAR *name, int type);
+extern xmlElementContentPtr xmlCopyElementContent(xmlElementContentPtr content);
 extern void xmlFreeElementContent(xmlElementContentPtr cur);
+
+extern xmlElementTablePtr xmlCopyElementTable(xmlElementTablePtr table);
+extern void xmlFreeElementTable(xmlElementTablePtr table);
 #endif /* __XML_VALID_H__ */
diff --git a/parser.c b/parser.c
index a466b8b..03cfa4e 100644
--- a/parser.c
+++ b/parser.c
@@ -2388,16 +2388,21 @@
         (NXT(6) == 'A')) {
 	SKIP(7);
 	SKIP_BLANKS;
+	if (CUR == ')') {
+	    NEXT;
+	    ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
+	    return(ret);
+	}
 	if ((CUR == '(') || (CUR == '|')) {
 	    ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
 	    if (ret == NULL) return(NULL);
-	} else {
+	} /********** else {
 	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
 		ctxt->sax->error(ctxt, 
 		    "xmlParseElementMixedContentDecl : '|' or ')' expected\n");
 	    ctxt->wellFormed = 0;
 	    return(NULL);
-	}
+	} **********/
 	while (CUR == '|') {
 	    if (elem == NULL) {
 	        ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
@@ -2422,7 +2427,7 @@
 	    }
 	    SKIP_BLANKS;
 	}
-	if (CUR == ')') {
+	if ((CUR == ')') && (NXT(1) == '*')) {
 	    if (elem != NULL)
 		cur->c2 = xmlNewElementContent(elem,
 		                               XML_ELEMENT_CONTENT_ELEMENT);
@@ -2430,7 +2435,7 @@
 	} else {
 	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
 		ctxt->sax->error(ctxt, 
-		    "xmlParseElementMixedContentDecl : '|' or ')' expected\n");
+		    "xmlParseElementMixedContentDecl : '|' or ')*' expected\n");
 	    ctxt->wellFormed = 0;
 	    xmlFreeElementContent(ret);
 	    return(NULL);
@@ -2671,6 +2676,7 @@
 	return(-1);
     }
      ****************************/
+    *result = tree;
     return(res);
 }
 
diff --git a/tree.c b/tree.c
index 4d643d8..5892a4e 100644
--- a/tree.c
+++ b/tree.c
@@ -20,6 +20,7 @@
 
 #include "tree.h"
 #include "entities.h"
+#include "valid.h"
 
 static CHAR xmlStringText[] = { 't', 'e', 'x', 't', 0 };
 int oldXMLWDcompatibility = 0;
@@ -345,7 +346,7 @@
     if (cur->SystemID != NULL) free((char *) cur->SystemID);
     if (cur->ExternalID != NULL) free((char *) cur->ExternalID);
     if (cur->elements != NULL)
-        fprintf(stderr, "xmlFreeDtd: cur->elements != NULL !!! \n");
+        xmlFreeElementTable((xmlElementTablePtr) cur->elements);
     if (cur->entities != NULL)
         xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
     memset(cur, -1, sizeof(xmlDtd));
@@ -2268,13 +2269,15 @@
 	xmlBufferWriteCHAR(cur->SystemID);
 	xmlBufferWriteChar("\"");
     }
-    if (cur->entities == NULL) {
+    if ((cur->entities == NULL) && (cur->elements == NULL)) {
 	xmlBufferWriteChar(">\n");
 	return;
     }
     xmlBufferWriteChar(" [\n");
     if (cur->entities != NULL)
 	xmlDumpEntitiesTable((xmlEntitiesTablePtr) cur->entities);
+    if (cur->elements != NULL)
+	xmlDumpElementTable((xmlElementTablePtr) cur->elements);
     xmlBufferWriteChar("]");
 
     /* TODO !!! a lot more things to dump ... */
diff --git a/valid.c b/valid.c
index 215e463..6f2f440 100644
--- a/valid.c
+++ b/valid.c
@@ -56,11 +56,28 @@
     }
     ret->type = type;
     ret->ocur = XML_ELEMENT_CONTENT_ONCE;
-    ret->name = xmlStrdup(name);
+    if (name != NULL)
+        ret->name = xmlStrdup(name);
+    else
+        ret->name = NULL;
     return(ret);
 }
 
 /**
+ * xmlCopyElementContent:
+ * @content:  An element content pointer.
+ *
+ * Build a copy of an element content description.
+ * 
+ * return values: the new xmlElementContentPtr or NULL in case of error.
+ */
+xmlElementContentPtr
+xmlCopyElementContent(xmlElementContentPtr content) {
+/* TODO !!! */
+    return(NULL);
+}
+
+/**
  * xmlNewElementContent:
  * @name:  the subelement name or NULL
  * @type:  the type of element content decl
@@ -78,6 +95,37 @@
  *								*
  ****************************************************************/
 
+/**
+ * xmlCreateElementTable:
+ *
+ * create and initialize an empty element hash table.
+ *
+ * return values: the xmlElementTablePtr just created or NULL in case of error.
+ */
+xmlElementTablePtr
+xmlCreateElementTable(void) {
+    xmlElementTablePtr ret;
+
+    ret = (xmlElementTablePtr) 
+         malloc(sizeof(xmlElementTable));
+    if (ret == NULL) {
+        fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
+	        sizeof(xmlElementTable));
+        return(NULL);
+    }
+    ret->max_elements = XML_MIN_ENTITIES_TABLE;
+    ret->nb_elements = 0;
+    ret->table = (xmlElementPtr ) 
+         malloc(ret->max_elements * sizeof(xmlElement));
+    if (ret == NULL) {
+        fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
+	        ret->max_elements * sizeof(xmlElement));
+	free(ret);
+        return(NULL);
+    }
+    return(ret);
+}
+
 
 /**
  * xmlAddElementDecl:
@@ -90,7 +138,9 @@
 xmlElementPtr
 xmlAddElementDecl(xmlDtdPtr dtd, char *name, int type, 
                   xmlElementContentPtr content) {
-    xmlElementPtr ret;
+    xmlElementPtr ret, cur;
+    xmlElementTablePtr table;
+    int i;
 
     if (dtd == NULL) {
         fprintf(stderr, "xmlAddElementDecl: dtd == NULL\n");
@@ -135,28 +185,175 @@
     }
 
     /*
+     * Create the Element table if needed.
+     */
+    table = dtd->elements;
+    if (table == NULL) 
+        table = dtd->elements = xmlCreateElementTable();
+    if (table == NULL) {
+	fprintf(stderr, "xmlAddElementDecl: Table creation failed!\n");
+        return(NULL);
+    }
+
+    /*
      * Validity Check:
      * Search the DTD for previous declarations of the ELEMENT
      */
-    /* TODO */
+    for (i = 0;i < table->nb_elements;i++) {
+        cur = &table->table[i];
+	if (!xmlStrcmp(cur->name, name)) {
+	    /*
+	     * The element is already defined in this Dtd.
+	     */
+	    fprintf(stderr,
+		    "xmlAddElementDecl: %s already defined\n", name);
+	    return(NULL);
+	}
+    }
 
     /*
-     * Create and fill the structure.
+     * Grow the table, if needed.
      */
-    ret = (xmlElementPtr) malloc(sizeof(xmlElement));
-    if (ret == NULL) {
-        fprintf(stderr, "xmlAddElementDecl: out of memory\n");
-	return(NULL);
+    if (table->nb_elements >= table->max_elements) {
+        /*
+	 * need more elements.
+	 */
+	table->max_elements *= 2;
+	table->table = (xmlElementPtr) 
+	    realloc(table->table, table->max_elements * sizeof(xmlElement));
+	if (table->table) {
+	    fprintf(stderr, "xmlAddElementDecl: out of memory\n");
+	    return(NULL);
+	}
     }
+    ret = &table->table[table->nb_elements];
+
+    /*
+     * fill the structure.
+     */
     ret->type = type;
     ret->name = xmlStrdup(name);
     ret->content = content;
-
-    /*
-     * Insert the structure in the DTD Element table
-     */
-    /* TODO */
+    table->nb_elements++;
 
     return(ret);
 }
 
+/**
+ * xmlFreeElement:
+ * @elem:  An element
+ *
+ * Deallocate the memory used by an element definition
+ */
+void
+xmlFreeElement(xmlElementPtr elem) {
+    if (elem == NULL) return;
+    xmlFreeElementContent(elem->content);
+    if (elem->name != NULL)
+	free((CHAR *) elem->name);
+    memset(elem, -1, sizeof(xmlElement));
+    free(elem);
+}
+
+/**
+ * xmlFreeElementTable:
+ * @table:  An element table
+ *
+ * Deallocate the memory used by an entities hash table.
+ */
+void
+xmlFreeElementTable(xmlElementTablePtr table) {
+    int i;
+
+    if (table == NULL) return;
+
+    for (i = 0;i < table->nb_elements;i++) {
+        xmlFreeElement(&table->table[i]);
+    }
+    free(table->table);
+    free(table);
+}
+
+/**
+ * xmlCopyElementTable:
+ * @table:  An element table
+ *
+ * Build a copy of an element table.
+ * 
+ * return values: the new xmlElementTablePtr or NULL in case of error.
+ */
+xmlElementTablePtr
+xmlCopyElementTable(xmlElementTablePtr table) {
+    xmlElementTablePtr ret;
+    xmlElementPtr cur, ent;
+    int i;
+
+    ret = (xmlElementTablePtr) malloc(sizeof(xmlElementTable));
+    if (ret == NULL) {
+        fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
+	return(NULL);
+    }
+    ret->table = (xmlElementPtr) malloc(table->max_elements *
+                                         sizeof(xmlElement));
+    if (ret->table == NULL) {
+        fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
+	free(ret);
+	return(NULL);
+    }
+    ret->max_elements = table->max_elements;
+    ret->nb_elements = table->nb_elements;
+    for (i = 0;i < ret->nb_elements;i++) {
+	cur = &ret->table[i];
+	ent = &table->table[i];
+	cur->type = ent->type;
+	if (ent->name != NULL)
+	    cur->name = xmlStrdup(ent->name);
+	else
+	    cur->name = NULL;
+	cur->content = xmlCopyElementContent(ent->content);
+    }
+    return(ret);
+}
+
+/**
+ * xmlDumpElementTable:
+ * @table:  An element table
+ *
+ * This will dump the content of the element table as an XML DTD definition
+ *
+ * NOTE: TODO an extra parameter allowing a reentant implementation will
+ *       be added.
+ */
+void
+xmlDumpElementTable(xmlElementTablePtr table) {
+    int i;
+    xmlElementPtr cur;
+
+    if (table == NULL) return;
+
+    for (i = 0;i < table->nb_elements;i++) {
+        cur = &table->table[i];
+        switch (cur->type) {
+	    case XML_ELEMENT_TYPE_EMPTY:
+	        xmlBufferWriteChar("<!ELEMENT ");
+		xmlBufferWriteCHAR(cur->name);
+		xmlBufferWriteChar(" EMPTY>");
+	        break;
+	    case XML_ELEMENT_TYPE_ANY:
+	        xmlBufferWriteChar("<!ELEMENT ");
+		xmlBufferWriteCHAR(cur->name);
+		xmlBufferWriteChar(" ANY>");
+	        break;
+	    case XML_ELEMENT_TYPE_MIXED:
+		/* TODO !!! */
+	        break;
+	    case XML_ELEMENT_TYPE_ELEMENT:
+		/* TODO !!! */
+	        break;
+	    default:
+	        fprintf(stderr,
+		    "xmlDumpElementTable: internal: unknown type %d\n",
+		        cur->type);
+	}
+    }
+}
diff --git a/valid.h b/valid.h
index d6765ff..bef45dc 100644
--- a/valid.h
+++ b/valid.h
@@ -11,8 +11,25 @@
 #define __XML_VALID_H__
 #include "tree.h"
 
+/*
+ * ALl element declarations are stored in a table
+ * there is one table per DTD
+ */
+
+#define XML_MIN_ELEMENT_TABLE	32
+
+typedef struct xmlElementTable {
+    int nb_elements;		/* number of elements stored */
+    int max_elements;		/* maximum number of elements */
+    xmlElementPtr table;	/* the table of entities */
+} xmlElementTable, *xmlElementTablePtr;
+
 extern xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, char *name, int type, 
                                        xmlElementContentPtr content);
 extern xmlElementContentPtr xmlNewElementContent(CHAR *name, int type);
+extern xmlElementContentPtr xmlCopyElementContent(xmlElementContentPtr content);
 extern void xmlFreeElementContent(xmlElementContentPtr cur);
+
+extern xmlElementTablePtr xmlCopyElementTable(xmlElementTablePtr table);
+extern void xmlFreeElementTable(xmlElementTablePtr table);
 #endif /* __XML_VALID_H__ */