blob: 064e38e522d3013f054a6c0a949dab4c180332b7 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
3static 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 */
9int
10asn1f_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
Lev Walkin03850182005-03-10 10:02:50 +000016 DEBUG("(%s:%x@%d, %s:%x@%d)",
Lev Walkinf15320b2004-06-03 03:38:44 +000017 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
Lev Walkina7247f92005-03-20 11:07:34 +000026 if(a == b)
27 return 0; /* Fairly obviously */
28
Lev Walkinf15320b2004-06-03 03:38:44 +000029 if(atype != btype) {
30 /*
Lev Walkina7247f92005-03-20 11:07:34 +000031 * Limited cross-compatibility of integer types.
Lev Walkinf15320b2004-06-03 03:38:44 +000032 */
33 if((atype == A1TC_UNIVERVAL && btype == ASN_BASIC_INTEGER)
34 || (atype == A1TC_UNIVERVAL && btype == ASN_BASIC_ENUMERATED)
35 )
36 return 0;
Lev Walkina7247f92005-03-20 11:07:34 +000037
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
Lev Walkinf15320b2004-06-03 03:38:44 +000049 DEBUG("\t%s and %s are not compatible",
50 a->Identifier, b->Identifier);
51 return -1; /* Fairly obviously */
52 }
53
Lev Walkinf15320b2004-06-03 03:38:44 +000054 switch(atype) {
55 case ASN_BASIC_INTEGER:
Lev Walkina7247f92005-03-20 11:07:34 +000056 /* All integers are compatible, X.680, B.4.5 */
Lev Walkinf15320b2004-06-03 03:38:44 +000057 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:
Lev Walkina7247f92005-03-20 11:07:34 +000070 if((atype & ASN_STRING_MASK)
71 && (btype & ASN_STRING_MASK)) {
72 /* String type is compatible with the same type */
73 return 0;
74 }
Lev Walkinf15320b2004-06-03 03:38:44 +000075 /* 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 */
87static int
88asn1f_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