X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=libasn1fix%2Fasn1fix_compat.c;fp=libasn1fix%2Fasn1fix_compat.c;h=064e38e522d3013f054a6c0a949dab4c180332b7;hb=70ee6fc793ec8e828067a3569849b6c216054497;hp=0000000000000000000000000000000000000000;hpb=59f84608ec15c016958a6e0e0ddd813f376c0925;p=com%2Fasn1c.git diff --git a/libasn1fix/asn1fix_compat.c b/libasn1fix/asn1fix_compat.c new file mode 100644 index 0000000..064e38e --- /dev/null +++ b/libasn1fix/asn1fix_compat.c @@ -0,0 +1,149 @@ +#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:%x@%d, %s:%x@%d)", + a->Identifier, atype, a->_lineno, + b->Identifier, btype, b->_lineno); + + /* + * Expected terminal type! + */ + assert(atype != A1TC_REFERENCE); + assert(btype != A1TC_REFERENCE); + + if(a == b) + return 0; /* Fairly obviously */ + + if(atype != btype) { + /* + * Limited cross-compatibility of integer types. + */ + if((atype == A1TC_UNIVERVAL && btype == ASN_BASIC_INTEGER) + || (atype == A1TC_UNIVERVAL && btype == ASN_BASIC_ENUMERATED) + ) + return 0; + + /* Limited cross-compatibility of string types */ + if((atype & ASN_STRING_MASK) + && (btype & ASN_STRING_MASK)) { + /* X.680, B.5 */ + int akm = (atype & ASN_STRING_KM_MASK) + || atype == ASN_STRING_UTF8String; + int bkm = (btype & ASN_STRING_KM_MASK) + || btype == ASN_STRING_UTF8String; + return (akm == bkm) ? 0 : -1; + } + + DEBUG("\t%s and %s are not compatible", + a->Identifier, b->Identifier); + return -1; /* Fairly obviously */ + } + + switch(atype) { + case ASN_BASIC_INTEGER: + /* All integers are compatible, X.680, B.4.5 */ + 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: + if((atype & ASN_STRING_MASK) + && (btype & ASN_STRING_MASK)) { + /* String type is compatible with the same type */ + return 0; + } + /* 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; +} + +