blob: 847bdcea5d16e93db53a00f66f7a245a3c25398e [file] [log] [blame]
Lev Walkin4efbfb72005-02-25 14:20:30 +00001#include "asn1fix_internal.h"
2#include "asn1fix_constraint.h"
3#include "asn1fix_crange.h"
Lev Walkinb45e0672004-08-18 05:42:05 +00004
Lev Walkin38d00172006-09-21 02:21:53 +00005static void _remove_extensions(arg_t *arg, asn1p_constraint_t *ct, int flast);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +00006static 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);
Lev Walkinb45e0672004-08-18 05:42:05 +00008
9int
10asn1constraint_pullup(arg_t *arg) {
11 asn1p_expr_t *expr = arg->expr;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +000012 asn1p_expr_t *top_parent;
Lev Walkinb45e0672004-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;
Lev Walkinb45e0672004-08-18 05:42:05 +000030 asn1p_expr_t *parent_expr;
31
32 assert(ref);
Lev Walkina00d6b32006-03-21 03:40:38 +000033 parent_expr = asn1f_lookup_symbol(arg, expr->module, expr->rhs_pspecs, ref);
Lev Walkinb45e0672004-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
Lev Walkin7ec9b4c2005-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 */
Lev Walkinb45e0672004-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 */
Lev Walkin38d00172006-09-21 02:21:53 +0000105 _remove_extensions(arg, ct_parent, 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000106
107 expr->combined_constraints = ct_parent;
108 if(ct_expr->type == ACT_CA_SET) {
Lev Walkind541c252004-09-05 10:36:22 +0000109 unsigned int i;
Lev Walkinb45e0672004-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 {
Lev Walkin38d00172006-09-21 02:21:53 +0000128 _remove_extensions(arg, ct_expr, 1);
Lev Walkinb45e0672004-08-18 05:42:05 +0000129 expr->combined_constraints = ct_expr;
130 }
131
132 return 0;
133}
134
135int
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000136asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) {
Lev Walkin9288d1c2005-03-10 11:27:13 +0000137 enum asn1p_constraint_type_e real_constraint_type;
Lev Walkind541c252004-09-05 10:36:22 +0000138 unsigned int el;
Lev Walkinb45e0672004-08-18 05:42:05 +0000139 int rvalue = 0;
140 int ret;
Lev Walkinb45e0672004-08-18 05:42:05 +0000141
Lev Walkin9288d1c2005-03-10 11:27:13 +0000142 DEBUG("(\"%s\")", arg->expr->Identifier);
Lev Walkin03850182005-03-10 10:02:50 +0000143
Lev Walkinb45e0672004-08-18 05:42:05 +0000144 if(!ct) return 0;
145
146 /* Don't touch information object classes */
147 switch(ct->type) {
Lev Walkin5253da42004-08-20 13:25:56 +0000148 case ACT_CT_SIZE:
149 case ACT_CT_FROM:
150 if(effective_type && effective_type != ct->type) {
151 FATAL("%s at line %d: "
152 "Incompatible nested %s within %s",
153 arg->expr->Identifier, ct->_lineno,
154 asn1p_constraint_type2str(ct->type),
155 asn1p_constraint_type2str(effective_type)
156 );
157 }
158 effective_type = ct->type;
159 break;
Lev Walkinb45e0672004-08-18 05:42:05 +0000160 case ACT_CT_WCOMP:
161 case ACT_CT_WCOMPS:
162 case ACT_CA_CRC:
163 return 0;
164 default:
165 break;
166 }
167
Lev Walkin9288d1c2005-03-10 11:27:13 +0000168 real_constraint_type = effective_type ? effective_type : ct->type;
169
Lev Walkin5253da42004-08-20 13:25:56 +0000170 if(etype != A1TC_INVALID) {
Lev Walkin5253da42004-08-20 13:25:56 +0000171
Lev Walkin4b553412005-08-14 14:45:44 +0000172 ret = asn1constraint_compatible(etype, real_constraint_type,
173 arg->flags & A1F_EXTENDED_SizeConstraint);
Lev Walkinb45e0672004-08-18 05:42:05 +0000174 switch(ret) {
175 case -1: /* If unknown, assume OK. */
176 case 1:
177 break;
178 case 0:
179 default:
180 FATAL("%s at line %d: "
181 "Constraint type %s is not applicable to %s",
182 arg->expr->Identifier, ct->_lineno,
Lev Walkin9288d1c2005-03-10 11:27:13 +0000183 asn1p_constraint_type2str(real_constraint_type),
Lev Walkin5253da42004-08-20 13:25:56 +0000184 ASN_EXPR_TYPE2STR(etype)
Lev Walkinb45e0672004-08-18 05:42:05 +0000185 );
186 rvalue = -1;
187 break;
188 }
189 } else {
190 WARNING("%s at line %d: "
191 "Constraints ignored: Unresolved parent type",
192 arg->expr->Identifier, arg->expr->_lineno);
193 }
194
Lev Walkin5253da42004-08-20 13:25:56 +0000195 /*
196 * Resolve all possible references, wherever they occur.
197 */
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000198 if(ct->containedSubtype) {
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000199 ret = constraint_type_resolve(arg, ct);
200 RET2RVAL(ret, rvalue);
201 }
Lev Walkinb45e0672004-08-18 05:42:05 +0000202 if(ct->value && ct->value->type == ATV_REFERENCED) {
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000203 ret = constraint_value_resolve(arg,
Lev Walkin9288d1c2005-03-10 11:27:13 +0000204 &ct->value, real_constraint_type);
Lev Walkinb45e0672004-08-18 05:42:05 +0000205 RET2RVAL(ret, rvalue);
206 }
207 if(ct->range_start && ct->range_start->type == ATV_REFERENCED) {
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000208 ret = constraint_value_resolve(arg,
Lev Walkin9288d1c2005-03-10 11:27:13 +0000209 &ct->range_start, real_constraint_type);
Lev Walkinb45e0672004-08-18 05:42:05 +0000210 RET2RVAL(ret, rvalue);
211 }
212 if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) {
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000213 ret = constraint_value_resolve(arg,
Lev Walkin9288d1c2005-03-10 11:27:13 +0000214 &ct->range_stop, real_constraint_type);
Lev Walkinb45e0672004-08-18 05:42:05 +0000215 RET2RVAL(ret, rvalue);
216 }
217
Lev Walkin5253da42004-08-20 13:25:56 +0000218 /*
219 * Proceed recursively.
220 */
Lev Walkinb45e0672004-08-18 05:42:05 +0000221 for(el = 0; el < ct->el_count; el++) {
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000222 ret = asn1constraint_resolve(arg, ct->elements[el],
Lev Walkin5253da42004-08-20 13:25:56 +0000223 etype, effective_type);
Lev Walkinb45e0672004-08-18 05:42:05 +0000224 RET2RVAL(ret, rvalue);
225 }
226
227 return rvalue;
228}
229
230static void
Lev Walkin38d00172006-09-21 02:21:53 +0000231_remove_extensions(arg_t *arg, asn1p_constraint_t *ct, int forgive_last) {
Lev Walkind541c252004-09-05 10:36:22 +0000232 unsigned int i;
Lev Walkinb45e0672004-08-18 05:42:05 +0000233
Lev Walkin38d00172006-09-21 02:21:53 +0000234 if(!ct) return;
235
Lev Walkinb45e0672004-08-18 05:42:05 +0000236 for(i = 0; i < ct->el_count; i++) {
237 if(ct->elements[i]->type == ACT_EL_EXT)
238 break;
Lev Walkin38d00172006-09-21 02:21:53 +0000239 if(forgive_last && ct->type == ACT_CA_SET
240 && i + 1 == ct->el_count)
241 return;
242 _remove_extensions(arg, ct->elements[i], 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000243 }
244
245 /* Remove the elements at and after the extensibility mark */
246 for(; i < ct->el_count; ct->el_count--) {
247 asn1p_constraint_t *rm;
248 rm = ct->elements[ct->el_count-1];
249 asn1p_constraint_free(rm);
250 }
251
252 if(i < ct->el_size)
253 ct->elements[i] = 0;
254}
255
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000256static int
257constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct) {
Lev Walkin5045dfa2006-03-21 09:41:28 +0000258 asn1p_constraint_t *ct_expr;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000259 int ret;
260
261 DEBUG("(\"%s\")", asn1f_printable_value(ct->containedSubtype));
262
Lev Walkin5045dfa2006-03-21 09:41:28 +0000263 if(ct->containedSubtype->type == ATV_VALUESET) {
264 ct_expr = ct->containedSubtype->value.constraint;
265 DEBUG("Found %s in constraints", "ValueSet");
266 } else if(ct->containedSubtype->type == ATV_REFERENCED) {
267 asn1p_expr_t *rtype;
268 arg_t tmparg;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000269
Lev Walkin5045dfa2006-03-21 09:41:28 +0000270 rtype = asn1f_lookup_symbol(arg, arg->expr->module,
271 arg->expr->rhs_pspecs,
272 ct->containedSubtype->value.reference);
273 if(!rtype) {
274 FATAL("Cannot find type \"%s\" in constraints "
275 "at line %d",
276 asn1f_printable_value(ct->containedSubtype),
277 ct->_lineno);
278 return -1;
279 }
280
281 tmparg = *arg;
282 tmparg.expr = rtype;
283 tmparg.mod = rtype->module;
284 ret = asn1constraint_pullup(&tmparg);
285 if(ret) return ret;
286
287 ct_expr = rtype->combined_constraints;
288 if(!ct_expr) return 0;
289 } else {
290 FATAL("Unsupported feature at line %d", ct->_lineno);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000291 return -1;
292 }
293
Lev Walkin5045dfa2006-03-21 09:41:28 +0000294 ct_expr = asn1p_constraint_clone(ct_expr);
295 assert(ct_expr);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000296
Lev Walkin38d00172006-09-21 02:21:53 +0000297 _remove_extensions(arg, ct_expr, 0);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000298
Lev Walkin5045dfa2006-03-21 09:41:28 +0000299 if(ct_expr->type == ACT_CA_SET) {
300 unsigned int i;
301 for(i = 0; i < ct_expr->el_count; i++) {
302 if(asn1p_constraint_insert(
303 ct, ct_expr->elements[i])) {
304 asn1p_constraint_free(ct_expr);
305 return -1;
306 } else {
307 ct_expr->elements[i] = 0;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000308 }
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000309 }
Lev Walkin5045dfa2006-03-21 09:41:28 +0000310 asn1p_constraint_free(ct_expr);
311 } else {
312 ret = asn1p_constraint_insert(ct, ct_expr);
313 assert(ret == 0);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000314 }
315
Lev Walkin5045dfa2006-03-21 09:41:28 +0000316 ct->type = ACT_CA_SET;
317 asn1p_value_free(ct->containedSubtype);
318 ct->containedSubtype = NULL;
319
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000320 return 0;
321}
Lev Walkinb45e0672004-08-18 05:42:05 +0000322
323static int
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000324constraint_value_resolve(arg_t *arg,
Lev Walkin9288d1c2005-03-10 11:27:13 +0000325 asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype) {
Lev Walkinb45e0672004-08-18 05:42:05 +0000326 asn1p_expr_t static_expr;
Lev Walkinb45e0672004-08-18 05:42:05 +0000327 arg_t tmp_arg;
328 int rvalue = 0;
329 int ret;
330
Lev Walkin9288d1c2005-03-10 11:27:13 +0000331 DEBUG("(\"%s\", within <%s>)",
332 asn1f_printable_value(*value),
333 asn1p_constraint_type2str(real_ctype));
334
335 static_expr = *arg->expr;
Lev Walkinb45e0672004-08-18 05:42:05 +0000336 static_expr.value = *value;
Lev Walkin9288d1c2005-03-10 11:27:13 +0000337 static_expr.meta_type = AMT_VALUE;
Lev Walkinb45e0672004-08-18 05:42:05 +0000338 tmp_arg = *arg;
Lev Walkin9288d1c2005-03-10 11:27:13 +0000339 tmp_arg.mod = arg->expr->module;
Lev Walkinb45e0672004-08-18 05:42:05 +0000340 tmp_arg.expr = &static_expr;
Lev Walkin9288d1c2005-03-10 11:27:13 +0000341 ret = asn1f_value_resolve(&tmp_arg, &static_expr, &real_ctype);
Lev Walkinb45e0672004-08-18 05:42:05 +0000342 RET2RVAL(ret, rvalue);
343 assert(static_expr.value);
344 *value = static_expr.value;
345
346 return rvalue;
347}
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000348