asn1c/libasn1fix/asn1fix_compat.c

133 lines
3.0 KiB
C

#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;
}