started adding schematron to the xmllint tool, the report infrastructure

* schematron.c xmllint.c: started adding schematron to the xmllint
  tool, the report infrastructure is gonna be fun.
Daniel
diff --git a/schematron.c b/schematron.c
index 4211b78..dbf4543 100644
--- a/schematron.c
+++ b/schematron.c
@@ -63,6 +63,7 @@
     xmlNodePtr node;		/* the node in the tree */
     xmlChar *test;		/* the expression to test */
     xmlXPathCompExprPtr comp;	/* the compiled expression */
+    xmlChar *report;		/* the message to report */
 };
 
 /**
@@ -78,6 +79,7 @@
     xmlChar *context;		/* the context evaluation rule */
     xmlSchematronTestPtr tests;	/* the list of tests */
     xmlPatternPtr pattern;	/* the compiled pattern associated */
+    xmlChar *report;		/* the message to report */
 };
 
 /**
@@ -247,6 +249,7 @@
  * @schema:  a schema structure
  * @node:  the node hosting the test
  * @context: the associated context string
+ * @report: the associated report string
  *
  * Add a test to a schematron
  *
@@ -255,7 +258,7 @@
 static xmlSchematronTestPtr
 xmlSchematronAddTest(xmlSchematronParserCtxtPtr ctxt, int type,
                      xmlSchematronRulePtr rule,
-                     xmlNodePtr node, xmlChar *test)
+                     xmlNodePtr node, xmlChar *test, xmlChar *report)
 {
     xmlSchematronTestPtr ret;
     xmlXPathCompExprPtr comp;
@@ -286,6 +289,7 @@
     ret->node = node;
     ret->test = test;
     ret->comp = comp;
+    ret->report = report;
     ret->next = rule->tests;
     rule->tests = ret;
     return (ret);
@@ -307,6 +311,8 @@
 	    xmlFree(tests->test);
 	if (tests->comp != NULL)
 	    xmlXPathFreeCompExpr(tests->comp);
+	if (tests->report != NULL)
+	    xmlFree(tests->report);
 	xmlFree(tests);
 	tests = next;
     }
@@ -318,6 +324,7 @@
  * @schema:  a schema structure
  * @node:  the node hosting the rule
  * @context: the associated context string
+ * @report: the associated report string
  *
  * Add a rule to a schematron
  *
@@ -325,7 +332,7 @@
  */
 static xmlSchematronRulePtr
 xmlSchematronAddRule(xmlSchematronParserCtxtPtr ctxt, xmlSchematronPtr schema,
-                     xmlNodePtr node, xmlChar *context)
+                     xmlNodePtr node, xmlChar *context, xmlChar *report)
 {
     xmlSchematronRulePtr ret;
     xmlPatternPtr pattern;
@@ -356,6 +363,7 @@
     ret->context = context;
     ret->next = schema->rules;
     ret->pattern = pattern;
+    ret->report = report;
     schema->rules = ret;
     return (ret);
 }
@@ -378,6 +386,8 @@
 	    xmlFree(rules->context);
 	if (rules->pattern)
 	    xmlFreePattern(rules->pattern);
+	if (rules->report != NULL)
+	    xmlFree(rules->report);
 	xmlFree(rules);
 	rules = next;
     }
@@ -704,6 +714,7 @@
     int nbChecks = 0;
     xmlChar *test;
     xmlChar *context;
+    xmlChar *report;
     xmlSchematronRulePtr ruleptr;
     xmlSchematronTestPtr testptr;
 
@@ -724,7 +735,7 @@
 	xmlFree(context);
 	return;
     } else {
-	ruleptr = xmlSchematronAddRule(ctxt, ctxt->schema, rule, context);
+	ruleptr = xmlSchematronAddRule(ctxt, ctxt->schema, rule, context, NULL);
 	if (ruleptr == NULL) {
 	    xmlFree(context);
 	    return;
@@ -749,8 +760,11 @@
 		    NULL, NULL);
 		xmlFree(test);
 	    } else {
+		/* TODO will need dynamic processing instead */
+		report = xmlNodeGetContent(cur);
+
 		testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_ASSERT,
-		                               ruleptr, cur, test);
+		                               ruleptr, cur, test, report);
 		if (testptr == NULL)
 		    xmlFree(test);
 	    }
