more work on grammars and refs/defs augmented/updated the regression tests

* relaxng: more work on grammars and refs/defs
* test/relaxng/* result/relaxng/*: augmented/updated the
  regression tests
Daniel
diff --git a/relaxng.c b/relaxng.c
index c6953c7..ab25bff 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -105,6 +105,7 @@
     XML_RELAXNG_DEF,		/* a definition */
     XML_RELAXNG_REF,		/* reference to a definition */
     XML_RELAXNG_EXTERNALREF,	/* reference to an external def */
+    XML_RELAXNG_PARENTREF,	/* reference to a def in the parent grammar */
     XML_RELAXNG_OPTIONAL,	/* optional patterns */
     XML_RELAXNG_ZEROORMORE,	/* zero or more non empty patterns */
     XML_RELAXNG_ONEORMORE,	/* one or more non empty patterns */
@@ -140,8 +141,10 @@
 
     xmlHashTablePtr defs;	/* define */
     xmlHashTablePtr refs;	/* references */
-    xmlHashTablePtr documents;     /* all the documents loaded */
-    xmlHashTablePtr includes;      /* all the includes loaded */
+    xmlHashTablePtr documents;  /* all the documents loaded */
+    xmlHashTablePtr includes;   /* all the includes loaded */
+    int                  defNr; /* number of defines used */
+    xmlRelaxNGDefinePtr *defTab;/* pointer to the allocated definitions */
     void *_private;	/* unused by the library for users or bindings */
 };
 
@@ -161,6 +164,7 @@
 
     xmlRelaxNGPtr      schema;        /* The schema in use */
     xmlRelaxNGGrammarPtr grammar;     /* the current grammar */
+    xmlRelaxNGGrammarPtr parentgrammar;/* the parent grammar */
     int                flags;         /* parser flags */
     int                nbErrors;      /* number of errors at parse time */
     int                nbWarnings;    /* number of warnings at parse time */
@@ -175,6 +179,10 @@
     xmlChar	      *URL;
     xmlDocPtr          document;
 
+    int                  defNr;       /* number of defines used */
+    int                  defMax;      /* number of defines aloocated */
+    xmlRelaxNGDefinePtr *defTab;      /* pointer to the allocated definitions */
+
     const char     *buffer;
     int               size;
 
@@ -337,7 +345,6 @@
  * 			Allocation functions				*
  * 									*
  ************************************************************************/
-static void xmlRelaxNGFreeDefineList(xmlRelaxNGDefinePtr defines);
 static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar);
 static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define);
 
@@ -430,6 +437,13 @@
     if (schema->includes != NULL)
 	xmlHashFree(schema->includes, (xmlHashDeallocator)
 		xmlRelaxNGFreeInclude);
+    if (schema->defTab != NULL) {
+	int i;
+
+	for (i = 0;i < schema->defNr;i++)
+	    xmlRelaxNGFreeDefine(schema->defTab[i]);
+	xmlFree(schema->defTab);
+    }
 
     xmlFree(schema);
 }
