blob: 4620ec52f874f62b3a22e9b52e8283547341ab00 [file] [log] [blame]
vlmb5be8c32004-08-18 05:42:05 +00001#include <asn1fix_internal.h>
2#include <asn1fix_constraint.h>
3#include <asn1fix_crange.h>
4
5static void _remove_exceptions(arg_t *arg, asn1p_constraint_t *ct);
6static int _constraint_value_resolve(arg_t *arg, asn1p_value_t **value);
7
8int
9asn1constraint_pullup(arg_t *arg) {
10 asn1p_expr_t *expr = arg->expr;
11 asn1p_constraint_t *ct_parent;
12 asn1p_constraint_t *ct_expr;
13 int ret;
14
15 if(expr->combined_constraints)
16 return 0; /* Operation already performed earlier */
17
18 switch(expr->meta_type) {
19 case AMT_TYPE:
20 case AMT_TYPEREF:
21 break;
22 default:
23 return 0; /* Nothing to do */
24 }
25
26 if(expr->expr_type == A1TC_REFERENCE) {
27 asn1p_ref_t *ref = expr->reference;
28 asn1p_module_t *mod_rw = arg->mod;
29 asn1p_expr_t *parent_expr;
30
31 assert(ref);
32 parent_expr = asn1f_lookup_symbol(arg, ref, &mod_rw);
33 if(!parent_expr) {
34 if(errno != EEXIST) {
35 DEBUG("\tWhile fetching parent constraints: "
36 "type \"%s\" not found: %s",
37 asn1f_printable_reference(ref),
38 strerror(errno));
39 return -1;
40 } else {
41 /*
42 * -fknown-extern-type is given.
43 * Assume there are no constraints there.
44 */
45 WARNING("External type \"%s\": "
46 "assuming no constraints",
47 asn1f_printable_reference(ref));
48 ct_parent = 0;
49 }
50 } else {
51 arg->expr = parent_expr;
52 ret = asn1constraint_pullup(arg);
53 arg->expr = expr;
54 if(ret) return ret;
55
56 ct_parent = parent_expr->combined_constraints;
57 }
58 } else {
59 ct_parent = 0;
60 }
61
62 ct_expr = expr->constraints;
63
64 if(!ct_parent && !ct_expr)
65 return 0; /* No constraints to consider */
66
67 if(ct_parent) {
68 ct_parent = asn1p_constraint_clone(ct_parent);
69 assert(ct_parent);
70 }
71
72 /*
73 * If the current type does not have constraints, it inherits
74 * the constraints of a parent.
75 */
76 if(ct_parent && !ct_expr) {
77 expr->combined_constraints = ct_parent;
78 return 0;
79 }
80
81 ct_expr = asn1p_constraint_clone(ct_expr);
82 assert(ct_expr);
83
84 /*
85 * Now we have a set of current expression's constraints,
86 * and an optional set of the parent expression's constraints.
87 */
88
89 if(ct_parent) {
90 /*
91 * If we have a parent, remove all the extensions (46.4).
92 */
93 _remove_exceptions(arg, ct_parent);
94
95 expr->combined_constraints = ct_parent;
96 if(ct_expr->type == ACT_CA_SET) {
97 int i;
98 for(i = 0; i < ct_expr->el_count; i++) {
99 if(asn1p_constraint_insert(
100 expr->combined_constraints,
101 ct_expr->elements[i])) {
102 expr->combined_constraints = 0;
103 asn1p_constraint_free(ct_expr);
104 asn1p_constraint_free(ct_parent);
105 return -1;
106 } else {
107 ct_expr->elements[i] = 0;
108 }
109 }
110 asn1p_constraint_free(ct_expr);
111 } else {
112 asn1p_constraint_insert(expr->combined_constraints,
113 ct_expr);
114 }
115 } else {
116 expr->combined_constraints = ct_expr;
117 }
118
119 return 0;
120}
121
122int
vlmd8d90352004-08-20 13:25:56 +0000123asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) {
vlmb5be8c32004-08-18 05:42:05 +0000124 int rvalue = 0;
125 int ret;
126 int el;
127
128 if(!ct) return 0;
129
130 /* Don't touch information object classes */
131 switch(ct->type) {
vlmd8d90352004-08-20 13:25:56 +0000132 case ACT_CT_SIZE:
133 case ACT_CT_FROM:
134 if(effective_type && effective_type != ct->type) {
135 FATAL("%s at line %d: "
136 "Incompatible nested %s within %s",
137 arg->expr->Identifier, ct->_lineno,
138 asn1p_constraint_type2str(ct->type),
139 asn1p_constraint_type2str(effective_type)
140 );
141 }
142 effective_type = ct->type;
143 break;
vlmb5be8c32004-08-18 05:42:05 +0000144 case ACT_CT_WCOMP:
145 case ACT_CT_WCOMPS:
146 case ACT_CA_CRC:
147 return 0;
148 default:
149 break;
150 }
151
vlmd8d90352004-08-20 13:25:56 +0000152 if(etype != A1TC_INVALID) {
153 enum asn1p_constraint_type_e check_type;
154
155 check_type = effective_type ? effective_type : ct->type;
156
157 ret = asn1constraint_compatible(etype, check_type);
vlmb5be8c32004-08-18 05:42:05 +0000158 switch(ret) {
159 case -1: /* If unknown, assume OK. */
160 case 1:
161 break;
162 case 0:
vlmd8d90352004-08-20 13:25:56 +0000163 if(effective_type == ACT_CT_SIZE
164 && (arg->flags & A1F_EXTENDED_SizeConstraint))
165 break;
vlmb5be8c32004-08-18 05:42:05 +0000166 default:
167 FATAL("%s at line %d: "
168 "Constraint type %s is not applicable to %s",
169 arg->expr->Identifier, ct->_lineno,
vlmd8d90352004-08-20 13:25:56 +0000170 asn1p_constraint_type2str(check_type),
171 ASN_EXPR_TYPE2STR(etype)
vlmb5be8c32004-08-18 05:42:05 +0000172 );
173 rvalue = -1;
174 break;
175 }
176 } else {
177 WARNING("%s at line %d: "
178 "Constraints ignored: Unresolved parent type",
179 arg->expr->Identifier, arg->expr->_lineno);
180 }
181
vlmd8d90352004-08-20 13:25:56 +0000182 /*
183 * Resolve all possible references, wherever they occur.
184 */
vlmb5be8c32004-08-18 05:42:05 +0000185 if(ct->value && ct->value->type == ATV_REFERENCED) {
186 ret = _constraint_value_resolve(arg, &ct->value);
187 RET2RVAL(ret, rvalue);
188 }
189 if(ct->range_start && ct->range_start->type == ATV_REFERENCED) {
190 ret = _constraint_value_resolve(arg, &ct->range_start);
191 RET2RVAL(ret, rvalue);
192 }
193 if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) {
194 ret = _constraint_value_resolve(arg, &ct->range_stop);
195 RET2RVAL(ret, rvalue);
196 }
197
vlmd8d90352004-08-20 13:25:56 +0000198 /*
199 * Proceed recursively.
200 */
vlmb5be8c32004-08-18 05:42:05 +0000201 for(el = 0; el < ct->el_count; el++) {
vlmd8d90352004-08-20 13:25:56 +0000202 ret = asn1constraint_resolve(arg, ct->elements[el],
203 etype, effective_type);
vlmb5be8c32004-08-18 05:42:05 +0000204 RET2RVAL(ret, rvalue);
205 }
206
207 return rvalue;
208}
209
210static void
211_remove_exceptions(arg_t *arg, asn1p_constraint_t *ct) {
212 int i;
213
214 for(i = 0; i < ct->el_count; i++) {
215 if(ct->elements[i]->type == ACT_EL_EXT)
216 break;
217 _remove_exceptions(arg, ct->elements[i]);
218 }
219
220 /* Remove the elements at and after the extensibility mark */
221 for(; i < ct->el_count; ct->el_count--) {
222 asn1p_constraint_t *rm;
223 rm = ct->elements[ct->el_count-1];
224 asn1p_constraint_free(rm);
225 }
226
227 if(i < ct->el_size)
228 ct->elements[i] = 0;
229}
230
231
232static int
233_constraint_value_resolve(arg_t *arg, asn1p_value_t **value) {
234 asn1p_expr_t static_expr;
235 asn1p_expr_t *tmp_expr;
236 asn1p_module_t *mod_rw = arg->mod;
237 arg_t tmp_arg;
238 int rvalue = 0;
239 int ret;
240
241 tmp_expr = asn1f_lookup_symbol(arg, (*value)->value.reference, &mod_rw);
242 if(tmp_expr == NULL) {
243 FATAL("Cannot find symbol %s "
244 "used in %s subtype constraint at line %d",
245 asn1f_printable_reference((*value)->value.reference),
246 arg->expr->Identifier, arg->expr->_lineno);
247 assert((*value)->type == ATV_REFERENCED);
248 return -1;
249 }
250
251 static_expr = *tmp_expr;
252 static_expr.value = *value;
253 tmp_arg = *arg;
254 tmp_arg.mod = mod_rw;
255 tmp_arg.expr = &static_expr;
256 ret = asn1f_fix_dereference_values(&tmp_arg);
257 RET2RVAL(ret, rvalue);
258 assert(static_expr.value);
259 *value = static_expr.value;
260
261 return rvalue;
262}