more work on Relax-NG regenerated the docs updated and augmented the

* relaxng.c: more work on Relax-NG
* doc/*: regenerated the docs
* test/relaxng/* result/relaxng/*: updated and augmented the
  Relax-NG regression tests and results
Daniel
diff --git a/relaxng.c b/relaxng.c
index 8777037..7ca09a3 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -40,8 +40,7 @@
 #define DEBUG 1                 /* very verbose output */
 #define DEBUG_CONTENT 1
 #define DEBUG_TYPE 1
-/* #define DEBUG_CONTENT_REGEXP 1 */
-/* #define DEBUG_AUTOMATA 1 */
+#define DEBUG_VALID 1
 
 #define UNBOUNDED (1 << 30)
 #define TODO 								\
@@ -143,6 +142,7 @@
     int                flags;         /* parser flags */
     int                nbErrors;      /* number of errors at parse time */
     int                nbWarnings;    /* number of warnings at parse time */
+    const xmlChar     *define;        /* the current define scope */
 
     xmlChar	      *URL;
     xmlDocPtr          doc;
@@ -284,6 +284,24 @@
 }
 
 /**
+ * xmlRelaxNGFreeDefineHash:
+ * @defines:  a list of define structures
+ *
+ * Deallocate a RelaxNG definition in the hash table
+ */
+static void
+xmlRelaxNGFreeDefineHash(xmlRelaxNGDefinePtr defines)
+{
+    xmlRelaxNGDefinePtr next;
+
+    while (defines != NULL) {
+	next = defines->nextHash;
+	xmlRelaxNGFreeDefine(defines);
+	defines = next;
+    }
+}
+
+/**
  * xmlRelaxNGFreeGrammar:
  * @grammar:  a grammar structure
  *
@@ -301,7 +319,8 @@
 	xmlHashFree(grammar->refs, NULL);
     }
     if (grammar->defs != NULL) {
-	xmlHashFree(grammar->defs, NULL);
+	xmlHashFree(grammar->defs, (xmlHashDeallocator)
+		xmlRelaxNGFreeDefineHash);
     }
 
     xmlFree(grammar);
@@ -370,7 +389,8 @@
 	xmlFree(define->ns);
     if (define->attrs != NULL)
 	xmlRelaxNGFreeDefineList(define->attrs);
-    if (define->content != NULL)
+    if ((define->content != NULL) &&
+	(define->type != XML_RELAXNG_REF))
 	xmlRelaxNGFreeDefineList(define->content);
     xmlFree(define);
 }
@@ -681,13 +701,79 @@
 #endif
 
 /**
+ * xmlRelaxNGParseDefine:
+ * @ctxt:  a Relax-NG parser context
+ * @node:  the define node
+ *
+ * parse the content of a RelaxNG define element node.
+ *
+ * Returns the definition pointer or NULL in case of error.
+ */
+static int
+xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
+    xmlChar *name;
+    int ret = 0, tmp;
+    xmlRelaxNGDefinePtr def;
+    const xmlChar *olddefine;
+
+    name = xmlGetProp(node, BAD_CAST "name");
+    if (name == NULL) {
+	if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+			"define has no name\n");
+	ctxt->nbErrors++;
+    } else {
+	def = xmlRelaxNGNewDefine(ctxt, node);
+	if (def == NULL) {
+	    xmlFree(name);
+	    return(-1);
+	}
+	def->type = XML_RELAXNG_DEF;
+	def->name = name;
+	if (node->children == NULL) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			    "define has no children\n");
+	    ctxt->nbErrors++;
+	} else {
+	    olddefine = ctxt->define;
+	    ctxt->define = name;
+	    def->content = xmlRelaxNGParsePatterns(ctxt,
+					       node->children);
+	    ctxt->define = olddefine;
+	}
+	if (ctxt->grammar->defs == NULL)
+	    ctxt->grammar->defs = xmlHashCreate(10);
+	if (ctxt->grammar->defs == NULL) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			    "Could not create definition hash\n");
+	    ctxt->nbErrors++;
+	    ret = -1;
+	    xmlRelaxNGFreeDefine(def);
+	} else {
+	    tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def);
+	    if (tmp < 0) {
+		TODO
+		/* store and implement 4.17 on combining */
+		ctxt->nbErrors++;
+		ret = -1;
+		xmlRelaxNGFreeDefine(def);
+	    }
+	}
+    }
+    return(ret);
+}
+
+/**
  * xmlRelaxNGParsePattern:
  * @ctxt:  a Relax-NG parser context
  * @node:  the pattern node.
  *
  * parse the content of a RelaxNG pattern node.
  *
- * Returns the definition pointer or NULL in case of error.
+ * Returns the definition pointer or NULL in case of error or if no
+ *     pattern is generated.
  */
 static xmlRelaxNGDefinePtr
 xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
