blob: 3fdaf307600ee95889276df4176d8cabcce0b9c9 [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 { \
62 asn1p_expr_t tmp, *__v; \
63 tmp = *(to); \
64 *(to) = *(from); \
65 TQ_MOVE(&(to)->members, &(from)->members); \
66 *(from) = tmp; \
67 (to)->next = tmp.next; \
68 (to)->parent_expr = tmp.parent_expr; \
69 memset(&((from)->next), 0, \
70 sizeof((from)->next)); \
71 memset(&((from)->members), 0, \
72 sizeof((from)->members)); \
73 asn1p_expr_free(from); \
74 TQ_FOR(__v, &((to)->members), next) { \
75 assert(__v->parent_expr == (from)); \
76 __v->parent_expr = (to); \
77 } \
Lev Walkinf15320b2004-06-03 03:38:44 +000078 } while(0)
79
80static int
81asn1f_parametrize(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype) {
82 asn1p_expr_t *nex;
83 void *p;
84 int ret;
85
Lev Walkinf593f102005-02-22 07:59:59 +000086 DEBUG("asn1f_parametrize(%s <= %s)",
87 expr->Identifier, ptype->Identifier);
88
Lev Walkinf15320b2004-06-03 03:38:44 +000089 /*
90 * The algorithm goes like that:
91 * 1. Replace the expression's type with parametrized type.
92 * 2. For every child in the parametrized type, import it
93 * as a child of the expression, replacing all occurences of
94 * symbols which are defined as parametrized type arguments
95 * with the actual values.
Lev Walkind541c252004-09-05 10:36:22 +000096 * 3. Don't forget to parametrize the subtype constraints.
Lev Walkinf15320b2004-06-03 03:38:44 +000097 */
98
Lev Walkin6fec44d2004-08-22 03:10:23 +000099 nex = asn1p_expr_clone(ptype, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000100 if(nex == NULL) return -1;
101
102 /*
103 * Cleanup the new expression so there is no ptype-related
104 * stuff hanging around.
105 */
106 p = strdup(expr->Identifier);
107 if(p) {
108 free(nex->Identifier);
109 nex->Identifier = p;
110 } else {
111 asn1p_expr_free(nex);
112 return -1;
113 }
114 asn1p_paramlist_free(nex->params);
115 nex->params = NULL;
116 nex->meta_type = expr->meta_type;
117
118 ret = asn1f_param_process_recursive(arg, nex, ptype, expr);
119 if(ret != 0) {
120 asn1p_expr_free(nex);
121 return ret;
122 }
123
124 SUBSTITUTE(expr, nex);
125
126 return ret;
127}
128
129static int
130asn1f_param_process_recursive(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
131 asn1p_expr_t *child;
132
Lev Walkinf593f102005-02-22 07:59:59 +0000133
Lev Walkinf15320b2004-06-03 03:38:44 +0000134 TQ_FOR(child, &(expr->members), next) {
135 asn1p_expr_t *ra;
Lev Walkind541c252004-09-05 10:36:22 +0000136 asn1p_expr_t *ne; /* new expression (clone) */
137
138 if(asn1f_param_process_constraints(arg, child, ptype, actargs))
139 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000140
141 ra = _referenced_argument(child->reference, ptype, actargs);
Lev Walkind541c252004-09-05 10:36:22 +0000142 if(ra) {
143 DEBUG("Substituting parameter for %s %s at line %d",
144 child->Identifier,
145 asn1f_printable_reference(child->reference),
146 child->_lineno
147 );
148
149 assert(child->meta_type == AMT_TYPEREF);
150 assert(child->expr_type == A1TC_REFERENCE);
151
152 ne = asn1p_expr_clone(ra, 0);
153 if(ne == NULL) return -1;
154 assert(ne->Identifier == 0);
155 ne->Identifier = strdup(child->Identifier);
156 if(ne->Identifier == 0) {
157 asn1p_expr_free(ne);
158 return -1;
159 }
160 SUBSTITUTE(child, ne);
Lev Walkinf15320b2004-06-03 03:38:44 +0000161 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000162 }
163
164 return 0;
165}
166
Lev Walkind541c252004-09-05 10:36:22 +0000167/*
168 * Check that the given ref looks like an argument of a parametrized type.
169 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000170static asn1p_expr_t *
171_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
172 asn1p_expr_t *aa;
173 int i;
174
175 if(ref == NULL || ref->comp_count != 1)
176 return NULL;
177
178 aa = TQ_FIRST(&(actargs->members));
179 for(i = 0; i < ptype->params->params_count;
180 i++, aa = TQ_NEXT(aa, next)) {
181 if(strcmp(ref->components[0].name,
182 ptype->params->params[i].argument) == 0)
183 return aa;
184 }
185
186 return NULL;
187}
Lev Walkind541c252004-09-05 10:36:22 +0000188
189/*
190 * Search for parameters inside constraints.
191 */
192static int
193asn1f_param_process_constraints(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
194 asn1p_constraint_t *cts;
195 int ret;
196
197 if(!expr->constraints) return 0;
198
199 cts = asn1p_constraint_clone(expr->constraints);
200 assert(cts);
201
202 ret = _process_constraints(arg, cts, ptype, actargs);
203 if(ret == 1) {
204 asn1p_constraint_free(expr->constraints);
205 expr->constraints = cts;
206 ret = 0;
207 } else {
208 asn1p_constraint_free(cts);
209 }
210
211 return ret;
212}
213
214static int
215_process_constraints(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
216 asn1p_value_t *values[3];
217 int rvalue = 0;
218 size_t i;
219
220 values[0] = ct->value;
221 values[1] = ct->range_start;
222 values[2] = ct->range_stop;
223
224 for(i = 0; i < sizeof(values)/sizeof(values[0]); i++) {
225 asn1p_value_t *v = values[i];
226 asn1p_expr_t *ra;
227 asn1p_ref_t *ref;
228 char *str;
229
230 if(!v || v->type != ATV_REFERENCED) continue;
231
232 ref = v->value.reference;
233 ra = _referenced_argument(ref, ptype, actargs);
234 if(!ra) continue;
235
236 DEBUG("_process_constraints(%s), ra=%s",
237 asn1f_printable_reference(ref), ra->Identifier);
238
Lev Walkinf593f102005-02-22 07:59:59 +0000239 if(ra->expr_type == A1TC_PARAMETRIZED) {
Lev Walkin2c65b122005-02-22 08:05:06 +0000240 DEBUG("Double %s", "parametrization");
Lev Walkinf593f102005-02-22 07:59:59 +0000241 }
242
243 assert(ra->Identifier);
Lev Walkind541c252004-09-05 10:36:22 +0000244 str = strdup(ra->Identifier);
245 if(!str) return -1;
246
247 assert(ref->comp_count == 1);
248 ref = asn1p_ref_new(ref->_lineno);
249 if(!ref) { free(str); return -1; }
250
251 if(asn1p_ref_add_component(ref, str, 0)) {
252 free(str);
253 return -1;
254 }
255
256 asn1p_ref_free(v->value.reference);
257 v->value.reference = ref;
258 rvalue = 1;
259 }
260
261 /* Process the rest of constraints recursively */
262 for(i = 0; i < ct->el_count; i++) {
263 int ret = _process_constraints(arg, ct->elements[i],
264 ptype, actargs);
265 if(ret == -1)
266 rvalue = -1;
267 else if(ret == 1 && rvalue != -1)
268 rvalue = 1;
269 }
270
271 return rvalue;
272}
273