more work on Relax-NG augmented/updated the regression tests Daniel

* relaxng.c: more work on Relax-NG
* test/relaxng/* result/relaxng/*: augmented/updated the
  regression tests
Daniel
diff --git a/ChangeLog b/ChangeLog
index d53f386..bbe98d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Sun Jan 26 01:49:58 CET 2003 Daniel Veillard <daniel@veillard.com>
+
+	* relaxng.c: more work on Relax-NG
+	* test/relaxng/* result/relaxng/*: augmented/updated the 
+	  regression tests
+
 Sat Jan 25 18:59:54 CET 2003 Daniel Veillard <daniel@veillard.com>
 
 	* README: updated the policy on private mail answers
diff --git a/relaxng.c b/relaxng.c
index 61af8c0..2391f72 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -98,6 +98,7 @@
     xmlNodePtr	   node;	/* the node in the source */
     xmlChar       *name;	/* the element local name if present */
     xmlChar       *ns;		/* the namespace local name if present */
+    xmlChar       *value;	/* value when available */
     void          *data;	/* data lib or specific pointer */
     xmlRelaxNGDefinePtr content;/* the expected content */
     xmlRelaxNGDefinePtr next;	/* list within grouping sequences */
@@ -438,6 +439,8 @@
 	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) &&
@@ -968,6 +971,88 @@
 }
 
 /**
+ * xmlRelaxNGParseValue:
+ * @ctxt:  a Relax-NG parser context
+ * @node:  the data node.
+ *
+ * parse the content of a RelaxNG value node.
+ *
+ * Returns the definition pointer or NULL in case of error
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
+    xmlRelaxNGDefinePtr def = NULL;
+    xmlRelaxNGTypeLibraryPtr lib;
+    xmlChar *type;
+    xmlChar *library;
+    int tmp;
+
+    def = xmlRelaxNGNewDefine(ctxt, node);
+    if (def == NULL)
+	return(NULL);
+    def->type = XML_RELAXNG_VALUE;
+
+    type = xmlGetProp(node, BAD_CAST "type");
+    if (type != NULL) {
+	library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
+	if (library == NULL)
+	    library = xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
+
+	def->name = type;
+	def->ns = library;
+
+	lib = (xmlRelaxNGTypeLibraryPtr)
+	    xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
+	if (lib == NULL) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+		    "Use of unregistered type library '%s'\n",
+			    library);
+	    ctxt->nbErrors++;
+	    def->data = NULL;
+	} else {
+	    def->data = lib;
+	    if (lib->have == NULL) {
+		ctxt->error(ctxt->userData,
+		    "Internal error with type library '%s': no 'have'\n",
+			    library);
+		ctxt->nbErrors++;
+	    } else {
+		tmp = lib->have(lib->data, def->name);
+		if (tmp != 1) {
+		    ctxt->error(ctxt->userData,
+		    "Error type '%s' is not exported by type library '%s'\n",
+				def->name, library);
+		    ctxt->nbErrors++;
+		}
+	    }
+	}
+    }
+    if (node->children == NULL) {
+	if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+			"Element <value> has no content\n");
+	ctxt->nbErrors++;
+    } else if ((node->children->type != XML_TEXT_NODE) ||
+	       (node->children->next != NULL)) {
+	if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+		"Expecting a single text value for <value>content\n");
+	ctxt->nbErrors++;
+    } else {
+	def->value = xmlNodeGetContent(node);
+	if (def->value == NULL) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			    "Element <value> has no content\n");
+	    ctxt->nbErrors++;
+	}
+    }
+    /* TODO check ahead of time that the value is okay per the type */
+    return(def);
+}
+
+/**
  * xmlRelaxNGParseData:
  * @ctxt:  a Relax-NG parser context
  * @node:  the data node.
@@ -1234,6 +1319,8 @@
     } else if (IS_RELAXNG(node, "define")) {
 	xmlRelaxNGParseDefine(ctxt, node);
 	def = NULL;
+    } else if (IS_RELAXNG(node, "value")) {
+	def = xmlRelaxNGParseValue(ctxt, node);
     } else {
 	TODO
     }
@@ -2546,6 +2633,49 @@
 }
 
 /**
+ * xmlRelaxNGNormalize:
+ * @ctxt:  a schema validation context
+ * @str:  the string to normalize
+ *
+ * Implements the  normalizeWhiteSpace( s ) function from
+ * section 6.2.9 of the spec
+ *
+ * Returns the new string or NULL in case of error.
+ */
+static xmlChar *
+xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *str) {
+    xmlChar *ret, *p;
+    const xmlChar *tmp;
+    int len;
+    
+    if (str == NULL)
+	return(NULL);
+    tmp = str;
+    while (*tmp != 0) tmp++;
+    len = tmp - str;
+
+    ret = (xmlChar *) xmlMalloc((len + 1) * sizeof(xmlChar));
+    if (ret == NULL) {
+	VALID_CTXT();
+	VALID_ERROR("xmlRelaxNGNormalize: out of memory\n");
+        return(NULL);
+    }
+    p = ret;
+    while (IS_BLANK(*str)) str++;
+    while (*str != 0) {
+	if (IS_BLANK(*str)) {
+	    while (IS_BLANK(*str)) str++;
+	    if (*str == 0)
+		break;
+	    *p++ = ' ';
+	} else 
+	    *p++ = *str++;
+    }
+    *p = 0;
+    return(ret);
+}
+
+/**
  * xmlRelaxNGValidateDatatype:
  * @ctxt:  a Relax-NG validation context
  * @value:  the string value
@@ -2596,7 +2726,7 @@
 static int
 xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, 
 	                xmlRelaxNGDefinePtr define) {
-    int ret = 0;
+    int ret = 0, oldflags;
     xmlChar *value;
 
     value = ctxt->state->value;
@@ -2607,6 +2737,46 @@
 	    break;
 	case XML_RELAXNG_TEXT:
 	    break;
+	case XML_RELAXNG_CHOICE: {
+	    xmlRelaxNGDefinePtr list = define->content;
+
+	    oldflags = ctxt->flags;
+	    ctxt->flags |= FLAGS_IGNORABLE;
+
+	    while (list != NULL) {
+		ret = xmlRelaxNGValidateValue(ctxt, list);
+		if (ret == 0) {
+		    break;
+		}
+		list = list->next;
+	    }
+	    ctxt->flags = oldflags;
+	    break;
+	}
+	case XML_RELAXNG_VALUE: {
+	    if (!xmlStrEqual(value, define->value)) {
+		if (define->name != NULL) {
+		    TODO /* value validation w.r.t. the type */
+		} else {
+		    xmlChar *nval, *nvalue;
+
+		    /*
+		     * TODO: trivial optimizations are possible by
+		     * computing at compile-time
+		     */
+		    nval = xmlRelaxNGNormalize(ctxt, define->value);
+		    nvalue = xmlRelaxNGNormalize(ctxt, value);
+
+		    if (!xmlStrEqual(nval, nvalue))
+			ret = -1;
+		    if (nval != NULL)
+			xmlFree(nval);
+		    if (nvalue != NULL)
+			xmlFree(nvalue);
+		}
+	    }
+	    break;
+	}
 	default:
 	    TODO
 	    ret = -1;
