diff options
author | vlm <vlm@59561ff5-6e30-0410-9f3c-9617f08c8826> | 2004-06-03 03:38:44 +0000 |
---|---|---|
committer | vlm <vlm@59561ff5-6e30-0410-9f3c-9617f08c8826> | 2004-06-03 03:38:44 +0000 |
commit | fa67ddcad9ce4ce04668d8ce46f4ac0057c914c2 (patch) | |
tree | 33461d45122896c6dde35f82f5c7d19b62004a6b /libasn1fix/asn1fix_compat.c | |
parent | 4cc3ff02fa66f711b10608e46a509bfcec57a876 (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.c | 132 |
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; +} + + |