aboutsummaryrefslogtreecommitdiffstats
path: root/libasn1fix/asn1fix_compat.c
diff options
context:
space:
mode:
authorvlm <vlm@59561ff5-6e30-0410-9f3c-9617f08c8826>2004-06-03 03:38:44 +0000
committervlm <vlm@59561ff5-6e30-0410-9f3c-9617f08c8826>2004-06-03 03:38:44 +0000
commitfa67ddcad9ce4ce04668d8ce46f4ac0057c914c2 (patch)
tree33461d45122896c6dde35f82f5c7d19b62004a6b /libasn1fix/asn1fix_compat.c
parent4cc3ff02fa66f711b10608e46a509bfcec57a876 (diff)
Initial revision
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@2 59561ff5-6e30-0410-9f3c-9617f08c8826
Diffstat (limited to 'libasn1fix/asn1fix_compat.c')
-rw-r--r--libasn1fix/asn1fix_compat.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/libasn1fix/asn1fix_compat.c b/libasn1fix/asn1fix_compat.c
new file mode 100644
index 00000000..aef26c0b
--- /dev/null
+++ b/libasn1fix/asn1fix_compat.c
@@ -0,0 +1,132 @@
+#include "asn1fix_internal.h"
+
+static int asn1f_check_same_children(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
+
+/*
+ * Check that the expressions given are compatible in their type.
+ * ORDER DOES MATTER! (See .h).
+ */
+int
+asn1f_check_type_compatibility(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
+ asn1p_expr_type_e atype, btype;
+
+ atype = a->expr_type;
+ btype = b->expr_type;
+
+ DEBUG("%s(%s:%x@%d, %s:%x@%d)", __func__,
+ a->Identifier, atype, a->_lineno,
+ b->Identifier, btype, b->_lineno);
+
+ /*
+ * Expected terminal type!
+ */
+ assert(atype != A1TC_REFERENCE);
+ assert(btype != A1TC_REFERENCE);
+
+ if(atype != btype) {
+ /*
+ * Limited compatibility.
+ */
+ if((atype == A1TC_UNIVERVAL && btype == ASN_BASIC_INTEGER)
+ || (atype == A1TC_UNIVERVAL && btype == ASN_BASIC_ENUMERATED)
+ )
+ return 0;
+ DEBUG("\t%s and %s are not compatible",
+ a->Identifier, b->Identifier);
+ return -1; /* Fairly obviously */
+ }
+
+ if(a == b)
+ return 0; /* Fairly obviously */
+
+ switch(atype) {
+ case ASN_BASIC_INTEGER:
+ /* All integers are compatible */
+ return 0;
+ case ASN_BASIC_ENUMERATED:
+ /*
+ * Enumerations are not compatible
+ * unless their definitions are the same.
+ */
+ if(asn1f_check_same_children(arg, a, b)) {
+ DEBUG("\tEnumerations are different %s and %s",
+ a->Identifier, b->Identifier);
+ return -1;
+ }
+ return 0;
+ default:
+ /* Compatibility is not defined yet */
+ DEBUG("\tCompatibility rule is not defined for %s and %s",
+ a->Identifier, b->Identifier);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Check that the children are exactly same.
+ */
+static int
+asn1f_check_same_children(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
+ asn1p_expr_t *achild;
+ asn1p_expr_t *bchild;
+
+ achild = TQ_FIRST(&(a->members));
+ bchild = TQ_FIRST(&(b->members));
+
+ while(1) {
+ if(achild->expr_type != bchild->expr_type)
+ return -1;
+
+ if(achild->Identifier && bchild->Identifier) {
+ if(strcmp(achild->Identifier, bchild->Identifier))
+ return -1;
+ } else if(!(!achild->Identifier && !bchild->Identifier)) {
+ return -1;
+ }
+
+ if(achild->value && bchild->value) {
+ if(achild->value->type != bchild->value->type)
+ return -1;
+ switch(achild->value->type) {
+ case ATV_INTEGER:
+ if(achild->value->value.v_integer
+ != bchild->value->value.v_integer)
+ return -1;
+ break;
+ case ATV_REFERENCED:
+ default:
+ DEBUG("Value %s at lines %d and "
+ "%d cannot be used in "
+ "semantical equality check",
+ asn1f_printable_value(achild->value),
+ achild->value->value.reference->_lineno,
+ bchild->value->value.reference->_lineno
+ );
+ return -1;
+ }
+ } else if(!(!achild->value && !bchild->value)) {
+ /* One of values is defined, and another is not */
+ return -1;
+ }
+
+ achild = TQ_NEXT(achild, next);
+ bchild = TQ_NEXT(bchild, next);
+
+ if(achild && bchild)
+ continue;
+ else if(!achild && !bchild)
+ break;
+ else
+ return -1;
+ }
+
+ DEBUG("\t%s:%x@%d and %s:%x@%d are semantically equivalent",
+ a->Identifier, a->expr_type, a->_lineno,
+ b->Identifier, b->expr_type, b->_lineno);
+
+ return 0;
+}
+
+