attempt to cope with ID/IDREF(S) declared both in the DTD and in the

* valid.c xmlschemastypes.c: attempt to cope with ID/IDREF(S)
  declared both in the DTD and in the Schemas <grin/>
* relaxng.c: more debug, added a big optimization for <mixed>
* test/relaxng/testsuite.xml: augmented the testsuite
* test/relaxng/ result/relaxng: added the RelaxNG spec and a
  DocBook example to the regression tests
Daniel
diff --git a/relaxng.c b/relaxng.c
index 4077903..beb11bb 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -6,7 +6,6 @@
  * Daniel Veillard <veillard@redhat.com>
  */
 
-#define FS
 /**
  * TODO:
  * - error reporting
@@ -131,6 +130,7 @@
 #define IS_NULLABLE		1
 #define IS_NOT_NULLABLE		2
 #define IS_INDETERMINIST	4
+#define IS_MIXED		8
 
 struct _xmlRelaxNGDefine {
     xmlRelaxNGType type;	/* the type of definition */
@@ -228,6 +228,7 @@
 
 #define FLAGS_IGNORABLE		1
 #define FLAGS_NEGATIVE		2
+#define FLAGS_MIXED_CONTENT	4
 
 /**
  * xmlRelaxNGInterleaveGroup:
@@ -795,7 +796,6 @@
 {
     xmlRelaxNGStatesPtr ret;
 
-#ifdef FS
     if ((ctxt != NULL) &&
 	(ctxt->freeState != NULL) && 
 	(ctxt->freeStatesNr > 0)) {
@@ -804,7 +804,6 @@
 	ret->nbState = 0;
 	return(ret);
     }
-#endif
     if (size < 16) size = 16;
 
     ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) +
@@ -922,7 +921,6 @@
 {
     if (states == NULL)
 	return;
-#ifdef FS
     if ((ctxt != NULL) && (ctxt->freeStates == NULL)) {
 	ctxt->freeStatesMax = 40;
 	ctxt->freeStatesNr = 0;
@@ -953,10 +951,6 @@
     } else {
 	ctxt->freeStates[ctxt->freeStatesNr++] = states;
     }
-#else
-	xmlFree(states->tabState);
-	xmlFree(states);
-#endif
 }
 
 /**
@@ -1555,7 +1549,7 @@
             return (0);
         }
     }
-    if ((ctxt->err != NULL) &&
+    if ((ctxt->err != NULL) && (ctxt->state != NULL) &&
 	(ctxt->err->node == ctxt->state->node) &&
 	(ctxt->err->err == err))
 	return(ctxt->errNr);
@@ -1601,9 +1595,11 @@
         ctxt->err = NULL;
     cur = &ctxt->errTab[ctxt->errNr];
     if (cur->flags & ERROR_IS_DUP) {
-	xmlFree((xmlChar *)cur->arg1);
+	if (cur->arg1 != NULL)
+	    xmlFree((xmlChar *)cur->arg1);
 	cur->arg1 = NULL;
-	xmlFree((xmlChar *)cur->arg2);
+	if (cur->arg2 != NULL)
+	    xmlFree((xmlChar *)cur->arg2);
 	cur->arg2 = NULL;
 	cur->flags = 0;
     }
@@ -2625,10 +2621,7 @@
 	      xmlRelaxNGDefinePtr define, xmlNodePtr elem);
 
 
-#define IS_BLANK_NODE(n)						\
-    ((((n)->type == XML_TEXT_NODE) ||					\
-      ((n)->type == XML_CDATA_SECTION_NODE)) &&				\
-     (xmlRelaxNGIsBlank((n)->content)))
+#define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content))
 
 /**
  * xmlRelaxNGIsNullable:
@@ -3455,6 +3448,7 @@
     int i,j,ret;
     int nbgroups = 0;
     int nbchild = 0;
+    int is_mixed = 0;
 
     /*
      * Don't run that check in case of error. Infinite recursion
@@ -3487,6 +3481,8 @@
 	    xmlMalloc(sizeof(xmlRelaxNGInterleaveGroup));
 	if (groups[nbgroups] == NULL)
 	    goto error;
+	if (cur->type == XML_RELAXNG_TEXT)
+	    is_mixed++;
 	groups[nbgroups]->rule = cur;
 	groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 0);
 	groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1);
@@ -3534,6 +3530,8 @@
      * and save the partition list back in the def
      */
     def->data = partitions;
