blob: 7477d72206cb683369818527c8e4c75d02ef6632 [file] [log] [blame]
vlm8a09e0f2005-02-25 14:20:30 +00001#include "asn1fix_internal.h"
2#include "asn1fix_constraint.h"
3#include "asn1fix_crange.h"
vlmb5be8c32004-08-18 05:42:05 +00004
vlm53832f12005-03-20 12:57:21 +00005static void _remove_extensions(arg_t *arg, asn1p_constraint_t *ct);
6static int constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct);
7static int constraint_value_resolve(arg_t *arg, asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype);
vlmb5be8c32004-08-18 05:42:05 +00008
9int
10asn1constraint_pullup(arg_t *arg) {
11 asn1p_expr_t *expr = arg->expr;
vlm53832f12005-03-20 12:57:21 +000012 asn1p_expr_t *top_parent;
vlmb5be8c32004-08-18 05:42:05 +000013 asn1p_constraint_t *ct_parent;
14 asn1p_constraint_t *ct_expr;
15 int ret;
16
17 if(expr->combined_constraints)
18 return 0; /* Operation already performed earlier */
19
20 switch(expr->meta_type) {
21 case AMT_TYPE:
22 case AMT_TYPEREF:
23 break;
24 default:
25 return 0; /* Nothing to do */
26 }
27
28 if(expr->expr_type == A1TC_REFERENCE) {
29 asn1p_ref_t *ref = expr->reference;
vlmb5be8c32004-08-18 05:42:05 +000030 asn1p_expr_t *parent_expr;
31
32 assert(ref);
vlm0c6d3812006-03-21 03:40:38 +000033 parent_expr = asn1f_lookup_symbol(arg, expr->module, expr->rhs_pspecs, ref);
vlmb5be8c32004-08-18 05:42:05 +000034 if(!parent_expr) {
35 if(errno != EEXIST) {
36 DEBUG("\tWhile fetching parent constraints: "
37 "type \"%s\" not found: %s",
38 asn1f_printable_reference(ref),
39 strerror(errno));
40 return -1;
41 } else {
42 /*
43 * -fknown-extern-type is given.
44 * Assume there are no constraints there.
45 */
46 WARNING("External type \"%s\": "
47 "assuming no constraints",
48 asn1f_printable_reference(ref));
49 ct_parent = 0;
50 }
51 } else {
52 arg->expr = parent_expr;
53 ret = asn1constraint_pullup(arg);
54 arg->expr = expr;
55 if(ret) return ret;
56
57 ct_parent = parent_expr->combined_constraints;
58 }
59 } else {
60 ct_parent = 0;
61 }
62
63 ct_expr = expr->constraints;
64
65 if(!ct_parent && !ct_expr)
66 return 0; /* No constraints to consider */
67
vlm53832f12005-03-20 12:57:21 +000068 /*
69 * Resolve constraints, if not already resolved.
70 */
71 top_parent = asn1f_find_terminal_type(arg, arg->expr);
72 ret = asn1constraint_resolve(arg, ct_expr,
73 top_parent ? top_parent->expr_type : A1TC_INVALID, 0);
74 if(ret) return ret;
75
76 /*
77 * Copy parent type constraints.
78 */
vlmb5be8c32004-08-18 05:42:05 +000079 if(ct_parent) {
80 ct_parent = asn1p_constraint_clone(ct_parent);
81 assert(ct_parent);
82 }
83
84 /*
85 * If the current type does not have constraints, it inherits
86 * the constraints of a parent.
87 */
88 if(ct_parent && !ct_expr) {
89 expr->combined_constraints = ct_parent;
90 return 0;
91 }
92
93 ct_expr = asn1p_constraint_clone(ct_expr);
94 assert(ct_expr);
95
96 /*
97 * Now we have a set of current expression's constraints,
98 * and an optional set of the parent expression's constraints.
99 */
100
101 if(ct_parent) {
102 /*
103 * If we have a parent, remove all the extensions (46.4).
104 */
vlm53832f12005-03-20 12:57:21 +0000105 _remove_extensions(arg, ct_parent);
vlmb5be8c32004-08-18 05:42:05 +0000106
107 expr->combined_constraints = ct_parent;
108 if(ct_expr->type == ACT_CA_SET) {
vlm76142452004-09-05 10:36:22 +0000109 unsigned int i;
vlmb5be8c32004-08-18 05:42:05 +0000110 for(i = 0; i < ct_expr->el_count; i++) {
111 if(asn1p_constraint_insert(
112 expr->combined_constraints,
113 ct_expr->elements[i])) {
114 expr->combined_constraints = 0;
115 asn1p_constraint_free(ct_expr);
116 asn1p_constraint_free(ct_parent);
117 return -1;
118 } else {
119 ct_expr->elements[i] = 0;
120 }
121 }
122 asn1p_constraint_free(ct_expr);
123 } else {
124 asn1p_constraint_insert(expr->combined_constraints,
125 ct_expr);
126 }
127 } else {
128 expr->combined_constraints = ct_expr;
129 }
130
131 return 0;
132}
133
134int
vlm53832f12005-03-20 12:57:21 +0000135asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) {
vlm8fba2572005-03-10 11:27:13 +0000136 enum asn1p_constraint_type_e real_constraint_type;
vlm76142452004-09-05 10:36:22 +0000137 unsigned int el;
vlmb5be8c32004-08-18 05:42:05 +0000138 int rvalue = 0;
139 int ret;
vlmb5be8c32004-08-18 05:42:05 +0000140
vlm8fba2572005-03-10 11:27:13 +0000141 DEBUG("(\"%s\")", arg->expr->Identifier);
vlmfd245932005-03-10 10:02:50 +0000142
vlmb5be8c32004-08-18 05:42:05 +0000143 if(!ct) return 0;
144
145 /* Don't touch information object classes */
146 switch(ct->type) {
vlmd8d90352004-08-20 13:25:56 +0000147 case ACT_CT_SIZE:
148 case ACT_CT_FROM:
149 if(effective_type && effective_type != ct->type) {
150 FATAL("%s at line %d: "
151 "Incompatible nested %s within %s",
152 arg->expr->Identifier, ct->_lineno,
153 asn1p_constraint_type2str(ct->type),
154 asn1p_constraint_type2str(effective_type)
155 );
156 }
157 effective_type = ct->type;
158 break;
vlmb5be8c32004-08-18 05:42:05 +0000159 case ACT_CT_WCOMP:
160 case ACT_CT_WCOMPS:
161 case ACT_CA_CRC:
162 return 0;
163 default:
164 break;
165 }
166
vlm8fba2572005-03-10 11:27:13 +0000167 real_constraint_type = effective_type ? effective_type : ct->type;
168
vlmd8d90352004-08-20 13:25:56 +0000169 if(etype != A1TC_INVALID) {
vlmd8d90352004-08-20 13:25:56 +0000170
vlm27028582005-08-14 14:45:44 +0000171 ret = asn1constraint_compatible(etype, real_constraint_type,
172 arg->flags & A1F_EXTENDED_SizeConstraint);
vlmb5be8c32004-08-18 05:42:05 +0000173 switch(ret) {
174 case -1: /* If unknown, assume OK. */
175 case 1:
176 break;
177 case 0:
178 default:
179 FATAL("%s at line %d: "
180 "Constraint type %s is not applicable to %s",
181 arg->expr->Identifier, ct->_lineno,
vlm8fba2572005-03-10 11:27:13 +0000182 asn1p_constraint_type2str(real_constraint_type),
vlmd8d90352004-08-20 13:25:56 +0000183 ASN_EXPR_TYPE2STR(etype)
vlmb5be8c32004-08-18 05:42:05 +0000184 );
185 rvalue = -1;
186 break;
187 }
188 } else {
189 WARNING("%s at line %d: "
190 "Constraints ignored: Unresolved parent type",
191 arg->expr->Identifier, arg->expr->_lineno);
192 }
193
vlmd8d90352004-08-20 13:25:56 +0000194 /*
195 * Resolve all possible references, wherever they occur.
196 */
vlm53832f12005-03-20 12:57:21 +0000197 if(ct->containedSubtype) {
vlm53832f12005-03-20 12:57:21 +0000198 ret = constraint_type_resolve(arg, ct);
199 RET2RVAL(ret, rvalue);
200 }
vlmb5be8c32004-08-18 05:42:05 +0000201 if(ct->value && ct->value->type == ATV_REFERENCED) {
vlm53832f12005-03-20 12:57:21 +0000202 ret = constraint_value_resolve(arg,
vlm8fba2572005-03-10 11:27:13 +0000203 &ct->value, real_constraint_type);
vlmb5be8c32004-08-18 05:42:05 +0000204 RET2RVAL(ret, rvalue);
205 }
206 if(ct->range_start && ct->range_start->type == ATV_REFERENCED) {
vlm53832f12005-03-20 12:57:21 +0000207 ret = constraint_value_resolve(arg,
vlm8fba2572005-03-10 11:27:13 +0000208 &ct->range_start, real_constraint_type);
vlmb5be8c32004-08-18 05:42:05 +0000209 RET2RVAL(ret, rvalue);
210 }
211 if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) {
vlm53832f12005-03-20 12:57:21 +0000212 ret = constraint_value_resolve(arg,
vlm8fba2572005-03-10 11:27:13 +0000213 &ct->range_stop, real_constraint_type);
vlmb5be8c32004-08-18 05:42:05 +0000214 RET2RVAL(ret, rvalue);
215 }
216
vlmd8d90352004-08-20 13:25:56 +0000217 /*
218 * Proceed recursively.
219 */
vlmb5be8c32004-08-18 05:42:05 +0000220 for(el = 0; el < ct->el_count; el++) {
vlm53832f12005-03-20 12:57:21 +0000221 ret = asn1constraint_resolve(arg, ct->elements[el],
vlmd8d90352004-08-20 13:25:56 +0000222 etype, effective_type);
vlmb5be8c32004-08-18 05:42:05 +0000223 RET2RVAL(ret, rvalue);
224 }
225
226 return rvalue;
227}
228
229static void
vlm53832f12005-03-20 12:57:21 +0000230_remove_extensions(arg_t *arg, asn1p_constraint_t *ct) {
vlm76142452004-09-05 10:36:22 +0000231 unsigned int i;
vlmb5be8c32004-08-18 05:42:05 +0000232
233 for(i = 0; i < ct->el_count; i++) {
234 if(ct->elements[i]->type == ACT_EL_EXT)
235 break;
vlm53832f12005-03-20 12:57:21 +0000236 _remove_extensions(arg, ct->elements[i]);
vlmb5be8c32004-08-18 05:42:05 +0000237 }
238
239 /* Remove the elements at and after the extensibility mark */
240 for(; i < ct->el_count; ct->el_count--) {
241 asn1p_constraint_t *rm;
242 rm = ct->elements[ct->el_count-1];
243 asn1p_constraint_free(rm);
244 }
245
246 if(i < ct->el_size)
247 ct->elements[i] = 0;
248}
249
vlm53832f12005-03-20 12:57:21 +0000250static int
251constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct) {
vlmdfbff8c2006-03-21 09:41:28 +0000252 asn1p_constraint_t *ct_expr;
vlm53832f12005-03-20 12:57:21 +0000253 int ret;
254
255 DEBUG("(\"%s\")", asn1f_printable_value(ct->containedSubtype));
256
vlmdfbff8c2006-03-21 09:41:28 +0000257 if(ct->containedSubtype->type == ATV_VALUESET) {
258 ct_expr = ct->containedSubtype->value.constraint;
259 DEBUG("Found %s in constraints", "ValueSet");
260 } else if(ct->containedSubtype->type == ATV_REFERENCED) {
261 asn1p_expr_t *rtype;
262 arg_t tmparg;
vlm53832f12005-03-20 12:57:21 +0000263
vlmdfbff8c2006-03-21 09:41:28 +0000264 rtype = asn1f_lookup_symbol(arg, arg->expr->module,
265 arg->expr->rhs_pspecs,
266 ct->containedSubtype->value.reference);
267 if(!rtype) {
268 FATAL("Cannot find type \"%s\" in constraints "
269 "at line %d",
270 asn1f_printable_value(ct->containedSubtype),
271 ct->_lineno);
272 return -1;
273 }
274
275 tmparg = *arg;
276 tmparg.expr = rtype;
277 tmparg.mod = rtype->module;
278 ret = asn1constraint_pullup(&tmparg);
279 if(ret) return ret;
280
281 ct_expr = rtype->combined_constraints;
282 if(!ct_expr) return 0;
283 } else {
284 FATAL("Unsupported feature at line %d", ct->_lineno);
vlm53832f12005-03-20 12:57:21 +0000285 return -1;
286 }
287
vlmdfbff8c2006-03-21 09:41:28 +0000288 ct_expr = asn1p_constraint_clone(ct_expr);
289 assert(ct_expr);
vlm53832f12005-03-20 12:57:21 +0000290
vlmdfbff8c2006-03-21 09:41:28 +0000291 _remove_extensions(arg, ct_expr);
vlm53832f12005-03-20 12:57:21 +0000292
vlmdfbff8c2006-03-21 09:41:28 +0000293 if(ct_expr->type == ACT_CA_SET) {
294 unsigned int i;
295 for(i = 0; i < ct_expr->el_count; i++) {
296 if(asn1p_constraint_insert(
297 ct, ct_expr->elements[i])) {
298 asn1p_constraint_free(ct_expr);
299 return -1;
300 } else {
301 ct_expr->elements[i] = 0;
vlm53832f12005-03-20 12:57:21 +0000302 }
vlm53832f12005-03-20 12:57:21 +0000303 }
vlmdfbff8c2006-03-21 09:41:28 +0000304 asn1p_constraint_free(ct_expr);
305 } else {
306 ret = asn1p_constraint_insert(ct, ct_expr);
307 assert(ret == 0);
vlm53832f12005-03-20 12:57:21 +0000308 }
309
vlmdfbff8c2006-03-21 09:41:28 +0000310 ct->type = ACT_CA_SET;
311 asn1p_value_free(ct->containedSubtype);
312 ct->containedSubtype = NULL;
313
vlm53832f12005-03-20 12:57:21 +0000314 return 0;
315}
vlmb5be8c32004-08-18 05:42:05 +0000316
317static int
vlm53832f12005-03-20 12:57:21 +0000318constraint_value_resolve(arg_t *arg,
vlm8fba2572005-03-10 11:27:13 +0000319 asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype) {
vlmb5be8c32004-08-18 05:42:05 +0000320 asn1p_expr_t static_expr;
vlmb5be8c32004-08-18 05:42:05 +0000321 arg_t tmp_arg;
322 int rvalue = 0;
323 int ret;
324
vlm8fba2572005-03-10 11:27:13 +0000325 DEBUG("(\"%s\", within <%s>)",
326 asn1f_printable_value(*value),
327 asn1p_constraint_type2str(real_ctype));
328
329 static_expr = *arg->expr;
vlmb5be8c32004-08-18 05:42:05 +0000330 static_expr.value = *value;
vlm8fba2572005-03-10 11:27:13 +0000331 static_expr.meta_type = AMT_VALUE;
vlmb5be8c32004-08-18 05:42:05 +0000332 tmp_arg = *arg;
vlm8fba2572005-03-10 11:27:13 +0000333 tmp_arg.mod = arg->expr->module;
vlmb5be8c32004-08-18 05:42:05 +0000334 tmp_arg.expr = &static_expr;
vlm8fba2572005-03-10 11:27:13 +0000335 ret = asn1f_value_resolve(&tmp_arg, &static_expr, &real_ctype);
vlmb5be8c32004-08-18 05:42:05 +0000336 RET2RVAL(ret, rvalue);
337 assert(static_expr.value);
338 *value = static_expr.value;
339
340 return rvalue;
341}
vlm53832f12005-03-20 12:57:21 +0000342