064e38e522d3013f054a6c0a949dab4c180332b7
[com/asn1c.git] / libasn1fix / asn1fix_compat.c
1 #include "asn1fix_internal.h"
2
3 static int asn1f_check_same_children(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
4
5 /*
6  * Check that the expressions given are compatible in their type.
7  * ORDER DOES MATTER! (See .h).
8  */
9 int
10 asn1f_check_type_compatibility(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
11         asn1p_expr_type_e atype, btype;
12
13         atype = a->expr_type;
14         btype = b->expr_type;
15
16         DEBUG("(%s:%x@%d, %s:%x@%d)",
17                 a->Identifier, atype, a->_lineno,
18                 b->Identifier, btype, b->_lineno);
19
20         /*
21          * Expected terminal type!
22          */
23         assert(atype != A1TC_REFERENCE);
24         assert(btype != A1TC_REFERENCE);
25
26         if(a == b)
27                 return 0;       /* Fairly obviously */
28
29         if(atype != btype) {
30                 /*
31                  * Limited cross-compatibility of integer types.
32                  */
33                 if((atype == A1TC_UNIVERVAL && btype == ASN_BASIC_INTEGER)
34                 || (atype == A1TC_UNIVERVAL && btype == ASN_BASIC_ENUMERATED)
35                 )
36                         return 0;
37
38                 /* Limited cross-compatibility of string types */
39                 if((atype & ASN_STRING_MASK)
40                 && (btype & ASN_STRING_MASK)) {
41                         /* X.680, B.5 */
42                         int akm = (atype & ASN_STRING_KM_MASK)
43                                 || atype == ASN_STRING_UTF8String;
44                         int bkm = (btype & ASN_STRING_KM_MASK)
45                                 || btype == ASN_STRING_UTF8String;
46                         return (akm == bkm) ? 0 : -1;
47                 }
48
49                 DEBUG("\t%s and %s are not compatible",
50                         a->Identifier, b->Identifier);
51                 return -1;      /* Fairly obviously */
52         }
53
54         switch(atype) {
55         case ASN_BASIC_INTEGER:
56                 /* All integers are compatible, X.680, B.4.5 */
57                 return 0;
58         case ASN_BASIC_ENUMERATED:
59                 /*
60                  * Enumerations are not compatible
61                  * unless their definitions are the same.
62                  */
63                 if(asn1f_check_same_children(arg, a, b)) {
64                         DEBUG("\tEnumerations are different %s and %s",
65                                 a->Identifier, b->Identifier);
66                         return -1;
67                 }
68                 return 0;
69         default:
70                 if((atype & ASN_STRING_MASK)
71                 && (btype & ASN_STRING_MASK)) {
72                         /* String type is compatible with the same type */
73                         return 0;
74                 }
75                 /* Compatibility is not defined yet */
76                 DEBUG("\tCompatibility rule is not defined for %s and %s",
77                         a->Identifier, b->Identifier);
78                 return -1;
79         }
80
81         return 0;
82 }
83
84 /*
85  * Check that the children are exactly same.
86  */
87 static int
88 asn1f_check_same_children(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
89         asn1p_expr_t *achild;
90         asn1p_expr_t *bchild;
91
92         achild = TQ_FIRST(&(a->members));
93         bchild = TQ_FIRST(&(b->members));
94
95         while(1) {
96                 if(achild->expr_type != bchild->expr_type)
97                         return -1;
98
99                 if(achild->Identifier && bchild->Identifier) {
100                         if(strcmp(achild->Identifier, bchild->Identifier))
101                                 return -1;
102                 } else if(!(!achild->Identifier && !bchild->Identifier)) {
103                         return -1;
104                 }
105
106                 if(achild->value && bchild->value) {
107                         if(achild->value->type != bchild->value->type)
108                                 return -1;
109                         switch(achild->value->type) {
110                         case ATV_INTEGER:
111                                 if(achild->value->value.v_integer
112                                 != bchild->value->value.v_integer)
113                                         return -1;
114                                 break;
115                         case ATV_REFERENCED:
116                         default:
117                                 DEBUG("Value %s at lines %d and "
118                                         "%d cannot be used in "
119                                         "semantical equality check",
120                                         asn1f_printable_value(achild->value),
121                                         achild->value->value.reference->_lineno,
122                                         bchild->value->value.reference->_lineno
123                                 );
124                                 return -1;
125                         }
126                 } else if(!(!achild->value && !bchild->value)) {
127                         /* One of values is defined, and another is not */
128                         return -1;
129                 }
130
131                 achild = TQ_NEXT(achild, next);
132                 bchild = TQ_NEXT(bchild, next);
133
134                 if(achild && bchild)
135                         continue;
136                 else if(!achild && !bchild)
137                         break;
138                 else
139                         return -1;
140         }
141
142         DEBUG("\t%s:%x@%d and %s:%x@%d are semantically equivalent",
143                 a->Identifier, a->expr_type, a->_lineno,
144                 b->Identifier, b->expr_type, b->_lineno);
145
146         return 0;
147 }
148
149