+    if (is_mixed != 0)
+	def->flags |= IS_MIXED;
     return;
 
 error:
@@ -6836,7 +6834,8 @@
 	    (node->type == XML_PI_NODE) ||
 	    (((node->type == XML_TEXT_NODE) || 
 	      (node->type == XML_CDATA_SECTION_NODE)) &&
-	     (IS_BLANK_NODE(node))))) {
+	     ((ctxt->flags & FLAGS_MIXED_CONTENT) ||
+	     (IS_BLANK_NODE(node)))))) {
 	node = node->next;
     }
     return(node);
@@ -7529,6 +7528,7 @@
 	                     xmlRelaxNGDefinePtr define) {
     int ret = 0, i, nbgroups, left;
     int errNr = ctxt->errNr;
+    int oldflags;
 
     xmlRelaxNGValidStatePtr oldstate;
     xmlRelaxNGPartitionPtr partitions;
@@ -7544,6 +7544,34 @@
 	VALID_ERR(XML_RELAXNG_ERR_INTERNODATA);
 	return(-1);
     }
+    /*
+     * Optimizations for MIXED
+     */
+    oldflags = ctxt->flags;
+    if (define->flags & IS_MIXED) {
+	ctxt->flags |= FLAGS_MIXED_CONTENT;
+	if (nbgroups == 2) {
+	    /*
+	     * this is a pure <mixed> case
+	     */
+	    if (ctxt->state != NULL)
+		ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
+			                                 ctxt->state->seq);
+	    if (partitions->groups[0]->rule->type == XML_RELAXNG_TEXT)
+		ret = xmlRelaxNGValidateDefinition(ctxt, 
+			           partitions->groups[1]->rule);
+	    else
+		ret = xmlRelaxNGValidateDefinition(ctxt, 
+			           partitions->groups[0]->rule);
+	    if (ret == 0) {
+		if (ctxt->state != NULL)
+		    ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
+			                                 ctxt->state->seq);
+	    }
+	    ctxt->flags = oldflags;
+	    return(ret);
+	}
+    }
 
     /*
      * Build arrays to store the first and last node of the chain
@@ -7673,6 +7701,7 @@
     }
 
 done:
+    ctxt->flags = oldflags;
     /*
      * builds the next links chain from the prev one
      */
@@ -7942,6 +7971,14 @@
 	     */
 	    if (node->_private == define) {
 		ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
+		if (ctxt->errNr != 0) {
+		    while ((ctxt->err != NULL) &&
+			   (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) &&
+			     (xmlStrEqual(ctxt->err->arg2, node->name))) ||
+			    (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) ||
+			    (ctxt->err->err == XML_RELAXNG_ERR_NOTELEM)))
+			xmlRelaxNGValidErrorPop(ctxt);
+		}
 		break;
 	    }
 
@@ -7963,6 +8000,10 @@
 	    }
 	    errNr = ctxt->errNr;
 	    
+	    oldflags = ctxt->flags;
+	    if (ctxt->flags & FLAGS_MIXED_CONTENT) {
+		ctxt->flags -= FLAGS_MIXED_CONTENT;
+	    }
 	    state = xmlRelaxNGNewValidState(ctxt, node);
 	    if (state == NULL) {
 		ret = -1;
@@ -7990,7 +8031,6 @@
 	    if (ctxt->states != NULL) {
 		tmp = -1;
 
-		oldflags = ctxt->flags;
 		ctxt->flags |= FLAGS_IGNORABLE;
 
 		for (i = 0;i < ctxt->states->nbState;i++) {
@@ -8012,6 +8052,7 @@
 		    ret = xmlRelaxNGValidateElementEnd(ctxt);
 		xmlRelaxNGFreeValidState(ctxt,state);
 	    }
+	    ctxt->flags = oldflags;
 	    ctxt->state = oldstate;
 	    if (oldstate != NULL)
 		oldstate->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
@@ -8695,14 +8736,12 @@
 	}
 	xmlRelaxNGFreeStates(NULL, ctxt->freeState);
     }
-#ifdef FS
     if (ctxt->freeStates != NULL) {
 	for (k = 0;k < ctxt->freeStatesNr;k++) {
 	    xmlRelaxNGFreeStates(NULL, ctxt->freeStates[k]);
 	}
 	xmlFree(ctxt->freeStates);
     }
-#endif
     if (ctxt->errTab != NULL)
 	xmlFree(ctxt->errTab);
     xmlFree(ctxt);