debug constraints


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@124 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/libasn1print/Makefile.am b/libasn1print/Makefile.am
index fb4861a..e88dac3 100644
--- a/libasn1print/Makefile.am
+++ b/libasn1print/Makefile.am
@@ -1,6 +1,8 @@
 
 AM_CFLAGS = @ADD_CFLAGS@
-AM_CPPFLAGS = -I${top_srcdir}/libasn1parser
+AM_CPPFLAGS = 				\
+	-I$(top_srcdir)/libasn1parser	\
+	-I$(top_srcdir)/libasn1fix
 
 noinst_LTLIBRARIES = libasn1print.la
 
@@ -8,7 +10,3 @@
 libasn1print_la_SOURCES =			\
 	asn1print.c asn1print.h
 
-LDADD = ${noinst_LTLIBRARIES} ${libasn1fix_la_LIBADD}
-DEPENDENCIES = ${LDADD} 
-
-TESTS = ${check_PROGRAMS}
diff --git a/libasn1print/Makefile.in b/libasn1print/Makefile.in
index c24ddf3..fce602b 100644
--- a/libasn1print/Makefile.in
+++ b/libasn1print/Makefile.in
@@ -180,15 +180,15 @@
 target_os = @target_os@
 target_vendor = @target_vendor@
 AM_CFLAGS = @ADD_CFLAGS@
-AM_CPPFLAGS = -I${top_srcdir}/libasn1parser
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/libasn1parser	\
+	-I$(top_srcdir)/libasn1fix
+
 noinst_LTLIBRARIES = libasn1print.la
 libasn1print_la_LDFLAGS = -all-static
 libasn1print_la_SOURCES = \
 	asn1print.c asn1print.h
 
-LDADD = ${noinst_LTLIBRARIES} ${libasn1fix_la_LIBADD}
-DEPENDENCIES = ${LDADD} 
-TESTS = ${check_PROGRAMS}
 all: all-am
 
 .SUFFIXES:
@@ -324,79 +324,6 @@
 distclean-tags:
 	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 
-check-TESTS: $(TESTS)
-	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
-	srcdir=$(srcdir); export srcdir; \
-	list='$(TESTS)'; \
-	if test -n "$$list"; then \
-	  for tst in $$list; do \
-	    if test -f ./$$tst; then dir=./; \
-	    elif test -f $$tst; then dir=; \
-	    else dir="$(srcdir)/"; fi; \
-	    if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
-	      all=`expr $$all + 1`; \
-	      case " $(XFAIL_TESTS) " in \
-	      *" $$tst "*) \
-		xpass=`expr $$xpass + 1`; \
-		failed=`expr $$failed + 1`; \
-		echo "XPASS: $$tst"; \
-	      ;; \
-	      *) \
-		echo "PASS: $$tst"; \
-	      ;; \
-	      esac; \
-	    elif test $$? -ne 77; then \
-	      all=`expr $$all + 1`; \
-	      case " $(XFAIL_TESTS) " in \
-	      *" $$tst "*) \
-		xfail=`expr $$xfail + 1`; \
-		echo "XFAIL: $$tst"; \
-	      ;; \
-	      *) \
-		failed=`expr $$failed + 1`; \
-		echo "FAIL: $$tst"; \
-	      ;; \
-	      esac; \
-	    else \
-	      skip=`expr $$skip + 1`; \
-	      echo "SKIP: $$tst"; \
-	    fi; \
-	  done; \
-	  if test "$$failed" -eq 0; then \
-	    if test "$$xfail" -eq 0; then \
-	      banner="All $$all tests passed"; \
-	    else \
-	      banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
-	    fi; \
-	  else \
-	    if test "$$xpass" -eq 0; then \
-	      banner="$$failed of $$all tests failed"; \
-	    else \
-	      banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
-	    fi; \
-	  fi; \
-	  dashes="$$banner"; \
-	  skipped=""; \
-	  if test "$$skip" -ne 0; then \
-	    skipped="($$skip tests were not run)"; \
-	    test `echo "$$skipped" | wc -c` -gt `echo "$$banner" | wc -c` && \
-	      dashes="$$skipped"; \
-	  fi; \
-	  report=""; \
-	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
-	    report="Please report to $(PACKAGE_BUGREPORT)"; \
-	    test `echo "$$report" | wc -c` -gt `echo "$$banner" | wc -c` && \
-	      dashes="$$report"; \
-	  fi; \
-	  dashes=`echo "$$dashes" | sed s/./=/g`; \
-	  echo "$$dashes"; \
-	  echo "$$banner"; \
-	  test -n "$$skipped" && echo "$$skipped"; \
-	  test -n "$$report" && echo "$$report"; \
-	  echo "$$dashes"; \
-	  test "$$failed" -eq 0; \
-	else :; fi
-
 distdir: $(DISTFILES)
 	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
 	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