@@ -460,24 +474,6 @@
 }
 
 /**
- * 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
  *
@@ -489,14 +485,14 @@
     if (grammar == NULL)
         return;
 
-    if (grammar->start != NULL)
-	xmlRelaxNGFreeDefine(grammar->start);
+    if (grammar->next != NULL) {
+	xmlRelaxNGFreeGrammar(grammar->next);
+    }
     if (grammar->refs != NULL) {
 	xmlHashFree(grammar->refs, NULL);
     }
     if (grammar->defs != NULL) {
-	xmlHashFree(grammar->defs, (xmlHashDeallocator)
-		xmlRelaxNGFreeDefineHash);
+	xmlHashFree(grammar->defs, NULL);
     }
 
     xmlFree(grammar);
@@ -516,38 +512,44 @@
 {
     xmlRelaxNGDefinePtr ret;
 
+    if (ctxt->defMax == 0) {
+	ctxt->defMax = 16;
+	ctxt->defNr = 0;
+	ctxt->defTab = (xmlRelaxNGDefinePtr *)
+	    xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
+	if (ctxt->defTab == NULL) {
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData, "Out of memory\n");
+	    ctxt->nbErrors++;
+	    return (NULL);
+	}
+    } else if (ctxt->defMax <= ctxt->defNr) {
+	xmlRelaxNGDefinePtr *tmp;
+	ctxt->defMax *= 2;
+	tmp = (xmlRelaxNGDefinePtr *) xmlRealloc(ctxt->defTab,
+		ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
+	if (tmp == NULL) {
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData, "Out of memory\n");
+	    ctxt->nbErrors++;
+	    return (NULL);
+	}
+	ctxt->defTab = tmp;
+    }
     ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine));
     if (ret == NULL) {
-        if ((ctxt != NULL) && (ctxt->error != NULL))
-            ctxt->error(ctxt->userData, "Out of memory\n");
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData, "Out of memory\n");
 	ctxt->nbErrors++;
-        return (NULL);
+	return(NULL);
     }
     memset(ret, 0, sizeof(xmlRelaxNGDefine));
+    ctxt->defTab[ctxt->defNr++] = ret;
     ret->node = node;
-
     return (ret);
 }
 
 /**
- * xmlRelaxNGFreeDefineList:
- * @defines:  a list of define structures
- *
- * Deallocate a RelaxNG define structures.
- */
-static void
-xmlRelaxNGFreeDefineList(xmlRelaxNGDefinePtr defines)
-{
-    xmlRelaxNGDefinePtr next;
-
-    while (defines != NULL) {
-	next = defines->next;
-	xmlRelaxNGFreeDefine(defines);
-	defines = next;
-    }
-}
-
-/**
  * xmlRelaxNGFreePartition:
  * @partitions:  a partition set structure
  *
@@ -585,23 +587,15 @@
     if (define == NULL)
         return;
 
+    if ((define->data != NULL) &&
+	(define->type == XML_RELAXNG_INTERLEAVE))
+	xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);
     if (define->name != NULL)
 	xmlFree(define->name);
     if (define->ns != NULL)
 	xmlFree(define->ns);
     if (define->value != NULL)
 	xmlFree(define->value);
-    if (define->attrs != NULL)
-	xmlRelaxNGFreeDefineList(define->attrs);
-    if ((define->content != NULL) &&
-	(define->type != XML_RELAXNG_REF) &&
-	(define->type != XML_RELAXNG_EXTERNALREF))
-	xmlRelaxNGFreeDefineList(define->content);
-    if (define->nameClass != NULL)
-	xmlRelaxNGFreeDefineList(define->nameClass);
-    if ((define->data != NULL) &&
-	(define->type == XML_RELAXNG_INTERLEAVE))
-	xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);
     xmlFree(define);
 }
 
@@ -1572,6 +1566,8 @@
 static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(
 	      xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
 	      xmlRelaxNGDefinePtr def);
+static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar(
+	      xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes);
 
 
 #define IS_BLANK_NODE(n)						\
@@ -2202,7 +2198,6 @@
 			    "Could not create definition hash\n");
 	    ctxt->nbErrors++;
 	    ret = -1;
-	    xmlRelaxNGFreeDefine(def);
 	} else {
 	    tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def);
 	    if (tmp < 0) {
@@ -2216,7 +2211,6 @@
 			            name);
 		    ctxt->nbErrors++;
 		    ret = -1;
-		    xmlRelaxNGFreeDefine(def);
 		} else {
 		    while (prev->nextHash != NULL)
 			prev = prev->nextHash;
@@ -2325,7 +2319,6 @@
 		ctxt->error(ctxt->userData,
 			    "Could not create references hash\n");
 	    ctxt->nbErrors++;
-	    xmlRelaxNGFreeDefine(def);
 	    def = NULL;
 	} else {
 	    int tmp;
@@ -2342,7 +2335,6 @@
 			    "Internal error refs definitions '%s'\n",
 				    def->name);
 		    ctxt->nbErrors++;
-		    xmlRelaxNGFreeDefine(def);
 		    def = NULL;
 		} else {
 		    def->nextHash = prev->nextHash;
@@ -2410,6 +2402,81 @@
 			"xmlRelaxNGParse: notAllowed element is not empty\n");
 	    ctxt->nbErrors++;
 	}
+    } else if (IS_RELAXNG(node, "grammar")) {
+	xmlRelaxNGGrammarPtr grammar, old;
+	xmlRelaxNGGrammarPtr oldparent;
+
+	oldparent = ctxt->parentgrammar;
+	old = ctxt->grammar;
+	ctxt->parentgrammar = old;
+	grammar = xmlRelaxNGParseGrammar(ctxt, node->children);
+	if (old != NULL) {
+	    ctxt->grammar = old;
+	    ctxt->parentgrammar = oldparent;
+	    if (grammar != NULL) {
+		grammar->next = old->next;
+		old->next = grammar;
+	    }
+	}
+	if (grammar != NULL)
+	    def = grammar->start;
+	else
+	    def = NULL;
+    } else if (IS_RELAXNG(node, "parentRef")) {
+	if (ctxt->parentgrammar == NULL) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			"Use of parentRef without a parent grammar\n");
+	    ctxt->nbErrors++;
+	    return(NULL);
+	}
+	def = xmlRelaxNGNewDefine(ctxt, node);
+	if (def == NULL)
+	    return(NULL);
+	def->type = XML_RELAXNG_PARENTREF;
+	def->name = xmlGetProp(node, BAD_CAST "name");
+	if (def->name == NULL) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			    "parentRef has no name\n");
+	    ctxt->nbErrors++;
+	}
+	if (node->children != NULL) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			    "parentRef is not empty\n");
+	    ctxt->nbErrors++;
+	}
+	if (ctxt->parentgrammar->refs == NULL)
+	    ctxt->parentgrammar->refs = xmlHashCreate(10);
+	if (ctxt->parentgrammar->refs == NULL) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			    "Could not create references hash\n");
+	    ctxt->nbErrors++;
+	    def = NULL;
+	} else {
+	    int tmp;
+
+	    tmp = xmlHashAddEntry(ctxt->parentgrammar->refs, def->name, def);
+	    if (tmp < 0) {
+		xmlRelaxNGDefinePtr prev;
+
+		prev = (xmlRelaxNGDefinePtr)
+		      xmlHashLookup(ctxt->parentgrammar->refs, def->name);
+		if (prev == NULL) {
+		    if (ctxt->error != NULL)
+			ctxt->error(ctxt->userData,
+			    "Internal error parentRef definitions '%s'\n",
+				    def->name);
+		    ctxt->nbErrors++;
+		    def = NULL;
+		} else {
+		    def->nextHash = prev->nextHash;
+		    prev->nextHash = def;
+		}
+	    }
+	}
     } else {
 	TODO
 	def = NULL;
@@ -2465,6 +2532,7 @@
 		case XML_RELAXNG_VALUE:
 		case XML_RELAXNG_LIST:
 		case XML_RELAXNG_REF:
+		case XML_RELAXNG_PARENTREF:
 		case XML_RELAXNG_EXTERNALREF:
 		case XML_RELAXNG_DEF:
 		case XML_RELAXNG_ONEORMORE:
@@ -2547,9 +2615,7 @@
 	else
 	    cur->type = XML_RELAXNG_ELEMENT;
 	
-        if (xmlRelaxNGParseNameClass(ctxt, child, cur) == NULL) {
-	    xmlRelaxNGFreeDefine(cur);
-	} else {
+        if (xmlRelaxNGParseNameClass(ctxt, child, cur) != NULL) {
 	    if (last == NULL) {
 		ret->content = cur;
 	    } else {
@@ -2674,6 +2740,7 @@
 		case XML_RELAXNG_VALUE:
 		case XML_RELAXNG_LIST:
 		case XML_RELAXNG_REF:
+		case XML_RELAXNG_PARENTREF:
 		case XML_RELAXNG_EXTERNALREF:
 		case XML_RELAXNG_DEF:
 		case XML_RELAXNG_ZEROORMORE:
@@ -2749,13 +2816,14 @@
 	    cur->parent = parent;
 	} else {
 	    cur = xmlRelaxNGParsePattern(ctxt, nodes);
-	    if (def == NULL) {
-		def = last = cur;
-	    } else {
-		last->next = cur;
-		last = cur;
+	    if (cur != NULL) {
+		if (def == NULL) {
+		    def = last = cur;
+		} else {
+		    last->next = cur;
+		    last = cur;
+		}
 	    }
-	    cur->parent = parent;
 	}
 	nodes = nodes->next;
     }
@@ -3321,6 +3389,13 @@
 	xmlFree(ctxt->docTab);
     if (ctxt->incTab != NULL)
 	xmlFree(ctxt->incTab);
+    if (ctxt->defTab != NULL) {
+	int i;
+
+	for (i = 0;i < ctxt->defNr;i++)
+	    xmlRelaxNGFreeDefine(ctxt->defTab[i]);
+	xmlFree(ctxt->defTab);
+    }
     xmlFree(ctxt);
 }
 
@@ -3746,6 +3821,9 @@
     ctxt->documents = NULL;
     ret->includes = ctxt->includes;
     ctxt->includes = NULL;
+    ret->defNr = ctxt->defNr;
+    ret->defTab = ctxt->defTab;
+    ctxt->defTab = NULL;
 
     return (ret);
 }
@@ -3880,6 +3958,14 @@
 	    xmlRelaxNGDumpDefines(output, define->content);
 	    fprintf(output, "</ref>\n");
 	    break;
+        case XML_RELAXNG_PARENTREF:
+	    fprintf(output, "<parentRef");
+	    if (define->name != NULL)
+		fprintf(output, " name=\"%s\"", define->name);
+	    fprintf(output, ">\n");
+	    xmlRelaxNGDumpDefines(output, define->content);
+	    fprintf(output, "</parentRef>\n");
+	    break;
 	case XML_RELAXNG_EXTERNALREF:
 	    fprintf(output, "<externalRef");
 	    xmlRelaxNGDumpDefines(output, define->content);
@@ -5081,8 +5167,9 @@
         case XML_RELAXNG_ATTRIBUTE:
 	    ret = xmlRelaxNGValidateAttribute(ctxt, define);
 	    break;
-	case XML_RELAXNG_EXTERNALREF:
         case XML_RELAXNG_REF:
+        case XML_RELAXNG_PARENTREF:
+	case XML_RELAXNG_EXTERNALREF:
 	    ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
 	    break;
         case XML_RELAXNG_DATATYPE: {