@@ -769,8 +783,11 @@
 		    NULL, NULL);
 		xmlFree(test);
 	    } else {
+		/* TODO will need dynamic processing instead */
+		report = xmlNodeGetContent(cur);
+
 		testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_REPORT,
-		                               ruleptr, cur, test);
+		                               ruleptr, cur, test, report);
 		if (testptr == NULL)
 		    xmlFree(test);
 	    }
@@ -1057,9 +1074,68 @@
  *									*
  ************************************************************************/
 
+/**
+ * xmlSchematronReportOutput:
+ * @ctxt: the validation context
+ * @cur: the current node tested
+ * @msg: the message output
+ *
+ * Output part of the report to whatever channel the user selected
+ */
+static void
+xmlSchematronReportOutput(xmlSchematronValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
+                          xmlNodePtr cur ATTRIBUTE_UNUSED,
+                          const char *msg ATTRIBUTE_UNUSED) {
+    /* TODO */
+    fprintf(stderr, "%s", msg);
+}
+
+/**
+ * xmlSchematronReportSuccess:
+ * @ctxt:  the validation context
+ * @test: the compiled test
+ * @cur: the current node tested
+ * @success: boolean value for the result
+ *
+ * called from the validation engine when an assert or report test have
+ * been done.
+ */
 static void
 xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt, 
-			   xmlSchematronTestPtr test, xmlNodePtr cur) {
+		   xmlSchematronTestPtr test, xmlNodePtr cur, int success) {
+    if ((ctxt == NULL) || (cur == NULL) || (test == NULL))
+        return;
+    /* if quiet and not SVRL report only failures */
+    if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) &&
+        ((ctxt->flags & XML_SCHEMATRON_OUT_XML) == 0) && (success))
+        return;
+    if (ctxt->flags & XML_SCHEMATRON_OUT_XML) {
+        TODO
+    } else {
+        xmlChar *path;
+	char msg[1000];
+	long line;
+	const xmlChar *report;
+
+	if (success)
+	    return;
+	line = xmlGetLineNo(cur);
+	path = xmlGetNodePath(cur);
+	if (path == NULL)
+	    path = (xmlChar *) cur->name;
+	if ((test->report != NULL) && (test->report[0] != 0))
+	    report = test->report;
+	else if (test->type == XML_SCHEMATRON_ASSERT) {
+	    report = BAD_CAST "node failed assert";
+	} else {
+	    report = BAD_CAST "node failed report";
+	}
+	snprintf(msg, 999, "%s line %ld:\n  %s\n", (const char *) path,
+	         line, (const char *) report);
+	xmlSchematronReportOutput(ctxt, cur, &msg[0]);
+	if ((path != NULL) && (path != (xmlChar *) cur->name))
+	    xmlFree(path);
+    }
 }
 
 /************************************************************************
@@ -1095,6 +1171,7 @@
     ret->type = XML_STRON_CTXT_VALIDATOR;
     ret->schema = schema;
     ret->xctxt = xmlXPathNewContext(NULL);
+    ret->flags = options;
     if (ret->xctxt == NULL) {
         xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
                                 NULL);
@@ -1216,15 +1293,9 @@
 	    failed = 1;
 	    break;
     }
-    if (test->type == XML_SCHEMATRON_REPORT) {
-	if (!failed) {
-	    printf("report failed\n");
-	}
-    } else {
-	if (failed) {
-	    printf("assert failed\n");
-	}
-    }
+    if (failed) 
+        ctxt->nberrors++;
+    xmlSchematronReportSuccess(ctxt, test, cur, !failed);
 
     return(!failed);
 }
@@ -1255,7 +1326,6 @@
         rule = ctxt->schema->rules;
 	while (rule != NULL) {
 	    if (xmlPatternMatch(rule->pattern, cur) == 1) {
-	        printf("%s matches\n", cur->name);
 	        test = rule->tests;
 		while (test != NULL) {
 		    xmlSchematronRunTest(ctxt, test, instance, cur);