diff --git a/result/relaxng/tutor3_2_1.err b/result/relaxng/tutor3_2_1.err
index 8e23334..48ac0c4 100644
--- a/result/relaxng/tutor3_2_1.err
+++ b/result/relaxng/tutor3_2_1.err
@@ -1,3 +1,3 @@
-error detected at relaxng.c:2812
-error detected at relaxng.c:2860
+error detected at relaxng.c:2982
+error detected at relaxng.c:3030
 xmlRelaxNGValidateDefinition(): validated card : -1
diff --git a/result/relaxng/tutor3_5_2.err b/result/relaxng/tutor3_5_2.err
index 909ad8b..9c72d17 100644
--- a/result/relaxng/tutor3_5_2.err
+++ b/result/relaxng/tutor3_5_2.err
@@ -1,5 +1,5 @@
 xmlRelaxNGValidateAttribute(name): -1
 xmlRelaxNGValidateDefinition(): validated email : 0
 xmlRelaxNGValidateDefinition(): validated card : -1
-error detected at relaxng.c:2860
+error detected at relaxng.c:3030
 xmlRelaxNGValidateDefinition(): validated addressBook : -1
diff --git a/result/relaxng/tutor5_1_1.err b/result/relaxng/tutor5_1_1.err
index d987a68..e9fa2d9 100644
--- a/result/relaxng/tutor5_1_1.err
+++ b/result/relaxng/tutor5_1_1.err
@@ -1,3 +1,3 @@
-Unimplemented block at relaxng.c:667
-Unimplemented block at relaxng.c:686
+Unimplemented block at relaxng.c:670
+Unimplemented block at relaxng.c:689
 xmlRelaxNGValidateDefinition(): validated number : 0
diff --git a/result/relaxng/tutor5_2_1.err b/result/relaxng/tutor5_2_1.err
index 24865cc..ac9beb0 100644
--- a/result/relaxng/tutor5_2_1.err
+++ b/result/relaxng/tutor5_2_1.err
@@ -1,7 +1,7 @@
-Unimplemented block at relaxng.c:667
-Unimplemented block at relaxng.c:667
-Unimplemented block at relaxng.c:686
+Unimplemented block at relaxng.c:670
+Unimplemented block at relaxng.c:670
+Unimplemented block at relaxng.c:689
 xmlRelaxNGValidateDefinition(): validated x : 0
