blob: a4d969026254811da30ca3024d76a2082753a5be [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
3static int asn1f_parametrize(arg_t *arg, asn1p_expr_t *ex, asn1p_expr_t *ptype);
4static int asn1f_param_process_recursive(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
Lev Walkind541c252004-09-05 10:36:22 +00005static int asn1f_param_process_constraints(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
6
Lev Walkinf15320b2004-06-03 03:38:44 +00007static asn1p_expr_t *_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
Lev Walkind541c252004-09-05 10:36:22 +00008static int _process_constraints(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
Lev Walkinf15320b2004-06-03 03:38:44 +00009
10int
11asn1f_fix_parametrized_assignment(arg_t *arg) {
12 asn1p_expr_t *expr = arg->expr;
13 asn1p_expr_t *ptype;
14
15 assert(expr->expr_type == A1TC_PARAMETRIZED);
16 assert(expr->reference);
17
Lev Walkin03850182005-03-10 10:02:50 +000018 DEBUG("(\"%s\" ::= \"%s\" { %s }) for line %d",
19 expr->Identifier,
Lev Walkinf15320b2004-06-03 03:38:44 +000020 asn1f_printable_reference(expr->reference),
21 asn1f_printable_value(expr->value),
22 expr->_lineno);
23
24 /*
25 * Find the corresponding parametrized type definition.
26 */
27 DEBUG("Looking for parametrized type definition \"%s\"",
28 asn1f_printable_reference(expr->reference));
Lev Walkin6fec44d2004-08-22 03:10:23 +000029 ptype = asn1f_lookup_symbol(arg, expr->module, expr->reference);
Lev Walkinf15320b2004-06-03 03:38:44 +000030 if(ptype == NULL) {
31 DEBUG("%s: missing parametrized type declaration",
32 asn1f_printable_reference(expr->reference));
33 return -1;
34 }
35
36 /*
37 * Check that the number of arguments which are expected by
38 * the parametrized type declaration is consistent with the
39 * number of arguments supplied by the parametrized assignment.
40 */
41 if(asn1f_count_children(expr) != ptype->params->params_count) {
42 FATAL("Number of actual arguments %d in %s at line %d "
43 "is not equal to number of expected arguments "
44 "%d in %s at line %d",
45 asn1f_count_children(expr),
46 asn1f_printable_reference(expr->reference),
47 expr->_lineno,
48 ptype->params->params_count,
49 ptype->Identifier,
50 ptype->_lineno
51 );
52 return -1;
53 }
54
55 /*
56 * Perform an expansion of a parametrized assignment.
57 */
58 return asn1f_parametrize(arg, expr, ptype);
59}
60
Lev Walkin1004aa92004-09-08 00:28:11 +000061#define SUBSTITUTE(to, from) do { \
Lev Walkin0320d872005-06-02 17:53:17 +000062 asn1p_expr_t tmp, *__v; \
63 if((to)->tag.tag_class \
64 && (from)->tag.tag_class) { \
65 FATAL("Layered tagging in parametrization " \
66 "is not yet supported, " \
Lev Walkin8f294e02005-06-06 08:28:58 +000067 "contact asn1c author for assistance " \
68 "with line %d", (to)->_lineno); \
Lev Walkin0320d872005-06-02 17:53:17 +000069 return -1; \
70 } \
71 /* This code shall not be invoked too early */ \
72 assert((to)->combined_constraints == NULL); \
73 assert((from)->combined_constraints == NULL); \
74 /* Copy stuff, and merge some parameters */ \
75 tmp = *(to); \
76 *(to) = *(from); \
77 TQ_MOVE(&(to)->members, &(from)->members); \
78 *(from) = tmp; \
79 (to)->next = tmp.next; \
80 (to)->parent_expr = tmp.parent_expr; \
81 assert((to)->marker.flags == EM_NOMARK); \
82 (to)->marker = tmp.marker; \
83 if(tmp.tag.tag_class) \
84 (to)->tag = tmp.tag; \
85 if(tmp.constraints) { \
86 if((to)->constraints) { \
87 asn1p_constraint_t *ct; \
88 ct = asn1p_constraint_new( \
89 (to)->constraints->_lineno); \
90 ct->type = ACT_CA_SET; \
91 asn1p_constraint_insert(ct, \
92 (to)->constraints); \
93 asn1p_constraint_insert(ct, \
94 tmp.constraints); \
95 (to)->constraints = ct; \
96 } else { \
97 (to)->constraints = tmp.constraints; \
Lev Walkin71160962005-06-02 05:21:53 +000098 } \
Lev Walkin0320d872005-06-02 17:53:17 +000099 } \
100 (from)->constraints = 0; \
101 (from)->marker.default_value = 0; \
102 memset(&((from)->next), 0, sizeof((from)->next)); \
103 memset(&((from)->members), 0, sizeof((from)->members)); \
104 asn1p_expr_free(from); \
105 TQ_FOR(__v, &((to)->members), next) { \
106 assert(__v->parent_expr == (from)); \
107 __v->parent_expr = (to); \
108 } \
109} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +0000110
111static int
112asn1f_parametrize(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype) {
113 asn1p_expr_t *nex;
114 void *p;
115 int ret;
116
Lev Walkinf593f102005-02-22 07:59:59 +0000117 DEBUG("asn1f_parametrize(%s <= %s)",
118 expr->Identifier, ptype->Identifier);
119
Lev Walkinf15320b2004-06-03 03:38:44 +0000120 /*
121 * The algorithm goes like that:
122 * 1. Replace the expression's type with parametrized type.
123 * 2. For every child in the parametrized type, import it
124 * as a child of the expression, replacing all occurences of
125 * symbols which are defined as parametrized type arguments
126 * with the actual values.
Lev Walkind541c252004-09-05 10:36:22 +0000127 * 3. Don't forget to parametrize the subtype constraints.
Lev Walkinf15320b2004-06-03 03:38:44 +0000128 */
129
Lev Walkin6fec44d2004-08-22 03:10:23 +0000130 nex = asn1p_expr_clone(ptype, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000131 if(nex == NULL) return -1;
132
133 /*
134 * Cleanup the new expression so there is no ptype-related
135 * stuff hanging around.
136 */
Lev Walkind5947712005-11-05 12:28:14 +0000137 if(expr->Identifier) {
138 p = strdup(expr->Identifier);
139 if(p) {
140 free(nex->Identifier);
141 nex->Identifier = p;
142 } else {
143 asn1p_expr_free(nex);
144 return -1;
145 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 }
147 asn1p_paramlist_free(nex->params);
148 nex->params = NULL;
149 nex->meta_type = expr->meta_type;
150
151 ret = asn1f_param_process_recursive(arg, nex, ptype, expr);
152 if(ret != 0) {
153 asn1p_expr_free(nex);
154 return ret;
155 }
156
157 SUBSTITUTE(expr, nex);
158
159 return ret;
160}
161
162static int
163asn1f_param_process_recursive(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
164 asn1p_expr_t *child;
165
Lev Walkinf593f102005-02-22 07:59:59 +0000166
Lev Walkinf15320b2004-06-03 03:38:44 +0000167 TQ_FOR(child, &(expr->members), next) {
168 asn1p_expr_t *ra;
Lev Walkind541c252004-09-05 10:36:22 +0000169 asn1p_expr_t *ne; /* new expression (clone) */
170
171 if(asn1f_param_process_constraints(arg, child, ptype, actargs))
172 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000173
174 ra = _referenced_argument(child->reference, ptype, actargs);
Lev Walkind541c252004-09-05 10:36:22 +0000175 if(ra) {
176 DEBUG("Substituting parameter for %s %s at line %d",
177 child->Identifier,
178 asn1f_printable_reference(child->reference),
179 child->_lineno
180 );
181
182 assert(child->meta_type == AMT_TYPEREF);
183 assert(child->expr_type == A1TC_REFERENCE);
184
185 ne = asn1p_expr_clone(ra, 0);
186 if(ne == NULL) return -1;
187 assert(ne->Identifier == 0);
188 ne->Identifier = strdup(child->Identifier);
189 if(ne->Identifier == 0) {
190 asn1p_expr_free(ne);
191 return -1;
192 }
193 SUBSTITUTE(child, ne);
Lev Walkinf15320b2004-06-03 03:38:44 +0000194 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000195 }
196
197 return 0;
198}
199
Lev Walkind541c252004-09-05 10:36:22 +0000200/*
201 * Check that the given ref looks like an argument of a parametrized type.
202 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000203static asn1p_expr_t *
204_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
205 asn1p_expr_t *aa;
206 int i;
207
208 if(ref == NULL || ref->comp_count != 1)
209 return NULL;
210
211 aa = TQ_FIRST(&(actargs->members));
212 for(i = 0; i < ptype->params->params_count;
213 i++, aa = TQ_NEXT(aa, next)) {
214 if(strcmp(ref->components[0].name,
215 ptype->params->params[i].argument) == 0)
216 return aa;
217 }
218
219 return NULL;
220}
Lev Walkind541c252004-09-05 10:36:22 +0000221
222/*
223 * Search for parameters inside constraints.
224 */
225static int
226asn1f_param_process_constraints(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
227 asn1p_constraint_t *cts;
228 int ret;
229
230 if(!expr->constraints) return 0;
231
232 cts = asn1p_constraint_clone(expr->constraints);
233 assert(cts);
234
235 ret = _process_constraints(arg, cts, ptype, actargs);
236 if(ret == 1) {
237 asn1p_constraint_free(expr->constraints);
238 expr->constraints = cts;
239 ret = 0;
240 } else {
241 asn1p_constraint_free(cts);
242 }
243
244 return ret;
245}
246
247static int
248_process_constraints(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
249 asn1p_value_t *values[3];
250 int rvalue = 0;
251 size_t i;
252
253 values[0] = ct->value;
254 values[1] = ct->range_start;
255 values[2] = ct->range_stop;
256
257 for(i = 0; i < sizeof(values)/sizeof(values[0]); i++) {
258 asn1p_value_t *v = values[i];
259 asn1p_expr_t *ra;
260 asn1p_ref_t *ref;
261 char *str;
262
263 if(!v || v->type != ATV_REFERENCED) continue;
264
265 ref = v->value.reference;
266 ra = _referenced_argument(ref, ptype, actargs);
267 if(!ra) continue;
268
269 DEBUG("_process_constraints(%s), ra=%s",
270 asn1f_printable_reference(ref), ra->Identifier);
271
Lev Walkinf593f102005-02-22 07:59:59 +0000272 if(ra->expr_type == A1TC_PARAMETRIZED) {
Lev Walkin2c65b122005-02-22 08:05:06 +0000273 DEBUG("Double %s", "parametrization");
Lev Walkinf593f102005-02-22 07:59:59 +0000274 }
275
276 assert(ra->Identifier);
Lev Walkind541c252004-09-05 10:36:22 +0000277 str = strdup(ra->Identifier);
278 if(!str) return -1;
279
280 assert(ref->comp_count == 1);
281 ref = asn1p_ref_new(ref->_lineno);
282 if(!ref) { free(str); return -1; }
283
284 if(asn1p_ref_add_component(ref, str, 0)) {
285 free(str);
286 return -1;
287 }
288
289 asn1p_ref_free(v->value.reference);
290 v->value.reference = ref;
291 rvalue = 1;
292 }
293
294 /* Process the rest of constraints recursively */
295 for(i = 0; i < ct->el_count; i++) {
296 int ret = _process_constraints(arg, ct->elements[i],
297 ptype, actargs);
298 if(ret == -1)
299 rvalue = -1;
300 else if(ret == 1 && rvalue != -1)
301 rvalue = 1;
302 }
303
304 return rvalue;
305}
306