blob: 808f4e8a3e3e40c327599aac8105c0368a023ee0 [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
5static void _remove_exceptions(arg_t *arg, asn1p_constraint_t *ct);
Lev Walkin9288d1c2005-03-10 11:27:13 +00006static int constraint_value_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype);
Lev Walkinb45e0672004-08-18 05:42:05 +00007
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;
Lev Walkinb45e0672004-08-18 05:42:05 +000028 asn1p_expr_t *parent_expr;
29
30 assert(ref);
Lev Walkin6fec44d2004-08-22 03:10:23 +000031 parent_expr = asn1f_lookup_symbol(arg, expr->module, ref);
Lev Walkinb45e0672004-08-18 05:42:05 +000032 if(!parent_expr) {
33 if(errno != EEXIST) {
34 DEBUG("\tWhile fetching parent constraints: "
35 "type \"%s\" not found: %s",
36 asn1f_printable_reference(ref),
37 strerror(errno));
38 return -1;
39 } else {
40 /*
41 * -fknown-extern-type is given.
42 * Assume there are no constraints there.
43 */
44 WARNING("External type \"%s\": "
45 "assuming no constraints",
46 asn1f_printable_reference(ref));
47 ct_parent = 0;
48 }
49 } else {
50 arg->expr = parent_expr;
51 ret = asn1constraint_pullup(arg);
52 arg->expr = expr;
53 if(ret) return ret;
54
55 ct_parent = parent_expr->combined_constraints;
56 }
57 } else {
58 ct_parent = 0;
59 }
60
61 ct_expr = expr->constraints;
62
63 if(!ct_parent && !ct_expr)
64 return 0; /* No constraints to consider */
65
66 if(ct_parent) {
67 ct_parent = asn1p_constraint_clone(ct_parent);
68 assert(ct_parent);
69 }
70
71 /*
72 * If the current type does not have constraints, it inherits
73 * the constraints of a parent.
74 */
75 if(ct_parent && !ct_expr) {
76 expr->combined_constraints = ct_parent;
77 return 0;
78 }
79
80 ct_expr = asn1p_constraint_clone(ct_expr);
81 assert(ct_expr);
82
83 /*
84 * Now we have a set of current expression's constraints,
85 * and an optional set of the parent expression's constraints.
86 */
87
88 if(ct_parent) {
89 /*
90 * If we have a parent, remove all the extensions (46.4).
91 */
92 _remove_exceptions(arg, ct_parent);
93
94 expr->combined_constraints = ct_parent;
95 if(ct_expr->type == ACT_CA_SET) {
Lev Walkind541c252004-09-05 10:36:22 +000096 unsigned int i;
Lev Walkinb45e0672004-08-18 05:42:05 +000097 for(i = 0; i < ct_expr->el_count; i++) {
98 if(asn1p_constraint_insert(
99 expr->combined_constraints,
100 ct_expr->elements[i])) {
101 expr->combined_constraints = 0;
102 asn1p_constraint_free(ct_expr);
103 asn1p_constraint_free(ct_parent);
104 return -1;
105 } else {
106 ct_expr->elements[i] = 0;
107 }
108 }
109 asn1p_constraint_free(ct_expr);
110 } else {
111 asn1p_constraint_insert(expr->combined_constraints,
112 ct_expr);
113 }
114 } else {
115 expr->combined_constraints = ct_expr;
116 }
117
118 return 0;
119}
120
121int
Lev Walkin6fec44d2004-08-22 03:10:23 +0000122asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) {
Lev Walkin9288d1c2005-03-10 11:27:13 +0000123 enum asn1p_constraint_type_e real_constraint_type;
Lev Walkind541c252004-09-05 10:36:22 +0000124 unsigned int el;
Lev Walkinb45e0672004-08-18 05:42:05 +0000125 int rvalue = 0;
126 int ret;
Lev Walkinb45e0672004-08-18 05:42:05 +0000127
Lev Walkin9288d1c2005-03-10 11:27:13 +0000128 DEBUG("(\"%s\")", arg->expr->Identifier);
Lev Walkin03850182005-03-10 10:02:50 +0000129
Lev Walkinb45e0672004-08-18 05:42:05 +0000130 if(!ct) return 0;
131
132 /* Don't touch information object classes */
133 switch(ct->type) {
Lev Walkin5253da42004-08-20 13:25:56 +0000134 case ACT_CT_SIZE:
135 case ACT_CT_FROM:
136 if(effective_type && effective_type != ct->type) {
137 FATAL("%s at line %d: "
138 "Incompatible nested %s within %s",
139 arg->expr->Identifier, ct->_lineno,
140 asn1p_constraint_type2str(ct->type),
141 asn1p_constraint_type2str(effective_type)
142 );
143 }
144 effective_type = ct->type;
145 break;
Lev Walkinb45e0672004-08-18 05:42:05 +0000146 case ACT_CT_WCOMP:
147 case ACT_CT_WCOMPS:
148 case ACT_CA_CRC:
149 return 0;
150 default:
151 break;
152 }
153
Lev Walkin9288d1c2005-03-10 11:27:13 +0000154 real_constraint_type = effective_type ? effective_type : ct->type;
155
Lev Walkin5253da42004-08-20 13:25:56 +0000156 if(etype != A1TC_INVALID) {
Lev Walkin5253da42004-08-20 13:25:56 +0000157
Lev Walkin9288d1c2005-03-10 11:27:13 +0000158 ret = asn1constraint_compatible(etype, real_constraint_type);
Lev Walkinb45e0672004-08-18 05:42:05 +0000159 switch(ret) {
160 case -1: /* If unknown, assume OK. */
161 case 1:
162 break;
163 case 0:
Lev Walkin5253da42004-08-20 13:25:56 +0000164 if(effective_type == ACT_CT_SIZE
165 && (arg->flags & A1F_EXTENDED_SizeConstraint))
166 break;
Lev Walkinb45e0672004-08-18 05:42:05 +0000167 default:
168 FATAL("%s at line %d: "
169 "Constraint type %s is not applicable to %s",
170 arg->expr->Identifier, ct->_lineno,
Lev Walkin9288d1c2005-03-10 11:27:13 +0000171 asn1p_constraint_type2str(real_constraint_type),
Lev Walkin5253da42004-08-20 13:25:56 +0000172 ASN_EXPR_TYPE2STR(etype)
Lev Walkinb45e0672004-08-18 05:42:05 +0000173 );
174 rvalue = -1;
175 break;
176 }
177 } else {
178 WARNING("%s at line %d: "
179 "Constraints ignored: Unresolved parent type",
180 arg->expr->Identifier, arg->expr->_lineno);
181 }
182
Lev Walkin5253da42004-08-20 13:25:56 +0000183 /*
184 * Resolve all possible references, wherever they occur.
185 */
Lev Walkinb45e0672004-08-18 05:42:05 +0000186 if(ct->value && ct->value->type == ATV_REFERENCED) {
Lev Walkin9288d1c2005-03-10 11:27:13 +0000187 ret = constraint_value_resolve(arg, mod,
188 &ct->value, real_constraint_type);
Lev Walkinb45e0672004-08-18 05:42:05 +0000189 RET2RVAL(ret, rvalue);
190 }
191 if(ct->range_start && ct->range_start->type == ATV_REFERENCED) {
Lev Walkin9288d1c2005-03-10 11:27:13 +0000192 ret = constraint_value_resolve(arg, mod,
193 &ct->range_start, real_constraint_type);
Lev Walkinb45e0672004-08-18 05:42:05 +0000194 RET2RVAL(ret, rvalue);
195 }
196 if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) {
Lev Walkin9288d1c2005-03-10 11:27:13 +0000197 ret = constraint_value_resolve(arg, mod,
198 &ct->range_stop, real_constraint_type);
Lev Walkinb45e0672004-08-18 05:42:05 +0000199 RET2RVAL(ret, rvalue);
200 }
201
Lev Walkin5253da42004-08-20 13:25:56 +0000202 /*
203 * Proceed recursively.
204 */
Lev Walkinb45e0672004-08-18 05:42:05 +0000205 for(el = 0; el < ct->el_count; el++) {
Lev Walkin6fec44d2004-08-22 03:10:23 +0000206 ret = asn1constraint_resolve(arg, mod, ct->elements[el],
Lev Walkin5253da42004-08-20 13:25:56 +0000207 etype, effective_type);
Lev Walkinb45e0672004-08-18 05:42:05 +0000208 RET2RVAL(ret, rvalue);
209 }
210
211 return rvalue;
212}
213
214static void
215_remove_exceptions(arg_t *arg, asn1p_constraint_t *ct) {
Lev Walkind541c252004-09-05 10:36:22 +0000216 unsigned int i;
Lev Walkinb45e0672004-08-18 05:42:05 +0000217
218 for(i = 0; i < ct->el_count; i++) {
219 if(ct->elements[i]->type == ACT_EL_EXT)
220 break;
221 _remove_exceptions(arg, ct->elements[i]);
222 }
223
224 /* Remove the elements at and after the extensibility mark */
225 for(; i < ct->el_count; ct->el_count--) {
226 asn1p_constraint_t *rm;
227 rm = ct->elements[ct->el_count-1];
228 asn1p_constraint_free(rm);
229 }
230
231 if(i < ct->el_size)
232 ct->elements[i] = 0;
233}
234
235
236static int
Lev Walkin9288d1c2005-03-10 11:27:13 +0000237constraint_value_resolve(arg_t *arg, asn1p_module_t *mod,
238 asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype) {
Lev Walkinb45e0672004-08-18 05:42:05 +0000239 asn1p_expr_t static_expr;
Lev Walkinb45e0672004-08-18 05:42:05 +0000240 arg_t tmp_arg;
241 int rvalue = 0;
242 int ret;
243
Lev Walkin9288d1c2005-03-10 11:27:13 +0000244 (void)mod;
Lev Walkinb45e0672004-08-18 05:42:05 +0000245
Lev Walkin9288d1c2005-03-10 11:27:13 +0000246 DEBUG("(\"%s\", within <%s>)",
247 asn1f_printable_value(*value),
248 asn1p_constraint_type2str(real_ctype));
249
250 static_expr = *arg->expr;
Lev Walkinb45e0672004-08-18 05:42:05 +0000251 static_expr.value = *value;
Lev Walkin9288d1c2005-03-10 11:27:13 +0000252 static_expr.meta_type = AMT_VALUE;
Lev Walkinb45e0672004-08-18 05:42:05 +0000253 tmp_arg = *arg;
Lev Walkin9288d1c2005-03-10 11:27:13 +0000254 tmp_arg.mod = arg->expr->module;
Lev Walkinb45e0672004-08-18 05:42:05 +0000255 tmp_arg.expr = &static_expr;
Lev Walkin9288d1c2005-03-10 11:27:13 +0000256 ret = asn1f_value_resolve(&tmp_arg, &static_expr, &real_ctype);
Lev Walkinb45e0672004-08-18 05:42:05 +0000257 RET2RVAL(ret, rvalue);
258 assert(static_expr.value);
259 *value = static_expr.value;
260
261 return rvalue;
262}