-Unimplemented block at relaxng.c:686
+Unimplemented block at relaxng.c:689
 xmlRelaxNGValidateDefinition(): validated y : 0
 xmlRelaxNGValidateDefinition(): validated point : 0
diff --git a/result/relaxng/tutor5_3_1.err b/result/relaxng/tutor5_3_1.err
index 0ea4f9a..5f30338 100644
--- a/result/relaxng/tutor5_3_1.err
+++ b/result/relaxng/tutor5_3_1.err
@@ -1,3 +1,3 @@
-error detected at relaxng.c:2993
+error detected at relaxng.c:3163
 xmlRelaxNGValidateDefinition(): validated note : 0
 xmlRelaxNGValidateDefinition(): validated bad : -1
diff --git a/result/relaxng/tutor6_1_1 b/result/relaxng/tutor6_1_1
new file mode 100644
index 0000000..3c44662
--- /dev/null
+++ b/result/relaxng/tutor6_1_1
@@ -0,0 +1 @@
+./test/relaxng/tutor6_1_1.xml validates
diff --git a/result/relaxng/tutor6_1_1.err b/result/relaxng/tutor6_1_1.err
new file mode 100644
index 0000000..6e45621
--- /dev/null
+++ b/result/relaxng/tutor6_1_1.err
@@ -0,0 +1,4 @@
+xmlRelaxNGValidateAttribute(preferredFormat): 0
+xmlRelaxNGValidateAttribute(email): 0
+xmlRelaxNGValidateAttribute(name): 0
+xmlRelaxNGValidateDefinition(): validated card : 0
diff --git a/result/relaxng/tutor6_1_2 b/result/relaxng/tutor6_1_2
new file mode 100644
index 0000000..6c70fed
--- /dev/null
+++ b/result/relaxng/tutor6_1_2
@@ -0,0 +1 @@
+./test/relaxng/tutor6_1_2.xml validates
diff --git a/result/relaxng/tutor6_1_2.err b/result/relaxng/tutor6_1_2.err
new file mode 100644
index 0000000..6e45621
--- /dev/null
+++ b/result/relaxng/tutor6_1_2.err
@@ -0,0 +1,4 @@
+xmlRelaxNGValidateAttribute(preferredFormat): 0
+xmlRelaxNGValidateAttribute(email): 0
+xmlRelaxNGValidateAttribute(name): 0
+xmlRelaxNGValidateDefinition(): validated card : 0
diff --git a/result/relaxng/tutor6_1_3 b/result/relaxng/tutor6_1_3
new file mode 100644
index 0000000..2dea674
--- /dev/null
+++ b/result/relaxng/tutor6_1_3
@@ -0,0 +1,2 @@
+Extra attribute preferredFormat for element card
+./test/relaxng/tutor6_1_3.xml validation generated an internal error
diff --git a/result/relaxng/tutor6_1_3.err b/result/relaxng/tutor6_1_3.err
new file mode 100644
index 0000000..68f183f
--- /dev/null
+++ b/result/relaxng/tutor6_1_3.err
@@ -0,0 +1,5 @@
+xmlRelaxNGValidateAttribute(preferredFormat): -1
+xmlRelaxNGValidateAttribute(email): 0
+xmlRelaxNGValidateAttribute(name): 0
+error detected at relaxng.c:3038
+xmlRelaxNGValidateDefinition(): validated card : -1
diff --git a/test/relaxng/tutor6_1_1.xml b/test/relaxng/tutor6_1_1.xml
new file mode 100644
index 0000000..30460ae
--- /dev/null
+++ b/test/relaxng/tutor6_1_1.xml
@@ -0,0 +1 @@
+<card name="foo" email="bar" preferredFormat="text"/>
diff --git a/test/relaxng/tutor6_1_2.xml b/test/relaxng/tutor6_1_2.xml
new file mode 100644
index 0000000..bf3dfc2
--- /dev/null
+++ b/test/relaxng/tutor6_1_2.xml
@@ -0,0 +1 @@
+<card name="foo" email="bar" preferredFormat="html"/>
diff --git a/test/relaxng/tutor6_1_3.xml b/test/relaxng/tutor6_1_3.xml
new file mode 100644
index 0000000..6038d79
--- /dev/null
+++ b/test/relaxng/tutor6_1_3.xml
@@ -0,0 +1 @@
+<card name="foo" email="bar" preferredFormat="error"/>