@@ -753,6 +839,15 @@
 		ctxt->error(ctxt->userData,
 			    "ref has no name\n");
 	    ctxt->nbErrors++;
+	} else {
+	    if ((ctxt->define != NULL) &&
+	        (xmlStrEqual(ctxt->define, def->name))) {
+		if (ctxt->error != NULL)
+		    ctxt->error(ctxt->userData,
+			"Recursive reference to %s not in an element\n",
+			        def->name);
+		ctxt->nbErrors++;
+	    }
 	}
 	if (node->children != NULL) {
 	    if (ctxt->error != NULL)
@@ -792,6 +887,9 @@
 		}
 	    }
 	}
+    } else if (IS_RELAXNG(node, "define")) {
+	xmlRelaxNGParseDefine(ctxt, node);
+	def = NULL;
     } else {
 	TODO
     }
@@ -912,6 +1010,7 @@
     xmlRelaxNGDefinePtr ret, cur, last;
     xmlNodePtr child;
     xmlChar *val;
+    const xmlChar *olddefine;
 
     ret = xmlRelaxNGNewDefine(ctxt, node);
     if (ret == NULL)
@@ -952,6 +1051,8 @@
 	ctxt->nbErrors++;
 	return(ret);
     } 
+    olddefine = ctxt->define;
+    ctxt->define = NULL;
     last = NULL;
     while (child != NULL) {
 	cur = xmlRelaxNGParsePattern(ctxt, child);
@@ -997,6 +1098,7 @@
 	}
 	child = child->next;
     }
+    ctxt->define = olddefine;
     return(ret);
 }
 