@@ -425,7 +352,6 @@
 	  fi; \
 	done
 check-am: all-am
-	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
 check: check-am
 all-am: Makefile $(LTLIBRARIES)
 installdirs:
@@ -504,17 +430,17 @@
 
 uninstall-am: uninstall-info-am
 
-.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
-	clean-generic clean-libtool clean-noinstLTLIBRARIES ctags \
-	distclean distclean-compile distclean-generic \
-	distclean-libtool distclean-tags distdir dvi dvi-am html \
-	html-am info info-am install install-am install-data \
-	install-data-am install-exec install-exec-am install-info \
-	install-info-am install-man install-strip installcheck \
-	installcheck-am installdirs maintainer-clean \
-	maintainer-clean-generic mostlyclean mostlyclean-compile \
-	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-	tags uninstall uninstall-am uninstall-info-am
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-info-am
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/libasn1print/asn1print.c b/libasn1print/asn1print.c
index 9c2fed7..58ce284 100644
--- a/libasn1print/asn1print.c
+++ b/libasn1print/asn1print.c
@@ -4,6 +4,7 @@
 #include <assert.h>
 
 #include <asn1parser.h>
+#include <asn1fix_export.h>
 
 #include "asn1print.h"
 
@@ -12,22 +13,22 @@
 		printf(fmt, ##args);					\
 	} while(0)
 
-static int asn1print_module(asn1p_module_t *mod, enum asn1print_flags_e flags);
-static int asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags_e flags);
-static int asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags_e flags);
-static int asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags_e flags);
-static int asn1print_params(asn1p_paramlist_t *pl,enum asn1print_flags_e flags);
-static int asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags_e flags);
-static int asn1print_constraint(asn1p_constraint_t *, enum asn1print_flags_e);
-static int asn1print_value(asn1p_value_t *val, enum asn1print_flags_e flags);
-static int asn1print_expr(asn1p_expr_t *tc, enum asn1print_flags_e flags,
+static int asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags);
+static int asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags flags);
+static int asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags);
+static int asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags);
+static int asn1print_params(asn1p_paramlist_t *pl,enum asn1print_flags flags);
+static int asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags);
+static int asn1print_constraint(asn1p_constraint_t *, enum asn1print_flags);
+static int asn1print_value(asn1p_value_t *val, enum asn1print_flags flags);
+static int asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags,
 		int level);
 
 /*
  * Print the contents of the parsed ASN tree.
  */
 int
-asn1print(asn1p_t *asn, enum asn1print_flags_e flags) {
+asn1print(asn1p_t *asn, enum asn1print_flags flags) {
 	asn1p_module_t *mod;
 
 	if(asn == NULL) {
@@ -36,14 +37,14 @@
 	}
 
 	TQ_FOR(mod, &(asn->modules), mod_next) {
-		asn1print_module(mod, flags);
+		asn1print_module(asn, mod, flags);
 	}
 
 	return 0;
 }
 
 static int
-asn1print_module(asn1p_module_t *mod, enum asn1print_flags_e flags) {
+asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags) {
 	asn1p_expr_t *tc;
 
 	printf("\n%s ", mod->Identifier);
@@ -54,6 +55,10 @@
 
 	printf("DEFINITIONS");
 
+	if(mod->module_flags & MSF_TAG_INSTRUCTIONS)
+		printf(" TAG INSTRUCTIONS");
+	if(mod->module_flags & MSF_XER_INSTRUCTIONS)
+		printf(" XER INSTRUCTIONS");
 	if(mod->module_flags & MSF_EXPLICIT_TAGS)
 		printf(" EXPLICIT TAGS");
 	if(mod->module_flags & MSF_IMPLICIT_TAGS)
@@ -67,7 +72,7 @@
 	printf("BEGIN\n\n");
 
 	TQ_FOR(tc, &(mod->members), next) {
-		asn1print_expr(tc, flags, 0);
+		asn1print_expr(asn, mod, tc, flags, 0);
 		printf("\n\n");
 	}
 
@@ -77,7 +82,7 @@
 }
 
 static int
-asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags_e flags) {
+asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags flags) {
 	int ac;
 	int accum = 0;
 
@@ -107,7 +112,7 @@
 }
 
 static int
-asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags_e flags) {
+asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags) {
 	int cc;
 
 	(void)flags;	/* Unused argument */
@@ -121,7 +126,7 @@
 }
 
 static int
-asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags_e flags) {
+asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags) {
 	struct asn1p_type_tag_s *tag = &tc->tag;
 
 	(void)flags;	/* Unused argument */
@@ -152,7 +157,7 @@
 }
 
 static int
-asn1print_value(asn1p_value_t *val, enum asn1print_flags_e flags) {
+asn1print_value(asn1p_value_t *val, enum asn1print_flags flags) {
 
 	if(val == NULL)
 		return 0;
@@ -226,7 +231,7 @@
 }
 
 static int
-asn1print_constraint(asn1p_constraint_t *ct, enum asn1print_flags_e flags) {
+asn1print_constraint(asn1p_constraint_t *ct, enum asn1print_flags flags) {
 	int symno = 0;
 
 	if(ct == 0) return 0;
@@ -258,8 +263,8 @@
 	case ACT_CT_SIZE:
 	case ACT_CT_FROM:
 		switch(ct->type) {
-		case ACT_CT_SIZE: printf("SIZE ("); break;
-		case ACT_CT_FROM: printf("FROM ("); break;
+		case ACT_CT_SIZE: printf("SIZE("); break;
+		case ACT_CT_FROM: printf("FROM("); break;
 		default: printf("??? ("); break;
 		}
 		assert(ct->el_count != 0);
@@ -278,11 +283,11 @@
 	case ACT_CA_INT: symno++;
 	case ACT_CA_EXC:
 		{
-			char *symtable[] = { " EXCEPT ", "^", "|", ",",
+			char *symtable[] = { " EXCEPT ", " ^ ", " | ", ",",
 					"", "(" };
 			int i;
 			for(i = 0; i < ct->el_count; i++) {
-				enum asn1print_flags_e nflags = flags;
+				enum asn1print_flags nflags = flags;
 				if(i) fputs(symtable[symno], stdout);
 				if(ct->type == ACT_CA_CRC) fputs("{", stdout);
 				asn1print_constraint(ct->elements[i], nflags);
@@ -305,7 +310,7 @@
 }
 
 static int
-asn1print_params(asn1p_paramlist_t *pl, enum asn1print_flags_e flags) {
+asn1print_params(asn1p_paramlist_t *pl, enum asn1print_flags flags) {
 	if(pl) {
 		int i;
 		printf("{");
@@ -324,7 +329,7 @@
 }
 
 static int
-asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags_e flags) {
+asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags) {
 	if(wx) {
 		asn1p_wsyntx_chunk_t *wc;
 		printf(" WITH SYNTAX {");
@@ -342,7 +347,78 @@
 }
 
 static int
-asn1print_expr(asn1p_expr_t *tc, enum asn1print_flags_e flags, int level) {
+asn1print_crange_value(asn1cnst_edge_t *edge, int as_char) {
+	switch(edge->type) {
+	case ARE_MIN: printf("MIN"); break;
+	case ARE_MAX: printf("MAX"); break;
+	case ARE_VALUE:
+		if(as_char) {
+			printf("\"%c\"", (unsigned char)edge->value);
+		} else {
+			printf("%lld", (long long)edge->value);
+		}
+	}
+	return 0;
+}
+
+static int
+asn1print_constraint_explain_type(asn1p_expr_type_e expr_type, asn1p_constraint_t *ct, enum asn1p_constraint_type_e type) {
+	asn1cnst_range_t *range;
+	int as_char = (type==ACT_CT_FROM);
+	int i;
+
+	range = asn1constraint_compute_PER_range(expr_type, ct, type, 0, 0);
+	if(!range) return -1;
+
+	switch(type) {
+	case ACT_CT_FROM: printf("(FROM("); break;
+	case ACT_CT_SIZE: printf("(SIZE("); break;
+	default: printf("("); break;
+	}
+	for(i = -1; i < range->el_count; i++) {
+		asn1cnst_range_t *r;
+		if(i == -1) {
+			if(range->el_count) continue;
+			r = range;
+		} else {
+			r = range->elements[i];
+		}
+		if(i > 0) {
+			printf(" | ");
+		}
+		asn1print_crange_value(&r->left, as_char);
+		if(r->left.type != r->right.type
+		|| r->left.value != r->right.value) {
+			printf("..");
+			asn1print_crange_value(&r->right, as_char);
+		}
+	}
+	if(range->extensible)
+		printf(",...");
+	printf(type==ACT_EL_RANGE?")":"))");
+
+	if(range->empty_constraint)
+		printf(":Empty!");
+
+	asn1constraint_range_free(range);
+	return 0;
+}
+
+static int
+asn1print_constraint_explain(asn1p_expr_type_e expr_type,
+		asn1p_constraint_t *ct) {
+
+	asn1print_constraint_explain_type(expr_type, ct, ACT_EL_RANGE);
+	printf(" ");
+	asn1print_constraint_explain_type(expr_type, ct, ACT_CT_SIZE);
+	printf(" ");
+	asn1print_constraint_explain_type(expr_type, ct, ACT_CT_FROM);
+
+	return 0;
+}
+
+static int
+asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level) {
 
 	if(flags & APF_LINE_COMMENTS)
 	INDENT("-- #line %d\n", tc->_lineno);
@@ -413,7 +489,7 @@
 			/*
 			 * Print the expression as it were stand-alone type.
 			 */
-			asn1print_expr(se, flags, level + 4);
+			asn1print_expr(asn, mod, se, flags, level + 4);
 			switch(se->marker) {
 			case EM_NOMARK: break;
 			case EM_OPTIONAL: printf(" OPTIONAL"); break;
@@ -440,6 +516,7 @@
 		printf(" ");
 		asn1print_constraint(tc->constraints, flags);
 	}
+
 	if(tc->unique) {
 		printf(" UNIQUE");
 	}
@@ -455,5 +532,22 @@
 			printf(")");
 	}
 
+	if(flags & APF_DEBUG_CONSTRAINTS) {
+		asn1p_expr_t *top_parent;
+
+		if(tc->combined_constraints) {
+			printf("\n-- Combined constraints: ");
+			asn1print_constraint(tc->combined_constraints, flags);
+		}
+
+		top_parent = asn1f_find_terminal_type_ex(asn, mod, tc, NULL);
+		if(top_parent) {
+			printf("\n-- PER-visible constraints: ");
+			asn1print_constraint_explain(top_parent->expr_type,
+				tc->combined_constraints);
+		}
+	}
+
 	return 0;
 }
+
diff --git a/libasn1print/asn1print.h b/libasn1print/asn1print.h
index 115e186..c24e58e 100644
--- a/libasn1print/asn1print.h
+++ b/libasn1print/asn1print.h
@@ -1,15 +1,16 @@
 #ifndef	_ASN1PRINT_H_
 #define	_ASN1PRINT_H_
 
-enum asn1print_flags_e {
-	APF_NOFLAGS		= 0x00,
-	APF_LINE_COMMENTS	= 0x01,
+enum asn1print_flags {
+	APF_NOFLAGS,
+	APF_LINE_COMMENTS	= 0x01, /* Include line comments */
+	APF_DEBUG_CONSTRAINTS	= 0x02,	/* Explain constraints */
 };
 
 /*
  * Print the contents of the parsed ASN.1 syntax tree.
  */
-int asn1print(asn1p_t *asn, enum asn1print_flags_e flags);
+int asn1print(asn1p_t *asn, enum asn1print_flags flags);
 
 
 #endif	/* _ASN1PRINT_H_ */