@@ -1084,9 +1186,7 @@
 xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt
                               ATTRIBUTE_UNUSED, xmlNodePtr nodes)
 {
-    int ret = 0, tmp;
-    xmlRelaxNGDefinePtr def;
-    xmlChar *name;
+    int ret = 0;
 
     if (nodes == NULL) {
 	if (ctxt->error != NULL)
@@ -1114,47 +1214,7 @@
     }
     while (nodes != NULL) {
         if (IS_RELAXNG(nodes, "define")) {
-	    name = xmlGetProp(nodes, BAD_CAST "name");
-	    if (name == NULL) {
-		if (ctxt->error != NULL)
-		    ctxt->error(ctxt->userData,
-				"define has no name\n");
-		ctxt->nbErrors++;
-	    } else {
-		def = xmlRelaxNGNewDefine(ctxt, nodes);
-		if (def == NULL)
-		    break;
-		def->type = XML_RELAXNG_DEF;
-		def->name = name;
-		if (nodes->children == NULL) {
-		    if (ctxt->error != NULL)
-			ctxt->error(ctxt->userData,
-				    "define has no children\n");
-		    ctxt->nbErrors++;
-		} else {
-		    def->content = xmlRelaxNGParsePatterns(ctxt,
-						       nodes->children);
-		}
-		if (ctxt->grammar->defs == NULL)
-		    ctxt->grammar->defs = xmlHashCreate(10);
-		if (ctxt->grammar->defs == NULL) {
-		    if (ctxt->error != NULL)
-			ctxt->error(ctxt->userData,
-				    "Could not create definition hash\n");
-		    ctxt->nbErrors++;
-		    ret = -1;
-		    xmlRelaxNGFreeDefine(def);
-		} else {
-		    tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def);
-		    if (tmp < 0) {
-			TODO
-			/* store and implement 4.17 on combining */
-			ctxt->nbErrors++;
-			ret = -1;
-			xmlRelaxNGFreeDefine(def);
-		    }
-		}
-	    }
+	    ret = xmlRelaxNGParseDefine(ctxt, nodes);
         } else {
 	    if (ctxt->error != NULL)
 		ctxt->error(ctxt->userData,
@@ -1180,7 +1240,7 @@
 xmlRelaxNGCheckReference(xmlRelaxNGDefinePtr ref,
 		xmlRelaxNGParserCtxtPtr ctxt, const xmlChar *name) {
     xmlRelaxNGGrammarPtr grammar;
-    xmlRelaxNGDefinePtr def;
+    xmlRelaxNGDefinePtr def, cur;
 
     grammar = ctxt->grammar;
     if (grammar == NULL) {
@@ -1202,7 +1262,11 @@
     if (grammar->defs != NULL) {
 	def = xmlHashLookup(grammar->defs, name);
 	if (def != NULL) {
-	    ref->content = def;
+	    cur = ref;
+	    while (cur != NULL) {
+		cur->content = def;
+		cur = cur->nextHash;
+	    }
 	} else {
 	    TODO
 	}
@@ -1439,10 +1503,6 @@
 xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes) {
     xmlRelaxNGGrammarPtr ret, tmp, old;
 
-#ifdef DEBUG
-    xmlGenericError(xmlGenericErrorContext,
-		    "xmlRelaxNGParseGrammar()\n");
-#endif
     ret = xmlRelaxNGNewGrammar(ctxt);
     if (ret == NULL)
         return(NULL);
@@ -1501,6 +1561,7 @@
 static xmlRelaxNGPtr
 xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
     xmlRelaxNGPtr schema = NULL;
+    const xmlChar *olddefine;
 
     if ((ctxt == NULL) || (node == NULL))
         return (NULL);
@@ -1509,6 +1570,8 @@
     if (schema == NULL)
 	return(NULL);
 
+    olddefine = ctxt->define;
+    ctxt->define = NULL;
     if (IS_RELAXNG(node, "grammar")) {
 	schema->topgrammar = xmlRelaxNGParseGrammar(ctxt, node->children);
     } else {
@@ -1520,6 +1583,7 @@
 	ctxt->grammar = schema->topgrammar;
 	xmlRelaxNGParseStart(ctxt, node);
     }
+    ctxt->define = olddefine;
 
 #ifdef DEBUG
     if (schema == NULL)
@@ -2346,13 +2410,13 @@
 		   ((node->type == XML_TEXT_NODE) ||
 		    (node->type == XML_CDATA_SECTION_NODE)))
 		node = node->next;
-	    ctxt->state->seq = node;
-	    if (node == NULL) {
-		return(0);
+	    if (node == ctxt->state->seq) {
+		VALID_CTXT();
+		VALID_ERROR("Expecting text content\n");
+		ret = -1;
 	    }
-	    VALID_CTXT();
-	    VALID_ERROR("Expecting text content\n");
-	    return(-1);
+	    ctxt->state->seq = node;
+	    break;
         case XML_RELAXNG_ELEMENT:
 	    node = xmlRelaxNGSkipIgnored(ctxt, node);
 	    if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
@@ -2460,10 +2524,15 @@
 		break;
 	    }
 	    /* no break on purpose */
-        case XML_RELAXNG_ZEROORMORE:
+        case XML_RELAXNG_ZEROORMORE: {
+            xmlNodePtr cur, temp;
+
 	    oldflags = ctxt->flags;
 	    ctxt->flags |= FLAGS_IGNORABLE;
-	    while (node != NULL) {
+	    cur = ctxt->state->seq;
+	    temp = NULL;
+	    while ((cur != NULL) && (temp != cur)) {
+		temp = cur;
 		oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
 		ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
 		if (ret != 0) {
@@ -2473,10 +2542,11 @@
 		    break;
 		}
 		xmlRelaxNGFreeValidState(oldstate);
-		node = ctxt->state->node;
+		cur = ctxt->state->seq;
 	    }
 	    ctxt->flags = oldflags;
 	    break;
+	}
         case XML_RELAXNG_CHOICE: {
 	    xmlRelaxNGDefinePtr list = define->content;